@wireai/activation 0.4.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.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +92 -0
- package/dist/analytics/index.d.mts +19 -2
- package/dist/analytics/index.d.ts +19 -2
- package/dist/analytics/index.js +258 -18
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +256 -19
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/{eventQueue-CA1d8Fmn.d.mts → currentSession-d9CrBxwe.d.mts} +152 -16
- package/dist/{eventQueue-CrNB9gzH.d.ts → currentSession-f7LWcdWG.d.ts} +152 -16
- package/dist/index.d.mts +96 -32
- package/dist/index.d.ts +96 -32
- package/dist/index.js +214 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +201 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/WireOnboarding.tsx +4 -3
- package/src/analytics/analyticsFacade.ts +120 -12
- package/src/analytics/contextEnvelope.ts +13 -7
- package/src/analytics/currentSession.ts +35 -0
- package/src/analytics/index.ts +3 -0
- package/src/context/deviceId.ts +43 -0
- package/src/context/userContext.ts +210 -0
- package/src/device/appVersion.ts +103 -0
- package/src/device/deviceContext.ts +31 -6
- package/src/device/deviceModel.ts +93 -0
- package/src/identity/userIdentity.ts +5 -0
- package/src/index.ts +25 -0
- package/src/session-analytics/reportSessionStart.ts +7 -0
- package/src/session-analytics/useLifecycleEvents.ts +4 -2
- package/src/session-analytics/useSessionStart.ts +2 -1
- package/src/types.ts +6 -5
|
@@ -11,9 +11,12 @@ import { Platform } from 'react-native';
|
|
|
11
11
|
* adding a single dependency to the kit or changing a host app's App Privacy / Data Safety
|
|
12
12
|
* declarations.
|
|
13
13
|
*
|
|
14
|
-
* HARD RULE (why this file
|
|
14
|
+
* HARD RULE (why this file adds no dependency):
|
|
15
15
|
* The kit stays dependency-free. Everything here comes from `Platform`, `Dimensions`,
|
|
16
|
-
* `I18nManager`, and the standard `Intl` global
|
|
16
|
+
* `I18nManager`, and the standard `Intl` global — plus a best-effort `appVersion` read via
|
|
17
|
+
* `detectAppVersion()`, which itself adds NO dependency (it reaches for `expo-constants` /
|
|
18
|
+
* `expo-application` through a guarded, variable-specifier require that a host without them
|
|
19
|
+
* simply never resolves — see device/appVersion.ts). There are NO advertising IDs, NO
|
|
17
20
|
* `getUniqueId`/IDFA/GAID/fingerprinting APIs, and nothing that would require a new
|
|
18
21
|
* privacy-label entry. A host can adopt this without touching its store declarations.
|
|
19
22
|
*
|
|
@@ -36,7 +39,15 @@ type DeviceContext = {
|
|
|
36
39
|
osVersion?: string;
|
|
37
40
|
/** Android device brand (e.g. "samsung"). Android only. */
|
|
38
41
|
brand?: string;
|
|
39
|
-
/**
|
|
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
|
+
*/
|
|
40
51
|
model?: string;
|
|
41
52
|
/** iOS interface idiom ("phone" | "pad" | …), when reported. iOS only. */
|
|
42
53
|
interfaceIdiom?: string;
|
|
@@ -55,9 +66,11 @@ type DeviceContext = {
|
|
|
55
66
|
/** IANA time zone (e.g. "Europe/Berlin"), from `Intl` when available. */
|
|
56
67
|
timeZone?: string;
|
|
57
68
|
/**
|
|
58
|
-
* Host app version (e.g. "1.4.2).
|
|
59
|
-
*
|
|
60
|
-
*
|
|
69
|
+
* Host app version (e.g. "1.4.2"). BEST-EFFORT auto-detected here via `detectAppVersion()`
|
|
70
|
+
* (reads `expo-constants` / `expo-application` when present; adds no dependency — see
|
|
71
|
+
* device/appVersion.ts). An explicit host-injected `config.appVersion` always WINS: the merge
|
|
72
|
+
* sites (`WireOnboarding`, the session-analytics hooks, the context envelope) overwrite this
|
|
73
|
+
* with the host value when one is supplied. Omitted when neither source yields a version.
|
|
61
74
|
*/
|
|
62
75
|
appVersion?: string;
|
|
63
76
|
};
|
|
@@ -179,11 +192,12 @@ type WireOnboardingConfig = {
|
|
|
179
192
|
*/
|
|
180
193
|
metadata?: Record<string, unknown>;
|
|
181
194
|
/**
|
|
182
|
-
* Host app version string (e.g. "1.4.2").
|
|
183
|
-
*
|
|
184
|
-
* (`
|
|
185
|
-
*
|
|
186
|
-
*
|
|
195
|
+
* Host app version string (e.g. "1.4.2"). OPTIONAL — when omitted, the kit makes a best-effort
|
|
196
|
+
* auto-detection from `expo-constants` (`Constants.expoConfig?.version` / `nativeAppVersion`) or
|
|
197
|
+
* `expo-application` (`nativeApplicationVersion`) WITHOUT adding a dependency (a host that lacks
|
|
198
|
+
* those modules just gets no version — see device/appVersion.ts). Pass this to override the
|
|
199
|
+
* auto-detected value (it always wins). Forwarded to the backend on the session metadata and on
|
|
200
|
+
* client events (as `device.appVersion`) so analytics can segment the funnel by app version.
|
|
187
201
|
*/
|
|
188
202
|
appVersion?: string;
|
|
189
203
|
};
|
|
@@ -451,7 +465,7 @@ type ContextEnvelope = {
|
|
|
451
465
|
device: DeviceContext;
|
|
452
466
|
/** Correlation id for this app-open / flow (caller-supplied). */
|
|
453
467
|
sessionId?: string;
|
|
454
|
-
/**
|
|
468
|
+
/** App version, e.g. "1.4.2" (mirrors `device.appVersion`; host-injected, else auto-detected). */
|
|
455
469
|
appVersion?: string;
|
|
456
470
|
/** Host native build number, e.g. "412" (from `expo-constants` `nativeBuildVersion`). */
|
|
457
471
|
appBuild?: string;
|
|
@@ -466,9 +480,10 @@ type ContextEnvelopeInput = {
|
|
|
466
480
|
networkType?: string;
|
|
467
481
|
};
|
|
468
482
|
/**
|
|
469
|
-
* Build a fresh context envelope. Reuses `collectDeviceContext()` for the device block
|
|
470
|
-
*
|
|
471
|
-
*
|
|
483
|
+
* Build a fresh context envelope. Reuses `collectDeviceContext()` for the device block (which
|
|
484
|
+
* already carries a best-effort auto-detected `appVersion`) and layers the host-injected scalars
|
|
485
|
+
* on top. An explicit `input.appVersion` overrides the auto-detected `device.appVersion`, and the
|
|
486
|
+
* outer `appVersion` scalar mirrors whichever version is effective.
|
|
472
487
|
*
|
|
473
488
|
* Returns a NEW object on every call (no shared mutable reference), so a caller can hold or mutate
|
|
474
489
|
* the result without leaking into the next envelope. Never throws — `collectDeviceContext` is
|
|
@@ -547,4 +562,125 @@ type EventQueue = {
|
|
|
547
562
|
*/
|
|
548
563
|
declare const createEventQueue: (options: EventQueueOptions) => EventQueue;
|
|
549
564
|
|
|
550
|
-
|
|
565
|
+
/**
|
|
566
|
+
* The single, extensible user-context object. A host passes it ONCE (at analytics init) and may
|
|
567
|
+
* update it post-mount (e.g. attach `userId`/`userEmail` at login) via `setUserContext(partial)`.
|
|
568
|
+
* Every field is optional; missing fields are omitted from the wire payload.
|
|
569
|
+
*/
|
|
570
|
+
interface WireUserContext {
|
|
571
|
+
/**
|
|
572
|
+
* Host app version, e.g. "1.4.2". EXPLICIT — wins over the #42 auto-detected `device.appVersion`.
|
|
573
|
+
* Lands in `user_context.app_version`. Omitted when neither this nor auto-detect yields a version.
|
|
574
|
+
*/
|
|
575
|
+
appVersion?: string;
|
|
576
|
+
/**
|
|
577
|
+
* A stable, non-PII device id the host owns. Lands in `user_context.device_key` (NOT `session_id`),
|
|
578
|
+
* where the server groups a device's sessions. Host-supplied; the kit never mints or reads one.
|
|
579
|
+
*/
|
|
580
|
+
deviceKey?: string;
|
|
581
|
+
/**
|
|
582
|
+
* The host's OPAQUE PSEUDONYMOUS user id (their internal id — NOT an email/name/phone). Sanitized +
|
|
583
|
+
* capped (see `sanitizeUserId`) and placed on the event's top-level `user_id`. NEVER the bucket.
|
|
584
|
+
*/
|
|
585
|
+
userId?: string;
|
|
586
|
+
/**
|
|
587
|
+
* OPT-IN PII. The user's email, its OWN field (`user_context.user_email`) — NEVER merged into
|
|
588
|
+
* `userId`. The kit NEVER auto-collects this; a host passes it only WITH the user's consent (EU
|
|
589
|
+
* users: treat as personal data). For a non-reversible form, set {@link hashEmail} `true` (the kit
|
|
590
|
+
* folds it with a dependency-free hash and stamps `user_context.user_email_hashed: true`), OR
|
|
591
|
+
* pre-hash host-side with a cryptographic digest and pass that here with `hashEmail` falsy.
|
|
592
|
+
*/
|
|
593
|
+
userEmail?: string;
|
|
594
|
+
/**
|
|
595
|
+
* When `true`, {@link userEmail} is folded with the kit's dependency-free {@link hashEmailFnv1a}
|
|
596
|
+
* before it leaves the device, and `user_context.user_email_hashed` is set `true`. NOTE: FNV-1a is
|
|
597
|
+
* a lightweight NON-cryptographic fold (obfuscation, not a secure digest). For a cryptographic
|
|
598
|
+
* hash, compute it host-side (e.g. SHA-256 via `expo-crypto`) and pass the digest as `userEmail`
|
|
599
|
+
* with `hashEmail` falsy. Default: raw email is sent as-is (opt-in already gated it upstream).
|
|
600
|
+
*/
|
|
601
|
+
hashEmail?: boolean;
|
|
602
|
+
/**
|
|
603
|
+
* Arbitrary host context (signup method, referral, plan tier…). Each value is coerced to a scalar
|
|
604
|
+
* (`string | number | boolean`; non-scalars and non-finite numbers are DROPPED) and NAMESPACED
|
|
605
|
+
* under a `custom.` key prefix in `user_context` (e.g. `user_context["custom.referral"]`) so it can
|
|
606
|
+
* never collide with a reserved key. No raw PII — use {@link userEmail} for email.
|
|
607
|
+
*/
|
|
608
|
+
extra?: Record<string, string | number | boolean>;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* The wire-shaped result of {@link resolveUserContext}. `userContext` is the non-PII/opt-in-PII
|
|
612
|
+
* bucket stamped onto the event; `userId` is the top-level opaque id; `appVersion`/`deviceKey` are
|
|
613
|
+
* echoed for callers that also place them elsewhere (e.g. `device.appVersion`). Absent fields are
|
|
614
|
+
* omitted so a caller can spread this without sending empties.
|
|
615
|
+
*/
|
|
616
|
+
interface ResolvedUserContext {
|
|
617
|
+
/** The opaque, sanitized user id → the event's top-level `user_id`. Omitted when unset/blank. */
|
|
618
|
+
userId?: string;
|
|
619
|
+
/** The stable device id → `user_context.device_key`. Omitted when unset. */
|
|
620
|
+
deviceKey?: string;
|
|
621
|
+
/** The effective app version (explicit > auto-detected) → `user_context.app_version`. */
|
|
622
|
+
appVersion?: string;
|
|
623
|
+
/** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */
|
|
624
|
+
userContext?: Record<string, string | number | boolean>;
|
|
625
|
+
}
|
|
626
|
+
/** Reserved `user_context` keys the kit itself writes; host `extra` is namespaced away from these. */
|
|
627
|
+
declare const RESERVED_USER_CONTEXT_KEYS: readonly ["device_key", "app_version", "app_build", "network_type", "session_count", "returning", "platform", "user_email", "user_email_hashed"];
|
|
628
|
+
/** The prefix applied to every host `extra` key so it can never collide with a reserved key. */
|
|
629
|
+
declare const EXTRA_KEY_PREFIX: "custom.";
|
|
630
|
+
/** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */
|
|
631
|
+
declare const isWireScalar: (value: unknown) => value is string | number | boolean;
|
|
632
|
+
/**
|
|
633
|
+
* Fold an email to a stable, dependency-free 32-bit FNV-1a hex token (lowercased + trimmed first so
|
|
634
|
+
* the same address always folds identically). This is OBFUSCATION, not a cryptographic digest — it
|
|
635
|
+
* is not collision-resistant. For a real hash, pre-hash host-side and pass the digest as `userEmail`.
|
|
636
|
+
*/
|
|
637
|
+
declare const hashEmailFnv1a: (email: string) => string;
|
|
638
|
+
/**
|
|
639
|
+
* Coerce a host `extra` map into the namespaced, scalar-only bucket shape. Every kept value is
|
|
640
|
+
* placed under `custom.<key>`; non-scalar values (objects, arrays, null, functions, NaN/Infinity)
|
|
641
|
+
* are DROPPED. Returns an object (possibly empty).
|
|
642
|
+
*/
|
|
643
|
+
declare const namespaceExtra: (extra: Record<string, unknown> | undefined) => Record<string, string | number | boolean>;
|
|
644
|
+
/** Options for {@link resolveUserContext}. */
|
|
645
|
+
interface ResolveUserContextOptions {
|
|
646
|
+
/**
|
|
647
|
+
* The kit's best-effort auto-detected app version (#42; from `detectAppVersion()`/the device
|
|
648
|
+
* snapshot). Used ONLY when the explicit `WireUserContext.appVersion` is absent — explicit wins.
|
|
649
|
+
*/
|
|
650
|
+
autoAppVersion?: string;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Merge a {@link WireUserContext} into the wire shape with the precedence rule (explicit field >
|
|
654
|
+
* auto-detected). Pure, never throws. Missing fields are omitted so the result can be spread onto an
|
|
655
|
+
* event without sending empties.
|
|
656
|
+
*/
|
|
657
|
+
declare const resolveUserContext: (ctx?: WireUserContext, opts?: ResolveUserContextOptions) => ResolvedUserContext;
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* currentSession — a tiny module-level registry of the CURRENT per-open `session_id`.
|
|
661
|
+
*
|
|
662
|
+
* WHY it exists (kills the phantom-session): the per-open emitters (`reportSessionStart` and the
|
|
663
|
+
* `useSessionStart` / `useLifecycleEvents` hooks) mint a fresh `session_id` for each app-open and
|
|
664
|
+
* post `app.session_started` with it — so the SERVER knows that id. But other client paths
|
|
665
|
+
* (`identify`, host `app_event`s through the analytics façade) used to reference a DIFFERENT id
|
|
666
|
+
* (a frozen per-instance id), which the server had never seen, so it back-filled a synthetic
|
|
667
|
+
* `session_started` — inflating session counts (the Morrow/Myelino "phantom-session" bug).
|
|
668
|
+
*
|
|
669
|
+
* This registry is the single seam that lets those paths reuse the LIVE per-open session id the
|
|
670
|
+
* server already ingested. `reportSessionStart` writes the current id here on every open; the façade
|
|
671
|
+
* reads it so `identify`/app-events correlate to the real session instead of minting a phantom.
|
|
672
|
+
*
|
|
673
|
+
* DEPENDENCY-FREE + PROCESS-LOCAL: a plain module variable. It is intentionally NOT persisted — it
|
|
674
|
+
* tracks the CURRENT process's open, and a fresh open always overwrites it. No cross-launch state.
|
|
675
|
+
*/
|
|
676
|
+
/**
|
|
677
|
+
* Record the current per-open `session_id`. Called by `reportSessionStart` when it emits an
|
|
678
|
+
* app-open. A blank / non-string id is ignored (the previous id stays current). Idempotent.
|
|
679
|
+
*/
|
|
680
|
+
declare const setCurrentSessionId: (id: string | undefined) => void;
|
|
681
|
+
/** The current per-open `session_id`, or `undefined` when no app-open has been registered yet. */
|
|
682
|
+
declare const getCurrentSessionId: () => string | undefined;
|
|
683
|
+
/** Test-only: forget the current session id so a unit test starts from a clean registry. */
|
|
684
|
+
declare const resetCurrentSessionId: () => void;
|
|
685
|
+
|
|
686
|
+
export { type AnalyticsEvent as A, collectDeviceContext as B, type ClientEvent as C, type DeviceContext as D, type EventQueueOptions as E, hashEmailFnv1a as F, isWireScalar as G, namespaceExtra as H, resolveUserContext as I, type OnboardingResult as O, RESERVED_USER_CONTEXT_KEYS as R, type StepValidator as S, type WireUserContext as W, type ClientEventTarget as a, type ClientEventType as b, type ContextEnvelope as c, type ContextEnvelopeInput as d, type EnvelopeSource as e, type EventQueue as f, WIRE_ONBOARDING_EVENTS as g, type WireOnboardingEventName as h, buildContextEnvelope as i, createEventQueue as j, getCurrentSessionId as k, reportClientEvents as l, makeSessionId as m, resetCurrentSessionId as n, type WireOnboardingProps as o, type WireOnboardingConfig as p, type OnboardingEvent as q, reportClientEvent as r, setCurrentSessionId as s, toAnalyticsEvent as t, type OnboardingCopy as u, type DeviceFormFactor as v, EXTRA_KEY_PREFIX as w, type OnboardingProgress as x, type ResolveUserContextOptions as y, type ResolvedUserContext as z };
|
|
@@ -11,9 +11,12 @@ import { Platform } from 'react-native';
|
|
|
11
11
|
* adding a single dependency to the kit or changing a host app's App Privacy / Data Safety
|
|
12
12
|
* declarations.
|
|
13
13
|
*
|
|
14
|
-
* HARD RULE (why this file
|
|
14
|
+
* HARD RULE (why this file adds no dependency):
|
|
15
15
|
* The kit stays dependency-free. Everything here comes from `Platform`, `Dimensions`,
|
|
16
|
-
* `I18nManager`, and the standard `Intl` global
|
|
16
|
+
* `I18nManager`, and the standard `Intl` global — plus a best-effort `appVersion` read via
|
|
17
|
+
* `detectAppVersion()`, which itself adds NO dependency (it reaches for `expo-constants` /
|
|
18
|
+
* `expo-application` through a guarded, variable-specifier require that a host without them
|
|
19
|
+
* simply never resolves — see device/appVersion.ts). There are NO advertising IDs, NO
|
|
17
20
|
* `getUniqueId`/IDFA/GAID/fingerprinting APIs, and nothing that would require a new
|
|
18
21
|
* privacy-label entry. A host can adopt this without touching its store declarations.
|
|
19
22
|
*
|
|
@@ -36,7 +39,15 @@ type DeviceContext = {
|
|
|
36
39
|
osVersion?: string;
|
|
37
40
|
/** Android device brand (e.g. "samsung"). Android only. */
|
|
38
41
|
brand?: string;
|
|
39
|
-
/**
|
|
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
|
+
*/
|
|
40
51
|
model?: string;
|
|
41
52
|
/** iOS interface idiom ("phone" | "pad" | …), when reported. iOS only. */
|
|
42
53
|
interfaceIdiom?: string;
|
|
@@ -55,9 +66,11 @@ type DeviceContext = {
|
|
|
55
66
|
/** IANA time zone (e.g. "Europe/Berlin"), from `Intl` when available. */
|
|
56
67
|
timeZone?: string;
|
|
57
68
|
/**
|
|
58
|
-
* Host app version (e.g. "1.4.2).
|
|
59
|
-
*
|
|
60
|
-
*
|
|
69
|
+
* Host app version (e.g. "1.4.2"). BEST-EFFORT auto-detected here via `detectAppVersion()`
|
|
70
|
+
* (reads `expo-constants` / `expo-application` when present; adds no dependency — see
|
|
71
|
+
* device/appVersion.ts). An explicit host-injected `config.appVersion` always WINS: the merge
|
|
72
|
+
* sites (`WireOnboarding`, the session-analytics hooks, the context envelope) overwrite this
|
|
73
|
+
* with the host value when one is supplied. Omitted when neither source yields a version.
|
|
61
74
|
*/
|
|
62
75
|
appVersion?: string;
|
|
63
76
|
};
|
|
@@ -179,11 +192,12 @@ type WireOnboardingConfig = {
|
|
|
179
192
|
*/
|
|
180
193
|
metadata?: Record<string, unknown>;
|
|
181
194
|
/**
|
|
182
|
-
* Host app version string (e.g. "1.4.2").
|
|
183
|
-
*
|
|
184
|
-
* (`
|
|
185
|
-
*
|
|
186
|
-
*
|
|
195
|
+
* Host app version string (e.g. "1.4.2"). OPTIONAL — when omitted, the kit makes a best-effort
|
|
196
|
+
* auto-detection from `expo-constants` (`Constants.expoConfig?.version` / `nativeAppVersion`) or
|
|
197
|
+
* `expo-application` (`nativeApplicationVersion`) WITHOUT adding a dependency (a host that lacks
|
|
198
|
+
* those modules just gets no version — see device/appVersion.ts). Pass this to override the
|
|
199
|
+
* auto-detected value (it always wins). Forwarded to the backend on the session metadata and on
|
|
200
|
+
* client events (as `device.appVersion`) so analytics can segment the funnel by app version.
|
|
187
201
|
*/
|
|
188
202
|
appVersion?: string;
|
|
189
203
|
};
|
|
@@ -451,7 +465,7 @@ type ContextEnvelope = {
|
|
|
451
465
|
device: DeviceContext;
|
|
452
466
|
/** Correlation id for this app-open / flow (caller-supplied). */
|
|
453
467
|
sessionId?: string;
|
|
454
|
-
/**
|
|
468
|
+
/** App version, e.g. "1.4.2" (mirrors `device.appVersion`; host-injected, else auto-detected). */
|
|
455
469
|
appVersion?: string;
|
|
456
470
|
/** Host native build number, e.g. "412" (from `expo-constants` `nativeBuildVersion`). */
|
|
457
471
|
appBuild?: string;
|
|
@@ -466,9 +480,10 @@ type ContextEnvelopeInput = {
|
|
|
466
480
|
networkType?: string;
|
|
467
481
|
};
|
|
468
482
|
/**
|
|
469
|
-
* Build a fresh context envelope. Reuses `collectDeviceContext()` for the device block
|
|
470
|
-
*
|
|
471
|
-
*
|
|
483
|
+
* Build a fresh context envelope. Reuses `collectDeviceContext()` for the device block (which
|
|
484
|
+
* already carries a best-effort auto-detected `appVersion`) and layers the host-injected scalars
|
|
485
|
+
* on top. An explicit `input.appVersion` overrides the auto-detected `device.appVersion`, and the
|
|
486
|
+
* outer `appVersion` scalar mirrors whichever version is effective.
|
|
472
487
|
*
|
|
473
488
|
* Returns a NEW object on every call (no shared mutable reference), so a caller can hold or mutate
|
|
474
489
|
* the result without leaking into the next envelope. Never throws — `collectDeviceContext` is
|
|
@@ -547,4 +562,125 @@ type EventQueue = {
|
|
|
547
562
|
*/
|
|
548
563
|
declare const createEventQueue: (options: EventQueueOptions) => EventQueue;
|
|
549
564
|
|
|
550
|
-
|
|
565
|
+
/**
|
|
566
|
+
* The single, extensible user-context object. A host passes it ONCE (at analytics init) and may
|
|
567
|
+
* update it post-mount (e.g. attach `userId`/`userEmail` at login) via `setUserContext(partial)`.
|
|
568
|
+
* Every field is optional; missing fields are omitted from the wire payload.
|
|
569
|
+
*/
|
|
570
|
+
interface WireUserContext {
|
|
571
|
+
/**
|
|
572
|
+
* Host app version, e.g. "1.4.2". EXPLICIT — wins over the #42 auto-detected `device.appVersion`.
|
|
573
|
+
* Lands in `user_context.app_version`. Omitted when neither this nor auto-detect yields a version.
|
|
574
|
+
*/
|
|
575
|
+
appVersion?: string;
|
|
576
|
+
/**
|
|
577
|
+
* A stable, non-PII device id the host owns. Lands in `user_context.device_key` (NOT `session_id`),
|
|
578
|
+
* where the server groups a device's sessions. Host-supplied; the kit never mints or reads one.
|
|
579
|
+
*/
|
|
580
|
+
deviceKey?: string;
|
|
581
|
+
/**
|
|
582
|
+
* The host's OPAQUE PSEUDONYMOUS user id (their internal id — NOT an email/name/phone). Sanitized +
|
|
583
|
+
* capped (see `sanitizeUserId`) and placed on the event's top-level `user_id`. NEVER the bucket.
|
|
584
|
+
*/
|
|
585
|
+
userId?: string;
|
|
586
|
+
/**
|
|
587
|
+
* OPT-IN PII. The user's email, its OWN field (`user_context.user_email`) — NEVER merged into
|
|
588
|
+
* `userId`. The kit NEVER auto-collects this; a host passes it only WITH the user's consent (EU
|
|
589
|
+
* users: treat as personal data). For a non-reversible form, set {@link hashEmail} `true` (the kit
|
|
590
|
+
* folds it with a dependency-free hash and stamps `user_context.user_email_hashed: true`), OR
|
|
591
|
+
* pre-hash host-side with a cryptographic digest and pass that here with `hashEmail` falsy.
|
|
592
|
+
*/
|
|
593
|
+
userEmail?: string;
|
|
594
|
+
/**
|
|
595
|
+
* When `true`, {@link userEmail} is folded with the kit's dependency-free {@link hashEmailFnv1a}
|
|
596
|
+
* before it leaves the device, and `user_context.user_email_hashed` is set `true`. NOTE: FNV-1a is
|
|
597
|
+
* a lightweight NON-cryptographic fold (obfuscation, not a secure digest). For a cryptographic
|
|
598
|
+
* hash, compute it host-side (e.g. SHA-256 via `expo-crypto`) and pass the digest as `userEmail`
|
|
599
|
+
* with `hashEmail` falsy. Default: raw email is sent as-is (opt-in already gated it upstream).
|
|
600
|
+
*/
|
|
601
|
+
hashEmail?: boolean;
|
|
602
|
+
/**
|
|
603
|
+
* Arbitrary host context (signup method, referral, plan tier…). Each value is coerced to a scalar
|
|
604
|
+
* (`string | number | boolean`; non-scalars and non-finite numbers are DROPPED) and NAMESPACED
|
|
605
|
+
* under a `custom.` key prefix in `user_context` (e.g. `user_context["custom.referral"]`) so it can
|
|
606
|
+
* never collide with a reserved key. No raw PII — use {@link userEmail} for email.
|
|
607
|
+
*/
|
|
608
|
+
extra?: Record<string, string | number | boolean>;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* The wire-shaped result of {@link resolveUserContext}. `userContext` is the non-PII/opt-in-PII
|
|
612
|
+
* bucket stamped onto the event; `userId` is the top-level opaque id; `appVersion`/`deviceKey` are
|
|
613
|
+
* echoed for callers that also place them elsewhere (e.g. `device.appVersion`). Absent fields are
|
|
614
|
+
* omitted so a caller can spread this without sending empties.
|
|
615
|
+
*/
|
|
616
|
+
interface ResolvedUserContext {
|
|
617
|
+
/** The opaque, sanitized user id → the event's top-level `user_id`. Omitted when unset/blank. */
|
|
618
|
+
userId?: string;
|
|
619
|
+
/** The stable device id → `user_context.device_key`. Omitted when unset. */
|
|
620
|
+
deviceKey?: string;
|
|
621
|
+
/** The effective app version (explicit > auto-detected) → `user_context.app_version`. */
|
|
622
|
+
appVersion?: string;
|
|
623
|
+
/** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */
|
|
624
|
+
userContext?: Record<string, string | number | boolean>;
|
|
625
|
+
}
|
|
626
|
+
/** Reserved `user_context` keys the kit itself writes; host `extra` is namespaced away from these. */
|
|
627
|
+
declare const RESERVED_USER_CONTEXT_KEYS: readonly ["device_key", "app_version", "app_build", "network_type", "session_count", "returning", "platform", "user_email", "user_email_hashed"];
|
|
628
|
+
/** The prefix applied to every host `extra` key so it can never collide with a reserved key. */
|
|
629
|
+
declare const EXTRA_KEY_PREFIX: "custom.";
|
|
630
|
+
/** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */
|
|
631
|
+
declare const isWireScalar: (value: unknown) => value is string | number | boolean;
|
|
632
|
+
/**
|
|
633
|
+
* Fold an email to a stable, dependency-free 32-bit FNV-1a hex token (lowercased + trimmed first so
|
|
634
|
+
* the same address always folds identically). This is OBFUSCATION, not a cryptographic digest — it
|
|
635
|
+
* is not collision-resistant. For a real hash, pre-hash host-side and pass the digest as `userEmail`.
|
|
636
|
+
*/
|
|
637
|
+
declare const hashEmailFnv1a: (email: string) => string;
|
|
638
|
+
/**
|
|
639
|
+
* Coerce a host `extra` map into the namespaced, scalar-only bucket shape. Every kept value is
|
|
640
|
+
* placed under `custom.<key>`; non-scalar values (objects, arrays, null, functions, NaN/Infinity)
|
|
641
|
+
* are DROPPED. Returns an object (possibly empty).
|
|
642
|
+
*/
|
|
643
|
+
declare const namespaceExtra: (extra: Record<string, unknown> | undefined) => Record<string, string | number | boolean>;
|
|
644
|
+
/** Options for {@link resolveUserContext}. */
|
|
645
|
+
interface ResolveUserContextOptions {
|
|
646
|
+
/**
|
|
647
|
+
* The kit's best-effort auto-detected app version (#42; from `detectAppVersion()`/the device
|
|
648
|
+
* snapshot). Used ONLY when the explicit `WireUserContext.appVersion` is absent — explicit wins.
|
|
649
|
+
*/
|
|
650
|
+
autoAppVersion?: string;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Merge a {@link WireUserContext} into the wire shape with the precedence rule (explicit field >
|
|
654
|
+
* auto-detected). Pure, never throws. Missing fields are omitted so the result can be spread onto an
|
|
655
|
+
* event without sending empties.
|
|
656
|
+
*/
|
|
657
|
+
declare const resolveUserContext: (ctx?: WireUserContext, opts?: ResolveUserContextOptions) => ResolvedUserContext;
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* currentSession — a tiny module-level registry of the CURRENT per-open `session_id`.
|
|
661
|
+
*
|
|
662
|
+
* WHY it exists (kills the phantom-session): the per-open emitters (`reportSessionStart` and the
|
|
663
|
+
* `useSessionStart` / `useLifecycleEvents` hooks) mint a fresh `session_id` for each app-open and
|
|
664
|
+
* post `app.session_started` with it — so the SERVER knows that id. But other client paths
|
|
665
|
+
* (`identify`, host `app_event`s through the analytics façade) used to reference a DIFFERENT id
|
|
666
|
+
* (a frozen per-instance id), which the server had never seen, so it back-filled a synthetic
|
|
667
|
+
* `session_started` — inflating session counts (the Morrow/Myelino "phantom-session" bug).
|
|
668
|
+
*
|
|
669
|
+
* This registry is the single seam that lets those paths reuse the LIVE per-open session id the
|
|
670
|
+
* server already ingested. `reportSessionStart` writes the current id here on every open; the façade
|
|
671
|
+
* reads it so `identify`/app-events correlate to the real session instead of minting a phantom.
|
|
672
|
+
*
|
|
673
|
+
* DEPENDENCY-FREE + PROCESS-LOCAL: a plain module variable. It is intentionally NOT persisted — it
|
|
674
|
+
* tracks the CURRENT process's open, and a fresh open always overwrites it. No cross-launch state.
|
|
675
|
+
*/
|
|
676
|
+
/**
|
|
677
|
+
* Record the current per-open `session_id`. Called by `reportSessionStart` when it emits an
|
|
678
|
+
* app-open. A blank / non-string id is ignored (the previous id stays current). Idempotent.
|
|
679
|
+
*/
|
|
680
|
+
declare const setCurrentSessionId: (id: string | undefined) => void;
|
|
681
|
+
/** The current per-open `session_id`, or `undefined` when no app-open has been registered yet. */
|
|
682
|
+
declare const getCurrentSessionId: () => string | undefined;
|
|
683
|
+
/** Test-only: forget the current session id so a unit test starts from a clean registry. */
|
|
684
|
+
declare const resetCurrentSessionId: () => void;
|
|
685
|
+
|
|
686
|
+
export { type AnalyticsEvent as A, collectDeviceContext as B, type ClientEvent as C, type DeviceContext as D, type EventQueueOptions as E, hashEmailFnv1a as F, isWireScalar as G, namespaceExtra as H, resolveUserContext as I, type OnboardingResult as O, RESERVED_USER_CONTEXT_KEYS as R, type StepValidator as S, type WireUserContext as W, type ClientEventTarget as a, type ClientEventType as b, type ContextEnvelope as c, type ContextEnvelopeInput as d, type EnvelopeSource as e, type EventQueue as f, WIRE_ONBOARDING_EVENTS as g, type WireOnboardingEventName as h, buildContextEnvelope as i, createEventQueue as j, getCurrentSessionId as k, reportClientEvents as l, makeSessionId as m, resetCurrentSessionId as n, type WireOnboardingProps as o, type WireOnboardingConfig as p, type OnboardingEvent as q, reportClientEvent as r, setCurrentSessionId as s, toAnalyticsEvent as t, type OnboardingCopy as u, type DeviceFormFactor as v, EXTRA_KEY_PREFIX as w, type OnboardingProgress as x, type ResolveUserContextOptions as y, type ResolvedUserContext as z };
|
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 {
|
|
4
|
-
export { A as AnalyticsEvent, b as ClientEventType,
|
|
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';
|
|
@@ -826,6 +826,73 @@ declare const attributionMetadata: (a: OnboardingAttribution) => {
|
|
|
826
826
|
attribution: Record<string, unknown>;
|
|
827
827
|
};
|
|
828
828
|
|
|
829
|
+
/**
|
|
830
|
+
* appVersion — best-effort, DEPENDENCY-FREE auto-detection of the host app's version string.
|
|
831
|
+
*
|
|
832
|
+
* WHY this exists: analytics segments the funnel `by_app_version`, but that breakdown is only
|
|
833
|
+
* populated when a `device.appVersion` rides the event. `config.appVersion` (see types.ts) has
|
|
834
|
+
* always been the way to supply it — but it is easy for a host to forget, and then the release
|
|
835
|
+
* breakdown is silently empty. This module fills that gap: when the host does NOT pass a version,
|
|
836
|
+
* the kit makes a best-effort read of the app version the host already ships in its Expo config,
|
|
837
|
+
* so the breakdown works out of the box. An explicit `config.appVersion` always WINS over this.
|
|
838
|
+
*
|
|
839
|
+
* WHY it adds NO dependency (the kit's hard rule): `expo-constants` / `expo-application` are read
|
|
840
|
+
* through a GUARDED, VARIABLE-specifier `require`. Passing a variable (not a string literal) keeps
|
|
841
|
+
* Metro/esbuild from statically resolving the module, so a host that does NOT have it installed
|
|
842
|
+
* (e.g. bare React Native) never fails to bundle — the require simply throws at runtime and is
|
|
843
|
+
* swallowed. Nothing is added to `package.json`; nothing is forced on the host.
|
|
844
|
+
*
|
|
845
|
+
* PRIVACY: an app version string is not PII and identifies no user or device, so surfacing it
|
|
846
|
+
* changes no App Privacy / Data Safety declaration (same guarantee as the rest of deviceContext).
|
|
847
|
+
*
|
|
848
|
+
* NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.
|
|
849
|
+
* Analytics must never be able to break onboarding.
|
|
850
|
+
*/
|
|
851
|
+
/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */
|
|
852
|
+
type OptionalRequire$1 = (moduleName: string) => unknown;
|
|
853
|
+
/**
|
|
854
|
+
* Detect the host app version, preferring `expo-constants` (`expoConfig.version`, then
|
|
855
|
+
* `nativeAppVersion`) and finally `expo-application` (`nativeApplicationVersion`). Returns the
|
|
856
|
+
* first real string, or `undefined` when none of those are available. Pure and never throws.
|
|
857
|
+
*
|
|
858
|
+
* `requireModule` is injectable so tests can exercise the "found" path without the native modules;
|
|
859
|
+
* production defaults to the guarded runtime require above.
|
|
860
|
+
*/
|
|
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;
|
|
895
|
+
|
|
829
896
|
/** Max accepted user-id length. Longer strings are truncated (never rejected). Keep in sync
|
|
830
897
|
* with the server's `USER_ID_MAX_LENGTH` (analytics/events.py). */
|
|
831
898
|
declare const USER_ID_MAX_LENGTH = 128;
|
|
@@ -873,38 +940,35 @@ type IdentifyOnboardingOptions = {
|
|
|
873
940
|
declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<boolean>;
|
|
874
941
|
|
|
875
942
|
/**
|
|
876
|
-
*
|
|
877
|
-
*
|
|
878
|
-
*
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
* 1. SESSION MAPPING. It carries the host's opaque `userId` + a stable `deviceKey`, so the
|
|
882
|
-
* backend can group a user's (or a pre-auth device's) opens over time — "when did this
|
|
883
|
-
* user last use the app, and how many times". The device_key links the pre-auth opens to
|
|
884
|
-
* the user once `userId` arrives (here or via `identifyOnboarding`).
|
|
885
|
-
* 2. QUESTIONNAIRE / RETENTION FIRING. It flows into the SAME event stream the server's
|
|
886
|
-
* decision engines read, so a questionnaire trigger `{event:"app.session_started", min_count:N}`
|
|
887
|
-
* (matched within a session) or a questionnaire `min_sessions:N` (distinct device sessions)
|
|
888
|
-
* fires on the user's Nth open with no new server endpoint.
|
|
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.
|
|
889
948
|
*
|
|
890
|
-
*
|
|
891
|
-
* The
|
|
892
|
-
*
|
|
893
|
-
*
|
|
894
|
-
*
|
|
895
|
-
*
|
|
896
|
-
*
|
|
897
|
-
*
|
|
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).
|
|
898
957
|
*
|
|
899
|
-
*
|
|
900
|
-
*
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
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.
|
|
907
970
|
*/
|
|
971
|
+
declare const mintDeviceId: () => string;
|
|
908
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";
|
|
@@ -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, 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 };
|