@hawcx/react-native-sdk 1.0.1 → 1.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.
- package/CHANGELOG.md +5 -1
- package/HawcxReactNative.podspec +2 -2
- package/LICENSE +48 -15
- package/README.md +150 -88
- package/docs/RELEASE.md +2 -2
- package/example/ios/HawcxExampleApp.xcodeproj/project.pbxproj +57 -57
- package/example/ios/HawcxExampleApp.xcodeproj/project.xcworkspace/xcuserdata/agambhullar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Podfile +24 -0
- package/example/ios/Podfile.lock +3 -3
- package/example/package-lock.json +3 -3
- package/example/package.json +1 -1
- package/example/src/App.tsx +211 -8
- package/example/src/hawcx.config.ts +4 -26
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/HawcxFramework +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.abi.json +208 -77
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.private.swiftinterface +10 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftinterface +10 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/HawcxFramework +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.abi.json +208 -77
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +10 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftinterface +10 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json +208 -77
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +10 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +10 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/_CodeSignature/CodeResources +20 -20
- package/ios/HawcxReactNative.swift +64 -0
- package/lib/commonjs/index.js +34 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +33 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +28 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/react_mobile_sdk_plan.md +2 -0
- package/src/__tests__/index.test.ts +40 -1
- package/src/index.ts +66 -0
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
initialize,
|
|
3
3
|
authenticate,
|
|
4
4
|
submitOtp,
|
|
5
|
+
storeBackendOAuthTokens,
|
|
5
6
|
webLogin,
|
|
6
7
|
webApprove,
|
|
7
8
|
approvePushRequest,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
HawcxAuthError,
|
|
12
13
|
__INTERNAL_EVENTS__,
|
|
13
14
|
} from '../index';
|
|
14
|
-
import { Platform } from 'react-native';
|
|
15
|
+
import { NativeModules, Platform } from 'react-native';
|
|
15
16
|
|
|
16
17
|
const ORIGINAL_PLATFORM = Platform.OS;
|
|
17
18
|
|
|
@@ -114,6 +115,22 @@ describe('HawcxClient helpers', () => {
|
|
|
114
115
|
});
|
|
115
116
|
});
|
|
116
117
|
|
|
118
|
+
it('invokes authorization code callback', async () => {
|
|
119
|
+
const onAuthorizationCode = jest.fn();
|
|
120
|
+
client.authenticate('user@example.com', { onAuthorizationCode });
|
|
121
|
+
const payload = { code: 'abc', expiresIn: 30 };
|
|
122
|
+
emitAuth({ type: 'authorization_code', payload });
|
|
123
|
+
expect(onAuthorizationCode).toHaveBeenCalledWith(payload);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('invokes additional verification callback', async () => {
|
|
127
|
+
const onAdditionalVerificationRequired = jest.fn();
|
|
128
|
+
client.authenticate('user@example.com', { onAdditionalVerificationRequired });
|
|
129
|
+
const payload = { sessionId: 'sid', detail: 'extra' };
|
|
130
|
+
emitAuth({ type: 'additional_verification_required', payload });
|
|
131
|
+
expect(onAdditionalVerificationRequired).toHaveBeenCalledWith(payload);
|
|
132
|
+
});
|
|
133
|
+
|
|
117
134
|
it('invokes push event handlers', async () => {
|
|
118
135
|
const handler = jest.fn();
|
|
119
136
|
const subscription = client.addPushListener(handler);
|
|
@@ -161,3 +178,25 @@ describe('push token helpers', () => {
|
|
|
161
178
|
);
|
|
162
179
|
});
|
|
163
180
|
});
|
|
181
|
+
|
|
182
|
+
describe('storeBackendOAuthTokens helper', () => {
|
|
183
|
+
const bridge = NativeModules.HawcxReactNative.storeBackendOAuthTokens as jest.Mock;
|
|
184
|
+
|
|
185
|
+
beforeEach(() => {
|
|
186
|
+
bridge.mockResolvedValue(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('calls native bridge with trimmed values', async () => {
|
|
190
|
+
await storeBackendOAuthTokens(' user@example.com ', ' token ', ' refresh ');
|
|
191
|
+
expect(bridge).toHaveBeenCalledWith('user@example.com', 'token', 'refresh');
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('passes null refresh token when omitted', async () => {
|
|
195
|
+
await storeBackendOAuthTokens('user@example.com', 'token');
|
|
196
|
+
expect(bridge).toHaveBeenCalledWith('user@example.com', 'token', null);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('rejects when userId empty', async () => {
|
|
200
|
+
await expect(storeBackendOAuthTokens(' ', 'token')).rejects.toThrow('userId is required');
|
|
201
|
+
});
|
|
202
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -33,6 +33,21 @@ export type AuthSuccessPayload = {
|
|
|
33
33
|
isLoginFlow: boolean;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
export type AuthorizationCodePayload = {
|
|
37
|
+
code: string;
|
|
38
|
+
expiresIn?: number;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type AdditionalVerificationPayload = {
|
|
42
|
+
sessionId: string;
|
|
43
|
+
detail?: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type BackendOAuthTokens = {
|
|
47
|
+
accessToken: string;
|
|
48
|
+
refreshToken?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
36
51
|
export type AuthErrorPayload = {
|
|
37
52
|
code: string;
|
|
38
53
|
message: string;
|
|
@@ -41,6 +56,8 @@ export type AuthErrorPayload = {
|
|
|
41
56
|
export type AuthEvent =
|
|
42
57
|
| { type: 'otp_required' }
|
|
43
58
|
| { type: 'auth_success'; payload: AuthSuccessPayload }
|
|
59
|
+
| { type: 'authorization_code'; payload: AuthorizationCodePayload }
|
|
60
|
+
| { type: 'additional_verification_required'; payload: AdditionalVerificationPayload }
|
|
44
61
|
| { type: 'auth_error'; payload: AuthErrorPayload };
|
|
45
62
|
|
|
46
63
|
export type SessionEvent =
|
|
@@ -63,6 +80,11 @@ type NativeBridge = {
|
|
|
63
80
|
initialize(config: HawcxInitializeConfig): Promise<void>;
|
|
64
81
|
authenticate(userId: string): Promise<void>;
|
|
65
82
|
submitOtp(otp: string): Promise<void>;
|
|
83
|
+
storeBackendOAuthTokens(
|
|
84
|
+
userId: string,
|
|
85
|
+
accessToken: string,
|
|
86
|
+
refreshToken?: string | null,
|
|
87
|
+
): Promise<boolean>;
|
|
66
88
|
getDeviceDetails(): Promise<void>;
|
|
67
89
|
webLogin(pin: string): Promise<void>;
|
|
68
90
|
webApprove(token: string): Promise<void>;
|
|
@@ -127,6 +149,25 @@ export function submitOtp(otp: string): Promise<void> {
|
|
|
127
149
|
}
|
|
128
150
|
}
|
|
129
151
|
|
|
152
|
+
export function storeBackendOAuthTokens(
|
|
153
|
+
userId: string,
|
|
154
|
+
accessToken: string,
|
|
155
|
+
refreshToken?: string,
|
|
156
|
+
): Promise<void> {
|
|
157
|
+
try {
|
|
158
|
+
const trimmedUser = ensureNonEmpty(userId, 'userId');
|
|
159
|
+
const trimmedAccess = ensureNonEmpty(accessToken, 'accessToken');
|
|
160
|
+
const trimmedRefresh = refreshToken?.trim();
|
|
161
|
+
return HawcxReactNative.storeBackendOAuthTokens(
|
|
162
|
+
trimmedUser,
|
|
163
|
+
trimmedAccess,
|
|
164
|
+
trimmedRefresh && trimmedRefresh.length > 0 ? trimmedRefresh : null,
|
|
165
|
+
).then(() => undefined);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
return Promise.reject(error);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
130
171
|
export function getDeviceDetails(): Promise<void> {
|
|
131
172
|
return HawcxReactNative.getDeviceDetails();
|
|
132
173
|
}
|
|
@@ -244,6 +285,8 @@ export class HawcxAuthError extends Error {
|
|
|
244
285
|
|
|
245
286
|
export type HawcxAuthOptions = {
|
|
246
287
|
onOtpRequired?: () => void;
|
|
288
|
+
onAuthorizationCode?: (payload: AuthorizationCodePayload) => void;
|
|
289
|
+
onAdditionalVerificationRequired?: (payload: AdditionalVerificationPayload) => void;
|
|
247
290
|
onEvent?: (event: AuthEvent) => void;
|
|
248
291
|
};
|
|
249
292
|
|
|
@@ -280,6 +323,12 @@ export class HawcxClient {
|
|
|
280
323
|
case 'otp_required':
|
|
281
324
|
options?.onOtpRequired?.();
|
|
282
325
|
break;
|
|
326
|
+
case 'authorization_code':
|
|
327
|
+
options?.onAuthorizationCode?.(event.payload);
|
|
328
|
+
break;
|
|
329
|
+
case 'additional_verification_required':
|
|
330
|
+
options?.onAdditionalVerificationRequired?.(event.payload);
|
|
331
|
+
break;
|
|
283
332
|
case 'auth_success':
|
|
284
333
|
cleanup();
|
|
285
334
|
resolve(event.payload);
|
|
@@ -387,6 +436,10 @@ export class HawcxClient {
|
|
|
387
436
|
addPushListener(handler: (event: PushEvent) => void): EmitterSubscription {
|
|
388
437
|
return addPushListener(handler);
|
|
389
438
|
}
|
|
439
|
+
|
|
440
|
+
storeBackendOAuthTokens(userId: string, tokens: BackendOAuthTokens): Promise<void> {
|
|
441
|
+
return storeBackendOAuthTokens(userId, tokens.accessToken, tokens.refreshToken);
|
|
442
|
+
}
|
|
390
443
|
}
|
|
391
444
|
|
|
392
445
|
export const hawcxClient = new HawcxClient();
|
|
@@ -395,6 +448,8 @@ export type HawcxAuthHookState =
|
|
|
395
448
|
| { status: 'idle' }
|
|
396
449
|
| { status: 'pending' }
|
|
397
450
|
| { status: 'otp'; attempts: number }
|
|
451
|
+
| { status: 'authorization_code'; payload: AuthorizationCodePayload }
|
|
452
|
+
| { status: 'additional_verification_required'; payload: AdditionalVerificationPayload }
|
|
398
453
|
| { status: 'success'; result: AuthSuccessPayload }
|
|
399
454
|
| { status: 'error'; error: AuthErrorPayload };
|
|
400
455
|
|
|
@@ -415,6 +470,17 @@ export function useHawcxAuth(client: HawcxClient = hawcxClient) {
|
|
|
415
470
|
otpAttempts.current += 1;
|
|
416
471
|
setState({ status: 'otp', attempts: otpAttempts.current });
|
|
417
472
|
break;
|
|
473
|
+
case 'authorization_code':
|
|
474
|
+
otpAttempts.current = 0;
|
|
475
|
+
setState({ status: 'authorization_code', payload: event.payload });
|
|
476
|
+
break;
|
|
477
|
+
case 'additional_verification_required':
|
|
478
|
+
otpAttempts.current = 0;
|
|
479
|
+
setState({
|
|
480
|
+
status: 'additional_verification_required',
|
|
481
|
+
payload: event.payload,
|
|
482
|
+
});
|
|
483
|
+
break;
|
|
418
484
|
case 'auth_success':
|
|
419
485
|
otpAttempts.current = 0;
|
|
420
486
|
setState({ status: 'success', result: event.payload });
|