@usero/sdk 1.1.1 → 1.1.2

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/react.js CHANGED
@@ -161,7 +161,11 @@ function getGradientEnd(color) {
161
161
 
162
162
  // src/identity.ts
163
163
  var ANON_STORAGE_KEY = "usero:anonymous-id";
164
+ var SDK_SESSION_STORAGE_KEY = "usero:session-replay:sdk-session-id";
164
165
  var cachedAnonymousId = null;
166
+ var cachedSdkSessionId = null;
167
+ var currentUserId = null;
168
+ var replayStartMs = null;
165
169
  var lastIdentifyFingerprint = null;
166
170
  function generateRandomId() {
167
171
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
@@ -192,6 +196,21 @@ function safeWriteLocalStorage(key, value) {
192
196
  } catch {
193
197
  }
194
198
  }
199
+ function safeReadSessionStorage(key) {
200
+ if (typeof window === "undefined") return null;
201
+ try {
202
+ return window.sessionStorage?.getItem(key) ?? null;
203
+ } catch {
204
+ return null;
205
+ }
206
+ }
207
+ function safeWriteSessionStorage(key, value) {
208
+ if (typeof window === "undefined") return;
209
+ try {
210
+ window.sessionStorage?.setItem(key, value);
211
+ } catch {
212
+ }
213
+ }
195
214
  function getOrMintAnonymousId() {
196
215
  if (cachedAnonymousId) return cachedAnonymousId;
197
216
  const existing = safeReadLocalStorage(ANON_STORAGE_KEY);
@@ -209,8 +228,30 @@ function rotateAnonymousId() {
209
228
  cachedAnonymousId = id;
210
229
  safeWriteLocalStorage(ANON_STORAGE_KEY, id);
211
230
  lastIdentifyFingerprint = null;
231
+ currentUserId = null;
212
232
  return id;
213
233
  }
234
+ function getOrMintSdkSessionId() {
235
+ if (cachedSdkSessionId) return cachedSdkSessionId;
236
+ const existing = safeReadSessionStorage(SDK_SESSION_STORAGE_KEY);
237
+ if (existing && /^[a-z0-9-]{8,}$/i.test(existing)) {
238
+ cachedSdkSessionId = existing;
239
+ return existing;
240
+ }
241
+ const id = generateRandomId();
242
+ safeWriteSessionStorage(SDK_SESSION_STORAGE_KEY, id);
243
+ cachedSdkSessionId = id;
244
+ return id;
245
+ }
246
+ function getCurrentUserId() {
247
+ return currentUserId;
248
+ }
249
+ function publishReplayStartMs(epochMs) {
250
+ if (replayStartMs === null) replayStartMs = epochMs;
251
+ }
252
+ function getReplayStartMs() {
253
+ return replayStartMs;
254
+ }
214
255
  function fingerprintUser(anonymousId, user) {
215
256
  const traits = user.traits ?? {};
216
257
  const keys = Object.keys(traits).sort();
@@ -219,6 +260,7 @@ function fingerprintUser(anonymousId, user) {
219
260
  }
220
261
  async function identifyIfChanged(transport, user) {
221
262
  const anonymousId = getOrMintAnonymousId();
263
+ currentUserId = user.id;
222
264
  const fp = fingerprintUser(anonymousId, user);
223
265
  if (fp === lastIdentifyFingerprint) return false;
224
266
  const url = `${transport.apiUrl.replace(/\/$/, "")}/api/identify`;
@@ -907,7 +949,15 @@ function initUseroFeedbackWidget(props) {
907
949
  } else {
908
950
  resolveAndApplyGetUser();
909
951
  }
910
- }
952
+ },
953
+ // Core-owned cross-cutting identity. Every plugin reads the same
954
+ // source of truth in identity.ts, so user-test and session-replay
955
+ // agree on the per-tab sdkSessionId without importing each other.
956
+ getSdkSessionId: () => getOrMintSdkSessionId(),
957
+ getAnonymousId: () => getOrMintAnonymousId(),
958
+ getUserId: () => getCurrentUserId(),
959
+ getReplayStartMs: () => getReplayStartMs(),
960
+ publishReplayStartMs: (epochMs) => publishReplayStartMs(epochMs)
911
961
  };
912
962
  pluginContexts.set(plugin.name, ctx);
913
963
  if (plugin.onInit) {