@wireai/activation 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,7 +39,15 @@ type DeviceContext = {
39
39
  osVersion?: string;
40
40
  /** Android device brand (e.g. "samsung"). Android only. */
41
41
  brand?: string;
42
- /** Android device model (e.g. "SM-G991B"). Android only. */
42
+ /**
43
+ * Device model. On Android it is read directly from `Platform.constants.Model` (e.g. "SM-G991B").
44
+ * iOS `Platform.constants` exposes NO model, so on iOS it is a BEST-EFFORT read of `expo-device`'s
45
+ * `modelName` ("iPhone 14 Pro"), falling back to `modelId` ("iPhone15,2") — dependency-free via a
46
+ * guarded require (see device/deviceModel.ts). ASYMMETRY: without `expo-device` installed, iOS
47
+ * `model` is omitted (there is no dependency-free iOS model in the already-used RN surface, and the
48
+ * kit will not add a native dep for it); Android needs no extra module. Not PII (a device class,
49
+ * not a unique id), so it changes no privacy-label declaration.
50
+ */
43
51
  model?: string;
44
52
  /** iOS interface idiom ("phone" | "pad" | …), when reported. iOS only. */
45
53
  interfaceIdiom?: string;
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { o as WireOnboardingProps, p as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, q as OnboardingEvent, u as OnboardingCopy, a as ClientEventTarget, D as DeviceContext, C as ClientEvent, e as EnvelopeSource } from './currentSession-BJBB7i4-.mjs';
4
- export { A as AnalyticsEvent, b as ClientEventType, v as DeviceFormFactor, w as EXTRA_KEY_PREFIX, x as OnboardingProgress, R as RESERVED_USER_CONTEXT_KEYS, y as ResolveUserContextOptions, z as ResolvedUserContext, g as WIRE_ONBOARDING_EVENTS, h as WireOnboardingEventName, W as WireUserContext, B as collectDeviceContext, k as getCurrentSessionId, F as hashEmailFnv1a, G as isWireScalar, m as makeSessionId, H as namespaceExtra, r as reportClientEvent, l as reportClientEvents, n as resetCurrentSessionId, I as resolveUserContext, s as setCurrentSessionId, t as toAnalyticsEvent } from './currentSession-BJBB7i4-.mjs';
3
+ import { o as WireOnboardingProps, p as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, q as OnboardingEvent, u as OnboardingCopy, a as ClientEventTarget, D as DeviceContext, C as ClientEvent, e as EnvelopeSource } from './currentSession-d9CrBxwe.mjs';
4
+ export { A as AnalyticsEvent, b as ClientEventType, v as DeviceFormFactor, w as EXTRA_KEY_PREFIX, x as OnboardingProgress, R as RESERVED_USER_CONTEXT_KEYS, y as ResolveUserContextOptions, z as ResolvedUserContext, g as WIRE_ONBOARDING_EVENTS, h as WireOnboardingEventName, W as WireUserContext, B as collectDeviceContext, k as getCurrentSessionId, F as hashEmailFnv1a, G as isWireScalar, m as makeSessionId, H as namespaceExtra, r as reportClientEvent, l as reportClientEvents, n as resetCurrentSessionId, I as resolveUserContext, s as setCurrentSessionId, t as toAnalyticsEvent } from './currentSession-d9CrBxwe.mjs';
5
5
  import { O as OnboardingTheme } from './types-BKfpdZzX.mjs';
6
6
  export { a as OnboardingButtonStyle, b as OnboardingColors, c as OnboardingFonts, d as OnboardingRadius, e as OnboardingSpacing } from './types-BKfpdZzX.mjs';
7
7
  export { C as CenteredModal, a as CenteredModalHandle, b as CenteredModalProps } from './CenteredModal-C3qQBHsA.mjs';
@@ -849,7 +849,7 @@ declare const attributionMetadata: (a: OnboardingAttribution) => {
849
849
  * Analytics must never be able to break onboarding.
850
850
  */
851
851
  /** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */
852
- type OptionalRequire = (moduleName: string) => unknown;
852
+ type OptionalRequire$1 = (moduleName: string) => unknown;
853
853
  /**
854
854
  * Detect the host app version, preferring `expo-constants` (`expoConfig.version`, then
855
855
  * `nativeAppVersion`) and finally `expo-application` (`nativeApplicationVersion`). Returns the
@@ -858,7 +858,40 @@ type OptionalRequire = (moduleName: string) => unknown;
858
858
  * `requireModule` is injectable so tests can exercise the "found" path without the native modules;
859
859
  * production defaults to the guarded runtime require above.
860
860
  */
861
- declare const detectAppVersion: (requireModule?: OptionalRequire) => string | undefined;
861
+ declare const detectAppVersion: (requireModule?: OptionalRequire$1) => string | undefined;
862
+
863
+ /**
864
+ * deviceModel — best-effort, DEPENDENCY-FREE detection of the device MODEL on iOS.
865
+ *
866
+ * WHY this exists (the asymmetry it closes): `collectDeviceContext` already reports `device.model`
867
+ * on Android straight from `Platform.constants.Model` (e.g. "SM-G991B"), but iOS `Platform.constants`
868
+ * exposes NO model — only `osVersion` / `interfaceIdiom`. So the analytics `by_model` breakdown was
869
+ * Android-only. This module fills the iOS gap with the SAME zero-dependency technique the kit already
870
+ * uses for `appVersion` (see device/appVersion.ts): a GUARDED, VARIABLE-specifier `require` of the
871
+ * common Expo `expo-device` module. If the host has it, iOS gets a model out of the box; if not, the
872
+ * require simply throws and is swallowed and iOS `model` stays omitted — nothing is forced, nothing
873
+ * is added to `package.json`, and a host without `expo-device` never fails to bundle.
874
+ *
875
+ * WHY it is NOT PII: `expo-device`'s `modelName` ("iPhone 14 Pro") and `modelId` ("iPhone15,2") are a
876
+ * device CLASS shared by millions of units — the same privacy category as the Android `Model` the kit
877
+ * already sends. It is NOT a unique device id / IDFA / fingerprint, so surfacing it changes no App
878
+ * Privacy / Data Safety declaration (identical guarantee to the rest of deviceContext). It deliberately
879
+ * does NOT read `expo-device`'s `deviceName` (that is the user-set name, e.g. "Malik's iPhone", and IS
880
+ * personal data).
881
+ *
882
+ * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.
883
+ */
884
+ /** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */
885
+ type OptionalRequire = (moduleName: string) => unknown;
886
+ /**
887
+ * Detect the device model via `expo-device`, preferring the human-readable `modelName`
888
+ * ("iPhone 14 Pro") and falling back to the identifier `modelId` ("iPhone15,2"). Returns the first
889
+ * real string, or `undefined` when `expo-device` is absent. Pure and never throws.
890
+ *
891
+ * `requireModule` is injectable so tests can exercise the "found" path without the native module;
892
+ * production defaults to the guarded runtime require above.
893
+ */
894
+ declare const detectNativeModel: (requireModule?: OptionalRequire) => string | undefined;
862
895
 
863
896
  /** Max accepted user-id length. Longer strings are truncated (never rejected). Keep in sync
864
897
  * with the server's `USER_ID_MAX_LENGTH` (analytics/events.py). */
@@ -906,6 +939,37 @@ type IdentifyOnboardingOptions = {
906
939
  */
907
940
  declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<boolean>;
908
941
 
942
+ /**
943
+ * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies
944
+ * none. This is the headline of "device fully automatic": the analytics façade auto-mints ONE id,
945
+ * persists it via the host's `storage` abstraction, and reuses it on every subsequent open — so
946
+ * `user_context.device_key` is ALWAYS present and the server's review/questionnaire gating +
947
+ * A/B stickiness (both key on `device_key`) work out of the box, with zero host wiring.
948
+ *
949
+ * WHY it is NOT PII and adds NO dependency (the kit's hard rules):
950
+ * The id is a random token generated from `Date.now()` + `Math.random()` — it carries NO hardware
951
+ * identifier, NO IDFA/GAID, NO fingerprint. It is a first-party per-install correlation key, the
952
+ * same privacy category as a first-party cookie: it groups a single install's sessions and cannot
953
+ * identify a person or be joined across apps. There is NO `uuid` (or any) dependency — a
954
+ * time+random scheme is sufficient because the id is minted ONCE and then persisted, so global
955
+ * uniqueness across the fleet is not required (a per-install collision is astronomically unlikely
956
+ * and inconsequential — worst case two installs share a bucket).
957
+ *
958
+ * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses
959
+ * that verbatim and never mints/persists an auto id.
960
+ */
961
+ /** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */
962
+ declare const AUTO_DEVICE_ID_PREFIX = "wdev_";
963
+ /** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */
964
+ declare const deviceIdStorageKey: (appId?: string) => string;
965
+ /**
966
+ * Mint a fresh per-install device id. Dependency-free (`Date.now()` + `Math.random()`), never
967
+ * throws, and returns a NEW value on every call — the façade mints ONCE and persists, so this is
968
+ * called at most once per install (then the persisted value is reused). Two random chunks plus the
969
+ * timestamp keep the token wide enough that a per-install collision is not a practical concern.
970
+ */
971
+ declare const mintDeviceId: () => string;
972
+
909
973
  /** The canonical event name for an app-open. A trigger keys off this exact string. */
910
974
  declare const SESSION_STARTED_EVENT: "app.session_started";
911
975
  /** Options for {@link reportSessionStart}. Everything except `target` is optional so a pre-auth
@@ -1132,4 +1196,4 @@ interface UseLifecycleEventsOptions {
1132
1196
  */
1133
1197
  declare const useLifecycleEvents: (config: LifecycleConfig | undefined, options?: UseLifecycleEventsOptions) => void;
1134
1198
 
1135
- export { AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardHandoff, type CardHandoffProps, type CardHandoffVariant, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, DoneBlock, ErrorBlock, FIRST_OPEN_EVENT, type IdentifyOnboardingOptions, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, USER_ID_MAX_LENGTH, type UseLifecycleEventsOptions, type UseSessionStartOptions, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, attributionMetadata, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, detectAppVersion, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, identifyOnboarding, isFeaturesFresh, isOnboardingEnabled, mergeTheme, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetFirstOpenLatch, resetSessionStartGuard, sanitizeUserId, themeFromBrand, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };
1199
+ export { AUTO_DEVICE_ID_PREFIX, AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardHandoff, type CardHandoffProps, type CardHandoffVariant, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, DoneBlock, ErrorBlock, FIRST_OPEN_EVENT, type IdentifyOnboardingOptions, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, USER_ID_MAX_LENGTH, type UseLifecycleEventsOptions, type UseSessionStartOptions, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, attributionMetadata, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, detectAppVersion, detectNativeModel, deviceIdStorageKey, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, identifyOnboarding, isFeaturesFresh, isOnboardingEnabled, mergeTheme, mintDeviceId, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetFirstOpenLatch, resetSessionStartGuard, sanitizeUserId, themeFromBrand, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { o as WireOnboardingProps, p as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, q as OnboardingEvent, u as OnboardingCopy, a as ClientEventTarget, D as DeviceContext, C as ClientEvent, e as EnvelopeSource } from './currentSession-CxnP7gAa.js';
4
- export { A as AnalyticsEvent, b as ClientEventType, v as DeviceFormFactor, w as EXTRA_KEY_PREFIX, x as OnboardingProgress, R as RESERVED_USER_CONTEXT_KEYS, y as ResolveUserContextOptions, z as ResolvedUserContext, g as WIRE_ONBOARDING_EVENTS, h as WireOnboardingEventName, W as WireUserContext, B as collectDeviceContext, k as getCurrentSessionId, F as hashEmailFnv1a, G as isWireScalar, m as makeSessionId, H as namespaceExtra, r as reportClientEvent, l as reportClientEvents, n as resetCurrentSessionId, I as resolveUserContext, s as setCurrentSessionId, t as toAnalyticsEvent } from './currentSession-CxnP7gAa.js';
3
+ import { o as WireOnboardingProps, p as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, q as OnboardingEvent, u as OnboardingCopy, a as ClientEventTarget, D as DeviceContext, C as ClientEvent, e as EnvelopeSource } from './currentSession-f7LWcdWG.js';
4
+ export { A as AnalyticsEvent, b as ClientEventType, v as DeviceFormFactor, w as EXTRA_KEY_PREFIX, x as OnboardingProgress, R as RESERVED_USER_CONTEXT_KEYS, y as ResolveUserContextOptions, z as ResolvedUserContext, g as WIRE_ONBOARDING_EVENTS, h as WireOnboardingEventName, W as WireUserContext, B as collectDeviceContext, k as getCurrentSessionId, F as hashEmailFnv1a, G as isWireScalar, m as makeSessionId, H as namespaceExtra, r as reportClientEvent, l as reportClientEvents, n as resetCurrentSessionId, I as resolveUserContext, s as setCurrentSessionId, t as toAnalyticsEvent } from './currentSession-f7LWcdWG.js';
5
5
  import { O as OnboardingTheme } from './types-BKfpdZzX.js';
6
6
  export { a as OnboardingButtonStyle, b as OnboardingColors, c as OnboardingFonts, d as OnboardingRadius, e as OnboardingSpacing } from './types-BKfpdZzX.js';
7
7
  export { C as CenteredModal, a as CenteredModalHandle, b as CenteredModalProps } from './CenteredModal-Cdgns6--.js';
@@ -849,7 +849,7 @@ declare const attributionMetadata: (a: OnboardingAttribution) => {
849
849
  * Analytics must never be able to break onboarding.
850
850
  */
851
851
  /** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */
852
- type OptionalRequire = (moduleName: string) => unknown;
852
+ type OptionalRequire$1 = (moduleName: string) => unknown;
853
853
  /**
854
854
  * Detect the host app version, preferring `expo-constants` (`expoConfig.version`, then
855
855
  * `nativeAppVersion`) and finally `expo-application` (`nativeApplicationVersion`). Returns the
@@ -858,7 +858,40 @@ type OptionalRequire = (moduleName: string) => unknown;
858
858
  * `requireModule` is injectable so tests can exercise the "found" path without the native modules;
859
859
  * production defaults to the guarded runtime require above.
860
860
  */
861
- declare const detectAppVersion: (requireModule?: OptionalRequire) => string | undefined;
861
+ declare const detectAppVersion: (requireModule?: OptionalRequire$1) => string | undefined;
862
+
863
+ /**
864
+ * deviceModel — best-effort, DEPENDENCY-FREE detection of the device MODEL on iOS.
865
+ *
866
+ * WHY this exists (the asymmetry it closes): `collectDeviceContext` already reports `device.model`
867
+ * on Android straight from `Platform.constants.Model` (e.g. "SM-G991B"), but iOS `Platform.constants`
868
+ * exposes NO model — only `osVersion` / `interfaceIdiom`. So the analytics `by_model` breakdown was
869
+ * Android-only. This module fills the iOS gap with the SAME zero-dependency technique the kit already
870
+ * uses for `appVersion` (see device/appVersion.ts): a GUARDED, VARIABLE-specifier `require` of the
871
+ * common Expo `expo-device` module. If the host has it, iOS gets a model out of the box; if not, the
872
+ * require simply throws and is swallowed and iOS `model` stays omitted — nothing is forced, nothing
873
+ * is added to `package.json`, and a host without `expo-device` never fails to bundle.
874
+ *
875
+ * WHY it is NOT PII: `expo-device`'s `modelName` ("iPhone 14 Pro") and `modelId` ("iPhone15,2") are a
876
+ * device CLASS shared by millions of units — the same privacy category as the Android `Model` the kit
877
+ * already sends. It is NOT a unique device id / IDFA / fingerprint, so surfacing it changes no App
878
+ * Privacy / Data Safety declaration (identical guarantee to the rest of deviceContext). It deliberately
879
+ * does NOT read `expo-device`'s `deviceName` (that is the user-set name, e.g. "Malik's iPhone", and IS
880
+ * personal data).
881
+ *
882
+ * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.
883
+ */
884
+ /** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */
885
+ type OptionalRequire = (moduleName: string) => unknown;
886
+ /**
887
+ * Detect the device model via `expo-device`, preferring the human-readable `modelName`
888
+ * ("iPhone 14 Pro") and falling back to the identifier `modelId` ("iPhone15,2"). Returns the first
889
+ * real string, or `undefined` when `expo-device` is absent. Pure and never throws.
890
+ *
891
+ * `requireModule` is injectable so tests can exercise the "found" path without the native module;
892
+ * production defaults to the guarded runtime require above.
893
+ */
894
+ declare const detectNativeModel: (requireModule?: OptionalRequire) => string | undefined;
862
895
 
863
896
  /** Max accepted user-id length. Longer strings are truncated (never rejected). Keep in sync
864
897
  * with the server's `USER_ID_MAX_LENGTH` (analytics/events.py). */
@@ -906,6 +939,37 @@ type IdentifyOnboardingOptions = {
906
939
  */
907
940
  declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<boolean>;
908
941
 
942
+ /**
943
+ * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies
944
+ * none. This is the headline of "device fully automatic": the analytics façade auto-mints ONE id,
945
+ * persists it via the host's `storage` abstraction, and reuses it on every subsequent open — so
946
+ * `user_context.device_key` is ALWAYS present and the server's review/questionnaire gating +
947
+ * A/B stickiness (both key on `device_key`) work out of the box, with zero host wiring.
948
+ *
949
+ * WHY it is NOT PII and adds NO dependency (the kit's hard rules):
950
+ * The id is a random token generated from `Date.now()` + `Math.random()` — it carries NO hardware
951
+ * identifier, NO IDFA/GAID, NO fingerprint. It is a first-party per-install correlation key, the
952
+ * same privacy category as a first-party cookie: it groups a single install's sessions and cannot
953
+ * identify a person or be joined across apps. There is NO `uuid` (or any) dependency — a
954
+ * time+random scheme is sufficient because the id is minted ONCE and then persisted, so global
955
+ * uniqueness across the fleet is not required (a per-install collision is astronomically unlikely
956
+ * and inconsequential — worst case two installs share a bucket).
957
+ *
958
+ * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses
959
+ * that verbatim and never mints/persists an auto id.
960
+ */
961
+ /** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */
962
+ declare const AUTO_DEVICE_ID_PREFIX = "wdev_";
963
+ /** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */
964
+ declare const deviceIdStorageKey: (appId?: string) => string;
965
+ /**
966
+ * Mint a fresh per-install device id. Dependency-free (`Date.now()` + `Math.random()`), never
967
+ * throws, and returns a NEW value on every call — the façade mints ONCE and persists, so this is
968
+ * called at most once per install (then the persisted value is reused). Two random chunks plus the
969
+ * timestamp keep the token wide enough that a per-install collision is not a practical concern.
970
+ */
971
+ declare const mintDeviceId: () => string;
972
+
909
973
  /** The canonical event name for an app-open. A trigger keys off this exact string. */
910
974
  declare const SESSION_STARTED_EVENT: "app.session_started";
911
975
  /** Options for {@link reportSessionStart}. Everything except `target` is optional so a pre-auth
@@ -1132,4 +1196,4 @@ interface UseLifecycleEventsOptions {
1132
1196
  */
1133
1197
  declare const useLifecycleEvents: (config: LifecycleConfig | undefined, options?: UseLifecycleEventsOptions) => void;
1134
1198
 
1135
- export { AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardHandoff, type CardHandoffProps, type CardHandoffVariant, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, DoneBlock, ErrorBlock, FIRST_OPEN_EVENT, type IdentifyOnboardingOptions, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, USER_ID_MAX_LENGTH, type UseLifecycleEventsOptions, type UseSessionStartOptions, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, attributionMetadata, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, detectAppVersion, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, identifyOnboarding, isFeaturesFresh, isOnboardingEnabled, mergeTheme, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetFirstOpenLatch, resetSessionStartGuard, sanitizeUserId, themeFromBrand, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };
1199
+ export { AUTO_DEVICE_ID_PREFIX, AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardHandoff, type CardHandoffProps, type CardHandoffVariant, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, DoneBlock, ErrorBlock, FIRST_OPEN_EVENT, type IdentifyOnboardingOptions, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, USER_ID_MAX_LENGTH, type UseLifecycleEventsOptions, type UseSessionStartOptions, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, attributionMetadata, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, detectAppVersion, detectNativeModel, deviceIdStorageKey, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, identifyOnboarding, isFeaturesFresh, isOnboardingEnabled, mergeTheme, mintDeviceId, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetFirstOpenLatch, resetSessionStartGuard, sanitizeUserId, themeFromBrand, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };
package/dist/index.js CHANGED
@@ -2405,6 +2405,47 @@ var detectAppVersion = (requireModule = runtimeRequire) => {
2405
2405
  return void 0;
2406
2406
  };
2407
2407
 
2408
+ // src/device/deviceModel.ts
2409
+ var coerceModel = (value) => {
2410
+ if (typeof value !== "string") return void 0;
2411
+ const trimmed = value.trim();
2412
+ return trimmed.length > 0 ? trimmed : void 0;
2413
+ };
2414
+ var runtimeRequire2 = (moduleName) => {
2415
+ try {
2416
+ if (typeof __require !== "function") return void 0;
2417
+ return __require(moduleName);
2418
+ } catch {
2419
+ return void 0;
2420
+ }
2421
+ };
2422
+ var interop2 = (mod) => {
2423
+ if (!mod || typeof mod !== "object") return void 0;
2424
+ const def = mod.default;
2425
+ if (def && typeof def === "object") return def;
2426
+ return mod;
2427
+ };
2428
+ var safeInterop2 = (requireModule, moduleName) => {
2429
+ try {
2430
+ return interop2(requireModule(moduleName));
2431
+ } catch {
2432
+ return void 0;
2433
+ }
2434
+ };
2435
+ var detectNativeModel = (requireModule = runtimeRequire2) => {
2436
+ try {
2437
+ const device = safeInterop2(requireModule, "expo-device");
2438
+ if (device) {
2439
+ const modelName = coerceModel(device.modelName);
2440
+ if (modelName) return modelName;
2441
+ const modelId = coerceModel(device.modelId);
2442
+ if (modelId) return modelId;
2443
+ }
2444
+ } catch {
2445
+ }
2446
+ return void 0;
2447
+ };
2448
+
2408
2449
  // src/device/deviceContext.ts
2409
2450
  var deriveFormFactor = (iosIdiom, width, height) => {
2410
2451
  if (iosIdiom === "pad") return "tablet";
@@ -2451,6 +2492,8 @@ var collectDeviceContext = () => {
2451
2492
  ctx.interfaceIdiom = idiom;
2452
2493
  iosIdiom = idiom;
2453
2494
  }
2495
+ const iosModel = detectNativeModel();
2496
+ if (iosModel) ctx.model = iosModel;
2454
2497
  }
2455
2498
  } catch {
2456
2499
  }
@@ -3299,6 +3342,15 @@ var resolveUserContext = (ctx = {}, opts = {}) => {
3299
3342
  return result;
3300
3343
  };
3301
3344
 
3345
+ // src/context/deviceId.ts
3346
+ var AUTO_DEVICE_ID_PREFIX = "wdev_";
3347
+ var deviceIdStorageKey = (appId) => `wireai:analytics:deviceKey:${appId != null ? appId : "default"}`;
3348
+ var randomChunk = () => Math.floor(Math.random() * 4294967296).toString(36).padStart(6, "0");
3349
+ var mintDeviceId = () => {
3350
+ const time = Date.now().toString(36);
3351
+ return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;
3352
+ };
3353
+
3302
3354
  // src/session-analytics/reportSessionStart.ts
3303
3355
  var SESSION_STARTED_EVENT = "app.session_started";
3304
3356
  var _emitted = /* @__PURE__ */ new Set();
@@ -3798,6 +3850,7 @@ var useLifecycleEvents = (config, options = {}) => {
3798
3850
  }, []);
3799
3851
  };
3800
3852
 
3853
+ exports.AUTO_DEVICE_ID_PREFIX = AUTO_DEVICE_ID_PREFIX;
3801
3854
  exports.AnimatedSparkle = AnimatedSparkle;
3802
3855
  exports.BACKGROUND_SESSION_MS = BACKGROUND_SESSION_MS;
3803
3856
  exports.CardHandoff = CardHandoff;
@@ -3838,6 +3891,8 @@ exports.defaultOnboardingTheme = defaultOnboardingTheme;
3838
3891
  exports.defaultWireFeatures = defaultWireFeatures;
3839
3892
  exports.deriveAnswers = deriveAnswers;
3840
3893
  exports.detectAppVersion = detectAppVersion;
3894
+ exports.detectNativeModel = detectNativeModel;
3895
+ exports.deviceIdStorageKey = deviceIdStorageKey;
3841
3896
  exports.featuresCacheKey = featuresCacheKey;
3842
3897
  exports.featuresEqual = featuresEqual;
3843
3898
  exports.fetchWireFeatures = fetchWireFeatures;
@@ -3851,6 +3906,7 @@ exports.isWireScalar = isWireScalar;
3851
3906
  exports.loadPersistedSession = loadPersistedSession;
3852
3907
  exports.makeSessionId = makeSessionId;
3853
3908
  exports.mergeTheme = mergeTheme;
3909
+ exports.mintDeviceId = mintDeviceId;
3854
3910
  exports.motionSpec = motionSpec_exports;
3855
3911
  exports.namespaceExtra = namespaceExtra;
3856
3912
  exports.onboardingComponents = onboardingComponents;