@fluxstack/live-client 0.5.1 → 0.6.1
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/dist/index.cjs +29 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +29 -2
- package/dist/index.js.map +1 -1
- package/dist/live-client.browser.global.js +30 -2
- package/dist/live-client.browser.global.js.map +1 -1
- package/package.json +2 -2
- package/src/component.ts +4 -0
- package/src/connection.ts +17 -1
- package/src/persistence.ts +5 -1
- package/src/rooms.ts +4 -0
package/src/connection.ts
CHANGED
|
@@ -245,16 +245,32 @@ export class LiveConnection {
|
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
+
private consecutiveHeartbeatFailures = 0
|
|
249
|
+
private static readonly MAX_HEARTBEAT_FAILURES = 3
|
|
250
|
+
|
|
248
251
|
private startHeartbeat(): void {
|
|
249
252
|
this.stopHeartbeat()
|
|
253
|
+
this.consecutiveHeartbeatFailures = 0
|
|
250
254
|
this.heartbeatInterval = setInterval(() => {
|
|
251
255
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
256
|
+
let failed = false
|
|
252
257
|
for (const componentId of this.componentCallbacks.keys()) {
|
|
253
258
|
this.sendMessage({
|
|
254
259
|
type: 'COMPONENT_PING',
|
|
255
260
|
componentId,
|
|
256
261
|
timestamp: Date.now(),
|
|
257
|
-
}).catch(() => {})
|
|
262
|
+
}).catch(() => { failed = true })
|
|
263
|
+
}
|
|
264
|
+
if (failed) {
|
|
265
|
+
this.consecutiveHeartbeatFailures++
|
|
266
|
+
this.log(`Heartbeat failed (${this.consecutiveHeartbeatFailures}/${LiveConnection.MAX_HEARTBEAT_FAILURES})`)
|
|
267
|
+
if (this.consecutiveHeartbeatFailures >= LiveConnection.MAX_HEARTBEAT_FAILURES) {
|
|
268
|
+
this.log('Too many heartbeat failures, reconnecting...')
|
|
269
|
+
this.setState({ error: 'Heartbeat failed' })
|
|
270
|
+
this.reconnect()
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
this.consecutiveHeartbeatFailures = 0
|
|
258
274
|
}
|
|
259
275
|
}
|
|
260
276
|
}, this.options.heartbeatInterval)
|
package/src/persistence.ts
CHANGED
|
@@ -25,7 +25,11 @@ export function persistState(
|
|
|
25
25
|
localStorage.setItem(`${STORAGE_KEY_PREFIX}${name}`, JSON.stringify({
|
|
26
26
|
componentName: name, signedState, room, userId, lastUpdate: Date.now(),
|
|
27
27
|
}))
|
|
28
|
-
} catch {
|
|
28
|
+
} catch (e) {
|
|
29
|
+
if (typeof console !== 'undefined') {
|
|
30
|
+
console.warn(`[fluxstack] Failed to persist state for '${name}':`, e instanceof Error ? e.message : e)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
export function getPersistedState(enabled: boolean, name: string): PersistedState | null {
|
package/src/rooms.ts
CHANGED
|
@@ -18,6 +18,10 @@ function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>,
|
|
|
18
18
|
const result = { ...target }
|
|
19
19
|
for (const key of Object.keys(source) as Array<keyof T>) {
|
|
20
20
|
const newVal = source[key]
|
|
21
|
+
if (newVal === null) {
|
|
22
|
+
delete result[key]
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
21
25
|
const oldVal = result[key]
|
|
22
26
|
if (isPlainObject(oldVal) && isPlainObject(newVal)) {
|
|
23
27
|
result[key] = deepMerge(oldVal as any, newVal as any, seen)
|