Skip to content

Commit 1731f83

Browse files
authored
Merge pull request #685 from Iterable/new-arch/MOB-11826-make-frontend-api-and-codegen
[MOB-11826] make-frontend-api-and-codegen
2 parents bf71a3d + fd99e15 commit 1731f83

File tree

10 files changed

+184
-45
lines changed

10 files changed

+184
-45
lines changed

example/src/components/Login/Login.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const Login = ({ navigation }: RootStackScreenProps<Route.Login>) => {
4444
<TextInput
4545
style={styles.input}
4646
onChangeText={setUserId}
47-
value={userId}
47+
value={userId ?? ''}
4848
placeholder="eg: my.name@gmail.com or 1234567890"
4949
autoCapitalize="none"
5050
autoCorrect={false}

example/src/hooks/useIterableApp.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ interface IterableAppProps {
6060
/** Sets the user ID for the user */
6161
setUserId: (value: string) => void;
6262
/** The user ID for the user */
63-
userId?: string;
63+
userId?: string | null;
6464
}
6565

6666
const IterableAppContext = createContext<IterableAppProps>({
@@ -79,7 +79,7 @@ const IterableAppContext = createContext<IterableAppProps>({
7979
setLoginInProgress: () => undefined,
8080
setReturnToInboxTrigger: () => undefined,
8181
setUserId: () => undefined,
82-
userId: undefined,
82+
userId: null,
8383
});
8484

8585
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
@@ -96,7 +96,7 @@ export const IterableAppProvider: FunctionComponent<
9696
const [apiKey, setApiKey] = useState<string | undefined>(
9797
process.env.ITBL_API_KEY
9898
);
99-
const [userId, setUserId] = useState<string | undefined>(process.env.ITBL_ID);
99+
const [userId, setUserId] = useState<string | null>(process.env.ITBL_ID ?? null);
100100
const [loginInProgress, setLoginInProgress] = useState<boolean>(false);
101101

102102
const getUserId = useCallback(() => userId ?? process.env.ITBL_ID, [userId]);
@@ -196,8 +196,8 @@ export const IterableAppProvider: FunctionComponent<
196196
);
197197

198198
const logout = useCallback(() => {
199-
Iterable.setEmail(undefined);
200-
Iterable.setUserId(undefined);
199+
Iterable.setEmail(null);
200+
Iterable.setUserId(null);
201201
setIsLoggedIn(false);
202202
}, []);
203203

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@
177177
]
178178
},
179179
"codegenConfig": {
180-
"name": "RNIterableSpec",
180+
"name": "RNIterableAPISpec",
181181
"type": "modules",
182-
"jsSrcsDir": "src",
182+
"jsSrcsDir": "src/api/",
183183
"android": {
184184
"javaPackageName": "com.iterable.reactnative"
185185
}

src/api/NativeRNIterableAPI.ts

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import type { TurboModule } from 'react-native';
2+
import { TurboModuleRegistry } from 'react-native';
3+
4+
export interface Spec extends TurboModule {
5+
// Initialization
6+
initializeWithApiKey(
7+
apiKey: string,
8+
config: { [key: string]: string | number | boolean | undefined | string[] },
9+
version: string
10+
): Promise<boolean>;
11+
12+
initialize2WithApiKey(
13+
apiKey: string,
14+
config: { [key: string]: string | number | boolean | undefined | string[] },
15+
apiEndPointOverride: string,
16+
version: string
17+
): Promise<boolean>;
18+
19+
// User management
20+
setEmail(email: string | null, authToken?: string | null): void;
21+
getEmail(): Promise<string | null>;
22+
setUserId(userId?: string | null, authToken?: string | null): void;
23+
getUserId(): Promise<string | null | undefined>;
24+
25+
// In-app messaging
26+
setInAppShowResponse(number: number): void;
27+
getInAppMessages(): Promise<{ [key: string]: string | number | boolean }[]>;
28+
getInboxMessages(): Promise<{ [key: string]: string | number | boolean }[]>;
29+
getUnreadInboxMessagesCount(): Promise<number>;
30+
showMessage(messageId: string, consume: boolean): Promise<string | null>;
31+
removeMessage(messageId: string, location: number, source: number): void;
32+
setReadForMessage(messageId: string, read: boolean): void;
33+
setAutoDisplayPaused(autoDisplayPaused: boolean): void;
34+
35+
// Tracking
36+
trackEvent(
37+
name: string,
38+
dataFields?: { [key: string]: string | number | boolean }
39+
): void;
40+
trackPushOpenWithCampaignId(
41+
campaignId: number,
42+
templateId: number | null,
43+
messageId: string,
44+
appAlreadyRunning: boolean,
45+
dataFields?: { [key: string]: string | number | boolean }
46+
): void;
47+
trackInAppOpen(messageId: string, location: number): void;
48+
trackInAppClick(
49+
messageId: string,
50+
location: number,
51+
clickedUrl: string
52+
): void;
53+
trackInAppClose(
54+
messageId: string,
55+
location: number,
56+
source: number,
57+
clickedUrl?: string
58+
): void;
59+
inAppConsume(messageId: string, location: number, source: number): void;
60+
61+
// Commerce
62+
updateCart(items: { [key: string]: string | number | boolean }[]): void;
63+
trackPurchase(
64+
total: number,
65+
items: { [key: string]: string | number | boolean }[],
66+
dataFields?: { [key: string]: string | number | boolean }
67+
): void;
68+
69+
// User data
70+
updateUser(
71+
dataFields: { [key: string]: string | number | boolean },
72+
mergeNestedObjects: boolean
73+
): void;
74+
updateEmail(email: string, authToken?: string): void;
75+
76+
// Attribution
77+
getAttributionInfo(): Promise<{
78+
[key: string]: string | number | boolean;
79+
} | null>;
80+
setAttributionInfo(
81+
dict: { [key: string]: string | number | boolean } | null
82+
): void;
83+
84+
// Device management
85+
disableDeviceForCurrentUser(): void;
86+
getLastPushPayload(): Promise<{
87+
[key: string]: string | number | boolean;
88+
} | null>;
89+
90+
// Content
91+
getHtmlInAppContentForMessage(
92+
messageId: string
93+
): Promise<{ [key: string]: string | number | boolean }>;
94+
95+
// App links
96+
handleAppLink(appLink: string): Promise<boolean>;
97+
98+
// Subscriptions
99+
updateSubscriptions(
100+
emailListIds: number[] | null,
101+
unsubscribedChannelIds: number[] | null,
102+
unsubscribedMessageTypeIds: number[] | null,
103+
subscribedMessageTypeIds: number[] | null,
104+
campaignId: number,
105+
templateId: number
106+
): void;
107+
108+
// Session tracking
109+
startSession(
110+
visibleRows: { [key: string]: string | number | boolean }[]
111+
): void;
112+
endSession(): void;
113+
updateVisibleRows(
114+
visibleRows: { [key: string]: string | number | boolean }[]
115+
): void;
116+
117+
// Auth
118+
passAlongAuthToken(authToken?: string | null): void;
119+
120+
// Wake app -- android only
121+
wakeApp(): void;
122+
123+
124+
// REQUIRED for RCTEventEmitter
125+
addListener(eventName: string): void;
126+
removeListeners(count: number): void;
127+
}
128+
129+
// Check if we're in a test environment
130+
const isTestEnvironment = () => {
131+
return (
132+
typeof jest !== 'undefined' ||
133+
process.env.NODE_ENV === 'test' ||
134+
process.env.JEST_WORKER_ID !== undefined
135+
);
136+
};
137+
138+
export default isTestEnvironment()
139+
? undefined
140+
: TurboModuleRegistry.getEnforcing<Spec>('RNIterableAPI');

src/api/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { NativeModules } from 'react-native';
2+
import BridgelessModule from './NativeRNIterableAPI';
3+
4+
export const RNIterableAPI = BridgelessModule ?? NativeModules.RNIterableAPI;
5+
6+
export default RNIterableAPI;

src/core/classes/Iterable.ts

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import {
22
Linking,
33
NativeEventEmitter,
4-
NativeModules,
54
Platform,
65
} from 'react-native';
76

87
import { buildInfo } from '../../itblBuildInfo';
98

9+
import { RNIterableAPI } from '../../api';
1010
// TODO: Organize these so that there are no circular dependencies
1111
// See https://github.com/expo/expo/issues/35100
1212
import { IterableInAppMessage } from '../../inApp/classes/IterableInAppMessage';
@@ -23,7 +23,6 @@ import type { IterableCommerceItem } from './IterableCommerceItem';
2323
import { IterableConfig } from './IterableConfig';
2424
import { IterableLogger } from './IterableLogger';
2525

26-
const RNIterableAPI = NativeModules.RNIterableAPI;
2726
const RNEventEmitter = new NativeEventEmitter(RNIterableAPI);
2827

2928
/* eslint-disable tsdoc/syntax */
@@ -181,7 +180,7 @@ export class Iterable {
181180
* Iterable.setEmail('my.user.name@gmail.com');
182181
* ```
183182
*/
184-
static setEmail(email?: string | null, authToken?: string | null) {
183+
static setEmail(email: string | null, authToken?: string | null) {
185184
Iterable?.logger?.log('setEmail: ' + email);
186185

187186
RNIterableAPI.setEmail(email, authToken);
@@ -197,7 +196,7 @@ export class Iterable {
197196
* });
198197
* ```
199198
*/
200-
static getEmail(): Promise<string | undefined> {
199+
static getEmail(): Promise<string | null> {
201200
Iterable?.logger?.log('getEmail');
202201

203202
return RNIterableAPI.getEmail();
@@ -262,7 +261,7 @@ export class Iterable {
262261
* });
263262
* ```
264263
*/
265-
static getUserId(): Promise<string | undefined> {
264+
static getUserId(): Promise<string | null | undefined> {
266265
Iterable?.logger?.log('getUserId');
267266

268267
return RNIterableAPI.getUserId();
@@ -325,12 +324,12 @@ export class Iterable {
325324
Iterable?.logger?.log('getAttributionInfo');
326325

327326
return RNIterableAPI.getAttributionInfo().then(
328-
(dict?: IterableAttributionInfo) => {
327+
(dict: { campaignId: number; templateId: number; messageId: string } | null) => {
329328
if (dict) {
330329
return new IterableAttributionInfo(
331-
dict.campaignId,
332-
dict.templateId,
333-
dict.messageId
330+
dict.campaignId as number,
331+
dict.templateId as number,
332+
dict.messageId as string
334333
);
335334
} else {
336335
return undefined;
@@ -366,7 +365,7 @@ export class Iterable {
366365
static setAttributionInfo(attributionInfo?: IterableAttributionInfo) {
367366
Iterable?.logger?.log('setAttributionInfo');
368367

369-
RNIterableAPI.setAttributionInfo(attributionInfo);
368+
RNIterableAPI.setAttributionInfo(attributionInfo as unknown as { [key: string]: string | number | boolean; } | null);
370369
}
371370

372371
/**
@@ -410,9 +409,9 @@ export class Iterable {
410409
RNIterableAPI.trackPushOpenWithCampaignId(
411410
campaignId,
412411
templateId,
413-
messageId,
412+
messageId as string,
414413
appAlreadyRunning,
415-
dataFields
414+
dataFields as { [key: string]: string | number | boolean } | undefined
416415
);
417416
}
418417

@@ -445,7 +444,7 @@ export class Iterable {
445444
static updateCart(items: IterableCommerceItem[]) {
446445
Iterable?.logger?.log('updateCart');
447446

448-
RNIterableAPI.updateCart(items);
447+
RNIterableAPI.updateCart(items as unknown as { [key: string]: string | number | boolean }[]);
449448
}
450449

451450
/**
@@ -497,7 +496,7 @@ export class Iterable {
497496
) {
498497
Iterable?.logger?.log('trackPurchase');
499498

500-
RNIterableAPI.trackPurchase(total, items, dataFields);
499+
RNIterableAPI.trackPurchase(total, items as unknown as { [key: string]: string | number | boolean }[], dataFields as { [key: string]: string | number | boolean } | undefined);
501500
}
502501

503502
/**
@@ -666,7 +665,7 @@ export class Iterable {
666665
static trackEvent(name: string, dataFields?: unknown) {
667666
Iterable?.logger?.log('trackEvent');
668667

669-
RNIterableAPI.trackEvent(name, dataFields);
668+
RNIterableAPI.trackEvent(name, dataFields as { [key: string]: string | number | boolean } | undefined);
670669
}
671670

672671
/**
@@ -714,7 +713,7 @@ export class Iterable {
714713
) {
715714
Iterable?.logger?.log('updateUser');
716715

717-
RNIterableAPI.updateUser(dataFields, mergeNestedObjects);
716+
RNIterableAPI.updateUser(dataFields as { [key: string]: string | number | boolean }, mergeNestedObjects);
718717
}
719718

720719
/**
@@ -859,10 +858,10 @@ export class Iterable {
859858
* ```
860859
*/
861860
static updateSubscriptions(
862-
emailListIds: number[] | undefined,
863-
unsubscribedChannelIds: number[] | undefined,
864-
unsubscribedMessageTypeIds: number[] | undefined,
865-
subscribedMessageTypeIds: number[] | undefined,
861+
emailListIds: number[] | null,
862+
unsubscribedChannelIds: number[] | null,
863+
unsubscribedMessageTypeIds: number[] | null,
864+
subscribedMessageTypeIds: number[] | null,
866865
campaignId: number,
867866
templateId: number
868867
) {

src/core/classes/IterableAuthResponse.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
export class IterableAuthResponse {
77
/** JWT Token */
8-
authToken?: string = '';
8+
authToken?: string | null = '';
99
/** Callback when the authentication to Iterable succeeds */
1010
successCallback?: () => void;
1111
/** Callback when the authentication to Iterable fails */

0 commit comments

Comments
 (0)