@hawcx/react-native-sdk 1.0.1 → 1.0.3
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 +8 -1
- package/HawcxReactNative.podspec +2 -2
- package/LICENSE +48 -15
- package/README.md +155 -88
- package/docs/RELEASE.md +15 -4
- package/example/README.md +1 -1
- package/example/android/build.gradle +12 -0
- package/example/android/settings.gradle +34 -0
- 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 +10 -26
- package/ios/Frameworks/HawcxFramework.xcframework/Info.plist +5 -5
- 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 +185 -300
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.private.swiftinterface +11 -1
- 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 +11 -1
- 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 +185 -300
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +11 -1
- 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 +11 -1
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json +185 -300
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +11 -1
- 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 +11 -1
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/_CodeSignature/CodeResources +20 -20
- package/ios/HawcxReactNative.swift +87 -1
- package/lib/commonjs/index.js +41 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +40 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +36 -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 +44 -1
- package/src/index.ts +81 -0
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { NativeEventEmitter, EmitterSubscription } from 'react-native';
|
|
2
2
|
export type HawcxInitializeConfig = {
|
|
3
3
|
projectApiKey: string;
|
|
4
|
+
/**
|
|
5
|
+
* Tenant-specific Hawcx host (for example: https://hawcx-api.hawcx.com).
|
|
6
|
+
* The native SDK appends /hc_auth internally—do not add extra paths.
|
|
7
|
+
*/
|
|
8
|
+
baseUrl?: string;
|
|
4
9
|
oauthConfig?: {
|
|
5
10
|
clientId: string;
|
|
6
11
|
publicKeyPem: string;
|
|
7
12
|
tokenEndpoint: string;
|
|
8
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated Use root-level `baseUrl` instead. Kept for backward compatibility during migration.
|
|
16
|
+
*/
|
|
9
17
|
endpoints?: {
|
|
10
18
|
authBaseUrl?: string;
|
|
11
19
|
};
|
|
@@ -15,6 +23,18 @@ export type AuthSuccessPayload = {
|
|
|
15
23
|
refreshToken?: string;
|
|
16
24
|
isLoginFlow: boolean;
|
|
17
25
|
};
|
|
26
|
+
export type AuthorizationCodePayload = {
|
|
27
|
+
code: string;
|
|
28
|
+
expiresIn?: number;
|
|
29
|
+
};
|
|
30
|
+
export type AdditionalVerificationPayload = {
|
|
31
|
+
sessionId: string;
|
|
32
|
+
detail?: string;
|
|
33
|
+
};
|
|
34
|
+
export type BackendOAuthTokens = {
|
|
35
|
+
accessToken: string;
|
|
36
|
+
refreshToken?: string;
|
|
37
|
+
};
|
|
18
38
|
export type AuthErrorPayload = {
|
|
19
39
|
code: string;
|
|
20
40
|
message: string;
|
|
@@ -24,6 +44,12 @@ export type AuthEvent = {
|
|
|
24
44
|
} | {
|
|
25
45
|
type: 'auth_success';
|
|
26
46
|
payload: AuthSuccessPayload;
|
|
47
|
+
} | {
|
|
48
|
+
type: 'authorization_code';
|
|
49
|
+
payload: AuthorizationCodePayload;
|
|
50
|
+
} | {
|
|
51
|
+
type: 'additional_verification_required';
|
|
52
|
+
payload: AdditionalVerificationPayload;
|
|
27
53
|
} | {
|
|
28
54
|
type: 'auth_error';
|
|
29
55
|
payload: AuthErrorPayload;
|
|
@@ -51,6 +77,7 @@ export type PushEvent = {
|
|
|
51
77
|
export declare function initialize(config: HawcxInitializeConfig): Promise<void>;
|
|
52
78
|
export declare function authenticate(userId: string): Promise<void>;
|
|
53
79
|
export declare function submitOtp(otp: string): Promise<void>;
|
|
80
|
+
export declare function storeBackendOAuthTokens(userId: string, accessToken: string, refreshToken?: string): Promise<void>;
|
|
54
81
|
export declare function getDeviceDetails(): Promise<void>;
|
|
55
82
|
export declare function webLogin(pin: string): Promise<void>;
|
|
56
83
|
export declare function webApprove(token: string): Promise<void>;
|
|
@@ -73,6 +100,8 @@ export declare class HawcxAuthError extends Error {
|
|
|
73
100
|
}
|
|
74
101
|
export type HawcxAuthOptions = {
|
|
75
102
|
onOtpRequired?: () => void;
|
|
103
|
+
onAuthorizationCode?: (payload: AuthorizationCodePayload) => void;
|
|
104
|
+
onAdditionalVerificationRequired?: (payload: AdditionalVerificationPayload) => void;
|
|
76
105
|
onEvent?: (event: AuthEvent) => void;
|
|
77
106
|
};
|
|
78
107
|
export type AuthInvocation = {
|
|
@@ -100,6 +129,7 @@ export declare class HawcxClient {
|
|
|
100
129
|
approvePushRequest(requestId: string): Promise<void>;
|
|
101
130
|
declinePushRequest(requestId: string): Promise<void>;
|
|
102
131
|
addPushListener(handler: (event: PushEvent) => void): EmitterSubscription;
|
|
132
|
+
storeBackendOAuthTokens(userId: string, tokens: BackendOAuthTokens): Promise<void>;
|
|
103
133
|
}
|
|
104
134
|
export declare const hawcxClient: HawcxClient;
|
|
105
135
|
export type HawcxAuthHookState = {
|
|
@@ -109,6 +139,12 @@ export type HawcxAuthHookState = {
|
|
|
109
139
|
} | {
|
|
110
140
|
status: 'otp';
|
|
111
141
|
attempts: number;
|
|
142
|
+
} | {
|
|
143
|
+
status: 'authorization_code';
|
|
144
|
+
payload: AuthorizationCodePayload;
|
|
145
|
+
} | {
|
|
146
|
+
status: 'additional_verification_required';
|
|
147
|
+
payload: AdditionalVerificationPayload;
|
|
112
148
|
} | {
|
|
113
149
|
status: 'success';
|
|
114
150
|
result: AuthSuccessPayload;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAElB,mBAAmB,EAEpB,MAAM,cAAc,CAAC;AAWtB,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,SAAS,CAAC,EAAE;QACV,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/react_mobile_sdk_plan.md
CHANGED
|
@@ -219,6 +219,8 @@ _Update this table as you work. Status values: TODO / IN-PROGRESS / BLOCKED / DO
|
|
|
219
219
|
| E | JS/TS platform ergonomics | Codex (2025-11-15) | DONE | Added cross-platform push helpers, Android guards, README/testing updates |
|
|
220
220
|
| F | Example app + Android QA harness | Codex (2025-11-15) | DONE | Example app updated for Android + push harness, README + Maestro docs refreshed |
|
|
221
221
|
| G | Docs + release updates | Codex (2025-11-15) | DONE | Release guide now covers Android Gradle checks + dual-platform handoff |
|
|
222
|
+
| H | OAuth authorization-code surfacing + backend token helper | Codex (2025-11-17) | DONE | React bridges emit `authorization_code`/`additional_verification_required` events and expose `storeBackendOAuthTokens`; TypeScript API + tests updated |
|
|
223
|
+
| I | Example app backend toggle + documentation refresh | Codex (2025-11-17) | DONE | RN demo app can send codes to `hawcx_node_oauth_client/demo`, README + mint docs document backend setup and ngrok flow |
|
|
222
224
|
|
|
223
225
|
Add rows if new scope appears (e.g., analytics hook, tenant-specific API). Include blockers and links to PRs.
|
|
224
226
|
|
|
@@ -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
|
|
|
@@ -27,6 +28,10 @@ describe('Hawcx React Native SDK', () => {
|
|
|
27
28
|
await expect(initialize({ projectApiKey: '' })).rejects.toThrow('projectApiKey is required');
|
|
28
29
|
});
|
|
29
30
|
|
|
31
|
+
it('rejects initialize call without base url', async () => {
|
|
32
|
+
await expect(initialize({ projectApiKey: 'key' })).rejects.toThrow('baseUrl is required');
|
|
33
|
+
});
|
|
34
|
+
|
|
30
35
|
it('rejects authenticate call without userId', async () => {
|
|
31
36
|
await expect(authenticate(' ')).rejects.toThrow('userId is required');
|
|
32
37
|
});
|
|
@@ -114,6 +119,22 @@ describe('HawcxClient helpers', () => {
|
|
|
114
119
|
});
|
|
115
120
|
});
|
|
116
121
|
|
|
122
|
+
it('invokes authorization code callback', async () => {
|
|
123
|
+
const onAuthorizationCode = jest.fn();
|
|
124
|
+
client.authenticate('user@example.com', { onAuthorizationCode });
|
|
125
|
+
const payload = { code: 'abc', expiresIn: 30 };
|
|
126
|
+
emitAuth({ type: 'authorization_code', payload });
|
|
127
|
+
expect(onAuthorizationCode).toHaveBeenCalledWith(payload);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('invokes additional verification callback', async () => {
|
|
131
|
+
const onAdditionalVerificationRequired = jest.fn();
|
|
132
|
+
client.authenticate('user@example.com', { onAdditionalVerificationRequired });
|
|
133
|
+
const payload = { sessionId: 'sid', detail: 'extra' };
|
|
134
|
+
emitAuth({ type: 'additional_verification_required', payload });
|
|
135
|
+
expect(onAdditionalVerificationRequired).toHaveBeenCalledWith(payload);
|
|
136
|
+
});
|
|
137
|
+
|
|
117
138
|
it('invokes push event handlers', async () => {
|
|
118
139
|
const handler = jest.fn();
|
|
119
140
|
const subscription = client.addPushListener(handler);
|
|
@@ -161,3 +182,25 @@ describe('push token helpers', () => {
|
|
|
161
182
|
);
|
|
162
183
|
});
|
|
163
184
|
});
|
|
185
|
+
|
|
186
|
+
describe('storeBackendOAuthTokens helper', () => {
|
|
187
|
+
const bridge = NativeModules.HawcxReactNative.storeBackendOAuthTokens as jest.Mock;
|
|
188
|
+
|
|
189
|
+
beforeEach(() => {
|
|
190
|
+
bridge.mockResolvedValue(true);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('calls native bridge with trimmed values', async () => {
|
|
194
|
+
await storeBackendOAuthTokens(' user@example.com ', ' token ', ' refresh ');
|
|
195
|
+
expect(bridge).toHaveBeenCalledWith('user@example.com', 'token', 'refresh');
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('passes null refresh token when omitted', async () => {
|
|
199
|
+
await storeBackendOAuthTokens('user@example.com', 'token');
|
|
200
|
+
expect(bridge).toHaveBeenCalledWith('user@example.com', 'token', null);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('rejects when userId empty', async () => {
|
|
204
|
+
await expect(storeBackendOAuthTokens(' ', 'token')).rejects.toThrow('userId is required');
|
|
205
|
+
});
|
|
206
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -17,11 +17,19 @@ const PUSH_EVENT = 'hawcx.push.event';
|
|
|
17
17
|
|
|
18
18
|
export type HawcxInitializeConfig = {
|
|
19
19
|
projectApiKey: string;
|
|
20
|
+
/**
|
|
21
|
+
* Tenant-specific Hawcx host (for example: https://hawcx-api.hawcx.com).
|
|
22
|
+
* The native SDK appends /hc_auth internally—do not add extra paths.
|
|
23
|
+
*/
|
|
24
|
+
baseUrl?: string;
|
|
20
25
|
oauthConfig?: {
|
|
21
26
|
clientId: string;
|
|
22
27
|
publicKeyPem: string;
|
|
23
28
|
tokenEndpoint: string;
|
|
24
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use root-level `baseUrl` instead. Kept for backward compatibility during migration.
|
|
32
|
+
*/
|
|
25
33
|
endpoints?: {
|
|
26
34
|
authBaseUrl?: string;
|
|
27
35
|
};
|
|
@@ -33,6 +41,21 @@ export type AuthSuccessPayload = {
|
|
|
33
41
|
isLoginFlow: boolean;
|
|
34
42
|
};
|
|
35
43
|
|
|
44
|
+
export type AuthorizationCodePayload = {
|
|
45
|
+
code: string;
|
|
46
|
+
expiresIn?: number;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type AdditionalVerificationPayload = {
|
|
50
|
+
sessionId: string;
|
|
51
|
+
detail?: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type BackendOAuthTokens = {
|
|
55
|
+
accessToken: string;
|
|
56
|
+
refreshToken?: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
36
59
|
export type AuthErrorPayload = {
|
|
37
60
|
code: string;
|
|
38
61
|
message: string;
|
|
@@ -41,6 +64,8 @@ export type AuthErrorPayload = {
|
|
|
41
64
|
export type AuthEvent =
|
|
42
65
|
| { type: 'otp_required' }
|
|
43
66
|
| { type: 'auth_success'; payload: AuthSuccessPayload }
|
|
67
|
+
| { type: 'authorization_code'; payload: AuthorizationCodePayload }
|
|
68
|
+
| { type: 'additional_verification_required'; payload: AdditionalVerificationPayload }
|
|
44
69
|
| { type: 'auth_error'; payload: AuthErrorPayload };
|
|
45
70
|
|
|
46
71
|
export type SessionEvent =
|
|
@@ -63,6 +88,11 @@ type NativeBridge = {
|
|
|
63
88
|
initialize(config: HawcxInitializeConfig): Promise<void>;
|
|
64
89
|
authenticate(userId: string): Promise<void>;
|
|
65
90
|
submitOtp(otp: string): Promise<void>;
|
|
91
|
+
storeBackendOAuthTokens(
|
|
92
|
+
userId: string,
|
|
93
|
+
accessToken: string,
|
|
94
|
+
refreshToken?: string | null,
|
|
95
|
+
): Promise<boolean>;
|
|
66
96
|
getDeviceDetails(): Promise<void>;
|
|
67
97
|
webLogin(pin: string): Promise<void>;
|
|
68
98
|
webApprove(token: string): Promise<void>;
|
|
@@ -99,12 +129,19 @@ const ensureNonEmpty = (value: string, field: string): string => {
|
|
|
99
129
|
return trimmed;
|
|
100
130
|
};
|
|
101
131
|
|
|
132
|
+
const resolveBaseUrl = (config: HawcxInitializeConfig): string => {
|
|
133
|
+
const candidate = config.baseUrl ?? config.endpoints?.authBaseUrl ?? '';
|
|
134
|
+
return ensureNonEmpty(candidate, 'baseUrl');
|
|
135
|
+
};
|
|
136
|
+
|
|
102
137
|
export function initialize(config: HawcxInitializeConfig): Promise<void> {
|
|
103
138
|
try {
|
|
104
139
|
const apiKey = ensureNonEmpty(config.projectApiKey, 'projectApiKey');
|
|
140
|
+
const baseUrl = resolveBaseUrl(config);
|
|
105
141
|
return HawcxReactNative.initialize({
|
|
106
142
|
...config,
|
|
107
143
|
projectApiKey: apiKey,
|
|
144
|
+
baseUrl,
|
|
108
145
|
});
|
|
109
146
|
} catch (error) {
|
|
110
147
|
return Promise.reject(error);
|
|
@@ -127,6 +164,25 @@ export function submitOtp(otp: string): Promise<void> {
|
|
|
127
164
|
}
|
|
128
165
|
}
|
|
129
166
|
|
|
167
|
+
export function storeBackendOAuthTokens(
|
|
168
|
+
userId: string,
|
|
169
|
+
accessToken: string,
|
|
170
|
+
refreshToken?: string,
|
|
171
|
+
): Promise<void> {
|
|
172
|
+
try {
|
|
173
|
+
const trimmedUser = ensureNonEmpty(userId, 'userId');
|
|
174
|
+
const trimmedAccess = ensureNonEmpty(accessToken, 'accessToken');
|
|
175
|
+
const trimmedRefresh = refreshToken?.trim();
|
|
176
|
+
return HawcxReactNative.storeBackendOAuthTokens(
|
|
177
|
+
trimmedUser,
|
|
178
|
+
trimmedAccess,
|
|
179
|
+
trimmedRefresh && trimmedRefresh.length > 0 ? trimmedRefresh : null,
|
|
180
|
+
).then(() => undefined);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
return Promise.reject(error);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
130
186
|
export function getDeviceDetails(): Promise<void> {
|
|
131
187
|
return HawcxReactNative.getDeviceDetails();
|
|
132
188
|
}
|
|
@@ -244,6 +300,8 @@ export class HawcxAuthError extends Error {
|
|
|
244
300
|
|
|
245
301
|
export type HawcxAuthOptions = {
|
|
246
302
|
onOtpRequired?: () => void;
|
|
303
|
+
onAuthorizationCode?: (payload: AuthorizationCodePayload) => void;
|
|
304
|
+
onAdditionalVerificationRequired?: (payload: AdditionalVerificationPayload) => void;
|
|
247
305
|
onEvent?: (event: AuthEvent) => void;
|
|
248
306
|
};
|
|
249
307
|
|
|
@@ -280,6 +338,12 @@ export class HawcxClient {
|
|
|
280
338
|
case 'otp_required':
|
|
281
339
|
options?.onOtpRequired?.();
|
|
282
340
|
break;
|
|
341
|
+
case 'authorization_code':
|
|
342
|
+
options?.onAuthorizationCode?.(event.payload);
|
|
343
|
+
break;
|
|
344
|
+
case 'additional_verification_required':
|
|
345
|
+
options?.onAdditionalVerificationRequired?.(event.payload);
|
|
346
|
+
break;
|
|
283
347
|
case 'auth_success':
|
|
284
348
|
cleanup();
|
|
285
349
|
resolve(event.payload);
|
|
@@ -387,6 +451,10 @@ export class HawcxClient {
|
|
|
387
451
|
addPushListener(handler: (event: PushEvent) => void): EmitterSubscription {
|
|
388
452
|
return addPushListener(handler);
|
|
389
453
|
}
|
|
454
|
+
|
|
455
|
+
storeBackendOAuthTokens(userId: string, tokens: BackendOAuthTokens): Promise<void> {
|
|
456
|
+
return storeBackendOAuthTokens(userId, tokens.accessToken, tokens.refreshToken);
|
|
457
|
+
}
|
|
390
458
|
}
|
|
391
459
|
|
|
392
460
|
export const hawcxClient = new HawcxClient();
|
|
@@ -395,6 +463,8 @@ export type HawcxAuthHookState =
|
|
|
395
463
|
| { status: 'idle' }
|
|
396
464
|
| { status: 'pending' }
|
|
397
465
|
| { status: 'otp'; attempts: number }
|
|
466
|
+
| { status: 'authorization_code'; payload: AuthorizationCodePayload }
|
|
467
|
+
| { status: 'additional_verification_required'; payload: AdditionalVerificationPayload }
|
|
398
468
|
| { status: 'success'; result: AuthSuccessPayload }
|
|
399
469
|
| { status: 'error'; error: AuthErrorPayload };
|
|
400
470
|
|
|
@@ -415,6 +485,17 @@ export function useHawcxAuth(client: HawcxClient = hawcxClient) {
|
|
|
415
485
|
otpAttempts.current += 1;
|
|
416
486
|
setState({ status: 'otp', attempts: otpAttempts.current });
|
|
417
487
|
break;
|
|
488
|
+
case 'authorization_code':
|
|
489
|
+
otpAttempts.current = 0;
|
|
490
|
+
setState({ status: 'authorization_code', payload: event.payload });
|
|
491
|
+
break;
|
|
492
|
+
case 'additional_verification_required':
|
|
493
|
+
otpAttempts.current = 0;
|
|
494
|
+
setState({
|
|
495
|
+
status: 'additional_verification_required',
|
|
496
|
+
payload: event.payload,
|
|
497
|
+
});
|
|
498
|
+
break;
|
|
418
499
|
case 'auth_success':
|
|
419
500
|
otpAttempts.current = 0;
|
|
420
501
|
setState({ status: 'success', result: event.payload });
|