react-native-test-adx 0.1.3 → 0.1.4

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.
@@ -1,18 +1,16 @@
1
1
  "use strict";
2
2
 
3
3
  import { AdaxonClient } from "./core/AdaxonClient.js";
4
- import { MEDIATION_PROVIDER, OFFER_OPENED_EVENT } from "./config/ApiConstants.js";
4
+ import { MEDIATION_PROVIDER, OFFER_OPENED_EVENT, RECOMMENDATION_VIEW_EVENT } from "./config/ApiConstants.js";
5
+ import { dismissInterstitial, presentInterstitial } from "./components/InterstitialAd.js";
5
6
  import { AdaxonSdkError } from "./errors/AdaxonSdkError.js";
6
7
  import { detectReactNativePlatform, reactNativeAppInfoReader, reactNativeDeviceReader, reactNativeNetworkInfoReader, reactNativeNetworkStatusReader, reactNativeUrlOpener } from "./platform/reactNative.js";
7
8
  import { buildAddToCartProperties, buildPurchaseProperties, normalizeEventValues } from "./services/event/normalizeProperties.js";
8
9
  import { AdxEvent } from "./services/event/predefined.js";
9
10
  export class AdaxonSdk {
10
- static sharedInstance = new AdaxonSdk();
11
+ static shared = new AdaxonSdk();
11
12
  client = null;
12
13
  testMode = false;
13
- static get shared() {
14
- return AdaxonSdk.sharedInstance;
15
- }
16
14
  isInitialized() {
17
15
  return this.client !== null;
18
16
  }
@@ -70,58 +68,67 @@ export class AdaxonSdk {
70
68
  async trackCompleteRegistration(params = {}, options = {}) {
71
69
  return this.logEvent(AdxEvent.COMPLETE_REGISTRATION, params, options);
72
70
  }
73
- async loadRecommendations(eventName, properties = {}, listener) {
71
+ async showAd() {
74
72
  try {
75
- const response = await this.requireClient().getRecommendations({
76
- eventName,
77
- properties: {
78
- ...properties,
79
- mediation_provider: MEDIATION_PROVIDER,
80
- test_mode: this.testMode
81
- }
82
- });
83
- listener?.onRecommendationsLoaded(response.offers);
84
- return response.offers;
85
- } catch (error) {
86
- const message = AdaxonSdkError.messageOf(error, 'Failed to load recommendations.');
87
- const code = error instanceof AdaxonSdkError ? error.code : undefined;
88
- listener?.onRecommendationsFailedToLoad(message, code);
89
- throw error;
90
- }
91
- }
92
- async showOffer(offer, listener) {
93
- try {
94
- const client = this.requireClient();
95
- const targetUrl = offer.offer_url;
96
- const canOpen = await reactNativeUrlOpener.canOpenURL(targetUrl);
97
- if (!canOpen) {
98
- throw new AdaxonSdkError('VALIDATION_ERROR', `Cannot open offer URL: ${targetUrl}`);
73
+ const offers = await this.loadRecommendations(RECOMMENDATION_VIEW_EVENT);
74
+ const offer = offers[0];
75
+ if (!offer) {
76
+ console.warn('[Adaxon] No offer available.');
77
+ return;
78
+ }
79
+ if (!this.displayInterstitial(offer)) {
80
+ console.warn('[Adaxon] Interstitial host is not mounted. Wrap the app in AdaxonProvider.');
99
81
  }
100
- await reactNativeUrlOpener.openURL(targetUrl);
101
- await client.track(OFFER_OPENED_EVENT, {
102
- offer_id: offer.offer_id,
103
- offer_name: offer.offer_name,
104
- ad_type: offer.ad_type,
105
- mediation_provider: MEDIATION_PROVIDER
106
- });
107
- listener?.onOfferOpened(offer);
108
82
  } catch (error) {
109
- const message = AdaxonSdkError.messageOf(error, 'Failed to open offer.');
110
- listener?.onOfferFailedToOpen(offer, message);
111
- throw error;
83
+ console.warn('[Adaxon] Failed to show ad.', AdaxonSdkError.messageOf(error, 'Failed to show ad.'));
84
+ if (this.testMode) {
85
+ throw error;
86
+ }
112
87
  }
113
88
  }
114
- setExternalUserId(externalUserId) {
115
- this.requireClient().setExternalUserId(externalUserId);
116
- }
117
89
  isNetworkAvailable() {
118
90
  return this.client?.isNetworkAvailable() ?? false;
119
91
  }
120
92
  destroy() {
93
+ dismissInterstitial();
121
94
  this.client?.destroy();
122
95
  this.client = null;
123
96
  this.testMode = false;
124
97
  }
98
+ async loadRecommendations(eventName, properties = {}) {
99
+ const response = await this.requireClient().getRecommendations({
100
+ eventName,
101
+ properties: {
102
+ ...properties,
103
+ mediation_provider: MEDIATION_PROVIDER,
104
+ test_mode: this.testMode
105
+ }
106
+ });
107
+ return response.offers;
108
+ }
109
+ displayInterstitial(offer) {
110
+ return presentInterstitial({
111
+ offer,
112
+ interact: () => {
113
+ this.openOfferUrl(offer).then(dismissInterstitial).catch(error => {
114
+ console.warn('[Adaxon] Failed to open offer URL.', AdaxonSdkError.messageOf(error, 'Failed to open offer.'));
115
+ });
116
+ }
117
+ });
118
+ }
119
+ async openOfferUrl(offer) {
120
+ const client = this.requireClient();
121
+ if (!(await reactNativeUrlOpener.canOpenURL(offer.offer_url))) {
122
+ throw new AdaxonSdkError('VALIDATION_ERROR', `Cannot open offer URL: ${offer.offer_url}`);
123
+ }
124
+ await reactNativeUrlOpener.openURL(offer.offer_url);
125
+ await client.track(OFFER_OPENED_EVENT, {
126
+ offer_id: offer.offer_id,
127
+ offer_name: offer.offer_name,
128
+ ad_type: offer.ad_type,
129
+ mediation_provider: MEDIATION_PROVIDER
130
+ });
131
+ }
125
132
  requireClient() {
126
133
  if (!this.client) {
127
134
  throw new AdaxonSdkError('INVALID_CONFIG', 'Adaxon SDK is not initialized. Call Adaxon.initialize(...) first.');
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
 
3
3
  import { useEffect, useMemo, useRef, useState } from 'react';
4
+ import { StyleSheet, View } from "../platform/reactNative.js";
4
5
  import { AdaxonSdk } from "../AdaxonSdk.js";
5
6
  import { AdaxonSdkError } from "../errors/AdaxonSdkError.js";
6
7
  import { AdaxonContext } from "../state/AdaxonContext.js";
7
- import { jsx as _jsx } from "react/jsx-runtime";
8
+ import { InterstitialAd } from "./InterstitialAd.js";
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
10
  export function AdaxonProvider({
9
11
  configuration,
10
12
  listener,
@@ -44,6 +46,14 @@ export function AdaxonProvider({
44
46
  }), [initializationError, isInitialized, sdk]);
45
47
  return /*#__PURE__*/_jsx(AdaxonContext.Provider, {
46
48
  value: value,
47
- children: children
49
+ children: /*#__PURE__*/_jsxs(View, {
50
+ style: styles.root,
51
+ children: [children, /*#__PURE__*/_jsx(InterstitialAd, {})]
52
+ })
48
53
  });
49
- }
54
+ }
55
+ const styles = StyleSheet.create({
56
+ root: {
57
+ flex: 1
58
+ }
59
+ });
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+
3
+ import { useEffect, useState } from 'react';
4
+ import { BackHandler, Image, Platform, Pressable, SafeAreaView, StatusBar, StyleSheet, Text, View } from "../platform/reactNative.js";
5
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
6
+ const CLOSE_EDGE_INSET = 12;
7
+ const CLOSE_HIT_SIZE = 44;
8
+ let listener = null;
9
+ export function presentInterstitial(session) {
10
+ if (!listener) {
11
+ return false;
12
+ }
13
+ listener(session);
14
+ return true;
15
+ }
16
+ export function dismissInterstitial() {
17
+ listener?.(null);
18
+ }
19
+ const emptySafeAreaInsets = {
20
+ top: 0,
21
+ right: 0,
22
+ bottom: 0,
23
+ left: 0
24
+ };
25
+ function useEmptySafeAreaInsets() {
26
+ return emptySafeAreaInsets;
27
+ }
28
+ const useSafeAreaInsets = loadUseSafeAreaInsets() ?? useEmptySafeAreaInsets;
29
+ function loadUseSafeAreaInsets() {
30
+ try {
31
+ const module = require('react-native-safe-area-context');
32
+ return typeof module.useSafeAreaInsets === 'function' ? module.useSafeAreaInsets : undefined;
33
+ } catch {
34
+ return undefined;
35
+ }
36
+ }
37
+ function useTopInset() {
38
+ const safeArea = useSafeAreaInsets();
39
+ if (safeArea.top > 0) {
40
+ return safeArea.top;
41
+ }
42
+ if (Platform.OS === 'android') {
43
+ return StatusBar.currentHeight ?? 0;
44
+ }
45
+ return 0;
46
+ }
47
+ export function InterstitialAd() {
48
+ const [session, setSession] = useState(null);
49
+ const [closeTone, setCloseTone] = useState('onLightSurface');
50
+ const safeArea = useSafeAreaInsets();
51
+ const topInset = useTopInset();
52
+ const offerId = session?.offer.offer_id;
53
+ useEffect(() => {
54
+ listener = setSession;
55
+ return () => {
56
+ if (listener === setSession) {
57
+ listener = null;
58
+ }
59
+ };
60
+ }, []);
61
+ useEffect(() => {
62
+ setCloseTone('onLightSurface');
63
+ }, [offerId]);
64
+ useEffect(() => {
65
+ if (!session) {
66
+ return;
67
+ }
68
+ const onBackPress = () => {
69
+ dismissInterstitial();
70
+ return true;
71
+ };
72
+ const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);
73
+ return () => subscription.remove();
74
+ }, [session]);
75
+ if (!session) {
76
+ return null;
77
+ }
78
+ const {
79
+ offer,
80
+ interact
81
+ } = session;
82
+ const closeAppearance = closeButtonAppearance(closeTone);
83
+ const closeRightInset = Platform.OS === 'android' ? CLOSE_EDGE_INSET + safeArea.right : CLOSE_EDGE_INSET;
84
+ const adFrame = /*#__PURE__*/_jsx(_Fragment, {
85
+ children: /*#__PURE__*/_jsxs(View, {
86
+ style: styles.adContainer,
87
+ children: [/*#__PURE__*/_jsx(Pressable, {
88
+ accessibilityRole: "button",
89
+ accessibilityLabel: "Close ad",
90
+ onPress: dismissInterstitial,
91
+ style: [styles.closeButton, closeAppearance.button, {
92
+ top: CLOSE_EDGE_INSET,
93
+ right: closeRightInset
94
+ }],
95
+ testID: "adaxon-interstitial-close",
96
+ children: /*#__PURE__*/_jsx(Text, {
97
+ style: [styles.closeLabel, closeAppearance.label],
98
+ children: "\xD7"
99
+ })
100
+ }), /*#__PURE__*/_jsx(Pressable, {
101
+ accessibilityRole: "button",
102
+ accessibilityLabel: offer.offer_name,
103
+ onPress: interact,
104
+ style: styles.offer,
105
+ testID: "adaxon-interstitial-offer",
106
+ children: /*#__PURE__*/_jsx(OfferCreative, {
107
+ offer: offer,
108
+ onCloseToneChange: setCloseTone
109
+ })
110
+ })]
111
+ })
112
+ });
113
+ return /*#__PURE__*/_jsx(View, {
114
+ style: styles.overlay,
115
+ testID: "adaxon-interstitial",
116
+ children: Platform.OS === 'ios' ? /*#__PURE__*/_jsx(SafeAreaView, {
117
+ style: styles.safeFrame,
118
+ children: adFrame
119
+ }) : /*#__PURE__*/_jsx(View, {
120
+ style: [styles.safeFrame, {
121
+ paddingTop: topInset
122
+ }],
123
+ children: adFrame
124
+ })
125
+ });
126
+ }
127
+ function OfferCreative({
128
+ offer,
129
+ onCloseToneChange
130
+ }) {
131
+ const imageUrl = remoteImageUrl(offer.creative_url) ?? remoteImageUrl(offer.preview_url);
132
+ const [failed, setFailed] = useState(false);
133
+ useEffect(() => {
134
+ setFailed(false);
135
+ }, [imageUrl]);
136
+ useEffect(() => {
137
+ if (!imageUrl || failed) {
138
+ onCloseToneChange('onDarkSurface');
139
+ return;
140
+ }
141
+ onCloseToneChange('onLightSurface');
142
+ }, [failed, imageUrl, onCloseToneChange]);
143
+ if (!imageUrl || failed) {
144
+ return /*#__PURE__*/_jsx(View, {
145
+ style: styles.fallback,
146
+ testID: "adaxon-interstitial-fallback",
147
+ children: /*#__PURE__*/_jsx(Text, {
148
+ style: styles.offerName,
149
+ children: offer.offer_name
150
+ })
151
+ });
152
+ }
153
+ return /*#__PURE__*/_jsx(Image, {
154
+ source: {
155
+ uri: imageUrl
156
+ },
157
+ style: styles.creativeImage,
158
+ resizeMode: "contain",
159
+ onError: () => setFailed(true),
160
+ testID: "adaxon-interstitial-image"
161
+ });
162
+ }
163
+ function closeButtonAppearance(tone) {
164
+ if (tone === 'onDarkSurface') {
165
+ return {
166
+ button: {
167
+ backgroundColor: 'rgba(255, 255, 255, 0.94)',
168
+ borderColor: 'rgba(0, 0, 0, 0.35)'
169
+ },
170
+ label: {
171
+ color: '#111111',
172
+ textShadowColor: 'rgba(255, 255, 255, 0.85)',
173
+ textShadowRadius: 2
174
+ }
175
+ };
176
+ }
177
+ return {
178
+ button: {
179
+ backgroundColor: 'rgba(0, 0, 0, 0.62)',
180
+ borderColor: 'rgba(255, 255, 255, 0.55)'
181
+ },
182
+ label: {
183
+ color: '#ffffff',
184
+ textShadowColor: 'rgba(0, 0, 0, 0.75)',
185
+ textShadowRadius: 3
186
+ }
187
+ };
188
+ }
189
+ function remoteImageUrl(value) {
190
+ const trimmed = value?.trim();
191
+ if (!trimmed) {
192
+ return null;
193
+ }
194
+ try {
195
+ const url = new URL(trimmed);
196
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
197
+ return null;
198
+ }
199
+ return trimmed;
200
+ } catch {
201
+ return null;
202
+ }
203
+ }
204
+ const styles = StyleSheet.create({
205
+ overlay: {
206
+ position: 'absolute',
207
+ top: 0,
208
+ right: 0,
209
+ bottom: 0,
210
+ left: 0,
211
+ zIndex: 9999,
212
+ elevation: 9999,
213
+ backgroundColor: '#000000'
214
+ },
215
+ safeFrame: {
216
+ flex: 1,
217
+ width: '100%'
218
+ },
219
+ adContainer: {
220
+ flex: 1,
221
+ width: '100%',
222
+ position: 'relative'
223
+ },
224
+ closeButton: {
225
+ position: 'absolute',
226
+ zIndex: 2,
227
+ minWidth: CLOSE_HIT_SIZE,
228
+ minHeight: CLOSE_HIT_SIZE,
229
+ width: CLOSE_HIT_SIZE,
230
+ height: CLOSE_HIT_SIZE,
231
+ alignItems: 'center',
232
+ justifyContent: 'center',
233
+ borderRadius: CLOSE_HIT_SIZE / 2,
234
+ borderWidth: 1.5,
235
+ shadowColor: '#000000',
236
+ shadowOffset: {
237
+ width: 0,
238
+ height: 2
239
+ },
240
+ shadowOpacity: 0.45,
241
+ shadowRadius: 4,
242
+ elevation: 8
243
+ },
244
+ closeLabel: {
245
+ fontSize: 32,
246
+ lineHeight: 36,
247
+ textShadowOffset: {
248
+ width: 0,
249
+ height: 0
250
+ }
251
+ },
252
+ offer: {
253
+ flex: 1,
254
+ width: '100%',
255
+ alignSelf: 'stretch',
256
+ overflow: 'hidden'
257
+ },
258
+ creativeImage: {
259
+ position: 'absolute',
260
+ top: 0,
261
+ right: 0,
262
+ bottom: 0,
263
+ left: 0,
264
+ width: '100%',
265
+ height: '100%'
266
+ },
267
+ fallback: {
268
+ flex: 1,
269
+ width: '100%',
270
+ alignItems: 'center',
271
+ justifyContent: 'center',
272
+ paddingHorizontal: 24
273
+ },
274
+ offerName: {
275
+ color: '#ffffff',
276
+ fontSize: 22,
277
+ textAlign: 'center'
278
+ }
279
+ });
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
 
3
- export const SDK_VERSION = '0.1.3';
3
+ import packageJson from '../../package.json';
4
+ export const SDK_VERSION = packageJson.version;
4
5
  export const MEDIATION_PROVIDER = 'mts';
5
6
  export const BASE_URL = 'http://localhost:3002';
6
7
  export const EVENT_TRACKING_PATH = '/event/tracking';
7
8
  export const RECOMMENDATIONS_PATH = '/api/mts/recommendations';
8
9
  export const CLICK_TRACKING_PATH = '/click/tracking';
9
10
  export const OFFER_OPENED_EVENT = 'offer_opened';
11
+ export const RECOMMENDATION_VIEW_EVENT = 'recommendation_view';
10
12
  export const DEFAULT_TIMEOUT_MS = 10_000;
11
13
  export const PUBLIC_IP_LOOKUP_URL = 'https://api.ipify.org?format=json';
12
14
  export const PUBLIC_IP_LOOKUP_TIMEOUT_MS = 2_000;
@@ -29,8 +29,7 @@ export class AdaxonClient {
29
29
  deviceInfo: new DeviceInfoService(config.platform ?? 'web', config.deviceInfoReader, config.storage, auth.appId),
30
30
  appInfo: new AppInfoService(Boolean(config.testMode), config.appInfoReader),
31
31
  networkInfo,
32
- validator: this.validator,
33
- externalUserId: config.externalUserId
32
+ validator: this.validator
34
33
  });
35
34
  this.events = new EventService({
36
35
  api,
@@ -115,9 +114,6 @@ export class AdaxonClient {
115
114
  });
116
115
  return `${BASE_URL}${CLICK_TRACKING_PATH}?${query}`;
117
116
  }
118
- setExternalUserId(externalUserId) {
119
- this.builder.setExternalUserId(externalUserId);
120
- }
121
117
  toQueryString(params) {
122
118
  return Object.entries(params).filter(([, value]) => value !== undefined).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`).join('&');
123
119
  }
@@ -23,9 +23,7 @@ export function useAdaxon() {
23
23
  trackAddToCart: sdk.trackAddToCart.bind(sdk),
24
24
  trackLogin: sdk.trackLogin.bind(sdk),
25
25
  trackCompleteRegistration: sdk.trackCompleteRegistration.bind(sdk),
26
- loadRecommendations: sdk.loadRecommendations.bind(sdk),
27
- showOffer: sdk.showOffer.bind(sdk),
28
- setExternalUserId: sdk.setExternalUserId.bind(sdk)
26
+ showAd: sdk.showAd.bind(sdk)
29
27
  }), [sdk]);
30
28
  return {
31
29
  isInitialized,
@@ -1,12 +1,53 @@
1
1
  "use strict";
2
2
 
3
3
  import { nonEmptyString, setIfPresent } from "../utils/strings.js";
4
- export function appFieldsFromNative(constants) {
4
+ export function appFieldsFromNative(...sources) {
5
+ const value = key => lastPresent(sources, key);
6
+ const expo = expoConfig(value('expoConfig'), value('manifest'), value('extra'));
5
7
  const fields = {};
6
- setIfPresent(fields, 'package_name', firstNonEmpty(constants.applicationId, constants.bundleId, constants.androidPackage, constants.iosBundleIdentifier));
7
- setIfPresent(fields, 'app_version', firstNonEmpty(constants.nativeApplicationVersion, constants.appVersion, constants.nativeAppVersion));
8
+ setIfPresent(fields, 'package_name', firstNonEmpty(value('applicationId'), value('bundleId'), value('packageName'), value('androidPackage'), value('iosBundleIdentifier'), asRecord(value('android'))?.package, asRecord(value('ios'))?.bundleIdentifier, asRecord(expo?.android)?.package, asRecord(expo?.ios)?.bundleIdentifier));
9
+ setIfPresent(fields, 'app_version', firstNonEmpty(value('nativeApplicationVersion'), value('appVersion'), value('nativeAppVersion'), value('version'), expo?.version));
8
10
  return fields;
9
11
  }
12
+ function expoConfig(expoConfigValue, manifestValue, extraValue) {
13
+ const manifest = asRecord(manifestValue);
14
+ return firstRecord(expoConfigValue, asRecord(manifest?.extra)?.expoClient, manifest?.expoClient, manifest, asRecord(extraValue)?.expoClient);
15
+ }
16
+ function lastPresent(sources, key) {
17
+ let found;
18
+ for (const source of sources) {
19
+ if (!source) {
20
+ continue;
21
+ }
22
+ const next = source[key];
23
+ if (next != null && next !== '') {
24
+ found = next;
25
+ }
26
+ }
27
+ return found;
28
+ }
29
+ function firstRecord(...values) {
30
+ for (const value of values) {
31
+ const record = asRecord(value);
32
+ if (record) {
33
+ return record;
34
+ }
35
+ }
36
+ return undefined;
37
+ }
38
+ function asRecord(value) {
39
+ if (typeof value === 'string') {
40
+ try {
41
+ return asRecord(JSON.parse(value));
42
+ } catch {
43
+ return undefined;
44
+ }
45
+ }
46
+ if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
47
+ return value;
48
+ }
49
+ return undefined;
50
+ }
10
51
  function firstNonEmpty(...values) {
11
52
  for (const value of values) {
12
53
  const next = nonEmptyString(value);
@@ -1,14 +1,23 @@
1
1
  "use strict";
2
2
 
3
3
  import { Linking, NativeEventEmitter, NativeModules, Platform } from 'react-native';
4
+ export { BackHandler, Dimensions, Image, Modal, Platform, Pressable, SafeAreaView, StatusBar, StyleSheet, Text, View } from 'react-native';
4
5
  import { nonEmptyString, setIfPresent } from "../utils/strings.js";
5
6
  import { readLocaleFields } from "../utils/locale.js";
6
7
  import { appFieldsFromNative } from "./app.js";
7
8
  import { deviceFieldsFromAndroid } from "./android.js";
8
9
  import { deviceFieldsFromIos } from "./ios.js";
9
10
  import { connectionTypeFromNativeState, ipAddressFromNativeState, isOnlineFromNativeState, usableIpAddress } from "./network.js";
11
+ function expoNativeModule(name) {
12
+ try {
13
+ const expoGlobal = globalThis;
14
+ return expoGlobal.expo?.modules?.[name];
15
+ } catch {
16
+ return undefined;
17
+ }
18
+ }
10
19
  function nativeModule(name) {
11
- return (NativeModules ?? {})[name];
20
+ return (NativeModules ?? {})[name] ?? expoNativeModule(name);
12
21
  }
13
22
  async function callNative(method, arg) {
14
23
  if (typeof method !== 'function') {
@@ -53,13 +62,6 @@ async function readUniqueIdFromNative() {
53
62
  const deviceInfo = nativeModule('RNDeviceInfo');
54
63
  return nonEmptyString(await callNative(deviceInfo?.getUniqueId)) ?? '';
55
64
  }
56
- function readNativeAppConstants() {
57
- return {
58
- ...nativeModule('RNDeviceInfo'),
59
- ...nativeModule('ExponentConstants'),
60
- ...nativeModule('ExpoApplication')
61
- };
62
- }
63
65
  function nativeNetworkModules() {
64
66
  return {
65
67
  netInfo: nativeModule('RNCNetInfo'),
@@ -121,7 +123,7 @@ export const reactNativeDeviceReader = {
121
123
  getUniqueId: readUniqueIdFromNative
122
124
  };
123
125
  export const reactNativeAppInfoReader = {
124
- readAppInfo: () => appFieldsFromNative(readNativeAppConstants())
126
+ readAppInfo: () => appFieldsFromNative(nativeModule('RNDeviceInfo'), nativeModule('ExponentConstants'), nativeModule('ExpoApplication'))
125
127
  };
126
128
  export const reactNativeNetworkInfoReader = {
127
129
  readNetworkInfo: collectFromNativeNetwork
@@ -1,15 +1,10 @@
1
1
  "use strict";
2
2
 
3
3
  import { createUuid } from "../../utils/uuid.js";
4
- import { nonEmptyString, setIfPresent } from "../../utils/strings.js";
5
4
  export class EventBuilder {
6
5
  sessionId = createUuid();
7
6
  constructor(config) {
8
7
  this.config = config;
9
- this.externalUserId = config.externalUserId;
10
- }
11
- setExternalUserId(externalUserId) {
12
- this.externalUserId = externalUserId;
13
8
  }
14
9
  async build(input) {
15
10
  const {
@@ -23,7 +18,6 @@ export class EventBuilder {
23
18
  const user = {
24
19
  anonymous_id: await deviceInfo.getUniqueId()
25
20
  };
26
- setIfPresent(user, 'external_user_id', nonEmptyString(this.externalUserId));
27
21
  return {
28
22
  event_id: input.eventId ?? createUuid(),
29
23
  event_name: input.eventName,
@@ -19,11 +19,13 @@ export class EventService {
19
19
  }
20
20
  async getRecommendations(input) {
21
21
  const eventPayload = await this.builder.build(input);
22
- const payload = {
23
- ...eventPayload,
24
- event_type: 'recommendation'
25
- };
26
- const response = await this.api.post(RECOMMENDATIONS_PATH, payload);
22
+ await this.postEvents([eventPayload]);
23
+ const response = await this.api.post(RECOMMENDATIONS_PATH, {
24
+ app_id: eventPayload.app_id,
25
+ device: {
26
+ platform: eventPayload.device.platform
27
+ }
28
+ });
27
29
  if (!Array.isArray(response.offers)) {
28
30
  throw new AdaxonSdkError('HTTP_ERROR', 'Adaxon recommendation response is missing the offers array.');
29
31
  }
@@ -1,3 +1 @@
1
- "use strict";
2
-
3
- export {};
1
+ "use strict";
@@ -1,13 +1,12 @@
1
1
  import { type TrackAddToCartParams, type TrackCompleteRegistrationParams, type TrackLoginParams, type TrackPurchaseParams } from './services/event/normalizeProperties.js';
2
- import type { AdaxonInitializationConfiguration, AdaxonInitializationListener, AdaxonOfferShowListener, AdaxonRecommendationLoadListener } from './types/AdaxonConfig.js';
3
- import type { EventIngestionResponse, RecommendationOffer } from './types/ApiTypes.js';
2
+ import type { AdaxonInitializationConfiguration, AdaxonInitializationListener } from './types/AdaxonConfig.js';
3
+ import type { EventIngestionResponse } from './types/ApiTypes.js';
4
4
  import type { EventProperties, TrackEventInput, TrackEventOptions } from './types/EventTypes.js';
5
5
  import type { BatchProcessResult } from './types/QueuedEvent.js';
6
6
  export declare class AdaxonSdk {
7
- private static readonly sharedInstance;
7
+ static readonly shared: AdaxonSdk;
8
8
  private client;
9
9
  private testMode;
10
- static get shared(): AdaxonSdk;
11
10
  isInitialized(): boolean;
12
11
  initialize(configuration: AdaxonInitializationConfiguration, listener?: AdaxonInitializationListener): Promise<void>;
13
12
  track(eventName: string, properties?: EventProperties, options?: TrackEventOptions): Promise<EventIngestionResponse>;
@@ -19,11 +18,12 @@ export declare class AdaxonSdk {
19
18
  trackAddToCart(params: TrackAddToCartParams, options?: TrackEventOptions): Promise<EventIngestionResponse>;
20
19
  trackLogin(params?: TrackLoginParams, options?: TrackEventOptions): Promise<EventIngestionResponse>;
21
20
  trackCompleteRegistration(params?: TrackCompleteRegistrationParams, options?: TrackEventOptions): Promise<EventIngestionResponse>;
22
- loadRecommendations(eventName: string, properties?: EventProperties, listener?: AdaxonRecommendationLoadListener): Promise<RecommendationOffer[]>;
23
- showOffer(offer: RecommendationOffer, listener?: AdaxonOfferShowListener): Promise<void>;
24
- setExternalUserId(externalUserId?: string): void;
21
+ showAd(): Promise<void>;
25
22
  isNetworkAvailable(): boolean;
26
23
  destroy(): void;
24
+ private loadRecommendations;
25
+ private displayInterstitial;
26
+ private openOfferUrl;
27
27
  private requireClient;
28
28
  }
29
29
  //# sourceMappingURL=AdaxonSdk.d.ts.map