@onairos/react-native 3.0.0 → 3.0.2

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.
Files changed (32) hide show
  1. package/lib/commonjs/api/index.js +105 -86
  2. package/lib/commonjs/api/index.js.map +1 -1
  3. package/lib/commonjs/components/OnairosButton.js +21 -13
  4. package/lib/commonjs/components/OnairosButton.js.map +1 -1
  5. package/lib/commonjs/components/UniversalOnboarding.js +18 -0
  6. package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
  7. package/lib/commonjs/index.js +367 -12
  8. package/lib/commonjs/index.js.map +1 -1
  9. package/lib/commonjs/services/oauthService.js +101 -192
  10. package/lib/commonjs/services/oauthService.js.map +1 -1
  11. package/lib/commonjs/utils/secureStorage.js +129 -42
  12. package/lib/commonjs/utils/secureStorage.js.map +1 -1
  13. package/lib/module/api/index.js +105 -86
  14. package/lib/module/api/index.js.map +1 -1
  15. package/lib/module/components/OnairosButton.js +22 -14
  16. package/lib/module/components/OnairosButton.js.map +1 -1
  17. package/lib/module/components/UniversalOnboarding.js +19 -1
  18. package/lib/module/components/UniversalOnboarding.js.map +1 -1
  19. package/lib/module/index.js +11 -10
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/services/oauthService.js +83 -192
  22. package/lib/module/services/oauthService.js.map +1 -1
  23. package/lib/module/utils/secureStorage.js +129 -42
  24. package/lib/module/utils/secureStorage.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/api/index.ts +86 -101
  27. package/src/components/OnairosButton.tsx +23 -14
  28. package/src/components/UniversalOnboarding.tsx +13 -0
  29. package/src/index.ts +2 -4
  30. package/src/services/oauthService.ts +419 -534
  31. package/src/types/index.ts +5 -0
  32. package/src/utils/secureStorage.ts +140 -57
@@ -132,4 +132,9 @@ export interface ApiResponse<T> {
132
132
  success: boolean;
133
133
  data?: T;
134
134
  error?: string;
135
+ }
136
+
137
+ export interface CredentialsResult {
138
+ isValid: boolean;
139
+ credentials?: any;
135
140
  }
@@ -1,41 +1,137 @@
1
+ import * as Keychain from 'react-native-keychain';
1
2
  import { Platform } from 'react-native';
2
3
  import { sha256 } from './crypto';
4
+ import { STORAGE_KEYS } from '../constants';
3
5
 
6
+ // Define OnairosCredentials interface locally to avoid circular dependencies
4
7
  export interface OnairosCredentials {
5
8
  username: string;
6
- accessToken: string;
9
+ accessToken?: string;
7
10
  refreshToken?: string;
8
11
  userPin?: string;
9
12
  platforms?: {
10
- instagram?: { token: string; username: string };
11
- youtube?: { token: string; username: string };
12
- pinterest?: { token: string; username: string };
13
- reddit?: { token: string; username: string };
13
+ instagram?: { token: string; username: string; userId?: string };
14
+ youtube?: { token: string; username: string; userId?: string };
15
+ pinterest?: { token: string; username: string; userId?: string };
16
+ reddit?: { token: string; username: string; userId?: string };
14
17
  };
15
18
  createdAt: number;
16
19
  }
17
20
 
18
21
  export interface StorageOptions {
19
- useBiometrics?: boolean;
20
- biometricPrompt?: {
21
- title: string;
22
- subtitle?: string;
23
- };
22
+ service?: string;
23
+ accessControl?: Keychain.ACCESS_CONTROL;
24
+ accessible?: Keychain.ACCESSIBLE;
24
25
  }
25
26
 
