@advenue/react-native 0.8.0 → 1.0.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.
Files changed (94) hide show
  1. package/README.md +8 -7
  2. package/android/src/main/java/expo/modules/advenue/AdvenueAndroidModule.kt +118 -347
  3. package/android/src/main/kotlin/io/advenue/Advenue.kt +549 -0
  4. package/android/src/main/kotlin/io/advenue/AdvenueConfig.kt +114 -0
  5. package/android/src/main/kotlin/io/advenue/core/Backoff.kt +28 -0
  6. package/android/src/main/kotlin/io/advenue/core/ClientEvent.kt +136 -0
  7. package/android/src/main/kotlin/io/advenue/core/CommandPipe.kt +186 -0
  8. package/android/src/main/kotlin/io/advenue/core/Consent.kt +52 -0
  9. package/android/src/main/kotlin/io/advenue/core/Contracts.kt +80 -0
  10. package/android/src/main/kotlin/io/advenue/core/Conversion.kt +69 -0
  11. package/android/src/main/kotlin/io/advenue/core/Engine.kt +414 -0
  12. package/android/src/main/kotlin/io/advenue/core/EventQueue.kt +89 -0
  13. package/android/src/main/kotlin/io/advenue/core/HmacSigner.kt +31 -0
  14. package/android/src/main/kotlin/io/advenue/core/InstallReferrer.kt +146 -0
  15. package/android/src/main/kotlin/io/advenue/core/Json.kt +272 -0
  16. package/android/src/main/kotlin/io/advenue/core/Limits.kt +47 -0
  17. package/android/src/main/kotlin/io/advenue/core/MetaReferrer.kt +80 -0
  18. package/android/src/main/kotlin/io/advenue/core/SessionTracker.kt +189 -0
  19. package/android/src/main/kotlin/io/advenue/core/SystemServices.kt +58 -0
  20. package/android/src/main/kotlin/io/advenue/core/Tcf.kt +48 -0
  21. package/android/src/main/kotlin/io/advenue/core/Time.kt +56 -0
  22. package/android/src/main/kotlin/io/advenue/platform/Collectors.kt +149 -0
  23. package/android/src/main/kotlin/io/advenue/platform/CompositeStore.kt +33 -0
  24. package/android/src/main/kotlin/io/advenue/platform/ConversionFetcher.kt +68 -0
  25. package/android/src/main/kotlin/io/advenue/platform/ForegroundTracker.kt +90 -0
  26. package/android/src/main/kotlin/io/advenue/platform/HttpUrlTransport.kt +101 -0
  27. package/android/src/main/kotlin/io/advenue/platform/Identity.kt +79 -0
  28. package/android/src/main/kotlin/io/advenue/platform/InstallEnrichment.kt +197 -0
  29. package/android/src/main/kotlin/io/advenue/platform/InstallScopedStore.kt +91 -0
  30. package/android/src/main/kotlin/io/advenue/platform/LifecycleBridge.kt +72 -0
  31. package/android/src/main/kotlin/io/advenue/platform/PreferencesStore.kt +32 -0
  32. package/android/src/main/kotlin/io/advenue/plugin/Contracts.kt +67 -0
  33. package/android/src/main/kotlin/io/advenue/plugin/FirebaseAppInstanceIdSource.kt +73 -0
  34. package/android/src/main/kotlin/io/advenue/plugin/PlayAdvertisingIdSource.kt +47 -0
  35. package/android/src/main/kotlin/io/advenue/plugin/PlayInstallReferrerSource.kt +85 -0
  36. package/android/src/main/kotlin/io/advenue/plugin/PlayIntegritySource.kt +86 -0
  37. package/android/src/main/kotlin/io/advenue/plugin/PluginRegistry.kt +61 -0
  38. package/dist/index.cjs +183 -655
  39. package/dist/index.d.cts +199 -331
  40. package/dist/index.d.ts +199 -331
  41. package/dist/index.js +182 -661
  42. package/ios/AdvenueIosModule.swift +144 -432
  43. package/ios/vendor/Advenue/Advenue.swift +596 -0
  44. package/ios/vendor/Advenue/AdvenueConfig.swift +77 -0
  45. package/ios/vendor/AdvenueCore/AdvenueValue.swift +103 -0
  46. package/ios/vendor/AdvenueCore/Attestation.swift +52 -0
  47. package/ios/vendor/AdvenueCore/Backoff.swift +28 -0
  48. package/ios/vendor/AdvenueCore/ClientEvent.swift +154 -0
  49. package/ios/vendor/AdvenueCore/Consent.swift +40 -0
  50. package/ios/vendor/AdvenueCore/Contracts.swift +59 -0
  51. package/ios/vendor/AdvenueCore/Conversion.swift +74 -0
  52. package/ios/vendor/AdvenueCore/ConversionValue.swift +217 -0
  53. package/ios/vendor/AdvenueCore/Engine.swift +587 -0
  54. package/ios/vendor/AdvenueCore/EventQueue.swift +89 -0
  55. package/ios/vendor/AdvenueCore/Limits.swift +41 -0
  56. package/ios/vendor/AdvenueCore/PIIScrub.swift +102 -0
  57. package/ios/vendor/AdvenueCore/SessionTracker.swift +139 -0
  58. package/ios/vendor/AdvenueCore/SkanConfig.swift +76 -0
  59. package/ios/vendor/AdvenueCore/SkanReporter.swift +25 -0
  60. package/ios/vendor/AdvenueCore/SkanState.swift +258 -0
  61. package/ios/vendor/AdvenueCore/Tcf.swift +48 -0
  62. package/ios/vendor/AdvenueCore/Transport.swift +14 -0
  63. package/ios/vendor/AdvenueFirebase/FirebaseAppInstanceId.swift +33 -0
  64. package/ios/vendor/AdvenuePlatform/AdvertisingIdentity.swift +87 -0
  65. package/ios/vendor/AdvenuePlatform/ChallengeFetcher.swift +42 -0
  66. package/ios/vendor/AdvenuePlatform/ConversionFetcher.swift +63 -0
  67. package/ios/vendor/AdvenuePlatform/CryptoKitSigner.swift +19 -0
  68. package/ios/vendor/AdvenuePlatform/DeviceCheckAttestation.swift +91 -0
  69. package/ios/vendor/AdvenuePlatform/DeviceInfo.swift +65 -0
  70. package/ios/vendor/AdvenuePlatform/ForegroundTracker.swift +55 -0
  71. package/ios/vendor/AdvenuePlatform/HttpTransport.swift +96 -0
  72. package/ios/vendor/AdvenuePlatform/Identity.swift +52 -0
  73. package/ios/vendor/AdvenuePlatform/InstallEnrichment.swift +143 -0
  74. package/ios/vendor/AdvenuePlatform/KeychainStore.swift +95 -0
  75. package/ios/vendor/AdvenuePlatform/SearchAdsToken.swift +76 -0
  76. package/ios/vendor/AdvenuePlatform/SkanConfigFetcher.swift +70 -0
  77. package/ios/vendor/AdvenuePlatform/StoreKitSkanReporter.swift +140 -0
  78. package/ios/vendor/AdvenuePlatform/SystemServices.swift +55 -0
  79. package/ios/vendor/AdvenuePlatform/TcfReader.swift +18 -0
  80. package/ios/vendor/AdvenuePlatform/UserDefaultsStore.swift +26 -0
  81. package/package.json +9 -11
  82. package/scripts/check-dist.mjs +17 -0
  83. package/scripts/check-vendored-swift.mjs +148 -0
  84. package/scripts/vendor-natives.mjs +149 -0
  85. package/scripts/vendor-natives.test.mjs +112 -0
  86. package/src/deep-links.ts +19 -1
  87. package/src/index.ts +267 -803
  88. package/src/native-types.ts +74 -171
  89. package/src/native.ts +0 -23
  90. package/src/types.ts +81 -0
  91. package/src/aem.ts +0 -33
  92. package/src/mmkv-storage.ts +0 -21
  93. package/src/native-storage.ts +0 -63
  94. package/src/secure-store.ts +0 -26
