@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.
Files changed (39) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/HawcxReactNative.podspec +2 -2
  3. package/LICENSE +48 -15
  4. package/README.md +150 -88
  5. package/docs/RELEASE.md +2 -2
  6. package/example/ios/HawcxExampleApp.xcodeproj/project.pbxproj +57 -57
  7. package/example/ios/HawcxExampleApp.xcodeproj/project.xcworkspace/xcuserdata/agambhullar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  8. package/example/ios/Podfile +24 -0
  9. package/example/ios/Podfile.lock +3 -3
  10. package/example/package-lock.json +3 -3
  11. package/example/package.json +1 -1
  12. package/example/src/App.tsx +211 -8
  13. package/example/src/hawcx.config.ts +4 -26
  14. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/HawcxFramework +0 -0
  15. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.abi.json +208 -77
  16. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.private.swiftinterface +10 -0
  17. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  18. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftinterface +10 -0
  19. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/HawcxFramework +0 -0
  20. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.abi.json +208 -77
  21. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +10 -0
  22. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  23. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftinterface +10 -0
  24. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json +208 -77
  25. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +10 -0
  26. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  27. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +10 -0
  28. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/_CodeSignature/CodeResources +20 -20
  29. package/ios/HawcxReactNative.swift +64 -0
  30. package/lib/commonjs/index.js +34 -0
  31. package/lib/commonjs/index.js.map +1 -1
  32. package/lib/module/index.js +33 -0
  33. package/lib/module/index.js.map +1 -1
  34. package/lib/typescript/index.d.ts +28 -0
  35. package/lib/typescript/index.d.ts.map +1 -1
  36. package/package.json +1 -1
  37. package/react_mobile_sdk_plan.md +2 -0
  38. package/src/__tests__/index.test.ts +40 -1
  39. 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 });