26
- // Temporary in-memory storage
27
- let mockStorage: { [key: string]: string } = {};
27
+ // Create a mock storage for environments without Keychain access (like Expo Go)
28
+ const mockStorage: Record<string, { username: string; password: string }> = {};
29
+
30
+ // Check if running in Expo Go or environments without native module access
31
+ const isKeychainAvailable = () => {
32
+ try {
33
+ return typeof Keychain.getGenericPassword === 'function';
34
+ } catch (e) {
35
+ return false;
36
+ }
37
+ };
38
+
39
+ // Wrapper for getGenericPassword that falls back to mock storage
40
+ const safeGetGenericPassword = async (options: Keychain.Options) => {
41
+ try {
42
+ if (isKeychainAvailable()) {
43
+ return await Keychain.getGenericPassword(options);
44
+ } else {
45
+ // Fall back to mock storage in memory
46
+ const key = options?.service || 'default';
47
+ return mockStorage[key] || null;
48
+ }
49
+ } catch (error) {
50
+ console.warn('Keychain access failed, using mock storage', error);
51
+ // Fall back to mock storage on error
52
+ const key = options?.service || 'default';
53
+ return mockStorage[key] || null;
54
+ }
55
+ };
56
+
57
+ // Wrapper for setGenericPassword that falls back to mock storage
58
+ const safeSetGenericPassword = async (
59
+ username: string,
60
+ password: string,
61
+ options?: Keychain.Options
62
+ ) => {
63
+ try {
64
+ if (isKeychainAvailable()) {
65
+ return await Keychain.setGenericPassword(username, password, options);
66
+ } else {
67
+ // Fall back to mock storage in memory
68
+ const key = options?.service || 'default';
69
+ mockStorage[key] = { username, password };
70
+ return true;
71
+ }
72
+ } catch (error) {
73
+ console.warn('Keychain access failed, using mock storage', error);
74
+ // Fall back to mock storage on error
75
+ const key = options?.service || 'default';
76
+ mockStorage[key] = { username, password };
77
+ return true;
78
+ }
79
+ };
80
+
81
+ // Wrapper for resetGenericPassword that falls back to mock storage
82
+ const safeResetGenericPassword = async (options?: Keychain.Options) => {
83
+ try {
84
+ if (isKeychainAvailable()) {
85
+ return await Keychain.resetGenericPassword(options);
86
+ } else {
87
+ // Fall back to mock storage in memory
88
+ const key = options?.service || 'default';
89
+ delete mockStorage[key];
90
+ return true;
91
+ }
92
+ } catch (error) {
93
+ console.warn('Keychain access failed, using mock storage', error);
94
+ // Fall back to mock storage on error
95
+ const key = options?.service || 'default';
96
+ delete mockStorage[key];
97
+ return true;
98
+ }
99
+ };
28
100
 
29
101
  /**
30
102
  * Store credentials in memory (temporary solution)
31
103
  */