@@ -1,190 +1,93 @@
1
- // Native module contracts for the Expo modules that ship inside this package
2
- // (ios/ and android/ directories, registered via expo-module.config.json).
3
- // Formerly the public surface of @advenue/sdk-ios and @advenue/sdk-android —
4
- // both retired when the native code moved in-package (single-install DX).
1
+ // Contracts for the Expo modules that ship inside this package (ios/ and
2
+ // android/, registered via expo-module.config.json).
3
+ //
4
+ // These are a bridge, not a toolbox. The old surface exposed one function per
5
+ // native capability — storage, advertising ids, attestation, TCF — because a
6
+ // TypeScript core drove them. That core is gone: each function below maps to
7
+ // one method on the native SDK, and the native SDK decides everything else.
5
8
 
6
- export interface InstallReferrerResult {
7
- referrer: string;
8
- /** Device-clock: referrerClickTimestampSeconds. */
9
- clickTimestamp: number;
10
- /** Device-clock: installBeginTimestampSeconds. */
11
- installTimestamp: number;
12
- /**
13
- * Server-clock: referrerClickTimestampServerSeconds (G1 fraud trust —
14
- * referrerTrust:'server'). 0 = unverified; absent on older native builds.
15
- */
16
- clickServerTimestamp?: number;
17
- /** Server-clock: installBeginTimestampServerSeconds. 0 = unverified. */
18
- installServerTimestamp?: number;
19
- googlePlayInstant: boolean;
20
- }
9
+ import type { Consent, DeepLink } from './types';
21
10
 
