@modelriver/client 1.1.3 → 1.1.36

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.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Official ModelRiver client SDK for real-time AI response streaming via WebSocket
6
6
 
7
7
  - **WebSocket streaming** - Receive AI responses in real-time via Phoenix Channels
8
8
  - **Auto-reconnection** - Automatically reconnects on connection loss
9
- - **Persistence** - Survives page refreshes with localStorage persistence
9
+ - **Persistence + reconnect** - Survives page refreshes with localStorage + backend reconnect
10
10
  - **Framework adapters** - First-class support for React, Vue, Angular, and Svelte
11
11
  - **CDN ready** - Use via script tag without a build step
12
12
  - **TypeScript** - Full type definitions included
@@ -27,16 +27,16 @@ pnpm add @modelriver/client
27
27
  ### CDN
28
28
 
29
29
  ```html
30
- <script src="https://cdn.modelriver.com/client/v1.0.0/modelriver.min.js"></script>
30
+ <script src="https://cdn.modelriver.com/client/v1.1.36/modelriver.min.js"></script>
31
31
  <!-- or latest -->
32
32
  <script src="https://cdn.modelriver.com/client/latest/modelriver.min.js"></script>
33
33
  ```
34
34
 
35
35
  ## Quick Start
36
36
 
37
- ### 1. Get channel ID from your backend
37
+ ### 1. Get async connection details from your backend
38
38
 
39
- Your backend calls the ModelRiver `/api/ai/async` endpoint and receives connection details:
39
+ Your backend calls the ModelRiver `/api/v1/ai/async` endpoint and receives connection details:
40
40
 
41
41
  ```javascript
42
42
  // Your backend endpoint proxies to ModelRiver
@@ -45,18 +45,19 @@ const response = await fetch('/api/ai/request', {
45
45
  body: JSON.stringify({ message: 'Hello AI' }),
46
46
  });
47
47
 
48
- // Response from /api/ai/async:
48
+ // Response from /api/v1/ai/async:
49
49
  // {
50
50
  // "message": "success",
51
51
  // "status": "pending",
52
52
  // "channel_id": "a1b2c3d4-...",
53
+ // "ws_token": "one-time-websocket-token",
53
54
  // "websocket_url": "wss://api.modelriver.com/socket",
54
- // "websocket_channel": "ai_response:a1b2c3d4-..."
55
+ // "websocket_channel": "ai_response:PROJECT_ID:a1b2c3d4-..."
55
56
  // }
56
- const { channel_id, websocket_url, websocket_channel } = await response.json();
57
+ const { channel_id, ws_token, websocket_url, websocket_channel } = await response.json();
57
58
  ```
58
59
 
59
- ### 2. Connect to ModelRiver
60
+ ### 2. Connect to ModelRiver WebSocket
60
61
 
61
62
  ```javascript
62
63
  import { ModelRiverClient } from '@modelriver/client';
@@ -73,7 +74,12 @@ client.on('error', (error) => {
73
74
  console.error('Error:', error);
74
75
  });
75
76
 
76
- client.connect({ channelId: channel_id, websocketUrl: websocket_url });
77
+ client.connect({
78
+ channelId: channel_id,
79
+ wsToken: ws_token,
80
+ websocketUrl: websocket_url,
81
+ websocketChannel: websocket_channel,
82
+ });
77
83
  ```
78
84
 
79
85
  ## Framework Usage
@@ -97,8 +103,19 @@ function ChatComponent() {
97
103
  });
98
104
 
99
105
  const handleSend = async () => {
100
- const { channel_id, websocket_url } = await yourBackendAPI.createRequest(message);
101
- connect({ channelId: channel_id, websocketUrl: websocket_url });
106
+ const {
107
+ channel_id,
108
+ ws_token,
109
+ websocket_url,
110
+ websocket_channel,
111
+ } = await yourBackendAPI.createRequest(message); // calls /api/v1/ai/async
112
+
113
+ connect({
114
+ channelId: channel_id,
115
+ wsToken: ws_token,
116
+ websocketUrl: websocket_url,
117
+ websocketChannel: websocket_channel,
118
+ });
102
119
  };
103
120
 
104
121
  return (
@@ -144,8 +161,19 @@ const {
144
161
  });
145
162
 
146
163
  async function handleSend() {
147
- const { channel_id, websocket_url } = await yourBackendAPI.createRequest(message);
148
- connect({ channelId: channel_id, websocketUrl: websocket_url });
164
+ const {
165
+ channel_id,
166
+ ws_token,
167
+ websocket_url,
168
+ websocket_channel,
169
+ } = await yourBackendAPI.createRequest(message); // calls /api/v1/ai/async
170
+
171
+ connect({
172
+ channelId: channel_id,
173
+ wsToken: ws_token,
174
+ websocketUrl: websocket_url,
175
+ websocketChannel: websocket_channel,
176
+ });
149
177
  }
150
178
  </script>
151
179
 
@@ -198,8 +226,19 @@ export class ChatComponent implements OnDestroy {
198
226
  }
199
227
 
200
228
  async send() {
201
- const { channel_id, websocket_url } = await this.backendService.createRequest(message);
202
- this.modelRiver.connect({ channelId: channel_id, websocketUrl: websocket_url });
229
+ const {
230
+ channel_id,
231
+ ws_token,
232
+ websocket_url,
233
+ websocket_channel,
234
+ } = await this.backendService.createRequest(message); // calls /api/v1/ai/async
235
+
236
+ this.modelRiver.connect({
237
+ channelId: channel_id,
238
+ wsToken: ws_token,
239
+ websocketUrl: websocket_url,
240
+ websocketChannel: websocket_channel,
241
+ });
203
242
  }
204
243
 
