@attryio/react-native 0.1.7 → 0.1.9
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 +4 -0
- package/dist/index.js +72 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,6 +47,10 @@ The SDK starts with practical defaults:
|
|
|
47
47
|
- Requests Apple AdServices attribution tokens on iOS when the native module is available.
|
|
48
48
|
- Batches events and retries failed requests through the shared Attry SDK engine.
|
|
49
49
|
|
|
50
|
+
## React Native compatibility
|
|
51
|
+
|
|
52
|
+
The SDK avoids importing the root `react-native` namespace at runtime. Instead, it loads only the React Native APIs it needs, which prevents deprecated core export getters from being touched in newer React Native versions.
|
|
53
|
+
|
|
50
54
|
## Track custom events
|
|
51
55
|
|
|
52
56
|
Use `track` for app-specific actions. Event names should be stable `snake_case`; details belong in `properties`.
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Attry, ATTRY_EVENTS, MemoryStorage, parseAttryUrl } from "@attryio/sdk-core";
|
|
2
2
|
const SDK_NAME = "attry-react-native";
|
|
3
|
-
const SDK_VERSION = "0.1.
|
|
3
|
+
const SDK_VERSION = "0.1.9";
|
|
4
4
|
export { parseAttryUrl };
|
|
5
5
|
export async function createAttryReactNative(config) {
|
|
6
|
-
const rn =
|
|
6
|
+
const rn = loadReactNative();
|
|
7
7
|
const platform = rn?.Platform?.OS === "ios" || rn?.Platform?.OS === "android"
|
|
8
8
|
? rn.Platform.OS
|
|
9
9
|
: "unknown";
|
|
@@ -30,7 +30,7 @@ export async function createAttryReactNative(config) {
|
|
|
30
30
|
return client;
|
|
31
31
|
}
|
|
32
32
|
export async function collectReactNativeContext(rn, configuredContext = {}) {
|
|
33
|
-
const native = rn ??
|
|
33
|
+
const native = rn ?? loadReactNative();
|
|
34
34
|
const modules = native?.NativeModules;
|
|
35
35
|
const deviceInfo = modules?.RNDeviceInfo;
|
|
36
36
|
const expoConstants = modules?.ExpoConstants ?? modules?.ExponentConstants;
|
|
@@ -131,7 +131,7 @@ export async function collectReactNativeContext(rn, configuredContext = {}) {
|
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
export async function attachReactNativeLifecycleTracking(client, rn, storage = new MemoryStorage(), options) {
|
|
134
|
-
const native = rn ??
|
|
134
|
+
const native = rn ?? loadReactNative();
|
|
135
135
|
const installKey = `attry.${options.appId}.install_tracked`;
|
|
136
136
|
const sessionStartedAt = Date.now();
|
|
137
137
|
const sessionId = `ses_${sessionStartedAt.toString(36)}`;
|
|
@@ -210,7 +210,7 @@ export async function attachReactNativeLifecycleTracking(client, rn, storage = n
|
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
212
|
export async function attachDeepLinkTracking(client, rn) {
|
|
213
|
-
const native = rn ??
|
|
213
|
+
const native = rn ?? loadReactNative();
|
|
214
214
|
const initialUrl = await native?.Linking?.getInitialURL?.();
|
|
215
215
|
if (initialUrl) {
|
|
216
216
|
await trackDeepLinkOpen(client, initialUrl, "initial_url", native);
|
|
@@ -220,15 +220,15 @@ export async function attachDeepLinkTracking(client, rn) {
|
|
|
220
220
|
});
|
|
221
221
|
}
|
|
222
222
|
export async function collectInstallAttribution(client, rn) {
|
|
223
|
-
const native = rn ??
|
|
223
|
+
const native = rn ?? loadReactNative();
|
|
224
224
|
if (native?.Platform?.OS === "ios") {
|
|
225
225
|
const token = await native.NativeModules?.AttryAppleAds?.attributionToken?.();
|
|
226
226
|
if (token) {
|
|
227
227
|
const response = await client.submitAppleAdsToken(token);
|
|
228
228
|
await client.track("apple_ads_token_collected", {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
229
|
+
properties: {
|
|
230
|
+
exchangeStatus: response?.exchangeStatus ?? "unknown",
|
|
231
|
+
attributed: Boolean(response?.attribution)
|
|
232
232
|
}
|
|
233
233
|
});
|
|
234
234
|
}
|
|
@@ -252,7 +252,7 @@ export async function collectInstallAttribution(client, rn) {
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
async function trackDeepLinkOpen(client, url, openType, rn) {
|
|
255
|
-
const native = rn ??
|
|
255
|
+
const native = rn ?? loadReactNative();
|
|
256
256
|
const parsed = parseAttryUrl(url);
|
|
257
257
|
const openedFromUniversalLink = native?.Platform?.OS === "ios";
|
|
258
258
|
const openedFromAndroidAppLink = native?.Platform?.OS === "android";
|
|
@@ -385,14 +385,74 @@ function safeTimezone() {
|
|
|
385
385
|
return undefined;
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
|
-
|
|
388
|
+
function loadReactNative() {
|
|
389
|
+
// Avoid importing the root "react-native" namespace. In RN 0.81+, namespace
|
|
390
|
+
// imports can touch deprecated core export getters such as PushNotificationIOS.
|
|
391
|
+
const native = {
|
|
392
|
+
AppState: requireAppState(),
|
|
393
|
+
Dimensions: requireDimensions(),
|
|
394
|
+
I18nManager: requireI18nManager(),
|
|
395
|
+
Linking: requireLinking(),
|
|
396
|
+
NativeModules: requireNativeModules(),
|
|
397
|
+
Platform: requirePlatform()
|
|
398
|
+
};
|
|
399
|
+
return Object.values(native).some(Boolean) ? native : undefined;
|
|
400
|
+
}
|
|
401
|
+
function requireAppState() {
|
|
402
|
+
try {
|
|
403
|
+
return defaultExport(require("react-native/Libraries/AppState/AppState"));
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
return undefined;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function requireDimensions() {
|
|
389
410
|
try {
|
|
390
|
-
return (
|
|
411
|
+
return defaultExport(require("react-native/Libraries/Utilities/Dimensions"));
|
|
391
412
|
}
|
|
392
413
|
catch {
|
|
393
414
|
return undefined;
|
|
394
415
|
}
|
|
395
416
|
}
|
|
417
|
+
function requireI18nManager() {
|
|
418
|
+
try {
|
|
419
|
+
return defaultExport(require("react-native/Libraries/ReactNative/I18nManager"));
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
return undefined;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function requireLinking() {
|
|
426
|
+
try {
|
|
427
|
+
return defaultExport(require("react-native/Libraries/Linking/Linking"));
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
return undefined;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function requireNativeModules() {
|
|
434
|
+
try {
|
|
435
|
+
return defaultExport(require("react-native/Libraries/BatchedBridge/NativeModules"));
|
|
436
|
+
}
|
|
437
|
+
catch {
|
|
438
|
+
return undefined;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function requirePlatform() {
|
|
442
|
+
try {
|
|
443
|
+
return defaultExport(require("react-native/Libraries/Utilities/Platform"));
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
return undefined;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
function defaultExport(moduleValue) {
|
|
450
|
+
if (!moduleValue) {
|
|
451
|
+
return undefined;
|
|
452
|
+
}
|
|
453
|
+
const maybeDefault = moduleValue;
|
|
454
|
+
return maybeDefault.default ?? moduleValue;
|
|
455
|
+
}
|
|
396
456
|
async function createAsyncStorageAdapter() {
|
|
397
457
|
try {
|
|
398
458
|
const asyncStorageModule = (await import("@react-native-async-storage/async-storage"));
|
package/package.json
CHANGED