Skip to content

Commit 1e67f85

Browse files
committed
feat: add ArchitectureDetector for detecting architecture features and capabilities
1 parent 12097a9 commit 1e67f85

2 files changed

Lines changed: 339 additions & 53 deletions

File tree

src/core/ArchitectureDetector.ts

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import { NativeModules, Platform } from 'react-native';
2+
3+
export enum ArchitectureFeature {
4+
IN_APP_MESSAGES = 'inAppMessages',
5+
INBOX_MESSAGES = 'inboxMessages',
6+
PUSH_NOTIFICATIONS = 'pushNotifications',
7+
DEEP_LINKING = 'deepLinking',
8+
COMMERCE_TRACKING = 'commerceTracking',
9+
ATTRIBUTION = 'attribution',
10+
USER_MANAGEMENT = 'userManagement',
11+
EVENT_TRACKING = 'eventTracking',
12+
}
13+
14+
export class ArchitectureDetector {
15+
private static instance: ArchitectureDetector;
16+
private isNewArchitecture: boolean | null = null;
17+
private isTurboModuleAvailable: boolean | null = null;
18+
private isFabricAvailable: boolean | null = null;
19+
private availableFeatures: Set<ArchitectureFeature> = new Set();
20+
21+
private constructor() {
22+
this.detectAvailableFeatures();
23+
}
24+
25+
static getInstance(): ArchitectureDetector {
26+
if (!ArchitectureDetector.instance) {
27+
ArchitectureDetector.instance = new ArchitectureDetector();
28+
}
29+
return ArchitectureDetector.instance;
30+
}
31+
32+
/**
33+
* Check if the app is running with the new architecture
34+
*/
35+
isNewArchitectureEnabled(): boolean {
36+
if (this.isNewArchitecture === null) {
37+
this.isNewArchitecture = this.detectNewArchitecture();
38+
}
39+
return this.isNewArchitecture;
40+
}
41+
42+
/**
43+
* Check if TurboModules are available (Android)
44+
*/
45+
isTurboModuleEnabled(): boolean {
46+
if (this.isTurboModuleAvailable === null) {
47+
this.isTurboModuleAvailable = this.detectTurboModule();
48+
}
49+
return this.isTurboModuleAvailable;
50+
}
51+
52+
/**
53+
* Check if Fabric is available (iOS)
54+
*/
55+
isFabricEnabled(): boolean {
56+
if (this.isFabricAvailable === null) {
57+
this.isFabricAvailable = this.detectFabric();
58+
}
59+
return this.isFabricAvailable;
60+
}
61+
62+
/**
63+
* Get the current architecture name
64+
*/
65+
getArchitectureName(): string {
66+
if (Platform.OS === 'ios') {
67+
return this.isFabricEnabled() ? 'Fabric' : 'Paper';
68+
} else {
69+
return this.isTurboModuleEnabled() ? 'TurboModule' : 'Paper';
70+
}
71+
}
72+
73+
/**
74+
* Check if a specific feature is available
75+
* @param feature - Feature to check
76+
*/
77+
isFeatureAvailable(feature: ArchitectureFeature): boolean {
78+
return this.availableFeatures.has(feature);
79+
}
80+
81+
/**
82+
* Get all available features
83+
*/
84+
getAvailableFeatures(): ArchitectureFeature[] {
85+
return Array.from(this.availableFeatures);
86+
}
87+
88+
/**
89+
* Get features that are only available in the new architecture
90+
*/
91+
getNewArchitectureFeatures(): ArchitectureFeature[] {
92+
if (!this.isNewArchitectureEnabled()) {
93+
return [];
94+
}
95+
96+
return this.getAvailableFeatures().filter((feature) => {
97+
// Features that are only available in the new architecture
98+
const newArchOnlyFeatures = [
99+
ArchitectureFeature.IN_APP_MESSAGES,
100+
ArchitectureFeature.INBOX_MESSAGES,
101+
ArchitectureFeature.COMMERCE_TRACKING,
102+
];
103+
return newArchOnlyFeatures.includes(feature);
104+
});
105+
}
106+
107+
private detectNewArchitecture(): boolean {
108+
if (Platform.OS === 'ios') {
109+
return this.detectFabric();
110+
} else {
111+
return this.detectTurboModule();
112+
}
113+
}
114+
115+
private detectTurboModule(): boolean {
116+
try {
117+
const { RNIterableAPI } = NativeModules;
118+
const hasTurboModule =
119+
RNIterableAPI &&
120+
typeof RNIterableAPI === 'object' &&
121+
'getConstants' in RNIterableAPI;
122+
123+
if (hasTurboModule) {
124+
console.log('TurboModule architecture detected');
125+
}
126+
return hasTurboModule;
127+
} catch (error) {
128+
console.warn('Error detecting TurboModule:', error);
129+
return false;
130+
}
131+
}
132+
133+
private detectFabric(): boolean {
134+
try {
135+
const { RNIterableAPI } = NativeModules;
136+
const hasFabric =
137+
RNIterableAPI &&
138+
typeof RNIterableAPI === 'object' &&
139+
'getConstants' in RNIterableAPI;
140+
141+
if (hasFabric) {
142+
console.log('Fabric architecture detected');
143+
}
144+
return hasFabric;
145+
} catch (error) {
146+
console.warn('Error detecting Fabric:', error);
147+
return false;
148+
}
149+
}
150+
151+
private detectAvailableFeatures(): void {
152+
const { RNIterableAPI } = NativeModules;
153+
if (!RNIterableAPI) {
154+
console.warn('RNIterableAPI module not found');
155+
return;
156+
}
157+
158+
// Basic features available in both architectures
159+
this.availableFeatures.add(ArchitectureFeature.USER_MANAGEMENT);
160+
this.availableFeatures.add(ArchitectureFeature.EVENT_TRACKING);
161+
162+
// Check for new architecture features
163+
if (this.isNewArchitectureEnabled()) {
164+
// Features available in new architecture
165+
this.availableFeatures.add(ArchitectureFeature.IN_APP_MESSAGES);
166+
this.availableFeatures.add(ArchitectureFeature.INBOX_MESSAGES);
167+
this.availableFeatures.add(ArchitectureFeature.COMMERCE_TRACKING);
168+
this.availableFeatures.add(ArchitectureFeature.ATTRIBUTION);
169+
170+
// Platform-specific features
171+
if (Platform.OS === 'ios') {
172+
this.availableFeatures.add(ArchitectureFeature.PUSH_NOTIFICATIONS);
173+
this.availableFeatures.add(ArchitectureFeature.DEEP_LINKING);
174+
}
175+
}
176+
177+
console.log('Available features:', Array.from(this.availableFeatures));
178+
}
179+
}
180+
181+
export const ArchitectureDetectorInstance = ArchitectureDetector.getInstance();

0 commit comments

Comments
 (0)