205
244
  ngOnDestroy() {
@@ -222,8 +261,19 @@ export class ChatComponent implements OnDestroy {
222
261
  const { response, error, isConnected, steps, connect, disconnect } = modelRiver;
223
262
 
224
263
  async function send() {
225
- const { channel_id, websocket_url } = await backendAPI.createRequest(message);
226
- connect({ channelId: channel_id, websocketUrl: websocket_url });
264
+ const {
265
+ channel_id,
266
+ ws_token,
267
+ websocket_url,
268
+ websocket_channel,
269
+ } = await backendAPI.createRequest(message); // calls /api/v1/ai/async
270
+
271
+ connect({
272
+ channelId: channel_id,
273
+ wsToken: ws_token,
274
+ websocketUrl: websocket_url,
275
+ websocketChannel: websocket_channel,
276
+ });
227
277
  }
228
278
 
229
279
  onDestroy(() => disconnect());
@@ -271,11 +321,21 @@ export class ChatComponent implements OnDestroy {
271
321
  });
272
322
 
273
323
  document.getElementById('send').addEventListener('click', async () => {
274
- // Get channel ID from your backend
324
+ // Get async connection info from your backend
275
325
  const res = await fetch('/api/ai/request', { method: 'POST' });
276
- const { channel_id, websocket_url } = await res.json();
326
+ const {
327
+ channel_id,
328
+ ws_token,
329
+ websocket_url,
330
+ websocket_channel,
331
+ } = await res.json(); // your backend calls /api/v1/ai/async
277
332
 
278
- client.connect({ channelId: channel_id, websocketUrl: websocket_url });
333
+ client.connect({
334
+ channelId: channel_id,
335
+ wsToken: ws_token,
336
+ websocketUrl: websocket_url,
337
+ websocketChannel: websocket_channel,
338
+ });
279
339
  });
280
340
  </script>
281
341
  </body>
@@ -291,6 +351,7 @@ export class ChatComponent implements OnDestroy {
291
351
  ```typescript
292
352
  interface ModelRiverClientOptions {
293
353
  baseUrl?: string; // WebSocket URL (default: 'wss://api.modelriver.com/socket')
354
+ apiBaseUrl?: string; // Optional HTTP base URL for backend reconnect (/api/v1/ai/reconnect)
294
355
  debug?: boolean; // Enable debug logging (default: false)
295
356
  persist?: boolean; // Enable localStorage persistence (default: true)
296
357
  storageKeyPrefix?: string; // Storage key prefix (default: 'modelriver_')
@@ -307,6 +368,7 @@ interface ModelRiverClientOptions {
307
368
  | `disconnect()` | Disconnect from WebSocket |
308
369
  | `reset()` | Reset state and clear stored data |
309
370
  | `reconnect()` | Reconnect using stored channel ID |
371
+ | `reconnectWithBackend()` | Call your backend `/api/v1/ai/reconnect` to get a fresh `ws_token` and reconnect |
310
372
  | `getState()` | Get current client state |
311
373
  | `hasPendingRequest()` | Check if there's a pending request |
312
374
  | `on(event, callback)` | Add event listener (returns unsubscribe function) |
@@ -334,6 +396,7 @@ interface AsyncResponse {
334
396
  message: string; // "success"
335
397
  status: 'pending'; // Always "pending" for async
336
398
  channel_id: string; // Unique channel ID
399
+ ws_token: string; // One-time WebSocket token for authentication
337
400
  websocket_url: string; // WebSocket URL to connect to
338
401
  websocket_channel: string; // Full channel name (e.g., "ai_response:uuid")
339
402
  instructions?: {
@@ -377,12 +440,13 @@ interface WorkflowStep {
377
440
 
378
441
  ## How It Works
379
442
 
380
- 1. **Your backend** calls ModelRiver's `/api/ai/async` endpoint
381
- 2. **ModelRiver** returns `channel_id`, `websocket_url`, and `websocket_channel`
382
- 3. **Your backend** returns these fields to the frontend
383
- 4. **Your frontend** uses this SDK to connect via WebSocket using `channel_id`
443
+ 1. **Your backend** calls ModelRiver's `/api/v1/ai/async` endpoint
444
+ 2. **ModelRiver** returns `channel_id`, `ws_token`, `websocket_url`, and `websocket_channel`
445
+ 3. **Your backend** returns these fields to the frontend (never the API key)
446
+ 4. **Your frontend** uses this SDK to connect via WebSocket using `channel_id` + `ws_token`
384
447
  5. **AI responses** are delivered in real-time to your frontend
385
- 6. **The SDK** handles reconnection, heartbeats, and error recovery
448
+ 6. **The SDK** handles heartbeats, channel joins, and automatic reconnection for transient network issues.
449
+ 7. For **page refresh recovery**, use the persistence + reconnect helpers (`persist`, `hasPendingRequest`, `reconnect`, `reconnectWithBackend`) together with your backend `/api/v1/ai/reconnect` endpoint.
386
450
 
387
451
  ```
388
452
  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
@@ -409,14 +473,27 @@ interface WorkflowStep {
409
473
 
410
474
  ## Security
411
475
 
412
- The `/api/ai/async` response contains:
476
+ The `/api/v1/ai/async` response contains:
413
477
  - `channel_id` - Unique identifier for this request
478
+ - `ws_token` - Short-lived, one-time WebSocket token (per user + project)
414
479
  - `websocket_url` - WebSocket endpoint URL
415
480
  - `websocket_channel` - Channel name to join
416
481
 
417
- The client SDK uses `channel_id` directly to connect to the WebSocket. The `channel_id` is unique per request and is used to join the appropriate channel for receiving responses.
482
+ The client SDK uses `channel_id` and `ws_token` to connect to the WebSocket.
483
+ The `ws_token` is:
484
+
485
+ - Short-lived (≈5 minutes)
486
+ - Single-use (consumed on first successful WebSocket authentication)
487
+
488
+ For page refresh recovery:
489
+
490
+ - The SDK persists the active request (by default) to `localStorage`
491
+ - On reload, you can:
492
+ - either call `client.reconnect()` to reuse the stored `ws_token` (if still valid)
493
+ - or call `client.reconnectWithBackend()` to have your backend issue a **fresh** `ws_token` via `/api/v1/ai/reconnect`
418
494
 
419
- **Important**: Always obtain `channel_id` from your backend. Never expose your ModelRiver API key in frontend code.
495
+ **Important**: Always obtain `channel_id` and `ws_token` from your backend.
496
+ Never expose your ModelRiver API key in frontend code. Your backend should be the only component that talks to ModelRiver's HTTP API (`/api/v1/ai/async`, `/api/v1/ai/reconnect`, etc.).
420
497
 
421
498
  ## Browser Support
422
499
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelriver/client",
3
- "version": "1.1.3",
3
+ "version": "1.1.36",
4
4
  "description": "Official ModelRiver client SDK for real-time AI response streaming via WebSockets",
5
5
  "author": "ModelRiver",
6
6
  "license": "MIT",
@@ -35,8 +35,7 @@
35
35
  }
36
36
  },
37
37
  "files": [
38
- "dist",
39
- "cdn"
38
+ "dist"
40
39
  ],
41
40
  "sideEffects": false,
42
41
  "scripts": {
@@ -49,7 +48,7 @@
49
48
  "test:watch": "vitest --watch",
50
49
  "typecheck": "tsc --noEmit",
51
50
  "clean": "rm -rf dist cdn",
52
- "prepublishOnly": "npm run clean && npm run build && npm run build:cdn"
51
+ "prepublishOnly": "npm run clean && npm run build"
53
52
  },
54
53
  "dependencies": {
55
54
  "phoenix": "^1.7.14"
@@ -1,2 +0,0 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ModelRiver={})}(this,function(e){"use strict";var t=e=>{if("function"==typeof e)return e;return function(){return e}},s="undefined"!=typeof self?self:null,n="undefined"!=typeof window?window:null,i=s||n||globalThis,o=0,r=1,h=2,a=3,c="closed",l="errored",u="joined",d="joining",p="leaving",g="phx_close",f="phx_error",m="phx_join",b="phx_reply",k="phx_leave",T="longpoll",C="websocket",v=4,w="base64url.bearer.phx.",y=class{constructor(e,t,s,n){this.channel=e,this.event=t,this.payload=s||function(){return{}},this.receivedResp=null,this.timeout=n,this.timeoutTimer=null,this.recHooks=[],this.sent=!1}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}matchReceive({status:e,response:t,_ref:s}){this.recHooks.filter(t=>t.status===e).forEach(e=>e.callback(t))}cancelRefEvent(){this.refEvent&&this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}},E=class{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=null,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}},R=class{constructor(e,s,n){this.state=c,this.topic=e,this.params=t(s||{}),this.socket=n,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new y(this,m,this.params,this.timeout),this.pushBuffer=[],this.stateChangeRefs=[],this.rejoinTimer=new E(()=>{this.socket.isConnected()&&this.rejoin()},this.socket.rejoinAfterMs),this.stateChangeRefs.push(this.socket.onError(()=>this.rejoinTimer.reset())),this.stateChangeRefs.push(this.socket.onOpen(()=>{this.rejoinTimer.reset(),this.isErrored()&&this.rejoin()})),this.joinPush.receive("ok",()=>{this.state=u,this.rejoinTimer.reset(),this.pushBuffer.forEach(e=>e.send()),this.pushBuffer=[]}),this.joinPush.receive("error",()=>{this.state=l,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.hasLogger()&&this.socket.log("channel",`close ${this.topic} ${this.joinRef()}`),this.state=c,this.socket.remove(this)}),this.onError(e=>{this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,e),this.isJoining()&&this.joinPush.reset(),this.state=l,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.joinPush.receive("timeout",()=>{this.socket.hasLogger()&&this.socket.log("channel",`timeout ${this.topic} (${this.joinRef()})`,this.joinPush.timeout),new y(this,k,t({}),this.timeout).send(),this.state=l,this.joinPush.reset(),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.on(b,(e,t)=>{this.trigger(this.replyEventName(t),e)})}join(e=this.timeout){if(this.joinedOnce)throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");return this.timeout=e,this.joinedOnce=!0,this.rejoin(),this.joinPush}onClose(e){this.on(g,e)}onError(e){return this.on(f,t=>e(t))}on(e,t){let s=this.bindingRef++;return this.bindings.push({event:e,ref:s,callback:t}),s}off(e,t){this.bindings=this.bindings.filter(s=>!(s.event===e&&(void 0===t||t===s.ref)))}canPush(){return this.socket.isConnected()&&this.isJoined()}push(e,t,s=this.timeout){if(t=t||{},!this.joinedOnce)throw new Error(`tried to push '${e}' to '${this.topic}' before joining. Use channel.join() before pushing events`);let n=new y(this,e,function(){return t},s);return this.canPush()?n.send():(n.startTimeout(),this.pushBuffer.push(n)),n}leave(e=this.timeout){this.rejoinTimer.reset(),this.joinPush.cancelTimeout(),this.state=p;let s=()=>{this.socket.hasLogger()&&this.socket.log("channel",`leave ${this.topic}`),this.trigger(g,"leave")},n=new y(this,k,t({}),e);return n.receive("ok",()=>s()).receive("timeout",()=>s()),n.send(),this.canPush()||n.trigger("ok",{}),n}onMessage(e,t,s){return t}isMember(e,t,s,n){return this.topic===e&&(!n||n===this.joinRef()||(this.socket.hasLogger()&&this.socket.log("channel","dropping outdated message",{topic:e,event:t,payload:s,joinRef:n}),!1))}joinRef(){return this.joinPush.ref}rejoin(e=this.timeout){this.isLeaving()||(this.socket.leaveOpenTopic(this.topic),this.state=d,this.joinPush.resend(e))}trigger(e,t,s,n){let i=this.onMessage(e,t,s,n);if(t&&!i)throw new Error("channel onMessage callbacks must return the payload, modified or unmodified");let o=this.bindings.filter(t=>t.event===e);for(let e=0;e<o.length;e++){o[e].callback(i,s,n||this.joinRef())}}replyEventName(e){return`chan_reply_${e}`}isClosed(){return this.state===c}isErrored(){return this.state===l}isJoined(){return this.state===u}isJoining(){return this.state===d}isLeaving(){return this.state===p}},S=class{static request(e,t,s,n,o,r,h){if(i.XDomainRequest){let s=new i.XDomainRequest;return this.xdomainRequest(s,e,t,n,o,r,h)}if(i.XMLHttpRequest){let a=new i.XMLHttpRequest;return this.xhrRequest(a,e,t,s,n,o,r,h)}if(i.fetch&&i.AbortController)return this.fetchRequest(e,t,s,n,o,r,h);throw new Error("No suitable XMLHttpRequest implementation found")}static fetchRequest(e,t,s,n,o,r,h){let a={method:e,headers:s,body:n},c=null;return o&&(c=new AbortController,setTimeout(()=>c.abort(),o),a.signal=c.signal),i.fetch(t,a).then(e=>e.text()).then(e=>this.parseJSON(e)).then(e=>h&&h(e)).catch(e=>{"AbortError"===e.name&&r?r():h&&h(null)}),c}static xdomainRequest(e,t,s,n,i,o,r){return e.timeout=i,e.open(t,s),e.onload=()=>{let t=this.parseJSON(e.responseText);r&&r(t)},o&&(e.ontimeout=o),e.onprogress=()=>{},e.send(n),e}static xhrRequest(e,t,s,n,i,o,r,h){e.open(t,s,!0),e.timeout=o;for(let[t,s]of Object.entries(n))e.setRequestHeader(t,s);return e.onerror=()=>h&&h(null),e.onreadystatechange=()=>{if(e.readyState===v&&h){let t=this.parseJSON(e.responseText);h(t)}},r&&(e.ontimeout=r),e.send(i),e}static parseJSON(e){if(!e||""===e)return null;try{return JSON.parse(e)}catch{return console&&console.log("failed to parse JSON response",e),null}}static serialize(e,t){let s=[];for(var n in e){if(!Object.prototype.hasOwnProperty.call(e,n))continue;let i=t?`${t}[${n}]`:n,o=e[n];"object"==typeof o?s.push(this.serialize(o,i)):s.push(encodeURIComponent(i)+"="+encodeURIComponent(o))}return s.join("&")}static appendParams(e,t){if(0===Object.keys(t).length)return e;let s=e.match(/\?/)?"&":"?";return`${e}${s}${this.serialize(t)}`}},j=class{constructor(e,t){t&&2===t.length&&t[1].startsWith(w)&&(this.authToken=atob(t[1].slice(21))),this.endPoint=null,this.token=null,this.skipHeartbeat=!0,this.reqs=new Set,this.awaitingBatchAck=!1,this.currentBatch=null,this.currentBatchTimer=null,this.batchBuffer=[],this.onopen=function(){},this.onerror=function(){},this.onmessage=function(){},this.onclose=function(){},this.pollEndpoint=this.normalizeEndpoint(e),this.readyState=o,setTimeout(()=>this.poll(),0)}normalizeEndpoint(e){return e.replace("ws://","http://").replace("wss://","https://").replace(new RegExp("(.*)/"+C),"$1/"+T)}endpointURL(){return S.appendParams(this.pollEndpoint,{token:this.token})}closeAndRetry(e,t,s){this.close(e,t,s),this.readyState=o}ontimeout(){this.onerror("timeout"),this.closeAndRetry(1005,"timeout",!1)}isActive(){return this.readyState===r||this.readyState===o}poll(){const e={Accept:"application/json"};this.authToken&&(e["X-Phoenix-AuthToken"]=this.authToken),this.ajax("GET",e,null,()=>this.ontimeout(),e=>{if(e){var{status:t,token:s,messages:n}=e;if(410===t&&null!==this.token)return this.onerror(410),void this.closeAndRetry(3410,"session_gone",!1);this.token=s}else t=0;switch(t){case 200:n.forEach(e=>{setTimeout(()=>this.onmessage({data:e}),0)}),this.poll();break;case 204:this.poll();break;case 410:this.readyState=r,this.onopen({}),this.poll();break;case 403:this.onerror(403),this.close(1008,"forbidden",!1);break;case 0:case 500:this.onerror(500),this.closeAndRetry(1011,"internal server error",500);break;default:throw new Error(`unhandled poll status ${t}`)}})}send(e){"string"!=typeof e&&(e=(e=>{let t="",s=new Uint8Array(e),n=s.byteLength;for(let e=0;e<n;e++)t+=String.fromCharCode(s[e]);return btoa(t)})(e)),this.currentBatch?this.currentBatch.push(e):this.awaitingBatchAck?this.batchBuffer.push(e):(this.currentBatch=[e],this.currentBatchTimer=setTimeout(()=>{this.batchSend(this.currentBatch),this.currentBatch=null},0))}batchSend(e){this.awaitingBatchAck=!0,this.ajax("POST",{"Content-Type":"application/x-ndjson"},e.join("\n"),()=>this.onerror("timeout"),e=>{this.awaitingBatchAck=!1,e&&200===e.status?this.batchBuffer.length>0&&(this.batchSend(this.batchBuffer),this.batchBuffer=[]):(this.onerror(e&&e.status),this.closeAndRetry(1011,"internal server error",!1))})}close(e,t,s){for(let e of this.reqs)e.abort();this.readyState=a;let n=Object.assign({code:1e3,reason:void 0,wasClean:!0},{code:e,reason:t,wasClean:s});this.batchBuffer=[],clearTimeout(this.currentBatchTimer),this.currentBatchTimer=null,"undefined"!=typeof CloseEvent?this.onclose(new CloseEvent("close",n)):this.onclose(n)}ajax(e,t,s,n,i){let o;o=S.request(e,this.endpointURL(),t,s,this.timeout,()=>{this.reqs.delete(o),n()},e=>{this.reqs.delete(o),this.isActive()&&i(e)}),this.reqs.add(o)}},A={HEADER_LENGTH:1,META_LENGTH:4,KINDS:{push:0,reply:1,broadcast:2},encode(e,t){if(e.payload.constructor===ArrayBuffer)return t(this.binaryEncode(e));{let s=[e.join_ref,e.ref,e.topic,e.event,e.payload];return t(JSON.stringify(s))}},decode(e,t){if(e.constructor===ArrayBuffer)return t(this.binaryDecode(e));{let[s,n,i,o,r]=JSON.parse(e);return t({join_ref:s,ref:n,topic:i,event:o,payload:r})}},binaryEncode(e){let{join_ref:t,ref:s,event:n,topic:i,payload:o}=e,r=this.META_LENGTH+t.length+s.length+i.length+n.length,h=new ArrayBuffer(this.HEADER_LENGTH+r),a=new DataView(h),c=0;a.setUint8(c++,this.KINDS.push),a.setUint8(c++,t.length),a.setUint8(c++,s.length),a.setUint8(c++,i.length),a.setUint8(c++,n.length),Array.from(t,e=>a.setUint8(c++,e.charCodeAt(0))),Array.from(s,e=>a.setUint8(c++,e.charCodeAt(0))),Array.from(i,e=>a.setUint8(c++,e.charCodeAt(0))),Array.from(n,e=>a.setUint8(c++,e.charCodeAt(0)));var l=new Uint8Array(h.byteLength+o.byteLength);return l.set(new Uint8Array(h),0),l.set(new Uint8Array(o),h.byteLength),l.buffer},binaryDecode(e){let t=new DataView(e),s=t.getUint8(0),n=new TextDecoder;switch(s){case this.KINDS.push:return this.decodePush(e,t,n);case this.KINDS.reply:return this.decodeReply(e,t,n);case this.KINDS.broadcast:return this.decodeBroadcast(e,t,n)}},decodePush(e,t,s){let n=t.getUint8(1),i=t.getUint8(2),o=t.getUint8(3),r=this.HEADER_LENGTH+this.META_LENGTH-1,h=s.decode(e.slice(r,r+n));r+=n;let a=s.decode(e.slice(r,r+i));r+=i;let c=s.decode(e.slice(r,r+o));return r+=o,{join_ref:h,ref:null,topic:a,event:c,payload:e.slice(r,e.byteLength)}},decodeReply(e,t,s){let n=t.getUint8(1),i=t.getUint8(2),o=t.getUint8(3),r=t.getUint8(4),h=this.HEADER_LENGTH+this.META_LENGTH,a=s.decode(e.slice(h,h+n));h+=n;let c=s.decode(e.slice(h,h+i));h+=i;let l=s.decode(e.slice(h,h+o));h+=o;let u=s.decode(e.slice(h,h+r));h+=r;let d=e.slice(h,e.byteLength);return{join_ref:a,ref:c,topic:l,event:b,payload:{status:u,response:d}}},decodeBroadcast(e,t,s){let n=t.getUint8(1),i=t.getUint8(2),o=this.HEADER_LENGTH+2,r=s.decode(e.slice(o,o+n));o+=n;let h=s.decode(e.slice(o,o+i));return o+=i,{join_ref:null,ref:null,topic:r,event:h,payload:e.slice(o,e.byteLength)}}},_=class{constructor(e,s={}){this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.fallbackRef=null,this.timeout=s.timeout||1e4,this.transport=s.transport||i.WebSocket||j,this.primaryPassedHealthCheck=!1,this.longPollFallbackMs=s.longPollFallbackMs,this.fallbackTimer=null,this.sessionStore=s.sessionStorage||i&&i.sessionStorage,this.establishedConnections=0,this.defaultEncoder=A.encode.bind(A),this.defaultDecoder=A.decode.bind(A),this.closeWasClean=!1,this.disconnecting=!1,this.binaryType=s.binaryType||"arraybuffer",this.connectClock=1,this.pageHidden=!1,this.transport!==j?(this.encode=s.encode||this.defaultEncoder,this.decode=s.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder);let o=null;n&&n.addEventListener&&(n.addEventListener("pagehide",e=>{this.conn&&(this.disconnect(),o=this.connectClock)}),n.addEventListener("pageshow",e=>{o===this.connectClock&&(o=null,this.connect())}),n.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState?this.pageHidden=!0:(this.pageHidden=!1,this.isConnected()||this.teardown(()=>this.connect()))})),this.heartbeatIntervalMs=s.heartbeatIntervalMs||3e4,this.rejoinAfterMs=e=>s.rejoinAfterMs?s.rejoinAfterMs(e):[1e3,2e3,5e3][e-1]||1e4,this.reconnectAfterMs=e=>s.reconnectAfterMs?s.reconnectAfterMs(e):[10,50,100,150,200,250,500,1e3,2e3][e-1]||5e3,this.logger=s.logger||null,!this.logger&&s.debug&&(this.logger=(e,t,s)=>{console.log(`${e}: ${t}`,s)}),this.longpollerTimeout=s.longpollerTimeout||2e4,this.params=t(s.params||{}),this.endPoint=`${e}/${C}`,this.vsn=s.vsn||"2.0.0",this.heartbeatTimeoutTimer=null,this.heartbeatTimer=null,this.pendingHeartbeatRef=null,this.reconnectTimer=new E(()=>{if(this.pageHidden)return this.log("Not reconnecting as page is hidden!"),void this.teardown();this.teardown(()=>this.connect())},this.reconnectAfterMs),this.authToken=s.authToken}getLongPollTransport(){return j}replaceTransport(e){this.connectClock++,this.closeWasClean=!0,clearTimeout(this.fallbackTimer),this.reconnectTimer.reset(),this.conn&&(this.conn.close(),this.conn=null),this.transport=e}protocol(){return location.protocol.match(/^https/)?"wss":"ws"}endPointURL(){let e=S.appendParams(S.appendParams(this.endPoint,this.params()),{vsn:this.vsn});return"/"!==e.charAt(0)?e:"/"===e.charAt(1)?`${this.protocol()}:${e}`:`${this.protocol()}://${location.host}${e}`}disconnect(e,t,s){this.connectClock++,this.disconnecting=!0,this.closeWasClean=!0,clearTimeout(this.fallbackTimer),this.reconnectTimer.reset(),this.teardown(()=>{this.disconnecting=!1,e&&e()},t,s)}connect(e){e&&(console&&console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor"),this.params=t(e)),this.conn&&!this.disconnecting||(this.longPollFallbackMs&&this.transport!==j?this.connectWithFallback(j,this.longPollFallbackMs):this.transportConnect())}log(e,t,s){this.logger&&this.logger(e,t,s)}hasLogger(){return null!==this.logger}onOpen(e){let t=this.makeRef();return this.stateChangeCallbacks.open.push([t,e]),t}onClose(e){let t=this.makeRef();return this.stateChangeCallbacks.close.push([t,e]),t}onError(e){let t=this.makeRef();return this.stateChangeCallbacks.error.push([t,e]),t}onMessage(e){let t=this.makeRef();return this.stateChangeCallbacks.message.push([t,e]),t}ping(e){if(!this.isConnected())return!1;let t=this.makeRef(),s=Date.now();this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:t});let n=this.onMessage(i=>{i.ref===t&&(this.off([n]),e(Date.now()-s))});return!0}transportConnect(){let e;this.connectClock++,this.closeWasClean=!1,this.authToken&&(e=["phoenix",`${w}${btoa(this.authToken).replace(/=/g,"")}`]),this.conn=new this.transport(this.endPointURL(),e),this.conn.binaryType=this.binaryType,this.conn.timeout=this.longpollerTimeout,this.conn.onopen=()=>this.onConnOpen(),this.conn.onerror=e=>this.onConnError(e),this.conn.onmessage=e=>this.onConnMessage(e),this.conn.onclose=e=>this.onConnClose(e)}getSession(e){return this.sessionStore&&this.sessionStore.getItem(e)}storeSession(e,t){this.sessionStore&&this.sessionStore.setItem(e,t)}connectWithFallback(e,t=2500){clearTimeout(this.fallbackTimer);let s,n=!1,i=!0,o=t=>{this.log("transport",`falling back to ${e.name}...`,t),this.off([undefined,s]),i=!1,this.replaceTransport(e),this.transportConnect()};if(this.getSession(`phx:fallback:${e.name}`))return o("memorized");this.fallbackTimer=setTimeout(o,t),s=this.onError(e=>{this.log("transport","error",e),i&&!n&&(clearTimeout(this.fallbackTimer),o(e))}),this.fallbackRef&&this.off([this.fallbackRef]),this.fallbackRef=this.onOpen(()=>{if(n=!0,!i)return this.primaryPassedHealthCheck||this.storeSession(`phx:fallback:${e.name}`,"true"),this.log("transport",`established ${e.name} fallback`);clearTimeout(this.fallbackTimer),this.fallbackTimer=setTimeout(o,t),this.ping(e=>{this.log("transport","connected to primary after",e),this.primaryPassedHealthCheck=!0,clearTimeout(this.fallbackTimer)})}),this.transportConnect()}clearHeartbeats(){clearTimeout(this.heartbeatTimer),clearTimeout(this.heartbeatTimeoutTimer)}onConnOpen(){this.hasLogger()&&this.log("transport",`${this.transport.name} connected to ${this.endPointURL()}`),this.closeWasClean=!1,this.disconnecting=!1,this.establishedConnections++,this.flushSendBuffer(),this.reconnectTimer.reset(),this.resetHeartbeat(),this.stateChangeCallbacks.open.forEach(([,e])=>e())}heartbeatTimeout(){this.pendingHeartbeatRef&&(this.pendingHeartbeatRef=null,this.hasLogger()&&this.log("transport","heartbeat timeout. Attempting to re-establish connection"),this.triggerChanError(),this.closeWasClean=!1,this.teardown(()=>this.reconnectTimer.scheduleTimeout(),1e3,"heartbeat timeout"))}resetHeartbeat(){this.conn&&this.conn.skipHeartbeat||(this.pendingHeartbeatRef=null,this.clearHeartbeats(),this.heartbeatTimer=setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs))}teardown(e,t,s){if(!this.conn)return e&&e();let n=this.connectClock;this.waitForBufferDone(()=>{n===this.connectClock&&(this.conn&&(t?this.conn.close(t,s||""):this.conn.close()),this.waitForSocketClosed(()=>{n===this.connectClock&&(this.conn&&(this.conn.onopen=function(){},this.conn.onerror=function(){},this.conn.onmessage=function(){},this.conn.onclose=function(){},this.conn=null),e&&e())}))})}waitForBufferDone(e,t=1){5!==t&&this.conn&&this.conn.bufferedAmount?setTimeout(()=>{this.waitForBufferDone(e,t+1)},150*t):e()}waitForSocketClosed(e,t=1){5!==t&&this.conn&&this.conn.readyState!==a?setTimeout(()=>{this.waitForSocketClosed(e,t+1)},150*t):e()}onConnClose(e){this.conn&&(this.conn.onclose=()=>{});let t=e&&e.code;this.hasLogger()&&this.log("transport","close",e),this.triggerChanError(),this.clearHeartbeats(),this.closeWasClean||1e3===t||this.reconnectTimer.scheduleTimeout(),this.stateChangeCallbacks.close.forEach(([,t])=>t(e))}onConnError(e){this.hasLogger()&&this.log("transport",e);let t=this.transport,s=this.establishedConnections;this.stateChangeCallbacks.error.forEach(([,n])=>{n(e,t,s)}),(t===this.transport||s>0)&&this.triggerChanError()}triggerChanError(){this.channels.forEach(e=>{e.isErrored()||e.isLeaving()||e.isClosed()||e.trigger(f)})}connectionState(){switch(this.conn&&this.conn.readyState){case o:return"connecting";case r:return"open";case h:return"closing";default:return"closed"}}isConnected(){return"open"===this.connectionState()}remove(e){this.off(e.stateChangeRefs),this.channels=this.channels.filter(t=>t!==e)}off(e){for(let t in this.stateChangeCallbacks)this.stateChangeCallbacks[t]=this.stateChangeCallbacks[t].filter(([t])=>-1===e.indexOf(t))}channel(e,t={}){let s=new R(e,t,this);return this.channels.push(s),s}push(e){if(this.hasLogger()){let{topic:t,event:s,payload:n,ref:i,join_ref:o}=e;this.log("push",`${t} ${s} (${o}, ${i})`,n)}this.isConnected()?this.encode(e,e=>this.conn.send(e)):this.sendBuffer.push(()=>this.encode(e,e=>this.conn.send(e)))}makeRef(){let e=this.ref+1;return e===this.ref?this.ref=0:this.ref=e,this.ref.toString()}sendHeartbeat(){this.pendingHeartbeatRef&&!this.isConnected()||(this.pendingHeartbeatRef=this.makeRef(),this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:this.pendingHeartbeatRef}),this.heartbeatTimeoutTimer=setTimeout(()=>this.heartbeatTimeout(),this.heartbeatIntervalMs))}flushSendBuffer(){this.isConnected()&&this.sendBuffer.length>0&&(this.sendBuffer.forEach(e=>e()),this.sendBuffer=[])}onConnMessage(e){this.decode(e.data,e=>{let{topic:t,event:s,payload:n,ref:i,join_ref:o}=e;i&&i===this.pendingHeartbeatRef&&(this.clearHeartbeats(),this.pendingHeartbeatRef=null,this.heartbeatTimer=setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs)),this.hasLogger()&&this.log("receive",`${n.status||""} ${t} ${s} ${i&&"("+i+")"||""}`,n);for(let e=0;e<this.channels.length;e++){const r=this.channels[e];r.isMember(t,s,n,o)&&r.trigger(s,n,i,o)}for(let t=0;t<this.stateChangeCallbacks.message.length;t++){let[,s]=this.stateChangeCallbacks.message[t];s(e)}})}leaveOpenTopic(e){let t=this.channels.find(t=>t.topic===e&&(t.isJoined()||t.isJoining()));t&&(this.hasLogger()&&this.log("transport",`leaving duplicate topic "${e}"`),t.leave())}};const $="wss://api.modelriver.com/socket",H=3e5,P="active_request";function U(){try{const e="__modelriver_test__";return localStorage.setItem(e,"test"),localStorage.removeItem(e),!0}catch{return!1}}function I(e,t,s,n,i){if(!U())return;const o={channelId:t,wsToken:s,timestamp:Date.now(),websocketUrl:n,websocketChannel:i};try{localStorage.setItem(`${e}${P}`,JSON.stringify(o))}catch{}}function B(e){if(!U())return null;try{const t=localStorage.getItem(`${e}${P}`);if(!t)return null;const s=JSON.parse(t);return Date.now()-s.timestamp>H?(L(e),null):s}catch{return null}}function L(e){if(U())try{localStorage.removeItem(`${e}${P}`)}catch{}}e.DEFAULT_BASE_URL=$,e.DEFAULT_HEARTBEAT_INTERVAL=3e4,e.DEFAULT_REQUEST_TIMEOUT=H,e.ModelRiverClient=class{constructor(e={}){this.socket=null,this.channel=null,this.heartbeatInterval=null,this.connectionState="disconnected",this.steps=[],this.response=null,this.error=null,this.currentWebsocketChannel=null,this.isConnecting=!1,this.listeners=new Map,this.options={baseUrl:e.baseUrl??$,debug:e.debug??!1,persist:e.persist??!0,storageKeyPrefix:e.storageKeyPrefix??"modelriver_",heartbeatInterval:e.heartbeatInterval??3e4,requestTimeout:e.requestTimeout??H,apiBaseUrl:e.apiBaseUrl??""},this.logger=function(e){const t="[ModelRiver]";return{log:(...s)=>{e&&console.log(t,...s)},warn:(...s)=>{e&&console.warn(t,...s)},error:(...e)=>{console.error(t,...e)}}}(this.options.debug),this.logger.log("Client initialized with options:",this.options)}getState(){return{connectionState:this.connectionState,isConnected:"connected"===this.connectionState,isConnecting:this.isConnecting,steps:[...this.steps],response:this.response,error:this.error,hasPendingRequest:this.hasPendingRequest()}}hasPendingRequest(){if(!this.options.persist)return!1;return null!==B(this.options.storageKeyPrefix)}connect(e){if(this.isConnecting)return void this.logger.warn("Connection already in progress, skipping...");const{channelId:t,wsToken:s,websocketUrl:n,websocketChannel:i}=e;if(!t){const e="channelId is required";return this.setError(e),void this.emit("error",e)}if(!s){const e="wsToken is required for WebSocket authentication";return this.setError(e),void this.emit("error",e)}this.isConnecting=!0,this.currentWebsocketChannel=i||`ai_response:${t}`,this.emit("connecting"),this.cleanupConnection(),this.steps=[{id:"queue",name:"Queueing request",status:"pending"},{id:"process",name:"Processing AI request",status:"pending"},{id:"receive",name:"Waiting for response",status:"pending"},{id:"complete",name:"Response received",status:"pending"}],this.error=null,this.response=null,this.options.persist&&I(this.options.storageKeyPrefix,t,s,n,i),this.updateStepAndEmit("queue",{status:"pending"});const o=n||this.options.baseUrl,r=o.endsWith("/socket")?o:`${o}/socket`;this.logger.log("Connecting to:",r),this.socket=new _(r,{params:{token:s}}),this.socket.onOpen(()=>{this.logger.log("Socket connected"),this.connectionState="connected",this.isConnecting=!1,this.emit("connected"),this.joinChannel(this.currentWebsocketChannel)}),this.socket.onError(e=>{this.logger.error("Socket error:",e),this.connectionState="error",this.isConnecting=!1;const t="WebSocket connection error";this.setError(t),this.updateStepAndEmit("queue",{status:"error",errorMessage:t}),this.emit("error",t)}),this.socket.onClose(e=>{this.logger.log("Socket closed:",e),this.connectionState="disconnected",this.isConnecting=!1,this.stopHeartbeat(),this.emit("disconnected","Socket closed")}),this.socket.connect()}joinChannel(e){this.socket&&(this.logger.log("Joining channel:",e),this.channel=this.socket.channel(e,{}),this.channel.join().receive("ok",()=>{this.logger.log("Channel joined successfully"),this.updateStepAndEmit("queue",{status:"success",duration:100}),this.updateStepAndEmit("process",{status:"pending"}),this.updateStepAndEmit("receive",{status:"pending"}),this.emit("channel_joined"),this.startHeartbeat()}).receive("error",e=>{const t=e?.reason||"unknown";this.logger.error("Channel join failed:",t);let s="Failed to join channel";"unauthorized_project_access"===t?s="Unauthorized: You do not have access to this project":"invalid_channel_format"===t?s="Invalid channel format":"invalid_project_uuid"===t||"invalid_channel_uuid"===t?s="Invalid project or channel ID":"unknown"!==t&&(s=`Channel join failed: ${t}`),this.setError(s),this.updateStepAndEmit("queue",{status:"error",errorMessage:s}),this.emit("channel_error",t)}),this.channel.on("response",e=>{this.logger.log("AI Response received:",e),this.handleResponse(e)}),this.channel.on("error",e=>{const t=e?.message||"An error occurred";this.logger.error("Channel error:",t),this.handleError(t)}))}handleResponse(e){if("success"===e.status||"SUCCESS"===e.status||"success"===e.meta?.status||"ok"===e.status)this.updateStepAndEmit("process",{status:"success",duration:e.meta?.duration_ms}),this.updateStepAndEmit("receive",{status:"success",duration:50}),this.updateStepAndEmit("complete",{status:"success"}),this.response=e;else{const t=e.error?.message||"Unknown error";this.updateStepAndEmit("process",{status:"error",errorMessage:t}),this.updateStepAndEmit("receive",{status:"error"}),this.updateStepAndEmit("complete",{status:"error"}),this.setError(t)}this.options.persist&&L(this.options.storageKeyPrefix),this.emit("response",e),setTimeout(()=>{this.cleanupConnection()},1e3)}handleError(e){this.setError(e),this.updateStepAndEmit("process",{status:"error",errorMessage:e}),this.emit("error",e),this.options.persist&&L(this.options.storageKeyPrefix)}disconnect(){this.logger.log("Disconnecting..."),this.isConnecting=!1,this.cleanupConnection(),this.options.persist&&L(this.options.storageKeyPrefix),this.emit("disconnected","Manual disconnect")}reset(){this.logger.log("Resetting..."),this.disconnect(),this.steps=[],this.response=null,this.error=null,this.currentWebsocketChannel=null}reconnect(){if(!this.options.persist)return this.logger.warn("Persistence is disabled, cannot reconnect"),!1;const e=B(this.options.storageKeyPrefix);return e?e.wsToken?(this.logger.log("Reconnecting with stored channel ID..."),this.connect({channelId:e.channelId,wsToken:e.wsToken,websocketUrl:e.websocketUrl,websocketChannel:e.websocketChannel}),!0):(this.logger.warn("No wsToken found in stored request, cannot reconnect"),L(this.options.storageKeyPrefix),!1):(this.logger.log("No active request found for reconnection"),!1)}async reconnectWithBackend(){if(!this.options.persist)return this.logger.warn("Persistence is disabled, cannot reconnect with backend"),!1;if(!this.options.apiBaseUrl)return this.logger.warn("apiBaseUrl is not configured, cannot call /api/v1/ai/reconnect"),!1;const e=B(this.options.storageKeyPrefix);if(!e)return this.logger.log("No active request found for backend reconnection"),!1;const t=`${this.options.apiBaseUrl.replace(/\/+$/,"")}/api/v1/ai/reconnect`;try{const s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:e.channelId})});if(!s.ok)return this.logger.error("Backend reconnect failed with HTTP status",s.status),!1;const n=await s.json();return n?.channel_id&&n?.ws_token?(I(this.options.storageKeyPrefix,n.channel_id,n.ws_token,n.websocket_url,n.websocket_channel),this.connect({channelId:n.channel_id,wsToken:n.ws_token,websocketUrl:n.websocket_url,websocketChannel:n.websocket_channel}),!0):(this.logger.error("Backend reconnect response missing channel_id or ws_token",n),!1)}catch(e){return this.logger.error("Backend reconnect request failed",e),!1}}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{this.listeners.get(e)?.delete(t)}}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,...t){const s=this.listeners.get(e);s&&s.forEach(s=>{try{s(...t)}catch(t){this.logger.error(`Error in ${e} listener:`,t)}})}updateStepAndEmit(e,t){this.steps=function(e,t,s){return e.map(e=>e.id===t?{...e,...s}:e)}(this.steps,e,t);const s=this.steps.find(t=>t.id===e);s&&this.emit("step",s)}setError(e){this.error=e}startHeartbeat(){this.stopHeartbeat(),this.heartbeatInterval=setInterval(()=>{this.channel&&this.channel.push("heartbeat",{})},this.options.heartbeatInterval)}stopHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null)}cleanupConnection(){if(this.stopHeartbeat(),this.channel){try{this.channel.leave()}catch{}this.channel=null}if(this.socket){try{this.socket.disconnect()}catch{}this.socket=null}this.connectionState="disconnected"}destroy(){this.reset(),this.listeners.clear()}},e.buildWebSocketUrl=function(e,t){return`${e.endsWith("/websocket")?e:`${e}/websocket`}?token=${encodeURIComponent(t)}&vsn=2.0.0`},e.decodeToken=function(e){if(!e||"string"!=typeof e)throw new Error("Invalid token: token must be a non-empty string");const t=e.split(".");if(3!==t.length)throw new Error("Invalid token: JWT must have 3 parts");try{const e=JSON.parse(function(e){let t=e.replace(/-/g,"+").replace(/_/g,"/");const s=t.length%4;s&&(t+="=".repeat(4-s));try{return atob(t)}catch{throw new Error("Invalid base64url string")}}(t[1]));if(!e.project_id||!e.channel_id)throw new Error("Invalid token: missing required fields (project_id, channel_id)");const s=e.topic||`ai_response:${e.project_id}:${e.channel_id}`;return{project_id:e.project_id,channel_id:e.channel_id,topic:s,exp:e.exp}}catch(e){if(e instanceof Error&&e.message.startsWith("Invalid token:"))throw e;throw new Error("Invalid token: failed to decode payload")}},e.isStorageAvailable=U,e.isTokenExpired=function(e){return!!e.exp&&Date.now()>=1e3*e.exp}});
2
- //# sourceMappingURL=modelriver.umd.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"modelriver.umd.js","sources":["../node_modules/phoenix/priv/static/phoenix.mjs","../src/utils.ts","../src/client.ts"],"sourcesContent":["// js/phoenix/utils.js\nvar closure = (value) => {\n if (typeof value === \"function\") {\n return value;\n } else {\n let closure2 = function() {\n return value;\n };\n return closure2;\n }\n};\n\n// js/phoenix/constants.js\nvar globalSelf = typeof self !== \"undefined\" ? self : null;\nvar phxWindow = typeof window !== \"undefined\" ? window : null;\nvar global = globalSelf || phxWindow || globalThis;\nvar DEFAULT_VSN = \"2.0.0\";\nvar SOCKET_STATES = { connecting: 0, open: 1, closing: 2, closed: 3 };\nvar DEFAULT_TIMEOUT = 1e4;\nvar WS_CLOSE_NORMAL = 1e3;\nvar CHANNEL_STATES = {\n closed: \"closed\",\n errored: \"errored\",\n joined: \"joined\",\n joining: \"joining\",\n leaving: \"leaving\"\n};\nvar CHANNEL_EVENTS = {\n close: \"phx_close\",\n error: \"phx_error\",\n join: \"phx_join\",\n reply: \"phx_reply\",\n leave: \"phx_leave\"\n};\nvar TRANSPORTS = {\n longpoll: \"longpoll\",\n websocket: \"websocket\"\n};\nvar XHR_STATES = {\n complete: 4\n};\nvar AUTH_TOKEN_PREFIX = \"base64url.bearer.phx.\";\n\n// js/phoenix/push.js\nvar Push = class {\n constructor(channel, event, payload, timeout) {\n this.channel = channel;\n this.event = event;\n this.payload = payload || function() {\n return {};\n };\n this.receivedResp = null;\n this.timeout = timeout;\n this.timeoutTimer = null;\n this.recHooks = [];\n this.sent = false;\n }\n /**\n *\n * @param {number} timeout\n */\n resend(timeout) {\n this.timeout = timeout;\n this.reset();\n this.send();\n }\n /**\n *\n */\n send() {\n if (this.hasReceived(\"timeout\")) {\n return;\n }\n this.startTimeout();\n this.sent = true;\n this.channel.socket.push({\n topic: this.channel.topic,\n event: this.event,\n payload: this.payload(),\n ref: this.ref,\n join_ref: this.channel.joinRef()\n });\n }\n /**\n *\n * @param {*} status\n * @param {*} callback\n */\n receive(status, callback) {\n if (this.hasReceived(status)) {\n callback(this.receivedResp.response);\n }\n this.recHooks.push({ status, callback });\n return this;\n }\n /**\n * @private\n */\n reset() {\n this.cancelRefEvent();\n this.ref = null;\n this.refEvent = null;\n this.receivedResp = null;\n this.sent = false;\n }\n /**\n * @private\n */\n matchReceive({ status, response, _ref }) {\n this.recHooks.filter((h) => h.status === status).forEach((h) => h.callback(response));\n }\n /**\n * @private\n */\n cancelRefEvent() {\n if (!this.refEvent) {\n return;\n }\n this.channel.off(this.refEvent);\n }\n /**\n * @private\n */\n cancelTimeout() {\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = null;\n }\n /**\n * @private\n */\n startTimeout() {\n if (this.timeoutTimer) {\n this.cancelTimeout();\n }\n this.ref = this.channel.socket.makeRef();\n this.refEvent = this.channel.replyEventName(this.ref);\n this.channel.on(this.refEvent, (payload) => {\n this.cancelRefEvent();\n this.cancelTimeout();\n this.receivedResp = payload;\n this.matchReceive(payload);\n });\n this.timeoutTimer = setTimeout(() => {\n this.trigger(\"timeout\", {});\n }, this.timeout);\n }\n /**\n * @private\n */\n hasReceived(status) {\n return this.receivedResp && this.receivedResp.status === status;\n }\n /**\n * @private\n */\n trigger(status, response) {\n this.channel.trigger(this.refEvent, { status, response });\n }\n};\n\n// js/phoenix/timer.js\nvar Timer = class {\n constructor(callback, timerCalc) {\n this.callback = callback;\n this.timerCalc = timerCalc;\n this.timer = null;\n this.tries = 0;\n }\n reset() {\n this.tries = 0;\n clearTimeout(this.timer);\n }\n /**\n * Cancels any previous scheduleTimeout and schedules callback\n */\n scheduleTimeout() {\n clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.tries = this.tries + 1;\n this.callback();\n }, this.timerCalc(this.tries + 1));\n }\n};\n\n// js/phoenix/channel.js\nvar Channel = class {\n constructor(topic, params, socket) {\n this.state = CHANNEL_STATES.closed;\n this.topic = topic;\n this.params = closure(params || {});\n this.socket = socket;\n this.bindings = [];\n this.bindingRef = 0;\n this.timeout = this.socket.timeout;\n this.joinedOnce = false;\n this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout);\n this.pushBuffer = [];\n this.stateChangeRefs = [];\n this.rejoinTimer = new Timer(() => {\n if (this.socket.isConnected()) {\n this.rejoin();\n }\n }, this.socket.rejoinAfterMs);\n this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()));\n this.stateChangeRefs.push(\n this.socket.onOpen(() => {\n this.rejoinTimer.reset();\n if (this.isErrored()) {\n this.rejoin();\n }\n })\n );\n this.joinPush.receive(\"ok\", () => {\n this.state = CHANNEL_STATES.joined;\n this.rejoinTimer.reset();\n this.pushBuffer.forEach((pushEvent) => pushEvent.send());\n this.pushBuffer = [];\n });\n this.joinPush.receive(\"error\", () => {\n this.state = CHANNEL_STATES.errored;\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.onClose(() => {\n this.rejoinTimer.reset();\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`);\n this.state = CHANNEL_STATES.closed;\n this.socket.remove(this);\n });\n this.onError((reason) => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason);\n if (this.isJoining()) {\n this.joinPush.reset();\n }\n this.state = CHANNEL_STATES.errored;\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.joinPush.receive(\"timeout\", () => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout);\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout);\n leavePush.send();\n this.state = CHANNEL_STATES.errored;\n this.joinPush.reset();\n if (this.socket.isConnected()) {\n this.rejoinTimer.scheduleTimeout();\n }\n });\n this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n this.trigger(this.replyEventName(ref), payload);\n });\n }\n /**\n * Join the channel\n * @param {integer} timeout\n * @returns {Push}\n */\n join(timeout = this.timeout) {\n if (this.joinedOnce) {\n throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\");\n } else {\n this.timeout = timeout;\n this.joinedOnce = true;\n this.rejoin();\n return this.joinPush;\n }\n }\n /**\n * Hook into channel close\n * @param {Function} callback\n */\n onClose(callback) {\n this.on(CHANNEL_EVENTS.close, callback);\n }\n /**\n * Hook into channel errors\n * @param {Function} callback\n */\n onError(callback) {\n return this.on(CHANNEL_EVENTS.error, (reason) => callback(reason));\n }\n /**\n * Subscribes on channel events\n *\n * Subscription returns a ref counter, which can be used later to\n * unsubscribe the exact event listener\n *\n * @example\n * const ref1 = channel.on(\"event\", do_stuff)\n * const ref2 = channel.on(\"event\", do_other_stuff)\n * channel.off(\"event\", ref1)\n * // Since unsubscription, do_stuff won't fire,\n * // while do_other_stuff will keep firing on the \"event\"\n *\n * @param {string} event\n * @param {Function} callback\n * @returns {integer} ref\n */\n on(event, callback) {\n let ref = this.bindingRef++;\n this.bindings.push({ event, ref, callback });\n return ref;\n }\n /**\n * Unsubscribes off of channel events\n *\n * Use the ref returned from a channel.on() to unsubscribe one\n * handler, or pass nothing for the ref to unsubscribe all\n * handlers for the given event.\n *\n * @example\n * // Unsubscribe the do_stuff handler\n * const ref1 = channel.on(\"event\", do_stuff)\n * channel.off(\"event\", ref1)\n *\n * // Unsubscribe all handlers from event\n * channel.off(\"event\")\n *\n * @param {string} event\n * @param {integer} ref\n */\n off(event, ref) {\n this.bindings = this.bindings.filter((bind) => {\n return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref));\n });\n }\n /**\n * @private\n */\n canPush() {\n return this.socket.isConnected() && this.isJoined();\n }\n /**\n * Sends a message `event` to phoenix with the payload `payload`.\n * Phoenix receives this in the `handle_in(event, payload, socket)`\n * function. if phoenix replies or it times out (default 10000ms),\n * then optionally the reply can be received.\n *\n * @example\n * channel.push(\"event\")\n * .receive(\"ok\", payload => console.log(\"phoenix replied:\", payload))\n * .receive(\"error\", err => console.log(\"phoenix errored\", err))\n * .receive(\"timeout\", () => console.log(\"timed out pushing\"))\n * @param {string} event\n * @param {Object} payload\n * @param {number} [timeout]\n * @returns {Push}\n */\n push(event, payload, timeout = this.timeout) {\n payload = payload || {};\n if (!this.joinedOnce) {\n throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`);\n }\n let pushEvent = new Push(this, event, function() {\n return payload;\n }, timeout);\n if (this.canPush()) {\n pushEvent.send();\n } else {\n pushEvent.startTimeout();\n this.pushBuffer.push(pushEvent);\n }\n return pushEvent;\n }\n /** Leaves the channel\n *\n * Unsubscribes from server events, and\n * instructs channel to terminate on server\n *\n * Triggers onClose() hooks\n *\n * To receive leave acknowledgements, use the `receive`\n * hook to bind to the server ack, ie:\n *\n * @example\n * channel.leave().receive(\"ok\", () => alert(\"left!\") )\n *\n * @param {integer} timeout\n * @returns {Push}\n */\n leave(timeout = this.timeout) {\n this.rejoinTimer.reset();\n this.joinPush.cancelTimeout();\n this.state = CHANNEL_STATES.leaving;\n let onClose = () => {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`);\n this.trigger(CHANNEL_EVENTS.close, \"leave\");\n };\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout);\n leavePush.receive(\"ok\", () => onClose()).receive(\"timeout\", () => onClose());\n leavePush.send();\n if (!this.canPush()) {\n leavePush.trigger(\"ok\", {});\n }\n return leavePush;\n }\n /**\n * Overridable message hook\n *\n * Receives all events for specialized message handling\n * before dispatching to the channel callbacks.\n *\n * Must return the payload, modified or unmodified\n * @param {string} event\n * @param {Object} payload\n * @param {integer} ref\n * @returns {Object}\n */\n onMessage(_event, payload, _ref) {\n return payload;\n }\n /**\n * @private\n */\n isMember(topic, event, payload, joinRef) {\n if (this.topic !== topic) {\n return false;\n }\n if (joinRef && joinRef !== this.joinRef()) {\n if (this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", { topic, event, payload, joinRef });\n return false;\n } else {\n return true;\n }\n }\n /**\n * @private\n */\n joinRef() {\n return this.joinPush.ref;\n }\n /**\n * @private\n */\n rejoin(timeout = this.timeout) {\n if (this.isLeaving()) {\n return;\n }\n this.socket.leaveOpenTopic(this.topic);\n this.state = CHANNEL_STATES.joining;\n this.joinPush.resend(timeout);\n }\n /**\n * @private\n */\n trigger(event, payload, ref, joinRef) {\n let handledPayload = this.onMessage(event, payload, ref, joinRef);\n if (payload && !handledPayload) {\n throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\");\n }\n let eventBindings = this.bindings.filter((bind) => bind.event === event);\n for (let i = 0; i < eventBindings.length; i++) {\n let bind = eventBindings[i];\n bind.callback(handledPayload, ref, joinRef || this.joinRef());\n }\n }\n /**\n * @private\n */\n replyEventName(ref) {\n return `chan_reply_${ref}`;\n }\n /**\n * @private\n */\n isClosed() {\n return this.state === CHANNEL_STATES.closed;\n }\n /**\n * @private\n */\n isErrored() {\n return this.state === CHANNEL_STATES.errored;\n }\n /**\n * @private\n */\n isJoined() {\n return this.state === CHANNEL_STATES.joined;\n }\n /**\n * @private\n */\n isJoining() {\n return this.state === CHANNEL_STATES.joining;\n }\n /**\n * @private\n */\n isLeaving() {\n return this.state === CHANNEL_STATES.leaving;\n }\n};\n\n// js/phoenix/ajax.js\nvar Ajax = class {\n static request(method, endPoint, headers, body, timeout, ontimeout, callback) {\n if (global.XDomainRequest) {\n let req = new global.XDomainRequest();\n return this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback);\n } else if (global.XMLHttpRequest) {\n let req = new global.XMLHttpRequest();\n return this.xhrRequest(req, method, endPoint, headers, body, timeout, ontimeout, callback);\n } else if (global.fetch && global.AbortController) {\n return this.fetchRequest(method, endPoint, headers, body, timeout, ontimeout, callback);\n } else {\n throw new Error(\"No suitable XMLHttpRequest implementation found\");\n }\n }\n static fetchRequest(method, endPoint, headers, body, timeout, ontimeout, callback) {\n let options = {\n method,\n headers,\n body\n };\n let controller = null;\n if (timeout) {\n controller = new AbortController();\n const _timeoutId = setTimeout(() => controller.abort(), timeout);\n options.signal = controller.signal;\n }\n global.fetch(endPoint, options).then((response) => response.text()).then((data) => this.parseJSON(data)).then((data) => callback && callback(data)).catch((err) => {\n if (err.name === \"AbortError\" && ontimeout) {\n ontimeout();\n } else {\n callback && callback(null);\n }\n });\n return controller;\n }\n static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback) {\n req.timeout = timeout;\n req.open(method, endPoint);\n req.onload = () => {\n let response = this.parseJSON(req.responseText);\n callback && callback(response);\n };\n if (ontimeout) {\n req.ontimeout = ontimeout;\n }\n req.onprogress = () => {\n };\n req.send(body);\n return req;\n }\n static xhrRequest(req, method, endPoint, headers, body, timeout, ontimeout, callback) {\n req.open(method, endPoint, true);\n req.timeout = timeout;\n for (let [key, value] of Object.entries(headers)) {\n req.setRequestHeader(key, value);\n }\n req.onerror = () => callback && callback(null);\n req.onreadystatechange = () => {\n if (req.readyState === XHR_STATES.complete && callback) {\n let response = this.parseJSON(req.responseText);\n callback(response);\n }\n };\n if (ontimeout) {\n req.ontimeout = ontimeout;\n }\n req.send(body);\n return req;\n }\n static parseJSON(resp) {\n if (!resp || resp === \"\") {\n return null;\n }\n try {\n return JSON.parse(resp);\n } catch {\n console && console.log(\"failed to parse JSON response\", resp);\n return null;\n }\n }\n static serialize(obj, parentKey) {\n let queryStr = [];\n for (var key in obj) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) {\n continue;\n }\n let paramKey = parentKey ? `${parentKey}[${key}]` : key;\n let paramVal = obj[key];\n if (typeof paramVal === \"object\") {\n queryStr.push(this.serialize(paramVal, paramKey));\n } else {\n queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal));\n }\n }\n return queryStr.join(\"&\");\n }\n static appendParams(url, params) {\n if (Object.keys(params).length === 0) {\n return url;\n }\n let prefix = url.match(/\\?/) ? \"&\" : \"?\";\n return `${url}${prefix}${this.serialize(params)}`;\n }\n};\n\n// js/phoenix/longpoll.js\nvar arrayBufferToBase64 = (buffer) => {\n let binary = \"\";\n let bytes = new Uint8Array(buffer);\n let len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n};\nvar LongPoll = class {\n constructor(endPoint, protocols) {\n if (protocols && protocols.length === 2 && protocols[1].startsWith(AUTH_TOKEN_PREFIX)) {\n this.authToken = atob(protocols[1].slice(AUTH_TOKEN_PREFIX.length));\n }\n this.endPoint = null;\n this.token = null;\n this.skipHeartbeat = true;\n this.reqs = /* @__PURE__ */ new Set();\n this.awaitingBatchAck = false;\n this.currentBatch = null;\n this.currentBatchTimer = null;\n this.batchBuffer = [];\n this.onopen = function() {\n };\n this.onerror = function() {\n };\n this.onmessage = function() {\n };\n this.onclose = function() {\n };\n this.pollEndpoint = this.normalizeEndpoint(endPoint);\n this.readyState = SOCKET_STATES.connecting;\n setTimeout(() => this.poll(), 0);\n }\n normalizeEndpoint(endPoint) {\n return endPoint.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\").replace(new RegExp(\"(.*)/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll);\n }\n endpointURL() {\n return Ajax.appendParams(this.pollEndpoint, { token: this.token });\n }\n closeAndRetry(code, reason, wasClean) {\n this.close(code, reason, wasClean);\n this.readyState = SOCKET_STATES.connecting;\n }\n ontimeout() {\n this.onerror(\"timeout\");\n this.closeAndRetry(1005, \"timeout\", false);\n }\n isActive() {\n return this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting;\n }\n poll() {\n const headers = { \"Accept\": \"application/json\" };\n if (this.authToken) {\n headers[\"X-Phoenix-AuthToken\"] = this.authToken;\n }\n this.ajax(\"GET\", headers, null, () => this.ontimeout(), (resp) => {\n if (resp) {\n var { status, token, messages } = resp;\n if (status === 410 && this.token !== null) {\n this.onerror(410);\n this.closeAndRetry(3410, \"session_gone\", false);\n return;\n }\n this.token = token;\n } else {\n status = 0;\n }\n switch (status) {\n case 200:\n messages.forEach((msg) => {\n setTimeout(() => this.onmessage({ data: msg }), 0);\n });\n this.poll();\n break;\n case 204:\n this.poll();\n break;\n case 410:\n this.readyState = SOCKET_STATES.open;\n this.onopen({});\n this.poll();\n break;\n case 403:\n this.onerror(403);\n this.close(1008, \"forbidden\", false);\n break;\n case 0:\n case 500:\n this.onerror(500);\n this.closeAndRetry(1011, \"internal server error\", 500);\n break;\n default:\n throw new Error(`unhandled poll status ${status}`);\n }\n });\n }\n // we collect all pushes within the current event loop by\n // setTimeout 0, which optimizes back-to-back procedural\n // pushes against an empty buffer\n send(body) {\n if (typeof body !== \"string\") {\n body = arrayBufferToBase64(body);\n }\n if (this.currentBatch) {\n this.currentBatch.push(body);\n } else if (this.awaitingBatchAck) {\n this.batchBuffer.push(body);\n } else {\n this.currentBatch = [body];\n this.currentBatchTimer = setTimeout(() => {\n this.batchSend(this.currentBatch);\n this.currentBatch = null;\n }, 0);\n }\n }\n batchSend(messages) {\n this.awaitingBatchAck = true;\n this.ajax(\"POST\", { \"Content-Type\": \"application/x-ndjson\" }, messages.join(\"\\n\"), () => this.onerror(\"timeout\"), (resp) => {\n this.awaitingBatchAck = false;\n if (!resp || resp.status !== 200) {\n this.onerror(resp && resp.status);\n this.closeAndRetry(1011, \"internal server error\", false);\n } else if (this.batchBuffer.length > 0) {\n this.batchSend(this.batchBuffer);\n this.batchBuffer = [];\n }\n });\n }\n close(code, reason, wasClean) {\n for (let req of this.reqs) {\n req.abort();\n }\n this.readyState = SOCKET_STATES.closed;\n let opts = Object.assign({ code: 1e3, reason: void 0, wasClean: true }, { code, reason, wasClean });\n this.batchBuffer = [];\n clearTimeout(this.currentBatchTimer);\n this.currentBatchTimer = null;\n if (typeof CloseEvent !== \"undefined\") {\n this.onclose(new CloseEvent(\"close\", opts));\n } else {\n this.onclose(opts);\n }\n }\n ajax(method, headers, body, onCallerTimeout, callback) {\n let req;\n let ontimeout = () => {\n this.reqs.delete(req);\n onCallerTimeout();\n };\n req = Ajax.request(method, this.endpointURL(), headers, body, this.timeout, ontimeout, (resp) => {\n this.reqs.delete(req);\n if (this.isActive()) {\n callback(resp);\n }\n });\n this.reqs.add(req);\n }\n};\n\n// js/phoenix/presence.js\nvar Presence = class _Presence {\n constructor(channel, opts = {}) {\n let events = opts.events || { state: \"presence_state\", diff: \"presence_diff\" };\n this.state = {};\n this.pendingDiffs = [];\n this.channel = channel;\n this.joinRef = null;\n this.caller = {\n onJoin: function() {\n },\n onLeave: function() {\n },\n onSync: function() {\n }\n };\n this.channel.on(events.state, (newState) => {\n let { onJoin, onLeave, onSync } = this.caller;\n this.joinRef = this.channel.joinRef();\n this.state = _Presence.syncState(this.state, newState, onJoin, onLeave);\n this.pendingDiffs.forEach((diff) => {\n this.state = _Presence.syncDiff(this.state, diff, onJoin, onLeave);\n });\n this.pendingDiffs = [];\n onSync();\n });\n this.channel.on(events.diff, (diff) => {\n let { onJoin, onLeave, onSync } = this.caller;\n if (this.inPendingSyncState()) {\n this.pendingDiffs.push(diff);\n } else {\n this.state = _Presence.syncDiff(this.state, diff, onJoin, onLeave);\n onSync();\n }\n });\n }\n onJoin(callback) {\n this.caller.onJoin = callback;\n }\n onLeave(callback) {\n this.caller.onLeave = callback;\n }\n onSync(callback) {\n this.caller.onSync = callback;\n }\n list(by) {\n return _Presence.list(this.state, by);\n }\n inPendingSyncState() {\n return !this.joinRef || this.joinRef !== this.channel.joinRef();\n }\n // lower-level public static API\n /**\n * Used to sync the list of presences on the server\n * with the client's state. An optional `onJoin` and `onLeave` callback can\n * be provided to react to changes in the client's local presences across\n * disconnects and reconnects with the server.\n *\n * @returns {Presence}\n */\n static syncState(currentState, newState, onJoin, onLeave) {\n let state = this.clone(currentState);\n let joins = {};\n let leaves = {};\n this.map(state, (key, presence) => {\n if (!newState[key]) {\n leaves[key] = presence;\n }\n });\n this.map(newState, (key, newPresence) => {\n let currentPresence = state[key];\n if (currentPresence) {\n let newRefs = newPresence.metas.map((m) => m.phx_ref);\n let curRefs = currentPresence.metas.map((m) => m.phx_ref);\n let joinedMetas = newPresence.metas.filter((m) => curRefs.indexOf(m.phx_ref) < 0);\n let leftMetas = currentPresence.metas.filter((m) => newRefs.indexOf(m.phx_ref) < 0);\n if (joinedMetas.length > 0) {\n joins[key] = newPresence;\n joins[key].metas = joinedMetas;\n }\n if (leftMetas.length > 0) {\n leaves[key] = this.clone(currentPresence);\n leaves[key].metas = leftMetas;\n }\n } else {\n joins[key] = newPresence;\n }\n });\n return this.syncDiff(state, { joins, leaves }, onJoin, onLeave);\n }\n /**\n *\n * Used to sync a diff of presence join and leave\n * events from the server, as they happen. Like `syncState`, `syncDiff`\n * accepts optional `onJoin` and `onLeave` callbacks to react to a user\n * joining or leaving from a device.\n *\n * @returns {Presence}\n */\n static syncDiff(state, diff, onJoin, onLeave) {\n let { joins, leaves } = this.clone(diff);\n if (!onJoin) {\n onJoin = function() {\n };\n }\n if (!onLeave) {\n onLeave = function() {\n };\n }\n this.map(joins, (key, newPresence) => {\n let currentPresence = state[key];\n state[key] = this.clone(newPresence);\n if (currentPresence) {\n let joinedRefs = state[key].metas.map((m) => m.phx_ref);\n let curMetas = currentPresence.metas.filter((m) => joinedRefs.indexOf(m.phx_ref) < 0);\n state[key].metas.unshift(...curMetas);\n }\n onJoin(key, currentPresence, newPresence);\n });\n this.map(leaves, (key, leftPresence) => {\n let currentPresence = state[key];\n if (!currentPresence) {\n return;\n }\n let refsToRemove = leftPresence.metas.map((m) => m.phx_ref);\n currentPresence.metas = currentPresence.metas.filter((p) => {\n return refsToRemove.indexOf(p.phx_ref) < 0;\n });\n onLeave(key, currentPresence, leftPresence);\n if (currentPresence.metas.length === 0) {\n delete state[key];\n }\n });\n return state;\n }\n /**\n * Returns the array of presences, with selected metadata.\n *\n * @param {Object} presences\n * @param {Function} chooser\n *\n * @returns {Presence}\n */\n static list(presences, chooser) {\n if (!chooser) {\n chooser = function(key, pres) {\n return pres;\n };\n }\n return this.map(presences, (key, presence) => {\n return chooser(key, presence);\n });\n }\n // private\n static map(obj, func) {\n return Object.getOwnPropertyNames(obj).map((key) => func(key, obj[key]));\n }\n static clone(obj) {\n return JSON.parse(JSON.stringify(obj));\n }\n};\n\n// js/phoenix/serializer.js\nvar serializer_default = {\n HEADER_LENGTH: 1,\n META_LENGTH: 4,\n KINDS: { push: 0, reply: 1, broadcast: 2 },\n encode(msg, callback) {\n if (msg.payload.constructor === ArrayBuffer) {\n return callback(this.binaryEncode(msg));\n } else {\n let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload];\n return callback(JSON.stringify(payload));\n }\n },\n decode(rawPayload, callback) {\n if (rawPayload.constructor === ArrayBuffer) {\n return callback(this.binaryDecode(rawPayload));\n } else {\n let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload);\n return callback({ join_ref, ref, topic, event, payload });\n }\n },\n // private\n binaryEncode(message) {\n let { join_ref, ref, event, topic, payload } = message;\n let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length;\n let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength);\n let view = new DataView(header);\n let offset = 0;\n view.setUint8(offset++, this.KINDS.push);\n view.setUint8(offset++, join_ref.length);\n view.setUint8(offset++, ref.length);\n view.setUint8(offset++, topic.length);\n view.setUint8(offset++, event.length);\n Array.from(join_ref, (char) => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(ref, (char) => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(topic, (char) => view.setUint8(offset++, char.charCodeAt(0)));\n Array.from(event, (char) => view.setUint8(offset++, char.charCodeAt(0)));\n var combined = new Uint8Array(header.byteLength + payload.byteLength);\n combined.set(new Uint8Array(header), 0);\n combined.set(new Uint8Array(payload), header.byteLength);\n return combined.buffer;\n },\n binaryDecode(buffer) {\n let view = new DataView(buffer);\n let kind = view.getUint8(0);\n let decoder = new TextDecoder();\n switch (kind) {\n case this.KINDS.push:\n return this.decodePush(buffer, view, decoder);\n case this.KINDS.reply:\n return this.decodeReply(buffer, view, decoder);\n case this.KINDS.broadcast:\n return this.decodeBroadcast(buffer, view, decoder);\n }\n },\n decodePush(buffer, view, decoder) {\n let joinRefSize = view.getUint8(1);\n let topicSize = view.getUint8(2);\n let eventSize = view.getUint8(3);\n let offset = this.HEADER_LENGTH + this.META_LENGTH - 1;\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));\n offset = offset + joinRefSize;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n return { join_ref: joinRef, ref: null, topic, event, payload: data };\n },\n decodeReply(buffer, view, decoder) {\n let joinRefSize = view.getUint8(1);\n let refSize = view.getUint8(2);\n let topicSize = view.getUint8(3);\n let eventSize = view.getUint8(4);\n let offset = this.HEADER_LENGTH + this.META_LENGTH;\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));\n offset = offset + joinRefSize;\n let ref = decoder.decode(buffer.slice(offset, offset + refSize));\n offset = offset + refSize;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n let payload = { status: event, response: data };\n return { join_ref: joinRef, ref, topic, event: CHANNEL_EVENTS.reply, payload };\n },\n decodeBroadcast(buffer, view, decoder) {\n let topicSize = view.getUint8(1);\n let eventSize = view.getUint8(2);\n let offset = this.HEADER_LENGTH + 2;\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize));\n offset = offset + topicSize;\n let event = decoder.decode(buffer.slice(offset, offset + eventSize));\n offset = offset + eventSize;\n let data = buffer.slice(offset, buffer.byteLength);\n return { join_ref: null, ref: null, topic, event, payload: data };\n }\n};\n\n// js/phoenix/socket.js\nvar Socket = class {\n constructor(endPoint, opts = {}) {\n this.stateChangeCallbacks = { open: [], close: [], error: [], message: [] };\n this.channels = [];\n this.sendBuffer = [];\n this.ref = 0;\n this.fallbackRef = null;\n this.timeout = opts.timeout || DEFAULT_TIMEOUT;\n this.transport = opts.transport || global.WebSocket || LongPoll;\n this.primaryPassedHealthCheck = false;\n this.longPollFallbackMs = opts.longPollFallbackMs;\n this.fallbackTimer = null;\n this.sessionStore = opts.sessionStorage || global && global.sessionStorage;\n this.establishedConnections = 0;\n this.defaultEncoder = serializer_default.encode.bind(serializer_default);\n this.defaultDecoder = serializer_default.decode.bind(serializer_default);\n this.closeWasClean = false;\n this.disconnecting = false;\n this.binaryType = opts.binaryType || \"arraybuffer\";\n this.connectClock = 1;\n this.pageHidden = false;\n if (this.transport !== LongPoll) {\n this.encode = opts.encode || this.defaultEncoder;\n this.decode = opts.decode || this.defaultDecoder;\n } else {\n this.encode = this.defaultEncoder;\n this.decode = this.defaultDecoder;\n }\n let awaitingConnectionOnPageShow = null;\n if (phxWindow && phxWindow.addEventListener) {\n phxWindow.addEventListener(\"pagehide\", (_e) => {\n if (this.conn) {\n this.disconnect();\n awaitingConnectionOnPageShow = this.connectClock;\n }\n });\n phxWindow.addEventListener(\"pageshow\", (_e) => {\n if (awaitingConnectionOnPageShow === this.connectClock) {\n awaitingConnectionOnPageShow = null;\n this.connect();\n }\n });\n phxWindow.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") {\n this.pageHidden = true;\n } else {\n this.pageHidden = false;\n if (!this.isConnected()) {\n this.teardown(() => this.connect());\n }\n }\n });\n }\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 3e4;\n this.rejoinAfterMs = (tries) => {\n if (opts.rejoinAfterMs) {\n return opts.rejoinAfterMs(tries);\n } else {\n return [1e3, 2e3, 5e3][tries - 1] || 1e4;\n }\n };\n this.reconnectAfterMs = (tries) => {\n if (opts.reconnectAfterMs) {\n return opts.reconnectAfterMs(tries);\n } else {\n return [10, 50, 100, 150, 200, 250, 500, 1e3, 2e3][tries - 1] || 5e3;\n }\n };\n this.logger = opts.logger || null;\n if (!this.logger && opts.debug) {\n this.logger = (kind, msg, data) => {\n console.log(`${kind}: ${msg}`, data);\n };\n }\n this.longpollerTimeout = opts.longpollerTimeout || 2e4;\n this.params = closure(opts.params || {});\n this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`;\n this.vsn = opts.vsn || DEFAULT_VSN;\n this.heartbeatTimeoutTimer = null;\n this.heartbeatTimer = null;\n this.pendingHeartbeatRef = null;\n this.reconnectTimer = new Timer(() => {\n if (this.pageHidden) {\n this.log(\"Not reconnecting as page is hidden!\");\n this.teardown();\n return;\n }\n this.teardown(() => this.connect());\n }, this.reconnectAfterMs);\n this.authToken = opts.authToken;\n }\n /**\n * Returns the LongPoll transport reference\n */\n getLongPollTransport() {\n return LongPoll;\n }\n /**\n * Disconnects and replaces the active transport\n *\n * @param {Function} newTransport - The new transport class to instantiate\n *\n */\n replaceTransport(newTransport) {\n this.connectClock++;\n this.closeWasClean = true;\n clearTimeout(this.fallbackTimer);\n this.reconnectTimer.reset();\n if (this.conn) {\n this.conn.close();\n this.conn = null;\n }\n this.transport = newTransport;\n }\n /**\n * Returns the socket protocol\n *\n * @returns {string}\n */\n protocol() {\n return location.protocol.match(/^https/) ? \"wss\" : \"ws\";\n }\n /**\n * The fully qualified socket url\n *\n * @returns {string}\n */\n endPointURL() {\n let uri = Ajax.appendParams(\n Ajax.appendParams(this.endPoint, this.params()),\n { vsn: this.vsn }\n );\n if (uri.charAt(0) !== \"/\") {\n return uri;\n }\n if (uri.charAt(1) === \"/\") {\n return `${this.protocol()}:${uri}`;\n }\n return `${this.protocol()}://${location.host}${uri}`;\n }\n /**\n * Disconnects the socket\n *\n * See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.\n *\n * @param {Function} callback - Optional callback which is called after socket is disconnected.\n * @param {integer} code - A status code for disconnection (Optional).\n * @param {string} reason - A textual description of the reason to disconnect. (Optional)\n */\n disconnect(callback, code, reason) {\n this.connectClock++;\n this.disconnecting = true;\n this.closeWasClean = true;\n clearTimeout(this.fallbackTimer);\n this.reconnectTimer.reset();\n this.teardown(() => {\n this.disconnecting = false;\n callback && callback();\n }, code, reason);\n }\n /**\n *\n * @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`\n *\n * Passing params to connect is deprecated; pass them in the Socket constructor instead:\n * `new Socket(\"/socket\", {params: {user_id: userToken}})`.\n */\n connect(params) {\n if (params) {\n console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\");\n this.params = closure(params);\n }\n if (this.conn && !this.disconnecting) {\n return;\n }\n if (this.longPollFallbackMs && this.transport !== LongPoll) {\n this.connectWithFallback(LongPoll, this.longPollFallbackMs);\n } else {\n this.transportConnect();\n }\n }\n /**\n * Logs the message. Override `this.logger` for specialized logging. noops by default\n * @param {string} kind\n * @param {string} msg\n * @param {Object} data\n */\n log(kind, msg, data) {\n this.logger && this.logger(kind, msg, data);\n }\n /**\n * Returns true if a logger has been set on this socket.\n */\n hasLogger() {\n return this.logger !== null;\n }\n /**\n * Registers callbacks for connection open events\n *\n * @example socket.onOpen(function(){ console.info(\"the socket was opened\") })\n *\n * @param {Function} callback\n */\n onOpen(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.open.push([ref, callback]);\n return ref;\n }\n /**\n * Registers callbacks for connection close events\n * @param {Function} callback\n */\n onClose(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.close.push([ref, callback]);\n return ref;\n }\n /**\n * Registers callbacks for connection error events\n *\n * @example socket.onError(function(error){ alert(\"An error occurred\") })\n *\n * @param {Function} callback\n */\n onError(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.error.push([ref, callback]);\n return ref;\n }\n /**\n * Registers callbacks for connection message events\n * @param {Function} callback\n */\n onMessage(callback) {\n let ref = this.makeRef();\n this.stateChangeCallbacks.message.push([ref, callback]);\n return ref;\n }\n /**\n * Pings the server and invokes the callback with the RTT in milliseconds\n * @param {Function} callback\n *\n * Returns true if the ping was pushed or false if unable to be pushed.\n */\n ping(callback) {\n if (!this.isConnected()) {\n return false;\n }\n let ref = this.makeRef();\n let startTime = Date.now();\n this.push({ topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref });\n let onMsgRef = this.onMessage((msg) => {\n if (msg.ref === ref) {\n this.off([onMsgRef]);\n callback(Date.now() - startTime);\n }\n });\n return true;\n }\n /**\n * @private\n */\n transportConnect() {\n this.connectClock++;\n this.closeWasClean = false;\n let protocols = void 0;\n if (this.authToken) {\n protocols = [\"phoenix\", `${AUTH_TOKEN_PREFIX}${btoa(this.authToken).replace(/=/g, \"\")}`];\n }\n this.conn = new this.transport(this.endPointURL(), protocols);\n this.conn.binaryType = this.binaryType;\n this.conn.timeout = this.longpollerTimeout;\n this.conn.onopen = () => this.onConnOpen();\n this.conn.onerror = (error) => this.onConnError(error);\n this.conn.onmessage = (event) => this.onConnMessage(event);\n this.conn.onclose = (event) => this.onConnClose(event);\n }\n getSession(key) {\n return this.sessionStore && this.sessionStore.getItem(key);\n }\n storeSession(key, val) {\n this.sessionStore && this.sessionStore.setItem(key, val);\n }\n connectWithFallback(fallbackTransport, fallbackThreshold = 2500) {\n clearTimeout(this.fallbackTimer);\n let established = false;\n let primaryTransport = true;\n let openRef, errorRef;\n let fallback = (reason) => {\n this.log(\"transport\", `falling back to ${fallbackTransport.name}...`, reason);\n this.off([openRef, errorRef]);\n primaryTransport = false;\n this.replaceTransport(fallbackTransport);\n this.transportConnect();\n };\n if (this.getSession(`phx:fallback:${fallbackTransport.name}`)) {\n return fallback(\"memorized\");\n }\n this.fallbackTimer = setTimeout(fallback, fallbackThreshold);\n errorRef = this.onError((reason) => {\n this.log(\"transport\", \"error\", reason);\n if (primaryTransport && !established) {\n clearTimeout(this.fallbackTimer);\n fallback(reason);\n }\n });\n if (this.fallbackRef) {\n this.off([this.fallbackRef]);\n }\n this.fallbackRef = this.onOpen(() => {\n established = true;\n if (!primaryTransport) {\n if (!this.primaryPassedHealthCheck) {\n this.storeSession(`phx:fallback:${fallbackTransport.name}`, \"true\");\n }\n return this.log(\"transport\", `established ${fallbackTransport.name} fallback`);\n }\n clearTimeout(this.fallbackTimer);\n this.fallbackTimer = setTimeout(fallback, fallbackThreshold);\n this.ping((rtt) => {\n this.log(\"transport\", \"connected to primary after\", rtt);\n this.primaryPassedHealthCheck = true;\n clearTimeout(this.fallbackTimer);\n });\n });\n this.transportConnect();\n }\n clearHeartbeats() {\n clearTimeout(this.heartbeatTimer);\n clearTimeout(this.heartbeatTimeoutTimer);\n }\n onConnOpen() {\n if (this.hasLogger()) this.log(\"transport\", `${this.transport.name} connected to ${this.endPointURL()}`);\n this.closeWasClean = false;\n this.disconnecting = false;\n this.establishedConnections++;\n this.flushSendBuffer();\n this.reconnectTimer.reset();\n this.resetHeartbeat();\n this.stateChangeCallbacks.open.forEach(([, callback]) => callback());\n }\n /**\n * @private\n */\n heartbeatTimeout() {\n if (this.pendingHeartbeatRef) {\n this.pendingHeartbeatRef = null;\n if (this.hasLogger()) {\n this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\");\n }\n this.triggerChanError();\n this.closeWasClean = false;\n this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, \"heartbeat timeout\");\n }\n }\n resetHeartbeat() {\n if (this.conn && this.conn.skipHeartbeat) {\n return;\n }\n this.pendingHeartbeatRef = null;\n this.clearHeartbeats();\n this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);\n }\n teardown(callback, code, reason) {\n if (!this.conn) {\n return callback && callback();\n }\n let connectClock = this.connectClock;\n this.waitForBufferDone(() => {\n if (connectClock !== this.connectClock) {\n return;\n }\n if (this.conn) {\n if (code) {\n this.conn.close(code, reason || \"\");\n } else {\n this.conn.close();\n }\n }\n this.waitForSocketClosed(() => {\n if (connectClock !== this.connectClock) {\n return;\n }\n if (this.conn) {\n this.conn.onopen = function() {\n };\n this.conn.onerror = function() {\n };\n this.conn.onmessage = function() {\n };\n this.conn.onclose = function() {\n };\n this.conn = null;\n }\n callback && callback();\n });\n });\n }\n waitForBufferDone(callback, tries = 1) {\n if (tries === 5 || !this.conn || !this.conn.bufferedAmount) {\n callback();\n return;\n }\n setTimeout(() => {\n this.waitForBufferDone(callback, tries + 1);\n }, 150 * tries);\n }\n waitForSocketClosed(callback, tries = 1) {\n if (tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed) {\n callback();\n return;\n }\n setTimeout(() => {\n this.waitForSocketClosed(callback, tries + 1);\n }, 150 * tries);\n }\n onConnClose(event) {\n if (this.conn) this.conn.onclose = () => {\n };\n let closeCode = event && event.code;\n if (this.hasLogger()) this.log(\"transport\", \"close\", event);\n this.triggerChanError();\n this.clearHeartbeats();\n if (!this.closeWasClean && closeCode !== 1e3) {\n this.reconnectTimer.scheduleTimeout();\n }\n this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event));\n }\n /**\n * @private\n */\n onConnError(error) {\n if (this.hasLogger()) this.log(\"transport\", error);\n let transportBefore = this.transport;\n let establishedBefore = this.establishedConnections;\n this.stateChangeCallbacks.error.forEach(([, callback]) => {\n callback(error, transportBefore, establishedBefore);\n });\n if (transportBefore === this.transport || establishedBefore > 0) {\n this.triggerChanError();\n }\n }\n /**\n * @private\n */\n triggerChanError() {\n this.channels.forEach((channel) => {\n if (!(channel.isErrored() || channel.isLeaving() || channel.isClosed())) {\n channel.trigger(CHANNEL_EVENTS.error);\n }\n });\n }\n /**\n * @returns {string}\n */\n connectionState() {\n switch (this.conn && this.conn.readyState) {\n case SOCKET_STATES.connecting:\n return \"connecting\";\n case SOCKET_STATES.open:\n return \"open\";\n case SOCKET_STATES.closing:\n return \"closing\";\n default:\n return \"closed\";\n }\n }\n /**\n * @returns {boolean}\n */\n isConnected() {\n return this.connectionState() === \"open\";\n }\n /**\n * @private\n *\n * @param {Channel}\n */\n remove(channel) {\n this.off(channel.stateChangeRefs);\n this.channels = this.channels.filter((c) => c !== channel);\n }\n /**\n * Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.\n *\n * @param {refs} - list of refs returned by calls to\n * `onOpen`, `onClose`, `onError,` and `onMessage`\n */\n off(refs) {\n for (let key in this.stateChangeCallbacks) {\n this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n return refs.indexOf(ref) === -1;\n });\n }\n }\n /**\n * Initiates a new channel for the given topic\n *\n * @param {string} topic\n * @param {Object} chanParams - Parameters for the channel\n * @returns {Channel}\n */\n channel(topic, chanParams = {}) {\n let chan = new Channel(topic, chanParams, this);\n this.channels.push(chan);\n return chan;\n }\n /**\n * @param {Object} data\n */\n push(data) {\n if (this.hasLogger()) {\n let { topic, event, payload, ref, join_ref } = data;\n this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload);\n }\n if (this.isConnected()) {\n this.encode(data, (result) => this.conn.send(result));\n } else {\n this.sendBuffer.push(() => this.encode(data, (result) => this.conn.send(result)));\n }\n }\n /**\n * Return the next message ref, accounting for overflows\n * @returns {string}\n */\n makeRef() {\n let newRef = this.ref + 1;\n if (newRef === this.ref) {\n this.ref = 0;\n } else {\n this.ref = newRef;\n }\n return this.ref.toString();\n }\n sendHeartbeat() {\n if (this.pendingHeartbeatRef && !this.isConnected()) {\n return;\n }\n this.pendingHeartbeatRef = this.makeRef();\n this.push({ topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.pendingHeartbeatRef });\n this.heartbeatTimeoutTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs);\n }\n flushSendBuffer() {\n if (this.isConnected() && this.sendBuffer.length > 0) {\n this.sendBuffer.forEach((callback) => callback());\n this.sendBuffer = [];\n }\n }\n onConnMessage(rawMessage) {\n this.decode(rawMessage.data, (msg) => {\n let { topic, event, payload, ref, join_ref } = msg;\n if (ref && ref === this.pendingHeartbeatRef) {\n this.clearHeartbeats();\n this.pendingHeartbeatRef = null;\n this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);\n }\n if (this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload);\n for (let i = 0; i < this.channels.length; i++) {\n const channel = this.channels[i];\n if (!channel.isMember(topic, event, payload, join_ref)) {\n continue;\n }\n channel.trigger(event, payload, ref, join_ref);\n }\n for (let i = 0; i < this.stateChangeCallbacks.message.length; i++) {\n let [, callback] = this.stateChangeCallbacks.message[i];\n callback(msg);\n }\n });\n }\n leaveOpenTopic(topic) {\n let dupChannel = this.channels.find((c) => c.topic === topic && (c.isJoined() || c.isJoining()));\n if (dupChannel) {\n if (this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`);\n dupChannel.leave();\n }\n }\n};\nexport {\n Channel,\n LongPoll,\n Presence,\n serializer_default as Serializer,\n Socket\n};\n//# sourceMappingURL=phoenix.mjs.map\n",null,null],"names":["closure","value","globalSelf","self","phxWindow","window","global","globalThis","SOCKET_STATES","CHANNEL_STATES","CHANNEL_EVENTS","TRANSPORTS","XHR_STATES","AUTH_TOKEN_PREFIX","Push","constructor","channel","event","payload","timeout","this","receivedResp","timeoutTimer","recHooks","sent","resend","reset","send","hasReceived","startTimeout","socket","push","topic","ref","join_ref","joinRef","receive","status","callback","response","cancelRefEvent","refEvent","matchReceive","_ref","filter","h","forEach","off","cancelTimeout","clearTimeout","makeRef","replyEventName","on","setTimeout","trigger","Timer","timerCalc","timer","tries","scheduleTimeout","Channel","params","state","bindings","bindingRef","joinedOnce","joinPush","pushBuffer","stateChangeRefs","rejoinTimer","isConnected","rejoin","rejoinAfterMs","onError","onOpen","isErrored","pushEvent","onClose","hasLogger","log","remove","reason","isJoining","join","Error","bind","canPush","isJoined","leave","leavePush","onMessage","_event","isMember","isLeaving","leaveOpenTopic","handledPayload","eventBindings","i","length","isClosed","Ajax","request","method","endPoint","headers","body","ontimeout","XDomainRequest","req","xdomainRequest","XMLHttpRequest","xhrRequest","fetch","AbortController","fetchRequest","options","controller","abort","signal","then","text","data","parseJSON","catch","err","name","open","onload","responseText","onprogress","key","Object","entries","setRequestHeader","onerror","onreadystatechange","readyState","resp","JSON","parse","console","serialize","obj","parentKey","queryStr","prototype","hasOwnProperty","call","paramKey","paramVal","encodeURIComponent","appendParams","url","keys","prefix","match","LongPoll","protocols","startsWith","authToken","atob","slice","token","skipHeartbeat","reqs","Set","awaitingBatchAck","currentBatch","currentBatchTimer","batchBuffer","onopen","onmessage","onclose","pollEndpoint","normalizeEndpoint","poll","replace","RegExp","endpointURL","closeAndRetry","code","wasClean","close","isActive","Accept","ajax","messages","msg","buffer","binary","bytes","Uint8Array","len","byteLength","String","fromCharCode","btoa","arrayBufferToBase64","batchSend","opts","assign","CloseEvent","onCallerTimeout","delete","add","serializer_default","HEADER_LENGTH","META_LENGTH","KINDS","reply","broadcast","encode","ArrayBuffer","binaryEncode","stringify","decode","rawPayload","binaryDecode","message","metaLength","header","view","DataView","offset","setUint8","Array","from","char","charCodeAt","combined","set","kind","getUint8","decoder","TextDecoder","decodePush","decodeReply","decodeBroadcast","joinRefSize","topicSize","eventSize","refSize","Socket","stateChangeCallbacks","error","channels","sendBuffer","fallbackRef","transport","WebSocket","primaryPassedHealthCheck","longPollFallbackMs","fallbackTimer","sessionStore","sessionStorage","establishedConnections","defaultEncoder","defaultDecoder","closeWasClean","disconnecting","binaryType","connectClock","pageHidden","awaitingConnectionOnPageShow","addEventListener","_e","conn","disconnect","connect","document","visibilityState","teardown","heartbeatIntervalMs","reconnectAfterMs","logger","debug","longpollerTimeout","vsn","heartbeatTimeoutTimer","heartbeatTimer","pendingHeartbeatRef","reconnectTimer","getLongPollTransport","replaceTransport","newTransport","protocol","location","endPointURL","uri","charAt","host","connectWithFallback","transportConnect","ping","startTime","Date","now","onMsgRef","onConnOpen","onConnError","onConnMessage","onConnClose","getSession","getItem","storeSession","val","setItem","fallbackTransport","fallbackThreshold","errorRef","established","primaryTransport","fallback","openRef","rtt","clearHeartbeats","flushSendBuffer","resetHeartbeat","heartbeatTimeout","triggerChanError","sendHeartbeat","waitForBufferDone","waitForSocketClosed","bufferedAmount","closeCode","transportBefore","establishedBefore","connectionState","c","refs","indexOf","chanParams","chan","result","newRef","toString","rawMessage","dupChannel","find","DEFAULT_BASE_URL","DEFAULT_REQUEST_TIMEOUT","ACTIVE_REQUEST_KEY","isStorageAvailable","testKey","localStorage","removeItem","saveActiveRequest","channelId","wsToken","websocketUrl","websocketChannel","timestamp","getActiveRequest","stored","clearActiveRequest","heartbeatInterval","steps","currentWebsocketChannel","isConnecting","listeners","Map","baseUrl","persist","storageKeyPrefix","requestTimeout","apiBaseUrl","args","warn","createLogger","getState","hasPendingRequest","errorMsg","setError","emit","cleanupConnection","id","updateStepAndEmit","wsUrl","socketUrl","endsWith","joinChannel","errorMessage","stopHeartbeat","duration","startHeartbeat","handleResponse","handleError","meta","duration_ms","reconnect","activeRequest","reconnectWithBackend","channel_id","ok","json","ws_token","websocket_url","websocket_channel","has","get","callbacks","updates","map","step","updateStep","s","setInterval","clearInterval","destroy","clear","parts","split","str","base64","padding","repeat","base64UrlDecode","project_id","exp"],"mappings":"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","x_google_ignoreList":[0]}