Skip to content

Commit ce09f80

Browse files
Merge pull request #883 from Iterable/feature/SDK-521-tighten-turbomodule-bridge-type-safety
feat(SDK-521): tighten TurboModule bridge type safety
2 parents f713bf3 + 0d43856 commit ce09f80

2 files changed

Lines changed: 45 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
- Android accepts an FCM token string.
1414
- iOS accepts a continuous hex string representation of the APNS token.
1515

16+
### Internal
17+
18+
- Tightened TurboModule spec type safety in `NativeRNIterableAPI.ts` (SDK-521, Phase 1).
19+
- Replaced `{ [key: string]: string | number | boolean }` dictionaries on the fixed-shape bridge methods (`updateCart`, `trackPurchase`, `setAttributionInfo`, `getAttributionInfo`, `startSession`, `updateVisibleRows`) with inline interfaces (`CommerceItemSpec`, `AttributionInfoSpec`, `InboxImpressionRowSpec`).
20+
- No runtime behavior change; native layers read by string key as before. Public facade signatures (`IterableCommerceItem`, `IterableAttributionInfo`, `IterableInboxImpressionRowInfo`) are unchanged and remain structurally compatible — no casts required.
21+
1622
## 3.0.1
1723

1824
### Updates

src/api/NativeRNIterableAPI.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,39 @@ interface EmbeddedMessage {
3030
payload?: { [key: string]: string | number | boolean | null } | null;
3131
}
3232

33+
// Inbound fixed-shape structs. Keys are the source of truth and MUST stay in sync
34+
// with the native decoders that read by string key. See the native `Serialization`
35+
// files (iOS: ios/RNIterableAPI/Serialization.swift; Android:
36+
// android/.../Serialization.java) for the authoritative key list per struct:
37+
// - CommerceItemSpec ↔ CommerceItem
38+
// - InboxImpressionRowSpec ↔ InboxImpressionTracker.RowInfo
39+
// `dataFields` is `unknown` (not a typed dict): IterableCommerceItem.dataFields is
40+
// typed `unknown` and is an open consumer-supplied data bag. Codegen accepts
41+
// `unknown` (maps to GenericObjectTypeAnnotation, same as `Object`).
42+
interface CommerceItemSpec {
43+
id: string;
44+
name: string;
45+
price: number;
46+
quantity: number;
47+
sku?: string | null;
48+
description?: string | null;
49+
url?: string | null;
50+
imageUrl?: string | null;
51+
categories?: Array<string> | null;
52+
dataFields?: unknown;
53+
}
54+
55+
interface AttributionInfoSpec {
56+
campaignId: number;
57+
templateId: number;
58+
messageId: string;
59+
}
60+
61+
interface InboxImpressionRowSpec {
62+
messageId: string;
63+
silentInbox: boolean;
64+
}
65+
3366
export interface Spec extends TurboModule {
3467
// Initialization
3568
initializeWithApiKey(
@@ -94,12 +127,10 @@ export interface Spec extends TurboModule {
94127
inAppConsume(messageId: string, location: number, source: number): void;
95128

96129
// Commerce
97-
updateCart(
98-
items: Array<{ [key: string]: string | number | boolean }>
99-
): void;
130+
updateCart(items: Array<CommerceItemSpec>): void;
100131
trackPurchase(
101132
total: number,
102-
items: Array<{ [key: string]: string | number | boolean }>,
133+
items: Array<CommerceItemSpec>,
103134
dataFields?: { [key: string]: string | number | boolean }
104135
): void;
105136

@@ -111,12 +142,8 @@ export interface Spec extends TurboModule {
111142
updateEmail(email: string, authToken?: string): void;
112143

113144
// Attribution
114-
getAttributionInfo(): Promise<{
115-
[key: string]: string | number | boolean;
116-
} | null>;
117-
setAttributionInfo(
118-
dict: { [key: string]: string | number | boolean } | null
119-
): void;
145+
getAttributionInfo(): Promise<AttributionInfoSpec | null>;
146+
setAttributionInfo(dict: AttributionInfoSpec | null): void;
120147

121148
// Device management
122149
disableDeviceForCurrentUser(): void;
@@ -144,12 +171,10 @@ export interface Spec extends TurboModule {
144171
): void;
145172

146173
// Session tracking
147-
startSession(
148-
visibleRows: Array<{ [key: string]: string | number | boolean }>
149-
): void;
174+
startSession(visibleRows: Array<InboxImpressionRowSpec>): void;
150175
endSession(): void;
151176
updateVisibleRows(
152-
visibleRows: Array<{ [key: string]: string | number | boolean }>
177+
visibleRows: Array<InboxImpressionRowSpec>
153178
): void;
154179

155180
// Auth

0 commit comments

Comments
 (0)