@onairos/react-native 3.0.70 → 3.0.72
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/lib/commonjs/components/Onairos.js +294 -155
- package/lib/commonjs/components/Onairos.js.map +1 -1
- package/lib/commonjs/components/OnairosButton.js +1 -1
- package/lib/commonjs/components/OnairosButton.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +6 -6
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/components/onboarding/OAuthWebView.js +188 -52
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/commonjs/index.js +66 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/services/apiKeyService.js +325 -0
- package/lib/commonjs/services/apiKeyService.js.map +1 -0
- package/lib/commonjs/services/platformAuthService.js +104 -113
- package/lib/commonjs/services/platformAuthService.js.map +1 -1
- package/lib/module/components/Onairos.js +297 -158
- package/lib/module/components/Onairos.js.map +1 -1
- package/lib/module/components/OnairosButton.js +1 -1
- package/lib/module/components/OnairosButton.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +6 -6
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/components/onboarding/OAuthWebView.js +188 -52
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/module/index.js +4 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/services/apiKeyService.js +310 -0
- package/lib/module/services/apiKeyService.js.map +1 -0
- package/lib/module/services/platformAuthService.js +104 -113
- package/lib/module/services/platformAuthService.js.map +1 -1
- package/lib/typescript/components/Onairos.d.ts +6 -5
- package/lib/typescript/components/Onairos.d.ts.map +1 -1
- package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +3 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/services/apiKeyService.d.ts +48 -0
- package/lib/typescript/services/apiKeyService.d.ts.map +1 -0
- package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +36 -3
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Onairos.tsx +336 -184
- package/src/components/OnairosButton.tsx +1 -1
- package/src/components/UniversalOnboarding.tsx +6 -6
- package/src/components/onboarding/OAuthWebView.tsx +236 -71
- package/src/index.ts +19 -0
- package/src/services/apiKeyService.ts +325 -0
- package/src/services/platformAuthService.ts +111 -130
- package/src/types.ts +40 -3
|
@@ -32,6 +32,8 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
32
32
|
}) => {
|
|
33
33
|
const [isLoading, setIsLoading] = useState(true);
|
|
34
34
|
const [error, setError] = useState<string | null>(null);
|
|
35
|
+
const [errorMessage, setErrorMessage] = useState<string>('');
|
|
36
|
+
const [isRetryable, setIsRetryable] = useState(true);
|
|
35
37
|
const [retryCount, setRetryCount] = useState(0);
|
|
36
38
|
const webViewRef = useRef<WebView>(null);
|
|
37
39
|
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -74,91 +76,140 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
74
76
|
};
|
|
75
77
|
}, []);
|
|
76
78
|
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
79
|
+
const onNavigationStateChange = (navState: any) => {
|
|
80
|
+
const currentUrl = navState.url;
|
|
81
|
+
console.log('🌐 Navigation state changed:', {
|
|
82
|
+
url: currentUrl,
|
|
83
|
+
canGoBack: navState.canGoBack,
|
|
84
|
+
canGoForward: navState.canGoForward,
|
|
85
|
+
loading: navState.loading,
|
|
86
|
+
title: navState.title,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Don't process if still loading
|
|
90
|
+
if (navState.loading) {
|
|
89
91
|
return;
|
|
90
92
|
}
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
|
|
94
|
+
// Check if this URL indicates OAuth completion
|
|
95
|
+
if (isOAuthComplete(currentUrl)) {
|
|
96
|
+
console.log('🎉 OAuth completion detected!');
|
|
97
|
+
|
|
98
|
+
// Extract the result
|
|
99
|
+
const result = extractOAuthResult(currentUrl);
|
|
100
|
+
|
|
101
|
+
if (result.success) {
|
|
102
|
+
console.log('✅ OAuth completed successfully:', result);
|
|
99
103
|
|
|
100
|
-
// Clear timeout
|
|
104
|
+
// Clear timeout
|
|
101
105
|
if (timeoutRef.current) {
|
|
102
106
|
clearTimeout(timeoutRef.current);
|
|
107
|
+
timeoutRef.current = null;
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
// Call success callback
|
|
111
|
+
if (onSuccess && result.code) {
|
|
112
|
+
onSuccess(result.code);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Close the WebView
|
|
116
|
+
if (onComplete) {
|
|
117
|
+
onComplete();
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
console.error('❌ OAuth failed:', result.error);
|
|
121
|
+
|
|
122
|
+
// Clear timeout
|
|
123
|
+
if (timeoutRef.current) {
|
|
124
|
+
clearTimeout(timeoutRef.current);
|
|
125
|
+
timeoutRef.current = null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Set error state
|
|
129
|
+
setError('OAuth authentication failed');
|
|
130
|
+
setErrorMessage(result.error || 'Authentication failed');
|
|
131
|
+
setIsRetryable(true);
|
|
114
132
|
}
|
|
115
133
|
}
|
|
116
134
|
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
// Only close when we get the final redirect from Onairos backend
|
|
128
|
-
if (isFinalOAuthRedirect) {
|
|
129
|
-
console.log(`Final OAuth redirect detected for ${platform} - user has completed login`);
|
|
135
|
+
// Additional check for Gmail specific patterns
|
|
136
|
+
if (platform === 'email' || platform === 'gmail') {
|
|
137
|
+
const gmailPatterns = [
|
|
138
|
+
'onairos.uk/Home',
|
|
139
|
+
'onairos.uk/home',
|
|
140
|
+
'https://onairos.uk/Home',
|
|
141
|
+
'https://onairos.uk/home',
|
|
142
|
+
];
|
|
130
143
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
for (const pattern of gmailPatterns) {
|
|
145
|
+
if (currentUrl.includes(pattern)) {
|
|
146
|
+
console.log('✅ Gmail OAuth success detected via home page redirect');
|
|
147
|
+
|
|
148
|
+
// Clear timeout
|
|
149
|
+
if (timeoutRef.current) {
|
|
150
|
+
clearTimeout(timeoutRef.current);
|
|
151
|
+
timeoutRef.current = null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Call success callback with Gmail-specific code
|
|
155
|
+
if (onSuccess) {
|
|
156
|
+
onSuccess('gmail_success');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Close the WebView
|
|
160
|
+
if (onComplete) {
|
|
161
|
+
onComplete();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
143
166
|
}
|
|
144
|
-
}, 1500);
|
|
145
|
-
return;
|
|
146
167
|
}
|
|
147
168
|
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
169
|
+
// Check for error URLs
|
|
170
|
+
const errorPatterns = [
|
|
171
|
+
'error=',
|
|
172
|
+
'error_description=',
|
|
173
|
+
'access_denied',
|
|
174
|
+
'user_cancelled',
|
|
175
|
+
'cancelled',
|
|
176
|
+
'denied',
|
|
177
|
+
];
|
|
154
178
|
|
|
155
|
-
|
|
156
|
-
|
|
179
|
+
for (const pattern of errorPatterns) {
|
|
180
|
+
if (currentUrl.includes(pattern)) {
|
|
181
|
+
console.log('❌ OAuth error detected in URL:', pattern);
|
|
182
|
+
|
|
183
|
+
// Clear timeout
|
|
184
|
+
if (timeoutRef.current) {
|
|
185
|
+
clearTimeout(timeoutRef.current);
|
|
186
|
+
timeoutRef.current = null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Parse error details
|
|
190
|
+
try {
|
|
191
|
+
const urlObj = new URL(currentUrl);
|
|
192
|
+
const params = new URLSearchParams(urlObj.search);
|
|
193
|
+
const errorDescription = params.get('error_description') || params.get('error') || 'Authentication failed';
|
|
194
|
+
|
|
195
|
+
setError('OAuth authentication failed');
|
|
196
|
+
setErrorMessage(errorDescription);
|
|
197
|
+
setIsRetryable(true);
|
|
198
|
+
} catch (parseError) {
|
|
199
|
+
setError('OAuth authentication failed');
|
|
200
|
+
setErrorMessage('Authentication failed');
|
|
201
|
+
setIsRetryable(true);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
157
207
|
};
|
|
158
208
|
|
|
159
209
|
const handleLoadEnd = () => {
|
|
160
210
|
setIsLoading(false);
|
|
161
211
|
setError(null);
|
|
212
|
+
setErrorMessage('');
|
|
162
213
|
};
|
|
163
214
|
|
|
164
215
|
const handleError = (syntheticEvent: any) => {
|
|
@@ -272,6 +323,8 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
272
323
|
const handleRetry = () => {
|
|
273
324
|
console.log('Manual retry requested');
|
|
274
325
|
setError(null);
|
|
326
|
+
setErrorMessage('');
|
|
327
|
+
setIsRetryable(true);
|
|
275
328
|
setIsLoading(true);
|
|
276
329
|
setRetryCount(0);
|
|
277
330
|
|
|
@@ -320,6 +373,116 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
320
373
|
}
|
|
321
374
|
};
|
|
322
375
|
|
|
376
|
+
// Check if URL indicates OAuth completion
|
|
377
|
+
const isOAuthComplete = (url: string): boolean => {
|
|
378
|
+
// Gmail OAuth completion patterns
|
|
379
|
+
const gmailSuccessPatterns = [
|
|
380
|
+
'https://onairos.uk/Home',
|
|
381
|
+
'https://onairos.uk/home',
|
|
382
|
+
'onairos.uk/Home',
|
|
383
|
+
'onairos.uk/home',
|
|
384
|
+
process.env.APP_HOME_URL,
|
|
385
|
+
].filter(Boolean);
|
|
386
|
+
|
|
387
|
+
// Check for success redirect patterns
|
|
388
|
+
for (const pattern of gmailSuccessPatterns) {
|
|
389
|
+
if (url.includes(pattern)) {
|
|
390
|
+
console.log('✅ OAuth success detected via redirect to:', pattern);
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Check for traditional OAuth callback patterns
|
|
396
|
+
const callbackPatterns = [
|
|
397
|
+
'code=',
|
|
398
|
+
'access_token=',
|
|
399
|
+
'oauth_token=',
|
|
400
|
+
'authorization_code=',
|
|
401
|
+
'auth_code=',
|
|
402
|
+
'token=',
|
|
403
|
+
'callback',
|
|
404
|
+
'success',
|
|
405
|
+
'complete',
|
|
406
|
+
'connected',
|
|
407
|
+
'authorized',
|
|
408
|
+
];
|
|
409
|
+
|
|
410
|
+
for (const pattern of callbackPatterns) {
|
|
411
|
+
if (url.includes(pattern)) {
|
|
412
|
+
console.log('✅ OAuth success detected via callback pattern:', pattern);
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Check for error patterns
|
|
418
|
+
const errorPatterns = [
|
|
419
|
+
'error=',
|
|
420
|
+
'error_description=',
|
|
421
|
+
'oauth_error=',
|
|
422
|
+
'auth_error=',
|
|
423
|
+
'access_denied',
|
|
424
|
+
'user_cancelled',
|
|
425
|
+
'cancelled',
|
|
426
|
+
'denied',
|
|
427
|
+
];
|
|
428
|
+
|
|
429
|
+
for (const pattern of errorPatterns) {
|
|
430
|
+
if (url.includes(pattern)) {
|
|
431
|
+
console.log('❌ OAuth error detected via pattern:', pattern);
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return false;
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// Extract OAuth result from URL
|
|
440
|
+
const extractOAuthResult = (url: string): { success: boolean; code?: string; error?: string } => {
|
|
441
|
+
try {
|
|
442
|
+
const urlObj = new URL(url);
|
|
443
|
+
const params = new URLSearchParams(urlObj.search);
|
|
444
|
+
|
|
445
|
+
// Check for error first
|
|
446
|
+
const error = params.get('error') || params.get('error_description') || params.get('oauth_error');
|
|
447
|
+
if (error) {
|
|
448
|
+
return { success: false, error };
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Check for success indicators
|
|
452
|
+
const code = params.get('code') || params.get('authorization_code') || params.get('auth_code');
|
|
453
|
+
const accessToken = params.get('access_token') || params.get('oauth_token') || params.get('token');
|
|
454
|
+
|
|
455
|
+
if (code || accessToken) {
|
|
456
|
+
return { success: true, code: code || accessToken };
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Check for success redirect to home page (Gmail pattern)
|
|
460
|
+
const gmailSuccessPatterns = [
|
|
461
|
+
'https://onairos.uk/Home',
|
|
462
|
+
'https://onairos.uk/home',
|
|
463
|
+
'onairos.uk/Home',
|
|
464
|
+
'onairos.uk/home',
|
|
465
|
+
];
|
|
466
|
+
|
|
467
|
+
for (const pattern of gmailSuccessPatterns) {
|
|
468
|
+
if (url.includes(pattern)) {
|
|
469
|
+
console.log('✅ Gmail OAuth success detected via home page redirect');
|
|
470
|
+
return { success: true, code: 'gmail_home_redirect' };
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// If we reached here and isOAuthComplete returned true, assume success
|
|
475
|
+
if (isOAuthComplete(url)) {
|
|
476
|
+
return { success: true, code: 'oauth_complete' };
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return { success: false, error: 'OAuth completion not detected' };
|
|
480
|
+
} catch (error) {
|
|
481
|
+
console.error('Error parsing OAuth URL:', error);
|
|
482
|
+
return { success: false, error: 'Invalid OAuth callback URL' };
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
|
|
323
486
|
if (error) {
|
|
324
487
|
return (
|
|
325
488
|
<SafeAreaView style={styles.container}>
|
|
@@ -340,7 +503,7 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
340
503
|
<View style={styles.errorContainer}>
|
|
341
504
|
<Icon name="error-outline" size={48} color="#FF6B6B" />
|
|
342
505
|
<Text style={styles.errorTitle}>Connection Error</Text>
|
|
343
|
-
<Text style={styles.errorMessage}>{error}</Text>
|
|
506
|
+
<Text style={styles.errorMessage}>{errorMessage || error}</Text>
|
|
344
507
|
|
|
345
508
|
{/* Help text based on error type */}
|
|
346
509
|
{error.includes('internet') || error.includes('network') ? (
|
|
@@ -375,10 +538,12 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
375
538
|
)}
|
|
376
539
|
|
|
377
540
|
<View style={styles.buttonContainer}>
|
|
378
|
-
|
|
379
|
-
<
|
|
380
|
-
|
|
381
|
-
|
|
541
|
+
{isRetryable && (
|
|
542
|
+
<TouchableOpacity style={styles.retryButton} onPress={handleRetry}>
|
|
543
|
+
<Icon name="refresh" size={20} color="#fff" style={styles.buttonIcon} />
|
|
544
|
+
<Text style={styles.retryButtonText}>Retry</Text>
|
|
545
|
+
</TouchableOpacity>
|
|
546
|
+
)}
|
|
382
547
|
<TouchableOpacity style={styles.browserButton} onPress={handleOpenInBrowser}>
|
|
383
548
|
<Icon name="open-in-browser" size={20} color="#666" style={styles.buttonIcon} />
|
|
384
549
|
<Text style={styles.browserButtonText}>Open in Browser</Text>
|
|
@@ -428,7 +593,7 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
428
593
|
<WebView
|
|
429
594
|
ref={webViewRef}
|
|
430
595
|
source={{ uri: url }}
|
|
431
|
-
onNavigationStateChange={
|
|
596
|
+
onNavigationStateChange={onNavigationStateChange}
|
|
432
597
|
onLoadEnd={handleLoadEnd}
|
|
433
598
|
onError={handleError}
|
|
434
599
|
onHttpError={(syntheticEvent) => {
|
package/src/index.ts
CHANGED
|
@@ -14,11 +14,17 @@ export type {
|
|
|
14
14
|
TrainingModalProps,
|
|
15
15
|
OAuthWebViewProps,
|
|
16
16
|
PlatformConfig,
|
|
17
|
+
PlatformAuthConfig,
|
|
17
18
|
ApiResponse,
|
|
18
19
|
CredentialsResult,
|
|
19
20
|
OverlayProps,
|
|
20
21
|
BiometricOptions,
|
|
21
22
|
PinRequirements,
|
|
23
|
+
OnairosConfig,
|
|
24
|
+
ApiKeyConfig,
|
|
25
|
+
ApiKeyValidationResult,
|
|
26
|
+
TestModeOptions,
|
|
27
|
+
DataRequest,
|
|
22
28
|
} from './types';
|
|
23
29
|
|
|
24
30
|
export type { EmailVerificationModalProps } from './components/EmailVerificationModal';
|
|
@@ -80,8 +86,21 @@ export {
|
|
|
80
86
|
verifyEmailCode,
|
|
81
87
|
checkEmailVerificationStatus,
|
|
82
88
|
disconnectPlatform,
|
|
89
|
+
initiateOAuth,
|
|
83
90
|
} from './services/platformAuthService';
|
|
84
91
|
|
|
92
|
+
// API Key Service - Initialize SDK with API key
|
|
93
|
+
export {
|
|
94
|
+
initializeApiKey,
|
|
95
|
+
validateApiKey,
|
|
96
|
+
getApiConfig,
|
|
97
|
+
getApiKey,
|
|
98
|
+
isApiKeyInitialized,
|
|
99
|
+
resetApiKeyService,
|
|
100
|
+
getAuthHeaders,
|
|
101
|
+
makeAuthenticatedRequest,
|
|
102
|
+
} from './services/apiKeyService';
|
|
103
|
+
|
|
85
104
|
// Export API and Services
|
|
86
105
|
export { onairosApi } from './api';
|
|
87
106
|
export { OAuthService } from './services/oauthService';
|