@sesionario/blocks 1.13.1 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -6985,6 +6985,162 @@ function createSupportChatClient(basePath = "/api/chat-svc") {
6985
6985
  }
6986
6986
  var DEFAULT_RECONNECT_MS = 2e3;
6987
6987
  var MAX_RECONNECT_MS = 3e4;
6988
+ var HEARTBEAT_MS = 3e4;
6989
+ var registry = /* @__PURE__ */ new Map();
6990
+ function channelKeyFromUrl(url) {
6991
+ const q = url.indexOf("?");
6992
+ return q === -1 ? url : url.slice(0, q);
6993
+ }
6994
+ function stopHeartbeat(shared) {
6995
+ if (shared.heartbeatTimer) {
6996
+ clearInterval(shared.heartbeatTimer);
6997
+ shared.heartbeatTimer = null;
6998
+ }
6999
+ }
7000
+ function startHeartbeat(shared, gen) {
7001
+ stopHeartbeat(shared);
7002
+ shared.heartbeatTimer = setInterval(() => {
7003
+ if (gen !== shared.gen) return;
7004
+ if (shared.ws?.readyState === WebSocket.OPEN) {
7005
+ try {
7006
+ shared.ws.send("ping");
7007
+ } catch {
7008
+ }
7009
+ }
7010
+ }, HEARTBEAT_MS);
7011
+ }
7012
+ function clearReconnect(shared) {
7013
+ if (shared.reconnectTimer) {
7014
+ clearTimeout(shared.reconnectTimer);
7015
+ shared.reconnectTimer = null;
7016
+ }
7017
+ }
7018
+ function openSocket(shared, url) {
7019
+ const gen = ++shared.gen;
7020
+ clearReconnect(shared);
7021
+ if (shared.ws) {
7022
+ try {
7023
+ shared.ws.close();
7024
+ } catch {
7025
+ }
7026
+ }
7027
+ const ws = new WebSocket(url);
7028
+ shared.ws = ws;
7029
+ ws.onopen = () => {
7030
+ if (gen !== shared.gen) return;
7031
+ shared.attempt = 0;
7032
+ startHeartbeat(shared, gen);
7033
+ };
7034
+ ws.onmessage = (msg) => {
7035
+ if (gen !== shared.gen) return;
7036
+ let data;
7037
+ try {
7038
+ data = JSON.parse(String(msg.data));
7039
+ } catch {
7040
+ return;
7041
+ }
7042
+ if (typeof data?.type !== "string") return;
7043
+ if (data.type === "pong") return;
7044
+ for (const listener of shared.listeners) {
7045
+ listener(data);
7046
+ }
7047
+ };
7048
+ ws.onclose = () => {
7049
+ if (gen !== shared.gen) return;
7050
+ shared.ws = null;
7051
+ stopHeartbeat(shared);
7052
+ scheduleReconnect(shared);
7053
+ };
7054
+ ws.onerror = () => {
7055
+ };
7056
+ }
7057
+ function scheduleReconnect(shared) {
7058
+ if (shared.listeners.size === 0) return;
7059
+ clearReconnect(shared);
7060
+ const delay = Math.min(
7061
+ shared.reconnectDelayMs * 2 ** shared.attempt,
7062
+ MAX_RECONNECT_MS
7063
+ );
7064
+ shared.attempt += 1;
7065
+ shared.reconnectTimer = setTimeout(() => {
7066
+ shared.reconnectTimer = null;
7067
+ void connectShared(shared);
7068
+ }, delay);
7069
+ }
7070
+ async function connectShared(shared) {
7071
+ if (shared.connecting || shared.listeners.size === 0) return;
7072
+ shared.connecting = true;
7073
+ let url = null;
7074
+ try {
7075
+ url = await shared.getWsUrl();
7076
+ } finally {
7077
+ shared.connecting = false;
7078
+ }
7079
+ if (shared.listeners.size === 0) return;
7080
+ if (!url) return;
7081
+ openSocket(shared, url);
7082
+ }
7083
+ function destroyShared(shared) {
7084
+ shared.gen += 1;
7085
+ clearReconnect(shared);
7086
+ stopHeartbeat(shared);
7087
+ if (shared.ws) {
7088
+ try {
7089
+ shared.ws.close();
7090
+ } catch {
7091
+ }
7092
+ shared.ws = null;
7093
+ }
7094
+ }
7095
+ function joinChannel(key, url, getWsUrl, reconnectDelayMs, listener) {
7096
+ ensureVisibilityHook();
7097
+ let shared = registry.get(key);
7098
+ if (!shared) {
7099
+ shared = {
7100
+ key,
7101
+ listeners: /* @__PURE__ */ new Set(),
7102
+ getWsUrl,
7103
+ reconnectDelayMs,
7104
+ ws: null,
7105
+ attempt: 0,
7106
+ reconnectTimer: null,
7107
+ heartbeatTimer: null,
7108
+ connecting: false,
7109
+ gen: 0
7110
+ };
7111
+ registry.set(key, shared);
7112
+ shared.listeners.add(listener);
7113
+ openSocket(shared, url);
7114
+ return;
7115
+ }
7116
+ shared.getWsUrl = getWsUrl;
7117
+ shared.listeners.add(listener);
7118
+ if (!shared.ws && !shared.connecting && !shared.reconnectTimer) {
7119
+ openSocket(shared, url);
7120
+ }
7121
+ }
7122
+ function leaveChannel(key, listener) {
7123
+ const shared = registry.get(key);
7124
+ if (!shared) return;
7125
+ shared.listeners.delete(listener);
7126
+ if (shared.listeners.size === 0) {
7127
+ destroyShared(shared);
7128
+ registry.delete(key);
7129
+ }
7130
+ }
7131
+ var visibilityHooked = false;
7132
+ function ensureVisibilityHook() {
7133
+ if (visibilityHooked || typeof document === "undefined") return;
7134
+ visibilityHooked = true;
7135
+ document.addEventListener("visibilitychange", () => {
7136
+ if (document.visibilityState !== "visible") return;
7137
+ for (const shared of registry.values()) {
7138
+ if (!shared.ws && !shared.reconnectTimer && !shared.connecting) {
7139
+ void connectShared(shared);
7140
+ }
7141
+ }
7142
+ });
7143
+ }
6988
7144
  function useRealtimeChannel({
6989
7145
  getWsUrl,
6990
7146
  onEvent,
@@ -6998,87 +7154,26 @@ function useRealtimeChannel({
6998
7154
  React7.useEffect(() => {
6999
7155
  if (!enabled) return;
7000
7156
  let cancelled = false;
7001
- let socket = null;
7002
- let reconnectTimer = null;
7003
- let attempt = 0;
7004
- const connectGen = { current: 0 };
7005
- const clearReconnect = () => {
7006
- if (reconnectTimer) {
7007
- clearTimeout(reconnectTimer);
7008
- reconnectTimer = null;
7009
- }
7010
- };
7011
- const scheduleReconnect = () => {
7012
- if (cancelled) return;
7013
- clearReconnect();
7014
- const delay = Math.min(reconnectDelayMs * 2 ** attempt, MAX_RECONNECT_MS);
7015
- attempt += 1;
7016
- reconnectTimer = setTimeout(() => {
7017
- void connect();
7018
- }, delay);
7019
- };
7020
- const connect = async () => {
7021
- const gen = ++connectGen.current;
7022
- clearReconnect();
7023
- const url = await getWsUrlRef.current();
7024
- if (cancelled || gen !== connectGen.current) return;
7025
- if (!url) {
7026
- scheduleReconnect();
7027
- return;
7028
- }
7029
- if (socket) {
7030
- try {
7031
- socket.close();
7032
- } catch {
7033
- }
7034
- socket = null;
7035
- }
7036
- const ws = new WebSocket(url);
7037
- socket = ws;
7038
- ws.onopen = () => {
7039
- if (cancelled || gen !== connectGen.current) return;
7040
- attempt = 0;
7041
- };
7042
- ws.onmessage = (msg) => {
7043
- if (cancelled || gen !== connectGen.current) return;
7044
- let data;
7045
- try {
7046
- data = JSON.parse(String(msg.data));
7047
- } catch {
7048
- return;
7049
- }
7050
- if (typeof data?.type !== "string") return;
7051
- if (data.type === "pong") return;
7052
- onEventRef.current(data);
7053
- };
7054
- ws.onclose = () => {
7055
- if (cancelled || gen !== connectGen.current) return;
7056
- socket = null;
7057
- scheduleReconnect();
7058
- };
7059
- ws.onerror = () => {
7060
- };
7157
+ let joinedKey = null;
7158
+ const listener = (event) => onEventRef.current(event);
7159
+ const resolver = () => getWsUrlRef.current();
7160
+ const join = async () => {
7161
+ if (cancelled || joinedKey) return;
7162
+ const url = await resolver();
7163
+ if (cancelled || !url) return;
7164
+ joinedKey = channelKeyFromUrl(url);
7165
+ joinChannel(joinedKey, url, resolver, reconnectDelayMs, listener);
7061
7166
  };
7062
7167
  const onVisibility = () => {
7063
7168
  if (document.visibilityState !== "visible" || cancelled) return;
7064
- if (!socket || socket.readyState === WebSocket.CLOSED) {
7065
- void connect();
7066
- }
7169
+ if (!joinedKey) void join();
7067
7170
  };
7068
- void connect();
7171
+ void join();
7069
7172
  document.addEventListener("visibilitychange", onVisibility);
7070
7173
  return () => {
7071
7174
  cancelled = true;
7072
- connectGen.current += 1;
7073
- clearReconnect();
7074
7175
  document.removeEventListener("visibilitychange", onVisibility);
7075
- if (socket) {
7076
- try {
7077
- socket.close();
7078
- } catch {
7079
- }
7080
- socket = null;
7081
- }
7176
+ if (joinedKey) leaveChannel(joinedKey, listener);
7082
7177
  };
7083
7178
  }, [enabled, reconnectDelayMs]);
7084
7179
  }