@wireai/activation 0.9.1 → 0.9.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../node_modules/expo-modules-core/src/errors/CodedError.ts","../../node_modules/expo-modules-core/src/NativeModulesProxy.ts","../../node_modules/expo-modules-core/src/TurboModuleToExpoModuleProxy.ts","../../node_modules/expo-modules-core/src/ensureNativeModulesAreInstalled.ts","../../node_modules/expo-modules-core/src/requireNativeModule.ts","../../node_modules/expo-modules-core/src/sweet/setUpJsLogger.fx.ts","../../node_modules/expo-modules-core/src/registerWebModule.ts","../../node_modules/expo-modules-core/src/TypedArrays.types.ts","../../node_modules/expo-modules-core/src/PermissionsInterface.ts","../../node_modules/expo-modules-core/src/PermissionsHook.ts","../../node_modules/expo-modules-core/src/Refs.ts","../../node_modules/expo-modules-core/src/hooks/useReleasingSharedObject.ts","../../node_modules/expo-modules-core/src/reload.ts","../../node_modules/expo-modules-core/src/index.ts","../../node_modules/expo-constants/src/Constants.types.ts","../../node_modules/expo-constants/src/ExponentConstants.ts","../../node_modules/expo-constants/src/Constants.ts","../../src/reviews/transport.ts","../../src/analytics/screenTracking.ts","../../src/analytics/useScreenTracking.ts","../../src/analytics/reportClientEvent.ts","../../src/analytics/analyticsEvent.ts","../../src/device/appVersion.ts","../../src/device/deviceModel.ts","../../src/device/deviceContext.ts","../../src/analytics/contextEnvelope.ts","../../src/analytics/eventQueue.ts","../../src/analytics/currentSession.ts","../../src/identity/userIdentity.ts","../../src/context/userContext.ts","../../src/context/deviceId.ts","../../src/analytics/analyticsFacade.ts","../../src/analytics/useAnalytics.ts"],"names":["name","_a","TurboModuleRegistry","AppOwnership","ExecutionEnvironment","UserInterfaceIdiom","Platform","NativeModules","useRef","useEffect","constants","runtimeRequire","interop","safeInterop","Dimensions","I18nManager","_b"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * A general error class that should be used for all errors in Expo modules.\n * Guarantees a `code` field that can be used to differentiate between different\n * types of errors without further subclassing Error.\n */\nexport class CodedError extends Error {\n code: string;\n info?: any;\n\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n }\n}\n","import type { ProxyNativeModule } from './NativeModulesProxy.types';\n\n// We default to an empty object shim wherever we don't have an environment-specific implementation\n\n/**\n * @deprecated `NativeModulesProxy` is deprecated and might be removed in the future releases.\n * Use `requireNativeModule` or `requireOptionalNativeModule` instead.\n */\nexport default {} as Record<string, ProxyNativeModule>;\n","// Copyright © 2024 650 Industries.\nimport type { TurboModule } from 'react-native';\n\nexport function createTurboModuleToExpoProxy(turboModule: TurboModule | null, name: string) {\n return null;\n}\n","// Installs the expo global on web\nimport './polyfill';\n\n/**\n * Ensures that the native modules are installed in the current runtime.\n * Otherwise, it synchronously calls a native function that installs them.\n */\nexport function ensureNativeModulesAreInstalled(): void {\n // No-op on web\n}\n","import { TurboModuleRegistry } from 'react-native';\n\nimport NativeModulesProxy from './NativeModulesProxy';\nimport { createTurboModuleToExpoProxy } from './TurboModuleToExpoModuleProxy';\nimport { ensureNativeModulesAreInstalled } from './ensureNativeModulesAreInstalled';\n\n/**\n * Imports the native module registered with given name. In the first place it tries to load\n * the module installed through the JSI host object and then falls back to the bridge proxy module.\n * Notice that the modules loaded from the proxy may not support some features like synchronous functions.\n *\n * @param moduleName Name of the requested native module.\n * @returns Object representing the native module.\n * @throws Error when there is no native module with given name.\n */\nexport function requireNativeModule<ModuleType = any>(moduleName: string): ModuleType {\n const nativeModule = requireOptionalNativeModule<ModuleType>(moduleName);\n\n if (!nativeModule) {\n throw new Error(`Cannot find native module '${moduleName}'`);\n }\n return nativeModule;\n}\n\n/**\n * Imports the native module registered with the given name. The same as `requireNativeModule`,\n * but returns `null` when the module cannot be found instead of throwing an error.\n *\n * @param moduleName Name of the requested native module.\n * @returns Object representing the native module or `null` when it cannot be found.\n */\nexport function requireOptionalNativeModule<ModuleType = any>(\n moduleName: string\n): ModuleType | null {\n ensureNativeModulesAreInstalled();\n\n try {\n return (\n globalThis.expo?.modules?.[moduleName] ??\n NativeModulesProxy[moduleName] ??\n createTurboModuleToExpoProxy(TurboModuleRegistry.get(moduleName), moduleName) ??\n null\n );\n } catch (e) {\n const error = e as Error;\n console.warn(`An error occurred while requiring the '${moduleName}' module: ${error.message}`);\n return null;\n }\n}\n","import { CodedError } from '../errors/CodedError';\nimport { requireOptionalNativeModule } from '../requireNativeModule';\n\ntype LogListener = {\n action: (...data: any[]) => void;\n eventName: string;\n};\n\nif (\n __DEV__ &&\n typeof window !== 'undefined' &&\n (process.env.EXPO_OS === 'android' || process.env.EXPO_OS === 'ios')\n) {\n const NativeJSLogger = requireOptionalNativeModule('ExpoModulesCoreJSLogger');\n if (NativeJSLogger) {\n const onNewException: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewError',\n action: console.error,\n };\n\n const onNewWarning: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewWarning',\n action: console.warn,\n };\n\n const onNewDebug: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewDebug',\n action: console.debug,\n };\n\n const onNewInfo: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewInfo',\n action: console.info,\n };\n\n const onNewTrace: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewTrace',\n action: console.trace,\n };\n\n const listeners: LogListener[] = [\n onNewException,\n onNewWarning,\n onNewDebug,\n onNewInfo,\n onNewTrace,\n ];\n\n for (const listener of listeners) {\n NativeJSLogger.addListener(listener.eventName, ({ message }: { message: string }) => {\n listener.action(message);\n });\n }\n }\n}\n\ndeclare namespace globalThis {\n let ExpoModulesCore_CodedError: undefined | typeof CodedError;\n}\n\n// We have to export `CodedError` via global object to use in later in the C++ code.\nglobalThis.ExpoModulesCore_CodedError = CodedError;\n","import { ensureNativeModulesAreInstalled } from './ensureNativeModulesAreInstalled';\nimport type { NativeModule } from './ts-declarations/NativeModule';\n\n/**\n * Registers a web module.\n * @param moduleImplementation A class that extends `NativeModule`. The class is registered under `globalThis.expo.modules[className]`.\n * @param moduleName A name to register the module under `globalThis.expo.modules[className]`.\n * @returns A singleton instance of the class passed into arguments.\n */\n\nexport function registerWebModule<\n EventsMap extends Record<never, never>,\n ModuleType extends typeof NativeModule<EventsMap>,\n>(moduleImplementation: ModuleType, moduleName: string): ModuleType {\n ensureNativeModulesAreInstalled();\n\n moduleName = moduleName ?? moduleImplementation.name;\n if (!moduleName) {\n throw new Error(\n 'Web module implementation is missing a name - it is either not a class or has been minified. Pass the name as a second argument to the `registerWebModule` function.'\n );\n }\n if (!globalThis?.expo?.modules) {\n globalThis.expo.modules = {};\n }\n if (globalThis.expo.modules[moduleName]) {\n return globalThis.expo.modules[moduleName];\n }\n globalThis.expo.modules[moduleName] = new moduleImplementation();\n return globalThis.expo.modules[moduleName];\n}\n","/** A union type for all integer based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type IntBasedTypedArray = Int8Array | Int16Array | Int32Array;\n\n/** A union type for all unsigned integer based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type UintBasedTypedArray = Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array;\n\n/** A union type for all floating point based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type FloatBasedTypedArray = Float32Array | Float64Array;\n\n/** A [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) describes an array-like view of an underlying binary data buffer. */\nexport type TypedArray = IntBasedTypedArray | UintBasedTypedArray | FloatBasedTypedArray;\n","export enum PermissionStatus {\n /**\n * User has granted the permission.\n */\n GRANTED = 'granted',\n /**\n * User hasn't granted or denied the permission yet.\n */\n UNDETERMINED = 'undetermined',\n /**\n * User has denied the permission.\n */\n DENIED = 'denied',\n}\n\n/**\n * Permission expiration time. Currently, all permissions are granted permanently.\n */\nexport type PermissionExpiration = 'never' | number;\n\n/**\n * An object obtained by permissions get and request functions.\n */\nexport type PermissionResponse = {\n /**\n * Determines the status of the permission.\n */\n status: PermissionStatus;\n /**\n * Determines time when the permission expires.\n */\n expires: PermissionExpiration;\n /**\n * A convenience boolean that indicates if the permission is granted.\n */\n granted: boolean;\n /**\n * Indicates if user can be asked again for specific permission.\n * If not, one should be directed to the Settings app\n * in order to enable/disable the permission.\n */\n canAskAgain: boolean;\n};\n","// Copyright © 2024 650 Industries.\n\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { PermissionResponse } from './PermissionsInterface';\n\n// These types are identical, but improves the readability for suggestions in editors\ntype RequestPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;\ntype GetPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;\n\ntype PermissionHookMethods<Permission extends PermissionResponse, Options = never> = {\n /** The permission method that requests the user to grant permission. */\n requestMethod: (options?: Options) => Promise<Permission>;\n /** The permission method that only fetches the current permission status. */\n getMethod: (options?: Options) => Promise<Permission>;\n};\n\ntype PermissionHookBehavior = {\n /** If the hook should automatically fetch the current permission status, without asking the user. */\n get?: boolean;\n /** If the hook should automatically request the user to grant permission. */\n request?: boolean;\n};\n\nexport type PermissionHookOptions<Options extends object> = PermissionHookBehavior & Options;\n\n/**\n * Get or request permission for protected functionality within the app.\n * It uses separate permission requesters to interact with a single permission.\n * By default, the hook will only retrieve the permission status.\n */\nfunction usePermission<Permission extends PermissionResponse, Options extends object>(\n methods: PermissionHookMethods<Permission, Options>,\n options?: PermissionHookOptions<Options>\n): [Permission | null, RequestPermissionMethod<Permission>, GetPermissionMethod<Permission>] {\n const isMounted = useRef(true);\n const [status, setStatus] = useState<Permission | null>(null);\n const { get = true, request = false, ...permissionOptions } = options || {};\n\n const getPermission = useCallback(async () => {\n let response: Permission;\n if (Object.keys(permissionOptions).length > 0) {\n response = await methods.getMethod(permissionOptions as Options);\n } else {\n response = await methods.getMethod();\n }\n if (isMounted.current) setStatus(response);\n return response;\n }, [methods.getMethod]);\n\n const requestPermission = useCallback(async () => {\n let response: Permission;\n if (Object.keys(permissionOptions).length > 0) {\n response = await methods.requestMethod(permissionOptions as Options);\n } else {\n response = await methods.requestMethod();\n }\n if (isMounted.current) setStatus(response);\n return response;\n }, [methods.requestMethod]);\n\n useEffect(\n function runMethods() {\n if (request) requestPermission();\n if (!request && get) getPermission();\n },\n [get, request, requestPermission, getPermission]\n );\n\n // Workaround for unmounting components receiving state updates\n useEffect(function didMount() {\n isMounted.current = true;\n return () => {\n isMounted.current = false;\n };\n }, []);\n\n return [status, requestPermission, getPermission];\n}\n\n/**\n * Create a new permission hook with the permission methods built-in.\n * This can be used to quickly create specific permission hooks in every module.\n */\nexport function createPermissionHook<Permission extends PermissionResponse, Options extends object>(\n methods: PermissionHookMethods<Permission, Options>\n) {\n return (options?: PermissionHookOptions<Options>) =>\n usePermission<Permission, Options>(methods, options);\n}\n","import { createRef, type RefObject } from 'react';\n\n/**\n * Create a React ref object that is friendly for snapshots.\n * It will be represented as `[React.ref]` in snapshots.\n * @returns A React ref object.\n */\nexport function createSnapshotFriendlyRef<T>(): RefObject<T | null> {\n return createRef<T>();\n}\n","'use client';\n\nimport type { DependencyList } from 'react';\nimport { useEffect, useMemo, useRef } from 'react';\n\nimport type { SharedObject } from '../ts-declarations/SharedObject';\n\n/**\n * Returns a shared object, which is automatically cleaned up when the component is unmounted.\n */\nexport function useReleasingSharedObject<TSharedObject extends SharedObject>(\n factory: () => TSharedObject,\n dependencies: DependencyList\n): TSharedObject {\n const objectRef = useRef<TSharedObject | null>(null);\n const objectRefToRelease = useRef<TSharedObject | null>(null);\n const isFastRefresh = useRef(false);\n const previousDependencies = useRef<DependencyList>(dependencies);\n\n if (objectRef.current == null) {\n objectRef.current = factory();\n }\n\n const object = useMemo(() => {\n let newObject = objectRef.current;\n const dependenciesAreEqual =\n previousDependencies.current?.length === dependencies.length &&\n dependencies.every((value, index) => value === previousDependencies.current[index]);\n\n // If the dependencies have changed, schedule the previous object for release and create a new one,\n // otherwise this has been called because of an unrelated fast refresh, and we don't want to release the object.\n if (!newObject || !dependenciesAreEqual) {\n objectRefToRelease.current = objectRef.current;\n newObject = factory();\n objectRef.current = newObject;\n previousDependencies.current = dependencies;\n }\n return newObject;\n }, dependencies);\n\n useEffect(() => {\n // When the object changes, release the previous one - it is important to do this in a useEffect, so that we don't release\n // the object during render.\n if (objectRefToRelease.current) {\n objectRefToRelease.current.release();\n objectRefToRelease.current = null;\n }\n }, [object]);\n\n useMemo(() => {\n isFastRefresh.current = true;\n }, []);\n\n useEffect(() => {\n isFastRefresh.current = false;\n\n return () => {\n // This will be called on every fast refresh and on unmount, but we only want to release the object on unmount.\n if (!isFastRefresh.current && objectRef.current) {\n objectRef.current.release();\n }\n };\n }, []);\n\n return object;\n}\n","/**\n * Reloads the app. This method works for both release and debug builds.\n *\n * Unlike [`Updates.reloadAsync()`](/versions/latest/sdk/updates/#updatesreloadasync),\n * this function does not use a new update even if one is available. It only reloads the app using the same JavaScript bundle that is currently running.\n *\n * @param reason The reason for reloading the app. This is used only for some platforms.\n */\nexport async function reloadAppAsync(reason: string = 'Reloaded from JS call'): Promise<void> {\n await globalThis.expo?.reloadAppAsync(reason);\n}\n","import './ts-declarations/global';\nimport './sweet/setUpJsLogger.fx';\nimport './polyfill';\n\nexport type * from './ts-declarations/global';\n\nexport { EventEmitter, type EventSubscription } from './EventEmitter';\nexport { NativeModule } from './NativeModule';\nexport { SharedObject } from './SharedObject';\nexport { SharedRef } from './SharedRef';\n\nexport { default as Platform } from './Platform';\nexport { default as uuid } from './uuid';\n\nexport type { ProxyNativeModule } from './NativeModulesProxy.types';\nexport { requireNativeViewManager } from './NativeViewManagerAdapter';\n\nexport * from './requireNativeModule';\nexport * from './registerWebModule';\nexport * from './TypedArrays.types';\n\nexport * from './PermissionsInterface';\nexport * from './PermissionsHook';\n\nexport * from './Refs';\n\nexport * from './hooks/useReleasingSharedObject';\nexport * from './reload';\n\n// Errors\nexport { CodedError } from './errors/CodedError';\nexport { UnavailabilityError } from './errors/UnavailabilityError';\n\n// Deprecated\nexport { LegacyEventEmitter } from './LegacyEventEmitter';\nexport { default as NativeModulesProxy } from './NativeModulesProxy';\n\nexport { installOnUIRuntime } from './worklets';\n","import type { ExpoConfig } from 'expo/config';\nimport type {\n EASConfig as ManifestsEASConfig,\n ExpoGoConfig as ManifestsExpoGoConfig,\n ExpoUpdatesManifest,\n EmbeddedManifest,\n ManifestAsset as ManifestAssetForReExport,\n ManifestExtra as ManifestExtraForReExport,\n ClientScopingConfig as ClientScopingConfigForReExport,\n ExpoGoPackagerOpts as ExpoGoPackagerOptsForReExport,\n // @ts-ignore -- optional interface, will gracefully degrade to `any` not installed\n} from 'expo-manifests';\n\nexport enum AppOwnership {\n /**\n * The experience is running inside the Expo Go app.\n * @deprecated Use [`Constants.executionEnvironment`](#executionenvironment) instead.\n */\n Expo = 'expo',\n}\n\n/**\n * Identifies where the app's JavaScript bundle is currently running.\n */\nexport enum ExecutionEnvironment {\n /** A project that includes native project directories that you maintain directly in your\n * [existing React Native project](/bare/overview/).\n */\n Bare = 'bare',\n /** Production/release build created with or without EAS Build. */\n Standalone = 'standalone',\n /** Expo Go or a development build built with `expo-dev-client`. */\n StoreClient = 'storeClient',\n}\n\n// @needsAudit\n/**\n * Current supported values are `handset`, `tablet`, `desktop` and `tv`. CarPlay will show up\n * as `unsupported`.\n */\nexport enum UserInterfaceIdiom {\n Handset = 'handset',\n Tablet = 'tablet',\n Desktop = 'desktop',\n TV = 'tv',\n Unsupported = 'unsupported',\n}\n\n// @needsAudit\n/**\n * @platform ios\n */\nexport type IOSManifest = {\n /**\n * The build number specified in the embedded **Info.plist** value for `CFBundleVersion` in this app.\n * In a standalone app, you can set this with the `ios.buildNumber` value in **app.json**. This\n * may differ from the value in `Constants.expoConfig.ios.buildNumber` because the manifest\n * can be updated, whereas this value will never change for a given native binary.\n * The value is set to `null` in case you run your app in Expo Go.\n */\n buildNumber: string | null;\n /**\n * The Apple internal model identifier for this device.\n * @example\n * `iPhone1,1`\n * @deprecated Use `expo-device`'s [`Device.modelId`](./device/#devicemodelid).\n */\n platform: string;\n /**\n * The human-readable model name of this device. For example, `\"iPhone 7 Plus\"` if it can be determined,\n * otherwise will be `null`.\n * @deprecated Moved to `expo-device` as [`Device.modelName`](./device/#devicemodelname).\n */\n model: string | null;\n /**\n * The user interface idiom of the current device, such as whether the app is running on an iPhone, iPad, Mac or Apple TV.\n * @deprecated Use `expo-device`'s [`Device.getDeviceTypeAsync()`](./device/#devicegetdevicetypeasync).\n */\n userInterfaceIdiom: UserInterfaceIdiom;\n /**\n * The version of iOS running on this device.\n * @example\n * `10.3`\n * @deprecated Use `expo-device`'s [`Device.osVersion`](./device/#deviceosversion).\n */\n systemVersion: string;\n} & Record<string, any>;\n\n// @needsAudit\n/**\n * @platform android\n */\nexport type AndroidManifest = {\n /**\n * The version code set by `android.versionCode` in app.json.\n * The value is set to `null` in case you run your app in Expo Go.\n * @deprecated Use `expo-application`'s [`Application.nativeBuildVersion`](./application/#applicationnativebuildversion).\n */\n versionCode: number;\n} & Record<string, any>;\n\n/**\n * @platform web\n */\nexport type WebManifest = Record<string, any>;\n\n// type re-exports to prevent breaking change\n\nexport type ManifestAsset = ManifestAssetForReExport;\nexport type Manifest = ExpoUpdatesManifest;\nexport type ManifestExtra = ManifestExtraForReExport;\nexport type EASConfig = ManifestsEASConfig;\nexport type ClientScopingConfig = ClientScopingConfigForReExport;\nexport type ExpoGoConfig = ManifestsExpoGoConfig;\nexport type ExpoGoPackagerOpts = ExpoGoPackagerOptsForReExport;\n\n// @needsAudit @docsMissing\nexport type PlatformManifest = {\n ios?: IOSManifest;\n android?: AndroidManifest;\n web?: WebManifest;\n detach?: {\n scheme?: string;\n [key: string]: any;\n };\n scheme?: string;\n hostUri?: string;\n developer?: string;\n} & Record<string, any>;\n\n// @needsAudit @docsMissing\nexport type NativeConstants = {\n /**\n * @hidden\n */\n name: 'ExponentConstants';\n /**\n * Returns `expo` when running in Expo Go, otherwise `null`.\n * @deprecated Use [`Constants.executionEnvironment`](#executionenvironment) instead.\n */\n appOwnership: AppOwnership | null;\n /**\n * Returns `true` when the app is running in debug mode (`__DEV__`). Otherwise, returns `false`.\n */\n debugMode: boolean;\n /**\n * A human-readable name for the device type.\n */\n deviceName?: string;\n /**\n * The [device year class](https://github.com/facebook/device-year-class) of this device.\n * @deprecated Moved to `expo-device` as [`Device.deviceYearClass`](./device/#deviceyearclass).\n */\n deviceYearClass: number | null;\n /**\n * Returns the current execution environment.\n */\n executionEnvironment: ExecutionEnvironment;\n experienceUrl: string;\n /**\n * Nullable only on the web.\n */\n expoRuntimeVersion: string | null;\n /**\n * The version string of the Expo Go app currently running.\n * Returns `null` in existing React Native projects and on web.\n */\n expoVersion: string | null;\n isDetached?: boolean;\n intentUri?: string;\n /**\n * Returns `true` if the app is running in headless mode. Otherwise, returns `false`.\n */\n isHeadless: boolean;\n linkingUri: string;\n\n /**\n * @hidden\n * Manifest embedded in the build. Returns `null` when `manifest2` is non-null.\n * @deprecated Use `Constants.expoConfig` instead, which behaves more consistently across EAS Build\n * and EAS Update.\n */\n manifest: EmbeddedManifest | null;\n /**\n * Manifest for Expo apps using modern Expo Updates from a remote source, such as apps that\n * use EAS Update. `Constants.expoConfig` should be used for accessing the Expo config object.\n */\n manifest2: ExpoUpdatesManifest | null;\n /**\n * The standard Expo config object defined in **app.json** and **app.config.js** files. For both\n * classic and modern manifests, whether they are embedded or remote.\n */\n expoConfig:\n | (ExpoConfig & {\n /**\n * Only present during development using @expo/cli.\n */\n hostUri?: string;\n })\n | null;\n /**\n * The standard Expo Go config object populated when running in Expo Go.\n */\n expoGoConfig: ManifestsExpoGoConfig | null;\n /**\n * The standard EAS config object populated when using EAS.\n */\n easConfig: ManifestsEASConfig | null;\n /**\n * A string that is unique to the current session of your app. It is different across apps and\n * across multiple launches of the same app.\n */\n sessionId: string;\n /**\n * The default status bar height for the device. Does not factor in changes when location tracking\n * is in use or a phone call is active.\n */\n statusBarHeight: number;\n /**\n * A list of the system font names available on the current device.\n */\n systemFonts: string[];\n systemVersion?: number;\n /**\n * @hidden\n */\n supportedExpoSdks?: string[];\n /**\n * Returns the specific platform manifest object.\n *\n * > **Note**: This is distinct from the `manifest` and `manifest2`.\n */\n platform?: PlatformManifest;\n /**\n * Gets the user agent string which would be included in requests sent by a web view running on\n * this device. This is probably not the same user agent you might be providing in your JS `fetch`\n * requests.\n */\n getWebViewUserAgentAsync: () => Promise<string | null>;\n} & Record<string, any>;\n\n/**\n * @hidden\n */\nexport type Constants = NativeConstants & {\n /**\n * > **Warning**: Do not use this property. Use `manifest` by default.\n *\n * In certain cases accessing manifest via this property\n * suppresses important warning about missing manifest.\n */\n __unsafeNoWarnManifest?: EmbeddedManifest;\n /**\n * > **Warning**: Do not use this property. Use `manifest2` by default.\n *\n * In certain cases accessing manifest via this property\n * suppresses important warning about missing manifest.\n */\n __unsafeNoWarnManifest2?: ExpoUpdatesManifest;\n};\n","import { requireOptionalNativeModule } from 'expo-modules-core';\n\nexport default requireOptionalNativeModule('ExponentConstants');\n","// TODO(@kitten): Add missing optional peers\n\nimport type { ExpoConfig } from 'expo/config';\n// @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\nimport type {\n EmbeddedManifest,\n EASConfig,\n ExpoGoConfig,\n ExpoUpdatesManifest,\n // @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\n} from 'expo-manifests';\nimport { CodedError, requireOptionalNativeModule } from 'expo-modules-core';\n// @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\nimport type { Manifest as UpdatesManifest, ExpoUpdatesModule } from 'expo-updates';\nimport { Platform, NativeModules } from 'react-native';\n\nimport { type Constants, ExecutionEnvironment } from './Constants.types';\nimport ExponentConstants from './ExponentConstants';\ntype DevLauncherManifest = ExpoUpdatesManifest;\n\nexport {\n type AndroidManifest,\n AppOwnership,\n type Constants,\n ExecutionEnvironment,\n type IOSManifest,\n type NativeConstants,\n type PlatformManifest,\n UserInterfaceIdiom,\n type WebManifest,\n} from './Constants.types';\n\nif (!ExponentConstants) {\n console.warn(\n \"No native ExponentConstants module found, are you sure the expo-constants's module is linked properly?\"\n );\n}\n\nconst ExpoUpdates = requireOptionalNativeModule<ExpoUpdatesModule>('ExpoUpdates');\n\nlet rawUpdatesManifest: UpdatesManifest | null = null;\n// If expo-updates defines a non-empty manifest, prefer that one\nif (ExpoUpdates) {\n let updatesManifest: object | undefined;\n if (ExpoUpdates.manifest) {\n updatesManifest = ExpoUpdates.manifest;\n } else if (ExpoUpdates.manifestString) {\n updatesManifest = JSON.parse(ExpoUpdates.manifestString);\n }\n if (updatesManifest && Object.keys(updatesManifest).length > 0) {\n rawUpdatesManifest = updatesManifest as any;\n }\n}\n\n// If dev-launcher defines a non-empty manifest, prefer that one\nlet rawDevLauncherManifest: DevLauncherManifest | null = null;\nif (NativeModules.EXDevLauncher) {\n let devLauncherManifest;\n if (NativeModules.EXDevLauncher.manifestString) {\n devLauncherManifest = JSON.parse(NativeModules.EXDevLauncher.manifestString);\n }\n\n if (devLauncherManifest && Object.keys(devLauncherManifest).length > 0) {\n rawDevLauncherManifest = devLauncherManifest as any;\n }\n}\n\n// Fall back to ExponentConstants.manifest if we don't have one from Updates\nlet rawAppConfig: ExpoConfig | null = null;\nif (ExponentConstants && ExponentConstants.manifest) {\n const appConfig: object | string = ExponentConstants.manifest;\n\n // On Android we pass the manifest in JSON form so this step is necessary\n if (typeof appConfig === 'string') {\n rawAppConfig = JSON.parse(appConfig);\n } else {\n rawAppConfig = appConfig as any;\n }\n}\n\ntype RawManifest = UpdatesManifest | DevLauncherManifest | ExpoConfig;\nlet rawManifest: RawManifest | null = rawUpdatesManifest ?? rawDevLauncherManifest ?? rawAppConfig;\n\nconst { name, appOwnership, ...nativeConstants } = (ExponentConstants || {}) as any;\n\nconst constants: Constants = {\n ...nativeConstants,\n // Ensure this is null in bare workflow\n appOwnership: appOwnership ?? null,\n};\n\nObject.defineProperties(constants, {\n /**\n * Use `manifest` property by default.\n * This property is only used for internal purposes.\n * It behaves similarly to the original one, but suppresses warning upon no manifest available.\n * `expo-asset` uses it to prevent users from seeing mentioned warning.\n */\n __unsafeNoWarnManifest: {\n get(): EmbeddedManifest | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: false,\n },\n __unsafeNoWarnManifest2: {\n get(): ExpoUpdatesManifest | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: false,\n },\n manifest: {\n get(): EmbeddedManifest | null {\n const maybeManifest = getManifest();\n if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: true,\n },\n manifest2: {\n get(): ExpoUpdatesManifest | null {\n const maybeManifest = getManifest();\n if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: true,\n },\n expoConfig: {\n get():\n | (ExpoConfig & {\n /**\n * Only present during development using @expo/cli.\n */\n hostUri?: string;\n })\n | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n // if running an embedded update, maybeManifest is a EmbeddedManifest which doesn't have\n // the expo config. Instead, the embedded expo-constants app.config should be used.\n if (ExpoUpdates && ExpoUpdates.isEmbeddedLaunch) {\n return rawAppConfig;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.expoClient ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n expoGoConfig: {\n get(): ExpoGoConfig | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.expoGo ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n easConfig: {\n get(): EASConfig | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.eas ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n __rawManifest_TEST: {\n get(): RawManifest | null {\n return rawManifest;\n },\n set(value: RawManifest | null) {\n rawManifest = value;\n },\n enumerable: false,\n },\n});\n\nfunction isEmbeddedManifest(manifest: RawManifest): manifest is EmbeddedManifest {\n return !isExpoUpdatesManifest(manifest);\n}\n\nfunction isExpoUpdatesManifest(manifest: RawManifest): manifest is ExpoUpdatesManifest {\n return 'metadata' in manifest;\n}\n\nfunction getManifest(suppressWarning = false): RawManifest | null {\n if (!rawManifest) {\n const invalidManifestType = rawManifest === null ? 'null' : 'undefined';\n if (\n nativeConstants.executionEnvironment === ExecutionEnvironment.Bare &&\n Platform.OS !== 'web'\n ) {\n if (!suppressWarning) {\n console.warn(\n `Constants.manifest is ${invalidManifestType} because the embedded app.config could not be read. Ensure that you have installed the expo-constants build scripts if you need to read from Constants.manifest.`\n );\n }\n } else if (\n nativeConstants.executionEnvironment === ExecutionEnvironment.StoreClient ||\n nativeConstants.executionEnvironment === ExecutionEnvironment.Standalone\n ) {\n // If we somehow get here, this is a truly exceptional state to be in.\n // Constants.manifest should *always* be defined in those contexts.\n throw new CodedError(\n 'ERR_CONSTANTS_MANIFEST_UNAVAILABLE',\n `Constants.manifest is ${invalidManifestType}, must be an object.`\n );\n }\n }\n return rawManifest;\n}\n\nexport default constants as Constants;\n","/**\n * transport.ts — kit → Wire server requests for the review module, all fire-and-forget\n * (analytics/reviews must never break the app). Mirrors analytics/reportClientEvent: a\n * thin fetch wrapper, Bearer tenant key, swallow every error.\n *\n * • submitReview → POST {serverUrl}/v1/reviews (the review row)\n * • fetchReviewDecision → GET {serverUrl}/v1/reviews/decision (best-effort, the AI seam)\n * • reportAppEvent → POST {serverUrl}/v1/events (generic app.* namespace)\n *\n * `reportAppEvent` is the strategic extension: it lets a host report arbitrary in-app\n * events through the SAME transport (stored server-side as event_type='app_event',\n * question_key=<name>), which is what the backend review-firing rules evaluate on — and\n * it seeds the broader app-analytics stream. Keep payloads minimal + non-PII.\n */\nimport type { ReviewDecisionResponse, ReviewSubmission, ReviewTarget } from \"./types\";\n\n/**\n * POST a review (the 1-4 feedback path). Fire-and-forget: a missing target, a build error,\n * a missing `fetch`, or a network failure is swallowed and the call returns immediately.\n */\nexport const submitReview = (\n target: ReviewTarget | undefined,\n review: ReviewSubmission,\n): void => {\n if (!target?.serverUrl) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/reviews`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(review),\n }).catch(() => {\n /* best-effort, swallow */\n });\n } catch {\n /* URL/JSON/missing-fetch — swallow */\n }\n};\n\n/**\n * Options for the best-effort review decision fetch.\n *\n * ── WHAT THE DEPLOYED SERVER ACTUALLY READS (verified 2026-07-17) ────────────────────────\n *\n * `GET /v1/reviews/decision` declares exactly two query params — `session_id` and\n * `device_key` — plus the `Authorization` header. That is the whole wire. Verified against\n * the deployed OpenAPI schema, not against intent.\n *\n * This type is CLOSED on purpose. Hosts that hand-rolled this fetch invented `user_id` and\n * `session_count` query params believing \"the server ignores what it doesn't read, so passing\n * it is always safe\". Both are no-ops: the route declares neither. `session_count` is real, but\n * only on the questionnaire POST body — which is precisely how it copy-pasted its way into a\n * reviews call site and sat there doing nothing. They cost a wire lie — a call site that reads as though\n * identity and a session counter reach the firing brain when neither does. So they are not\n * offered here. Pass identity as `deviceKey`; the session count the server reasons about is the\n * one IT derives from the event stream keyed by `deviceKey`, not one the client asserts.\n *\n * The client-side session floor is a LOCAL rule, not a wire param: use `ReviewConfig.minSessions`\n * (evaluated by `useReviewGate` against the kit's own `wire_review_<id>_sessions` counter).\n */\nexport interface FetchReviewDecisionOptions {\n /**\n * The onboarding session id, when there IS one. OPTIONAL on purpose: the review gate lives on\n * the home feed, where a user legitimately has no onboarding session. `deviceKey` is the real\n * identity for this call. (The server relaxed `session_id` to optional on 2026-07-16 and the\n * relaxation IS deployed — the route no longer 422s without it. Permissive wire: do NOT make\n * this required here.)\n */\n sessionId?: string;\n /**\n * A stable, non-PII device id — THE identity for this call. The decision endpoint reads it for\n * cooldown + min-sessions, and it is the key the server groups a device's events under. A host\n * whose own identity is a user id passes that id here rather than reaching for a `user_id`\n * param the route does not declare.\n */\n deviceKey?: string;\n}\n\n/**\n * Best-effort fetch of the SERVER's review firing decision. The mirror of\n * `fetchQuestionnaireDecision`, and the primitive whose absence caused a live incident.\n *\n * ── WHY THIS LIVES IN THE KIT (Malik, 2026-07-16) ────────────────────────────────────────\n *\n * The questionnaire module has always had its decision fetch; reviews never did. So a host\n * hand-rolled one, and got it subtly wrong: its helper collapsed an explicit `{fire:false}`\n * into `undefined`. `decideReview` is `(local, decision) => decision ?? local`, so `undefined`\n * means \"the server has no opinion, use the local rules\" — and the local timer fired. The\n * server could therefore only ever turn review prompts ON, never OFF. A real user was asked to\n * rate the app ~3 minutes into their FIRST session, having seen nothing yet, and left 1 star.\n *\n * The bug was not that the host was careless. It was that the kit made every host invent this.\n * So the primitive moves here and hosts keep a thin call site.\n *\n * ── THE CONTRACT THAT MATTERS ────────────────────────────────────────────────────────────\n *\n * • 2xx → the FULL `{fire, reason, arm}`, INCLUDING `fire:false`. Never collapse a false\n * into null. That collapse IS the bug: a false must reach `decideReview` intact so\n * it can override the local rules and keep the gate shut.\n * • else → null, and ONLY then. Null means \"the server genuinely has no opinion\", which is\n * the one case where falling back to local rules is correct.\n *\n * Never throws: unreachable, non-2xx, bad JSON, or a missing `fetch` all resolve to null. The\n * kit does not call this internally; a host awaits it and passes the result straight to\n * `useReviewGate({ decision })`.\n *\n * ── DON'T RACE THIS AGAINST A LOCAL TIMER ────────────────────────────────────────────────\n *\n * The return type is `ReviewDecisionResponse`, which carries `arm` alongside `{fire, reason}`.\n * Hand the WHOLE object to the gate and echo `arm` into the submission's `meta.firing_arm`;\n * narrowing it to `{fire, reason}` on the way through silently kills per-arm attribution\n * across a reweighting of the experiment.\n *\n * A host that starts its own dwell timer in parallel with this fetch has built a race a slow\n * server loses: the timer fires, the local rules show the prompt, and the `{fire:false}` still\n * in flight arrives too late to stop it. Do not hand-roll that. `useReviewGate` already owns\n * the wait — set `ReviewConfig.timeoutFallbackMs` and the local rules stay parked until either\n * the decision lands or the window expires, whichever comes first.\n *\n * const decision = await fetchReviewDecision(target, { deviceKey });\n * const gate = useReviewGate({\n * config: { id: \"home\", minSessions: 2, timeoutFallbackMs: 3000 },\n * decision: decision ?? undefined, // pass it whole — keep `arm`\n * storage,\n * });\n */\nexport const fetchReviewDecision = async (\n target: ReviewTarget | undefined,\n options: FetchReviewDecisionOptions = {},\n): Promise<ReviewDecisionResponse | null> => {\n if (!target?.serverUrl) return null;\n try {\n const base = target.serverUrl.replace(/\\/$/, \"\");\n const params = new URLSearchParams();\n if (options.sessionId) params.set(\"session_id\", options.sessionId);\n if (options.deviceKey) params.set(\"device_key\", options.deviceKey);\n const qs = params.toString();\n const url = `${base}/v1/reviews/decision${qs ? `?${qs}` : \"\"}`;\n const headers: Record<string, string> = {};\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n const res = await fetch(url, { headers });\n if (!res || !res.ok) return null;\n const json = (await res.json()) as ReviewDecisionResponse | null;\n // A body without a boolean `fire` is not a decision. Guard it explicitly rather than\n // letting `{}` through as a truthy object that `decideReview` would treat as a verdict\n // (`{}.fire === undefined` is falsy, so it would silently read as \"never fire\").\n if (!json || typeof json.fire !== \"boolean\") return null;\n return json;\n } catch {\n /* unreachable / non-2xx / bad JSON / missing-fetch → the server has no opinion */\n return null;\n }\n};\n\n/** Options for a reported app event. `deviceKey` groups a device's sessions server-side. */\nexport interface ReportAppEventOptions {\n /** The onboarding/session id to correlate with, when known. */\n sessionId?: string;\n /** A stable, non-PII device id — the review-decision endpoint reads it for min-sessions. */\n deviceKey?: string;\n /** Small non-PII extras. */\n meta?: Record<string, unknown>;\n}\n\n/**\n * Report a generic in-app event through the existing events transport. Stored server-side\n * as `event_type='app_event'`, `question_key=<name>`. Fire-and-forget. Keep `name` a short\n * stable identifier and `meta` small + non-PII.\n *\n * reportAppEvent(target, \"content_share\", { sessionId, deviceKey });\n */\nexport const reportAppEvent = (\n target: ReviewTarget | undefined,\n name: string,\n options: ReportAppEventOptions = {},\n): void => {\n if (!target?.serverUrl || !name) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n const event: Record<string, unknown> = {\n event_type: \"app_event\",\n question_key: name,\n };\n if (options.sessionId) event.session_id = options.sessionId;\n // device_key rides in the non-PII user_context bucket the server sanitizes; the\n // review-decision endpoint reads it to group a device's sessions.\n if (options.deviceKey) event.user_context = { device_key: options.deviceKey };\n if (options.meta && Object.keys(options.meta).length > 0) {\n event.meta = JSON.stringify(options.meta);\n }\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events: [event] }),\n }).catch(() => {\n /* best-effort, swallow */\n });\n } catch {\n /* swallow */\n }\n};\n","/**\n * screenTracking — an OPT-IN, dependency-free automatic screen-view helper.\n *\n * Given the host app's navigation STATE (or a nav ref, via the useScreenTracking hook), this\n * emits exactly ONE `screen` app-event per REAL screen change through the kit's existing\n * `reportAppEvent` transport (`POST {serverUrl}/v1/events`, `event_type='app_event'`,\n * `question_key='screen'`, `meta={ screen }`). Param-only changes and re-renders are de-duped\n * away because we resolve and compare the route NAME only — never the params.\n *\n * Dependency-free core: this file imports NO navigation library. React-Navigation / expo-router\n * are host concerns; the host supplies plain state objects and refs, typed structurally here\n * (`NavigationStateLike`). It is also React-free — the optional React glue lives in\n * `useScreenTracking.ts`. `reportAppEvent` is imported from the pure `../reviews/transport`\n * module (NOT the `../reviews` barrel, which would drag the review UI into an analytics-only\n * bundle and defeat tree-shaking).\n *\n * Privacy: only the route NAME ever leaves the device. Route params, query strings, and any\n * user data are never read into the event. Fire-and-forget — this never throws into the UI.\n */\nimport { reportAppEvent } from \"../reviews/transport\";\n\n/** A single route inside a React-Navigation-shaped state (structural — no `@react-navigation`). */\nexport interface NavigationRouteLike {\n name: string;\n /** A nested navigator's own state, when this route hosts one. */\n state?: NavigationStateLike;\n /** Route params are intentionally left `unknown` — this helper never reads them. */\n params?: unknown;\n}\n\n/** A React-Navigation-shaped navigator state (structural type; no library import). */\nexport interface NavigationStateLike {\n /** Index of the active route within `routes`. */\n index?: number;\n routes?: NavigationRouteLike[];\n}\n\n/** Options for {@link createScreenTracker}. */\nexport interface ScreenTrackerOptions {\n /**\n * Where to POST. `{ serverUrl, apiKey }` — same shape the kit's review/analytics config\n * exposes. When omitted, the tracker still de-dups and fires `onScreen`, but sends nothing.\n */\n target?: { serverUrl: string; apiKey: string };\n /** The onboarding/session id to correlate screen views with, when known. */\n sessionId?: string;\n /** A stable, non-PII device id — groups a device's sessions server-side. */\n deviceKey?: string;\n /** Called on every REAL screen change (after de-dup), before the network emit. */\n onScreen?: (screen: string) => void;\n /**\n * Per-screen filter. Return `false` to skip the NETWORK emit for a screen (last-screen memory\n * is still advanced + `onScreen` still fires) — e.g. to keep a sensitive route out of analytics.\n */\n shouldTrack?: (screen: string) => boolean;\n}\n\n/** The screen tracker returned by {@link createScreenTracker}. */\nexport interface ScreenTracker {\n /** Report the active screen. Ignores `undefined`/empty and de-dups repeats of the last screen. */\n track: (screen: string | undefined) => void;\n /** Clear the last-screen memory (e.g. on logout) so the next `track` always emits. */\n reset: () => void;\n}\n\n/**\n * Walk a React-Navigation-shaped state to the DEEPEST active route and return its NAME (never\n * its params). Recurses `routes[index]` while a nested `.state` exists. Returns `undefined` for\n * a missing/empty/malformed state — the caller treats that as \"nothing to report\".\n */\nexport const getActiveRouteName = (\n state: NavigationStateLike | undefined,\n): string | undefined => {\n let current: NavigationStateLike | undefined = state;\n let name: string | undefined;\n // Bounded by the finite nesting depth of a real navigator tree.\n while (current && Array.isArray(current.routes) && current.routes.length > 0) {\n const index = typeof current.index === \"number\" ? current.index : 0;\n const route = current.routes[index];\n if (!route) break;\n name = route.name;\n current = route.state;\n }\n return name;\n};\n\n/**\n * Build a stateful screen tracker. `track` de-dups against the last reported screen so only a\n * REAL change emits; `reset` clears that memory. Fire-and-forget throughout — a missing `target`\n * skips the network but keeps the de-dup + `onScreen` behaviour intact.\n */\nexport const createScreenTracker = (options: ScreenTrackerOptions = {}): ScreenTracker => {\n let lastScreen: string | undefined;\n return {\n track: (screen: string | undefined): void => {\n if (!screen || screen === lastScreen) return;\n lastScreen = screen;\n options.onScreen?.(screen);\n if (options.shouldTrack && !options.shouldTrack(screen)) return;\n reportAppEvent(options.target, \"screen\", {\n sessionId: options.sessionId,\n deviceKey: options.deviceKey,\n meta: { screen },\n });\n },\n reset: (): void => {\n lastScreen = undefined;\n },\n };\n};\n\n/**\n * Adapt a tracker into a React-Navigation `onStateChange` handler — the one-place wiring:\n *\n * <NavigationContainer onStateChange={screenTrackingHandler(tracker)}>\n *\n * It resolves the deepest active route name and hands it to `tracker.track` (which de-dups).\n */\nexport const screenTrackingHandler =\n (tracker: ScreenTracker) =>\n (state: NavigationStateLike | undefined): void =>\n tracker.track(getActiveRouteName(state));\n","/**\n * useScreenTracking — a THIN optional React hook over the pure screen-tracking core.\n *\n * It builds one tracker for the component's lifetime and subscribes to the host's navigation\n * ref: it reports the current route on mount and on every `state` event, and unsubscribes on\n * unmount. React is a REQUIRED peer of the kit, so importing it here is allowed; the hook adds\n * NO navigation-library dependency — the ref is typed structurally (`NavigationRefLike`).\n *\n * const navigationRef = useNavigationContainerRef(); // host's @react-navigation ref\n * useScreenTracking(navigationRef, { target, sessionId });\n * // ...<NavigationContainer ref={navigationRef}>\n */\nimport { useEffect, useRef } from \"react\";\n\nimport { createScreenTracker, type ScreenTracker, type ScreenTrackerOptions } from \"./screenTracking\";\n\n/**\n * The structural slice of a React-Navigation container ref this hook needs — no\n * `@react-navigation` import. `getCurrentRoute` yields the active route; `addListener(\"state\", …)`\n * fires on every navigation state change and returns its own unsubscribe.\n */\nexport interface NavigationRefLike {\n getCurrentRoute?: () => { name?: string } | undefined;\n addListener?: (type: \"state\", callback: () => void) => () => void;\n}\n\n/**\n * Subscribe screen tracking to a host navigation ref. Safe to call with a not-yet-ready ref\n * (the effect no-ops until `addListener` exists). Returns nothing — it wires side effects only.\n */\nexport const useScreenTracking = (\n navigationRef: NavigationRefLike | undefined,\n options: ScreenTrackerOptions = {},\n): void => {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // One tracker per mount; kept in a ref so re-renders never rebuild the de-dup memory.\n const trackerRef = useRef<ScreenTracker | undefined>(undefined);\n if (!trackerRef.current) {\n const dynamicOptions: ScreenTrackerOptions = {\n get target() {\n return optionsRef.current.target;\n },\n get sessionId() {\n return optionsRef.current.sessionId;\n },\n get deviceKey() {\n return optionsRef.current.deviceKey;\n },\n get onScreen() {\n return optionsRef.current.onScreen;\n },\n get shouldTrack() {\n return optionsRef.current.shouldTrack;\n },\n };\n trackerRef.current = createScreenTracker(dynamicOptions);\n }\n\n useEffect(() => {\n const tracker = trackerRef.current;\n if (!tracker || !navigationRef?.addListener) return;\n const report = (): void => tracker.track(navigationRef.getCurrentRoute?.()?.name);\n report(); // initial screen on mount\n const unsubscribe = navigationRef.addListener(\"state\", report);\n return unsubscribe;\n // Re-subscribe only when the ref identity changes; option changes are read live off the closure.\n }, [navigationRef]);\n};\n","/**\n * reportClientEvent — forward DEVICE-ONLY onboarding events to the Wire AI analytics\n * backend (`POST {serverUrl}/v1/events`), completing the funnel for events the server\n * can't observe on its own.\n *\n * The backend already records the server-observable funnel during the A2A flow\n * (`session_started`, `screen_shown`, `answer_submitted`, `completed`, `llm_fallback`,\n * and even `screen_skipped` — it derives that from the kit's skip sentinel). The one\n * event no server request can capture is `dropped`: the user closing the app / unmounting\n * the flow without finishing. That's what this reporter is for.\n *\n * Contract (server: routers/onboarding.py → analytics/events.py):\n * POST {serverUrl}/v1/events\n * Authorization: Bearer {apiKey}\n * { \"events\": [ { event_type, session_id, screen_index?, component?, question_key?,\n * latency_ms?, meta?, device?, user_context? } ] }\n * The server fills `app_id` + `environment` from the resolving key (never send app_id),\n * and silently skips malformed events — one bad payload never fails the batch.\n *\n * ⚠️ Correlation: `session_id` MUST equal the A2A `contextId` the server uses to key the\n * server-side events, or the funnel report (which groups by `session_id`) treats this as a\n * phantom session. See `makeSessionId` + WireOnboarding for how the kit seeds it.\n *\n * Fire-and-forget: this never throws into the UI and never awaits — analytics must never\n * be able to break onboarding.\n */\nimport type { DeviceContext } from \"../device/deviceContext\";\n\n/** Event types a CLIENT may report. The rest of the funnel is server-side; sending those\n * here would double-count. `screen_skipped` is included for completeness, but the kit does\n * NOT emit it — the backend already derives it from the skip sentinel (see OnboardingFlow).\n * `client_fallback` is emitted by the kit when the AI flow degrades to the static fallback,\n * so the dashboard's fallback-rate counts the whole-flow case (distinct from the server's\n * per-turn `llm_fallback`). The server back-fills a `session_started` for it if unseen.\n * This is the SINGLE fallback signal — hosts must NOT also report their own.\n * `identify` binds the host's opaque `user_id` to this `session_id` (late binding — the user\n * registered during/after onboarding). It carries no funnel weight; the server maps the\n * session to the user and back-fills a `session_started` if it never saw the session.\n * `app_event` is the host's own in-app event (the `createAnalytics` façade's `track`/`screen`\n * route through the offline queue as first-class `ClientEvent`s). The server already ingests\n * it — `reportAppEvent` (reviews/transport) has fired `event_type='app_event'` all along; this\n * widening just lets the same shape flow through the durable queue instead of a blind POST. */\nexport type ClientEventType =\n | \"screen_skipped\"\n | \"dropped\"\n | \"client_fallback\"\n | \"identify\"\n | \"app_event\";\n\n/** One client-reported event. Mirrors the server's `OnboardingEvent` (client-settable fields). */\nexport type ClientEvent = {\n event_type: ClientEventType;\n /** Must match the server-side A2A contextId for this onboarding (see makeSessionId). */\n session_id: string;\n /** 0-based index of the screen the event refers to (matches server `screen_shown`). */\n screen_index?: number;\n component?: string;\n question_key?: string;\n latency_ms?: number;\n /** JSON-stringified extras; the server stores it verbatim. */\n meta?: string;\n /**\n * Privacy-label-neutral device snapshot (platform / form factor / locale / host appVersion).\n * Sent as an object; the server sanitizes + persists it and derives a coarse country. Old\n * servers ignore this unknown field — fully backward compatible. See device/deviceContext.ts.\n */\n device?: DeviceContext;\n /**\n * Host-injected, non-PII context (signup method, referral, plan, hashed user id). Old servers\n * ignore it. MUST NOT contain PII like raw emails — see the README `userContext` section.\n */\n user_context?: Record<string, string | number | boolean>;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id, NOT an email/name). Required on\n * `identify`, optional (rides along) on other events. Trimmed + capped at 128 chars host-side.\n * Lets the backend reconcile onboarding sessions to real users. Old servers ignore it.\n */\n user_id?: string;\n};\n\n/** Where to POST. Derived from `WireOnboardingConfig` (`serverUrl` + `apiKey`). */\nexport type ClientEventTarget = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n};\n\n/**\n * A unique-per-onboarding session id. Used both as the client event `session_id` AND as the\n * seed the kit forwards to the backend so the SERVER adopts it as the A2A `contextId` — making\n * client and server agree (see WireOnboarding + the SDK-correlation note in the kit docs).\n * No crypto dependency: timestamp + random is collision-safe for a single device's onboarding.\n */\nexport const makeSessionId = (): string =>\n `wire_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n\n/**\n * POST one or more client events, fire-and-forget. A missing/invalid target, a build error,\n * a missing `fetch`, or a network failure is swallowed — the call returns immediately and the\n * request (if any) runs in the background.\n */\nexport const reportClientEvents = (\n target: ClientEventTarget | undefined,\n events: ClientEvent[],\n): void => {\n if (!target?.serverUrl || events.length === 0) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events }),\n }).catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // URL construction, JSON serialization, or a missing fetch — swallow.\n }\n};\n\n/** Convenience single-event wrapper around {@link reportClientEvents}. */\nexport const reportClientEvent = (\n target: ClientEventTarget | undefined,\n event: ClientEvent,\n): void => reportClientEvents(target, [event]);\n","/**\n * Canonical analytics names for the onboarding funnel. The kit already emits a typed\n * `OnboardingEvent` (`started | turn | error | retry | fallback`) — but one app logged them as\n * `onboarding_*` and another as `AI_ONBOARDING_*`, so the same funnel reads differently per app.\n * This maps the kit event to ONE canonical `wire_onboarding_*` name + params, and the app logs\n * it through whatever transport it already has (Firebase, Amplitude, console). The app still\n * owns the logger; only the NAMES are standardized.\n *\n * <WireOnboarding\n * onEvent={(e) => { const a = toAnalyticsEvent(e); logEvent(a.name, a.params); }}\n * onComplete={(r) => { logEvent(WIRE_ONBOARDING_EVENTS.completed, { answers: Object.keys(r.answers).length }); persist(r); }}\n * />\n *\n * `completed` has no kit `OnboardingEvent` (the kit signals completion via `onComplete`, not\n * `onEvent`) — the app logs it explicitly on `onComplete` using the constant below, so the\n * funnel name stays canonical.\n */\nimport type { OnboardingEvent } from \"../types\";\n\nexport const WIRE_ONBOARDING_EVENTS = {\n started: \"wire_onboarding_started\",\n /** A persisted session was restored after an app kill (fires instead of `started`). */\n resumed: \"wire_onboarding_resumed\",\n turn: \"wire_onboarding_turn\",\n error: \"wire_onboarding_error\",\n retry: \"wire_onboarding_retry\",\n fallback: \"wire_onboarding_fallback\",\n /** Logged by the host on `onComplete` (no matching kit `OnboardingEvent`). */\n completed: \"wire_onboarding_completed\",\n} as const;\n\nexport type WireOnboardingEventName =\n (typeof WIRE_ONBOARDING_EVENTS)[keyof typeof WIRE_ONBOARDING_EVENTS];\n\nexport type AnalyticsEvent = {\n name: WireOnboardingEventName;\n params?: Record<string, unknown>;\n};\n\n/**\n * Map a kit `OnboardingEvent` to its canonical `{ name, params }`. Exhaustive over the union\n * (the `never` default makes a new event type a compile error here — intentional).\n */\nexport const toAnalyticsEvent = (event: OnboardingEvent): AnalyticsEvent => {\n switch (event.type) {\n case \"started\":\n return { name: WIRE_ONBOARDING_EVENTS.started };\n case \"resumed\":\n return { name: WIRE_ONBOARDING_EVENTS.resumed };\n case \"turn\":\n return {\n name: WIRE_ONBOARDING_EVENTS.turn,\n params: { step: event.step, component: event.component },\n };\n case \"error\":\n return { name: WIRE_ONBOARDING_EVENTS.error, params: { reason: event.reason } };\n case \"retry\":\n return {\n name: WIRE_ONBOARDING_EVENTS.retry,\n params: { reason: event.reason, attempt: event.attempt },\n };\n case \"fallback\":\n return { name: WIRE_ONBOARDING_EVENTS.fallback, params: { reason: event.reason } };\n default: {\n const _exhaustive: never = event;\n return _exhaustive;\n }\n }\n};\n","/**\n * appVersion — best-effort, DEPENDENCY-FREE auto-detection of the host app's version string.\n *\n * WHY this exists: analytics segments the funnel `by_app_version`, but that breakdown is only\n * populated when a `device.appVersion` rides the event. `config.appVersion` (see types.ts) has\n * always been the way to supply it — but it is easy for a host to forget, and then the release\n * breakdown is silently empty. This module fills that gap: when the host does NOT pass a version,\n * the kit makes a best-effort read of the app version the host already ships in its Expo config,\n * so the breakdown works out of the box. An explicit `config.appVersion` always WINS over this.\n *\n * WHY it adds NO dependency (the kit's hard rule): `expo-constants` / `expo-application` are read\n * through a GUARDED require with a STRING-LITERAL specifier, inside a try/catch. Both halves are\n * required: the literal is what lets Metro COLLECT the dep, and the try/catch is what marks it\n * OPTIONAL, so an absent module becomes a `null` dependencyMap entry whose require throws \"Cannot\n * find module\" straight into the catch. (`withWireOnboarding` in metro/index.js adds a stub-to-\n * empty-module safety net for hosts that disable Metro's `allowOptionalDependencies`.) Nothing is\n * added to `package.json`; nothing is forced on the host.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) is not\n * \"lazier\" — it is broken: Metro collects dependencies statically, so a variable collects NOTHING,\n * the module never enters the bundle, and the aliased `require` is Metro's own numeric-id-keyed\n * `metroRequire`, which can never resolve a package-name string. That shape is why this function\n * returned `undefined` on every host despite `expo-constants` being installed, which silently\n * emptied the `by_app_version` breakdown this module exists to fill. See icons/expoIcons.ts for\n * the full autopsy, and reviews/storeReview.ts for the literal-specifier counter-example.\n *\n * PRIVACY: an app version string is not PII and identifies no user or device, so surfacing it\n * changes no App Privacy / Data Safety declaration (same guarantee as the rest of deviceContext).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n * Analytics must never be able to break onboarding.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real version string. */\nexport const coerceVersion = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * Every specifier below is a STRING LITERAL, because that is the only shape Metro's dependency\n * collector matches (callee literally `require`, argument literally a string). The `moduleName`\n * parameter exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name\n * resolves to undefined. See the header for why the old variable-specifier shape could not work.\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (typeof require !== \"function\") return undefined;\n try {\n switch (moduleName) {\n case \"expo-constants\":\n return require(\"expo-constants\");\n case \"expo-application\":\n return require(\"expo-application\");\n default:\n return undefined;\n }\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the host app version, preferring `expo-constants` (`expoConfig.version`, then\n * `nativeAppVersion`) and finally `expo-application` (`nativeApplicationVersion`). Returns the\n * first real string, or `undefined` when none of those are available. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native modules;\n * production defaults to the guarded runtime require above.\n */\nexport const detectAppVersion = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const constants = safeInterop(requireModule, \"expo-constants\");\n if (constants) {\n const expoConfig = constants.expoConfig;\n if (expoConfig && typeof expoConfig === \"object\") {\n const fromExpoConfig = coerceVersion((expoConfig as { version?: unknown }).version);\n if (fromExpoConfig) return fromExpoConfig;\n }\n const fromNative = coerceVersion(constants.nativeAppVersion);\n if (fromNative) return fromNative;\n }\n\n const application = safeInterop(requireModule, \"expo-application\");\n if (application) {\n const fromApplication = coerceVersion(application.nativeApplicationVersion);\n if (fromApplication) return fromApplication;\n }\n } catch {\n // Any unexpected read error → \"unknown\"; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceModel — best-effort, DEPENDENCY-FREE detection of the device MODEL on iOS.\n *\n * WHY this exists (the asymmetry it closes): `collectDeviceContext` already reports `device.model`\n * on Android straight from `Platform.constants.Model` (e.g. \"SM-G991B\"), but iOS `Platform.constants`\n * exposes NO model — only `osVersion` / `interfaceIdiom`. So the analytics `by_model` breakdown was\n * Android-only. This module fills the iOS gap with the SAME zero-dependency technique the kit already\n * uses for `appVersion` (see device/appVersion.ts): a GUARDED, STRING-LITERAL `require` of the common\n * Expo `expo-device` module, inside a try/catch — the literal is what lets Metro COLLECT the dep and\n * the try/catch is what marks it OPTIONAL, so an absent module degrades instead of failing the build.\n * (`withWireOnboarding` in metro/index.js adds a stub-to-empty-module safety net for hosts that\n * disable Metro's `allowOptionalDependencies`.) If the host has it, iOS gets a model out of the box;\n * if not, the read yields `undefined` and iOS `model` stays omitted — nothing is forced, and nothing\n * is added to `package.json`.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) collects\n * NOTHING under Metro's static dependency collector, so the module never enters the bundle and the\n * aliased `require` — really Metro's numeric-id-keyed `metroRequire` — can never resolve a package\n * name. See icons/expoIcons.ts for the full autopsy.\n *\n * WHY it is NOT PII: `expo-device`'s `modelName` (\"iPhone 14 Pro\") and `modelId` (\"iPhone15,2\") are a\n * device CLASS shared by millions of units — the same privacy category as the Android `Model` the kit\n * already sends. It is NOT a unique device id / IDFA / fingerprint, so surfacing it changes no App\n * Privacy / Data Safety declaration (identical guarantee to the rest of deviceContext). It deliberately\n * does NOT read `expo-device`'s `deviceName` (that is the user-set name, e.g. \"Malik's iPhone\", and IS\n * personal data).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real model string. */\nconst coerceModel = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * The specifier is a STRING LITERAL, because that is the only shape Metro's dependency collector\n * matches (callee literally `require`, argument literally a string). The `moduleName` parameter\n * exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name resolves to\n * undefined. (See the twin guard in ./appVersion.ts.)\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (moduleName !== \"expo-device\") return undefined;\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"expo-device\");\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are often consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the device model via `expo-device`, preferring the human-readable `modelName`\n * (\"iPhone 14 Pro\") and falling back to the identifier `modelId` (\"iPhone15,2\"). Returns the first\n * real string, or `undefined` when `expo-device` is absent. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native module;\n * production defaults to the guarded runtime require above.\n */\nexport const detectNativeModel = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const device = safeInterop(requireModule, \"expo-device\");\n if (device) {\n const modelName = coerceModel(device.modelName);\n if (modelName) return modelName;\n const modelId = coerceModel(device.modelId);\n if (modelId) return modelId;\n }\n } catch {\n // Any unexpected read error → undefined; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceContext — collect a small, privacy-label-neutral snapshot of the device so\n * onboarding analytics can segment the funnel (platform / form factor / locale) WITHOUT\n * adding a single dependency to the kit or changing a host app's App Privacy / Data Safety\n * declarations.\n *\n * HARD RULE (why this file adds no dependency):\n * The kit stays dependency-free. Everything here comes from `Platform`, `Dimensions`,\n * `I18nManager`, and the standard `Intl` global — plus a best-effort `appVersion` read via\n * `detectAppVersion()`, which itself adds NO dependency (it reaches for `expo-constants` /\n * `expo-application` through a guarded, variable-specifier require that a host without them\n * simply never resolves — see device/appVersion.ts). There are NO advertising IDs, NO\n * `getUniqueId`/IDFA/GAID/fingerprinting APIs, and nothing that would require a new\n * privacy-label entry. A host can adopt this without touching its store declarations.\n *\n * DEFENSIVE BY DESIGN: `collectDeviceContext()` never throws. Every read is guarded and\n * a missing/unavailable field is simply omitted (Hermes may ship without full `Intl`,\n * `Platform.constants` differs per OS and RN version, etc.). Analytics must never be able\n * to break onboarding.\n */\nimport { Dimensions, I18nManager, Platform } from \"react-native\";\n\nimport { detectAppVersion } from \"./appVersion\";\nimport { detectNativeModel } from \"./deviceModel\";\n\n/** Coarse device class. iOS uses the reported interface idiom; else a screen-size heuristic. */\nexport type DeviceFormFactor = \"phone\" | \"tablet\";\n\n/**\n * A privacy-label-neutral device snapshot. ALL fields except `platform` are optional and are\n * omitted when unavailable. Nothing here identifies a user or device uniquely.\n */\nexport type DeviceContext = {\n /** `Platform.OS` — \"ios\" | \"android\" | \"windows\" | \"macos\" | \"web\". Always present. */\n platform: typeof Platform.OS;\n /** OS version string (iOS `osVersion`/`Platform.Version`, Android `Release`). */\n osVersion?: string;\n /** Android device brand (e.g. \"samsung\"). Android only. */\n brand?: string;\n /**\n * Device model. On Android it is read directly from `Platform.constants.Model` (e.g. \"SM-G991B\").\n * iOS `Platform.constants` exposes NO model, so on iOS it is a BEST-EFFORT read of `expo-device`'s\n * `modelName` (\"iPhone 14 Pro\"), falling back to `modelId` (\"iPhone15,2\") — dependency-free via a\n * guarded require (see device/deviceModel.ts). ASYMMETRY: without `expo-device` installed, iOS\n * `model` is omitted (there is no dependency-free iOS model in the already-used RN surface, and the\n * kit will not add a native dep for it); Android needs no extra module. Not PII (a device class,\n * not a unique id), so it changes no privacy-label declaration.\n */\n model?: string;\n /** iOS interface idiom (\"phone\" | \"pad\" | …), when reported. iOS only. */\n interfaceIdiom?: string;\n /** Derived device class. */\n formFactor?: DeviceFormFactor;\n /** `Dimensions.get('screen')` width in dp. */\n screenWidth?: number;\n /** `Dimensions.get('screen')` height in dp. */\n screenHeight?: number;\n /** Screen pixel density (`scale`). */\n screenScale?: number;\n /** Right-to-left layout (`I18nManager.isRTL`). */\n isRTL?: boolean;\n /** Resolved locale (e.g. \"en-US\"), from `Intl` when available. */\n locale?: string;\n /** IANA time zone (e.g. \"Europe/Berlin\"), from `Intl` when available. */\n timeZone?: string;\n /**\n * Host app version (e.g. \"1.4.2\"). BEST-EFFORT auto-detected here via `detectAppVersion()`\n * (reads `expo-constants` / `expo-application` when present; adds no dependency — see\n * device/appVersion.ts). An explicit host-injected `config.appVersion` always WINS: the merge\n * sites (`WireOnboarding`, the session-analytics hooks, the context envelope) overwrite this\n * with the host value when one is supplied. Omitted when neither source yields a version.\n */\n appVersion?: string;\n};\n\n/** iOS idiom wins; otherwise the shortest side in dp (>= 600 → tablet) picks the class. */\nconst deriveFormFactor = (\n iosIdiom: string | undefined,\n width: number | undefined,\n height: number | undefined,\n): DeviceFormFactor | undefined => {\n if (iosIdiom === \"pad\") return \"tablet\";\n if (iosIdiom === \"phone\") return \"phone\";\n if (typeof width === \"number\" && typeof height === \"number\") {\n return Math.min(width, height) >= 600 ? \"tablet\" : \"phone\";\n }\n return undefined;\n};\n\n/**\n * Collect the device snapshot. Pure, synchronous, and never throws — call it once per\n * onboarding session. Missing fields are omitted rather than sent as null/undefined so the\n * payload (and the server's stored dict) stays compact.\n */\nexport const collectDeviceContext = (): DeviceContext => {\n const ctx: DeviceContext = { platform: Platform.OS };\n\n // OS version (fallback; per-OS constants below may refine it).\n try {\n const version = Platform.Version;\n if (version !== undefined && version !== null && String(version)) {\n ctx.osVersion = String(version);\n }\n } catch {\n // ignore\n }\n\n // `Platform.constants` shape differs by OS and RN version — read every field defensively.\n let constants: Record<string, unknown> = {};\n try {\n constants = (Platform.constants ?? {}) as Record<string, unknown>;\n } catch {\n constants = {};\n }\n\n let iosIdiom: string | undefined;\n try {\n if (Platform.OS === \"android\") {\n const brand = constants.Brand;\n const model = constants.Model;\n const release = constants.Release;\n if (typeof brand === \"string\" && brand) ctx.brand = brand;\n if (typeof model === \"string\" && model) ctx.model = model;\n if (release !== undefined && release !== null && String(release)) {\n ctx.osVersion = String(release);\n }\n } else if (Platform.OS === \"ios\") {\n const osVersion = constants.osVersion;\n const idiom = constants.interfaceIdiom;\n if (osVersion !== undefined && osVersion !== null && String(osVersion)) {\n ctx.osVersion = String(osVersion);\n }\n if (typeof idiom === \"string\" && idiom) {\n ctx.interfaceIdiom = idiom;\n iosIdiom = idiom;\n }\n // iOS has no model in `Platform.constants`; best-effort via `expo-device` (adds no dep,\n // omitted when the module is absent — see device/deviceModel.ts).\n const iosModel = detectNativeModel();\n if (iosModel) ctx.model = iosModel;\n }\n } catch {\n // ignore per-OS constant reads\n }\n\n // Screen dimensions + derived form factor.\n try {\n const screen = Dimensions.get(\"screen\");\n if (screen) {\n if (typeof screen.width === \"number\") ctx.screenWidth = screen.width;\n if (typeof screen.height === \"number\") ctx.screenHeight = screen.height;\n if (typeof screen.scale === \"number\") ctx.screenScale = screen.scale;\n const formFactor = deriveFormFactor(iosIdiom, screen.width, screen.height);\n if (formFactor) ctx.formFactor = formFactor;\n }\n } catch {\n // ignore\n }\n\n // Layout direction.\n try {\n ctx.isRTL = I18nManager.isRTL;\n } catch {\n // ignore\n }\n\n // Locale + time zone via the standard Intl global. Hermes may ship without full Intl,\n // so referencing it can throw ReferenceError — the try/catch covers that too.\n try {\n const resolved = Intl.DateTimeFormat().resolvedOptions();\n if (resolved.locale) ctx.locale = resolved.locale;\n if (resolved.timeZone) ctx.timeZone = resolved.timeZone;\n } catch {\n // Intl unavailable — omit locale/timeZone.\n }\n\n // Best-effort host app version (adds no dependency; omitted when unavailable). An explicit\n // `config.appVersion` overrides this downstream at the merge sites.\n const appVersion = detectAppVersion();\n if (appVersion) ctx.appVersion = appVersion;\n\n return ctx;\n};\n","/**\n * contextEnvelope — a small, PRIVACY-NEUTRAL context bundle stamped onto every outgoing\n * analytics event, giving the Wire dashboard the Sentry/Firebase-parity segmentation fields\n * (device model, OS + version, screen, locale, timezone, form factor) plus a few host-injected\n * scalars (session correlation id, app version + native build number, connectivity type).\n *\n * WHY a separate builder (not just `collectDeviceContext`): the envelope COMPOSES the existing\n * device snapshot with the handful of extras a host can cheaply supply but the kit can't collect\n * dependency-free (native build number, connectivity type). It never re-implements device\n * collection — it reuses `collectDeviceContext()` verbatim (see device/deviceContext.ts).\n *\n * HARD PRIVACY RULE (why this file, like deviceContext.ts, adds nothing new):\n * NEVER GPS / location, NEVER an advertising id (IDFA / GAID), NEVER a device fingerprint.\n * Location is derived SERVER-SIDE from IP-geo only — nothing here carries a coordinate or an\n * ad id, so a host adopting this changes no App Privacy / Data Safety declaration. There is a\n * test (contextEnvelope.test.ts) that asserts the ABSENCE of any such field.\n *\n * DEPENDENCY-FREE: the only import is the kit's own `collectDeviceContext`. `networkType` and\n * `appBuild` are HOST-INJECTED — there is no dependency-free RN core signal for either, so the\n * envelope simply omits them when the host does not pass them (no forced peer dependency).\n */\nimport { collectDeviceContext, type DeviceContext } from \"../device/deviceContext\";\n\n/**\n * The context stamped onto every event. `device` is always present (from\n * `collectDeviceContext`); every scalar is optional and OMITTED when the host does not supply it.\n */\nexport type ContextEnvelope = {\n /** The privacy-neutral device snapshot (reused from `collectDeviceContext`). */\n device: DeviceContext;\n /** Correlation id for this app-open / flow (caller-supplied). */\n sessionId?: string;\n /** App version, e.g. \"1.4.2\" (mirrors `device.appVersion`; host-injected, else auto-detected). */\n appVersion?: string;\n /** Host native build number, e.g. \"412\" (from `expo-constants` `nativeBuildVersion`). */\n appBuild?: string;\n /** Host connectivity signal, e.g. \"wifi\" | \"cellular\" (from `@react-native-community/netinfo`). */\n networkType?: string;\n};\n\n/** Host-injected inputs for {@link buildContextEnvelope}. All optional; each is omitted when absent. */\nexport type ContextEnvelopeInput = {\n sessionId?: string;\n appVersion?: string;\n appBuild?: string;\n networkType?: string;\n};\n\n/**\n * Build a fresh context envelope. Reuses `collectDeviceContext()` for the device block (which\n * already carries a best-effort auto-detected `appVersion`) and layers the host-injected scalars\n * on top. An explicit `input.appVersion` overrides the auto-detected `device.appVersion`, and the\n * outer `appVersion` scalar mirrors whichever version is effective.\n *\n * Returns a NEW object on every call (no shared mutable reference), so a caller can hold or mutate\n * the result without leaking into the next envelope. Never throws — `collectDeviceContext` is\n * itself guarded, and the rest is plain assignment.\n */\nexport const buildContextEnvelope = (input: ContextEnvelopeInput = {}): ContextEnvelope => {\n // Fresh copy so the returned envelope never aliases a cached device snapshot.\n const device: DeviceContext = { ...collectDeviceContext() };\n\n // `device.appVersion` is auto-detected best-effort by `collectDeviceContext`; an explicit\n // host `input.appVersion` always wins.\n if (input.appVersion) device.appVersion = input.appVersion;\n\n // The outer scalar mirrors the effective version (host-supplied, else auto-detected) so the\n // queue can stamp `user_context.app_version` even when the host never passed one.\n const effectiveAppVersion = input.appVersion ?? device.appVersion;\n\n const envelope: ContextEnvelope = { device };\n if (input.sessionId) envelope.sessionId = input.sessionId;\n if (effectiveAppVersion) envelope.appVersion = effectiveAppVersion;\n if (input.appBuild) envelope.appBuild = input.appBuild;\n if (input.networkType) envelope.networkType = input.networkType;\n\n return envelope;\n};\n","/**\n * eventQueue — the OFFLINE-FIRST, persistent transport buffer for client analytics events.\n *\n * The existing `reportClientEvents` is a blind fire-and-forget POST: it returns `void`, has no\n * success signal, and drops events when the network is down. The analytics data story depends on\n * NEVER losing an event offline, so this queue adds the missing durability layer on top of the\n * same `POST {serverUrl}/v1/events` contract:\n *\n * • Persists pending events to the host-injected `WireOnboardingStorage` (survives app kills).\n * • Batches them into one request body `{ events: [...] }`.\n * • Owns its OWN awaited `fetch` that reads `res.ok` — the only way to drive retry + dequeue,\n * since `reportClientEvents` cannot ack. A 2xx dequeues the batch; a non-ok / rejected / thrown\n * response keeps it and schedules an exponential backoff retry.\n * • Flushes on `enqueue`, on an explicit `flush()`, and on `notifyOnline()` (host reconnect).\n * • Caps the buffer (drop-OLDEST under pressure) and de-dups identical pending events.\n * • Stamps the current context envelope (device + host scalars) onto every event before send.\n *\n * FIRE-AND-FORGET (load-bearing): `enqueue` returns immediately and NEVER throws into the UI. A\n * missing `fetch`, a hung/broken storage, a rejecting network, or a JSON error is swallowed and\n * degrades gracefully — analytics must never be able to break the app. In-memory fallback covers\n * the no-storage case (survives re-renders, not app kills).\n *\n * DEPENDENCY-FREE: no network-detection or persistence library. Connectivity is host-driven via\n * `notifyOnline()`; persistence is the host-injected AsyncStorage-compatible subset.\n */\nimport type { ContextEnvelope } from \"./contextEnvelope\";\nimport type { ClientEvent, ClientEventTarget } from \"./reportClientEvent\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\n/** Envelope source: a fixed envelope or a provider evaluated at enqueue time (fresh network type). */\nexport type EnvelopeSource = ContextEnvelope | (() => ContextEnvelope | undefined);\n\n/** Options for {@link createEventQueue}. Only `target` is conceptually required to actually send. */\nexport type EventQueueOptions = {\n /** Where to POST — the tenant transport (`serverUrl` + `apiKey`), same as `WireOnboardingConfig`. */\n target: ClientEventTarget | undefined;\n /**\n * Host persistence (AsyncStorage-compatible subset). When omitted, the queue runs in the\n * documented DEGRADED in-memory mode — it survives re-renders but not an app kill.\n */\n storage?: WireOnboardingStorage;\n /** Tenant/app id used to namespace the default storage key (`wireai:evtq:<appId>`). */\n appId?: string;\n /** Explicit storage key override (wins over the `appId`-derived default). */\n storageKey?: string;\n /** The context envelope stamped onto every event before send (device + host scalars). */\n envelope?: EnvelopeSource;\n /** Max pending events; enqueuing past this DROPS THE OLDEST first (default 200). */\n maxSize?: number;\n /** Events per POST batch (default 20). */\n batchSize?: number;\n /** First retry delay in ms; doubles each failed attempt (default 1000). */\n baseBackoffMs?: number;\n /** Backoff ceiling in ms (default 30000). */\n maxBackoffMs?: number;\n /** Max AUTOMATIC backoff retries before pausing (default 6); `notifyOnline()`/`flush()` re-arm it. */\n maxRetries?: number;\n};\n\n/** The queue's public surface. `enqueue` is fire-and-forget (returns immediately, never throws). */\nexport type EventQueue = {\n /** Buffer one event (envelope-stamped), persist, and schedule a flush. Never throws. */\n enqueue(event: ClientEvent): void;\n /** Attempt an immediate drain of the pending buffer. Fire-and-forget. */\n flush(): void;\n /** Host reconnect signal: reset backoff and drain immediately. Fire-and-forget. */\n notifyOnline(): void;\n /** Current pending (in-memory) count. */\n size(): number;\n};\n\nconst DEFAULTS = {\n maxSize: 200,\n batchSize: 20,\n baseBackoffMs: 1000,\n maxBackoffMs: 30000,\n maxRetries: 6,\n} as const;\n\n/** Ceiling on the persisted-backlog read — a hung adapter degrades to an empty start, never a stall. */\nconst READ_TIMEOUT_MS = 1500;\n\n/** Internal buffered item. `id` is a local monotonic handle for deterministic dequeue-after-ack;\n * it is NEVER sent to the server. `sig` is the de-dup signature (serialized stamped event). */\ntype QueuedItem = { id: number; event: ClientEvent; sig: string };\n\n/** Persisted shape — the local id + the (already envelope-stamped) event. `sig` is recomputed on load. */\ntype PersistedItem = { id: number; event: ClientEvent };\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n/** Detach a timer from the event loop where the runtime supports it (Node test process / some RNs). */\nconst unrefTimer = (timer: ReturnType<typeof setTimeout>): void => {\n const t = timer as unknown as { unref?: () => void };\n if (typeof t.unref === \"function\") t.unref();\n};\n\nconst parsePersisted = (raw: string | null | undefined): PersistedItem[] => {\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const items: PersistedItem[] = [];\n for (const entry of parsed) {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof (entry as PersistedItem).id === \"number\" &&\n (entry as PersistedItem).event &&\n typeof (entry as PersistedItem).event === \"object\"\n ) {\n items.push(entry as PersistedItem);\n }\n }\n return items;\n } catch {\n // Corrupt backlog → start empty; the next persist overwrites it.\n return [];\n }\n};\n\n/**\n * Create an offline-first event queue. Loads any persisted backlog on creation so a\n * killed-and-relaunched app resumes where it left off. Returns the {@link EventQueue} surface.\n */\nexport const createEventQueue = (options: EventQueueOptions): EventQueue => {\n const target = options.target;\n const storage = options.storage;\n const key = options.storageKey ?? `wireai:evtq:${options.appId ?? \"default\"}`;\n const maxSize = options.maxSize ?? DEFAULTS.maxSize;\n const batchSize = options.batchSize ?? DEFAULTS.batchSize;\n const baseBackoffMs = options.baseBackoffMs ?? DEFAULTS.baseBackoffMs;\n const maxBackoffMs = options.maxBackoffMs ?? DEFAULTS.maxBackoffMs;\n const maxRetries = options.maxRetries ?? DEFAULTS.maxRetries;\n\n let pending: QueuedItem[] = [];\n let nextId = 0;\n let flushing = false;\n let attempt = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n\n const resolveEnvelope = (): ContextEnvelope | undefined => {\n try {\n return typeof options.envelope === \"function\" ? options.envelope() : options.envelope;\n } catch {\n return undefined;\n }\n };\n\n // Stamp the current envelope onto a COPY of the event (never mutate the caller's object):\n // device → event.device (when the event has none)\n // sessionId → event.session_id (when the event has none)\n // appVersion / appBuild / networkType → event.user_context (the non-PII bucket the server\n // sanitizes), never overwriting a key the caller already set.\n const stamp = (event: ClientEvent): ClientEvent => {\n const env = resolveEnvelope();\n const stamped: ClientEvent = { ...event };\n if (!env) return stamped;\n if (!stamped.device && env.device) stamped.device = env.device;\n if (!stamped.session_id && env.sessionId) stamped.session_id = env.sessionId;\n const uc: Record<string, string | number | boolean> = { ...(stamped.user_context ?? {}) };\n if (env.appVersion && uc.app_version === undefined) uc.app_version = env.appVersion;\n if (env.appBuild && uc.app_build === undefined) uc.app_build = env.appBuild;\n if (env.networkType && uc.network_type === undefined) uc.network_type = env.networkType;\n if (Object.keys(uc).length > 0) stamped.user_context = uc;\n return stamped;\n };\n\n const persist = (): void => {\n if (!storage) return;\n try {\n if (pending.length === 0) {\n void storage.removeItem(key).catch(() => {});\n return;\n }\n const payload: PersistedItem[] = pending.map((item) => ({ id: item.id, event: item.event }));\n void storage.setItem(key, JSON.stringify(payload)).catch(() => {});\n } catch {\n // Best-effort: a failed write just means the backlog is not durable this launch.\n }\n };\n\n const enforceSizeCap = (): void => {\n // Drop the OLDEST first so the newest events are never the ones lost under pressure.\n if (pending.length > maxSize) pending.splice(0, pending.length - maxSize);\n };\n\n const safeSig = (event: ClientEvent): string => {\n try {\n return JSON.stringify(event);\n } catch {\n // Non-serializable event → give it a unique signature so it is never wrongly de-duped.\n return `__nosig_${nextId}_${Math.random()}`;\n }\n };\n\n // Load any persisted backlog. Anything enqueued before this settles stays in memory; we merge\n // persisted (older) ahead of it and reassign monotonic ids so dequeue-after-ack is deterministic.\n const loadPromise: Promise<void> = (async () => {\n if (!storage) return;\n try {\n const persistedItems = parsePersisted(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS));\n if (persistedItems.length === 0) return;\n const events = [...persistedItems.map((p) => p.event), ...pending.map((p) => p.event)];\n pending = [];\n nextId = 0;\n const seen = new Set<string>();\n for (const event of events) {\n const sig = safeSig(event);\n if (seen.has(sig)) continue; // collapse duplicates carried across the merge\n seen.add(sig);\n pending.push({ id: nextId++, event, sig });\n }\n enforceSizeCap();\n persist();\n } catch {\n // Unreadable backlog → start empty; nothing enqueued in-memory is lost.\n }\n })();\n\n // The queue's OWN awaited POST. Reads `res.ok` to drive retry/dequeue. NEVER throws — a missing\n // fetch, a rejecting network, or a JSON error resolves to `false` (batch stays, retry schedules).\n const postBatch = async (events: ClientEvent[]): Promise<boolean> => {\n if (!target?.serverUrl || events.length === 0) return false;\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = setTimeout(() => controller?.abort(), 15_000);\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events }),\n signal: controller?.signal,\n });\n return !!(res && (res as { ok?: boolean }).ok);\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n };\n\n const clearRetry = (): void => {\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n retryTimer = undefined;\n }\n };\n\n const scheduleRetry = (): void => {\n // Bounded automatic retry. Past the cap the backlog simply waits for the next\n // `notifyOnline()` / `flush()` (both re-arm attempt), so events are paused, never dropped.\n if (attempt >= maxRetries) return;\n const delay = Math.min(baseBackoffMs * 2 ** attempt, maxBackoffMs);\n attempt++;\n clearRetry();\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n void drain();\n }, delay);\n unrefTimer(retryTimer);\n };\n\n const drain = async (): Promise<void> => {\n try {\n await loadPromise;\n } catch {\n // load already swallows; guard the await defensively.\n }\n if (flushing) return;\n flushing = true;\n try {\n while (pending.length > 0) {\n const batch = pending.slice(0, batchSize);\n const ok = await postBatch(batch.map((item) => item.event));\n if (!ok) {\n scheduleRetry();\n return;\n }\n // Dequeue exactly the acked batch by id (pending may have grown while in flight).\n const acked = new Set(batch.map((item) => item.id));\n pending = pending.filter((item) => !acked.has(item.id));\n persist();\n attempt = 0;\n clearRetry();\n }\n } finally {\n flushing = false;\n }\n };\n\n const flush = (): void => {\n try {\n void drain();\n } catch {\n // drain never throws synchronously, but guard the kick anyway.\n }\n };\n\n const enqueue = (event: ClientEvent): void => {\n try {\n const stamped = stamp(event);\n const sig = safeSig(stamped);\n // Collapse a redundant re-enqueue of an identical pending event.\n for (const item of pending) {\n if (item.sig === sig) return;\n }\n pending.push({ id: nextId++, event: stamped, sig });\n enforceSizeCap();\n persist();\n // Only kick a drain when no retry is already pending — avoids hammering fetch while offline.\n if (retryTimer === undefined) flush();\n } catch {\n // Fire-and-forget: nothing in enqueue may surface to the UI.\n }\n };\n\n const notifyOnline = (): void => {\n // Host reconnected: reset the backoff and drain now.\n attempt = 0;\n clearRetry();\n flush();\n };\n\n const size = (): number => pending.length;\n\n return { enqueue, flush, notifyOnline, size };\n};\n","/**\n * currentSession — a tiny module-level registry of the CURRENT per-open `session_id`.\n *\n * WHY it exists (kills the phantom-session): the per-open emitters (`reportSessionStart` and the\n * `useSessionStart` / `useLifecycleEvents` hooks) mint a fresh `session_id` for each app-open and\n * post `app.session_started` with it — so the SERVER knows that id. But other client paths\n * (`identify`, host `app_event`s through the analytics façade) used to reference a DIFFERENT id\n * (a frozen per-instance id), which the server had never seen, so it back-filled a synthetic\n * `session_started` — inflating session counts (the \"phantom-session\" bug).\n *\n * This registry is the single seam that lets those paths reuse the LIVE per-open session id the\n * server already ingested. `reportSessionStart` writes the current id here on every open; the façade\n * reads it so `identify`/app-events correlate to the real session instead of minting a phantom.\n *\n * DEPENDENCY-FREE + PROCESS-LOCAL: a plain module variable. It is intentionally NOT persisted — it\n * tracks the CURRENT process's open, and a fresh open always overwrites it. No cross-launch state.\n */\n\nlet _currentSessionId: string | undefined;\n\n/**\n * Record the current per-open `session_id`. Called by `reportSessionStart` when it emits an\n * app-open. A blank / non-string id is ignored (the previous id stays current). Idempotent.\n */\nexport const setCurrentSessionId = (id: string | undefined): void => {\n if (typeof id === \"string\" && id.length > 0) _currentSessionId = id;\n};\n\n/** The current per-open `session_id`, or `undefined` when no app-open has been registered yet. */\nexport const getCurrentSessionId = (): string | undefined => _currentSessionId;\n\n/** Test-only: forget the current session id so a unit test starts from a clean registry. */\nexport const resetCurrentSessionId = (): void => {\n _currentSessionId = undefined;\n};\n","/**\n * User identity — bind an onboarding session to the HOST's own user id so the funnel can\n * be reconciled to real users later (console sessions ↔ your user table / GA4 users).\n *\n * The id is an OPAQUE PSEUDONYMOUS STRING the host owns — its internal user id, NOT an\n * email/name/phone. Same host-injection philosophy as `storage` and `userContext`: the kit\n * mints nothing and reads nothing; the host passes what it wants. Dependency-free.\n *\n * Three binding moments (see WireOnboarding + the README \"User identity\" section):\n * 1. MOUNT — pass `userId` and it rides the A2A session-start metadata; the server\n * binds it when it creates the session.\n * 2. MID-SESSION— the user registers DURING onboarding: change the `userId` prop and the\n * kit emits an `identify` client event that attaches the id to the live\n * session (late binding — the key scenario).\n * 3. POST-FLOW — the user registers AFTER onboarding: call `identifyOnboarding(...)` with\n * the same host storage (it recovers the persisted contextId, before completion\n * clears it) or, more reliably, the `contextId` you captured from the\n * `started`/`resumed` `onEvent` (both events carry a `contextId` field).\n *\n * ⚠️ NO PII. Pass an opaque id (or a hash), never a raw email/name/phone. The id is capped at\n * {@link USER_ID_MAX_LENGTH} chars (longer ids are truncated, not rejected).\n */\nimport { getCurrentSessionId } from \"../analytics/currentSession\";\nimport { reportClientEvent } from \"../analytics/reportClientEvent\";\nimport {\n peekPersistedSession,\n sessionStorageKey,\n type WireOnboardingStorage,\n} from \"../session/persistedSession\";\n\n/** Max accepted user-id length. Longer strings are truncated (never rejected). Keep in sync\n * with the server's `USER_ID_MAX_LENGTH` (analytics/events.py). */\nexport const USER_ID_MAX_LENGTH = 128;\n\n/**\n * Normalize a host-supplied user id: trim, drop empty, and cap at {@link USER_ID_MAX_LENGTH}.\n * Returns `undefined` for a missing/blank/non-string value so callers can `if (id)`-gate.\n * PII is a host concern — this only bounds length, it does not (and cannot) detect an email.\n */\nexport const sanitizeUserId = (raw: unknown): string | undefined => {\n if (typeof raw !== \"string\") return undefined;\n const trimmed = raw.trim();\n if (!trimmed) return undefined;\n return trimmed.length > USER_ID_MAX_LENGTH ? trimmed.slice(0, USER_ID_MAX_LENGTH) : trimmed;\n};\n\n/** Options for {@link identifyOnboarding}. */\nexport type IdentifyOnboardingOptions = {\n /** Tenant transport, same shape as `WireOnboardingConfig` (only these two fields are used). */\n config: { serverUrl: string; apiKey: string };\n /** The host's opaque user id to bind. Trimmed + capped; NO PII. */\n userId: string;\n /**\n * The onboarding session id to bind to (the A2A contextId) — the `contextId` field carried on\n * the `started`/`resumed` `onEvent`. Pass this when you captured it there. Required after the\n * flow COMPLETED, since completion clears the persisted session. Wins over the storage lookup.\n */\n contextId?: string;\n /**\n * The SAME host storage you passed to `<WireOnboarding storage={…} />`. When `contextId` is\n * omitted, the helper reads the persisted contextId from it (works while the session is still\n * persisted — i.e. dropped or mid-flow, before completion clears it).\n */\n storage?: WireOnboardingStorage;\n /** App id, to derive the default storage key `wireai:session:<appId>` when reading from storage. */\n appId?: string;\n /** Storage key override — pass the same `persistKey` you gave `<WireOnboarding>`, if any. */\n persistKey?: string;\n};\n\n/**\n * Attach a host user id to an onboarding session AFTER the fact (post-registration), by sending\n * an `identify` client event to `/v1/events`. Resolves the contextId from an explicit\n * `contextId` or, failing that, from the persisted session in the host `storage`.\n *\n * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to `true`\n * when an identify event was dispatched, `false` when it couldn't (no user id, no server url,\n * or no resolvable contextId).\n */\nexport const identifyOnboarding = async (\n opts: IdentifyOnboardingOptions,\n): Promise<boolean> => {\n const userId = sanitizeUserId(opts.userId);\n if (!userId || !opts.config?.serverUrl) return false;\n\n let contextId = opts.contextId?.trim() || undefined;\n if (!contextId && opts.storage) {\n const key = opts.persistKey ?? (opts.appId ? sessionStorageKey(opts.appId) : undefined);\n if (key) {\n const stored = await peekPersistedSession(opts.storage, key);\n contextId = stored?.id;\n }\n }\n // Last resort: bind to the LIVE per-open session (registered by `reportSessionStart`) so a\n // post-flow identify with no captured contextId still attaches to a session the server saw,\n // instead of no-oping. The onboarding contextId (above) is still preferred when available.\n if (!contextId) contextId = getCurrentSessionId();\n if (!contextId) return false;\n\n reportClientEvent(\n { serverUrl: opts.config.serverUrl, apiKey: opts.config.apiKey },\n { event_type: \"identify\", session_id: contextId, user_id: userId },\n );\n return true;\n};\n","/**\n * userContext — the ONE extensible object a host passes once and the kit flows into every\n * analytics event's `user_context` (plus the top-level opaque `user_id`).\n *\n * WHY it exists: hosts already hand the kit fragments of \"who this user is\" — `config.appVersion`,\n * `useSessionStart({ deviceKey, userId })`, `<WireOnboarding userContext={…} />` — but there was no\n * single object that carries app version + device key + user id + (opt-in) email + arbitrary extras\n * together, with one precedence rule, into every event. `WireUserContext` is that object;\n * `resolveUserContext` is the pure merge that turns it into the wire shape.\n *\n * PRECEDENCE (the one rule): an explicit `WireUserContext` field WINS over the #42 auto-detected\n * `device`/`appVersion`. A missing field is OMITTED, never sent empty.\n *\n * WHERE EACH FIELD LANDS (deliberate separation so nothing leaks across buckets):\n * • `userId` → the event's TOP-LEVEL opaque `user_id` (via `sanitizeUserId`). NEVER the bucket.\n * • `userEmail` → its OWN key `user_context.user_email`. NEVER merged into `userId`. OPT-IN PII.\n * • `deviceKey` → `user_context.device_key` (the server's `_event_device_key` reads it there).\n * • `appVersion`→ `user_context.app_version` (and returned as `appVersion` for `device.appVersion`).\n * • `extra` → NAMESPACED under a `custom.` key prefix, coerced to scalars, so a host extra can\n * never collide with a reserved `user_context` key.\n *\n * DEPENDENCY-FREE: the only import is the kit's own `sanitizeUserId`. The optional email hash is a\n * dependency-free FNV-1a fold (see {@link hashEmailFnv1a}) — no crypto library, no async.\n */\nimport { sanitizeUserId } from \"../identity/userIdentity\";\n\n/**\n * The single, extensible user-context object. A host passes it ONCE (at analytics init) and may\n * update it post-mount (e.g. attach `userId`/`userEmail` at login) via `setUserContext(partial)`.\n * Every field is optional; missing fields are omitted from the wire payload.\n */\nexport interface WireUserContext {\n /**\n * Host app version, e.g. \"1.4.2\". EXPLICIT — wins over the #42 auto-detected `device.appVersion`.\n * Lands in `user_context.app_version`. Omitted when neither this nor auto-detect yields a version.\n */\n appVersion?: string;\n /**\n * A stable, non-PII device id the host owns. Lands in `user_context.device_key` (NOT `session_id`),\n * where the server groups a device's sessions. Host-supplied; the kit never mints or reads one.\n */\n deviceKey?: string;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id — NOT an email/name/phone). Sanitized +\n * capped (see `sanitizeUserId`) and placed on the event's top-level `user_id`. NEVER the bucket.\n */\n userId?: string;\n /**\n * OPT-IN PII. The user's email, its OWN field (`user_context.user_email`) — NEVER merged into\n * `userId`. The kit NEVER auto-collects this; a host passes it only WITH the user's consent (EU\n * users: treat as personal data). For a non-reversible form, set {@link hashEmail} `true` (the kit\n * folds it with a dependency-free hash and stamps `user_context.user_email_hashed: true`), OR\n * pre-hash host-side with a cryptographic digest and pass that here with `hashEmail` falsy.\n */\n userEmail?: string;\n /**\n * When `true`, {@link userEmail} is folded with the kit's dependency-free {@link hashEmailFnv1a}\n * before it leaves the device, and `user_context.user_email_hashed` is set `true`. NOTE: FNV-1a is\n * a lightweight NON-cryptographic fold (obfuscation, not a secure digest). For a cryptographic\n * hash, compute it host-side (e.g. SHA-256 via `expo-crypto`) and pass the digest as `userEmail`\n * with `hashEmail` falsy. Default: raw email is sent as-is (opt-in already gated it upstream).\n */\n hashEmail?: boolean;\n /**\n * Arbitrary host context (signup method, referral, plan tier…). Each value is coerced to a scalar\n * (`string | number | boolean`; non-scalars and non-finite numbers are DROPPED) and NAMESPACED\n * under a `custom.` key prefix in `user_context` (e.g. `user_context[\"custom.referral\"]`) so it can\n * never collide with a reserved key. No raw PII — use {@link userEmail} for email.\n */\n extra?: Record<string, string | number | boolean>;\n}\n\n/**\n * The wire-shaped result of {@link resolveUserContext}. `userContext` is the non-PII/opt-in-PII\n * bucket stamped onto the event; `userId` is the top-level opaque id; `appVersion`/`deviceKey` are\n * echoed for callers that also place them elsewhere (e.g. `device.appVersion`). Absent fields are\n * omitted so a caller can spread this without sending empties.\n */\nexport interface ResolvedUserContext {\n /** The opaque, sanitized user id → the event's top-level `user_id`. Omitted when unset/blank. */\n userId?: string;\n /** The stable device id → `user_context.device_key`. Omitted when unset. */\n deviceKey?: string;\n /** The effective app version (explicit > auto-detected) → `user_context.app_version`. */\n appVersion?: string;\n /** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */\n userContext?: Record<string, string | number | boolean>;\n}\n\n/** Reserved `user_context` keys the kit itself writes; host `extra` is namespaced away from these. */\nexport const RESERVED_USER_CONTEXT_KEYS = [\n \"device_key\",\n \"app_version\",\n \"app_build\",\n \"network_type\",\n \"session_count\",\n \"returning\",\n \"platform\",\n \"user_email\",\n \"user_email_hashed\",\n] as const;\n\n/** The prefix applied to every host `extra` key so it can never collide with a reserved key. */\nexport const EXTRA_KEY_PREFIX = \"custom.\" as const;\n\n/** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */\nexport const isWireScalar = (value: unknown): value is string | number | boolean => {\n const t = typeof value;\n if (t === \"string\" || t === \"boolean\") return true;\n if (t === \"number\") return Number.isFinite(value as number);\n return false;\n};\n\n/**\n * Fold an email to a stable, dependency-free 32-bit FNV-1a hex token (lowercased + trimmed first so\n * the same address always folds identically). This is OBFUSCATION, not a cryptographic digest — it\n * is not collision-resistant. For a real hash, pre-hash host-side and pass the digest as `userEmail`.\n */\nexport const hashEmailFnv1a = (email: string): string => {\n const normalized = email.trim().toLowerCase();\n let hash = 0x811c9dc5; // FNV offset basis (32-bit)\n for (let i = 0; i < normalized.length; i++) {\n hash ^= normalized.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193); // FNV prime (32-bit), kept in 32-bit via imul\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n};\n\n/** Trim a candidate string; return `undefined` for a non-string / blank so callers can `if`-gate. */\nconst cleanString = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Coerce a host `extra` map into the namespaced, scalar-only bucket shape. Every kept value is\n * placed under `custom.<key>`; non-scalar values (objects, arrays, null, functions, NaN/Infinity)\n * are DROPPED. Returns an object (possibly empty).\n */\nexport const namespaceExtra = (\n extra: Record<string, unknown> | undefined,\n): Record<string, string | number | boolean> => {\n const out: Record<string, string | number | boolean> = {};\n if (!extra || typeof extra !== \"object\") return out;\n for (const [key, value] of Object.entries(extra)) {\n const cleanKey = cleanString(key);\n if (!cleanKey) continue;\n if (!isWireScalar(value)) continue; // drop anything that isn't a finite scalar\n out[`${EXTRA_KEY_PREFIX}${cleanKey}`] = value;\n }\n return out;\n};\n\n/** Options for {@link resolveUserContext}. */\nexport interface ResolveUserContextOptions {\n /**\n * The kit's best-effort auto-detected app version (#42; from `detectAppVersion()`/the device\n * snapshot). Used ONLY when the explicit `WireUserContext.appVersion` is absent — explicit wins.\n */\n autoAppVersion?: string;\n}\n\n/**\n * Merge a {@link WireUserContext} into the wire shape with the precedence rule (explicit field >\n * auto-detected). Pure, never throws. Missing fields are omitted so the result can be spread onto an\n * event without sending empties.\n */\nexport const resolveUserContext = (\n ctx: WireUserContext = {},\n opts: ResolveUserContextOptions = {},\n): ResolvedUserContext => {\n const result: ResolvedUserContext = {};\n const bucket: Record<string, string | number | boolean> = {};\n\n // userId → top-level opaque id (NEVER the bucket). Sanitized + capped host-side.\n const userId = sanitizeUserId(ctx.userId);\n if (userId) result.userId = userId;\n\n // deviceKey → user_context.device_key (NOT session_id).\n const deviceKey = cleanString(ctx.deviceKey);\n if (deviceKey) {\n result.deviceKey = deviceKey;\n bucket.device_key = deviceKey;\n }\n\n // appVersion → explicit wins over auto-detected (#42); echoed for device.appVersion callers.\n const appVersion = cleanString(ctx.appVersion) ?? cleanString(opts.autoAppVersion);\n if (appVersion) {\n result.appVersion = appVersion;\n bucket.app_version = appVersion;\n }\n\n // userEmail → its OWN key. OPT-IN PII, optionally folded. NEVER touches userId.\n const email = cleanString(ctx.userEmail);\n if (email) {\n if (ctx.hashEmail) {\n bucket.user_email = hashEmailFnv1a(email);\n bucket.user_email_hashed = true;\n } else {\n bucket.user_email = email;\n }\n }\n\n // extra → namespaced + scalar-coerced.\n Object.assign(bucket, namespaceExtra(ctx.extra));\n\n if (Object.keys(bucket).length > 0) result.userContext = bucket;\n return result;\n};\n","/**\n * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies\n * none. This is the headline of \"device fully automatic\": the analytics façade auto-mints ONE id,\n * persists it via the host's `storage` abstraction, and reuses it on every subsequent open — so\n * `user_context.device_key` is ALWAYS present and the server's review/questionnaire gating +\n * A/B stickiness (both key on `device_key`) work out of the box, with zero host wiring.\n *\n * WHY it is NOT PII and adds NO dependency (the kit's hard rules):\n * The id is a random token generated from `Date.now()` + `Math.random()` — it carries NO hardware\n * identifier, NO IDFA/GAID, NO fingerprint. It is a first-party per-install correlation key, the\n * same privacy category as a first-party cookie: it groups a single install's sessions and cannot\n * identify a person or be joined across apps. There is NO `uuid` (or any) dependency — a\n * time+random scheme is sufficient because the id is minted ONCE and then persisted, so global\n * uniqueness across the fleet is not required (a per-install collision is astronomically unlikely\n * and inconsequential — worst case two installs share a bucket).\n *\n * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses\n * that verbatim and never mints/persists an auto id.\n */\n\n/** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */\nexport const AUTO_DEVICE_ID_PREFIX = \"wdev_\";\n\n/** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */\nexport const deviceIdStorageKey = (appId?: string): string =>\n `wireai:analytics:deviceKey:${appId ?? \"default\"}`;\n\n/** One 32-bit base-36 chunk of randomness. Two chunks are concatenated for a wider token. */\nconst randomChunk = (): string =>\n Math.floor(Math.random() * 0x100000000)\n .toString(36)\n .padStart(6, \"0\");\n\n/**\n * Mint a fresh per-install device id. Dependency-free (`Date.now()` + `Math.random()`), never\n * throws, and returns a NEW value on every call — the façade mints ONCE and persists, so this is\n * called at most once per install (then the persisted value is reused). Two random chunks plus the\n * timestamp keep the token wide enough that a per-install collision is not a practical concern.\n */\nexport const mintDeviceId = (): string => {\n const time = Date.now().toString(36);\n return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;\n};\n","/**\n * analyticsFacade — a Segment/PostHog-shaped developer API (`track` / `screen` / `identify`)\n * over the kit's OWN offline-first event queue. One package, one key, one line:\n *\n * const analytics = createAnalytics({ serverUrl, apiKey, storage });\n * analytics.track(\"content_share\", { source: \"feed\" });\n * analytics.screen(\"Home\", { tab: \"explore\" });\n * analytics.identify(\"u_123\", { plan: \"pro\" });\n *\n * WHY a façade: the primitives already exist (`createEventQueue` for durable offline-first\n * transport, `buildContextEnvelope` for the non-PII device context, the `identify` client-event\n * contract for user binding), but a host had to wire them together by hand. This composes them\n * into the familiar analytics-SDK surface so a consumer gets the ergonomics with NO second\n * install and NO second key — the same `{ serverUrl, apiKey }` creds as onboarding.\n *\n * ROUTING: every call builds a `ClientEvent` and `enqueue`s it. The queue stamps the context\n * envelope (device + host scalars), persists offline, batches, retries, and dequeues on ack —\n * so `track`/`screen`/`identify` inherit offline-first durability for free. `screen` routes\n * through the SAME queue rather than the direct `reportAppEvent` POST (a deliberate upgrade:\n * screen views survive being offline too).\n *\n * DEPENDENCY-FREE + TREE-SHAKEABLE: this module imports ONLY the queue, the envelope builder,\n * the client-event types + session-id seed, and the identity sanitizer. It reaches NO\n * onboarding / showcase / review UI, so an analytics-only consumer bundles none of it. React is\n * absent here on purpose — the optional React glue is the thin `useAnalytics` hook.\n *\n * FIRE-AND-FORGET: no method throws into the UI or blocks — the queue already guarantees that.\n */\nimport { buildContextEnvelope, type ContextEnvelope } from \"./contextEnvelope\";\nimport { getCurrentSessionId } from \"./currentSession\";\nimport { createEventQueue, type EventQueue, type EventQueueOptions } from \"./eventQueue\";\nimport { makeSessionId, type ClientEvent } from \"./reportClientEvent\";\nimport { resolveUserContext, type WireUserContext } from \"../context/userContext\";\nimport { mintDeviceId, deviceIdStorageKey } from \"../context/deviceId\";\nimport { sanitizeUserId } from \"../identity/userIdentity\";\n\n/** Arbitrary non-PII event properties. Serialized to the event's `meta` (a JSON string) on the wire. */\nexport type AnalyticsProps = Record<string, unknown>;\n\n/**\n * Tenant transport + context inputs for {@link createAnalytics}. `serverUrl`/`apiKey` are the\n * SAME creds as onboarding (never a second key). The rest feed the context envelope + the queue's\n * offline persistence — all optional.\n */\nexport type CreateAnalyticsConfig = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n /**\n * Correlation id shared by every event from this instance (and the `identify` event). Defaults\n * to a fresh `makeSessionId()` at creation so all events agree on one id per analytics instance.\n */\n sessionId?: string;\n /** Tenant/app id used to namespace the queue's default storage key (`wireai:evtq:<appId>`). */\n appId?: string;\n /**\n * Host persistence (AsyncStorage-compatible subset) for offline-first durability. When omitted,\n * the queue runs in the documented in-memory mode (survives re-renders, not app kills).\n */\n storage?: EventQueueOptions[\"storage\"];\n /** Host app version, e.g. \"1.4.2\" (host-injected; stamped onto every event's context). */\n appVersion?: string;\n /** Host native build number, e.g. \"412\" (host-injected). */\n appBuild?: string;\n /** Host connectivity signal, e.g. \"wifi\" | \"cellular\" — read fresh per event via the provider. */\n networkType?: string;\n /**\n * The rich {@link WireUserContext} to stamp onto every event's `user_context` (device key, opaque\n * user id, opt-in email, arbitrary `extra`). Passed ONCE here at init; updatable post-mount via\n * {@link Analytics.setUserContext} (e.g. attach `userId`/`userEmail` at login). Optional.\n *\n * NOTE on `deviceKey`: you do NOT need to supply one. When omitted, the kit auto-mints a stable,\n * non-PII per-install `device_key`, persists it via `storage`, and reuses it every open (in-memory\n * fallback without storage) — so `user_context.device_key` is ALWAYS present for the server's\n * review/questionnaire gating + A/B stickiness. Supply `deviceKey` only to use your OWN id (it wins).\n */\n userContext?: WireUserContext;\n};\n\n/** Optional queue tuning knobs, forwarded verbatim to {@link createEventQueue}. */\nexport type AnalyticsOptions = Partial<\n Pick<EventQueueOptions, \"maxSize\" | \"batchSize\" | \"baseBackoffMs\" | \"maxBackoffMs\" | \"maxRetries\">\n>;\n\n/**\n * The developer-facing analytics surface. `track`/`screen`/`identify` are the Segment/PostHog-shaped\n * API; `flush`/`notifyOnline`/`size` expose the underlying queue so a host can drive reconnect\n * draining (load-bearing for offline-first) and inspect the pending buffer.\n */\nexport type Analytics = {\n /** Record an in-app event: `event_type='app_event'`, `question_key=<event>`, `props`→`meta`. */\n track(event: string, props?: AnalyticsProps): void;\n /** Record a screen view: `event_type='app_event'`, `question_key='screen'`, `meta={ screen, ...props }`. */\n screen(name: string, props?: AnalyticsProps): void;\n /** Bind the host's opaque user id (per-session, in-memory) and emit an `identify` event. */\n identify(userId: string, traits?: AnalyticsProps): void;\n /**\n * Update the {@link WireUserContext} after init (e.g. attach `userId`/`userEmail` at login). Shallow\n * merges the partial over the current context (`extra` is deep-merged); a supplied `userId` also\n * binds like {@link identify}. Takes effect on subsequent events. Fire-and-forget.\n */\n setUserContext(partial: Partial<WireUserContext>): void;\n /** Attempt an immediate drain of the pending buffer. Fire-and-forget. */\n flush(): void;\n /** Host reconnect signal: reset backoff and drain now. Fire-and-forget. */\n notifyOnline(): void;\n /** Current pending (in-memory) count. */\n size(): number;\n};\n\n/**\n * Create a bound analytics instance. Seeds one correlation `sessionId`, builds an offline-first\n * queue over the tenant transport, and passes a fresh-per-event context envelope PROVIDER so the\n * connectivity type is read at enqueue time. The bound user id starts unset (see `identify`).\n */\nexport const createAnalytics = (\n config: CreateAnalyticsConfig,\n options: AnalyticsOptions = {},\n): Analytics => {\n // A STABLE per-instance fallback id, used only when no explicit `config.sessionId` was given AND\n // no per-open session has been registered yet (see `resolveSessionId`).\n const instanceSessionId = config.sessionId ?? makeSessionId();\n\n // The session id every event correlates to. Precedence: an explicit `config.sessionId` freezes the\n // id (opt-out of the reuse); otherwise reuse the LIVE per-open session the server saw (via\n // `app.session_started`) so `identify`/app-events don't mint a fresh id the server back-fills into a\n // phantom session; finally fall back to the stable per-instance id when no open is registered yet.\n const resolveSessionId = (): string =>\n config.sessionId ?? getCurrentSessionId() ?? instanceSessionId;\n\n // The mutable rich user-context: seeded at init, updated via `setUserContext`. Resolved fresh on\n // every event so a post-mount update (login) takes effect immediately. Declared before the envelope\n // provider so the provider can read the current `userContext.appVersion` (see below).\n let userContext: WireUserContext = { ...(config.userContext ?? {}) };\n\n // Auto device id (the headline: \"device\" fully automatic). When the host supplies NO `deviceKey`,\n // the kit mints ONE stable, non-PII per-install id, PERSISTS it via the host `storage`, and reuses it\n // on every subsequent open — so `user_context.device_key` is ALWAYS present (the server's\n // review/questionnaire gating + A/B stickiness both key on it) with zero host wiring. A host-supplied\n // `deviceKey` still wins (see `applyContext`). Falls back to an in-memory id (stable for this\n // instance) when no storage is available.\n const hostDeviceKeyAtInit =\n typeof config.userContext?.deviceKey === \"string\" && config.userContext.deviceKey.trim()\n ? config.userContext.deviceKey.trim()\n : undefined;\n // Minted synchronously so `device_key` is never missing, even before the async storage read resolves.\n let autoDeviceKey = mintDeviceId();\n if (config.storage && !hostDeviceKeyAtInit) {\n const storage = config.storage;\n const deviceKey = deviceIdStorageKey(config.appId);\n void storage\n .getItem(deviceKey)\n .then((saved) => {\n const persisted = typeof saved === \"string\" && saved.trim() ? saved.trim() : undefined;\n // Reuse the persisted per-install id across opens; on first run persist the freshly minted one.\n if (persisted) autoDeviceKey = persisted;\n else void storage.setItem(deviceKey, autoDeviceKey).catch(() => {});\n })\n .catch(() => {});\n }\n\n // A provider (not a fixed value) so `networkType`, the current session id, AND the effective app\n // version are evaluated fresh on every enqueue. An explicit `WireUserContext.appVersion` (a host that\n // set the version ONLY inside `userContext`) now flows into `device.appVersion` too — not just\n // `user_context.app_version` — so the server's `by_app_version` breakdown (which reads\n // `device.appVersion`) agrees. Explicit wins over the auto-detected device version;\n // `buildContextEnvelope` keeps the auto value when neither is set.\n const envelope = (): ContextEnvelope =>\n buildContextEnvelope({\n sessionId: resolveSessionId(),\n appVersion: userContext.appVersion ?? config.appVersion,\n appBuild: config.appBuild,\n networkType: config.networkType,\n });\n\n const queue: EventQueue = createEventQueue({\n target: { serverUrl: config.serverUrl, apiKey: config.apiKey },\n storage: config.storage,\n appId: config.appId,\n envelope,\n ...options,\n });\n\n // Per-session, in-memory user binding. Seeded from the init context, then persisted across\n // launches when storage is provided.\n let boundUserId: string | undefined = sanitizeUserId(config.userContext?.userId);\n const storageKey = `wireai:analytics:userId:${config.appId ?? \"default\"}`;\n\n if (config.storage) {\n void config.storage\n .getItem(storageKey)\n .then((saved) => {\n // Don't clobber an explicit init-context user id with a stale persisted one.\n if (saved && !boundUserId) boundUserId = saved;\n })\n .catch(() => {});\n }\n\n // Stamp the resolved rich context onto an event: the `user_context` bucket (device_key, app_version,\n // opt-in user_email, namespaced `custom.*`) and the top-level opaque `user_id`. Never overwrites a\n // key the caller already set (so `identify`'s explicit `user_id` and any caller `user_context` win).\n const applyContext = (event: ClientEvent): void => {\n // Host `deviceKey` wins; otherwise the auto-minted/persisted per-install id fills it in so\n // `user_context.device_key` is always present.\n const hostDeviceKey =\n typeof userContext.deviceKey === \"string\" && userContext.deviceKey.trim()\n ? userContext.deviceKey\n : undefined;\n const resolved = resolveUserContext(\n { ...userContext, deviceKey: hostDeviceKey ?? autoDeviceKey },\n { autoAppVersion: config.appVersion },\n );\n if (resolved.userContext) {\n event.user_context = { ...resolved.userContext, ...(event.user_context ?? {}) };\n }\n if (boundUserId && !event.user_id) event.user_id = boundUserId;\n };\n\n const setUserContext = (partial: Partial<WireUserContext>): void => {\n if (!partial || typeof partial !== \"object\") return;\n // Deep-merge `extra` so a partial update adds keys instead of replacing the whole map.\n const mergedExtra =\n partial.extra || userContext.extra\n ? { ...(userContext.extra ?? {}), ...(partial.extra ?? {}) }\n : undefined;\n userContext = { ...userContext, ...partial };\n if (mergedExtra) userContext.extra = mergedExtra;\n // A user id supplied here binds like `identify` so subsequent events carry `user_id`.\n const uid = sanitizeUserId(partial.userId);\n if (uid) {\n boundUserId = uid;\n if (config.storage) void config.storage.setItem(storageKey, uid).catch(() => {});\n }\n };\n\n const track = (event: string, props?: AnalyticsProps): void => {\n if (!event) return;\n const clientEvent: ClientEvent = {\n event_type: \"app_event\",\n session_id: resolveSessionId(),\n question_key: event,\n };\n if (props && Object.keys(props).length > 0) clientEvent.meta = JSON.stringify(props);\n applyContext(clientEvent);\n queue.enqueue(clientEvent);\n };\n\n const screen = (name: string, props?: AnalyticsProps): void => {\n if (!name) return;\n // Reuse the K6 screen event shape (question_key='screen'); route through the queue for offline-first.\n const meta = { screen: name, ...(props ?? {}) };\n const clientEvent: ClientEvent = {\n event_type: \"app_event\",\n session_id: resolveSessionId(),\n question_key: \"screen\",\n meta: JSON.stringify(meta),\n };\n applyContext(clientEvent);\n queue.enqueue(clientEvent);\n };\n\n const identify = (userId: string, traits?: AnalyticsProps): void => {\n const clean = sanitizeUserId(userId);\n // Blank / non-string → no binding, no event (sanitizeUserId returns undefined). >128 → truncated.\n if (!clean) return;\n boundUserId = clean;\n if (config.storage) {\n void config.storage.setItem(storageKey, clean).catch(() => {});\n }\n const clientEvent: ClientEvent = {\n event_type: \"identify\",\n // Reuse the LIVE per-open session id (see `resolveSessionId`) so the server binds identity to\n // the session it already saw instead of back-filling a phantom `session_started`.\n session_id: resolveSessionId(),\n user_id: clean,\n };\n if (traits && Object.keys(traits).length > 0) clientEvent.meta = JSON.stringify(traits);\n applyContext(clientEvent);\n queue.enqueue(clientEvent);\n };\n\n return {\n track,\n screen,\n identify,\n setUserContext,\n flush: queue.flush,\n notifyOnline: queue.notifyOnline,\n size: queue.size,\n };\n};\n","/**\n * useAnalytics — a THIN optional React hook over the pure {@link createAnalytics} factory.\n *\n * It builds ONE analytics instance for the component's lifetime and returns it, so re-renders\n * never rebuild the queue or lose the in-memory user binding. React is a REQUIRED peer of the\n * kit, so importing it here is allowed; the hook adds NO other dependency. Mirrors the existing\n * `createScreenTracker` / `useScreenTracking` split — the factory stays React-free, this is the\n * glue.\n *\n * const analytics = useAnalytics({ serverUrl, apiKey, storage, appId });\n * analytics.track(\"content_share\", { source: \"feed\" });\n * // ...on reconnect: analytics.notifyOnline();\n */\nimport { useRef } from \"react\";\n\nimport {\n createAnalytics,\n type Analytics,\n type AnalyticsOptions,\n type CreateAnalyticsConfig,\n} from \"./analyticsFacade\";\n\n/**\n * Build a per-mount analytics instance. `config`/`options` are read once at first render (the\n * instance is stable for the component's lifetime, held in a ref). Returns the {@link Analytics}\n * surface so the component can `track` / `screen` / `identify` and drive `notifyOnline` on reconnect.\n */\nexport const useAnalytics = (\n config: CreateAnalyticsConfig,\n options: AnalyticsOptions = {},\n): Analytics => {\n // One instance per mount; kept in a ref so re-renders never rebuild the queue or drop the binding.\n const ref = useRef<Analytics | undefined>(undefined);\n const prevKeys = useRef<string>(\"\");\n\n const currentKeys = `${config.serverUrl}|${config.apiKey}|${config.appId}`;\n if (!ref.current || prevKeys.current !== currentKeys) {\n prevKeys.current = currentKeys;\n ref.current = createAnalytics(config, options);\n }\n return ref.current;\n};\n"]}
1
+ {"version":3,"sources":["../../node_modules/expo-modules-core/src/errors/CodedError.ts","../../node_modules/expo-modules-core/src/NativeModulesProxy.ts","../../node_modules/expo-modules-core/src/TurboModuleToExpoModuleProxy.ts","../../node_modules/expo-modules-core/src/ensureNativeModulesAreInstalled.ts","../../node_modules/expo-modules-core/src/requireNativeModule.ts","../../node_modules/expo-modules-core/src/sweet/setUpJsLogger.fx.ts","../../node_modules/expo-modules-core/src/registerWebModule.ts","../../node_modules/expo-modules-core/src/TypedArrays.types.ts","../../node_modules/expo-modules-core/src/PermissionsInterface.ts","../../node_modules/expo-modules-core/src/PermissionsHook.ts","../../node_modules/expo-modules-core/src/Refs.ts","../../node_modules/expo-modules-core/src/hooks/useReleasingSharedObject.ts","../../node_modules/expo-modules-core/src/reload.ts","../../node_modules/expo-modules-core/src/index.ts","../../node_modules/expo-constants/src/Constants.types.ts","../../node_modules/expo-constants/src/ExponentConstants.ts","../../node_modules/expo-constants/src/Constants.ts","../../src/reviews/transport.ts","../../src/analytics/screenTracking.ts","../../src/analytics/useScreenTracking.ts","../../src/analytics/reportClientEvent.ts","../../src/analytics/analyticsEvent.ts","../../src/device/appVersion.ts","../../src/device/deviceModel.ts","../../src/device/deviceContext.ts","../../src/analytics/contextEnvelope.ts","../../src/analytics/eventQueue.ts","../../src/analytics/currentSession.ts","../../src/identity/userIdentity.ts","../../src/context/userContext.ts","../../src/context/deviceId.ts","../../src/analytics/analyticsFacade.ts","../../src/analytics/useAnalytics.ts"],"names":["name","_a","TurboModuleRegistry","AppOwnership","ExecutionEnvironment","UserInterfaceIdiom","Platform","NativeModules","useRef","useEffect","constants","runtimeRequire","interop","safeInterop","Dimensions","I18nManager","_b"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * A general error class that should be used for all errors in Expo modules.\n * Guarantees a `code` field that can be used to differentiate between different\n * types of errors without further subclassing Error.\n */\nexport class CodedError extends Error {\n code: string;\n info?: any;\n\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n }\n}\n","import type { ProxyNativeModule } from './NativeModulesProxy.types';\n\n// We default to an empty object shim wherever we don't have an environment-specific implementation\n\n/**\n * @deprecated `NativeModulesProxy` is deprecated and might be removed in the future releases.\n * Use `requireNativeModule` or `requireOptionalNativeModule` instead.\n */\nexport default {} as Record<string, ProxyNativeModule>;\n","// Copyright © 2024 650 Industries.\nimport type { TurboModule } from 'react-native';\n\nexport function createTurboModuleToExpoProxy(turboModule: TurboModule | null, name: string) {\n return null;\n}\n","// Installs the expo global on web\nimport './polyfill';\n\n/**\n * Ensures that the native modules are installed in the current runtime.\n * Otherwise, it synchronously calls a native function that installs them.\n */\nexport function ensureNativeModulesAreInstalled(): void {\n // No-op on web\n}\n","import { TurboModuleRegistry } from 'react-native';\n\nimport NativeModulesProxy from './NativeModulesProxy';\nimport { createTurboModuleToExpoProxy } from './TurboModuleToExpoModuleProxy';\nimport { ensureNativeModulesAreInstalled } from './ensureNativeModulesAreInstalled';\n\n/**\n * Imports the native module registered with given name. In the first place it tries to load\n * the module installed through the JSI host object and then falls back to the bridge proxy module.\n * Notice that the modules loaded from the proxy may not support some features like synchronous functions.\n *\n * @param moduleName Name of the requested native module.\n * @returns Object representing the native module.\n * @throws Error when there is no native module with given name.\n */\nexport function requireNativeModule<ModuleType = any>(moduleName: string): ModuleType {\n const nativeModule = requireOptionalNativeModule<ModuleType>(moduleName);\n\n if (!nativeModule) {\n throw new Error(`Cannot find native module '${moduleName}'`);\n }\n return nativeModule;\n}\n\n/**\n * Imports the native module registered with the given name. The same as `requireNativeModule`,\n * but returns `null` when the module cannot be found instead of throwing an error.\n *\n * @param moduleName Name of the requested native module.\n * @returns Object representing the native module or `null` when it cannot be found.\n */\nexport function requireOptionalNativeModule<ModuleType = any>(\n moduleName: string\n): ModuleType | null {\n ensureNativeModulesAreInstalled();\n\n try {\n return (\n globalThis.expo?.modules?.[moduleName] ??\n NativeModulesProxy[moduleName] ??\n createTurboModuleToExpoProxy(TurboModuleRegistry.get(moduleName), moduleName) ??\n null\n );\n } catch (e) {\n const error = e as Error;\n console.warn(`An error occurred while requiring the '${moduleName}' module: ${error.message}`);\n return null;\n }\n}\n","import { CodedError } from '../errors/CodedError';\nimport { requireOptionalNativeModule } from '../requireNativeModule';\n\ntype LogListener = {\n action: (...data: any[]) => void;\n eventName: string;\n};\n\nif (\n __DEV__ &&\n typeof window !== 'undefined' &&\n (process.env.EXPO_OS === 'android' || process.env.EXPO_OS === 'ios')\n) {\n const NativeJSLogger = requireOptionalNativeModule('ExpoModulesCoreJSLogger');\n if (NativeJSLogger) {\n const onNewException: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewError',\n action: console.error,\n };\n\n const onNewWarning: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewWarning',\n action: console.warn,\n };\n\n const onNewDebug: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewDebug',\n action: console.debug,\n };\n\n const onNewInfo: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewInfo',\n action: console.info,\n };\n\n const onNewTrace: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewTrace',\n action: console.trace,\n };\n\n const listeners: LogListener[] = [\n onNewException,\n onNewWarning,\n onNewDebug,\n onNewInfo,\n onNewTrace,\n ];\n\n for (const listener of listeners) {\n NativeJSLogger.addListener(listener.eventName, ({ message }: { message: string }) => {\n listener.action(message);\n });\n }\n }\n}\n\ndeclare namespace globalThis {\n let ExpoModulesCore_CodedError: undefined | typeof CodedError;\n}\n\n// We have to export `CodedError` via global object to use in later in the C++ code.\nglobalThis.ExpoModulesCore_CodedError = CodedError;\n","import { ensureNativeModulesAreInstalled } from './ensureNativeModulesAreInstalled';\nimport type { NativeModule } from './ts-declarations/NativeModule';\n\n/**\n * Registers a web module.\n * @param moduleImplementation A class that extends `NativeModule`. The class is registered under `globalThis.expo.modules[className]`.\n * @param moduleName A name to register the module under `globalThis.expo.modules[className]`.\n * @returns A singleton instance of the class passed into arguments.\n */\n\nexport function registerWebModule<\n EventsMap extends Record<never, never>,\n ModuleType extends typeof NativeModule<EventsMap>,\n>(moduleImplementation: ModuleType, moduleName: string): ModuleType {\n ensureNativeModulesAreInstalled();\n\n moduleName = moduleName ?? moduleImplementation.name;\n if (!moduleName) {\n throw new Error(\n 'Web module implementation is missing a name - it is either not a class or has been minified. Pass the name as a second argument to the `registerWebModule` function.'\n );\n }\n if (!globalThis?.expo?.modules) {\n globalThis.expo.modules = {};\n }\n if (globalThis.expo.modules[moduleName]) {\n return globalThis.expo.modules[moduleName];\n }\n globalThis.expo.modules[moduleName] = new moduleImplementation();\n return globalThis.expo.modules[moduleName];\n}\n","/** A union type for all integer based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type IntBasedTypedArray = Int8Array | Int16Array | Int32Array;\n\n/** A union type for all unsigned integer based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type UintBasedTypedArray = Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array;\n\n/** A union type for all floating point based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type FloatBasedTypedArray = Float32Array | Float64Array;\n\n/** A [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) describes an array-like view of an underlying binary data buffer. */\nexport type TypedArray = IntBasedTypedArray | UintBasedTypedArray | FloatBasedTypedArray;\n","export enum PermissionStatus {\n /**\n * User has granted the permission.\n */\n GRANTED = 'granted',\n /**\n * User hasn't granted or denied the permission yet.\n */\n UNDETERMINED = 'undetermined',\n /**\n * User has denied the permission.\n */\n DENIED = 'denied',\n}\n\n/**\n * Permission expiration time. Currently, all permissions are granted permanently.\n */\nexport type PermissionExpiration = 'never' | number;\n\n/**\n * An object obtained by permissions get and request functions.\n */\nexport type PermissionResponse = {\n /**\n * Determines the status of the permission.\n */\n status: PermissionStatus;\n /**\n * Determines time when the permission expires.\n */\n expires: PermissionExpiration;\n /**\n * A convenience boolean that indicates if the permission is granted.\n */\n granted: boolean;\n /**\n * Indicates if user can be asked again for specific permission.\n * If not, one should be directed to the Settings app\n * in order to enable/disable the permission.\n */\n canAskAgain: boolean;\n};\n","// Copyright © 2024 650 Industries.\n\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { PermissionResponse } from './PermissionsInterface';\n\n// These types are identical, but improves the readability for suggestions in editors\ntype RequestPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;\ntype GetPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;\n\ntype PermissionHookMethods<Permission extends PermissionResponse, Options = never> = {\n /** The permission method that requests the user to grant permission. */\n requestMethod: (options?: Options) => Promise<Permission>;\n /** The permission method that only fetches the current permission status. */\n getMethod: (options?: Options) => Promise<Permission>;\n};\n\ntype PermissionHookBehavior = {\n /** If the hook should automatically fetch the current permission status, without asking the user. */\n get?: boolean;\n /** If the hook should automatically request the user to grant permission. */\n request?: boolean;\n};\n\nexport type PermissionHookOptions<Options extends object> = PermissionHookBehavior & Options;\n\n/**\n * Get or request permission for protected functionality within the app.\n * It uses separate permission requesters to interact with a single permission.\n * By default, the hook will only retrieve the permission status.\n */\nfunction usePermission<Permission extends PermissionResponse, Options extends object>(\n methods: PermissionHookMethods<Permission, Options>,\n options?: PermissionHookOptions<Options>\n): [Permission | null, RequestPermissionMethod<Permission>, GetPermissionMethod<Permission>] {\n const isMounted = useRef(true);\n const [status, setStatus] = useState<Permission | null>(null);\n const { get = true, request = false, ...permissionOptions } = options || {};\n\n const getPermission = useCallback(async () => {\n let response: Permission;\n if (Object.keys(permissionOptions).length > 0) {\n response = await methods.getMethod(permissionOptions as Options);\n } else {\n response = await methods.getMethod();\n }\n if (isMounted.current) setStatus(response);\n return response;\n }, [methods.getMethod]);\n\n const requestPermission = useCallback(async () => {\n let response: Permission;\n if (Object.keys(permissionOptions).length > 0) {\n response = await methods.requestMethod(permissionOptions as Options);\n } else {\n response = await methods.requestMethod();\n }\n if (isMounted.current) setStatus(response);\n return response;\n }, [methods.requestMethod]);\n\n useEffect(\n function runMethods() {\n if (request) requestPermission();\n if (!request && get) getPermission();\n },\n [get, request, requestPermission, getPermission]\n );\n\n // Workaround for unmounting components receiving state updates\n useEffect(function didMount() {\n isMounted.current = true;\n return () => {\n isMounted.current = false;\n };\n }, []);\n\n return [status, requestPermission, getPermission];\n}\n\n/**\n * Create a new permission hook with the permission methods built-in.\n * This can be used to quickly create specific permission hooks in every module.\n */\nexport function createPermissionHook<Permission extends PermissionResponse, Options extends object>(\n methods: PermissionHookMethods<Permission, Options>\n) {\n return (options?: PermissionHookOptions<Options>) =>\n usePermission<Permission, Options>(methods, options);\n}\n","import { createRef, type RefObject } from 'react';\n\n/**\n * Create a React ref object that is friendly for snapshots.\n * It will be represented as `[React.ref]` in snapshots.\n * @returns A React ref object.\n */\nexport function createSnapshotFriendlyRef<T>(): RefObject<T | null> {\n return createRef<T>();\n}\n","'use client';\n\nimport type { DependencyList } from 'react';\nimport { useEffect, useMemo, useRef } from 'react';\n\nimport type { SharedObject } from '../ts-declarations/SharedObject';\n\n/**\n * Returns a shared object, which is automatically cleaned up when the component is unmounted.\n */\nexport function useReleasingSharedObject<TSharedObject extends SharedObject>(\n factory: () => TSharedObject,\n dependencies: DependencyList\n): TSharedObject {\n const objectRef = useRef<TSharedObject | null>(null);\n const objectRefToRelease = useRef<TSharedObject | null>(null);\n const isFastRefresh = useRef(false);\n const previousDependencies = useRef<DependencyList>(dependencies);\n\n if (objectRef.current == null) {\n objectRef.current = factory();\n }\n\n const object = useMemo(() => {\n let newObject = objectRef.current;\n const dependenciesAreEqual =\n previousDependencies.current?.length === dependencies.length &&\n dependencies.every((value, index) => value === previousDependencies.current[index]);\n\n // If the dependencies have changed, schedule the previous object for release and create a new one,\n // otherwise this has been called because of an unrelated fast refresh, and we don't want to release the object.\n if (!newObject || !dependenciesAreEqual) {\n objectRefToRelease.current = objectRef.current;\n newObject = factory();\n objectRef.current = newObject;\n previousDependencies.current = dependencies;\n }\n return newObject;\n }, dependencies);\n\n useEffect(() => {\n // When the object changes, release the previous one - it is important to do this in a useEffect, so that we don't release\n // the object during render.\n if (objectRefToRelease.current) {\n objectRefToRelease.current.release();\n objectRefToRelease.current = null;\n }\n }, [object]);\n\n useMemo(() => {\n isFastRefresh.current = true;\n }, []);\n\n useEffect(() => {\n isFastRefresh.current = false;\n\n return () => {\n // This will be called on every fast refresh and on unmount, but we only want to release the object on unmount.\n if (!isFastRefresh.current && objectRef.current) {\n objectRef.current.release();\n }\n };\n }, []);\n\n return object;\n}\n","/**\n * Reloads the app. This method works for both release and debug builds.\n *\n * Unlike [`Updates.reloadAsync()`](/versions/latest/sdk/updates/#updatesreloadasync),\n * this function does not use a new update even if one is available. It only reloads the app using the same JavaScript bundle that is currently running.\n *\n * @param reason The reason for reloading the app. This is used only for some platforms.\n */\nexport async function reloadAppAsync(reason: string = 'Reloaded from JS call'): Promise<void> {\n await globalThis.expo?.reloadAppAsync(reason);\n}\n","import './ts-declarations/global';\nimport './sweet/setUpJsLogger.fx';\nimport './polyfill';\n\nexport type * from './ts-declarations/global';\n\nexport { EventEmitter, type EventSubscription } from './EventEmitter';\nexport { NativeModule } from './NativeModule';\nexport { SharedObject } from './SharedObject';\nexport { SharedRef } from './SharedRef';\n\nexport { default as Platform } from './Platform';\nexport { default as uuid } from './uuid';\n\nexport type { ProxyNativeModule } from './NativeModulesProxy.types';\nexport { requireNativeViewManager } from './NativeViewManagerAdapter';\n\nexport * from './requireNativeModule';\nexport * from './registerWebModule';\nexport * from './TypedArrays.types';\n\nexport * from './PermissionsInterface';\nexport * from './PermissionsHook';\n\nexport * from './Refs';\n\nexport * from './hooks/useReleasingSharedObject';\nexport * from './reload';\n\n// Errors\nexport { CodedError } from './errors/CodedError';\nexport { UnavailabilityError } from './errors/UnavailabilityError';\n\n// Deprecated\nexport { LegacyEventEmitter } from './LegacyEventEmitter';\nexport { default as NativeModulesProxy } from './NativeModulesProxy';\n\nexport { installOnUIRuntime } from './worklets';\n","import type { ExpoConfig } from 'expo/config';\nimport type {\n EASConfig as ManifestsEASConfig,\n ExpoGoConfig as ManifestsExpoGoConfig,\n ExpoUpdatesManifest,\n EmbeddedManifest,\n ManifestAsset as ManifestAssetForReExport,\n ManifestExtra as ManifestExtraForReExport,\n ClientScopingConfig as ClientScopingConfigForReExport,\n ExpoGoPackagerOpts as ExpoGoPackagerOptsForReExport,\n // @ts-ignore -- optional interface, will gracefully degrade to `any` not installed\n} from 'expo-manifests';\n\nexport enum AppOwnership {\n /**\n * The experience is running inside the Expo Go app.\n * @deprecated Use [`Constants.executionEnvironment`](#executionenvironment) instead.\n */\n Expo = 'expo',\n}\n\n/**\n * Identifies where the app's JavaScript bundle is currently running.\n */\nexport enum ExecutionEnvironment {\n /** A project that includes native project directories that you maintain directly in your\n * [existing React Native project](/bare/overview/).\n */\n Bare = 'bare',\n /** Production/release build created with or without EAS Build. */\n Standalone = 'standalone',\n /** Expo Go or a development build built with `expo-dev-client`. */\n StoreClient = 'storeClient',\n}\n\n// @needsAudit\n/**\n * Current supported values are `handset`, `tablet`, `desktop` and `tv`. CarPlay will show up\n * as `unsupported`.\n */\nexport enum UserInterfaceIdiom {\n Handset = 'handset',\n Tablet = 'tablet',\n Desktop = 'desktop',\n TV = 'tv',\n Unsupported = 'unsupported',\n}\n\n// @needsAudit\n/**\n * @platform ios\n */\nexport type IOSManifest = {\n /**\n * The build number specified in the embedded **Info.plist** value for `CFBundleVersion` in this app.\n * In a standalone app, you can set this with the `ios.buildNumber` value in **app.json**. This\n * may differ from the value in `Constants.expoConfig.ios.buildNumber` because the manifest\n * can be updated, whereas this value will never change for a given native binary.\n * The value is set to `null` in case you run your app in Expo Go.\n */\n buildNumber: string | null;\n /**\n * The Apple internal model identifier for this device.\n * @example\n * `iPhone1,1`\n * @deprecated Use `expo-device`'s [`Device.modelId`](./device/#devicemodelid).\n */\n platform: string;\n /**\n * The human-readable model name of this device. For example, `\"iPhone 7 Plus\"` if it can be determined,\n * otherwise will be `null`.\n * @deprecated Moved to `expo-device` as [`Device.modelName`](./device/#devicemodelname).\n */\n model: string | null;\n /**\n * The user interface idiom of the current device, such as whether the app is running on an iPhone, iPad, Mac or Apple TV.\n * @deprecated Use `expo-device`'s [`Device.getDeviceTypeAsync()`](./device/#devicegetdevicetypeasync).\n */\n userInterfaceIdiom: UserInterfaceIdiom;\n /**\n * The version of iOS running on this device.\n * @example\n * `10.3`\n * @deprecated Use `expo-device`'s [`Device.osVersion`](./device/#deviceosversion).\n */\n systemVersion: string;\n} & Record<string, any>;\n\n// @needsAudit\n/**\n * @platform android\n */\nexport type AndroidManifest = {\n /**\n * The version code set by `android.versionCode` in app.json.\n * The value is set to `null` in case you run your app in Expo Go.\n * @deprecated Use `expo-application`'s [`Application.nativeBuildVersion`](./application/#applicationnativebuildversion).\n */\n versionCode: number;\n} & Record<string, any>;\n\n/**\n * @platform web\n */\nexport type WebManifest = Record<string, any>;\n\n// type re-exports to prevent breaking change\n\nexport type ManifestAsset = ManifestAssetForReExport;\nexport type Manifest = ExpoUpdatesManifest;\nexport type ManifestExtra = ManifestExtraForReExport;\nexport type EASConfig = ManifestsEASConfig;\nexport type ClientScopingConfig = ClientScopingConfigForReExport;\nexport type ExpoGoConfig = ManifestsExpoGoConfig;\nexport type ExpoGoPackagerOpts = ExpoGoPackagerOptsForReExport;\n\n// @needsAudit @docsMissing\nexport type PlatformManifest = {\n ios?: IOSManifest;\n android?: AndroidManifest;\n web?: WebManifest;\n detach?: {\n scheme?: string;\n [key: string]: any;\n };\n scheme?: string;\n hostUri?: string;\n developer?: string;\n} & Record<string, any>;\n\n// @needsAudit @docsMissing\nexport type NativeConstants = {\n /**\n * @hidden\n */\n name: 'ExponentConstants';\n /**\n * Returns `expo` when running in Expo Go, otherwise `null`.\n * @deprecated Use [`Constants.executionEnvironment`](#executionenvironment) instead.\n */\n appOwnership: AppOwnership | null;\n /**\n * Returns `true` when the app is running in debug mode (`__DEV__`). Otherwise, returns `false`.\n */\n debugMode: boolean;\n /**\n * A human-readable name for the device type.\n */\n deviceName?: string;\n /**\n * The [device year class](https://github.com/facebook/device-year-class) of this device.\n * @deprecated Moved to `expo-device` as [`Device.deviceYearClass`](./device/#deviceyearclass).\n */\n deviceYearClass: number | null;\n /**\n * Returns the current execution environment.\n */\n executionEnvironment: ExecutionEnvironment;\n experienceUrl: string;\n /**\n * Nullable only on the web.\n */\n expoRuntimeVersion: string | null;\n /**\n * The version string of the Expo Go app currently running.\n * Returns `null` in existing React Native projects and on web.\n */\n expoVersion: string | null;\n isDetached?: boolean;\n intentUri?: string;\n /**\n * Returns `true` if the app is running in headless mode. Otherwise, returns `false`.\n */\n isHeadless: boolean;\n linkingUri: string;\n\n /**\n * @hidden\n * Manifest embedded in the build. Returns `null` when `manifest2` is non-null.\n * @deprecated Use `Constants.expoConfig` instead, which behaves more consistently across EAS Build\n * and EAS Update.\n */\n manifest: EmbeddedManifest | null;\n /**\n * Manifest for Expo apps using modern Expo Updates from a remote source, such as apps that\n * use EAS Update. `Constants.expoConfig` should be used for accessing the Expo config object.\n */\n manifest2: ExpoUpdatesManifest | null;\n /**\n * The standard Expo config object defined in **app.json** and **app.config.js** files. For both\n * classic and modern manifests, whether they are embedded or remote.\n */\n expoConfig:\n | (ExpoConfig & {\n /**\n * Only present during development using @expo/cli.\n */\n hostUri?: string;\n })\n | null;\n /**\n * The standard Expo Go config object populated when running in Expo Go.\n */\n expoGoConfig: ManifestsExpoGoConfig | null;\n /**\n * The standard EAS config object populated when using EAS.\n */\n easConfig: ManifestsEASConfig | null;\n /**\n * A string that is unique to the current session of your app. It is different across apps and\n * across multiple launches of the same app.\n */\n sessionId: string;\n /**\n * The default status bar height for the device. Does not factor in changes when location tracking\n * is in use or a phone call is active.\n */\n statusBarHeight: number;\n /**\n * A list of the system font names available on the current device.\n */\n systemFonts: string[];\n systemVersion?: number;\n /**\n * @hidden\n */\n supportedExpoSdks?: string[];\n /**\n * Returns the specific platform manifest object.\n *\n * > **Note**: This is distinct from the `manifest` and `manifest2`.\n */\n platform?: PlatformManifest;\n /**\n * Gets the user agent string which would be included in requests sent by a web view running on\n * this device. This is probably not the same user agent you might be providing in your JS `fetch`\n * requests.\n */\n getWebViewUserAgentAsync: () => Promise<string | null>;\n} & Record<string, any>;\n\n/**\n * @hidden\n */\nexport type Constants = NativeConstants & {\n /**\n * > **Warning**: Do not use this property. Use `manifest` by default.\n *\n * In certain cases accessing manifest via this property\n * suppresses important warning about missing manifest.\n */\n __unsafeNoWarnManifest?: EmbeddedManifest;\n /**\n * > **Warning**: Do not use this property. Use `manifest2` by default.\n *\n * In certain cases accessing manifest via this property\n * suppresses important warning about missing manifest.\n */\n __unsafeNoWarnManifest2?: ExpoUpdatesManifest;\n};\n","import { requireOptionalNativeModule } from 'expo-modules-core';\n\nexport default requireOptionalNativeModule('ExponentConstants');\n","// TODO(@kitten): Add missing optional peers\n\nimport type { ExpoConfig } from 'expo/config';\n// @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\nimport type {\n EmbeddedManifest,\n EASConfig,\n ExpoGoConfig,\n ExpoUpdatesManifest,\n // @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\n} from 'expo-manifests';\nimport { CodedError, requireOptionalNativeModule } from 'expo-modules-core';\n// @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\nimport type { Manifest as UpdatesManifest, ExpoUpdatesModule } from 'expo-updates';\nimport { Platform, NativeModules } from 'react-native';\n\nimport { type Constants, ExecutionEnvironment } from './Constants.types';\nimport ExponentConstants from './ExponentConstants';\ntype DevLauncherManifest = ExpoUpdatesManifest;\n\nexport {\n type AndroidManifest,\n AppOwnership,\n type Constants,\n ExecutionEnvironment,\n type IOSManifest,\n type NativeConstants,\n type PlatformManifest,\n UserInterfaceIdiom,\n type WebManifest,\n} from './Constants.types';\n\nif (!ExponentConstants) {\n console.warn(\n \"No native ExponentConstants module found, are you sure the expo-constants's module is linked properly?\"\n );\n}\n\nconst ExpoUpdates = requireOptionalNativeModule<ExpoUpdatesModule>('ExpoUpdates');\n\nlet rawUpdatesManifest: UpdatesManifest | null = null;\n// If expo-updates defines a non-empty manifest, prefer that one\nif (ExpoUpdates) {\n let updatesManifest: object | undefined;\n if (ExpoUpdates.manifest) {\n updatesManifest = ExpoUpdates.manifest;\n } else if (ExpoUpdates.manifestString) {\n updatesManifest = JSON.parse(ExpoUpdates.manifestString);\n }\n if (updatesManifest && Object.keys(updatesManifest).length > 0) {\n rawUpdatesManifest = updatesManifest as any;\n }\n}\n\n// If dev-launcher defines a non-empty manifest, prefer that one\nlet rawDevLauncherManifest: DevLauncherManifest | null = null;\nif (NativeModules.EXDevLauncher) {\n let devLauncherManifest;\n if (NativeModules.EXDevLauncher.manifestString) {\n devLauncherManifest = JSON.parse(NativeModules.EXDevLauncher.manifestString);\n }\n\n if (devLauncherManifest && Object.keys(devLauncherManifest).length > 0) {\n rawDevLauncherManifest = devLauncherManifest as any;\n }\n}\n\n// Fall back to ExponentConstants.manifest if we don't have one from Updates\nlet rawAppConfig: ExpoConfig | null = null;\nif (ExponentConstants && ExponentConstants.manifest) {\n const appConfig: object | string = ExponentConstants.manifest;\n\n // On Android we pass the manifest in JSON form so this step is necessary\n if (typeof appConfig === 'string') {\n rawAppConfig = JSON.parse(appConfig);\n } else {\n rawAppConfig = appConfig as any;\n }\n}\n\ntype RawManifest = UpdatesManifest | DevLauncherManifest | ExpoConfig;\nlet rawManifest: RawManifest | null = rawUpdatesManifest ?? rawDevLauncherManifest ?? rawAppConfig;\n\nconst { name, appOwnership, ...nativeConstants } = (ExponentConstants || {}) as any;\n\nconst constants: Constants = {\n ...nativeConstants,\n // Ensure this is null in bare workflow\n appOwnership: appOwnership ?? null,\n};\n\nObject.defineProperties(constants, {\n /**\n * Use `manifest` property by default.\n * This property is only used for internal purposes.\n * It behaves similarly to the original one, but suppresses warning upon no manifest available.\n * `expo-asset` uses it to prevent users from seeing mentioned warning.\n */\n __unsafeNoWarnManifest: {\n get(): EmbeddedManifest | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: false,\n },\n __unsafeNoWarnManifest2: {\n get(): ExpoUpdatesManifest | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: false,\n },\n manifest: {\n get(): EmbeddedManifest | null {\n const maybeManifest = getManifest();\n if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: true,\n },\n manifest2: {\n get(): ExpoUpdatesManifest | null {\n const maybeManifest = getManifest();\n if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: true,\n },\n expoConfig: {\n get():\n | (ExpoConfig & {\n /**\n * Only present during development using @expo/cli.\n */\n hostUri?: string;\n })\n | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n // if running an embedded update, maybeManifest is a EmbeddedManifest which doesn't have\n // the expo config. Instead, the embedded expo-constants app.config should be used.\n if (ExpoUpdates && ExpoUpdates.isEmbeddedLaunch) {\n return rawAppConfig;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.expoClient ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n expoGoConfig: {\n get(): ExpoGoConfig | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.expoGo ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n easConfig: {\n get(): EASConfig | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.eas ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n __rawManifest_TEST: {\n get(): RawManifest | null {\n return rawManifest;\n },\n set(value: RawManifest | null) {\n rawManifest = value;\n },\n enumerable: false,\n },\n});\n\nfunction isEmbeddedManifest(manifest: RawManifest): manifest is EmbeddedManifest {\n return !isExpoUpdatesManifest(manifest);\n}\n\nfunction isExpoUpdatesManifest(manifest: RawManifest): manifest is ExpoUpdatesManifest {\n return 'metadata' in manifest;\n}\n\nfunction getManifest(suppressWarning = false): RawManifest | null {\n if (!rawManifest) {\n const invalidManifestType = rawManifest === null ? 'null' : 'undefined';\n if (\n nativeConstants.executionEnvironment === ExecutionEnvironment.Bare &&\n Platform.OS !== 'web'\n ) {\n if (!suppressWarning) {\n console.warn(\n `Constants.manifest is ${invalidManifestType} because the embedded app.config could not be read. Ensure that you have installed the expo-constants build scripts if you need to read from Constants.manifest.`\n );\n }\n } else if (\n nativeConstants.executionEnvironment === ExecutionEnvironment.StoreClient ||\n nativeConstants.executionEnvironment === ExecutionEnvironment.Standalone\n ) {\n // If we somehow get here, this is a truly exceptional state to be in.\n // Constants.manifest should *always* be defined in those contexts.\n throw new CodedError(\n 'ERR_CONSTANTS_MANIFEST_UNAVAILABLE',\n `Constants.manifest is ${invalidManifestType}, must be an object.`\n );\n }\n }\n return rawManifest;\n}\n\nexport default constants as Constants;\n","/**\n * transport.ts — kit → Wire server requests for the review module, all fire-and-forget\n * (analytics/reviews must never break the app). Mirrors analytics/reportClientEvent: a\n * thin fetch wrapper, Bearer tenant key, swallow every error.\n *\n * • submitReview → POST {serverUrl}/v1/reviews (the review row)\n * • fetchReviewDecision → GET {serverUrl}/v1/reviews/decision (best-effort, the AI seam)\n * • reportAppEvent → POST {serverUrl}/v1/events (generic app.* namespace)\n *\n * `reportAppEvent` is the strategic extension: it lets a host report arbitrary in-app\n * events through the SAME transport (stored server-side as event_type='app_event',\n * question_key=<name>), which is what the backend review-firing rules evaluate on — and\n * it seeds the broader app-analytics stream. Keep payloads minimal + non-PII.\n */\nimport type { ReviewDecisionResponse, ReviewSubmission, ReviewTarget } from \"./types\";\n\n/**\n * POST a review (the 1-4 feedback path). Fire-and-forget: a missing target, a build error,\n * a missing `fetch`, or a network failure is swallowed and the call returns immediately.\n */\nexport const submitReview = (\n target: ReviewTarget | undefined,\n review: ReviewSubmission,\n): void => {\n if (!target?.serverUrl) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/reviews`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(review),\n }).catch(() => {\n /* best-effort, swallow */\n });\n } catch {\n /* URL/JSON/missing-fetch — swallow */\n }\n};\n\n/**\n * Options for the best-effort review decision fetch.\n *\n * ── WHAT THE DEPLOYED SERVER ACTUALLY READS (verified 2026-07-17) ────────────────────────\n *\n * `GET /v1/reviews/decision` declares exactly two query params — `session_id` and\n * `device_key` — plus the `Authorization` header. That is the whole wire. Verified against\n * the deployed OpenAPI schema, not against intent.\n *\n * This type is CLOSED on purpose. Hosts that hand-rolled this fetch invented `user_id` and\n * `session_count` query params believing \"the server ignores what it doesn't read, so passing\n * it is always safe\". Both are no-ops: the route declares neither. `session_count` is real, but\n * only on the questionnaire POST body — which is precisely how it copy-pasted its way into a\n * reviews call site and sat there doing nothing. They cost a wire lie — a call site that reads as though\n * identity and a session counter reach the firing brain when neither does. So they are not\n * offered here. Pass identity as `deviceKey`; the session count the server reasons about is the\n * one IT derives from the event stream keyed by `deviceKey`, not one the client asserts.\n *\n * The client-side session floor is a LOCAL rule, not a wire param: use `ReviewConfig.minSessions`\n * (evaluated by `useReviewGate` against the kit's own `wire_review_<id>_sessions` counter).\n */\nexport interface FetchReviewDecisionOptions {\n /**\n * The onboarding session id, when there IS one. OPTIONAL on purpose: the review gate lives on\n * the home feed, where a user legitimately has no onboarding session. `deviceKey` is the real\n * identity for this call. (The server relaxed `session_id` to optional on 2026-07-16 and the\n * relaxation IS deployed — the route no longer 422s without it. Permissive wire: do NOT make\n * this required here.)\n */\n sessionId?: string;\n /**\n * A stable, non-PII device id — THE identity for this call. The decision endpoint reads it for\n * cooldown + min-sessions, and it is the key the server groups a device's events under. A host\n * whose own identity is a user id passes that id here rather than reaching for a `user_id`\n * param the route does not declare.\n */\n deviceKey?: string;\n}\n\n/**\n * Best-effort fetch of the SERVER's review firing decision. The mirror of\n * `fetchQuestionnaireDecision`, and the primitive whose absence caused a live incident.\n *\n * ── WHY THIS LIVES IN THE KIT (Malik, 2026-07-16) ────────────────────────────────────────\n *\n * The questionnaire module has always had its decision fetch; reviews never did. So a host\n * hand-rolled one, and got it subtly wrong: its helper collapsed an explicit `{fire:false}`\n * into `undefined`. `decideReview` is `(local, decision) => decision ?? local`, so `undefined`\n * means \"the server has no opinion, use the local rules\" — and the local timer fired. The\n * server could therefore only ever turn review prompts ON, never OFF. A real user was asked to\n * rate the app ~3 minutes into their FIRST session, having seen nothing yet, and left 1 star.\n *\n * The bug was not that the host was careless. It was that the kit made every host invent this.\n * So the primitive moves here and hosts keep a thin call site.\n *\n * ── THE CONTRACT THAT MATTERS ────────────────────────────────────────────────────────────\n *\n * • 2xx → the FULL `{fire, reason, arm}`, INCLUDING `fire:false`. Never collapse a false\n * into null. That collapse IS the bug: a false must reach `decideReview` intact so\n * it can override the local rules and keep the gate shut.\n * • else → null, and ONLY then. Null means \"the server genuinely has no opinion\", which is\n * the one case where falling back to local rules is correct.\n *\n * Never throws: unreachable, non-2xx, bad JSON, or a missing `fetch` all resolve to null. The\n * kit does not call this internally; a host awaits it and passes the result straight to\n * `useReviewGate({ decision })`.\n *\n * ── DON'T RACE THIS AGAINST A LOCAL TIMER ────────────────────────────────────────────────\n *\n * The return type is `ReviewDecisionResponse`, which carries `arm` alongside `{fire, reason}`.\n * Hand the WHOLE object to the gate and echo `arm` into the submission's `meta.firing_arm`;\n * narrowing it to `{fire, reason}` on the way through silently kills per-arm attribution\n * across a reweighting of the experiment.\n *\n * A host that starts its own dwell timer in parallel with this fetch has built a race a slow\n * server loses: the timer fires, the local rules show the prompt, and the `{fire:false}` still\n * in flight arrives too late to stop it. Do not hand-roll that. `useReviewGate` already owns\n * the wait — set `ReviewConfig.timeoutFallbackMs` and the local rules stay parked until either\n * the decision lands or the window expires, whichever comes first.\n *\n * const decision = await fetchReviewDecision(target, { deviceKey });\n * const gate = useReviewGate({\n * config: { id: \"home\", minSessions: 2, timeoutFallbackMs: 3000 },\n * decision: decision ?? undefined, // pass it whole — keep `arm`\n * storage,\n * });\n */\nexport const fetchReviewDecision = async (\n target: ReviewTarget | undefined,\n options: FetchReviewDecisionOptions = {},\n): Promise<ReviewDecisionResponse | null> => {\n if (!target?.serverUrl) return null;\n try {\n const base = target.serverUrl.replace(/\\/$/, \"\");\n const params = new URLSearchParams();\n if (options.sessionId) params.set(\"session_id\", options.sessionId);\n if (options.deviceKey) params.set(\"device_key\", options.deviceKey);\n const qs = params.toString();\n const url = `${base}/v1/reviews/decision${qs ? `?${qs}` : \"\"}`;\n const headers: Record<string, string> = {};\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n const res = await fetch(url, { headers });\n if (!res || !res.ok) return null;\n const json = (await res.json()) as ReviewDecisionResponse | null;\n // A body without a boolean `fire` is not a decision. Guard it explicitly rather than\n // letting `{}` through as a truthy object that `decideReview` would treat as a verdict\n // (`{}.fire === undefined` is falsy, so it would silently read as \"never fire\").\n if (!json || typeof json.fire !== \"boolean\") return null;\n return json;\n } catch {\n /* unreachable / non-2xx / bad JSON / missing-fetch → the server has no opinion */\n return null;\n }\n};\n\n/** Options for a reported app event. `deviceKey` groups a device's sessions server-side. */\nexport interface ReportAppEventOptions {\n /** The onboarding/session id to correlate with, when known. */\n sessionId?: string;\n /** A stable, non-PII device id — the review-decision endpoint reads it for min-sessions. */\n deviceKey?: string;\n /** Small non-PII extras. */\n meta?: Record<string, unknown>;\n}\n\n/**\n * Report a generic in-app event through the existing events transport. Stored server-side\n * as `event_type='app_event'`, `question_key=<name>`. Fire-and-forget. Keep `name` a short\n * stable identifier and `meta` small + non-PII.\n *\n * reportAppEvent(target, \"content_share\", { sessionId, deviceKey });\n */\nexport const reportAppEvent = (\n target: ReviewTarget | undefined,\n name: string,\n options: ReportAppEventOptions = {},\n): void => {\n if (!target?.serverUrl || !name) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n const event: Record<string, unknown> = {\n event_type: \"app_event\",\n question_key: name,\n };\n if (options.sessionId) event.session_id = options.sessionId;\n // device_key rides in the non-PII user_context bucket the server sanitizes; the\n // review-decision endpoint reads it to group a device's sessions.\n if (options.deviceKey) event.user_context = { device_key: options.deviceKey };\n if (options.meta && Object.keys(options.meta).length > 0) {\n event.meta = JSON.stringify(options.meta);\n }\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events: [event] }),\n }).catch(() => {\n /* best-effort, swallow */\n });\n } catch {\n /* swallow */\n }\n};\n","/**\n * screenTracking — an OPT-IN, dependency-free automatic screen-view helper.\n *\n * Given the host app's navigation STATE (or a nav ref, via the useScreenTracking hook), this\n * emits exactly ONE `screen` app-event per REAL screen change through the kit's existing\n * `reportAppEvent` transport (`POST {serverUrl}/v1/events`, `event_type='app_event'`,\n * `question_key='screen'`, `meta={ screen }`). Param-only changes and re-renders are de-duped\n * away because we resolve and compare the route NAME only — never the params.\n *\n * Dependency-free core: this file imports NO navigation library. React-Navigation / expo-router\n * are host concerns; the host supplies plain state objects and refs, typed structurally here\n * (`NavigationStateLike`). It is also React-free — the optional React glue lives in\n * `useScreenTracking.ts`. `reportAppEvent` is imported from the pure `../reviews/transport`\n * module (NOT the `../reviews` barrel, which would drag the review UI into an analytics-only\n * bundle and defeat tree-shaking).\n *\n * Privacy: only the route NAME ever leaves the device. Route params, query strings, and any\n * user data are never read into the event. Fire-and-forget — this never throws into the UI.\n */\nimport { reportAppEvent } from \"../reviews/transport\";\n\n/** A single route inside a React-Navigation-shaped state (structural — no `@react-navigation`). */\nexport interface NavigationRouteLike {\n name: string;\n /** A nested navigator's own state, when this route hosts one. */\n state?: NavigationStateLike;\n /** Route params are intentionally left `unknown` — this helper never reads them. */\n params?: unknown;\n}\n\n/** A React-Navigation-shaped navigator state (structural type; no library import). */\nexport interface NavigationStateLike {\n /** Index of the active route within `routes`. */\n index?: number;\n routes?: NavigationRouteLike[];\n}\n\n/** Options for {@link createScreenTracker}. */\nexport interface ScreenTrackerOptions {\n /**\n * Where to POST. `{ serverUrl, apiKey }` — same shape the kit's review/analytics config\n * exposes. When omitted, the tracker still de-dups and fires `onScreen`, but sends nothing.\n */\n target?: { serverUrl: string; apiKey: string };\n /** The onboarding/session id to correlate screen views with, when known. */\n sessionId?: string;\n /** A stable, non-PII device id — groups a device's sessions server-side. */\n deviceKey?: string;\n /** Called on every REAL screen change (after de-dup), before the network emit. */\n onScreen?: (screen: string) => void;\n /**\n * Per-screen filter. Return `false` to skip the NETWORK emit for a screen (last-screen memory\n * is still advanced + `onScreen` still fires) — e.g. to keep a sensitive route out of analytics.\n */\n shouldTrack?: (screen: string) => boolean;\n}\n\n/** The screen tracker returned by {@link createScreenTracker}. */\nexport interface ScreenTracker {\n /** Report the active screen. Ignores `undefined`/empty and de-dups repeats of the last screen. */\n track: (screen: string | undefined) => void;\n /** Clear the last-screen memory (e.g. on logout) so the next `track` always emits. */\n reset: () => void;\n}\n\n/**\n * Walk a React-Navigation-shaped state to the DEEPEST active route and return its NAME (never\n * its params). Recurses `routes[index]` while a nested `.state` exists. Returns `undefined` for\n * a missing/empty/malformed state — the caller treats that as \"nothing to report\".\n */\nexport const getActiveRouteName = (\n state: NavigationStateLike | undefined,\n): string | undefined => {\n let current: NavigationStateLike | undefined = state;\n let name: string | undefined;\n // Bounded by the finite nesting depth of a real navigator tree.\n while (current && Array.isArray(current.routes) && current.routes.length > 0) {\n const index = typeof current.index === \"number\" ? current.index : 0;\n const route = current.routes[index];\n if (!route) break;\n name = route.name;\n current = route.state;\n }\n return name;\n};\n\n/**\n * Build a stateful screen tracker. `track` de-dups against the last reported screen so only a\n * REAL change emits; `reset` clears that memory. Fire-and-forget throughout — a missing `target`\n * skips the network but keeps the de-dup + `onScreen` behaviour intact.\n */\nexport const createScreenTracker = (options: ScreenTrackerOptions = {}): ScreenTracker => {\n let lastScreen: string | undefined;\n return {\n track: (screen: string | undefined): void => {\n if (!screen || screen === lastScreen) return;\n lastScreen = screen;\n options.onScreen?.(screen);\n if (options.shouldTrack && !options.shouldTrack(screen)) return;\n reportAppEvent(options.target, \"screen\", {\n sessionId: options.sessionId,\n deviceKey: options.deviceKey,\n meta: { screen },\n });\n },\n reset: (): void => {\n lastScreen = undefined;\n },\n };\n};\n\n/**\n * Adapt a tracker into a React-Navigation `onStateChange` handler — the one-place wiring:\n *\n * <NavigationContainer onStateChange={screenTrackingHandler(tracker)}>\n *\n * It resolves the deepest active route name and hands it to `tracker.track` (which de-dups).\n */\nexport const screenTrackingHandler =\n (tracker: ScreenTracker) =>\n (state: NavigationStateLike | undefined): void =>\n tracker.track(getActiveRouteName(state));\n","/**\n * useScreenTracking — a THIN optional React hook over the pure screen-tracking core.\n *\n * It builds one tracker for the component's lifetime and subscribes to the host's navigation\n * ref: it reports the current route on mount and on every `state` event, and unsubscribes on\n * unmount. React is a REQUIRED peer of the kit, so importing it here is allowed; the hook adds\n * NO navigation-library dependency — the ref is typed structurally (`NavigationRefLike`).\n *\n * const navigationRef = useNavigationContainerRef(); // host's @react-navigation ref\n * useScreenTracking(navigationRef, { target, sessionId });\n * // ...<NavigationContainer ref={navigationRef}>\n */\nimport { useEffect, useRef } from \"react\";\n\nimport { createScreenTracker, type ScreenTracker, type ScreenTrackerOptions } from \"./screenTracking\";\n\n/**\n * The structural slice of a React-Navigation container ref this hook needs — no\n * `@react-navigation` import. `getCurrentRoute` yields the active route; `addListener(\"state\", …)`\n * fires on every navigation state change and returns its own unsubscribe.\n */\nexport interface NavigationRefLike {\n getCurrentRoute?: () => { name?: string } | undefined;\n addListener?: (type: \"state\", callback: () => void) => () => void;\n}\n\n/**\n * Subscribe screen tracking to a host navigation ref. Safe to call with a not-yet-ready ref\n * (the effect no-ops until `addListener` exists). Returns nothing — it wires side effects only.\n */\nexport const useScreenTracking = (\n navigationRef: NavigationRefLike | undefined,\n options: ScreenTrackerOptions = {},\n): void => {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // One tracker per mount; kept in a ref so re-renders never rebuild the de-dup memory.\n const trackerRef = useRef<ScreenTracker | undefined>(undefined);\n if (!trackerRef.current) {\n const dynamicOptions: ScreenTrackerOptions = {\n get target() {\n return optionsRef.current.target;\n },\n get sessionId() {\n return optionsRef.current.sessionId;\n },\n get deviceKey() {\n return optionsRef.current.deviceKey;\n },\n get onScreen() {\n return optionsRef.current.onScreen;\n },\n get shouldTrack() {\n return optionsRef.current.shouldTrack;\n },\n };\n trackerRef.current = createScreenTracker(dynamicOptions);\n }\n\n useEffect(() => {\n const tracker = trackerRef.current;\n if (!tracker || !navigationRef?.addListener) return;\n const report = (): void => tracker.track(navigationRef.getCurrentRoute?.()?.name);\n report(); // initial screen on mount\n const unsubscribe = navigationRef.addListener(\"state\", report);\n return unsubscribe;\n // Re-subscribe only when the ref identity changes; option changes are read live off the closure.\n }, [navigationRef]);\n};\n","/**\n * reportClientEvent — forward DEVICE-ONLY onboarding events to the Wire AI analytics\n * backend (`POST {serverUrl}/v1/events`), completing the funnel for events the server\n * can't observe on its own.\n *\n * The backend already records the server-observable funnel during the A2A flow\n * (`session_started`, `screen_shown`, `answer_submitted`, `completed`, `llm_fallback`,\n * and even `screen_skipped` — it derives that from the kit's skip sentinel). The one\n * event no server request can capture is `dropped`: the user closing the app / unmounting\n * the flow without finishing. That's what this reporter is for.\n *\n * Contract (server: routers/onboarding.py → analytics/events.py):\n * POST {serverUrl}/v1/events\n * Authorization: Bearer {apiKey}\n * { \"events\": [ { event_type, session_id, screen_index?, component?, question_key?,\n * latency_ms?, meta?, device?, user_context? } ] }\n * The server fills `app_id` + `environment` from the resolving key (never send app_id),\n * and silently skips malformed events — one bad payload never fails the batch.\n *\n * ⚠️ Correlation: `session_id` MUST equal the A2A `contextId` the server uses to key the\n * server-side events, or the funnel report (which groups by `session_id`) treats this as a\n * phantom session. See `makeSessionId` + WireOnboarding for how the kit seeds it.\n *\n * Fire-and-forget: this never throws into the UI and never awaits — analytics must never\n * be able to break onboarding.\n */\nimport type { DeviceContext } from \"../device/deviceContext\";\n\n/** Event types a CLIENT may report. The rest of the funnel is server-side; sending those\n * here would double-count. `screen_skipped` is included for completeness, but the kit does\n * NOT emit it — the backend already derives it from the skip sentinel (see OnboardingFlow).\n * `client_fallback` is emitted by the kit when the AI flow degrades to the static fallback,\n * so the dashboard's fallback-rate counts the whole-flow case (distinct from the server's\n * per-turn `llm_fallback`). The server back-fills a `session_started` for it if unseen.\n * This is the SINGLE fallback signal — hosts must NOT also report their own.\n * `identify` binds the host's opaque `user_id` to this `session_id` (late binding — the user\n * registered during/after onboarding). It carries no funnel weight; the server maps the\n * session to the user and back-fills a `session_started` if it never saw the session.\n * `app_event` is the host's own in-app event (the `createAnalytics` façade's `track`/`screen`\n * route through the offline queue as first-class `ClientEvent`s). The server already ingests\n * it — `reportAppEvent` (reviews/transport) has fired `event_type='app_event'` all along; this\n * widening just lets the same shape flow through the durable queue instead of a blind POST. */\nexport type ClientEventType =\n | \"screen_skipped\"\n | \"dropped\"\n | \"client_fallback\"\n | \"identify\"\n | \"app_event\";\n\n/** One client-reported event. Mirrors the server's `OnboardingEvent` (client-settable fields). */\nexport type ClientEvent = {\n event_type: ClientEventType;\n /** Must match the server-side A2A contextId for this onboarding (see makeSessionId). */\n session_id: string;\n /** 0-based index of the screen the event refers to (matches server `screen_shown`). */\n screen_index?: number;\n component?: string;\n question_key?: string;\n latency_ms?: number;\n /** JSON-stringified extras; the server stores it verbatim. */\n meta?: string;\n /**\n * Privacy-label-neutral device snapshot (platform / form factor / locale / host appVersion).\n * Sent as an object; the server sanitizes + persists it and derives a coarse country. Old\n * servers ignore this unknown field — fully backward compatible. See device/deviceContext.ts.\n */\n device?: DeviceContext;\n /**\n * Host-injected, non-PII context (signup method, referral, plan, hashed user id). Old servers\n * ignore it. MUST NOT contain PII like raw emails — see the README `userContext` section.\n */\n user_context?: Record<string, string | number | boolean>;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id, NOT an email/name). Required on\n * `identify`, optional (rides along) on other events. Trimmed + capped at 128 chars host-side.\n * Lets the backend reconcile onboarding sessions to real users. Old servers ignore it.\n */\n user_id?: string;\n};\n\n/** Where to POST. Derived from `WireOnboardingConfig` (`serverUrl` + `apiKey`). */\nexport type ClientEventTarget = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n};\n\n/**\n * A unique-per-onboarding session id. Used both as the client event `session_id` AND as the\n * seed the kit forwards to the backend so the SERVER adopts it as the A2A `contextId` — making\n * client and server agree (see WireOnboarding + the SDK-correlation note in the kit docs).\n * No crypto dependency: timestamp + random is collision-safe for a single device's onboarding.\n */\nexport const makeSessionId = (): string =>\n `wire_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n\n/**\n * POST one or more client events, fire-and-forget. A missing/invalid target, a build error,\n * a missing `fetch`, or a network failure is swallowed — the call returns immediately and the\n * request (if any) runs in the background.\n */\nexport const reportClientEvents = (\n target: ClientEventTarget | undefined,\n events: ClientEvent[],\n): void => {\n if (!target?.serverUrl || events.length === 0) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events }),\n }).catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // URL construction, JSON serialization, or a missing fetch — swallow.\n }\n};\n\n/** Convenience single-event wrapper around {@link reportClientEvents}. */\nexport const reportClientEvent = (\n target: ClientEventTarget | undefined,\n event: ClientEvent,\n): void => reportClientEvents(target, [event]);\n","/**\n * Canonical analytics names for the onboarding funnel. The kit already emits a typed\n * `OnboardingEvent` (`started | turn | error | retry | fallback`) — but one app logged them as\n * `onboarding_*` and another as `AI_ONBOARDING_*`, so the same funnel reads differently per app.\n * This maps the kit event to ONE canonical `wire_onboarding_*` name + params, and the app logs\n * it through whatever transport it already has (Firebase, Amplitude, console). The app still\n * owns the logger; only the NAMES are standardized.\n *\n * <WireOnboarding\n * onEvent={(e) => { const a = toAnalyticsEvent(e); logEvent(a.name, a.params); }}\n * onComplete={(r) => { logEvent(WIRE_ONBOARDING_EVENTS.completed, { answers: Object.keys(r.answers).length }); persist(r); }}\n * />\n *\n * `completed` has no kit `OnboardingEvent` (the kit signals completion via `onComplete`, not\n * `onEvent`) — the app logs it explicitly on `onComplete` using the constant below, so the\n * funnel name stays canonical.\n */\nimport type { OnboardingEvent } from \"../types\";\n\nexport const WIRE_ONBOARDING_EVENTS = {\n started: \"wire_onboarding_started\",\n /** A persisted session was restored after an app kill (fires instead of `started`). */\n resumed: \"wire_onboarding_resumed\",\n turn: \"wire_onboarding_turn\",\n error: \"wire_onboarding_error\",\n retry: \"wire_onboarding_retry\",\n fallback: \"wire_onboarding_fallback\",\n /** Logged by the host on `onComplete` (no matching kit `OnboardingEvent`). */\n completed: \"wire_onboarding_completed\",\n} as const;\n\nexport type WireOnboardingEventName =\n (typeof WIRE_ONBOARDING_EVENTS)[keyof typeof WIRE_ONBOARDING_EVENTS];\n\nexport type AnalyticsEvent = {\n name: WireOnboardingEventName;\n params?: Record<string, unknown>;\n};\n\n/**\n * Map a kit `OnboardingEvent` to its canonical `{ name, params }`. Exhaustive over the union\n * (the `never` default makes a new event type a compile error here — intentional).\n */\nexport const toAnalyticsEvent = (event: OnboardingEvent): AnalyticsEvent => {\n switch (event.type) {\n case \"started\":\n return { name: WIRE_ONBOARDING_EVENTS.started };\n case \"resumed\":\n return { name: WIRE_ONBOARDING_EVENTS.resumed };\n case \"turn\":\n return {\n name: WIRE_ONBOARDING_EVENTS.turn,\n params: { step: event.step, component: event.component },\n };\n case \"error\":\n return { name: WIRE_ONBOARDING_EVENTS.error, params: { reason: event.reason } };\n case \"retry\":\n return {\n name: WIRE_ONBOARDING_EVENTS.retry,\n params: { reason: event.reason, attempt: event.attempt },\n };\n case \"fallback\":\n return { name: WIRE_ONBOARDING_EVENTS.fallback, params: { reason: event.reason } };\n default: {\n const _exhaustive: never = event;\n return _exhaustive;\n }\n }\n};\n","/**\n * appVersion — best-effort, DEPENDENCY-FREE auto-detection of the host app's version string.\n *\n * WHY this exists: analytics segments the funnel `by_app_version`, but that breakdown is only\n * populated when a `device.appVersion` rides the event. `config.appVersion` (see types.ts) has\n * always been the way to supply it — but it is easy for a host to forget, and then the release\n * breakdown is silently empty. This module fills that gap: when the host does NOT pass a version,\n * the kit makes a best-effort read of the app version the host already ships in its Expo config,\n * so the breakdown works out of the box. An explicit `config.appVersion` always WINS over this.\n *\n * WHY it adds NO dependency (the kit's hard rule): `expo-constants` / `expo-application` are read\n * through a GUARDED require with a STRING-LITERAL specifier, inside a try/catch. Both halves are\n * required: the literal is what lets Metro COLLECT the dep, and the try/catch is what marks it\n * OPTIONAL, so an absent module becomes a `null` dependencyMap entry whose require throws \"Cannot\n * find module\" straight into the catch. (`withWireOnboarding` in metro/index.js adds a stub-to-\n * empty-module safety net for hosts that disable Metro's `allowOptionalDependencies`.) Nothing is\n * added to `package.json`; nothing is forced on the host.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) is not\n * \"lazier\" — it is broken: Metro collects dependencies statically, so a variable collects NOTHING,\n * the module never enters the bundle, and the aliased `require` is Metro's own numeric-id-keyed\n * `metroRequire`, which can never resolve a package-name string. That shape is why this function\n * returned `undefined` on every host despite `expo-constants` being installed, which silently\n * emptied the `by_app_version` breakdown this module exists to fill. See icons/expoIcons.ts for\n * the full autopsy, and reviews/storeReview.ts for the literal-specifier counter-example.\n *\n * PRIVACY: an app version string is not PII and identifies no user or device, so surfacing it\n * changes no App Privacy / Data Safety declaration (same guarantee as the rest of deviceContext).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n * Analytics must never be able to break onboarding.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real version string. */\nexport const coerceVersion = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * Every specifier below is a STRING LITERAL, because that is the only shape Metro's dependency\n * collector matches (callee literally `require`, argument literally a string). The `moduleName`\n * parameter exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name\n * resolves to undefined. See the header for why the old variable-specifier shape could not work.\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (typeof require !== \"function\") return undefined;\n try {\n switch (moduleName) {\n case \"expo-constants\":\n return require(\"expo-constants\");\n case \"expo-application\":\n return require(\"expo-application\");\n default:\n return undefined;\n }\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the host app version, preferring `expo-constants` (`expoConfig.version`, then\n * `nativeAppVersion`) and finally `expo-application` (`nativeApplicationVersion`). Returns the\n * first real string, or `undefined` when none of those are available. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native modules;\n * production defaults to the guarded runtime require above.\n */\nexport const detectAppVersion = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const constants = safeInterop(requireModule, \"expo-constants\");\n if (constants) {\n const expoConfig = constants.expoConfig;\n if (expoConfig && typeof expoConfig === \"object\") {\n const fromExpoConfig = coerceVersion((expoConfig as { version?: unknown }).version);\n if (fromExpoConfig) return fromExpoConfig;\n }\n const fromNative = coerceVersion(constants.nativeAppVersion);\n if (fromNative) return fromNative;\n }\n\n const application = safeInterop(requireModule, \"expo-application\");\n if (application) {\n const fromApplication = coerceVersion(application.nativeApplicationVersion);\n if (fromApplication) return fromApplication;\n }\n } catch {\n // Any unexpected read error → \"unknown\"; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceModel — best-effort, DEPENDENCY-FREE detection of the device MODEL on iOS.\n *\n * WHY this exists (the asymmetry it closes): `collectDeviceContext` already reports `device.model`\n * on Android straight from `Platform.constants.Model` (e.g. \"SM-G991B\"), but iOS `Platform.constants`\n * exposes NO model — only `osVersion` / `interfaceIdiom`. So the analytics `by_model` breakdown was\n * Android-only. This module fills the iOS gap with the SAME zero-dependency technique the kit already\n * uses for `appVersion` (see device/appVersion.ts): a GUARDED, STRING-LITERAL `require` of the common\n * Expo `expo-device` module, inside a try/catch — the literal is what lets Metro COLLECT the dep and\n * the try/catch is what marks it OPTIONAL, so an absent module degrades instead of failing the build.\n * (`withWireOnboarding` in metro/index.js adds a stub-to-empty-module safety net for hosts that\n * disable Metro's `allowOptionalDependencies`.) If the host has it, iOS gets a model out of the box;\n * if not, the read yields `undefined` and iOS `model` stays omitted — nothing is forced, and nothing\n * is added to `package.json`.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) collects\n * NOTHING under Metro's static dependency collector, so the module never enters the bundle and the\n * aliased `require` — really Metro's numeric-id-keyed `metroRequire` — can never resolve a package\n * name. See icons/expoIcons.ts for the full autopsy.\n *\n * WHY it is NOT PII: `expo-device`'s `modelName` (\"iPhone 14 Pro\") and `modelId` (\"iPhone15,2\") are a\n * device CLASS shared by millions of units — the same privacy category as the Android `Model` the kit\n * already sends. It is NOT a unique device id / IDFA / fingerprint, so surfacing it changes no App\n * Privacy / Data Safety declaration (identical guarantee to the rest of deviceContext). It deliberately\n * does NOT read `expo-device`'s `deviceName` (that is the user-set name, e.g. \"Malik's iPhone\", and IS\n * personal data).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real model string. */\nconst coerceModel = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * The specifier is a STRING LITERAL, because that is the only shape Metro's dependency collector\n * matches (callee literally `require`, argument literally a string). The `moduleName` parameter\n * exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name resolves to\n * undefined. (See the twin guard in ./appVersion.ts.)\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (moduleName !== \"expo-device\") return undefined;\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"expo-device\");\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are often consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the device model via `expo-device`, preferring the human-readable `modelName`\n * (\"iPhone 14 Pro\") and falling back to the identifier `modelId` (\"iPhone15,2\"). Returns the first\n * real string, or `undefined` when `expo-device` is absent. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native module;\n * production defaults to the guarded runtime require above.\n */\nexport const detectNativeModel = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const device = safeInterop(requireModule, \"expo-device\");\n if (device) {\n const modelName = coerceModel(device.modelName);\n if (modelName) return modelName;\n const modelId = coerceModel(device.modelId);\n if (modelId) return modelId;\n }\n } catch {\n // Any unexpected read error → undefined; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceContext — collect a small, privacy-label-neutral snapshot of the device so\n * onboarding analytics can segment the funnel (platform / form factor / locale) WITHOUT\n * adding a single dependency to the kit or changing a host app's App Privacy / Data Safety\n * declarations.\n *\n * HARD RULE (why this file adds no dependency):\n * The kit stays dependency-free. Everything here comes from `Platform`, `Dimensions`,\n * `I18nManager`, and the standard `Intl` global — plus a best-effort `appVersion` read via\n * `detectAppVersion()`, which itself adds NO dependency (it reaches for `expo-constants` /\n * `expo-application` through a guarded, variable-specifier require that a host without them\n * simply never resolves — see device/appVersion.ts). There are NO advertising IDs, NO\n * `getUniqueId`/IDFA/GAID/fingerprinting APIs, and nothing that would require a new\n * privacy-label entry. A host can adopt this without touching its store declarations.\n *\n * DEFENSIVE BY DESIGN: `collectDeviceContext()` never throws. Every read is guarded and\n * a missing/unavailable field is simply omitted (Hermes may ship without full `Intl`,\n * `Platform.constants` differs per OS and RN version, etc.). Analytics must never be able\n * to break onboarding.\n */\nimport { Dimensions, I18nManager, Platform } from \"react-native\";\n\nimport { detectAppVersion } from \"./appVersion\";\nimport { detectNativeModel } from \"./deviceModel\";\n\n/** Coarse device class. iOS uses the reported interface idiom; else a screen-size heuristic. */\nexport type DeviceFormFactor = \"phone\" | \"tablet\";\n\n/**\n * A privacy-label-neutral device snapshot. ALL fields except `platform` are optional and are\n * omitted when unavailable. Nothing here identifies a user or device uniquely.\n */\nexport type DeviceContext = {\n /** `Platform.OS` — \"ios\" | \"android\" | \"windows\" | \"macos\" | \"web\". Always present. */\n platform: typeof Platform.OS;\n /** OS version string (iOS `osVersion`/`Platform.Version`, Android `Release`). */\n osVersion?: string;\n /** Android device brand (e.g. \"samsung\"). Android only. */\n brand?: string;\n /**\n * Device model. On Android it is read directly from `Platform.constants.Model` (e.g. \"SM-G991B\").\n * iOS `Platform.constants` exposes NO model, so on iOS it is a BEST-EFFORT read of `expo-device`'s\n * `modelName` (\"iPhone 14 Pro\"), falling back to `modelId` (\"iPhone15,2\") — dependency-free via a\n * guarded require (see device/deviceModel.ts). ASYMMETRY: without `expo-device` installed, iOS\n * `model` is omitted (there is no dependency-free iOS model in the already-used RN surface, and the\n * kit will not add a native dep for it); Android needs no extra module. Not PII (a device class,\n * not a unique id), so it changes no privacy-label declaration.\n */\n model?: string;\n /** iOS interface idiom (\"phone\" | \"pad\" | …), when reported. iOS only. */\n interfaceIdiom?: string;\n /** Derived device class. */\n formFactor?: DeviceFormFactor;\n /** `Dimensions.get('screen')` width in dp. */\n screenWidth?: number;\n /** `Dimensions.get('screen')` height in dp. */\n screenHeight?: number;\n /** Screen pixel density (`scale`). */\n screenScale?: number;\n /** Right-to-left layout (`I18nManager.isRTL`). */\n isRTL?: boolean;\n /** Resolved locale (e.g. \"en-US\"), from `Intl` when available. */\n locale?: string;\n /** IANA time zone (e.g. \"Europe/Berlin\"), from `Intl` when available. */\n timeZone?: string;\n /**\n * Host app version (e.g. \"1.4.2\"). BEST-EFFORT auto-detected here via `detectAppVersion()`\n * (reads `expo-constants` / `expo-application` when present; adds no dependency — see\n * device/appVersion.ts). An explicit host-injected `config.appVersion` always WINS: the merge\n * sites (`WireOnboarding`, the session-analytics hooks, the context envelope) overwrite this\n * with the host value when one is supplied. Omitted when neither source yields a version.\n */\n appVersion?: string;\n};\n\n/** iOS idiom wins; otherwise the shortest side in dp (>= 600 → tablet) picks the class. */\nconst deriveFormFactor = (\n iosIdiom: string | undefined,\n width: number | undefined,\n height: number | undefined,\n): DeviceFormFactor | undefined => {\n if (iosIdiom === \"pad\") return \"tablet\";\n if (iosIdiom === \"phone\") return \"phone\";\n if (typeof width === \"number\" && typeof height === \"number\") {\n return Math.min(width, height) >= 600 ? \"tablet\" : \"phone\";\n }\n return undefined;\n};\n\n/**\n * Collect the device snapshot. Pure, synchronous, and never throws — call it once per\n * onboarding session. Missing fields are omitted rather than sent as null/undefined so the\n * payload (and the server's stored dict) stays compact.\n */\nexport const collectDeviceContext = (): DeviceContext => {\n const ctx: DeviceContext = { platform: Platform.OS };\n\n // OS version (fallback; per-OS constants below may refine it).\n try {\n const version = Platform.Version;\n if (version !== undefined && version !== null && String(version)) {\n ctx.osVersion = String(version);\n }\n } catch {\n // ignore\n }\n\n // `Platform.constants` shape differs by OS and RN version — read every field defensively.\n let constants: Record<string, unknown> = {};\n try {\n constants = (Platform.constants ?? {}) as Record<string, unknown>;\n } catch {\n constants = {};\n }\n\n let iosIdiom: string | undefined;\n try {\n if (Platform.OS === \"android\") {\n const brand = constants.Brand;\n const model = constants.Model;\n const release = constants.Release;\n if (typeof brand === \"string\" && brand) ctx.brand = brand;\n if (typeof model === \"string\" && model) ctx.model = model;\n if (release !== undefined && release !== null && String(release)) {\n ctx.osVersion = String(release);\n }\n } else if (Platform.OS === \"ios\") {\n const osVersion = constants.osVersion;\n const idiom = constants.interfaceIdiom;\n if (osVersion !== undefined && osVersion !== null && String(osVersion)) {\n ctx.osVersion = String(osVersion);\n }\n if (typeof idiom === \"string\" && idiom) {\n ctx.interfaceIdiom = idiom;\n iosIdiom = idiom;\n }\n // iOS has no model in `Platform.constants`; best-effort via `expo-device` (adds no dep,\n // omitted when the module is absent — see device/deviceModel.ts).\n const iosModel = detectNativeModel();\n if (iosModel) ctx.model = iosModel;\n }\n } catch {\n // ignore per-OS constant reads\n }\n\n // Screen dimensions + derived form factor.\n try {\n const screen = Dimensions.get(\"screen\");\n if (screen) {\n if (typeof screen.width === \"number\") ctx.screenWidth = screen.width;\n if (typeof screen.height === \"number\") ctx.screenHeight = screen.height;\n if (typeof screen.scale === \"number\") ctx.screenScale = screen.scale;\n const formFactor = deriveFormFactor(iosIdiom, screen.width, screen.height);\n if (formFactor) ctx.formFactor = formFactor;\n }\n } catch {\n // ignore\n }\n\n // Layout direction.\n try {\n ctx.isRTL = I18nManager.isRTL;\n } catch {\n // ignore\n }\n\n // Locale + time zone via the standard Intl global. Hermes may ship without full Intl,\n // so referencing it can throw ReferenceError — the try/catch covers that too.\n try {\n const resolved = Intl.DateTimeFormat().resolvedOptions();\n if (resolved.locale) ctx.locale = resolved.locale;\n if (resolved.timeZone) ctx.timeZone = resolved.timeZone;\n } catch {\n // Intl unavailable — omit locale/timeZone.\n }\n\n // Best-effort host app version (adds no dependency; omitted when unavailable). An explicit\n // `config.appVersion` overrides this downstream at the merge sites.\n const appVersion = detectAppVersion();\n if (appVersion) ctx.appVersion = appVersion;\n\n return ctx;\n};\n","/**\n * contextEnvelope — a small, PRIVACY-NEUTRAL context bundle stamped onto every outgoing\n * analytics event, giving the Wire dashboard the Sentry/Firebase-parity segmentation fields\n * (device model, OS + version, screen, locale, timezone, form factor) plus a few host-injected\n * scalars (session correlation id, app version + native build number, connectivity type).\n *\n * WHY a separate builder (not just `collectDeviceContext`): the envelope COMPOSES the existing\n * device snapshot with the handful of extras a host can cheaply supply but the kit can't collect\n * dependency-free (native build number, connectivity type). It never re-implements device\n * collection — it reuses `collectDeviceContext()` verbatim (see device/deviceContext.ts).\n *\n * HARD PRIVACY RULE (why this file, like deviceContext.ts, adds nothing new):\n * NEVER GPS / location, NEVER an advertising id (IDFA / GAID), NEVER a device fingerprint.\n * Location is derived SERVER-SIDE from IP-geo only — nothing here carries a coordinate or an\n * ad id, so a host adopting this changes no App Privacy / Data Safety declaration. There is a\n * test (contextEnvelope.test.ts) that asserts the ABSENCE of any such field.\n *\n * DEPENDENCY-FREE: the only import is the kit's own `collectDeviceContext`. `networkType` and\n * `appBuild` are HOST-INJECTED — there is no dependency-free RN core signal for either, so the\n * envelope simply omits them when the host does not pass them (no forced peer dependency).\n */\nimport { collectDeviceContext, type DeviceContext } from \"../device/deviceContext\";\n\n/**\n * The context stamped onto every event. `device` is always present (from\n * `collectDeviceContext`); every scalar is optional and OMITTED when the host does not supply it.\n */\nexport type ContextEnvelope = {\n /** The privacy-neutral device snapshot (reused from `collectDeviceContext`). */\n device: DeviceContext;\n /** Correlation id for this app-open / flow (caller-supplied). */\n sessionId?: string;\n /** App version, e.g. \"1.4.2\" (mirrors `device.appVersion`; host-injected, else auto-detected). */\n appVersion?: string;\n /** Host native build number, e.g. \"412\" (from `expo-constants` `nativeBuildVersion`). */\n appBuild?: string;\n /** Host connectivity signal, e.g. \"wifi\" | \"cellular\" (from `@react-native-community/netinfo`). */\n networkType?: string;\n};\n\n/** Host-injected inputs for {@link buildContextEnvelope}. All optional; each is omitted when absent. */\nexport type ContextEnvelopeInput = {\n sessionId?: string;\n appVersion?: string;\n appBuild?: string;\n networkType?: string;\n};\n\n/**\n * Build a fresh context envelope. Reuses `collectDeviceContext()` for the device block (which\n * already carries a best-effort auto-detected `appVersion`) and layers the host-injected scalars\n * on top. An explicit `input.appVersion` overrides the auto-detected `device.appVersion`, and the\n * outer `appVersion` scalar mirrors whichever version is effective.\n *\n * Returns a NEW object on every call (no shared mutable reference), so a caller can hold or mutate\n * the result without leaking into the next envelope. Never throws — `collectDeviceContext` is\n * itself guarded, and the rest is plain assignment.\n */\nexport const buildContextEnvelope = (input: ContextEnvelopeInput = {}): ContextEnvelope => {\n // Fresh copy so the returned envelope never aliases a cached device snapshot.\n const device: DeviceContext = { ...collectDeviceContext() };\n\n // `device.appVersion` is auto-detected best-effort by `collectDeviceContext`; an explicit\n // host `input.appVersion` always wins.\n if (input.appVersion) device.appVersion = input.appVersion;\n\n // The outer scalar mirrors the effective version (host-supplied, else auto-detected) so the\n // queue can stamp `user_context.app_version` even when the host never passed one.\n const effectiveAppVersion = input.appVersion ?? device.appVersion;\n\n const envelope: ContextEnvelope = { device };\n if (input.sessionId) envelope.sessionId = input.sessionId;\n if (effectiveAppVersion) envelope.appVersion = effectiveAppVersion;\n if (input.appBuild) envelope.appBuild = input.appBuild;\n if (input.networkType) envelope.networkType = input.networkType;\n\n return envelope;\n};\n","/**\n * eventQueue — the OFFLINE-FIRST, persistent transport buffer for client analytics events.\n *\n * The existing `reportClientEvents` is a blind fire-and-forget POST: it returns `void`, has no\n * success signal, and drops events when the network is down. The analytics data story depends on\n * NEVER losing an event offline, so this queue adds the missing durability layer on top of the\n * same `POST {serverUrl}/v1/events` contract:\n *\n * • Persists pending events to the host-injected `WireOnboardingStorage` (survives app kills).\n * • Batches them into one request body `{ events: [...] }`.\n * • Owns its OWN awaited `fetch` that reads `res.ok` — the only way to drive retry + dequeue,\n * since `reportClientEvents` cannot ack. A 2xx dequeues the batch; a non-ok / rejected / thrown\n * response keeps it and schedules an exponential backoff retry.\n * • Flushes on `enqueue`, on an explicit `flush()`, and on `notifyOnline()` (host reconnect).\n * • Caps the buffer (drop-OLDEST under pressure) and de-dups identical pending events.\n * • Stamps the current context envelope (device + host scalars) onto every event before send.\n *\n * FIRE-AND-FORGET (load-bearing): `enqueue` returns immediately and NEVER throws into the UI. A\n * missing `fetch`, a hung/broken storage, a rejecting network, or a JSON error is swallowed and\n * degrades gracefully — analytics must never be able to break the app. In-memory fallback covers\n * the no-storage case (survives re-renders, not app kills).\n *\n * DEPENDENCY-FREE: no network-detection or persistence library. Connectivity is host-driven via\n * `notifyOnline()`; persistence is the host-injected AsyncStorage-compatible subset.\n */\nimport type { ContextEnvelope } from \"./contextEnvelope\";\nimport type { ClientEvent, ClientEventTarget } from \"./reportClientEvent\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\n/** Envelope source: a fixed envelope or a provider evaluated at enqueue time (fresh network type). */\nexport type EnvelopeSource = ContextEnvelope | (() => ContextEnvelope | undefined);\n\n/** Options for {@link createEventQueue}. Only `target` is conceptually required to actually send. */\nexport type EventQueueOptions = {\n /** Where to POST — the tenant transport (`serverUrl` + `apiKey`), same as `WireOnboardingConfig`. */\n target: ClientEventTarget | undefined;\n /**\n * Host persistence (AsyncStorage-compatible subset). When omitted, the queue runs in the\n * documented DEGRADED in-memory mode — it survives re-renders but not an app kill.\n */\n storage?: WireOnboardingStorage;\n /** Tenant/app id used to namespace the default storage key (`wireai:evtq:<appId>`). */\n appId?: string;\n /** Explicit storage key override (wins over the `appId`-derived default). */\n storageKey?: string;\n /** The context envelope stamped onto every event before send (device + host scalars). */\n envelope?: EnvelopeSource;\n /** Max pending events; enqueuing past this DROPS THE OLDEST first (default 200). */\n maxSize?: number;\n /** Events per POST batch (default 20). */\n batchSize?: number;\n /** First retry delay in ms; doubles each failed attempt (default 1000). */\n baseBackoffMs?: number;\n /** Backoff ceiling in ms (default 30000). */\n maxBackoffMs?: number;\n /** Max AUTOMATIC backoff retries before pausing (default 6); `notifyOnline()`/`flush()` re-arm it. */\n maxRetries?: number;\n};\n\n/** The queue's public surface. `enqueue` is fire-and-forget (returns immediately, never throws). */\nexport type EventQueue = {\n /** Buffer one event (envelope-stamped), persist, and schedule a flush. Never throws. */\n enqueue(event: ClientEvent): void;\n /** Attempt an immediate drain of the pending buffer. Fire-and-forget. */\n flush(): void;\n /** Host reconnect signal: reset backoff and drain immediately. Fire-and-forget. */\n notifyOnline(): void;\n /** Current pending (in-memory) count. */\n size(): number;\n};\n\nconst DEFAULTS = {\n maxSize: 200,\n batchSize: 20,\n baseBackoffMs: 1000,\n maxBackoffMs: 30000,\n maxRetries: 6,\n} as const;\n\n/** Ceiling on the persisted-backlog read — a hung adapter degrades to an empty start, never a stall. */\nconst READ_TIMEOUT_MS = 1500;\n\n/** Internal buffered item. `id` is a local monotonic handle for deterministic dequeue-after-ack;\n * it is NEVER sent to the server. `sig` is the de-dup signature (serialized stamped event). */\ntype QueuedItem = { id: number; event: ClientEvent; sig: string };\n\n/** Persisted shape — the local id + the (already envelope-stamped) event. `sig` is recomputed on load. */\ntype PersistedItem = { id: number; event: ClientEvent };\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n/** Detach a timer from the event loop where the runtime supports it (Node test process / some RNs). */\nconst unrefTimer = (timer: ReturnType<typeof setTimeout>): void => {\n const t = timer as unknown as { unref?: () => void };\n if (typeof t.unref === \"function\") t.unref();\n};\n\nconst parsePersisted = (raw: string | null | undefined): PersistedItem[] => {\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const items: PersistedItem[] = [];\n for (const entry of parsed) {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof (entry as PersistedItem).id === \"number\" &&\n (entry as PersistedItem).event &&\n typeof (entry as PersistedItem).event === \"object\"\n ) {\n items.push(entry as PersistedItem);\n }\n }\n return items;\n } catch {\n // Corrupt backlog → start empty; the next persist overwrites it.\n return [];\n }\n};\n\n/**\n * Create an offline-first event queue. Loads any persisted backlog on creation so a\n * killed-and-relaunched app resumes where it left off. Returns the {@link EventQueue} surface.\n */\nexport const createEventQueue = (options: EventQueueOptions): EventQueue => {\n const target = options.target;\n const storage = options.storage;\n const key = options.storageKey ?? `wireai:evtq:${options.appId ?? \"default\"}`;\n const maxSize = options.maxSize ?? DEFAULTS.maxSize;\n const batchSize = options.batchSize ?? DEFAULTS.batchSize;\n const baseBackoffMs = options.baseBackoffMs ?? DEFAULTS.baseBackoffMs;\n const maxBackoffMs = options.maxBackoffMs ?? DEFAULTS.maxBackoffMs;\n const maxRetries = options.maxRetries ?? DEFAULTS.maxRetries;\n\n let pending: QueuedItem[] = [];\n let nextId = 0;\n let flushing = false;\n let attempt = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n\n const resolveEnvelope = (): ContextEnvelope | undefined => {\n try {\n return typeof options.envelope === \"function\" ? options.envelope() : options.envelope;\n } catch {\n return undefined;\n }\n };\n\n // Stamp the current envelope onto a COPY of the event (never mutate the caller's object):\n // device → event.device (when the event has none)\n // sessionId → event.session_id (when the event has none)\n // appVersion / appBuild / networkType → event.user_context (the non-PII bucket the server\n // sanitizes), never overwriting a key the caller already set.\n const stamp = (event: ClientEvent): ClientEvent => {\n const env = resolveEnvelope();\n const stamped: ClientEvent = { ...event };\n if (!env) return stamped;\n if (!stamped.device && env.device) stamped.device = env.device;\n if (!stamped.session_id && env.sessionId) stamped.session_id = env.sessionId;\n const uc: Record<string, string | number | boolean> = { ...(stamped.user_context ?? {}) };\n if (env.appVersion && uc.app_version === undefined) uc.app_version = env.appVersion;\n if (env.appBuild && uc.app_build === undefined) uc.app_build = env.appBuild;\n if (env.networkType && uc.network_type === undefined) uc.network_type = env.networkType;\n if (Object.keys(uc).length > 0) stamped.user_context = uc;\n return stamped;\n };\n\n const persist = (): void => {\n if (!storage) return;\n try {\n if (pending.length === 0) {\n void storage.removeItem(key).catch(() => {});\n return;\n }\n const payload: PersistedItem[] = pending.map((item) => ({ id: item.id, event: item.event }));\n void storage.setItem(key, JSON.stringify(payload)).catch(() => {});\n } catch {\n // Best-effort: a failed write just means the backlog is not durable this launch.\n }\n };\n\n const enforceSizeCap = (): void => {\n // Drop the OLDEST first so the newest events are never the ones lost under pressure.\n if (pending.length > maxSize) pending.splice(0, pending.length - maxSize);\n };\n\n const safeSig = (event: ClientEvent): string => {\n try {\n return JSON.stringify(event);\n } catch {\n // Non-serializable event → give it a unique signature so it is never wrongly de-duped.\n return `__nosig_${nextId}_${Math.random()}`;\n }\n };\n\n // Load any persisted backlog. Anything enqueued before this settles stays in memory; we merge\n // persisted (older) ahead of it and reassign monotonic ids so dequeue-after-ack is deterministic.\n const loadPromise: Promise<void> = (async () => {\n if (!storage) return;\n try {\n const persistedItems = parsePersisted(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS));\n if (persistedItems.length === 0) return;\n const events = [...persistedItems.map((p) => p.event), ...pending.map((p) => p.event)];\n pending = [];\n nextId = 0;\n const seen = new Set<string>();\n for (const event of events) {\n const sig = safeSig(event);\n if (seen.has(sig)) continue; // collapse duplicates carried across the merge\n seen.add(sig);\n pending.push({ id: nextId++, event, sig });\n }\n enforceSizeCap();\n persist();\n } catch {\n // Unreadable backlog → start empty; nothing enqueued in-memory is lost.\n }\n })();\n\n // The outcome of one POST attempt:\n // \"ok\" → the server accepted the batch (2xx) → dequeue it.\n // \"drop\" → a BATCH-SPECIFIC permanent error (this batch will never be accepted no matter how\n // often we retry) → discard it and continue, so it can't block the good events behind\n // it (head-of-line). See DROP_STATUSES.\n // \"retry\" → transient or tenant-wide (network/5xx/429/auth) → keep the batch and back off.\n type PostResult = \"ok\" | \"drop\" | \"retry\";\n\n // Statuses where retrying THIS batch is futile because the batch itself is the problem — a\n // malformed body (400/422), a too-large body (413), or a wrong route (404). Dropping a poison\n // batch is what stops it from stalling the whole backlog. Deliberately NOT here: 401/403 (auth is\n // tenant-wide, not batch-specific — dropping would silently lose EVERY event on a recoverable\n // credential blip, so we keep retrying/pausing instead) and 429/5xx (transient).\n const DROP_STATUSES = new Set([400, 404, 413, 422]);\n\n // The queue's OWN awaited POST. Classifies the response to drive dequeue/drop/retry. NEVER throws —\n // a missing fetch, a rejecting network, or an abort resolves to \"retry\" (batch stays, retry schedules).\n const postBatch = async (events: ClientEvent[]): Promise<PostResult> => {\n if (!target?.serverUrl || events.length === 0) return \"retry\";\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = setTimeout(() => controller?.abort(), 15_000);\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events }),\n signal: controller?.signal,\n });\n if (res && (res as { ok?: boolean }).ok) return \"ok\";\n const status = (res as { status?: number } | undefined)?.status;\n if (typeof status === \"number\" && DROP_STATUSES.has(status)) return \"drop\";\n return \"retry\";\n } catch {\n return \"retry\";\n } finally {\n clearTimeout(timer);\n }\n };\n\n const clearRetry = (): void => {\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n retryTimer = undefined;\n }\n };\n\n const scheduleRetry = (): void => {\n // Bounded automatic retry. Past the cap the backlog simply waits for the next\n // `notifyOnline()` / `flush()` (both re-arm attempt), so events are paused, never dropped.\n if (attempt >= maxRetries) return;\n const delay = Math.min(baseBackoffMs * 2 ** attempt, maxBackoffMs);\n attempt++;\n clearRetry();\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n void drain();\n }, delay);\n unrefTimer(retryTimer);\n };\n\n const drain = async (): Promise<void> => {\n try {\n await loadPromise;\n } catch {\n // load already swallows; guard the await defensively.\n }\n if (flushing) return;\n flushing = true;\n try {\n while (pending.length > 0) {\n const batch = pending.slice(0, batchSize);\n const result = await postBatch(batch.map((item) => item.event));\n if (result === \"retry\") {\n scheduleRetry();\n return;\n }\n // \"ok\" (accepted) or \"drop\" (poison batch discarded so it can't block the rest): remove\n // exactly this batch by id (pending may have grown while in flight) and keep draining.\n const acked = new Set(batch.map((item) => item.id));\n pending = pending.filter((item) => !acked.has(item.id));\n persist();\n attempt = 0;\n clearRetry();\n }\n } finally {\n flushing = false;\n }\n };\n\n const flush = (): void => {\n try {\n void drain();\n } catch {\n // drain never throws synchronously, but guard the kick anyway.\n }\n };\n\n const enqueue = (event: ClientEvent): void => {\n try {\n const stamped = stamp(event);\n const sig = safeSig(stamped);\n // Collapse a redundant re-enqueue of an identical pending event.\n for (const item of pending) {\n if (item.sig === sig) return;\n }\n pending.push({ id: nextId++, event: stamped, sig });\n enforceSizeCap();\n persist();\n // Only kick a drain when no retry is already pending — avoids hammering fetch while offline.\n if (retryTimer === undefined) flush();\n } catch {\n // Fire-and-forget: nothing in enqueue may surface to the UI.\n }\n };\n\n const notifyOnline = (): void => {\n // Host reconnected: reset the backoff and drain now.\n attempt = 0;\n clearRetry();\n flush();\n };\n\n const size = (): number => pending.length;\n\n return { enqueue, flush, notifyOnline, size };\n};\n","/**\n * currentSession — a tiny module-level registry of the CURRENT per-open `session_id`.\n *\n * WHY it exists (kills the phantom-session): the per-open emitters (`reportSessionStart` and the\n * `useSessionStart` / `useLifecycleEvents` hooks) mint a fresh `session_id` for each app-open and\n * post `app.session_started` with it — so the SERVER knows that id. But other client paths\n * (`identify`, host `app_event`s through the analytics façade) used to reference a DIFFERENT id\n * (a frozen per-instance id), which the server had never seen, so it back-filled a synthetic\n * `session_started` — inflating session counts (the \"phantom-session\" bug).\n *\n * This registry is the single seam that lets those paths reuse the LIVE per-open session id the\n * server already ingested. `reportSessionStart` writes the current id here on every open; the façade\n * reads it so `identify`/app-events correlate to the real session instead of minting a phantom.\n *\n * DEPENDENCY-FREE + PROCESS-LOCAL: a plain module variable. It is intentionally NOT persisted — it\n * tracks the CURRENT process's open, and a fresh open always overwrites it. No cross-launch state.\n */\n\nlet _currentSessionId: string | undefined;\n\n/**\n * Record the current per-open `session_id`. Called by `reportSessionStart` when it emits an\n * app-open. A blank / non-string id is ignored (the previous id stays current). Idempotent.\n */\nexport const setCurrentSessionId = (id: string | undefined): void => {\n if (typeof id === \"string\" && id.length > 0) _currentSessionId = id;\n};\n\n/** The current per-open `session_id`, or `undefined` when no app-open has been registered yet. */\nexport const getCurrentSessionId = (): string | undefined => _currentSessionId;\n\n/** Test-only: forget the current session id so a unit test starts from a clean registry. */\nexport const resetCurrentSessionId = (): void => {\n _currentSessionId = undefined;\n};\n","/**\n * User identity — bind an onboarding session to the HOST's own user id so the funnel can\n * be reconciled to real users later (console sessions ↔ your user table / GA4 users).\n *\n * The id is an OPAQUE PSEUDONYMOUS STRING the host owns — its internal user id, NOT an\n * email/name/phone. Same host-injection philosophy as `storage` and `userContext`: the kit\n * mints nothing and reads nothing; the host passes what it wants. Dependency-free.\n *\n * Three binding moments (see WireOnboarding + the README \"User identity\" section):\n * 1. MOUNT — pass `userId` and it rides the A2A session-start metadata; the server\n * binds it when it creates the session.\n * 2. MID-SESSION— the user registers DURING onboarding: change the `userId` prop and the\n * kit emits an `identify` client event that attaches the id to the live\n * session (late binding — the key scenario).\n * 3. POST-FLOW — the user registers AFTER onboarding: call `identifyOnboarding(...)` with\n * the same host storage (it recovers the persisted contextId, before completion\n * clears it) or, more reliably, the `contextId` you captured from the\n * `started`/`resumed` `onEvent` (both events carry a `contextId` field).\n *\n * ⚠️ NO PII. Pass an opaque id (or a hash), never a raw email/name/phone. The id is capped at\n * {@link USER_ID_MAX_LENGTH} chars (longer ids are truncated, not rejected).\n */\nimport { getCurrentSessionId } from \"../analytics/currentSession\";\nimport { reportClientEvent } from \"../analytics/reportClientEvent\";\nimport {\n peekPersistedSession,\n sessionStorageKey,\n type WireOnboardingStorage,\n} from \"../session/persistedSession\";\n\n/** Max accepted user-id length. Longer strings are truncated (never rejected). Keep in sync\n * with the server's `USER_ID_MAX_LENGTH` (analytics/events.py). */\nexport const USER_ID_MAX_LENGTH = 128;\n\n/**\n * Normalize a host-supplied user id: trim, drop empty, and cap at {@link USER_ID_MAX_LENGTH}.\n * Returns `undefined` for a missing/blank/non-string value so callers can `if (id)`-gate.\n * PII is a host concern — this only bounds length, it does not (and cannot) detect an email.\n */\nexport const sanitizeUserId = (raw: unknown): string | undefined => {\n if (typeof raw !== \"string\") return undefined;\n const trimmed = raw.trim();\n if (!trimmed) return undefined;\n return trimmed.length > USER_ID_MAX_LENGTH ? trimmed.slice(0, USER_ID_MAX_LENGTH) : trimmed;\n};\n\n/** Options for {@link identifyOnboarding}. */\nexport type IdentifyOnboardingOptions = {\n /** Tenant transport, same shape as `WireOnboardingConfig` (only these two fields are used). */\n config: { serverUrl: string; apiKey: string };\n /** The host's opaque user id to bind. Trimmed + capped; NO PII. */\n userId: string;\n /**\n * The onboarding session id to bind to (the A2A contextId) — the `contextId` field carried on\n * the `started`/`resumed` `onEvent`. Pass this when you captured it there. Required after the\n * flow COMPLETED, since completion clears the persisted session. Wins over the storage lookup.\n */\n contextId?: string;\n /**\n * The SAME host storage you passed to `<WireOnboarding storage={…} />`. When `contextId` is\n * omitted, the helper reads the persisted contextId from it (works while the session is still\n * persisted — i.e. dropped or mid-flow, before completion clears it).\n */\n storage?: WireOnboardingStorage;\n /** App id, to derive the default storage key `wireai:session:<appId>` when reading from storage. */\n appId?: string;\n /** Storage key override — pass the same `persistKey` you gave `<WireOnboarding>`, if any. */\n persistKey?: string;\n};\n\n/**\n * Attach a host user id to an onboarding session AFTER the fact (post-registration), by sending\n * an `identify` client event to `/v1/events`. Resolves the contextId from an explicit\n * `contextId` or, failing that, from the persisted session in the host `storage`.\n *\n * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to `true`\n * when an identify event was dispatched, `false` when it couldn't (no user id, no server url,\n * or no resolvable contextId).\n */\nexport const identifyOnboarding = async (\n opts: IdentifyOnboardingOptions,\n): Promise<boolean> => {\n const userId = sanitizeUserId(opts.userId);\n if (!userId || !opts.config?.serverUrl) return false;\n\n let contextId = opts.contextId?.trim() || undefined;\n if (!contextId && opts.storage) {\n const key = opts.persistKey ?? (opts.appId ? sessionStorageKey(opts.appId) : undefined);\n if (key) {\n const stored = await peekPersistedSession(opts.storage, key);\n contextId = stored?.id;\n }\n }\n // Last resort: bind to the LIVE per-open session (registered by `reportSessionStart`) so a\n // post-flow identify with no captured contextId still attaches to a session the server saw,\n // instead of no-oping. The onboarding contextId (above) is still preferred when available.\n if (!contextId) contextId = getCurrentSessionId();\n if (!contextId) return false;\n\n reportClientEvent(\n { serverUrl: opts.config.serverUrl, apiKey: opts.config.apiKey },\n { event_type: \"identify\", session_id: contextId, user_id: userId },\n );\n return true;\n};\n","/**\n * userContext — the ONE extensible object a host passes once and the kit flows into every\n * analytics event's `user_context` (plus the top-level opaque `user_id`).\n *\n * WHY it exists: hosts already hand the kit fragments of \"who this user is\" — `config.appVersion`,\n * `useSessionStart({ deviceKey, userId })`, `<WireOnboarding userContext={…} />` — but there was no\n * single object that carries app version + device key + user id + (opt-in) email + arbitrary extras\n * together, with one precedence rule, into every event. `WireUserContext` is that object;\n * `resolveUserContext` is the pure merge that turns it into the wire shape.\n *\n * PRECEDENCE (the one rule): an explicit `WireUserContext` field WINS over the #42 auto-detected\n * `device`/`appVersion`. A missing field is OMITTED, never sent empty.\n *\n * WHERE EACH FIELD LANDS (deliberate separation so nothing leaks across buckets):\n * • `userId` → the event's TOP-LEVEL opaque `user_id` (via `sanitizeUserId`). NEVER the bucket.\n * • `userEmail` → its OWN key `user_context.user_email`. NEVER merged into `userId`. OPT-IN PII.\n * • `deviceKey` → `user_context.device_key` (the server's `_event_device_key` reads it there).\n * • `appVersion`→ `user_context.app_version` (and returned as `appVersion` for `device.appVersion`).\n * • `extra` → NAMESPACED under a `custom.` key prefix, coerced to scalars, so a host extra can\n * never collide with a reserved `user_context` key.\n *\n * DEPENDENCY-FREE: the only import is the kit's own `sanitizeUserId`. The optional email hash is a\n * dependency-free FNV-1a fold (see {@link hashEmailFnv1a}) — no crypto library, no async.\n */\nimport { sanitizeUserId } from \"../identity/userIdentity\";\n\n/**\n * The single, extensible user-context object. A host passes it ONCE (at analytics init) and may\n * update it post-mount (e.g. attach `userId`/`userEmail` at login) via `setUserContext(partial)`.\n * Every field is optional; missing fields are omitted from the wire payload.\n */\nexport interface WireUserContext {\n /**\n * Host app version, e.g. \"1.4.2\". EXPLICIT — wins over the #42 auto-detected `device.appVersion`.\n * Lands in `user_context.app_version`. Omitted when neither this nor auto-detect yields a version.\n */\n appVersion?: string;\n /**\n * A stable, non-PII device id the host owns. Lands in `user_context.device_key` (NOT `session_id`),\n * where the server groups a device's sessions. Host-supplied; the kit never mints or reads one.\n */\n deviceKey?: string;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id — NOT an email/name/phone). Sanitized +\n * capped (see `sanitizeUserId`) and placed on the event's top-level `user_id`. NEVER the bucket.\n */\n userId?: string;\n /**\n * OPT-IN PII. The user's email, its OWN field (`user_context.user_email`) — NEVER merged into\n * `userId`. The kit NEVER auto-collects this; a host passes it only WITH the user's consent (EU\n * users: treat as personal data). For a non-reversible form, set {@link hashEmail} `true` (the kit\n * folds it with a dependency-free hash and stamps `user_context.user_email_hashed: true`), OR\n * pre-hash host-side with a cryptographic digest and pass that here with `hashEmail` falsy.\n */\n userEmail?: string;\n /**\n * When `true`, {@link userEmail} is folded with the kit's dependency-free {@link hashEmailFnv1a}\n * before it leaves the device, and `user_context.user_email_hashed` is set `true`. NOTE: FNV-1a is\n * a lightweight NON-cryptographic fold (obfuscation, not a secure digest). For a cryptographic\n * hash, compute it host-side (e.g. SHA-256 via `expo-crypto`) and pass the digest as `userEmail`\n * with `hashEmail` falsy. Default: raw email is sent as-is (opt-in already gated it upstream).\n */\n hashEmail?: boolean;\n /**\n * Arbitrary host context (signup method, referral, plan tier…). Each value is coerced to a scalar\n * (`string | number | boolean`; non-scalars and non-finite numbers are DROPPED) and NAMESPACED\n * under a `custom.` key prefix in `user_context` (e.g. `user_context[\"custom.referral\"]`) so it can\n * never collide with a reserved key. No raw PII — use {@link userEmail} for email.\n */\n extra?: Record<string, string | number | boolean>;\n}\n\n/**\n * The wire-shaped result of {@link resolveUserContext}. `userContext` is the non-PII/opt-in-PII\n * bucket stamped onto the event; `userId` is the top-level opaque id; `appVersion`/`deviceKey` are\n * echoed for callers that also place them elsewhere (e.g. `device.appVersion`). Absent fields are\n * omitted so a caller can spread this without sending empties.\n */\nexport interface ResolvedUserContext {\n /** The opaque, sanitized user id → the event's top-level `user_id`. Omitted when unset/blank. */\n userId?: string;\n /** The stable device id → `user_context.device_key`. Omitted when unset. */\n deviceKey?: string;\n /** The effective app version (explicit > auto-detected) → `user_context.app_version`. */\n appVersion?: string;\n /** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */\n userContext?: Record<string, string | number | boolean>;\n}\n\n/** Reserved `user_context` keys the kit itself writes; host `extra` is namespaced away from these. */\nexport const RESERVED_USER_CONTEXT_KEYS = [\n \"device_key\",\n \"app_version\",\n \"app_build\",\n \"network_type\",\n \"session_count\",\n \"returning\",\n \"platform\",\n \"user_email\",\n \"user_email_hashed\",\n] as const;\n\n/** The prefix applied to every host `extra` key so it can never collide with a reserved key. */\nexport const EXTRA_KEY_PREFIX = \"custom.\" as const;\n\n/** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */\nexport const isWireScalar = (value: unknown): value is string | number | boolean => {\n const t = typeof value;\n if (t === \"string\" || t === \"boolean\") return true;\n if (t === \"number\") return Number.isFinite(value as number);\n return false;\n};\n\n/**\n * Fold an email to a stable, dependency-free 32-bit FNV-1a hex token (lowercased + trimmed first so\n * the same address always folds identically). This is OBFUSCATION, not a cryptographic digest — it\n * is not collision-resistant. For a real hash, pre-hash host-side and pass the digest as `userEmail`.\n */\nexport const hashEmailFnv1a = (email: string): string => {\n const normalized = email.trim().toLowerCase();\n let hash = 0x811c9dc5; // FNV offset basis (32-bit)\n for (let i = 0; i < normalized.length; i++) {\n hash ^= normalized.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193); // FNV prime (32-bit), kept in 32-bit via imul\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n};\n\n/** Trim a candidate string; return `undefined` for a non-string / blank so callers can `if`-gate. */\nconst cleanString = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Coerce a host `extra` map into the namespaced, scalar-only bucket shape. Every kept value is\n * placed under `custom.<key>`; non-scalar values (objects, arrays, null, functions, NaN/Infinity)\n * are DROPPED. Returns an object (possibly empty).\n */\nexport const namespaceExtra = (\n extra: Record<string, unknown> | undefined,\n): Record<string, string | number | boolean> => {\n const out: Record<string, string | number | boolean> = {};\n if (!extra || typeof extra !== \"object\") return out;\n for (const [key, value] of Object.entries(extra)) {\n const cleanKey = cleanString(key);\n if (!cleanKey) continue;\n if (!isWireScalar(value)) continue; // drop anything that isn't a finite scalar\n out[`${EXTRA_KEY_PREFIX}${cleanKey}`] = value;\n }\n return out;\n};\n\n/** Options for {@link resolveUserContext}. */\nexport interface ResolveUserContextOptions {\n /**\n * The kit's best-effort auto-detected app version (#42; from `detectAppVersion()`/the device\n * snapshot). Used ONLY when the explicit `WireUserContext.appVersion` is absent — explicit wins.\n */\n autoAppVersion?: string;\n}\n\n/**\n * Merge a {@link WireUserContext} into the wire shape with the precedence rule (explicit field >\n * auto-detected). Pure, never throws. Missing fields are omitted so the result can be spread onto an\n * event without sending empties.\n */\nexport const resolveUserContext = (\n ctx: WireUserContext = {},\n opts: ResolveUserContextOptions = {},\n): ResolvedUserContext => {\n const result: ResolvedUserContext = {};\n const bucket: Record<string, string | number | boolean> = {};\n\n // userId → top-level opaque id (NEVER the bucket). Sanitized + capped host-side.\n const userId = sanitizeUserId(ctx.userId);\n if (userId) result.userId = userId;\n\n // deviceKey → user_context.device_key (NOT session_id).\n const deviceKey = cleanString(ctx.deviceKey);\n if (deviceKey) {\n result.deviceKey = deviceKey;\n bucket.device_key = deviceKey;\n }\n\n // appVersion → explicit wins over auto-detected (#42); echoed for device.appVersion callers.\n const appVersion = cleanString(ctx.appVersion) ?? cleanString(opts.autoAppVersion);\n if (appVersion) {\n result.appVersion = appVersion;\n bucket.app_version = appVersion;\n }\n\n // userEmail → its OWN key. OPT-IN PII, optionally folded. NEVER touches userId.\n const email = cleanString(ctx.userEmail);\n if (email) {\n if (ctx.hashEmail) {\n bucket.user_email = hashEmailFnv1a(email);\n bucket.user_email_hashed = true;\n } else {\n bucket.user_email = email;\n }\n }\n\n // extra → namespaced + scalar-coerced.\n Object.assign(bucket, namespaceExtra(ctx.extra));\n\n if (Object.keys(bucket).length > 0) result.userContext = bucket;\n return result;\n};\n","/**\n * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies\n * none. This is the headline of \"device fully automatic\": the analytics façade auto-mints ONE id,\n * persists it via the host's `storage` abstraction, and reuses it on every subsequent open — so\n * `user_context.device_key` is ALWAYS present and the server's review/questionnaire gating +\n * A/B stickiness (both key on `device_key`) work out of the box, with zero host wiring.\n *\n * WHY it is NOT PII and adds NO dependency (the kit's hard rules):\n * The id is a random token generated from `Date.now()` + `Math.random()` — it carries NO hardware\n * identifier, NO IDFA/GAID, NO fingerprint. It is a first-party per-install correlation key, the\n * same privacy category as a first-party cookie: it groups a single install's sessions and cannot\n * identify a person or be joined across apps. There is NO `uuid` (or any) dependency — a\n * time+random scheme is sufficient because the id is minted ONCE and then persisted, so global\n * uniqueness across the fleet is not required (a per-install collision is astronomically unlikely\n * and inconsequential — worst case two installs share a bucket).\n *\n * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses\n * that verbatim and never mints/persists an auto id.\n */\n\n/** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */\nexport const AUTO_DEVICE_ID_PREFIX = \"wdev_\";\n\n/** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */\nexport const deviceIdStorageKey = (appId?: string): string =>\n `wireai:analytics:deviceKey:${appId ?? \"default\"}`;\n\n/** One 32-bit base-36 chunk of randomness. Two chunks are concatenated for a wider token. */\nconst randomChunk = (): string =>\n Math.floor(Math.random() * 0x100000000)\n .toString(36)\n .padStart(6, \"0\");\n\n/**\n * Mint a fresh per-install device id. Dependency-free (`Date.now()` + `Math.random()`), never\n * throws, and returns a NEW value on every call — the façade mints ONCE and persists, so this is\n * called at most once per install (then the persisted value is reused). Two random chunks plus the\n * timestamp keep the token wide enough that a per-install collision is not a practical concern.\n */\nexport const mintDeviceId = (): string => {\n const time = Date.now().toString(36);\n return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;\n};\n","/**\n * analyticsFacade — a Segment/PostHog-shaped developer API (`track` / `screen` / `identify`)\n * over the kit's OWN offline-first event queue. One package, one key, one line:\n *\n * const analytics = createAnalytics({ serverUrl, apiKey, storage });\n * analytics.track(\"content_share\", { source: \"feed\" });\n * analytics.screen(\"Home\", { tab: \"explore\" });\n * analytics.identify(\"u_123\", { plan: \"pro\" });\n *\n * WHY a façade: the primitives already exist (`createEventQueue` for durable offline-first\n * transport, `buildContextEnvelope` for the non-PII device context, the `identify` client-event\n * contract for user binding), but a host had to wire them together by hand. This composes them\n * into the familiar analytics-SDK surface so a consumer gets the ergonomics with NO second\n * install and NO second key — the same `{ serverUrl, apiKey }` creds as onboarding.\n *\n * ROUTING: every call builds a `ClientEvent` and `enqueue`s it. The queue stamps the context\n * envelope (device + host scalars), persists offline, batches, retries, and dequeues on ack —\n * so `track`/`screen`/`identify` inherit offline-first durability for free. `screen` routes\n * through the SAME queue rather than the direct `reportAppEvent` POST (a deliberate upgrade:\n * screen views survive being offline too).\n *\n * DEPENDENCY-FREE + TREE-SHAKEABLE: this module imports ONLY the queue, the envelope builder,\n * the client-event types + session-id seed, and the identity sanitizer. It reaches NO\n * onboarding / showcase / review UI, so an analytics-only consumer bundles none of it. React is\n * absent here on purpose — the optional React glue is the thin `useAnalytics` hook.\n *\n * FIRE-AND-FORGET: no method throws into the UI or blocks — the queue already guarantees that.\n */\nimport { buildContextEnvelope, type ContextEnvelope } from \"./contextEnvelope\";\nimport { getCurrentSessionId } from \"./currentSession\";\nimport { createEventQueue, type EventQueue, type EventQueueOptions } from \"./eventQueue\";\nimport { makeSessionId, type ClientEvent } from \"./reportClientEvent\";\nimport { resolveUserContext, type WireUserContext } from \"../context/userContext\";\nimport { mintDeviceId, deviceIdStorageKey } from \"../context/deviceId\";\nimport { sanitizeUserId } from \"../identity/userIdentity\";\n\n/** Arbitrary non-PII event properties. Serialized to the event's `meta` (a JSON string) on the wire. */\nexport type AnalyticsProps = Record<string, unknown>;\n\n/**\n * Tenant transport + context inputs for {@link createAnalytics}. `serverUrl`/`apiKey` are the\n * SAME creds as onboarding (never a second key). The rest feed the context envelope + the queue's\n * offline persistence — all optional.\n */\nexport type CreateAnalyticsConfig = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n /**\n * Correlation id shared by every event from this instance (and the `identify` event). Defaults\n * to a fresh `makeSessionId()` at creation so all events agree on one id per analytics instance.\n */\n sessionId?: string;\n /** Tenant/app id used to namespace the queue's default storage key (`wireai:evtq:<appId>`). */\n appId?: string;\n /**\n * Host persistence (AsyncStorage-compatible subset) for offline-first durability. When omitted,\n * the queue runs in the documented in-memory mode (survives re-renders, not app kills).\n */\n storage?: EventQueueOptions[\"storage\"];\n /** Host app version, e.g. \"1.4.2\" (host-injected; stamped onto every event's context). */\n appVersion?: string;\n /** Host native build number, e.g. \"412\" (host-injected). */\n appBuild?: string;\n /** Host connectivity signal, e.g. \"wifi\" | \"cellular\" — read fresh per event via the provider. */\n networkType?: string;\n /**\n * The rich {@link WireUserContext} to stamp onto every event's `user_context` (device key, opaque\n * user id, opt-in email, arbitrary `extra`). Passed ONCE here at init; updatable post-mount via\n * {@link Analytics.setUserContext} (e.g. attach `userId`/`userEmail` at login). Optional.\n *\n * NOTE on `deviceKey`: you do NOT need to supply one. When omitted, the kit auto-mints a stable,\n * non-PII per-install `device_key`, persists it via `storage`, and reuses it every open (in-memory\n * fallback without storage) — so `user_context.device_key` is ALWAYS present for the server's\n * review/questionnaire gating + A/B stickiness. Supply `deviceKey` only to use your OWN id (it wins).\n */\n userContext?: WireUserContext;\n};\n\n/** Optional queue tuning knobs, forwarded verbatim to {@link createEventQueue}. */\nexport type AnalyticsOptions = Partial<\n Pick<EventQueueOptions, \"maxSize\" | \"batchSize\" | \"baseBackoffMs\" | \"maxBackoffMs\" | \"maxRetries\">\n>;\n\n/**\n * The developer-facing analytics surface. `track`/`screen`/`identify` are the Segment/PostHog-shaped\n * API; `flush`/`notifyOnline`/`size` expose the underlying queue so a host can drive reconnect\n * draining (load-bearing for offline-first) and inspect the pending buffer.\n */\nexport type Analytics = {\n /** Record an in-app event: `event_type='app_event'`, `question_key=<event>`, `props`→`meta`. */\n track(event: string, props?: AnalyticsProps): void;\n /** Record a screen view: `event_type='app_event'`, `question_key='screen'`, `meta={ screen, ...props }`. */\n screen(name: string, props?: AnalyticsProps): void;\n /** Bind the host's opaque user id (per-session, in-memory) and emit an `identify` event. */\n identify(userId: string, traits?: AnalyticsProps): void;\n /**\n * Update the {@link WireUserContext} after init (e.g. attach `userId`/`userEmail` at login). Shallow\n * merges the partial over the current context (`extra` is deep-merged); a supplied `userId` also\n * binds like {@link identify}. Takes effect on subsequent events. Fire-and-forget.\n */\n setUserContext(partial: Partial<WireUserContext>): void;\n /** Attempt an immediate drain of the pending buffer. Fire-and-forget. */\n flush(): void;\n /** Host reconnect signal: reset backoff and drain now. Fire-and-forget. */\n notifyOnline(): void;\n /** Current pending (in-memory) count. */\n size(): number;\n};\n\n/**\n * Create a bound analytics instance. Seeds one correlation `sessionId`, builds an offline-first\n * queue over the tenant transport, and passes a fresh-per-event context envelope PROVIDER so the\n * connectivity type is read at enqueue time. The bound user id starts unset (see `identify`).\n */\nexport const createAnalytics = (\n config: CreateAnalyticsConfig,\n options: AnalyticsOptions = {},\n): Analytics => {\n // A STABLE per-instance fallback id, used only when no explicit `config.sessionId` was given AND\n // no per-open session has been registered yet (see `resolveSessionId`).\n const instanceSessionId = config.sessionId ?? makeSessionId();\n\n // The session id every event correlates to. Precedence: an explicit `config.sessionId` freezes the\n // id (opt-out of the reuse); otherwise reuse the LIVE per-open session the server saw (via\n // `app.session_started`) so `identify`/app-events don't mint a fresh id the server back-fills into a\n // phantom session; finally fall back to the stable per-instance id when no open is registered yet.\n const resolveSessionId = (): string =>\n config.sessionId ?? getCurrentSessionId() ?? instanceSessionId;\n\n // The mutable rich user-context: seeded at init, updated via `setUserContext`. Resolved fresh on\n // every event so a post-mount update (login) takes effect immediately. Declared before the envelope\n // provider so the provider can read the current `userContext.appVersion` (see below).\n let userContext: WireUserContext = { ...(config.userContext ?? {}) };\n\n // Auto device id (the headline: \"device\" fully automatic). When the host supplies NO `deviceKey`,\n // the kit mints ONE stable, non-PII per-install id, PERSISTS it via the host `storage`, and reuses it\n // on every subsequent open — so `user_context.device_key` is ALWAYS present (the server's\n // review/questionnaire gating + A/B stickiness both key on it) with zero host wiring. A host-supplied\n // `deviceKey` still wins (see `applyContext`). Falls back to an in-memory id (stable for this\n // instance) when no storage is available.\n const hostDeviceKeyAtInit =\n typeof config.userContext?.deviceKey === \"string\" && config.userContext.deviceKey.trim()\n ? config.userContext.deviceKey.trim()\n : undefined;\n // Minted synchronously so `device_key` is never missing, even before the async storage read resolves.\n let autoDeviceKey = mintDeviceId();\n if (config.storage && !hostDeviceKeyAtInit) {\n const storage = config.storage;\n const deviceKey = deviceIdStorageKey(config.appId);\n void storage\n .getItem(deviceKey)\n .then((saved) => {\n const persisted = typeof saved === \"string\" && saved.trim() ? saved.trim() : undefined;\n // Reuse the persisted per-install id across opens; on first run persist the freshly minted one.\n if (persisted) autoDeviceKey = persisted;\n else void storage.setItem(deviceKey, autoDeviceKey).catch(() => {});\n })\n .catch(() => {});\n }\n\n // A provider (not a fixed value) so `networkType`, the current session id, AND the effective app\n // version are evaluated fresh on every enqueue. An explicit `WireUserContext.appVersion` (a host that\n // set the version ONLY inside `userContext`) now flows into `device.appVersion` too — not just\n // `user_context.app_version` — so the server's `by_app_version` breakdown (which reads\n // `device.appVersion`) agrees. Explicit wins over the auto-detected device version;\n // `buildContextEnvelope` keeps the auto value when neither is set.\n const envelope = (): ContextEnvelope =>\n buildContextEnvelope({\n sessionId: resolveSessionId(),\n appVersion: userContext.appVersion ?? config.appVersion,\n appBuild: config.appBuild,\n networkType: config.networkType,\n });\n\n const queue: EventQueue = createEventQueue({\n target: { serverUrl: config.serverUrl, apiKey: config.apiKey },\n storage: config.storage,\n appId: config.appId,\n envelope,\n ...options,\n });\n\n // Per-session, in-memory user binding. Seeded from the init context, then persisted across\n // launches when storage is provided.\n let boundUserId: string | undefined = sanitizeUserId(config.userContext?.userId);\n const storageKey = `wireai:analytics:userId:${config.appId ?? \"default\"}`;\n\n if (config.storage) {\n void config.storage\n .getItem(storageKey)\n .then((saved) => {\n // Don't clobber an explicit init-context user id with a stale persisted one.\n if (saved && !boundUserId) boundUserId = saved;\n })\n .catch(() => {});\n }\n\n // Stamp the resolved rich context onto an event: the `user_context` bucket (device_key, app_version,\n // opt-in user_email, namespaced `custom.*`) and the top-level opaque `user_id`. Never overwrites a\n // key the caller already set (so `identify`'s explicit `user_id` and any caller `user_context` win).\n const applyContext = (event: ClientEvent): void => {\n // Host `deviceKey` wins; otherwise the auto-minted/persisted per-install id fills it in so\n // `user_context.device_key` is always present.\n const hostDeviceKey =\n typeof userContext.deviceKey === \"string\" && userContext.deviceKey.trim()\n ? userContext.deviceKey\n : undefined;\n const resolved = resolveUserContext(\n { ...userContext, deviceKey: hostDeviceKey ?? autoDeviceKey },\n { autoAppVersion: config.appVersion },\n );\n if (resolved.userContext) {\n event.user_context = { ...resolved.userContext, ...(event.user_context ?? {}) };\n }\n if (boundUserId && !event.user_id) event.user_id = boundUserId;\n };\n\n const setUserContext = (partial: Partial<WireUserContext>): void => {\n if (!partial || typeof partial !== \"object\") return;\n // Deep-merge `extra` so a partial update adds keys instead of replacing the whole map.\n const mergedExtra =\n partial.extra || userContext.extra\n ? { ...(userContext.extra ?? {}), ...(partial.extra ?? {}) }\n : undefined;\n userContext = { ...userContext, ...partial };\n if (mergedExtra) userContext.extra = mergedExtra;\n // A user id supplied here binds like `identify` so subsequent events carry `user_id`.\n const uid = sanitizeUserId(partial.userId);\n if (uid) {\n boundUserId = uid;\n if (config.storage) void config.storage.setItem(storageKey, uid).catch(() => {});\n }\n };\n\n const track = (event: string, props?: AnalyticsProps): void => {\n if (!event) return;\n const clientEvent: ClientEvent = {\n event_type: \"app_event\",\n session_id: resolveSessionId(),\n question_key: event,\n };\n if (props && Object.keys(props).length > 0) clientEvent.meta = JSON.stringify(props);\n applyContext(clientEvent);\n queue.enqueue(clientEvent);\n };\n\n const screen = (name: string, props?: AnalyticsProps): void => {\n if (!name) return;\n // Reuse the K6 screen event shape (question_key='screen'); route through the queue for offline-first.\n const meta = { screen: name, ...(props ?? {}) };\n const clientEvent: ClientEvent = {\n event_type: \"app_event\",\n session_id: resolveSessionId(),\n question_key: \"screen\",\n meta: JSON.stringify(meta),\n };\n applyContext(clientEvent);\n queue.enqueue(clientEvent);\n };\n\n const identify = (userId: string, traits?: AnalyticsProps): void => {\n const clean = sanitizeUserId(userId);\n // Blank / non-string → no binding, no event (sanitizeUserId returns undefined). >128 → truncated.\n if (!clean) return;\n boundUserId = clean;\n if (config.storage) {\n void config.storage.setItem(storageKey, clean).catch(() => {});\n }\n const clientEvent: ClientEvent = {\n event_type: \"identify\",\n // Reuse the LIVE per-open session id (see `resolveSessionId`) so the server binds identity to\n // the session it already saw instead of back-filling a phantom `session_started`.\n session_id: resolveSessionId(),\n user_id: clean,\n };\n if (traits && Object.keys(traits).length > 0) clientEvent.meta = JSON.stringify(traits);\n applyContext(clientEvent);\n queue.enqueue(clientEvent);\n };\n\n return {\n track,\n screen,\n identify,\n setUserContext,\n flush: queue.flush,\n notifyOnline: queue.notifyOnline,\n size: queue.size,\n };\n};\n","/**\n * useAnalytics — a THIN optional React hook over the pure {@link createAnalytics} factory.\n *\n * It builds ONE analytics instance for the component's lifetime and returns it, so re-renders\n * never rebuild the queue or lose the in-memory user binding. React is a REQUIRED peer of the\n * kit, so importing it here is allowed; the hook adds NO other dependency. Mirrors the existing\n * `createScreenTracker` / `useScreenTracking` split — the factory stays React-free, this is the\n * glue.\n *\n * const analytics = useAnalytics({ serverUrl, apiKey, storage, appId });\n * analytics.track(\"content_share\", { source: \"feed\" });\n * // ...on reconnect: analytics.notifyOnline();\n */\nimport { useRef } from \"react\";\n\nimport {\n createAnalytics,\n type Analytics,\n type AnalyticsOptions,\n type CreateAnalyticsConfig,\n} from \"./analyticsFacade\";\n\n/**\n * Build a per-mount analytics instance. `config`/`options` are read once at first render (the\n * instance is stable for the component's lifetime, held in a ref). Returns the {@link Analytics}\n * surface so the component can `track` / `screen` / `identify` and drive `notifyOnline` on reconnect.\n */\nexport const useAnalytics = (\n config: CreateAnalyticsConfig,\n options: AnalyticsOptions = {},\n): Analytics => {\n // One instance per mount; kept in a ref so re-renders never rebuild the queue or drop the binding.\n const ref = useRef<Analytics | undefined>(undefined);\n const prevKeys = useRef<string>(\"\");\n\n const currentKeys = `${config.serverUrl}|${config.apiKey}|${config.appId}`;\n if (!ref.current || prevKeys.current !== currentKeys) {\n prevKeys.current = currentKeys;\n ref.current = createAnalytics(config, options);\n }\n return ref.current;\n};\n"]}