22
- export interface MetaInstallReferrerResult {
23
- installReferrer: string;
24
- isClickThrough: boolean;
25
- actualTimestamp: number;
26
- /** Which Meta app served the referrer (e.g. com.facebook.katana). */
27
- provider: string;
28
- }
11
+ export type TrackingAuthorizationStatus =
12
+ | 'authorized'
13
+ | 'denied'
14
+ | 'restricted'
15
+ | 'notDetermined'
16
+ | 'unavailable';
29
17
 
30
- /**
31
- * Device metadata for Meta CAPI `extinfo` (Task 3n). Structurally mirrors
32
- * `DeviceInfo` from `@advenue/shared` — kept as a local subset type (rather
33
- * than importing that package) so this native-module-only package stays
34
- * dependency-free; the RN facade's `collectDeviceInfo()` merges it into the
35
- * real `DeviceInfo` shape.
36
- */
37
- export interface AdvenueDeviceInfo {
38
- model?: string;
39
- locale?: string;
40
- carrier?: string;
41
- timezone?: string;
42
- screenWidth?: number;
43
- screenHeight?: number;
44
- screenDensity?: number;
45
- cpuCores?: number;
46
- totalStorageGb?: number;
47
- freeStorageGb?: number;
18
+ /** What `bridgeInitialize` accepts. Anything absent takes the native default. */
19
+ export interface BridgeInitOptions {
20
+ apiKey: string;
21
+ endpoint?: string;
22
+ appVersion?: string;
23
+ requireConsent: boolean;
24
+ batchSize?: number;
25
+ flushIntervalMs?: number;
26
+ signingSecret?: string;
27
+ /** Meta app id, for the Meta install referrer. Android only. */
28
+ fbAppId?: string;
29
+ autoTrackInstall: boolean;
30
+ /** Stamped by this package, never by the host app. */
31
+ sdkVersion: string;
48
32
  }
49
33
 
50
34
  /**
51
- * Raw IAB TCF v2 CMP values from the platform default store
52
- * (`UserDefaults.standard` / default SharedPreferences) — where TCF-compliant
53
- * CMPs (e.g. Google UMP) write `IABTCF_*` keys. Structurally mirrors
54
- * `TcfData` from `@advenue/sdk-core`.
35
+ * One diagnostic the SDK swallowed, on its way back to JavaScript.
36
+ *
37
+ * `context` is a stable dot-path identifier of the step that failed
38
+ * (`identity.deferred`, `track.rejected:name_too_long`, `flush.transport`), not
39
+ * a message to show a user. Never carries PII.
55
40
  */
56
- export interface NativeTcfData {
57
- gdprApplies?: number | null;
58
- purposeConsents?: string | null;
41
+ export interface NativeErrorEvent {
42
+ context: string;
43
+ message: string;
59
44
  }
60
45
 
61
- export interface AdvenueAndroidNativeModule {
62
- /** Raw Play Install Referrer; parse with @advenue/install-referrer. */
63
- getInstallReferrer(): Promise<InstallReferrerResult | null>;
64
- /**
65
- * Meta install referrer (null when no Facebook/Instagram app is installed);
66
- * parse with parseMetaInstallReferrer from @advenue/install-referrer.
67
- */
68
- getMetaInstallReferrer(): Promise<MetaInstallReferrerResult | null>;
69
- /** Google Advertising ID (GAID) + limit-ad-tracking flag; null when unavailable. */
70
- getAdvertisingId(): Promise<{ id: string; limitAdTracking: boolean } | null>;
71
- /** App Set ID — non-advertising, developer-scoped fallback id; null when unavailable. */
72
- getAppSetId(): Promise<string | null>;
73
- /**
74
- * Play Integrity Standard API token (G3.1n).
75
- *
76
- * `requestHash` MUST be sha256_hex("<appId>:<deviceId>") — lowercase hex SHA-256
77
- * of the literal string "<appId>:<deviceId>". The server's mapIntegrityVerdict
78
- * re-derives the same string and compares it byte-for-byte.
79
- *
80
- * Rejects when:
81
- * - ECONFIG: `io.advenue.INTEGRITY_CLOUD_PROJECT_NUMBER` meta-data is absent.
82
- * - EUNSUPPORTED: Play Services unavailable or provider warming failed.
83
- * - EINTEGRITY: Play returned an API-level error (network, quota, etc.).
84
- *
85
- * The JS bridge treats any rejection as "no attestation" and omits the token
86
- * from the install event — rejection must never block the install track call.
87
- */
88
- getIntegrityToken(requestHash: string): Promise<string>;
89
- /**
90
- * Device metadata (model, locale, screen, cpu, storage, timezone) used to
91
- * populate Meta CAPI `extinfo` (Task 3n). Synchronous, best-effort — the JS
92
- * facade (`collectDeviceInfo`) treats a thrown error as "unavailable" and
93
- * degrades to `{}` rather than blocking anything.
94
- */
95
- getDeviceInfo(): AdvenueDeviceInfo;
96
- /**
97
- * Built-in SDK storage (SharedPreferences `io.advenue.sdk`, MODE_PRIVATE) —
98
- * the durable offline buffer + SDK state, so the app never supplies storage.
99
- * Optional: absent on native builds predating this capability; the RN facade
100
- * feature-detects and falls back to in-memory buffering. (No secure variant:
101
- * Android has no reinstall-durable store — a reinstall legitimately re-fires
102
- * the install, which the backend per-device window deduplicates.)
103
- */
104
- storageGetItem?(key: string): string | null;
105
- storageSetItem?(key: string, value: string): void;
106
- storageRemoveItem?(key: string): void;
107
- /**
108
- * Android SSAID (Settings.Secure.ANDROID_ID) — signing-key-scoped, stable
109
- * across reinstalls. The RN facade reads it ONLY when no usable GAID exists
110
- * (Adjust-style fallback) and it is used strictly as a first-party
111
- * fraud/dedup + reinstall-detection signal, never for ad attribution (Play
112
- * policy). Optional: absent on older native builds; feature-detected.
113
- */
114
- getAndroidId?(): string | null;
115
- /**
116
- * IAB TCF v2 CMP data, null when no CMP has written TCF keys. Optional:
117
- * older native builds lack it — callers feature-detect (getAndroidId
118
- * precedent).
119
- */
120
- getTcfData?(): NativeTcfData | null;
46
+ /** The methods both native modules implement. */
47
+ export interface AdvenueBridge {
48
+ /** Expo's event subscription, used for `onAdvenueError`. */
49
+ addListener?(
50
+ name: 'onAdvenueError',
51
+ handler: (event: NativeErrorEvent) => void,
52
+ ): { remove(): void };
53
+ bridgeInitialize(options: BridgeInitOptions): void;
54
+ bridgeTrack(name: string, properties: Record<string, unknown> | null): void;
55
+ bridgeFlush(): void;
56
+ bridgeSetUserId(id: string | null): void;
57
+ bridgeSetConsent(granted: boolean): void;
58
+ /** Reads the persisted value; the JavaScript consent cache is seeded from it. */
59
+ bridgeGetConsent(): boolean;
60
+ bridgeSetConsentData(consent: Consent): void;
61
+ bridgeGetConsentData(): Consent | null;
62
+ bridgeSetAppInstanceId(id: string | null): void;
63
+ bridgeSetPushToken(token: string | null, provider: string | null): void;
64
+ bridgeProcessDeepLink(url: string): void;
65
+ bridgeForgetMe(): void;
66
+ bridgeShutdown(): void;
67
+ bridgeResolvedAppId(): string | null;
68
+ bridgeResolveDeferredDeepLink(): Promise<DeepLink | null>;
121
69
  }
122
70
 
123
- export type TrackingAuthorizationStatus = 'notDetermined' | 'restricted' | 'denied' | 'authorized';
124
-
125
- export interface AdvenueIosNativeModule {
126
- registerAppForAttribution(): void;
71
+ export interface AdvenueIosNativeModule extends AdvenueBridge {
127
72
  /**
128
- * Conversion value: fine 0–63, coarse 'low'|'medium'|'high'. Updates the
129
- * SKAN 4.0 postback, and on iOS 17.4+ the AdAttributionKit postback too.
73
+ * The app's price string ("9.99"), not micros. The conversion to exact
74
+ * micros happens natively: a money computation in JavaScript is the thing
75
+ * this release removed.
130
76
  */
131
- updateConversionValue(fineValue: number, coarse: string, lockWindow: boolean): Promise<void>;
132
- /** Apple Search Ads attribution token (resolve server-side). */
133
- getAttributionToken(): Promise<string | null>;
77
+ bridgeRecordSkanRevenue(amount: string, currency: string): void;
78
+ /** Resolves synchronously on the native side; a Promise across the bridge. */
79
+ bridgeDeviceId(): Promise<string | null>;
134
80
  /**
135
81
  * Shows the ATT consent prompt; requires NSUserTrackingUsageDescription in
136
82
  * the app's Info.plist. Resolves with the resulting status.
83
+ *
84
+ * Still a capability rather than a bridge call because the app chooses when
85
+ * to prompt, and that decision belongs to the app's UX, not the SDK.
137
86
  */
138
87
  requestTrackingAuthorization(): Promise<TrackingAuthorizationStatus>;
139
- getTrackingAuthorizationStatus(): TrackingAuthorizationStatus;
140
- getAdvertisingId(): Promise<string | null>;
141
- /** Vendor-scoped device id (IDFV) — available without ATT; a fallback anchor. */
142
- getIdentifierForVendor(): string | null;
143
- /**
144
- * G3.2n — App Attest. Generates (or reuses a keychain-cached) DCAppAttest
145
- * key, computes clientDataHash = SHA-256(challenge), and calls
146
- * DCAppAttestService.attestKey. Resolves { keyId, attestationObject } where
147
- * attestationObject is a base64-encoded CBOR attestation for the server.
148
- * Rejects with code EUNSUPPORTED on simulators (isSupported == false).
149
- */
150
- attestKey(challenge: string): Promise<{ keyId: string; attestationObject: string }>;
151
- /**
152
- * G3.3n — DeviceCheck. Calls DCDevice.current.generateToken to obtain the
153
- * opaque base64 token that identifies this physical device to the Apple
154
- * DeviceCheck API. The server queries/updates the persistent 2-bit per-device
155
- * flag to detect reinstall abuse. Rejects with code EUNSUPPORTED on devices
156
- * where DCDevice.current.isSupported is false (simulator, Catalyst, etc.).
157
- */
158
- getDeviceCheckToken(): Promise<string>;
159
- /**
160
- * Device metadata (model, locale, screen, cpu, storage, timezone) used to
161
- * populate Meta CAPI `extinfo` (Task 3n). Synchronous, best-effort — the JS
162
- * facade (`collectDeviceInfo`) treats a thrown error as "unavailable" and
163
- * degrades to `{}` rather than blocking anything.
164
- */
165
- getDeviceInfo(): AdvenueDeviceInfo;
166
- /**
167
- * Built-in SDK storage (UserDefaults suite `io.advenue.sdk`) — the durable
168
- * offline buffer + SDK state, so the app never supplies storage. Optional:
169
- * absent on native builds predating this capability; the RN facade
170
- * feature-detects and falls back to in-memory buffering.
171
- */
172
- storageGetItem?(key: string): string | null;
173
- storageSetItem?(key: string, value: string): void;
174
- storageRemoveItem?(key: string): void;
175
- /**
176
- * Built-in secure storage (Keychain, kSecAttrAccessibleAfterFirstUnlock,
177
- * ThisDeviceOnly) — survives app reinstall, which is what makes the device
178
- * identity and the install guard reinstall-resilient (Adjust-style).
179
- * Optional: absent on older native builds; feature-detected.
180
- */
181
- secureGetItem?(key: string): string | null;
182
- secureSetItem?(key: string, value: string): void;
183
- secureRemoveItem?(key: string): void;
184
- /**
185
- * IAB TCF v2 CMP data, null when no CMP has written TCF keys. Optional:
186
- * older native builds lack it — callers feature-detect (getAndroidId
187
- * precedent).
188
- */
189
- getTcfData?(): NativeTcfData | null;
88
+ }
89
+
90
+ export interface AdvenueAndroidNativeModule extends AdvenueBridge {
91
+ /** Synchronous on Android: the identity is resolved before start returns. */
92
+ bridgeDeviceId(): string | null;
190
93
  }
package/src/native.ts CHANGED
@@ -44,29 +44,6 @@ export function getPlatformOS(): string | null {
44
44
  }
45
45
  }
46
46
 
47
- /**
48
- * OS *release* version for attribution matching: iOS `Platform.Version` is the
49
- * system version string ('18.2'); Android `Platform.Version` is the API LEVEL
50
- * (34) — sending it would break the server's normalized fingerprint (the
51
- * click-side browser UA says "Android 14"), so Android reads
52
- * `Platform.constants.Release` and degrades to null when it's absent.
53
- */
54
- export function getOsVersion(): string | null {
55
- try {
56
- const rn = requireReactNative() as {
57
- Platform: { OS: string; Version?: unknown; constants?: { Release?: unknown } };
58
- } | null;
59
- if (!rn) return null;
60
- if (rn.Platform.OS === 'android') {
61
- const release = rn.Platform.constants?.Release;
62
- return release != null ? String(release) : null;
63
- }
64
- return rn.Platform.Version != null ? String(rn.Platform.Version) : null;
65
- } catch {
66
- return null;
67
- }
68
- }
69
-
70
47
  /** Subscription handle returned by AppState.addEventListener. */
71
48
  export interface AppStateSubscription {
72
49
  remove(): void;
package/src/types.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The types the package used to re-export from the retired TypeScript core.
3
+ *
4
+ * They live here now because the TypeScript core is retired and the native
5
+ * SDKs own the behaviour — but they are still the shapes apps destructure, so
6
+ * they must keep their names and fields exactly.
7
+ */
8
+
9
+ /** Granular ad-platform consent (Google DMA). */
10
+ export interface Consent {
11
+ /** Whether GDPR/EEA rules apply to this user. → Google `gdpr_applies` */
12
+ isUserSubjectToGDPR: boolean;
13
+ /** Consent to use data for advertising purposes. → Google `ad_user_data` */
14
+ hasConsentForDataUsage?: boolean;
15
+ /** Consent for personalized advertising. → Google `ad_personalization` */
16
+ hasConsentForAdsPersonalization?: boolean;
17
+ /** Consent for ad storage. → Google `ad_storage` */
18
+ hasConsentForAdStorage?: boolean;
19
+ }
20
+
21
+ /** A resolved deep link, deferred or direct. */
22
+ export interface DeepLink {
23
+ /** In-app destination, e.g. "product/123". Absent for an attributed install with no link. */
24
+ deepLinkValue?: string;
25
+ campaign?: string;
26
+ network?: string;
27
+ influencerId?: string;
28
+ params?: Record<string, unknown>;
29
+ /** Raw opening URL for direct (OS-delivered) links; absent for deferred. */
30
+ url?: string;
31
+ /** True when the link survived an install rather than arriving on an open. */
32
+ isDeferred: boolean;
33
+ /** True when this is the device's first-launch attribution (always true for deferred). */
34
+ isFirstLaunch: boolean;
35
+ }
36
+
37
+ /**
38
+ * The event types a client SDK may emit. Revenue-bearing subscription events
39
+ * are deliberately absent: those originate only from verified S2S sources, and
40
+ * the server rejects a batch that claims one.
41
+ */
42
+ export type ClientEventType = 'install' | 'session' | 'custom';
43
+
44
+ /** Per-event options. Most apps never pass any of these. */
45
+ export interface TrackOptions {
46
+ type?: ClientEventType;
47
+ network?: string;
48
+ campaign?: string;
49
+ }
50
+
51
+ /**
52
+ * SDK configuration.
53
+ *
54
+ * Several options that used to shape the TypeScript core are now decided
55
+ * natively and are accepted but ignored — see `initialize`, which reports each
56
+ * one through `onError` rather than dropping it silently. Passing storage to an
57
+ * SDK that owns its own storage should not look like it worked.
58
+ */
59
+ export interface AdvenueConfig {
60
+ apiKey: string;
61
+ endpoint?: string;
62
+ platform?: 'ios' | 'android' | 'web' | string;
63
+ appVersion?: string;
64
+ osVersion?: string;
65
+ /** Gates every event on `setTrackingConsent(true)`. */
66
+ requireConsent?: boolean;
67
+ /** Events per request. */
68
+ batchSize?: number;
69
+ /** Auto-flush period in milliseconds; 0 disables the timer. */
70
+ flushIntervalMs?: number;
71
+ /**
72
+ * Per-key HMAC secret. The signature provides integrity and replay
73
+ * protection, not authentication: anything inside an app binary can be
74
+ * extracted from it.
75
+ */
76
+ signingSecret?: string;
77
+ disableAutoSessions?: boolean;
78
+ /** Called when the SDK swallows a best-effort failure. Never receives PII. */
79
+ onError?: (context: string, cause: unknown) => void;
80
+ debug?: boolean;
81
+ }
package/src/aem.ts DELETED
@@ -1,33 +0,0 @@
1
- /**
2
- * Meta AEM campaign_ids extraction from an al_applink_data payload.
3
- *
4
- * The input string is the ALREADY percent-decoded query-param value
5
- * (URLSearchParams decodes; decoding again would corrupt blobs containing
6
- * '%'). Meta does not publicly document the al_applink_data schema for AEM,
7
- * so we accept the two shapes observed in the wild — top-level
8
- * `campaign_ids` and `extras.campaign_ids` — top level first. VERIFY against
9
- * a real captured payload when one is available and update this comment
10
- * with what production links actually show (spec: implementation-time
11
- * verification).
12
- *
13
- * The blob is opaque, Meta-encrypted, non-user metadata: returned verbatim,
14
- * never trimmed/re-encoded. ≤ 2048 chars as URL hygiene (the worker
15
- * re-validates — SDK caps are advisory at the trust boundary).
16
- */
17
- export function extractAemCampaignIds(alApplinkData: string): string | null {
18
- try {
19
- const parsed = JSON.parse(alApplinkData) as {
20
- campaign_ids?: unknown;
21
- extras?: { campaign_ids?: unknown };
22
- };
23
- const value =
24
- typeof parsed.campaign_ids === 'string' && parsed.campaign_ids
25
- ? parsed.campaign_ids
26
- : typeof parsed.extras?.campaign_ids === 'string' && parsed.extras.campaign_ids
27
- ? parsed.extras.campaign_ids
28
- : null;
29
- return value && value.length <= 2048 ? value : null;
30
- } catch {
31
- return null;
32
- }
33
- }
@@ -1,21 +0,0 @@
1
- import type { StorageAdapter } from '@advenue/sdk-core';
2
-
3
- /**
4
- * Minimal structural type for the bits of `react-native-mmkv`'s MMKV instance
5
- * we use. Declared locally so this package needs no react-native types at
6
- * compile time — the app injects a real `new MMKV()` instance at runtime.
7
- */
8
- export interface MMKVLike {
9
- set(key: string, value: string): void;
10
- getString(key: string): string | undefined;
11
- delete(key: string): void;
12
- }
13
-
14
- /** Wraps an MMKV instance as an Advenue StorageAdapter (synchronous, fast). */
15
- export function createMMKVStorage(mmkv: MMKVLike): StorageAdapter {
16
- return {
17
- getItem: (key) => mmkv.getString(key) ?? null,
18
- setItem: (key, value) => mmkv.set(key, value),
19
- removeItem: (key) => mmkv.delete(key),
20
- };
21
- }
@@ -1,63 +0,0 @@
1
- // Adapters over the native modules' built-in storage (UserDefaults /
2
- // SharedPreferences + iOS Keychain), so the app never supplies storage —
3
- // Adjust/AppsFlyer parity. Pure functions over a passed module (rather than
4
- // resolving the module themselves) so they stay unit-testable and respect the
5
- // test mocks of './native'.
6
- import type { SecureStorageAdapter, StorageAdapter } from '@advenue/sdk-core';
7
-
8
- interface NativeStorageFns {
9
- storageGetItem?(key: string): string | null;
10
- storageSetItem?(key: string, value: string): void;
11
- storageRemoveItem?(key: string): void;
12
- }
13
-
14
- interface NativeSecureFns {
15
- secureGetItem?(key: string): string | null;
16
- secureSetItem?(key: string, value: string): void;
17
- secureRemoveItem?(key: string): void;
18
- }
19
-
20
- /**
21
- * Wraps a native module's built-in key/value storage as the sync
22
- * {@link StorageAdapter}. Returns null when the module is absent or predates
23
- * the storage capability (feature-detected), so callers fall back.
24
- */
25
- export function createNativeStorage(mod: unknown): StorageAdapter | null {
26
- const m = mod as NativeStorageFns | null;
27
- if (
28
- !m ||
29
- typeof m.storageGetItem !== 'function' ||
30
- typeof m.storageSetItem !== 'function' ||
31
- typeof m.storageRemoveItem !== 'function'
32
- ) {
33
- return null;
34
- }
35
- return {
36
- getItem: (key) => m.storageGetItem?.(key) ?? null,
37
- setItem: (key, value) => m.storageSetItem?.(key, value),
38
- removeItem: (key) => m.storageRemoveItem?.(key),
39
- };
40
- }
41
-
42
- /**
43
- * Wraps the iOS module's Keychain functions as the async
44
- * {@link SecureStorageAdapter} (with erasure support). Returns null when the
45
- * module is absent or predates the capability — including all of Android,
46
- * which has no reinstall-durable store.
47
- */
48
- export function createNativeSecureStore(mod: unknown): SecureStorageAdapter | null {
49
- const m = mod as NativeSecureFns | null;
50
- if (
51
- !m ||
52
- typeof m.secureGetItem !== 'function' ||
53
- typeof m.secureSetItem !== 'function' ||
54
- typeof m.secureRemoveItem !== 'function'
55
- ) {
56
- return null;
57
- }
58
- return {
59
- getItemAsync: async (key) => m.secureGetItem?.(key) ?? null,
60
- setItemAsync: async (key, value) => m.secureSetItem?.(key, value),
61
- deleteItemAsync: async (key) => m.secureRemoveItem?.(key),
62
- };
63
- }
@@ -1,26 +0,0 @@
1
- import type { SecureStorageAdapter } from '@advenue/sdk-core';
2
-
3
- /**
4
- * Minimal structural type for the bits of `expo-secure-store` we use. Declared
5
- * locally so this package needs no expo types at compile time — the app passes
6
- * the module (`import * as SecureStore from 'expo-secure-store'`) at runtime.
7
- */
8
- export interface SecureStoreLike {
9
- getItemAsync(key: string): Promise<string | null>;
10
- setItemAsync(key: string, value: string): Promise<void>;
11
- /** Optional — forwarded so GDPR erasure can wipe the durable entries. */
12
- deleteItemAsync?(key: string): Promise<void>;
13
- }
14
-
15
- /** Wraps expo-secure-store as an Advenue SecureStorageAdapter (async, durable). */
16
- export function createSecureStore(secureStore: SecureStoreLike): SecureStorageAdapter {
17
- return {
18
- getItemAsync: async (key) => (await secureStore.getItemAsync(key)) ?? null,
19
- setItemAsync: (key, value) => secureStore.setItemAsync(key, value),
20
- ...(secureStore.deleteItemAsync
21
- ? {
22
- deleteItemAsync: (key: string) => secureStore.deleteItemAsync?.(key) ?? Promise.resolve(),
23
- }
24
- : {}),
25
- };
26
- }