@advenue/react-native 0.9.0 → 1.0.1

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 (96) hide show
  1. package/README.md +8 -7
  2. package/android/src/main/java/expo/modules/advenue/AdvenueAndroidModule.kt +117 -368
  3. package/android/src/main/kotlin/io/advenue/Advenue.kt +574 -0
  4. package/android/src/main/kotlin/io/advenue/AdvenueConfig.kt +141 -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 +193 -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 +436 -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 +50 -0
  17. package/android/src/main/kotlin/io/advenue/core/MetaReferrer.kt +80 -0
  18. package/android/src/main/kotlin/io/advenue/core/PiiScrub.kt +77 -0
  19. package/android/src/main/kotlin/io/advenue/core/SessionTracker.kt +189 -0
  20. package/android/src/main/kotlin/io/advenue/core/SystemServices.kt +58 -0
  21. package/android/src/main/kotlin/io/advenue/core/Tcf.kt +48 -0
  22. package/android/src/main/kotlin/io/advenue/core/Time.kt +56 -0
  23. package/android/src/main/kotlin/io/advenue/platform/Collectors.kt +163 -0
  24. package/android/src/main/kotlin/io/advenue/platform/CompositeStore.kt +33 -0
  25. package/android/src/main/kotlin/io/advenue/platform/ConversionFetcher.kt +68 -0
  26. package/android/src/main/kotlin/io/advenue/platform/ForegroundTracker.kt +90 -0
  27. package/android/src/main/kotlin/io/advenue/platform/HttpUrlTransport.kt +101 -0
  28. package/android/src/main/kotlin/io/advenue/platform/Identity.kt +79 -0
  29. package/android/src/main/kotlin/io/advenue/platform/InstallEnrichment.kt +197 -0
  30. package/android/src/main/kotlin/io/advenue/platform/InstallScopedStore.kt +96 -0
  31. package/android/src/main/kotlin/io/advenue/platform/LifecycleBridge.kt +72 -0
  32. package/android/src/main/kotlin/io/advenue/platform/PreferencesStore.kt +32 -0
  33. package/android/src/main/kotlin/io/advenue/plugin/Contracts.kt +67 -0
  34. package/android/src/main/kotlin/io/advenue/plugin/FirebaseAppInstanceIdSource.kt +73 -0
  35. package/android/src/main/kotlin/io/advenue/plugin/PlayAdvertisingIdSource.kt +47 -0
  36. package/android/src/main/kotlin/io/advenue/plugin/PlayInstallReferrerSource.kt +85 -0
  37. package/android/src/main/kotlin/io/advenue/plugin/PlayIntegritySource.kt +86 -0
  38. package/android/src/main/kotlin/io/advenue/plugin/PluginRegistry.kt +61 -0
  39. package/dist/index.cjs +188 -675
  40. package/dist/index.d.cts +203 -336
  41. package/dist/index.d.ts +203 -336
  42. package/dist/index.js +187 -681
  43. package/ios/AdvenueIosModule.swift +143 -446
  44. package/ios/vendor/Advenue/Advenue.swift +632 -0
  45. package/ios/vendor/Advenue/AdvenueConfig.swift +89 -0
  46. package/ios/vendor/AdvenueCore/AdvenueValue.swift +103 -0
  47. package/ios/vendor/AdvenueCore/Attestation.swift +52 -0
  48. package/ios/vendor/AdvenueCore/Backoff.swift +28 -0
  49. package/ios/vendor/AdvenueCore/ClientEvent.swift +154 -0
  50. package/ios/vendor/AdvenueCore/Consent.swift +40 -0
  51. package/ios/vendor/AdvenueCore/Contracts.swift +59 -0
  52. package/ios/vendor/AdvenueCore/Conversion.swift +74 -0
  53. package/ios/vendor/AdvenueCore/ConversionValue.swift +217 -0
  54. package/ios/vendor/AdvenueCore/Engine.swift +607 -0
  55. package/ios/vendor/AdvenueCore/EventQueue.swift +89 -0
  56. package/ios/vendor/AdvenueCore/Limits.swift +41 -0
  57. package/ios/vendor/AdvenueCore/PIIScrub.swift +102 -0
  58. package/ios/vendor/AdvenueCore/SessionTracker.swift +139 -0
  59. package/ios/vendor/AdvenueCore/SkanConfig.swift +76 -0
  60. package/ios/vendor/AdvenueCore/SkanReporter.swift +25 -0
  61. package/ios/vendor/AdvenueCore/SkanState.swift +258 -0
  62. package/ios/vendor/AdvenueCore/Tcf.swift +48 -0
  63. package/ios/vendor/AdvenueCore/Transport.swift +14 -0
  64. package/ios/vendor/AdvenueFirebase/FirebaseAppInstanceId.swift +33 -0
  65. package/ios/vendor/AdvenuePlatform/AdvertisingIdentity.swift +87 -0
  66. package/ios/vendor/AdvenuePlatform/CacheFileStore.swift +90 -0
  67. package/ios/vendor/AdvenuePlatform/ChallengeFetcher.swift +42 -0
  68. package/ios/vendor/AdvenuePlatform/ConversionFetcher.swift +63 -0
  69. package/ios/vendor/AdvenuePlatform/CryptoKitSigner.swift +19 -0
  70. package/ios/vendor/AdvenuePlatform/DeviceCheckAttestation.swift +91 -0
  71. package/ios/vendor/AdvenuePlatform/DeviceInfo.swift +77 -0
  72. package/ios/vendor/AdvenuePlatform/ForegroundTracker.swift +55 -0
  73. package/ios/vendor/AdvenuePlatform/HttpTransport.swift +96 -0
  74. package/ios/vendor/AdvenuePlatform/Identity.swift +52 -0
  75. package/ios/vendor/AdvenuePlatform/InstallEnrichment.swift +155 -0
  76. package/ios/vendor/AdvenuePlatform/KeychainStore.swift +95 -0
  77. package/ios/vendor/AdvenuePlatform/SearchAdsToken.swift +76 -0
  78. package/ios/vendor/AdvenuePlatform/SkanConfigFetcher.swift +70 -0
  79. package/ios/vendor/AdvenuePlatform/StoreKitSkanReporter.swift +140 -0
  80. package/ios/vendor/AdvenuePlatform/SystemServices.swift +55 -0
  81. package/ios/vendor/AdvenuePlatform/TcfReader.swift +18 -0
  82. package/ios/vendor/AdvenuePlatform/UserDefaultsStore.swift +26 -0
  83. package/package.json +13 -15
  84. package/scripts/check-dist.mjs +17 -0
  85. package/scripts/check-vendored-swift.mjs +148 -0
  86. package/scripts/vendor-natives.mjs +149 -0
  87. package/scripts/vendor-natives.test.mjs +112 -0
  88. package/src/deep-links.ts +19 -1
  89. package/src/index.ts +273 -830
  90. package/src/native-types.ts +73 -181
  91. package/src/native.ts +0 -23
  92. package/src/types.ts +86 -0
  93. package/src/aem.ts +0 -33
  94. package/src/mmkv-storage.ts +0 -21
  95. package/src/native-storage.ts +0 -63
  96. package/src/secure-store.ts +0 -26