32
104
  export const storeCredentials = async (
33
- credentials: OnairosCredentials,
34
- options: StorageOptions = {}
105
+ credentials: Partial<OnairosCredentials>
35
106
  ): Promise<boolean> => {
36
107
  try {
37
- console.log('[Mock] Storing credentials:', credentials.username);
38
- mockStorage[credentials.username] = JSON.stringify(credentials);
108
+ const existingCredentials = await getCredentials();
109
+ const updatedCredentials: OnairosCredentials = {
110
+ ...existingCredentials,
111
+ ...credentials,
112
+ createdAt: existingCredentials?.createdAt || Date.now(),
113
+ } as OnairosCredentials;
114
+
115
+ const username = updatedCredentials.username;
116
+ if (!username) {
117
+ throw new Error('Username is required for storing credentials');
118
+ }
119
+
120
+ const options: Keychain.Options = {
121
+ service: STORAGE_KEYS.credentials,
122
+ };
123
+
124
+ // Only use secure storage options on real devices
125
+ if (Platform.OS !== 'web' && isKeychainAvailable()) {
126
+ options.accessControl = Keychain.ACCESS_CONTROL.BIOMETRY_ANY_OR_DEVICE_PASSCODE;
127
+ options.accessible = Keychain.ACCESSIBLE.WHEN_UNLOCKED;
128
+ }
129
+
130
+ await safeSetGenericPassword(
131
+ username,
132
+ JSON.stringify(updatedCredentials),
133
+ options
134
+ );
39
135
  return true;
40
136
  } catch (error) {
41
137
  console.error('Error storing credentials:', error);
@@ -46,18 +142,17 @@ export const storeCredentials = async (
46
142
  /**
47
143
  * Retrieve credentials from memory (temporary solution)
48
144
  */
49
- export const getCredentials = async (
50
- options: StorageOptions = {}
51
- ): Promise<OnairosCredentials | null> => {
145
+ export const getCredentials = async (): Promise<OnairosCredentials | null> => {
52
146
  try {
53
- // Get the first stored credential (temporary solution)
54
- const storedCredential = Object.values(mockStorage)[0];
55
- if (!storedCredential) {
56
- return null;
147
+ const credentials = await safeGetGenericPassword({
148
+ service: STORAGE_KEYS.credentials,
149
+ });
150
+ if (credentials) {
151
+ return JSON.parse(credentials.password);
57
152
  }
58
- return JSON.parse(storedCredential);
153
+ return null;
59
154
  } catch (error) {
60
- console.error('Error retrieving credentials:', error);
155
+ console.error('Error getting credentials:', error);
61
156
  return null;
62
157
  }
63
158
  };
@@ -67,9 +162,12 @@ export const getCredentials = async (
67
162
  */
68
163
  export const hasCredentials = async (): Promise<boolean> => {
69
164
  try {
70
- return Object.keys(mockStorage).length > 0;
165
+ const credentials = await safeGetGenericPassword({
166
+ service: STORAGE_KEYS.credentials,
167
+ });
168
+ return !!credentials;
71
169
  } catch (error) {
72
- console.error('Error checking for credentials:', error);
170
+ console.error('Error checking credentials:', error);
73
171
  return false;
74
172
  }
75
173
  };
@@ -79,7 +177,9 @@ export const hasCredentials = async (): Promise<boolean> => {
79
177
  */
80
178
  export const deleteCredentials = async (): Promise<boolean> => {
81
179
  try {
82
- mockStorage = {};
180
+ await safeResetGenericPassword({
181
+ service: STORAGE_KEYS.credentials,
182
+ });
83
183
  return true;
84
184
  } catch (error) {
85
185
  console.error('Error deleting credentials:', error);
@@ -91,47 +191,30 @@ export const deleteCredentials = async (): Promise<boolean> => {
91
191
  * Update specific fields in the stored credentials
92
192
  */
93
193
  export const updateCredentials = async (
94
- updates: Partial<OnairosCredentials>,
95
- options: StorageOptions = {}
194
+ credentials: Partial<OnairosCredentials>
96
195
  ): Promise<boolean> => {
97
- try {
98
- const currentCredentials = await getCredentials(options);
99
- if (!currentCredentials) {
100
- return false;
101
- }
102
- const updatedCredentials: OnairosCredentials = {
103
- ...currentCredentials,
104
- ...updates,
105
- };
106
- return await storeCredentials(updatedCredentials, options);
107
- } catch (error) {
108
- console.error('Error updating credentials:', error);
109
- return false;
110
- }
196
+ return storeCredentials(credentials);
111
197
  };
112
198
 
113
199
  /**
114
200
  * Generate a device-specific unique username
115
201
  */
116
- export const generateDeviceUsername = async (): Promise<string> => {
117
- try {
118
- const deviceInfo = `${Platform.OS}-${Platform.Version}-${Date.now()}`;
119
- const username = `onairos_${sha256(deviceInfo).substring(0, 10)}`;
120
- return username;
121
- } catch (error) {
122
- console.error('Error generating device username:', error);
123
- return `onairos_${Date.now().toString(36)}`;
124
- }
202
+ export const generateDeviceUsername = (): string => {
203
+ const randomId = Math.random().toString(36).substring(2, 10);
204
+ return `dev_${randomId}`;
125
205
  };
126
206
 
127
207
  /**
128
208
  * Verify credentials (temporary mock implementation)
129
209
  */
130
- export const verifyCredentials = async (
131
- credentials: OnairosCredentials
132
- ): Promise<boolean> => {
210
+ export const verifyCredentials = async (username: string): Promise<boolean> => {
133
211
  try {
134
- console.log('[Mock] Verifying credentials for:', credentials.username);
212
+ // For Expo Go or development, always return true
213
+ if (!isKeychainAvailable()) {
214
+ return true;
215
+ }
216
+
217
+ // TODO: Implement actual verification with API
135
218
  return true;
136
219
  } catch (error) {
137
220
  console.error('Error verifying credentials:', error);