@onairos/react-native 3.0.71 → 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
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import type { OnairosConfig, ApiKeyValidationResult } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* API Key Service for Onairos React Native SDK
|
|
5
|
+
*
|
|
6
|
+
* This service handles API key validation, management, and authentication
|
|
7
|
+
* following standard SDK patterns for secure API key handling.
|
|
8
|
+
*
|
|
9
|
+
* How it works:
|
|
10
|
+
* 1. Initialize with API key and configuration
|
|
11
|
+
* 2. Validate API key with the Onairos backend
|
|
12
|
+
* 3. Cache validation results for performance
|
|
13
|
+
* 4. Include API key in all authenticated requests
|
|
14
|
+
* 5. Handle API key errors gracefully with developer-friendly messages
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// Global configuration state
|
|
18
|
+
let globalConfig: OnairosConfig | null = null;
|
|
19
|
+
let validationCache: Map<string, { result: ApiKeyValidationResult; timestamp: number }> = new Map();
|
|
20
|
+
let isInitialized = false;
|
|
21
|
+
|
|
22
|
+
// Cache duration (5 minutes)
|
|
23
|
+
const CACHE_DURATION = 5 * 60 * 1000;
|
|
24
|
+
|
|
25
|
+
// API endpoints for different environments
|
|
26
|
+
const API_ENDPOINTS = {
|
|
27
|
+
production: 'https://api2.onairos.uk',
|
|
28
|
+
staging: 'https://staging-api.onairos.uk',
|
|
29
|
+
development: 'https://dev-api.onairos.uk',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Initialize the SDK with API key and configuration
|
|
34
|
+
* @param config API configuration including API key
|
|
35
|
+
*/
|
|
36
|
+
export const initializeApiKey = async (config: OnairosConfig): Promise<void> => {
|
|
37
|
+
try {
|
|
38
|
+
console.log('🔑 Initializing Onairos SDK with API key...');
|
|
39
|
+
|
|
40
|
+
if (!config.apiKey) {
|
|
41
|
+
throw new Error('API key is required for SDK initialization');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (config.apiKey.length < 32) {
|
|
45
|
+
throw new Error('Invalid API key format. API key must be at least 32 characters long.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Set global configuration
|
|
49
|
+
globalConfig = {
|
|
50
|
+
apiKey: config.apiKey,
|
|
51
|
+
environment: config.environment || 'production',
|
|
52
|
+
enableLogging: config.enableLogging !== false, // Default to true
|
|
53
|
+
timeout: config.timeout || 30000,
|
|
54
|
+
retryAttempts: config.retryAttempts || 3,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
if (globalConfig.enableLogging) {
|
|
58
|
+
console.log('📝 SDK Configuration:', {
|
|
59
|
+
environment: globalConfig.environment,
|
|
60
|
+
timeout: globalConfig.timeout,
|
|
61
|
+
retryAttempts: globalConfig.retryAttempts,
|
|
62
|
+
apiKeyPrefix: config.apiKey.substring(0, 8) + '...',
|
|
63
|
+
enableLogging: globalConfig.enableLogging,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Validate the API key
|
|
68
|
+
const validation = await validateApiKey(config.apiKey);
|
|
69
|
+
|
|
70
|
+
if (!validation.isValid) {
|
|
71
|
+
throw new Error(`API key validation failed: ${validation.error}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
isInitialized = true;
|
|
75
|
+
|
|
76
|
+
if (globalConfig.enableLogging) {
|
|
77
|
+
console.log('✅ Onairos SDK initialized successfully');
|
|
78
|
+
if (validation.permissions) {
|
|
79
|
+
console.log('🔐 API Key Permissions:', validation.permissions);
|
|
80
|
+
}
|
|
81
|
+
if (validation.rateLimits) {
|
|
82
|
+
console.log('⏱️ Rate Limits:', validation.rateLimits);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error('❌ Failed to initialize Onairos SDK:', error);
|
|
87
|
+
isInitialized = false;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Validate an API key with the Onairos backend
|
|
94
|
+
* @param apiKey The API key to validate
|
|
95
|
+
* @returns Validation result with permissions and rate limits
|
|
96
|
+
*/
|
|
97
|
+
export const validateApiKey = async (apiKey: string): Promise<ApiKeyValidationResult> => {
|
|
98
|
+
try {
|
|
99
|
+
console.log('🔍 Validating API key...');
|
|
100
|
+
|
|
101
|
+
// Check cache first
|
|
102
|
+
const cached = validationCache.get(apiKey);
|
|
103
|
+
if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
|
|
104
|
+
if (globalConfig?.enableLogging) {
|
|
105
|
+
console.log('📋 Using cached API key validation result');
|
|
106
|
+
}
|
|
107
|
+
return cached.result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const environment = globalConfig?.environment || 'production';
|
|
111
|
+
const baseUrl = API_ENDPOINTS[environment];
|
|
112
|
+
const timeout = globalConfig?.timeout || 30000;
|
|
113
|
+
|
|
114
|
+
// Create abort controller for timeout
|
|
115
|
+
const controller = new AbortController();
|
|
116
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const response = await fetch(`${baseUrl}/auth/validate-key`, {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
headers: {
|
|
122
|
+
'Content-Type': 'application/json',
|
|
123
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
124
|
+
'User-Agent': 'OnairosReactNative/1.0',
|
|
125
|
+
},
|
|
126
|
+
body: JSON.stringify({
|
|
127
|
+
environment,
|
|
128
|
+
sdk_version: '3.0.71',
|
|
129
|
+
platform: 'react-native',
|
|
130
|
+
}),
|
|
131
|
+
signal: controller.signal,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
clearTimeout(timeoutId);
|
|
135
|
+
|
|
136
|
+
const data = await response.json();
|
|
137
|
+
|
|
138
|
+
if (response.ok && data.success) {
|
|
139
|
+
const result: ApiKeyValidationResult = {
|
|
140
|
+
isValid: true,
|
|
141
|
+
permissions: data.permissions || [],
|
|
142
|
+
rateLimits: data.rateLimits || null,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// Cache the successful result
|
|
146
|
+
validationCache.set(apiKey, {
|
|
147
|
+
result,
|
|
148
|
+
timestamp: Date.now(),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
if (globalConfig?.enableLogging) {
|
|
152
|
+
console.log('✅ API key validation successful');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return result;
|
|
156
|
+
} else {
|
|
157
|
+
const errorMessage = data.error || `HTTP ${response.status}: ${response.statusText}`;
|
|
158
|
+
|
|
159
|
+
const result: ApiKeyValidationResult = {
|
|
160
|
+
isValid: false,
|
|
161
|
+
error: errorMessage,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Don't cache failed results
|
|
165
|
+
if (globalConfig?.enableLogging) {
|
|
166
|
+
console.error('❌ API key validation failed:', errorMessage);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
} catch (fetchError) {
|
|
172
|
+
clearTimeout(timeoutId);
|
|
173
|
+
|
|
174
|
+
if (fetchError.name === 'AbortError') {
|
|
175
|
+
const errorMessage = 'API key validation timeout';
|
|
176
|
+
console.error('⏱️ API key validation timeout');
|
|
177
|
+
return { isValid: false, error: errorMessage };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const errorMessage = `Network error during API key validation: ${fetchError.message}`;
|
|
181
|
+
console.error('🌐 Network error during API key validation:', fetchError);
|
|
182
|
+
return { isValid: false, error: errorMessage };
|
|
183
|
+
}
|
|
184
|
+
} catch (error) {
|
|
185
|
+
const errorMessage = `API key validation error: ${error.message}`;
|
|
186
|
+
console.error('❌ API key validation error:', error);
|
|
187
|
+
return { isValid: false, error: errorMessage };
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get the current API configuration
|
|
193
|
+
* @returns Current API configuration or null if not initialized
|
|
194
|
+
*/
|
|
195
|
+
export const getApiConfig = (): OnairosConfig | null => {
|
|
196
|
+
return globalConfig;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get the current API key
|
|
201
|
+
* @returns Current API key or null if not initialized
|
|
202
|
+
*/
|
|
203
|
+
export const getApiKey = (): string | null => {
|
|
204
|
+
return globalConfig?.apiKey || null;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Check if the SDK is properly initialized
|
|
209
|
+
* @returns True if initialized with valid API key
|
|
210
|
+
*/
|
|
211
|
+
export const isApiKeyInitialized = (): boolean => {
|
|
212
|
+
return isInitialized && globalConfig !== null;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get authenticated headers for API requests
|
|
217
|
+
* @returns Headers object with Authorization and other required headers
|
|
218
|
+
*/
|
|
219
|
+
export const getAuthHeaders = (): Record<string, string> => {
|
|
220
|
+
if (!globalConfig?.apiKey) {
|
|
221
|
+
throw new Error('SDK not initialized. Call initializeApiKey() first.');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
'Content-Type': 'application/json',
|
|
226
|
+
'Authorization': `Bearer ${globalConfig.apiKey}`,
|
|
227
|
+
'User-Agent': 'OnairosReactNative/3.0.71',
|
|
228
|
+
'X-SDK-Version': '3.0.71',
|
|
229
|
+
'X-SDK-Environment': globalConfig.environment || 'production',
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Make an authenticated API request
|
|
235
|
+
* @param endpoint The API endpoint (relative to base URL)
|
|
236
|
+
* @param options Fetch options
|
|
237
|
+
* @returns Response promise
|
|
238
|
+
*/
|
|
239
|
+
export const makeAuthenticatedRequest = async (
|
|
240
|
+
endpoint: string,
|
|
241
|
+
options: RequestInit = {}
|
|
242
|
+
): Promise<Response> => {
|
|
243
|
+
if (!isApiKeyInitialized()) {
|
|
244
|
+
throw new Error('SDK not initialized. Call initializeApiKey() first.');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const config = getApiConfig()!;
|
|
248
|
+
const baseUrl = API_ENDPOINTS[config.environment || 'production'];
|
|
249
|
+
const url = `${baseUrl}${endpoint.startsWith('/') ? '' : '/'}${endpoint}`;
|
|
250
|
+
|
|
251
|
+
// Merge authentication headers
|
|
252
|
+
const headers = {
|
|
253
|
+
...getAuthHeaders(),
|
|
254
|
+
...(options.headers || {}),
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Add timeout
|
|
258
|
+
const controller = new AbortController();
|
|
259
|
+
const timeoutId = setTimeout(() => controller.abort(), config.timeout || 30000);
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
if (config.enableLogging) {
|
|
263
|
+
console.log(`🌐 Making authenticated request to: ${endpoint}`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const response = await fetch(url, {
|
|
267
|
+
...options,
|
|
268
|
+
headers,
|
|
269
|
+
signal: controller.signal,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
clearTimeout(timeoutId);
|
|
273
|
+
|
|
274
|
+
if (config.enableLogging) {
|
|
275
|
+
console.log(`📡 Response status: ${response.status} for ${endpoint}`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Handle API key errors
|
|
279
|
+
if (response.status === 401) {
|
|
280
|
+
console.error('❌ API key authentication failed. Please check your API key.');
|
|
281
|
+
throw new Error('Invalid or expired API key');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (response.status === 403) {
|
|
285
|
+
console.error('❌ API key permissions insufficient for this operation.');
|
|
286
|
+
throw new Error('Insufficient API key permissions');
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (response.status === 429) {
|
|
290
|
+
console.error('❌ API rate limit exceeded. Please try again later.');
|
|
291
|
+
throw new Error('Rate limit exceeded');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return response;
|
|
295
|
+
} catch (error) {
|
|
296
|
+
clearTimeout(timeoutId);
|
|
297
|
+
|
|
298
|
+
if (error.name === 'AbortError') {
|
|
299
|
+
console.error('⏱️ Request timeout for:', endpoint);
|
|
300
|
+
throw new Error('Request timeout');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
throw error;
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Clear the API key validation cache
|
|
309
|
+
*/
|
|
310
|
+
export const clearValidationCache = (): void => {
|
|
311
|
+
validationCache.clear();
|
|
312
|
+
if (globalConfig?.enableLogging) {
|
|
313
|
+
console.log('🗑️ API key validation cache cleared');
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Reset the SDK initialization state
|
|
319
|
+
*/
|
|
320
|
+
export const resetApiKeyService = (): void => {
|
|
321
|
+
globalConfig = null;
|
|
322
|
+
isInitialized = false;
|
|
323
|
+
clearValidationCache();
|
|
324
|
+
console.log('🔄 API key service reset');
|
|
325
|
+
};
|