package/dist/index.cjs CHANGED
@@ -55,174 +55,17 @@ var require_native_require = __commonJS({
55
55
  var index_exports = {};
56
56
  __export(index_exports, {
57
57
  Advenue: () => Advenue,
58
- applyAppState: () => applyAppState,
59
- collectDeviceInfo: () => collectDeviceInfo,
60
- createMMKVStorage: () => createMMKVStorage,
61
- createSecureStore: () => createSecureStore,
62
58
  getAndroidNative: () => getAndroidNative,
63
59
  getIosNative: () => getIosNative,
64
60
  parseDirectLink: () => parseDirectLink,
65
- resolveAdvertisingId: () => resolveAdvertisingId,
66
- resolveDmaConsent: () => resolveDmaConsent,
67
- trackInstall: () => trackInstall
61
+ platform: () => platform
68
62
  });
69
63
  module.exports = __toCommonJS(index_exports);
70
- var import_install_referrer = require("@advenue/install-referrer");
71
- var import_sdk_core = require("@advenue/sdk-core");
72
-
73
- // ../signing/src/index.ts
74
- var K = new Uint32Array([
75
- 1116352408,
76
- 1899447441,
77
- 3049323471,
78
- 3921009573,
79
- 961987163,
80
- 1508970993,
81
- 2453635748,
82
- 2870763221,
83
- 3624381080,
84
- 310598401,
85
- 607225278,
86
- 1426881987,
87
- 1925078388,
88
- 2162078206,
89
- 2614888103,
90
- 3248222580,
91
- 3835390401,
92
- 4022224774,
93
- 264347078,
94
- 604807628,
95
- 770255983,
96
- 1249150122,
97
- 1555081692,
98
- 1996064986,
99
- 2554220882,
100
- 2821834349,
101
- 2952996808,
102
- 3210313671,
103
- 3336571891,
104
- 3584528711,
105
- 113926993,
106
- 338241895,
107
- 666307205,
108
- 773529912,
109
- 1294757372,
110
- 1396182291,
111
- 1695183700,
112
- 1986661051,
113
- 2177026350,
114
- 2456956037,
115
- 2730485921,
116
- 2820302411,
117
- 3259730800,
118
- 3345764771,
119
- 3516065817,
120
- 3600352804,
121
- 4094571909,
122
- 275423344,
123
- 430227734,
124
- 506948616,
125
- 659060556,
126
- 883997877,
127
- 958139571,
128
- 1322822218,
129
- 1537002063,
130
- 1747873779,
131
- 1955562222,
132
- 2024104815,
133
- 2227730452,
134
- 2361852424,
135
- 2428436474,
136
- 2756734187,
137
- 3204031479,
138
- 3329325298
139
- ]);
140
- function rotr(x, n) {
141
- return x >>> n | x << 32 - n;
142
- }
143
- function sha256Bytes(msg) {
144
- const h = new Uint32Array([
145
- 1779033703,
146
- 3144134277,
147
- 1013904242,
148
- 2773480762,
149
- 1359893119,
150
- 2600822924,
151
- 528734635,
152
- 1541459225
153
- ]);
154
- const l = msg.length;
155
- const bitLen = l * 8;
156
- const withOne = l + 1;
157
- const padTo = (56 - withOne % 64 + 64) % 64;
158
- const padded = new Uint8Array(withOne + padTo + 8);
159
- padded.set(msg);
160
- padded[l] = 128;
161
- const dv = new DataView(padded.buffer);
162
- dv.setUint32(padded.length - 8, Math.floor(bitLen / 4294967296));
163
- dv.setUint32(padded.length - 4, bitLen >>> 0);
164
- const w = new Uint32Array(64);
165
- for (let i = 0; i < padded.length; i += 64) {
166
- for (let t = 0; t < 16; t++) w[t] = dv.getUint32(i + t * 4);
167
- for (let t = 16; t < 64; t++) {
168
- const w15 = w[t - 15];
169
- const w2 = w[t - 2];
170
- const s0 = rotr(w15, 7) ^ rotr(w15, 18) ^ w15 >>> 3;
171
- const s1 = rotr(w2, 17) ^ rotr(w2, 19) ^ w2 >>> 10;
172
- w[t] = w[t - 16] + s0 + w[t - 7] + s1 >>> 0;
173
- }
174
- let a = h[0];
175
- let b = h[1];
176
- let c = h[2];
177
- let d = h[3];
178
- let e = h[4];
179
- let f = h[5];
180
- let g = h[6];
181
- let hh = h[7];
182
- for (let t = 0; t < 64; t++) {
183
- const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
184
- const ch = e & f ^ ~e & g;
185
- const temp1 = hh + S1 + ch + K[t] + w[t] >>> 0;
186
- const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
187
- const maj = a & b ^ a & c ^ b & c;
188
- const temp2 = S0 + maj >>> 0;
189
- hh = g;
190
- g = f;
191
- f = e;
192
- e = d + temp1 >>> 0;
193
- d = c;
194
- c = b;
195
- b = a;
196
- a = temp1 + temp2 >>> 0;
197
- }
198
- h[0] = h[0] + a >>> 0;
199
- h[1] = h[1] + b >>> 0;
200
- h[2] = h[2] + c >>> 0;
201
- h[3] = h[3] + d >>> 0;
202
- h[4] = h[4] + e >>> 0;
203
- h[5] = h[5] + f >>> 0;
204
- h[6] = h[6] + g >>> 0;
205
- h[7] = h[7] + hh >>> 0;
206
- }
207
- const out = new Uint8Array(32);
208
- const odv = new DataView(out.buffer);
209
- for (let i = 0; i < 8; i++) odv.setUint32(i * 4, h[i]);
210
- return out;
211
- }
212
- function toHex(bytes) {
213
- let s = "";
214
- for (let i = 0; i < bytes.length; i++) s += bytes[i].toString(16).padStart(2, "0");
215
- return s;
216
- }
217
- var enc = new TextEncoder();
218
- function sha256Hex(message) {
219
- return toHex(sha256Bytes(enc.encode(message)));
220
- }
221
64
 
222
65
  // package.json
223
66
  var package_default = {
224
67
  name: "@advenue/react-native",
225
- version: "0.9.0",
68
+ version: "1.0.1",
226
69
  description: "Advenue MMP React Native SDK \u2014 attribution, install tracking, and deep links (bundled iOS/Android Expo native modules)",
227
70
  type: "module",
228
71
  license: "MIT",
@@ -245,20 +88,20 @@ var package_default = {
245
88
  "ios",
246
89
  "android",
247
90
  "expo-module.config.json",
248
- "!**/*.test.ts"
91
+ "!**/*.test.ts",
92
+ "ios/vendor",
93
+ "android/src/main/kotlin"
249
94
  ],
250
95
  publishConfig: {
251
96
  access: "public"
252
97
  },
253
98
  scripts: {
254
- build: "tsup && node scripts/check-dist.mjs",
99
+ build: "node scripts/vendor-natives.mjs && node scripts/check-vendored-swift.mjs && tsup && node scripts/check-dist.mjs",
255
100
  typecheck: "tsc --noEmit",
256
- test: "vitest run"
257
- },
258
- dependencies: {
259
- "@advenue/install-referrer": "workspace:*",
260
- "@advenue/sdk-core": "workspace:*"
101
+ test: "vitest run --minWorkers=1 --maxWorkers=2 && node --test scripts/vendor-natives.test.mjs && node scripts/vendor-natives.mjs && node scripts/check-vendored-swift.mjs",
102
+ vendor: "node scripts/vendor-natives.mjs"
261
103
  },
104
+ dependencies: {},
262
105
  peerDependencies: {
263
106
  "@expo/config-plugins": ">=8",
264
107
  react: ">=18.2",
@@ -274,8 +117,6 @@ var package_default = {
274
117
  }
275
118
  },
276
119
  devDependencies: {
277
- "@advenue/shared": "workspace:*",
278
- "@advenue/signing": "workspace:*",
279
120
  tsup: "^8.5.1",
280
121
  typescript: "^5.7.2",
281
122
  vitest: "^2.1.8"
@@ -283,18 +124,15 @@ var package_default = {
283
124
  "react-native": "./dist/index.cjs"
284
125
  };
285
126
 
286
- // src/aem.ts
287
- function extractAemCampaignIds(alApplinkData) {
288
- try {
289
- const parsed = JSON.parse(alApplinkData);
290
- const value = typeof parsed.campaign_ids === "string" && parsed.campaign_ids ? parsed.campaign_ids : typeof parsed.extras?.campaign_ids === "string" && parsed.extras.campaign_ids ? parsed.extras.campaign_ids : null;
291
- return value && value.length <= 2048 ? value : null;
292
- } catch {
293
- return null;
294
- }
295
- }
296
-
297
127
  // src/deep-links.ts
128
+ var ALLOWED_QUERY_KEYS = /* @__PURE__ */ new Set([
129
+ "ref",
130
+ "campaign",
131
+ "network",
132
+ "influencer_id",
133
+ "influencerId",
134
+ "al_applink_data"
135
+ ]);
298
136
  function parseDirectLink(url) {
299
137
  let deepLinkValue = "";
300
138
  let params;
@@ -304,6 +142,7 @@ function parseDirectLink(url) {
304
142
  const isHttp = parsed.protocol === "http:" || parsed.protocol === "https:";
305
143
  deepLinkValue = isHttp ? path : [parsed.host, path].filter(Boolean).join("/");
306
144
  parsed.searchParams.forEach((v, k) => {
145
+ if (!ALLOWED_QUERY_KEYS.has(k)) return;
307
146
  params ??= {};
308
147
  params[k] = v;
309
148
  });
@@ -339,15 +178,6 @@ function setupDeepLinks(setup) {
339
178
  return { remove: () => listener.remove(), ready };
340
179
  }
341
180
 
342
- // src/mmkv-storage.ts
343
- function createMMKVStorage(mmkv) {
344
- return {
345
- getItem: (key) => mmkv.getString(key) ?? null,
346
- setItem: (key, value) => mmkv.set(key, value),
347
- removeItem: (key) => mmkv.delete(key)
348
- };
349
- }
350
-
351
181
  // src/native.ts
352
182
  var import_native_require = __toESM(require_native_require(), 1);
353
183
  function getIosNative() {
@@ -374,27 +204,6 @@ function getPlatformOS() {
374
204
  return null;
375
205
  }
376
206
  }
377
- function getOsVersion() {
378
- try {
379
- const rn = (0, import_native_require.requireReactNative)();
380
- if (!rn) return null;
381
- if (rn.Platform.OS === "android") {
382
- const release = rn.Platform.constants?.Release;
383
- return release != null ? String(release) : null;
384
- }
385
- return rn.Platform.Version != null ? String(rn.Platform.Version) : null;
386
- } catch {
387
- return null;
388
- }
389
- }
390
- function getAppState() {
391
- try {
392
- const rn = (0, import_native_require.requireReactNative)();
393
- return rn?.AppState ?? null;
394
- } catch {
395
- return null;
396
- }
397
- }
398
207
  function getLinking() {
399
208
  try {
400
209
  const rn = (0, import_native_require.requireReactNative)();
@@ -404,510 +213,214 @@ function getLinking() {
404
213
  }
405
214
  }
406
215
 
407
- // src/native-storage.ts
408
- function createNativeStorage(mod) {
409
- const m = mod;
410
- if (!m || typeof m.storageGetItem !== "function" || typeof m.storageSetItem !== "function" || typeof m.storageRemoveItem !== "function") {
411
- return null;
412
- }
413
- return {
414
- getItem: (key) => m.storageGetItem?.(key) ?? null,
415
- setItem: (key, value) => m.storageSetItem?.(key, value),
416
- removeItem: (key) => m.storageRemoveItem?.(key)
417
- };
418
- }
419
- function createNativeSecureStore(mod) {
420
- const m = mod;
421
- if (!m || typeof m.secureGetItem !== "function" || typeof m.secureSetItem !== "function" || typeof m.secureRemoveItem !== "function") {
422
- return null;
423
- }
424
- return {
425
- getItemAsync: async (key) => m.secureGetItem?.(key) ?? null,
426
- setItemAsync: async (key, value) => m.secureSetItem?.(key, value),
427
- deleteItemAsync: async (key) => m.secureRemoveItem?.(key)
428
- };
429
- }
430
-
431
- // src/secure-store.ts
432
- function createSecureStore(secureStore2) {
433
- return {
434
- getItemAsync: async (key) => await secureStore2.getItemAsync(key) ?? null,
435
- setItemAsync: (key, value) => secureStore2.setItemAsync(key, value),
436
- ...secureStore2.deleteItemAsync ? {
437
- deleteItemAsync: (key) => secureStore2.deleteItemAsync?.(key) ?? Promise.resolve()
438
- } : {}
439
- };
440
- }
441
-
442
216
  // src/index.ts
443
- async function resolveAdvertisingId() {
444
- const client = active();
445
- const consent = client.getConsentData();
446
- if (client.getRequireConsent() && consent == null) {
447
- client.setAdvertisingId({});
448
- return;
449
- }
450
- if (consent?.isUserSubjectToGDPR === true && consent.hasConsentForDataUsage !== true) {
451
- client.setAdvertisingId({});
452
- return;
453
- }
454
- const ios = getIosNative();
455
- if (ios) {
456
- const idfa = ios.getTrackingAuthorizationStatus() === "authorized" ? await ios.getAdvertisingId() : null;
457
- const vendorId = typeof ios.getIdentifierForVendor === "function" ? ios.getIdentifierForVendor() : null;
458
- client.setAdvertisingId({ ...idfa ? { idfa } : {}, ...vendorId ? { vendorId } : {} });
459
- return;
460
- }
461
- const android = getAndroidNative();
462
- if (android && typeof android.getAdvertisingId === "function") {
463
- const r = await android.getAdvertisingId();
464
- const vendorId = typeof android.getAppSetId === "function" ? await android.getAppSetId() : null;
465
- const adFields = r ? r.limitAdTracking ? { limitAdTracking: true } : { gaid: r.id } : {};
466
- const hasUsableGaid = !!r && !r.limitAdTracking;
467
- const rawAndroidId = !hasUsableGaid && typeof android.getAndroidId === "function" ? android.getAndroidId() : null;
468
- const androidId = rawAndroidId && /^[0-9a-fA-F]{8,32}$/.test(rawAndroidId) ? rawAndroidId : null;
469
- client.setAdvertisingId({
470
- ...adFields,
471
- ...vendorId ? { vendorId } : {},
472
- ...androidId ? { androidId } : {}
473
- });
474
- return;
475
- }
476
- client.setAdvertisingId({});
477
- }
478
- function consentEquals(a, b) {
479
- return a.isUserSubjectToGDPR === b.isUserSubjectToGDPR && a.hasConsentForDataUsage === b.hasConsentForDataUsage && a.hasConsentForAdsPersonalization === b.hasConsentForAdsPersonalization && a.hasConsentForAdStorage === b.hasConsentForAdStorage;
217
+ var IGNORED_OPTIONS = [
218
+ "mmkv",
219
+ "secureStore",
220
+ "sdkConfigFetcher",
221
+ "tcfDataCollection",
222
+ "appVersion"
223
+ ];
224
+ var started = false;
225
+ var deepLinkSub = null;
226
+ var errorSub = null;
227
+ var onErrorHook;
228
+ var consentCache = false;
229
+ function bridge() {
230
+ return { ios: getIosNative(), android: getAndroidNative() };
480
231
  }
481
- function resolveDmaConsent() {
482
- if (manualConsentSet) return null;
483
- const native = getIosNative() ?? getAndroidNative();
484
- if (!native || typeof native.getTcfData !== "function") return null;
485
- let consent = null;
486
- try {
487
- consent = (0, import_sdk_core.tcfToConsent)(native.getTcfData());
488
- } catch (err) {
489
- reportError("consent.tcfRead", err);
490
- return null;
232
+ function call(name, ...args) {
233
+ const { ios, android } = bridge();
234
+ for (const mod of [ios, android]) {
235
+ const fn = mod?.[name];
236
+ if (typeof fn === "function") {
237
+ try {
238
+ return fn(...args);
239
+ } catch (error) {
240
+ report(`bridge.${name}`, error);
241
+ return void 0;
242
+ }
243
+ }
491
244
  }
492
- if (!consent) return null;
493
- const client = active();
494
- const current = client.getConsentData();
495
- if (current && consentEquals(current, consent)) return null;
496
- client.setConsentData(consent);
497
- void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
498
- return consent;
245
+ return void 0;
499
246
  }
500
- function readNativeDeviceInfo(natives) {
247
+ function report(context, cause) {
501
248
  try {
502
- if (natives.platform === "android" && natives.android?.getDeviceInfo) {
503
- return natives.android.getDeviceInfo();
504
- }
505
- if (natives.platform === "ios" && natives.ios?.getDeviceInfo) {
506
- return natives.ios.getDeviceInfo();
507
- }
249
+ onErrorHook?.(context, cause);
508
250
  } catch {
509
251
  }
510
- return {};
511
- }
512
- function collectDeviceInfo(natives) {
513
- const { shortVersion: _shortVersion, ...info } = readNativeDeviceInfo(natives);
514
- return info;
515
- }
516
- function applyAppState(client, status) {
517
- if (status === "active") {
518
- client.notifyAppActive();
519
- } else if (status === "background") {
520
- client.notifyAppBackground();
521
- }
522
- }
523
- var instance = null;
524
- var appStateSub = null;
525
- var deepLinkSub = null;
526
- var secureStore = null;
527
- var installFlagStore = null;
528
- var INSTALL_SENT_KEY = "advenue.install_sent";
529
- var installInFlight = false;
530
- var autoInstallPending = false;
531
- var autoInstallEnabled = true;
532
- var manualConsentSet = false;
533
- var tcfCollectionEnabled = false;
534
- var ATTEST_CHALLENGE_TIMEOUT_MS = 5e3;
535
- var configuredApiKey = null;
536
- var configuredEndpoint = import_sdk_core.DEFAULT_ENDPOINT;
537
- var aemSeenUrlHashes = /* @__PURE__ */ new Set();
538
- function active() {
539
- if (!instance) {
540
- throw new Error("Advenue.initialize() must be called before tracking events.");
541
- }
542
- return instance;
543
- }
544
- function reportError(context, cause) {
545
- instance?.report(context, cause);
546
- }
547
- function fireAutoInstall() {
548
- void trackInstall().catch((err) => reportError("install.auto", err));
549
- }
550
- function resolvePlatform(explicit) {
551
- if (explicit) {
552
- return explicit;
553
- }
554
- const os = getPlatformOS();
555
- if (os === "ios" || os === "android") {
556
- return os;
557
- }
558
- if (os) {
559
- return "web";
560
- }
561
- throw new Error(
562
- "Advenue.initialize(): platform could not be detected (react-native unavailable) \u2014 pass platform: 'ios' | 'android' | 'web'."
563
- );
564
252
  }
565
- function fireAutoInstallIfPending() {
566
- if (!autoInstallPending) {
567
- return;
568
- }
569
- autoInstallPending = false;
570
- fireAutoInstall();
253
+ function requireStarted() {
254
+ if (started) return true;
255
+ report("sdk.notInitialized", new Error("Advenue.initialize() has not been called"));
256
+ return false;
571
257
  }
572
258
  var Advenue = {
259
+ /**
260
+ * Starts the SDK. Safe to call from the app's entry point, and safe to call
261
+ * twice: the native side replaces its previous instance.
262
+ */
573
263
  async initialize(config) {
574
- const {
575
- mmkv,
576
- secureStore: secureMod,
577
- onDeepLink,
578
- autoTrackInstall,
579
- tcfDataCollection,
580
- ...rest
581
- } = config;
582
- autoInstallPending = false;
583
- manualConsentSet = false;
584
- tcfCollectionEnabled = tcfDataCollection === true;
585
- autoInstallEnabled = autoTrackInstall !== false;
586
- const platform = resolvePlatform(rest.platform);
587
- configuredApiKey = config.apiKey;
588
- configuredEndpoint = config.endpoint ?? import_sdk_core.DEFAULT_ENDPOINT;
589
- appStateSub?.remove();
590
- appStateSub = null;
591
- deepLinkSub?.remove();
592
- deepLinkSub = null;
593
- instance?.shutdown();
594
- const iosMod = getIosNative();
595
- const androidMod = getAndroidNative();
596
- const storage = mmkv ? createMMKVStorage(mmkv) : createNativeStorage(iosMod ?? androidMod) ?? new import_sdk_core.MemoryStorage();
597
- installFlagStore = storage;
598
- secureStore = secureMod ? createSecureStore(secureMod) : createNativeSecureStore(iosMod);
599
- const deviceId = rest.deviceId ?? await (0, import_sdk_core.resolveDurableDeviceId)(storage, secureStore ?? void 0);
600
- const osVersion = rest.osVersion ?? getOsVersion() ?? void 0;
601
- const nativeDeviceInfo = readNativeDeviceInfo({
602
- platform,
603
- ios: getIosNative(),
604
- android: getAndroidNative()
605
- });
606
- const { shortVersion, ...deviceInfo } = nativeDeviceInfo;
607
- const appVersion = rest.appVersion ?? shortVersion ?? void 0;
608
- instance = new import_sdk_core.AdvenueClient({
609
- ...rest,
610
- platform,
611
- deviceId,
612
- storage,
613
- ...osVersion ? { osVersion } : {},
614
- ...appVersion ? { appVersion } : {},
615
- // Stamped by the SDK, never by the host app — see AdvenueConfig.sdkVersion.
616
- sdkVersion: package_default.version
617
- });
618
- instance.debugLog(`SDK v${package_default.version} \u2014 events -> ${configuredEndpoint}`);
619
- if (tcfCollectionEnabled) resolveDmaConsent();
620
- void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
621
- if (Object.keys(deviceInfo).length > 0) instance.setDeviceInfo(deviceInfo);
622
- if (!config.disableAutoSessions) {
623
- const appState = getAppState();
624
- if (appState) {
625
- appStateSub?.remove();
626
- let seenBackground = false;
627
- const handler = (status) => {
628
- if (!instance) return;
629
- if (status === "background") {
630
- seenBackground = true;
631
- if (tcfCollectionEnabled) resolveDmaConsent();
632
- applyAppState(instance, status);
633
- } else if (status === "active") {
634
- if (!seenBackground) return;
635
- seenBackground = false;
636
- if (tcfCollectionEnabled) resolveDmaConsent();
637
- applyAppState(instance, status);
638
- void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
639
- }
640
- };
641
- appStateSub = appState.addEventListener("change", handler);
642
- instance.notifyAppActive();
643
- } else {
644
- instance.notifyAppActive();
264
+ onErrorHook = config.onError;
265
+ for (const option of IGNORED_OPTIONS) {
266
+ if (config[option] !== void 0) {
267
+ report(
268
+ `config.ignored:${option}`,
269
+ new Error(`${option} is decided by the native SDK and has no effect`)
270
+ );
645
271
  }
646
272
  }
647
- {
648
- const linking = getLinking();
649
- if (linking) {
650
- const client = instance;
651
- deepLinkSub = setupDeepLinks({
652
- getInitialURL: () => linking.getInitialURL(),
653
- addUrlListener: (handler) => linking.addEventListener("url", (e) => handler(e.url)),
654
- // Deferred deep link: server-side conversion poll (deterministic ids
655
- // where available, probabilistic otherwise).
656
- resolveDeferred: () => client.resolveDeferredDeepLink(),
657
- onDeepLink: onDeepLink ?? (() => {
658
- }),
659
- onDirectUrl: (url, link) => {
660
- const raw = link.params?.al_applink_data;
661
- if (typeof raw !== "string") return;
662
- const campaignIds = extractAemCampaignIds(raw);
663
- if (!campaignIds) return;
664
- const sourceUrlHash = sha256Hex(url);
665
- if (aemSeenUrlHashes.has(sourceUrlHash)) return;
666
- if (client.getRequireConsent() && !client.getTrackingConsent()) return;
667
- client.track("adv_meta_aem", { campaignIds, sourceUrlHash });
668
- aemSeenUrlHashes.add(sourceUrlHash);
669
- }
273
+ Advenue.shutdown();
274
+ call("bridgeInitialize", {
275
+ apiKey: config.apiKey,
276
+ endpoint: config.endpoint,
277
+ requireConsent: config.requireConsent ?? false,
278
+ batchSize: config.batchSize,
279
+ flushIntervalMs: config.flushIntervalMs,
280
+ signingSecret: config.signingSecret,
281
+ fbAppId: config.fbAppId,
282
+ autoTrackInstall: config.autoTrackInstall !== false,
283
+ sdkVersion: package_default.version
284
+ });
285
+ started = true;
286
+ const { ios: iosForErrors, android: androidForErrors } = bridge();
287
+ const emitter = iosForErrors ?? androidForErrors;
288
+ if (typeof emitter?.addListener === "function") {
289
+ try {
290
+ errorSub = emitter.addListener("onAdvenueError", (event) => {
291
+ report(event.context, new Error(event.message));
670
292
  });
671
- deepLinkSub.ready.catch((err) => reportError("deepLink.resolve", err));
293
+ } catch (error) {
294
+ report("diagnostics.subscribe", error);
672
295
  }
673
296
  }
674
- if (autoTrackInstall !== false) {
675
- if (instance.getRequireConsent() && !instance.getTrackingConsent()) {
676
- autoInstallPending = true;
677
- instance.debugLog("install deferred until consent is granted");
678
- } else {
679
- fireAutoInstall();
297
+ consentCache = call("bridgeGetConsent") ?? false;
298
+ if (config.appInstanceIdProvider) {
299
+ try {
300
+ const id = await config.appInstanceIdProvider();
301
+ if (id) call("bridgeSetAppInstanceId", id);
302
+ } catch (error) {
303
+ report("enrich.appInstanceId", error);
680
304
  }
681
305
  }
682
- return instance;
306
+ const linking = getLinking();
307
+ if (linking) {
308
+ deepLinkSub = setupDeepLinks({
309
+ getInitialURL: () => linking.getInitialURL(),
310
+ addUrlListener: (handler) => linking.addEventListener("url", (e) => handler(e.url)),
311
+ resolveDeferred: () => Advenue.resolveDeferredDeepLink(),
312
+ onDeepLink: config.onDeepLink ?? (() => {
313
+ }),
314
+ onDirectUrl: (url) => {
315
+ call("bridgeProcessDeepLink", url);
316
+ }
317
+ });
318
+ deepLinkSub.ready.catch((error) => report("deepLink.resolve", error));
319
+ }
320
+ },
321
+ track(name, properties) {
322
+ if (!requireStarted()) return;
323
+ call("bridgeTrack", name, properties ?? null);
324
+ },
325
+ /** Adds exact local revenue to Apple's conversion-value state. iOS only. */
326
+ async recordSkanRevenue(input) {
327
+ if (!requireStarted()) return;
328
+ call("bridgeRecordSkanRevenue", input.amount, input.currency);
329
+ },
330
+ setAppInstanceId(id) {
331
+ if (!requireStarted()) return;
332
+ call("bridgeSetAppInstanceId", id);
333
+ },
334
+ /**
335
+ * Cross-device linking: associates subsequent events with your user id.
336
+ * Pass null to clear.
337
+ *
338
+ * New on this object. The previous release reached it through the client
339
+ * `initialize()` resolved to, and that client no longer exists — so it is
340
+ * promoted here rather than dropped, which is what an app following the
341
+ * documented cross-device recipe would otherwise hit at runtime.
342
+ */
343
+ setUserId(id) {
344
+ if (!requireStarted()) return;
345
+ call("bridgeSetUserId", id);
346
+ },
347
+ /**
348
+ * Registers the device's push token for uninstall measurement.
349
+ *
350
+ * Advenue never requests the notification permission and never displays
351
+ * anything: pass the token your push library already produced, on every
352
+ * launch and from its refresh listener. A stale token is the one thing that
353
+ * makes uninstall measurement report churn that did not happen.
354
+ */
355
+ setPushToken(token, provider) {
356
+ if (!requireStarted()) return;
357
+ call("bridgeSetPushToken", token, provider ?? null);
683
358
  },
684
- track: (name, properties, opts) => active().track(name, properties, opts),
685
359
  /**
686
- * Shows the iOS ATT prompt (resolves 'authorized' immediately on Android/web,
687
- * where ATT doesn't exist) and forwards the result to the consent gate.
360
+ * Shows the iOS ATT prompt. Where ATT does not exist (non-iOS, or the iOS
361
+ * module is absent) there is no prompt to show and no signal to read, so
362
+ * consent is left untouched and the call resolves 'unavailable'.
688
363
  */
689
364
  async requestTrackingAuthorization() {
690
- const ios = getIosNative();
691
- const status = ios ? await ios.requestTrackingAuthorization() : "authorized";
692
- active().setTrackingConsent(status === "authorized");
693
- void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
694
- if (status === "authorized") {
695
- fireAutoInstallIfPending();
696
- }
365
+ const { ios } = bridge();
366
+ if (!ios) return "unavailable";
367
+ const status = await ios.requestTrackingAuthorization();
368
+ Advenue.setTrackingConsent(status === "authorized");
697
369
  return status;
698
370
  },
699
371
  setTrackingConsent(granted) {
700
- active().setTrackingConsent(granted);
701
- if (granted) {
702
- fireAutoInstallIfPending();
703
- }
372
+ if (!requireStarted()) return;
373
+ consentCache = granted;
374
+ call("bridgeSetConsent", granted);
704
375
  },
705
- getTrackingConsent: () => active().getTrackingConsent(),
706
- /** GDPR/CCPA erasure: stop tracking and wipe local identifiers/queue. */
376
+ getTrackingConsent: () => consentCache,
377
+ setConsentData(consent) {
378
+ if (!requireStarted()) return;
379
+ call("bridgeSetConsentData", consent);
380
+ },
381
+ getConsentData: () => call("bridgeGetConsentData") ?? null,
382
+ /** GDPR/CCPA erasure: stops tracking and wipes local identifiers and queue. */
707
383
  forgetMe() {
708
- active().forgetMe();
709
- try {
710
- installFlagStore?.removeItem(INSTALL_SENT_KEY);
711
- } catch (err) {
712
- reportError("forget.wipe", err);
713
- }
714
- const secure = secureStore;
715
- if (secure?.deleteItemAsync) {
716
- for (const key of [import_sdk_core.DEVICE_ID_KEY, INSTALL_SENT_KEY]) {
717
- void secure.deleteItemAsync(key).catch((err) => reportError("forget.secureWipe", err));
718
- }
719
- }
384
+ if (!requireStarted()) return;
385
+ call("bridgeForgetMe");
386
+ consentCache = false;
720
387
  },
721
- setConsentData(consent) {
722
- manualConsentSet = true;
723
- active().setConsentData(consent);
724
- void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
388
+ flush() {
389
+ if (!requireStarted()) return;
390
+ call("bridgeFlush");
391
+ },
392
+ getDeviceId: () => Promise.resolve(
393
+ call("bridgeDeviceId") ?? null
394
+ ),
395
+ /** The Advenue ID — alias of `getDeviceId`. */
396
+ getAdvenueId: () => Advenue.getDeviceId(),
397
+ /** Which app the server resolved this API key to; null until a batch lands. */
398
+ getResolvedAppId: () => call("bridgeResolvedAppId") ?? null,
399
+ /**
400
+ * Resolves the deferred deep link for this install, or null for an organic
401
+ * one — which is most of them.
402
+ */
403
+ async resolveDeferredDeepLink() {
404
+ if (!requireStarted()) return null;
405
+ const result = call("bridgeResolveDeferredDeepLink");
406
+ return await result ?? null;
725
407
  },
726
- getConsentData: () => active().getConsentData(),
727
- flush: () => active().flush(),
728
- getDeviceId: () => active().getDeviceId(),
729
- /** The Advenue ID — alias of getDeviceId (see AdvenueClient.getAdvenueId). */
730
- getAdvenueId: () => active().getAdvenueId(),
731
- /** Which app the server resolved this API key to; null until a batch lands
732
- * (see AdvenueClient.getResolvedAppId). */
733
- getResolvedAppId: () => active().getResolvedAppId(),
734
408
  shutdown() {
735
- appStateSub?.remove();
736
- appStateSub = null;
737
409
  deepLinkSub?.remove();
738
410
  deepLinkSub = null;
739
- instance?.shutdown();
740
- instance = null;
741
- secureStore = null;
742
- installInFlight = false;
743
- autoInstallPending = false;
744
- autoInstallEnabled = true;
745
- manualConsentSet = false;
746
- tcfCollectionEnabled = false;
747
- configuredApiKey = null;
748
- configuredEndpoint = import_sdk_core.DEFAULT_ENDPOINT;
749
- aemSeenUrlHashes.clear();
411
+ errorSub?.remove();
412
+ errorSub = null;
413
+ if (started) call("bridgeShutdown");
414
+ started = false;
415
+ consentCache = false;
750
416
  }
751
417
  };
752
- async function trackInstall() {
753
- const client = active();
754
- if (client.getRequireConsent() && !client.getTrackingConsent()) {
755
- return;
756
- }
757
- let sent = installFlagStore?.getItem(INSTALL_SENT_KEY) === "1";
758
- if (!sent && secureStore) {
759
- try {
760
- sent = await secureStore.getItemAsync(INSTALL_SENT_KEY) === "1";
761
- } catch (err) {
762
- reportError("install.guardRead", err);
763
- }
764
- }
765
- if (sent) {
766
- client.debugLog("install skipped (already sent on this device)");
767
- return;
768
- }
769
- if (installInFlight) {
770
- return;
771
- }
772
- installInFlight = true;
773
- const opts = {};
774
- const props = {};
775
- const android = getAndroidNative();
776
- if (android) {
777
- try {
778
- const result = await android.getInstallReferrer();
779
- if (result) {
780
- const parsed = (0, import_install_referrer.parseInstallReferrer)(result.referrer);
781
- if (parsed.network) opts.network = parsed.network;
782
- if (parsed.campaign) opts.campaign = parsed.campaign;
783
- if (parsed.gclid) props.gclid = parsed.gclid;
784
- if (parsed.fbclid) props.fbclid = parsed.fbclid;
785
- Object.assign(props, (0, import_install_referrer.extractReferrerProperties)(result));
786
- }
787
- } catch (err) {
788
- reportError("enrich.installReferrer", err);
789
- }
790
- try {
791
- const meta = await android.getMetaInstallReferrer();
792
- const parsedMeta = meta ? (0, import_install_referrer.parseMetaInstallReferrer)(meta) : null;
793
- if (parsedMeta) {
794
- props.metaInstallReferrer = parsedMeta.raw;
795
- if (parsedMeta.encryptedData) props.metaReferrerData = parsedMeta.encryptedData;
796
- if (parsedMeta.nonce) props.metaReferrerNonce = parsedMeta.nonce;
797
- if (!opts.network && parsedMeta.isClickThrough) {
798
- opts.network = "meta";
799
- if (parsedMeta.campaign) opts.campaign = parsedMeta.campaign;
800
- }
801
- }
802
- } catch (err) {
803
- reportError("enrich.metaReferrer", err);
804
- }
805
- }
806
- const ios = getIosNative();
807
- if (ios) {
808
- try {
809
- ios.registerAppForAttribution();
810
- } catch (err) {
811
- reportError("enrich.skanRegister", err);
812
- }
813
- try {
814
- const asaToken = await ios.getAttributionToken();
815
- if (asaToken) {
816
- opts.adservicesToken = asaToken;
817
- }
818
- } catch (err) {
819
- reportError("enrich.adservicesToken", err);
820
- }
821
- }
822
- await resolveAdvertisingId();
823
- const trackOpts = { type: "install", ...opts };
824
- if (android && typeof android.getIntegrityToken === "function") {
825
- try {
826
- const deviceId = client.getDeviceId();
827
- const requestHash = sha256Hex(deviceId);
828
- const token = await android.getIntegrityToken(requestHash);
829
- if (token) {
830
- trackOpts.attestationToken = token;
831
- trackOpts.attestationType = "play-integrity";
832
- }
833
- } catch (err) {
834
- reportError("attest.playIntegrity", err);
835
- }
836
- }
837
- if (configuredApiKey && ios && typeof ios.attestKey === "function") {
838
- try {
839
- const deviceId = client.getDeviceId();
840
- const challengeUrl = `${configuredEndpoint}/v1/attest/challenge?deviceId=${encodeURIComponent(deviceId)}`;
841
- const ac = new AbortController();
842
- const timer = setTimeout(
843
- () => ac.abort(new Error("attest challenge timed out")),
844
- ATTEST_CHALLENGE_TIMEOUT_MS
845
- );
846
- let challengeRes;
847
- try {
848
- challengeRes = await fetch(challengeUrl, {
849
- headers: { "x-api-key": configuredApiKey },
850
- signal: ac.signal
851
- });
852
- } finally {
853
- clearTimeout(timer);
854
- }
855
- if (!challengeRes.ok) throw new Error(`challenge HTTP ${challengeRes.status}`);
856
- const { challenge } = await challengeRes.json();
857
- const { keyId, attestationObject } = await ios.attestKey(challenge);
858
- trackOpts.attestationToken = attestationObject;
859
- trackOpts.attestationType = "app-attest";
860
- trackOpts.attestationKeyId = keyId;
861
- trackOpts.attestationChallenge = challenge;
862
- } catch (err) {
863
- reportError("attest.appAttest", err);
864
- }
865
- }
866
- if (ios && typeof ios.getDeviceCheckToken === "function") {
867
- try {
868
- const token = await ios.getDeviceCheckToken();
869
- if (token) {
870
- trackOpts.deviceCheckToken = token;
871
- }
872
- } catch (err) {
873
- reportError("attest.deviceCheck", err);
874
- }
875
- }
876
- const pendingBefore = client.pendingCount;
877
- client.track("install", props, trackOpts);
878
- if (client.pendingCount === pendingBefore) {
879
- installInFlight = false;
880
- client.debugLog("install dropped (consent revoked mid-flight)");
881
- if (autoInstallEnabled && client.getRequireConsent() && !client.getTrackingConsent()) {
882
- autoInstallPending = true;
883
- }
884
- return;
885
- }
886
- client.debugLog("install fired");
887
- try {
888
- installFlagStore?.setItem(INSTALL_SENT_KEY, "1");
889
- } catch (err) {
890
- reportError("install.flagPersist", err);
891
- }
892
- if (secureStore) {
893
- try {
894
- await secureStore.setItemAsync(INSTALL_SENT_KEY, "1");
895
- } catch (err) {
896
- reportError("install.flagPersistSecure", err);
897
- }
898
- }
899
- }
418
+ var platform = getPlatformOS;
900
419
  // Annotate the CommonJS export names for ESM import in node:
901
420
  0 && (module.exports = {
902
421
  Advenue,
903
- applyAppState,
904
- collectDeviceInfo,
905
- createMMKVStorage,
906
- createSecureStore,
907
422
  getAndroidNative,
908
423
  getIosNative,
909
424
  parseDirectLink,
910
- resolveAdvertisingId,
911
- resolveDmaConsent,
912
- trackInstall
425
+ platform
913
426
  });