@advenue/react-native 1.0.0 → 1.1.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/android/src/main/java/expo/modules/advenue/AdvenueAndroidModule.kt +4 -1
- package/android/src/main/kotlin/io/advenue/Advenue.kt +76 -11
- package/android/src/main/kotlin/io/advenue/AdvenueConfig.kt +36 -1
- package/android/src/main/kotlin/io/advenue/DebugLog.kt +51 -0
- package/android/src/main/kotlin/io/advenue/core/Backoff.kt +14 -1
- package/android/src/main/kotlin/io/advenue/core/CommandPipe.kt +36 -3
- package/android/src/main/kotlin/io/advenue/core/Engine.kt +96 -4
- package/android/src/main/kotlin/io/advenue/core/EventQueue.kt +12 -0
- package/android/src/main/kotlin/io/advenue/core/Limits.kt +3 -0
- package/android/src/main/kotlin/io/advenue/core/PiiScrub.kt +77 -0
- package/android/src/main/kotlin/io/advenue/core/SessionTracker.kt +109 -33
- package/android/src/main/kotlin/io/advenue/platform/Collectors.kt +14 -0
- package/android/src/main/kotlin/io/advenue/platform/ConversionFetcher.kt +24 -10
- package/android/src/main/kotlin/io/advenue/platform/ForegroundTracker.kt +9 -2
- package/android/src/main/kotlin/io/advenue/platform/HttpUrlTransport.kt +21 -8
- package/android/src/main/kotlin/io/advenue/platform/InstallEnrichment.kt +7 -0
- package/android/src/main/kotlin/io/advenue/platform/InstallScopedStore.kt +5 -0
- package/android/src/main/kotlin/io/advenue/platform/LifecycleBridge.kt +23 -1
- package/dist/index.cjs +16 -4
- package/dist/index.d.cts +18 -4
- package/dist/index.d.ts +18 -4
- package/dist/index.js +16 -4
- package/ios/AdvenueIosModule.swift +4 -2
- package/ios/vendor/Advenue/Advenue.swift +88 -17
- package/ios/vendor/Advenue/AdvenueConfig.swift +22 -2
- package/ios/vendor/Advenue/AdvenueSetupError.swift +24 -0
- package/ios/vendor/Advenue/DebugLog.swift +46 -0
- package/ios/vendor/AdvenueCore/Backoff.swift +16 -2
- package/ios/vendor/AdvenueCore/Engine.swift +83 -9
- package/ios/vendor/AdvenueCore/EventQueue.swift +12 -0
- package/ios/vendor/AdvenueCore/SessionTracker.swift +89 -32
- package/ios/vendor/AdvenuePlatform/CacheFileStore.swift +90 -0
- package/ios/vendor/AdvenuePlatform/ChallengeFetcher.swift +14 -2
- package/ios/vendor/AdvenuePlatform/ConversionFetcher.swift +14 -3
- package/ios/vendor/AdvenuePlatform/DeviceInfo.swift +31 -0
- package/ios/vendor/AdvenuePlatform/HttpTransport.swift +28 -4
- package/ios/vendor/AdvenuePlatform/InstallEnrichment.swift +20 -4
- package/ios/vendor/AdvenuePlatform/SkanConfigFetcher.swift +14 -2
- package/package.json +1 -1
- package/src/index.ts +20 -3
- package/src/native-types.ts +0 -1
- package/src/types.ts +18 -3
|
@@ -4,6 +4,10 @@ import Foundation
|
|
|
4
4
|
/// Spec §5: the install waits this long for enrichment and no longer. Matches
|
|
5
5
|
/// the deadlines the RN SDK already uses (SKAN config 3000 ms).
|
|
6
6
|
public let INSTALL_WINDOW_MS = 3_000
|
|
7
|
+
/// How long past `INSTALL_WINDOW_MS` flushes stay held for a pending install —
|
|
8
|
+
/// the enrichment deadline is checked by a task that still has to be
|
|
9
|
+
/// scheduled and then hop through the command pipe.
|
|
10
|
+
public let INSTALL_HOLD_MARGIN_MS = 2_000
|
|
7
11
|
|
|
8
12
|
/// What the install event carries beyond the envelope every event has.
|
|
9
13
|
public struct Enrichment: Sendable, Equatable {
|
|
@@ -13,11 +17,14 @@ public struct Enrichment: Sendable, Equatable {
|
|
|
13
17
|
public var vendorId: String?
|
|
14
18
|
public var appInstanceId: String?
|
|
15
19
|
public var adservicesToken: String?
|
|
20
|
+
/// B2: reklam takibi sınırlama bayrağı — düşürülüyordu, artık olaya işlenir.
|
|
21
|
+
public var limitAdTracking: Bool
|
|
16
22
|
|
|
17
23
|
public init(
|
|
18
24
|
idfa: String? = nil, vendorId: String? = nil,
|
|
19
25
|
appInstanceId: String? = nil, adservicesToken: String? = nil,
|
|
20
|
-
attestation: AttestationResult? = nil, attestationChallenge: String? = nil
|
|
26
|
+
attestation: AttestationResult? = nil, attestationChallenge: String? = nil,
|
|
27
|
+
limitAdTracking: Bool = false
|
|
21
28
|
) {
|
|
22
29
|
self.attestation = attestation
|
|
23
30
|
self.attestationChallenge = attestationChallenge
|
|
@@ -25,6 +32,7 @@ public struct Enrichment: Sendable, Equatable {
|
|
|
25
32
|
self.vendorId = vendorId
|
|
26
33
|
self.appInstanceId = appInstanceId
|
|
27
34
|
self.adservicesToken = adservicesToken
|
|
35
|
+
self.limitAdTracking = limitAdTracking
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
|
|
@@ -34,6 +42,9 @@ public struct Enrichment: Sendable, Equatable {
|
|
|
34
42
|
public struct EnrichmentSources: Sendable {
|
|
35
43
|
public var searchAdsToken: @Sendable () async -> String?
|
|
36
44
|
public var advertisingId: @Sendable () -> (idfa: String?, vendorId: String?)
|
|
45
|
+
/// B2: ATT sınırlama bayrağı. Ayrı kapanış — advertisingId demetini
|
|
46
|
+
/// değiştirmek mevcut sahte kaynakları kırardı.
|
|
47
|
+
public var limitAdTracking: @Sendable () -> Bool
|
|
37
48
|
public var appInstanceId: @Sendable () async -> String?
|
|
38
49
|
/// Returns the attested challenge and its result, or nil. Every failure path
|
|
39
50
|
/// — unsupported device, challenge fetch, attest — yields nil, because an
|
|
@@ -46,12 +57,14 @@ public struct EnrichmentSources: Sendable {
|
|
|
46
57
|
appInstanceId: @escaping @Sendable () async -> String?,
|
|
47
58
|
attestation: @escaping @Sendable () async -> (challenge: String, result: AttestationResult)? = {
|
|
48
59
|
nil
|
|
49
|
-
}
|
|
60
|
+
},
|
|
61
|
+
limitAdTracking: @escaping @Sendable () -> Bool = { false }
|
|
50
62
|
) {
|
|
51
63
|
self.searchAdsToken = searchAdsToken
|
|
52
64
|
self.advertisingId = advertisingId
|
|
53
65
|
self.appInstanceId = appInstanceId
|
|
54
66
|
self.attestation = attestation
|
|
67
|
+
self.limitAdTracking = limitAdTracking
|
|
55
68
|
}
|
|
56
69
|
|
|
57
70
|
/// Production wiring. `AdvertisingIdentity.advertisingId` already returns nil
|
|
@@ -68,7 +81,8 @@ public struct EnrichmentSources: Sendable {
|
|
|
68
81
|
return (idfa: identity.advertisingId, vendorId: identity.vendorId)
|
|
69
82
|
},
|
|
70
83
|
appInstanceId: { await appInstanceIdProvider?() },
|
|
71
|
-
attestation: { await attestation?() }
|
|
84
|
+
attestation: { await attestation?() },
|
|
85
|
+
limitAdTracking: { AdvertisingIdentity().limitAdTracking })
|
|
72
86
|
}
|
|
73
87
|
}
|
|
74
88
|
|
|
@@ -85,7 +99,9 @@ public func collectEnrichment(
|
|
|
85
99
|
) async -> Enrichment {
|
|
86
100
|
// Synchronous reads; no reason to race them.
|
|
87
101
|
let ids = sources.advertisingId()
|
|
88
|
-
var result = Enrichment(
|
|
102
|
+
var result = Enrichment(
|
|
103
|
+
idfa: ids.idfa, vendorId: ids.vendorId,
|
|
104
|
+
limitAdTracking: sources.limitAdTracking())
|
|
89
105
|
|
|
90
106
|
await withTaskGroup(of: (String, String?).self) { group in
|
|
91
107
|
group.addTask { ("adservices", await sources.searchAdsToken()) }
|
|
@@ -22,12 +22,24 @@ public struct HttpSkanConfigFetcher: SkanConfigSource {
|
|
|
22
22
|
self.session = session
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
/// The exact request this fetcher would send. Public so a test can assert
|
|
26
|
+
/// the wire shape without a network round trip.
|
|
27
|
+
///
|
|
28
|
+
/// Sends `?platform=ios`: this fetcher is iOS-only by construction, and a
|
|
29
|
+
/// project-scoped key otherwise cannot resolve a listing on a normal
|
|
30
|
+
/// two-listing (iOS + Android) product — see `resolveProjectListing` in
|
|
31
|
+
/// apps/ingestion/src/app.ts, which 400s an ambiguous project key rather
|
|
32
|
+
/// than guess.
|
|
33
|
+
public func buildRequest(etag: String?) -> URLRequest {
|
|
34
|
+
var request = URLRequest(url: URL(string: "\(endpoint)/v1/sdk-config?platform=ios")!)
|
|
27
35
|
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
|
|
28
36
|
if let etag { request.setValue(etag, forHTTPHeaderField: "if-none-match") }
|
|
29
37
|
request.timeoutInterval = Double(SKAN_CONFIG_TIMEOUT_MS) / 1000
|
|
38
|
+
return request
|
|
39
|
+
}
|
|
30
40
|
|
|
41
|
+
public func fetch(etag: String?) async throws -> SkanConfigResult {
|
|
42
|
+
let request = buildRequest(etag: etag)
|
|
31
43
|
let (payload, response) = try await session.data(for: request)
|
|
32
44
|
guard let http = response as? HTTPURLResponse else { throw IngestError(status: 408) }
|
|
33
45
|
if http.statusCode == 304 { return .notModified }
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -27,7 +27,15 @@ export type {
|
|
|
27
27
|
} from './native-types';
|
|
28
28
|
|
|
29
29
|
/** Options this package used to act on and the native SDKs now decide. */
|
|
30
|
-
|
|
30
|
+
// appVersion joins them: the native SDK resolves it from the package/bundle
|
|
31
|
+
// (as the 0.x JS layer did), so a config value would only shadow the real one.
|
|
32
|
+
const IGNORED_OPTIONS = [
|
|
33
|
+
'mmkv',
|
|
34
|
+
'secureStore',
|
|
35
|
+
'sdkConfigFetcher',
|
|
36
|
+
'tcfDataCollection',
|
|
37
|
+
'appVersion',
|
|
38
|
+
] as const;
|
|
31
39
|
|
|
32
40
|
export interface RNAdvenueConfig extends AdvenueConfig {
|
|
33
41
|
/** Meta app id, for the Meta install referrer on Android. */
|
|
@@ -55,6 +63,8 @@ let started = false;
|
|
|
55
63
|
let deepLinkSub: DeepLinkHandle | null = null;
|
|
56
64
|
let errorSub: { remove(): void } | null = null;
|
|
57
65
|
let onErrorHook: ((context: string, cause: unknown) => void) | undefined;
|
|
66
|
+
/** `config.debug`: failures are also written to the JS console. */
|
|
67
|
+
let debugLogging = false;
|
|
58
68
|
|
|
59
69
|
/**
|
|
60
70
|
* `getTrackingConsent` is synchronous in JavaScript and the value lives in the
|
|
@@ -97,6 +107,9 @@ function report(context: string, cause: unknown): void {
|
|
|
97
107
|
} catch {
|
|
98
108
|
// A throwing diagnostics hook must never break the SDK.
|
|
99
109
|
}
|
|
110
|
+
// Native failures come back through `onAdvenueError`, so this covers both
|
|
111
|
+
// sides. The native SDKs log their start and sent batches themselves.
|
|
112
|
+
if (debugLogging) console.warn(`[Advenue] ${context}`, cause);
|
|
100
113
|
}
|
|
101
114
|
|
|
102
115
|
function requireStarted(): boolean {
|
|
@@ -114,6 +127,7 @@ export const Advenue = {
|
|
|
114
127
|
*/
|
|
115
128
|
async initialize(config: RNAdvenueConfig): Promise<void> {
|
|
116
129
|
onErrorHook = config.onError;
|
|
130
|
+
debugLogging = config.debug === true;
|
|
117
131
|
|
|
118
132
|
for (const option of IGNORED_OPTIONS) {
|
|
119
133
|
if ((config as unknown as Record<string, unknown>)[option] !== undefined) {
|
|
@@ -131,14 +145,17 @@ export const Advenue = {
|
|
|
131
145
|
call('bridgeInitialize', {
|
|
132
146
|
apiKey: config.apiKey,
|
|
133
147
|
endpoint: config.endpoint,
|
|
134
|
-
appVersion: config.appVersion,
|
|
135
148
|
requireConsent: config.requireConsent ?? false,
|
|
136
149
|
batchSize: config.batchSize,
|
|
137
150
|
flushIntervalMs: config.flushIntervalMs,
|
|
138
151
|
signingSecret: config.signingSecret,
|
|
139
152
|
fbAppId: config.fbAppId,
|
|
140
153
|
autoTrackInstall: config.autoTrackInstall !== false,
|
|
141
|
-
|
|
154
|
+
// Names the wrapper, like Flutter's `advenue_sdk/…`: a bare version reads
|
|
155
|
+
// like the native SDK's own stamp.
|
|
156
|
+
sdkVersion: `react-native/${pkg.version}`,
|
|
157
|
+
debug: config.debug === true,
|
|
158
|
+
allowInsecureHttp: config.allowInsecureHttp === true,
|
|
142
159
|
});
|
|
143
160
|
started = true;
|
|
144
161
|
|
package/src/native-types.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -59,9 +59,12 @@ export interface TrackOptions {
|
|
|
59
59
|
export interface AdvenueConfig {
|
|
60
60
|
apiKey: string;
|
|
61
61
|
endpoint?: string;
|
|
62
|
-
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated Ignored: the native SDK resolves the app version from the
|
|
64
|
+
* package/bundle. Passing it reports `config.ignored:appVersion` via
|
|
65
|
+
* `onError`. Removed in the next major.
|
|
66
|
+
*/
|
|
63
67
|
appVersion?: string;
|
|
64
|
-
osVersion?: string;
|
|
65
68
|
/** Gates every event on `setTrackingConsent(true)`. */
|
|
66
69
|
requireConsent?: boolean;
|
|
67
70
|
/** Events per request. */
|
|
@@ -74,8 +77,20 @@ export interface AdvenueConfig {
|
|
|
74
77
|
* extracted from it.
|
|
75
78
|
*/
|
|
76
79
|
signingSecret?: string;
|
|
77
|
-
|
|
80
|
+
/**
|
|
81
|
+
* **Test only.** Allows an `http://` endpoint — a local self-hosted ingest,
|
|
82
|
+
* or a test server — which the native SDKs otherwise refuse at initialize.
|
|
83
|
+
* Never set it in a production build: everything, the API key included,
|
|
84
|
+
* then travels unencrypted.
|
|
85
|
+
*/
|
|
86
|
+
allowInsecureHttp?: boolean;
|
|
78
87
|
/** Called when the SDK swallows a best-effort failure. Never receives PII. */
|
|
79
88
|
onError?: (context: string, cause: unknown) => void;
|
|
89
|
+
/**
|
|
90
|
+
* Development aid: the native SDKs log their start, every swallowed failure
|
|
91
|
+
* and each sent batch to Xcode's console / logcat, and every failure is also
|
|
92
|
+
* written to the JS console as `[Advenue] <context>`. Never logs an
|
|
93
|
+
* identifier or a payload. Leave off in production; use `onError`.
|
|
94
|
+
*/
|
|
80
95
|
debug?: boolean;
|
|
81
96
|
}
|