@advenue/react-native 0.9.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.
- package/README.md +8 -7
- package/android/src/main/java/expo/modules/advenue/AdvenueAndroidModule.kt +118 -368
- package/android/src/main/kotlin/io/advenue/Advenue.kt +549 -0
- package/android/src/main/kotlin/io/advenue/AdvenueConfig.kt +114 -0
- package/android/src/main/kotlin/io/advenue/core/Backoff.kt +28 -0
- package/android/src/main/kotlin/io/advenue/core/ClientEvent.kt +136 -0
- package/android/src/main/kotlin/io/advenue/core/CommandPipe.kt +186 -0
- package/android/src/main/kotlin/io/advenue/core/Consent.kt +52 -0
- package/android/src/main/kotlin/io/advenue/core/Contracts.kt +80 -0
- package/android/src/main/kotlin/io/advenue/core/Conversion.kt +69 -0
- package/android/src/main/kotlin/io/advenue/core/Engine.kt +414 -0
- package/android/src/main/kotlin/io/advenue/core/EventQueue.kt +89 -0
- package/android/src/main/kotlin/io/advenue/core/HmacSigner.kt +31 -0
- package/android/src/main/kotlin/io/advenue/core/InstallReferrer.kt +146 -0
- package/android/src/main/kotlin/io/advenue/core/Json.kt +272 -0
- package/android/src/main/kotlin/io/advenue/core/Limits.kt +47 -0
- package/android/src/main/kotlin/io/advenue/core/MetaReferrer.kt +80 -0
- package/android/src/main/kotlin/io/advenue/core/SessionTracker.kt +189 -0
- package/android/src/main/kotlin/io/advenue/core/SystemServices.kt +58 -0
- package/android/src/main/kotlin/io/advenue/core/Tcf.kt +48 -0
- package/android/src/main/kotlin/io/advenue/core/Time.kt +56 -0
- package/android/src/main/kotlin/io/advenue/platform/Collectors.kt +149 -0
- package/android/src/main/kotlin/io/advenue/platform/CompositeStore.kt +33 -0
- package/android/src/main/kotlin/io/advenue/platform/ConversionFetcher.kt +68 -0
- package/android/src/main/kotlin/io/advenue/platform/ForegroundTracker.kt +90 -0
- package/android/src/main/kotlin/io/advenue/platform/HttpUrlTransport.kt +101 -0
- package/android/src/main/kotlin/io/advenue/platform/Identity.kt +79 -0
- package/android/src/main/kotlin/io/advenue/platform/InstallEnrichment.kt +197 -0
- package/android/src/main/kotlin/io/advenue/platform/InstallScopedStore.kt +91 -0
- package/android/src/main/kotlin/io/advenue/platform/LifecycleBridge.kt +72 -0
- package/android/src/main/kotlin/io/advenue/platform/PreferencesStore.kt +32 -0
- package/android/src/main/kotlin/io/advenue/plugin/Contracts.kt +67 -0
- package/android/src/main/kotlin/io/advenue/plugin/FirebaseAppInstanceIdSource.kt +73 -0
- package/android/src/main/kotlin/io/advenue/plugin/PlayAdvertisingIdSource.kt +47 -0
- package/android/src/main/kotlin/io/advenue/plugin/PlayInstallReferrerSource.kt +85 -0
- package/android/src/main/kotlin/io/advenue/plugin/PlayIntegritySource.kt +86 -0
- package/android/src/main/kotlin/io/advenue/plugin/PluginRegistry.kt +61 -0
- package/dist/index.cjs +183 -675
- package/dist/index.d.cts +199 -336
- package/dist/index.d.ts +199 -336
- package/dist/index.js +182 -681
- package/ios/AdvenueIosModule.swift +144 -446
- package/ios/vendor/Advenue/Advenue.swift +596 -0
- package/ios/vendor/Advenue/AdvenueConfig.swift +77 -0
- package/ios/vendor/AdvenueCore/AdvenueValue.swift +103 -0
- package/ios/vendor/AdvenueCore/Attestation.swift +52 -0
- package/ios/vendor/AdvenueCore/Backoff.swift +28 -0
- package/ios/vendor/AdvenueCore/ClientEvent.swift +154 -0
- package/ios/vendor/AdvenueCore/Consent.swift +40 -0
- package/ios/vendor/AdvenueCore/Contracts.swift +59 -0
- package/ios/vendor/AdvenueCore/Conversion.swift +74 -0
- package/ios/vendor/AdvenueCore/ConversionValue.swift +217 -0
- package/ios/vendor/AdvenueCore/Engine.swift +587 -0
- package/ios/vendor/AdvenueCore/EventQueue.swift +89 -0
- package/ios/vendor/AdvenueCore/Limits.swift +41 -0
- package/ios/vendor/AdvenueCore/PIIScrub.swift +102 -0
- package/ios/vendor/AdvenueCore/SessionTracker.swift +139 -0
- package/ios/vendor/AdvenueCore/SkanConfig.swift +76 -0
- package/ios/vendor/AdvenueCore/SkanReporter.swift +25 -0
- package/ios/vendor/AdvenueCore/SkanState.swift +258 -0
- package/ios/vendor/AdvenueCore/Tcf.swift +48 -0
- package/ios/vendor/AdvenueCore/Transport.swift +14 -0
- package/ios/vendor/AdvenueFirebase/FirebaseAppInstanceId.swift +33 -0
- package/ios/vendor/AdvenuePlatform/AdvertisingIdentity.swift +87 -0
- package/ios/vendor/AdvenuePlatform/ChallengeFetcher.swift +42 -0
- package/ios/vendor/AdvenuePlatform/ConversionFetcher.swift +63 -0
- package/ios/vendor/AdvenuePlatform/CryptoKitSigner.swift +19 -0
- package/ios/vendor/AdvenuePlatform/DeviceCheckAttestation.swift +91 -0
- package/ios/vendor/AdvenuePlatform/DeviceInfo.swift +65 -0
- package/ios/vendor/AdvenuePlatform/ForegroundTracker.swift +55 -0
- package/ios/vendor/AdvenuePlatform/HttpTransport.swift +96 -0
- package/ios/vendor/AdvenuePlatform/Identity.swift +52 -0
- package/ios/vendor/AdvenuePlatform/InstallEnrichment.swift +143 -0
- package/ios/vendor/AdvenuePlatform/KeychainStore.swift +95 -0
- package/ios/vendor/AdvenuePlatform/SearchAdsToken.swift +76 -0
- package/ios/vendor/AdvenuePlatform/SkanConfigFetcher.swift +70 -0
- package/ios/vendor/AdvenuePlatform/StoreKitSkanReporter.swift +140 -0
- package/ios/vendor/AdvenuePlatform/SystemServices.swift +55 -0
- package/ios/vendor/AdvenuePlatform/TcfReader.swift +18 -0
- package/ios/vendor/AdvenuePlatform/UserDefaultsStore.swift +26 -0
- package/package.json +9 -11
- package/scripts/check-dist.mjs +17 -0
- package/scripts/check-vendored-swift.mjs +148 -0
- package/scripts/vendor-natives.mjs +149 -0
- package/scripts/vendor-natives.test.mjs +112 -0
- package/src/deep-links.ts +19 -1
- package/src/index.ts +266 -830
- package/src/native-types.ts +74 -181
- package/src/native.ts +0 -23
- package/src/types.ts +81 -0
- package/src/aem.ts +0 -33
- package/src/mmkv-storage.ts +0 -21
- package/src/native-storage.ts +0 -63
- package/src/secure-store.ts +0 -26
package/src/native-types.ts
CHANGED
|
@@ -1,200 +1,93 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
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
|
-
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
11
|
+
export type TrackingAuthorizationStatus =
|
|
12
|
+
| 'authorized'
|
|
13
|
+
| 'denied'
|
|
14
|
+
| 'restricted'
|
|
15
|
+
| 'notDetermined'
|
|
16
|
+
| 'unavailable';
|
|
29
17
|
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/** Build identifier (CFBundleVersion / versionCode) — extinfo slot 3. */
|
|
45
|
-
longVersion?: string;
|
|
46
|
-
model?: string;
|
|
47
|
-
locale?: string;
|
|
48
|
-
carrier?: string;
|
|
49
|
-
timezone?: string;
|
|
50
|
-
screenWidth?: number;
|
|
51
|
-
screenHeight?: number;
|
|
52
|
-
screenDensity?: number;
|
|
53
|
-
cpuCores?: number;
|
|
54
|
-
totalStorageGb?: number;
|
|
55
|
-
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;
|
|
56
32
|
}
|
|
57
33
|
|
|
58
34
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* `
|
|
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.
|
|
63
40
|
*/
|
|
64
|
-
export interface
|
|
65
|
-
|
|
66
|
-
|
|
41
|
+
export interface NativeErrorEvent {
|
|
42
|
+
context: string;
|
|
43
|
+
message: string;
|
|
67
44
|
}
|
|
68
45
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
* - EUNSUPPORTED: Play Services unavailable or provider warming failed.
|
|
93
|
-
* - EINTEGRITY: Play returned an API-level error (network, quota, etc.).
|
|
94
|
-
*
|
|
95
|
-
* The JS bridge treats any rejection as "no attestation" and omits the token
|
|
96
|
-
* from the install event — rejection must never block the install track call.
|
|
97
|
-
*/
|
|
98
|
-
getIntegrityToken(requestHash: string): Promise<string>;
|
|
99
|
-
/**
|
|
100
|
-
* Device metadata (model, locale, screen, cpu, storage, timezone) used to
|
|
101
|
-
* populate Meta CAPI `extinfo` (Task 3n). Synchronous, best-effort — the JS
|
|
102
|
-
* facade (`collectDeviceInfo`) treats a thrown error as "unavailable" and
|
|
103
|
-
* degrades to `{}` rather than blocking anything.
|
|
104
|
-
*/
|
|
105
|
-
getDeviceInfo(): AdvenueDeviceInfo;
|
|
106
|
-
/**
|
|
107
|
-
* Built-in SDK storage (SharedPreferences `io.advenue.sdk`, MODE_PRIVATE) —
|
|
108
|
-
* the durable offline buffer + SDK state, so the app never supplies storage.
|
|
109
|
-
* Optional: absent on native builds predating this capability; the RN facade
|
|
110
|
-
* feature-detects and falls back to in-memory buffering. (No secure variant:
|
|
111
|
-
* Android has no reinstall-durable store — a reinstall legitimately re-fires
|
|
112
|
-
* the install, which the backend per-device window deduplicates.)
|
|
113
|
-
*/
|
|
114
|
-
storageGetItem?(key: string): string | null;
|
|
115
|
-
storageSetItem?(key: string, value: string): void;
|
|
116
|
-
storageRemoveItem?(key: string): void;
|
|
117
|
-
/**
|
|
118
|
-
* Android SSAID (Settings.Secure.ANDROID_ID) — signing-key-scoped, stable
|
|
119
|
-
* across reinstalls. The RN facade reads it ONLY when no usable GAID exists
|
|
120
|
-
* (Adjust-style fallback) and it is used strictly as a first-party
|
|
121
|
-
* fraud/dedup + reinstall-detection signal, never for ad attribution (Play
|
|
122
|
-
* policy). Optional: absent on older native builds; feature-detected.
|
|
123
|
-
*/
|
|
124
|
-
getAndroidId?(): string | null;
|
|
125
|
-
/**
|
|
126
|
-
* IAB TCF v2 CMP data, null when no CMP has written TCF keys. Optional:
|
|
127
|
-
* older native builds lack it — callers feature-detect (getAndroidId
|
|
128
|
-
* precedent).
|
|
129
|
-
*/
|
|
130
|
-
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>;
|
|
131
69
|
}
|
|
132
70
|
|
|
133
|
-
export
|
|
134
|
-
|
|
135
|
-
export interface AdvenueIosNativeModule {
|
|
136
|
-
registerAppForAttribution(): void;
|
|
71
|
+
export interface AdvenueIosNativeModule extends AdvenueBridge {
|
|
137
72
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
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.
|
|
140
76
|
*/
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
|
|
77
|
+
bridgeRecordSkanRevenue(amount: string, currency: string): void;
|
|
78
|
+
/** Resolves synchronously on the native side; a Promise across the bridge. */
|
|
79
|
+
bridgeDeviceId(): Promise<string | null>;
|
|
144
80
|
/**
|
|
145
81
|
* Shows the ATT consent prompt; requires NSUserTrackingUsageDescription in
|
|
146
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.
|
|
147
86
|
*/
|
|
148
87
|
requestTrackingAuthorization(): Promise<TrackingAuthorizationStatus>;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
* G3.2n — App Attest. Generates (or reuses a keychain-cached) DCAppAttest
|
|
155
|
-
* key, computes clientDataHash = SHA-256(challenge), and calls
|
|
156
|
-
* DCAppAttestService.attestKey. Resolves { keyId, attestationObject } where
|
|
157
|
-
* attestationObject is a base64-encoded CBOR attestation for the server.
|
|
158
|
-
* Rejects with code EUNSUPPORTED on simulators (isSupported == false).
|
|
159
|
-
*/
|
|
160
|
-
attestKey(challenge: string): Promise<{ keyId: string; attestationObject: string }>;
|
|
161
|
-
/**
|
|
162
|
-
* G3.3n — DeviceCheck. Calls DCDevice.current.generateToken to obtain the
|
|
163
|
-
* opaque base64 token that identifies this physical device to the Apple
|
|
164
|
-
* DeviceCheck API. The server queries/updates the persistent 2-bit per-device
|
|
165
|
-
* flag to detect reinstall abuse. Rejects with code EUNSUPPORTED on devices
|
|
166
|
-
* where DCDevice.current.isSupported is false (simulator, Catalyst, etc.).
|
|
167
|
-
*/
|
|
168
|
-
getDeviceCheckToken(): Promise<string>;
|
|
169
|
-
/**
|
|
170
|
-
* Device metadata (model, locale, screen, cpu, storage, timezone) used to
|
|
171
|
-
* populate Meta CAPI `extinfo` (Task 3n). Synchronous, best-effort — the JS
|
|
172
|
-
* facade (`collectDeviceInfo`) treats a thrown error as "unavailable" and
|
|
173
|
-
* degrades to `{}` rather than blocking anything.
|
|
174
|
-
*/
|
|
175
|
-
getDeviceInfo(): AdvenueDeviceInfo;
|
|
176
|
-
/**
|
|
177
|
-
* Built-in SDK storage (UserDefaults suite `io.advenue.sdk`) — the durable
|
|
178
|
-
* offline buffer + SDK state, so the app never supplies storage. Optional:
|
|
179
|
-
* absent on native builds predating this capability; the RN facade
|
|
180
|
-
* feature-detects and falls back to in-memory buffering.
|
|
181
|
-
*/
|
|
182
|
-
storageGetItem?(key: string): string | null;
|
|
183
|
-
storageSetItem?(key: string, value: string): void;
|
|
184
|
-
storageRemoveItem?(key: string): void;
|
|
185
|
-
/**
|
|
186
|
-
* Built-in secure storage (Keychain, kSecAttrAccessibleAfterFirstUnlock,
|
|
187
|
-
* ThisDeviceOnly) — survives app reinstall, which is what makes the device
|
|
188
|
-
* identity and the install guard reinstall-resilient (Adjust-style).
|
|
189
|
-
* Optional: absent on older native builds; feature-detected.
|
|
190
|
-
*/
|
|
191
|
-
secureGetItem?(key: string): string | null;
|
|
192
|
-
secureSetItem?(key: string, value: string): void;
|
|
193
|
-
secureRemoveItem?(key: string): void;
|
|
194
|
-
/**
|
|
195
|
-
* IAB TCF v2 CMP data, null when no CMP has written TCF keys. Optional:
|
|
196
|
-
* older native builds lack it — callers feature-detect (getAndroidId
|
|
197
|
-
* precedent).
|
|
198
|
-
*/
|
|
199
|
-
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;
|
|
200
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
|
-
}
|
package/src/mmkv-storage.ts
DELETED
|
@@ -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
|
-
}
|
package/src/native-storage.ts
DELETED
|
@@ -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
|
-
}
|
package/src/secure-store.ts
DELETED
|
@@ -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
|
-
}
|