@advenue/react-native 0.5.0 → 0.6.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,762 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/native-require.cjs
34
+ var require_native_require = __commonJS({
35
+ "src/native-require.cjs"(exports2, module2) {
36
+ "use strict";
37
+ module2.exports.requireExpoModulesCore = function requireExpoModulesCore2() {
38
+ try {
39
+ return require("expo-modules-core");
40
+ } catch {
41
+ return null;
42
+ }
43
+ };
44
+ module2.exports.requireReactNative = function requireReactNative2() {
45
+ try {
46
+ return require("react-native");
47
+ } catch {
48
+ return null;
49
+ }
50
+ };
51
+ }
52
+ });
53
+
54
+ // src/index.ts
55
+ var index_exports = {};
56
+ __export(index_exports, {
57
+ Advenue: () => Advenue,
58
+ applyAppState: () => applyAppState,
59
+ collectDeviceInfo: () => collectDeviceInfo,
60
+ createMMKVStorage: () => createMMKVStorage,
61
+ createSecureStore: () => createSecureStore,
62
+ getAndroidNative: () => getAndroidNative,
63
+ getIosNative: () => getIosNative,
64
+ parseDirectLink: () => parseDirectLink,
65
+ resolveAdvertisingId: () => resolveAdvertisingId,
66
+ resolveClipboardMatch: () => resolveClipboardMatch,
67
+ trackInstall: () => trackInstall
68
+ });
69
+ 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
+ // ../shared/src/match-token.ts
74
+ var MATCH_TOKEN_PREFIX = "advmatch:";
75
+ function parseMatchToken(raw) {
76
+ if (!raw || !raw.startsWith(MATCH_TOKEN_PREFIX)) return null;
77
+ const id = raw.slice(MATCH_TOKEN_PREFIX.length).trim();
78
+ return /^[A-Za-z0-9_-]{1,128}$/.test(id) ? id : null;
79
+ }
80
+
81
+ // ../signing/src/index.ts
82
+ var K = new Uint32Array([
83
+ 1116352408,
84
+ 1899447441,
85
+ 3049323471,
86
+ 3921009573,
87
+ 961987163,
88
+ 1508970993,
89
+ 2453635748,
90
+ 2870763221,
91
+ 3624381080,
92
+ 310598401,
93
+ 607225278,
94
+ 1426881987,
95
+ 1925078388,
96
+ 2162078206,
97
+ 2614888103,
98
+ 3248222580,
99
+ 3835390401,
100
+ 4022224774,
101
+ 264347078,
102
+ 604807628,
103
+ 770255983,
104
+ 1249150122,
105
+ 1555081692,
106
+ 1996064986,
107
+ 2554220882,
108
+ 2821834349,
109
+ 2952996808,
110
+ 3210313671,
111
+ 3336571891,
112
+ 3584528711,
113
+ 113926993,
114
+ 338241895,
115
+ 666307205,
116
+ 773529912,
117
+ 1294757372,
118
+ 1396182291,
119
+ 1695183700,
120
+ 1986661051,
121
+ 2177026350,
122
+ 2456956037,
123
+ 2730485921,
124
+ 2820302411,
125
+ 3259730800,
126
+ 3345764771,
127
+ 3516065817,
128
+ 3600352804,
129
+ 4094571909,
130
+ 275423344,
131
+ 430227734,
132
+ 506948616,
133
+ 659060556,
134
+ 883997877,
135
+ 958139571,
136
+ 1322822218,
137
+ 1537002063,
138
+ 1747873779,
139
+ 1955562222,
140
+ 2024104815,
141
+ 2227730452,
142
+ 2361852424,
143
+ 2428436474,
144
+ 2756734187,
145
+ 3204031479,
146
+ 3329325298
147
+ ]);
148
+ function rotr(x, n) {
149
+ return x >>> n | x << 32 - n;
150
+ }
151
+ function sha256Bytes(msg) {
152
+ const h = new Uint32Array([
153
+ 1779033703,
154
+ 3144134277,
155
+ 1013904242,
156
+ 2773480762,
157
+ 1359893119,
158
+ 2600822924,
159
+ 528734635,
160
+ 1541459225
161
+ ]);
162
+ const l = msg.length;
163
+ const bitLen = l * 8;
164
+ const withOne = l + 1;
165
+ const padTo = (56 - withOne % 64 + 64) % 64;
166
+ const padded = new Uint8Array(withOne + padTo + 8);
167
+ padded.set(msg);
168
+ padded[l] = 128;
169
+ const dv = new DataView(padded.buffer);
170
+ dv.setUint32(padded.length - 8, Math.floor(bitLen / 4294967296));
171
+ dv.setUint32(padded.length - 4, bitLen >>> 0);
172
+ const w = new Uint32Array(64);
173
+ for (let i = 0; i < padded.length; i += 64) {
174
+ for (let t = 0; t < 16; t++) w[t] = dv.getUint32(i + t * 4);
175
+ for (let t = 16; t < 64; t++) {
176
+ const w15 = w[t - 15];
177
+ const w2 = w[t - 2];
178
+ const s0 = rotr(w15, 7) ^ rotr(w15, 18) ^ w15 >>> 3;
179
+ const s1 = rotr(w2, 17) ^ rotr(w2, 19) ^ w2 >>> 10;
180
+ w[t] = w[t - 16] + s0 + w[t - 7] + s1 >>> 0;
181
+ }
182
+ let a = h[0];
183
+ let b = h[1];
184
+ let c = h[2];
185
+ let d = h[3];
186
+ let e = h[4];
187
+ let f = h[5];
188
+ let g = h[6];
189
+ let hh = h[7];
190
+ for (let t = 0; t < 64; t++) {
191
+ const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
192
+ const ch = e & f ^ ~e & g;
193
+ const temp1 = hh + S1 + ch + K[t] + w[t] >>> 0;
194
+ const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
195
+ const maj = a & b ^ a & c ^ b & c;
196
+ const temp2 = S0 + maj >>> 0;
197
+ hh = g;
198
+ g = f;
199
+ f = e;
200
+ e = d + temp1 >>> 0;
201
+ d = c;
202
+ c = b;
203
+ b = a;
204
+ a = temp1 + temp2 >>> 0;
205
+ }
206
+ h[0] = h[0] + a >>> 0;
207
+ h[1] = h[1] + b >>> 0;
208
+ h[2] = h[2] + c >>> 0;
209
+ h[3] = h[3] + d >>> 0;
210
+ h[4] = h[4] + e >>> 0;
211
+ h[5] = h[5] + f >>> 0;
212
+ h[6] = h[6] + g >>> 0;
213
+ h[7] = h[7] + hh >>> 0;
214
+ }
215
+ const out = new Uint8Array(32);
216
+ const odv = new DataView(out.buffer);
217
+ for (let i = 0; i < 8; i++) odv.setUint32(i * 4, h[i]);
218
+ return out;
219
+ }
220
+ function toHex(bytes) {
221
+ let s = "";
222
+ for (let i = 0; i < bytes.length; i++) s += bytes[i].toString(16).padStart(2, "0");
223
+ return s;
224
+ }
225
+ var enc = new TextEncoder();
226
+ function sha256Hex(message) {
227
+ return toHex(sha256Bytes(enc.encode(message)));
228
+ }
229
+
230
+ // src/deep-links.ts
231
+ function parseDirectLink(url) {
232
+ let deepLinkValue = "";
233
+ let params;
234
+ try {
235
+ const parsed = new URL(url);
236
+ const path = parsed.pathname.replace(/^\/+/, "");
237
+ const isHttp = parsed.protocol === "http:" || parsed.protocol === "https:";
238
+ deepLinkValue = isHttp ? path : [parsed.host, path].filter(Boolean).join("/");
239
+ parsed.searchParams.forEach((v, k) => {
240
+ params ??= {};
241
+ params[k] = v;
242
+ });
243
+ } catch {
244
+ deepLinkValue = url;
245
+ }
246
+ return {
247
+ deepLinkValue,
248
+ ...params ? { params } : {},
249
+ url,
250
+ isDeferred: false,
251
+ isFirstLaunch: false
252
+ };
253
+ }
254
+ function setupDeepLinks(setup) {
255
+ const listener = setup.addUrlListener((url) => setup.onDeepLink(parseDirectLink(url)));
256
+ const ready = (async () => {
257
+ const initial = await setup.getInitialURL();
258
+ if (initial) {
259
+ setup.onDeepLink(parseDirectLink(initial));
260
+ return;
261
+ }
262
+ const deferred = await setup.resolveDeferred();
263
+ if (deferred?.deepLinkValue) {
264
+ setup.onDeepLink(deferred);
265
+ }
266
+ })();
267
+ return { remove: () => listener.remove(), ready };
268
+ }
269
+
270
+ // src/mmkv-storage.ts
271
+ function createMMKVStorage(mmkv) {
272
+ return {
273
+ getItem: (key) => mmkv.getString(key) ?? null,
274
+ setItem: (key, value) => mmkv.set(key, value),
275
+ removeItem: (key) => mmkv.delete(key)
276
+ };
277
+ }
278
+
279
+ // src/native.ts
280
+ var import_native_require = __toESM(require_native_require(), 1);
281
+ function getIosNative() {
282
+ try {
283
+ const core = (0, import_native_require.requireExpoModulesCore)();
284
+ return core ? core.requireNativeModule("AdvenueIos") : null;
285
+ } catch {
286
+ return null;
287
+ }
288
+ }
289
+ function getAndroidNative() {
290
+ try {
291
+ const core = (0, import_native_require.requireExpoModulesCore)();
292
+ return core ? core.requireNativeModule("AdvenueAndroid") : null;
293
+ } catch {
294
+ return null;
295
+ }
296
+ }
297
+ function getPlatformOS() {
298
+ try {
299
+ const rn = (0, import_native_require.requireReactNative)();
300
+ return rn?.Platform.OS ?? null;
301
+ } catch {
302
+ return null;
303
+ }
304
+ }
305
+ function getAppState() {
306
+ try {
307
+ const rn = (0, import_native_require.requireReactNative)();
308
+ return rn?.AppState ?? null;
309
+ } catch {
310
+ return null;
311
+ }
312
+ }
313
+ function getLinking() {
314
+ try {
315
+ const rn = (0, import_native_require.requireReactNative)();
316
+ return rn?.Linking ?? null;
317
+ } catch {
318
+ return null;
319
+ }
320
+ }
321
+
322
+ // src/native-storage.ts
323
+ function createNativeStorage(mod) {
324
+ const m = mod;
325
+ if (!m || typeof m.storageGetItem !== "function" || typeof m.storageSetItem !== "function" || typeof m.storageRemoveItem !== "function") {
326
+ return null;
327
+ }
328
+ return {
329
+ getItem: (key) => m.storageGetItem?.(key) ?? null,
330
+ setItem: (key, value) => m.storageSetItem?.(key, value),
331
+ removeItem: (key) => m.storageRemoveItem?.(key)
332
+ };
333
+ }
334
+ function createNativeSecureStore(mod) {
335
+ const m = mod;
336
+ if (!m || typeof m.secureGetItem !== "function" || typeof m.secureSetItem !== "function" || typeof m.secureRemoveItem !== "function") {
337
+ return null;
338
+ }
339
+ return {
340
+ getItemAsync: async (key) => m.secureGetItem?.(key) ?? null,
341
+ setItemAsync: async (key, value) => m.secureSetItem?.(key, value),
342
+ deleteItemAsync: async (key) => m.secureRemoveItem?.(key)
343
+ };
344
+ }
345
+
346
+ // src/secure-store.ts
347
+ function createSecureStore(secureStore2) {
348
+ return {
349
+ getItemAsync: async (key) => await secureStore2.getItemAsync(key) ?? null,
350
+ setItemAsync: (key, value) => secureStore2.setItemAsync(key, value),
351
+ ...secureStore2.deleteItemAsync ? {
352
+ deleteItemAsync: (key) => secureStore2.deleteItemAsync?.(key) ?? Promise.resolve()
353
+ } : {}
354
+ };
355
+ }
356
+
357
+ // src/index.ts
358
+ async function resolveAdvertisingId() {
359
+ const client = active();
360
+ const consent = client.getConsentData();
361
+ if (client.getRequireConsent() && consent == null) {
362
+ client.setAdvertisingId({});
363
+ return;
364
+ }
365
+ if (consent?.isUserSubjectToGDPR === true && consent.hasConsentForDataUsage !== true) {
366
+ client.setAdvertisingId({});
367
+ return;
368
+ }
369
+ const ios = getIosNative();
370
+ if (ios) {
371
+ const idfa = ios.getTrackingAuthorizationStatus() === "authorized" ? await ios.getAdvertisingId() : null;
372
+ const vendorId = typeof ios.getIdentifierForVendor === "function" ? ios.getIdentifierForVendor() : null;
373
+ client.setAdvertisingId({ ...idfa ? { idfa } : {}, ...vendorId ? { vendorId } : {} });
374
+ return;
375
+ }
376
+ const android = getAndroidNative();
377
+ if (android && typeof android.getAdvertisingId === "function") {
378
+ const r = await android.getAdvertisingId();
379
+ const vendorId = typeof android.getAppSetId === "function" ? await android.getAppSetId() : null;
380
+ const adFields = r ? r.limitAdTracking ? { limitAdTracking: true } : { gaid: r.id } : {};
381
+ const hasUsableGaid = !!r && !r.limitAdTracking;
382
+ const rawAndroidId = !hasUsableGaid && typeof android.getAndroidId === "function" ? android.getAndroidId() : null;
383
+ const androidId = rawAndroidId && /^[0-9a-fA-F]{8,32}$/.test(rawAndroidId) ? rawAndroidId : null;
384
+ client.setAdvertisingId({
385
+ ...adFields,
386
+ ...vendorId ? { vendorId } : {},
387
+ ...androidId ? { androidId } : {}
388
+ });
389
+ return;
390
+ }
391
+ client.setAdvertisingId({});
392
+ }
393
+ function collectDeviceInfo(natives) {
394
+ try {
395
+ if (natives.platform === "android" && natives.android?.getDeviceInfo) {
396
+ return natives.android.getDeviceInfo();
397
+ }
398
+ if (natives.platform === "ios" && natives.ios?.getDeviceInfo) {
399
+ return natives.ios.getDeviceInfo();
400
+ }
401
+ } catch {
402
+ }
403
+ return {};
404
+ }
405
+ async function resolveClipboardMatch() {
406
+ const client = active();
407
+ if (client.getRequireConsent() && !client.getTrackingConsent()) return null;
408
+ const ios = getIosNative();
409
+ if (!ios || typeof ios.getPasteboardMatchToken !== "function") {
410
+ return null;
411
+ }
412
+ let token;
413
+ try {
414
+ token = ios.getPasteboardMatchToken();
415
+ } catch (err) {
416
+ reportError("enrich.clipboardMatch", err);
417
+ return null;
418
+ }
419
+ const matchId = parseMatchToken(token);
420
+ if (!matchId) return null;
421
+ return client.exchangeClipboardMatch(matchId);
422
+ }
423
+ function applyAppState(client, status) {
424
+ if (status === "active") {
425
+ client.notifyAppActive();
426
+ } else if (status === "background") {
427
+ client.notifyAppBackground();
428
+ }
429
+ }
430
+ var instance = null;
431
+ var appStateSub = null;
432
+ var deepLinkSub = null;
433
+ var secureStore = null;
434
+ var installFlagStore = null;
435
+ var INSTALL_SENT_KEY = "advenue.install_sent";
436
+ var installInFlight = false;
437
+ var autoInstallPending = false;
438
+ var autoInstallEnabled = true;
439
+ var configuredAppId = null;
440
+ var configuredApiKey = null;
441
+ var configuredEndpoint = import_sdk_core.DEFAULT_ENDPOINT;
442
+ function active() {
443
+ if (!instance) {
444
+ throw new Error("Advenue.initialize() must be called before tracking events.");
445
+ }
446
+ return instance;
447
+ }
448
+ function reportError(context, cause) {
449
+ instance?.report(context, cause);
450
+ }
451
+ function fireAutoInstall() {
452
+ void trackInstall().catch((err) => reportError("install.auto", err));
453
+ }
454
+ function resolvePlatform(explicit) {
455
+ if (explicit) {
456
+ return explicit;
457
+ }
458
+ const os = getPlatformOS();
459
+ if (os === "ios" || os === "android") {
460
+ return os;
461
+ }
462
+ if (os) {
463
+ return "web";
464
+ }
465
+ throw new Error(
466
+ "Advenue.initialize(): platform could not be detected (react-native unavailable) \u2014 pass platform: 'ios' | 'android' | 'web'."
467
+ );
468
+ }
469
+ function fireAutoInstallIfPending() {
470
+ if (!autoInstallPending) {
471
+ return;
472
+ }
473
+ autoInstallPending = false;
474
+ fireAutoInstall();
475
+ }
476
+ var Advenue = {
477
+ async initialize(config) {
478
+ const { mmkv, secureStore: secureMod, onDeepLink, appId, autoTrackInstall, ...rest } = config;
479
+ autoInstallPending = false;
480
+ autoInstallEnabled = autoTrackInstall !== false;
481
+ const platform = resolvePlatform(rest.platform);
482
+ configuredAppId = appId ?? null;
483
+ configuredApiKey = config.apiKey;
484
+ configuredEndpoint = config.endpoint ?? import_sdk_core.DEFAULT_ENDPOINT;
485
+ appStateSub?.remove();
486
+ appStateSub = null;
487
+ deepLinkSub?.remove();
488
+ deepLinkSub = null;
489
+ instance?.shutdown();
490
+ const iosMod = getIosNative();
491
+ const androidMod = getAndroidNative();
492
+ const storage = mmkv ? createMMKVStorage(mmkv) : createNativeStorage(iosMod ?? androidMod) ?? new import_sdk_core.MemoryStorage();
493
+ installFlagStore = storage;
494
+ secureStore = secureMod ? createSecureStore(secureMod) : createNativeSecureStore(iosMod);
495
+ const deviceId = rest.deviceId ?? await (0, import_sdk_core.resolveDurableDeviceId)(storage, secureStore ?? void 0);
496
+ instance = new import_sdk_core.AdvenueClient({ ...rest, platform, deviceId, storage });
497
+ void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
498
+ const deviceInfo = collectDeviceInfo({
499
+ platform,
500
+ ios: getIosNative(),
501
+ android: getAndroidNative()
502
+ });
503
+ if (Object.keys(deviceInfo).length > 0) instance.setDeviceInfo(deviceInfo);
504
+ if (!config.disableAutoSessions) {
505
+ const appState = getAppState();
506
+ if (appState) {
507
+ appStateSub?.remove();
508
+ let seenBackground = false;
509
+ const handler = (status) => {
510
+ if (!instance) return;
511
+ if (status === "background") {
512
+ seenBackground = true;
513
+ applyAppState(instance, status);
514
+ } else if (status === "active") {
515
+ if (!seenBackground) return;
516
+ seenBackground = false;
517
+ applyAppState(instance, status);
518
+ void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
519
+ }
520
+ };
521
+ appStateSub = appState.addEventListener("change", handler);
522
+ instance.notifyAppActive();
523
+ } else {
524
+ instance.notifyAppActive();
525
+ }
526
+ }
527
+ if (onDeepLink) {
528
+ const linking = getLinking();
529
+ if (linking) {
530
+ const client = instance;
531
+ deepLinkSub = setupDeepLinks({
532
+ getInitialURL: () => linking.getInitialURL(),
533
+ addUrlListener: (handler) => linking.addEventListener("url", (e) => handler(e.url)),
534
+ // Deferred waterfall: clipboard (deterministic) first, then the
535
+ // server-side conversion poll (IDFA / probabilistic).
536
+ resolveDeferred: async () => await resolveClipboardMatch() ?? client.resolveDeferredDeepLink(),
537
+ onDeepLink
538
+ });
539
+ deepLinkSub.ready.catch((err) => reportError("deepLink.resolve", err));
540
+ }
541
+ }
542
+ if (autoTrackInstall !== false) {
543
+ if (instance.getRequireConsent() && !instance.getTrackingConsent()) {
544
+ autoInstallPending = true;
545
+ instance.debugLog("install deferred until consent is granted");
546
+ } else {
547
+ fireAutoInstall();
548
+ }
549
+ }
550
+ return instance;
551
+ },
552
+ track: (name, properties, opts) => active().track(name, properties, opts),
553
+ /**
554
+ * Shows the iOS ATT prompt (resolves 'authorized' immediately on Android/web,
555
+ * where ATT doesn't exist) and forwards the result to the consent gate.
556
+ */
557
+ async requestTrackingAuthorization() {
558
+ const ios = getIosNative();
559
+ const status = ios ? await ios.requestTrackingAuthorization() : "authorized";
560
+ active().setTrackingConsent(status === "authorized");
561
+ void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
562
+ if (status === "authorized") {
563
+ fireAutoInstallIfPending();
564
+ }
565
+ return status;
566
+ },
567
+ setTrackingConsent(granted) {
568
+ active().setTrackingConsent(granted);
569
+ if (granted) {
570
+ fireAutoInstallIfPending();
571
+ }
572
+ },
573
+ getTrackingConsent: () => active().getTrackingConsent(),
574
+ /** GDPR/CCPA erasure: stop tracking and wipe local identifiers/queue. */
575
+ forgetMe() {
576
+ active().forgetMe();
577
+ try {
578
+ installFlagStore?.removeItem(INSTALL_SENT_KEY);
579
+ } catch (err) {
580
+ reportError("forget.wipe", err);
581
+ }
582
+ const secure = secureStore;
583
+ if (secure?.deleteItemAsync) {
584
+ for (const key of [import_sdk_core.DEVICE_ID_KEY, INSTALL_SENT_KEY]) {
585
+ void secure.deleteItemAsync(key).catch((err) => reportError("forget.secureWipe", err));
586
+ }
587
+ }
588
+ },
589
+ setConsentData(consent) {
590
+ active().setConsentData(consent);
591
+ void resolveAdvertisingId().catch((err) => reportError("enrich.advertisingId", err));
592
+ },
593
+ getConsentData: () => active().getConsentData(),
594
+ flush: () => active().flush(),
595
+ getDeviceId: () => active().getDeviceId(),
596
+ shutdown() {
597
+ appStateSub?.remove();
598
+ appStateSub = null;
599
+ deepLinkSub?.remove();
600
+ deepLinkSub = null;
601
+ instance?.shutdown();
602
+ instance = null;
603
+ secureStore = null;
604
+ installInFlight = false;
605
+ autoInstallPending = false;
606
+ autoInstallEnabled = true;
607
+ configuredAppId = null;
608
+ configuredApiKey = null;
609
+ configuredEndpoint = import_sdk_core.DEFAULT_ENDPOINT;
610
+ }
611
+ };
612
+ async function trackInstall() {
613
+ const client = active();
614
+ if (client.getRequireConsent() && !client.getTrackingConsent()) {
615
+ return;
616
+ }
617
+ let sent = installFlagStore?.getItem(INSTALL_SENT_KEY) === "1";
618
+ if (!sent && secureStore) {
619
+ try {
620
+ sent = await secureStore.getItemAsync(INSTALL_SENT_KEY) === "1";
621
+ } catch (err) {
622
+ reportError("install.guardRead", err);
623
+ }
624
+ }
625
+ if (sent) {
626
+ client.debugLog("install skipped (already sent on this device)");
627
+ return;
628
+ }
629
+ if (installInFlight) {
630
+ return;
631
+ }
632
+ installInFlight = true;
633
+ const opts = {};
634
+ const props = {};
635
+ const android = getAndroidNative();
636
+ if (android) {
637
+ try {
638
+ const result = await android.getInstallReferrer();
639
+ if (result) {
640
+ const parsed = (0, import_install_referrer.parseInstallReferrer)(result.referrer);
641
+ if (parsed.network) opts.network = parsed.network;
642
+ if (parsed.campaign) opts.campaign = parsed.campaign;
643
+ if (parsed.gclid) props.gclid = parsed.gclid;
644
+ if (parsed.fbclid) props.fbclid = parsed.fbclid;
645
+ Object.assign(props, (0, import_install_referrer.extractReferrerProperties)(result));
646
+ }
647
+ } catch (err) {
648
+ reportError("enrich.installReferrer", err);
649
+ }
650
+ try {
651
+ const meta = await android.getMetaInstallReferrer();
652
+ const parsedMeta = meta ? (0, import_install_referrer.parseMetaInstallReferrer)(meta) : null;
653
+ if (parsedMeta) {
654
+ props.metaInstallReferrer = parsedMeta.raw;
655
+ if (parsedMeta.encryptedData) props.metaReferrerData = parsedMeta.encryptedData;
656
+ if (parsedMeta.nonce) props.metaReferrerNonce = parsedMeta.nonce;
657
+ if (!opts.network && parsedMeta.isClickThrough) {
658
+ opts.network = "meta";
659
+ if (parsedMeta.campaign) opts.campaign = parsedMeta.campaign;
660
+ }
661
+ }
662
+ } catch (err) {
663
+ reportError("enrich.metaReferrer", err);
664
+ }
665
+ }
666
+ const ios = getIosNative();
667
+ if (ios) {
668
+ try {
669
+ ios.registerAppForAttribution();
670
+ } catch (err) {
671
+ reportError("enrich.skanRegister", err);
672
+ }
673
+ try {
674
+ const asaToken = await ios.getAttributionToken();
675
+ if (asaToken) {
676
+ opts.adservicesToken = asaToken;
677
+ }
678
+ } catch (err) {
679
+ reportError("enrich.adservicesToken", err);
680
+ }
681
+ }
682
+ await resolveAdvertisingId();
683
+ const trackOpts = { type: "install", ...opts };
684
+ if (configuredAppId && android && typeof android.getIntegrityToken === "function") {
685
+ try {
686
+ const deviceId = client.getDeviceId();
687
+ const requestHash = sha256Hex(`${configuredAppId}:${deviceId}`);
688
+ const token = await android.getIntegrityToken(requestHash);
689
+ if (token) {
690
+ trackOpts.attestationToken = token;
691
+ trackOpts.attestationType = "play-integrity";
692
+ }
693
+ } catch (err) {
694
+ reportError("attest.playIntegrity", err);
695
+ }
696
+ }
697
+ if (configuredAppId && configuredApiKey && ios && typeof ios.attestKey === "function") {
698
+ try {
699
+ const deviceId = client.getDeviceId();
700
+ const challengeUrl = `${configuredEndpoint}/v1/attest/challenge?deviceId=${encodeURIComponent(deviceId)}`;
701
+ const challengeRes = await fetch(challengeUrl, {
702
+ headers: { "x-api-key": configuredApiKey }
703
+ });
704
+ if (!challengeRes.ok) throw new Error(`challenge HTTP ${challengeRes.status}`);
705
+ const { challenge } = await challengeRes.json();
706
+ const { keyId, attestationObject } = await ios.attestKey(challenge);
707
+ trackOpts.attestationToken = attestationObject;
708
+ trackOpts.attestationType = "app-attest";
709
+ trackOpts.attestationKeyId = keyId;
710
+ trackOpts.attestationChallenge = challenge;
711
+ } catch (err) {
712
+ reportError("attest.appAttest", err);
713
+ }
714
+ }
715
+ if (ios && typeof ios.getDeviceCheckToken === "function") {
716
+ try {
717
+ const token = await ios.getDeviceCheckToken();
718
+ if (token) {
719
+ trackOpts.deviceCheckToken = token;
720
+ }
721
+ } catch (err) {
722
+ reportError("attest.deviceCheck", err);
723
+ }
724
+ }
725
+ const pendingBefore = client.pendingCount;
726
+ client.track("install", props, trackOpts);
727
+ if (client.pendingCount === pendingBefore) {
728
+ installInFlight = false;
729
+ client.debugLog("install dropped (consent revoked mid-flight)");
730
+ if (autoInstallEnabled && client.getRequireConsent() && !client.getTrackingConsent()) {
731
+ autoInstallPending = true;
732
+ }
733
+ return;
734
+ }
735
+ client.debugLog("install fired");
736
+ try {
737
+ installFlagStore?.setItem(INSTALL_SENT_KEY, "1");
738
+ } catch (err) {
739
+ reportError("install.flagPersist", err);
740
+ }
741
+ if (secureStore) {
742
+ try {
743
+ await secureStore.setItemAsync(INSTALL_SENT_KEY, "1");
744
+ } catch (err) {
745
+ reportError("install.flagPersistSecure", err);
746
+ }
747
+ }
748
+ }
749
+ // Annotate the CommonJS export names for ESM import in node:
750
+ 0 && (module.exports = {
751
+ Advenue,
752
+ applyAppState,
753
+ collectDeviceInfo,
754
+ createMMKVStorage,
755
+ createSecureStore,
756
+ getAndroidNative,
757
+ getIosNative,
758
+ parseDirectLink,
759
+ resolveAdvertisingId,
760
+ resolveClipboardMatch,
761
+ trackInstall
762
+ });