@arthurreira/analytics 0.9.0 → 0.10.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/client.js CHANGED
@@ -135,9 +135,19 @@ function connectPresence(apiKey, sessionId, wsUrl = DEFAULT_WS_URL) {
135
135
  let attempts = 0;
136
136
  let intentionalClose = false;
137
137
  let retryTimer = null;
138
+ let targetUrl;
139
+ try {
140
+ const u = new URL(wsUrl);
141
+ u.searchParams.set("api_key", apiKey);
142
+ u.searchParams.set("session_id", sessionId);
143
+ targetUrl = u.toString();
144
+ } catch {
145
+ return { disconnect: () => {
146
+ } };
147
+ }
138
148
  function connect() {
139
149
  try {
140
- ws = new WebSocket(wsUrl);
150
+ ws = new WebSocket(targetUrl);
141
151
  } catch {
142
152
  return;
143
153
  }
@@ -195,12 +205,17 @@ function useAnalytics(apiUrl, apiKey, options) {
195
205
  if (typeof window === "undefined") return;
196
206
  const visitor_id = localStorage.getItem("af_analytics_visitor_id") || crypto.randomUUID();
197
207
  localStorage.setItem("af_analytics_visitor_id", visitor_id);
208
+ let cancelled = false;
198
209
  getOrCreateSession(apiUrl, apiKey, visitor_id).then((id) => {
210
+ if (cancelled) return;
199
211
  sessionId.current = id;
200
212
  presence.current = connectPresence(apiKey, id, options?.wsUrl);
201
213
  pendingEvents.current.forEach((fn) => fn());
202
214
  pendingEvents.current = [];
203
215
  });
216
+ return () => {
217
+ cancelled = true;
218
+ };
204
219
  }, []);
205
220
  useEffect(() => {
206
221
  if (typeof window === "undefined") return;
package/dist/index.d.ts CHANGED
@@ -7,4 +7,10 @@ declare function trackSearch(apiUrl: string, apiKey: string, sessionId: string,
7
7
  declare function trackError(apiUrl: string, apiKey: string, sessionId: string, path: string, error: Error): Promise<void>;
8
8
  declare function trackCTA(apiUrl: string, apiKey: string, sessionId: string, path: string, ctaId: string, ctaVariant?: string): Promise<void>;
9
9
 
10
- export { createSession, trackCTA, trackClick, trackCopy, trackError, trackPageview, trackScroll, trackSearch };
10
+ declare const DEFAULT_WS_URL = "wss://edge.arthurreira.dev/realtime";
11
+ interface PresenceConnection {
12
+ disconnect: () => void;
13
+ }
14
+ declare function connectPresence(apiKey: string, sessionId: string, wsUrl?: string): PresenceConnection;
15
+
16
+ export { DEFAULT_WS_URL, type PresenceConnection, connectPresence, createSession, trackCTA, trackClick, trackCopy, trackError, trackPageview, trackScroll, trackSearch };
package/dist/index.js CHANGED
@@ -114,7 +114,63 @@ async function trackCTA(apiUrl, apiKey, sessionId, path, ctaId, ctaVariant) {
114
114
  cta_variant: ctaVariant || null
115
115
  });
116
116
  }
117
+
118
+ // src/lib/presence.ts
119
+ var DEFAULT_WS_URL = "wss://edge.arthurreira.dev/realtime";
120
+ function connectPresence(apiKey, sessionId, wsUrl = DEFAULT_WS_URL) {
121
+ if (typeof WebSocket === "undefined") {
122
+ return { disconnect: () => {
123
+ } };
124
+ }
125
+ let ws = null;
126
+ let attempts = 0;
127
+ let intentionalClose = false;
128
+ let retryTimer = null;
129
+ let targetUrl;
130
+ try {
131
+ const u = new URL(wsUrl);
132
+ u.searchParams.set("api_key", apiKey);
133
+ u.searchParams.set("session_id", sessionId);
134
+ targetUrl = u.toString();
135
+ } catch {
136
+ return { disconnect: () => {
137
+ } };
138
+ }
139
+ function connect() {
140
+ try {
141
+ ws = new WebSocket(targetUrl);
142
+ } catch {
143
+ return;
144
+ }
145
+ ws.onopen = () => {
146
+ attempts = 0;
147
+ ws.send(JSON.stringify({ type: "join", api_key: apiKey, session_id: sessionId }));
148
+ };
149
+ ws.onclose = () => {
150
+ if (intentionalClose || attempts >= 3) return;
151
+ const delay = Math.pow(2, attempts) * 1e3;
152
+ attempts++;
153
+ retryTimer = setTimeout(connect, delay);
154
+ };
155
+ }
156
+ connect();
157
+ return {
158
+ disconnect: () => {
159
+ intentionalClose = true;
160
+ if (retryTimer !== null) {
161
+ clearTimeout(retryTimer);
162
+ retryTimer = null;
163
+ }
164
+ if (ws) {
165
+ ws.close();
166
+ ws = null;
167
+ }
168
+ }
169
+ };
170
+ }
117
171
  export {
172
+ DEFAULT_WS_URL,
173
+ connectPresence,
118
174
  createSession,
119
175
  trackCTA,
120
176
  trackClick,
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  { "name": "@arthurreira/analytics",
2
- "version": "0.9.0",
2
+ "version": "0.10.0",
3
3
  "type": "module",
4
4
  "scripts": {
5
5
  "build": "tsup",