{"version":3,"file":"state.cjs","names":["generateUUID","EMBRACE_USER_SESSION_STATE_KEY","EMBRACE_PERMANENT_PROPERTIES_KEY"],"sources":["../../../../src/managers/EmbraceUserSessionManager/utils/state.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport type { NamespacedStorage } from '../../../utils/index.ts';\nimport { generateUUID } from '../../../utils/index.ts';\nimport {\n  EMBRACE_PERMANENT_PROPERTIES_KEY,\n  EMBRACE_USER_SESSION_STATE_KEY,\n  USER_SESSION_STATE_SCHEMA_VERSION,\n} from '../constants.ts';\nimport type { UserSessionState } from '../types.ts';\n\n/**\n * True when the stored state is no longer trustworthy: the device clock\n * jumped backwards past the recorded start, the max-duration deadline has\n * passed, or an inactivity deadline (set when the last part ended) has\n * passed. Inactivity only applies between parts; the deadline is null\n * while a part is active.\n */\nexport const isUserSessionExpired = (\n  state: UserSessionState,\n  now: number,\n): boolean =>\n  now < state.userSessionStartTs ||\n  now >= state.userSessionMaxEndTs ||\n  (state.inactivityDeadlineTs !== null && now >= state.inactivityDeadlineTs);\n\nexport interface CreateUserSessionStateArgs {\n  now: number;\n  previousUserSessionId: string | null;\n  userSessionMaxDurationSeconds: number;\n  userSessionInactivityTimeoutSeconds: number;\n  userSessionForegroundInactivityTimeoutSeconds: number;\n  userSessionNumber: number;\n}\n\nexport const createUserSessionState = ({\n  now,\n  previousUserSessionId,\n  userSessionMaxDurationSeconds,\n  userSessionInactivityTimeoutSeconds,\n  userSessionForegroundInactivityTimeoutSeconds,\n  userSessionNumber,\n}: CreateUserSessionStateArgs): UserSessionState => ({\n  schemaVersion: USER_SESSION_STATE_SCHEMA_VERSION,\n  userSessionId: generateUUID(),\n  previousUserSessionId,\n  userSessionStartTs: now,\n  userSessionMaxEndTs: now + userSessionMaxDurationSeconds * 1000,\n  userSessionNumber,\n  userSessionPartIndex: 0,\n  userSessionMaxDurationSeconds,\n  userSessionInactivityTimeoutSeconds,\n  userSessionForegroundInactivityTimeoutSeconds,\n  inactivityDeadlineTs: null,\n  userSessionProperties: {},\n});\n\n/**\n * Treats the schemaVersion stamp as the contract. Every field is written\n * by createUserSessionState (and userSessionProperties is validated at\n * addProperty time), so a matching version means the blob came from this\n * code path and we trust the rest of its shape.\n */\nconst isValidStoredUserSessionState = (\n  state: unknown,\n): state is UserSessionState =>\n  state !== null &&\n  typeof state === 'object' &&\n  (state as { schemaVersion?: unknown }).schemaVersion ===\n    USER_SESSION_STATE_SCHEMA_VERSION;\n\nexport const readUserSessionState = (\n  storage: NamespacedStorage,\n  diag: DiagLogger,\n): UserSessionState | null => {\n  const raw = storage.getItem(EMBRACE_USER_SESSION_STATE_KEY);\n  if (!raw) {\n    return null;\n  }\n  try {\n    const parsed: unknown = JSON.parse(raw);\n    if (!isValidStoredUserSessionState(parsed)) {\n      throw new Error('stored user session state failed structural validation');\n    }\n    return parsed;\n  } catch (e) {\n    diag.error('User session state in storage is corrupt; discarding it', e);\n    storage.removeItem(EMBRACE_USER_SESSION_STATE_KEY);\n    return null;\n  }\n};\n\nexport const readPermanentProperties = (\n  storage: NamespacedStorage,\n  diag: DiagLogger,\n): Record<string, string> => {\n  const raw = storage.getItem(EMBRACE_PERMANENT_PROPERTIES_KEY);\n  if (!raw) {\n    return {};\n  }\n  try {\n    const parsed = JSON.parse(raw) as unknown;\n    if (\n      parsed === null ||\n      typeof parsed !== 'object' ||\n      Array.isArray(parsed)\n    ) {\n      throw new Error('permanent properties blob is not a plain object');\n    }\n    const validated: Record<string, string> = {};\n    for (const [key, value] of Object.entries(parsed)) {\n      if (typeof value === 'string') {\n        validated[key] = value;\n      }\n    }\n    return validated;\n  } catch (e) {\n    diag.error('Permanent properties in storage are corrupt; discarding', e);\n    storage.removeItem(EMBRACE_PERMANENT_PROPERTIES_KEY);\n    return {};\n  }\n};\n\n/**\n * Empty blobs are removed rather than written so storage stays tidy when\n * the last property is cleared. Returns false on a failed write; callers\n * gate cross-scope flips on this so a failed permanent write doesn't\n * strip the previously-visible user-session-scoped value.\n */\nexport const storePermanentProperties = (\n  storage: NamespacedStorage,\n  properties: Record<string, string>,\n): boolean => {\n  if (Object.keys(properties).length === 0) {\n    return storage.removeItem(EMBRACE_PERMANENT_PROPERTIES_KEY);\n  }\n  return storage.setItem(\n    EMBRACE_PERMANENT_PROPERTIES_KEY,\n    JSON.stringify(properties),\n  );\n};\n"],"mappings":";;;;;;;;;;;AAiBA,MAAa,wBACX,OACA,QAEA,MAAM,MAAM,sBACZ,OAAO,MAAM,uBACZ,MAAM,yBAAyB,QAAQ,OAAO,MAAM;AAWvD,MAAa,0BAA0B,EACrC,KACA,uBACA,+BACA,qCACA,+CACA,yBACmD;CACnD,eAAA;CACA,eAAeA,2BAAAA,aAAa;CAC5B;CACA,oBAAoB;CACpB,qBAAqB,MAAM,gCAAgC;CAC3D;CACA,sBAAsB;CACtB;CACA;CACA;CACA,sBAAsB;CACtB,uBAAuB,CAAC;AAC1B;;;;;;;AAQA,MAAM,iCACJ,UAEA,UAAU,QACV,OAAO,UAAU,YAChB,MAAsC,kBAAA;AAGzC,MAAa,wBACX,SACA,SAC4B;CAC5B,MAAM,MAAM,QAAQ,QAAQC,qDAAAA,8BAA8B;CAC1D,IAAI,CAAC,KACH,OAAO;CAET,IAAI;EACF,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,IAAI,CAAC,8BAA8B,MAAM,GACvC,MAAM,IAAI,MAAM,wDAAwD;EAE1E,OAAO;CACT,SAAS,GAAG;EACV,KAAK,MAAM,2DAA2D,CAAC;EACvE,QAAQ,WAAWA,qDAAAA,8BAA8B;EACjD,OAAO;CACT;AACF;AAEA,MAAa,2BACX,SACA,SAC2B;CAC3B,MAAM,MAAM,QAAQ,QAAQC,qDAAAA,gCAAgC;CAC5D,IAAI,CAAC,KACH,OAAO,CAAC;CAEV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG;EAC7B,IACE,WAAW,QACX,OAAO,WAAW,YAClB,MAAM,QAAQ,MAAM,GAEpB,MAAM,IAAI,MAAM,iDAAiD;EAEnE,MAAM,YAAoC,CAAC;EAC3C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,OAAO,UAAU,UACnB,UAAU,OAAO;EAGrB,OAAO;CACT,SAAS,GAAG;EACV,KAAK,MAAM,2DAA2D,CAAC;EACvE,QAAQ,WAAWA,qDAAAA,gCAAgC;EACnD,OAAO,CAAC;CACV;AACF;;;;;;;AAQA,MAAa,4BACX,SACA,eACY;CACZ,IAAI,OAAO,KAAK,UAAU,CAAC,CAAC,WAAW,GACrC,OAAO,QAAQ,WAAWA,qDAAAA,gCAAgC;CAE5D,OAAO,QAAQ,QACbA,qDAAAA,kCACA,KAAK,UAAU,UAAU,CAC3B;AACF"}