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