@hawcx/react-native-sdk 1.0.8 → 1.1.1
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 +10 -1
- package/HawcxReactNative.podspec +2 -2
- package/README.md +325 -109
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/hawcx/reactnative/HawcxEventDispatcher.kt +4 -0
- package/android/src/main/java/com/hawcx/reactnative/HawcxReactNativeModule.kt +324 -1
- package/android/src/main/java/com/hawcx/reactnative/v6/HawcxV6Bridge.kt +402 -0
- 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/Info.plist +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.abi.json +22145 -2
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.private.swiftinterface +628 -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 +628 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftmodule +0 -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/Info.plist +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.abi.json +22145 -2
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +628 -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 +628 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftmodule +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json +22145 -2
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +628 -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 +628 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftmodule +0 -0
- package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/_CodeSignature/CodeResources +21 -21
- package/ios/HawcxReactNative.m +56 -0
- package/ios/HawcxReactNative.swift +380 -1
- package/ios/HawcxV6BridgeSupport.swift +468 -0
- package/lib/commonjs/index.js +326 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/v6Normalization.js +325 -0
- package/lib/commonjs/v6Normalization.js.map +1 -0
- package/lib/commonjs/v6State.js +186 -0
- package/lib/commonjs/v6State.js.map +1 -0
- package/lib/commonjs/v6Types.js +2 -0
- package/lib/commonjs/v6Types.js.map +1 -0
- package/lib/commonjs/v6WebLogin.js +101 -0
- package/lib/commonjs/v6WebLogin.js.map +1 -0
- package/lib/module/index.js +287 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/v6Normalization.js +318 -0
- package/lib/module/v6Normalization.js.map +1 -0
- package/lib/module/v6State.js +173 -0
- package/lib/module/v6State.js.map +1 -0
- package/lib/module/v6Types.js +2 -0
- package/lib/module/v6Types.js.map +1 -0
- package/lib/module/v6WebLogin.js +92 -0
- package/lib/module/v6WebLogin.js.map +1 -0
- package/lib/typescript/index.d.ts +83 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/v6Normalization.d.ts +3 -0
- package/lib/typescript/v6Normalization.d.ts.map +1 -0
- package/lib/typescript/v6State.d.ts +13 -0
- package/lib/typescript/v6State.d.ts.map +1 -0
- package/lib/typescript/v6Types.d.ts +157 -0
- package/lib/typescript/v6Types.d.ts.map +1 -0
- package/lib/typescript/v6WebLogin.d.ts +32 -0
- package/lib/typescript/v6WebLogin.d.ts.map +1 -0
- package/package.json +21 -9
- package/src/index.ts +477 -0
- package/src/v6Normalization.ts +356 -0
- package/src/v6State.ts +238 -0
- package/src/v6Types.ts +194 -0
- package/src/v6WebLogin.ts +154 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +0 -2
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
- package/android/gradlew +0 -185
- package/android/gradlew.bat +0 -89
- package/android/libs/hawcx-5.1.4.aar +0 -0
- package/docs/RELEASE.md +0 -129
- package/example/README.md +0 -59
- package/example/android/app/build.gradle +0 -126
- package/example/android/app/debug.keystore +0 -0
- package/example/android/app/proguard-rules.pro +0 -10
- package/example/android/app/src/debug/AndroidManifest.xml +0 -9
- package/example/android/app/src/main/AndroidManifest.xml +0 -27
- package/example/android/app/src/main/java/com/hawcx/example/MainActivity.kt +0 -22
- package/example/android/app/src/main/java/com/hawcx/example/MainApplication.kt +0 -45
- package/example/android/app/src/main/res/drawable/rn_edit_text_material.xml +0 -36
- package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/example/android/app/src/main/res/values/strings.xml +0 -3
- package/example/android/app/src/main/res/values/styles.xml +0 -9
- package/example/android/build.gradle +0 -35
- package/example/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/example/android/gradle/wrapper/gradle-wrapper.properties +0 -7
- package/example/android/gradle.properties +0 -41
- package/example/android/gradlew +0 -249
- package/example/android/gradlew.bat +0 -92
- package/example/android/local.properties +0 -2
- package/example/android/settings.gradle +0 -38
- package/example/app.json +0 -4
- package/example/babel.config.js +0 -3
- package/example/e2e/README.md +0 -17
- package/example/e2e/hawcx-login.yaml +0 -14
- package/example/index.js +0 -5
- package/example/ios/.xcode.env +0 -11
- package/example/ios/HawcxExampleApp/AppDelegate.h +0 -6
- package/example/ios/HawcxExampleApp/AppDelegate.mm +0 -31
- package/example/ios/HawcxExampleApp/Images.xcassets/AppIcon.appiconset/Contents.json +0 -53
- package/example/ios/HawcxExampleApp/Images.xcassets/Contents.json +0 -6
- package/example/ios/HawcxExampleApp/Info.plist +0 -55
- package/example/ios/HawcxExampleApp/LaunchScreen.storyboard +0 -47
- package/example/ios/HawcxExampleApp/PrivacyInfo.xcprivacy +0 -37
- package/example/ios/HawcxExampleApp/main.m +0 -10
- package/example/ios/HawcxExampleApp.xcodeproj/project.pbxproj +0 -704
- package/example/ios/HawcxExampleApp.xcodeproj/project.xcworkspace/xcuserdata/agambhullar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/HawcxExampleApp.xcodeproj/xcshareddata/xcschemes/HawcxExampleApp.xcscheme +0 -90
- package/example/ios/HawcxExampleApp.xcodeproj/xcuserdata/agambhullar.xcuserdatad/xcschemes/xcschememanagement.plist +0 -16
- package/example/ios/HawcxExampleApp.xcworkspace/contents.xcworkspacedata +0 -10
- package/example/ios/HawcxExampleAppTests/HawcxExampleAppTests.m +0 -66
- package/example/ios/HawcxExampleAppTests/Info.plist +0 -24
- package/example/ios/Podfile +0 -79
- package/example/ios/Podfile.lock +0 -1290
- package/example/metro.config.js +0 -16
- package/example/package-lock.json +0 -13220
- package/example/package.json +0 -30
- package/example/src/App.tsx +0 -755
- package/example/src/hawcx.config.ts +0 -25
- package/example/tsconfig.json +0 -8
- package/ios/Frameworks/.keep +0 -0
- package/lib/typescript/__tests__/index.test.d.ts +0 -2
- package/lib/typescript/__tests__/index.test.d.ts.map +0 -1
- package/react_mobile_sdk_plan.md +0 -242
- package/src/__tests__/index.test.ts +0 -206
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
package com.hawcx.reactnative.v6
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.bridge.WritableArray
|
|
6
|
+
import com.facebook.react.bridge.WritableMap
|
|
7
|
+
import com.hawcx.internal.HawcxSDK
|
|
8
|
+
import com.hawcx.protocol.v1.HawcxV1ErrorDetails
|
|
9
|
+
import com.hawcx.protocol.v1.HawcxV1FieldError
|
|
10
|
+
import com.hawcx.protocol.v1.HawcxV1FlowUpdate
|
|
11
|
+
import com.hawcx.protocol.v1.HawcxV1FlowType
|
|
12
|
+
import com.hawcx.protocol.v1.HawcxV1Method
|
|
13
|
+
import com.hawcx.protocol.v1.HawcxV1OAuthCallbackParser
|
|
14
|
+
import com.hawcx.protocol.v1.HawcxV1PromptContext
|
|
15
|
+
import com.hawcx.protocol.v1.HawcxV1QrApprovalOutcome
|
|
16
|
+
import com.hawcx.protocol.v1.HawcxV1QrPayloadParser
|
|
17
|
+
import com.hawcx.protocol.v1.HawcxV1RiskInfo
|
|
18
|
+
import com.hawcx.protocol.v1.HawcxV1RiskLocation
|
|
19
|
+
import com.hawcx.protocol.v1.HawcxV1SDK
|
|
20
|
+
import com.hawcx.protocol.v1.HawcxV1StepInfo
|
|
21
|
+
import com.hawcx.protocol.v1.HawcxV1UserPrompt
|
|
22
|
+
import com.hawcx.reactnative.HawcxEventDispatcher
|
|
23
|
+
import com.hawcx.reactnative.HawcxReactNativeLogger
|
|
24
|
+
|
|
25
|
+
internal data class HawcxV6StartOptions(
|
|
26
|
+
val identifier: String,
|
|
27
|
+
val flowType: HawcxV1FlowType = HawcxV1FlowType.SIGNIN,
|
|
28
|
+
val startToken: String? = null,
|
|
29
|
+
val inviteCode: String? = null,
|
|
30
|
+
val codeChallenge: String? = null
|
|
31
|
+
) {
|
|
32
|
+
companion object {
|
|
33
|
+
fun from(options: ReadableMap): HawcxV6StartOptions {
|
|
34
|
+
val identifier = options.getString("identifier")?.trim().orEmpty()
|
|
35
|
+
require(identifier.isNotEmpty()) { "identifier is required" }
|
|
36
|
+
|
|
37
|
+
val flowType = when (options.getString("flowType")?.trim().orEmpty().ifBlank { "signin" }) {
|
|
38
|
+
"signin" -> HawcxV1FlowType.SIGNIN
|
|
39
|
+
"signup" -> HawcxV1FlowType.SIGNUP
|
|
40
|
+
"account_manage" -> HawcxV1FlowType.ACCOUNT_MANAGE
|
|
41
|
+
else -> throw IllegalArgumentException(
|
|
42
|
+
"flowType must be one of signin, signup, or account_manage"
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return HawcxV6StartOptions(
|
|
47
|
+
identifier = identifier,
|
|
48
|
+
flowType = flowType,
|
|
49
|
+
startToken = options.getOptionalString("startToken"),
|
|
50
|
+
inviteCode = options.getOptionalString("inviteCode"),
|
|
51
|
+
codeChallenge = options.getOptionalString("codeChallenge")
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
internal data class HawcxV6InitializeOptions(
|
|
58
|
+
val relyingParty: String? = null,
|
|
59
|
+
val autoPollApprovals: Boolean = true
|
|
60
|
+
) {
|
|
61
|
+
companion object {
|
|
62
|
+
fun from(config: ReadableMap): HawcxV6InitializeOptions {
|
|
63
|
+
val relyingParty = if (config.hasKey("relyingParty") && !config.isNull("relyingParty")) {
|
|
64
|
+
config.getString("relyingParty")?.trim().takeUnless { it.isNullOrEmpty() }
|
|
65
|
+
} else {
|
|
66
|
+
null
|
|
67
|
+
}
|
|
68
|
+
val autoPollApprovals = if (config.hasKey("autoPollApprovals") && !config.isNull("autoPollApprovals")) {
|
|
69
|
+
config.getBoolean("autoPollApprovals")
|
|
70
|
+
} else {
|
|
71
|
+
true
|
|
72
|
+
}
|
|
73
|
+
return HawcxV6InitializeOptions(
|
|
74
|
+
relyingParty = relyingParty,
|
|
75
|
+
autoPollApprovals = autoPollApprovals
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
internal class HawcxV6Bridge(
|
|
82
|
+
private val eventDispatcher: HawcxEventDispatcher
|
|
83
|
+
) {
|
|
84
|
+
private var sdk: HawcxV1SDK? = null
|
|
85
|
+
|
|
86
|
+
fun configure(legacySdk: HawcxSDK, configId: String, options: HawcxV6InitializeOptions) {
|
|
87
|
+
dispose(resetFlow = true)
|
|
88
|
+
|
|
89
|
+
val sdk = legacySdk.buildProtocolV1Sdk(
|
|
90
|
+
configId = configId,
|
|
91
|
+
relyingParty = options.relyingParty,
|
|
92
|
+
autoPollApprovals = options.autoPollApprovals
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
sdk.flow.onUpdate = { update ->
|
|
96
|
+
val event = HawcxV6FlowEventCodec.encode(update)
|
|
97
|
+
eventDispatcher.emitV6FlowEvent(event.type, event.payload)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.sdk = sdk
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
fun start(options: HawcxV6StartOptions) {
|
|
104
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
105
|
+
sdk.start(
|
|
106
|
+
flowType = options.flowType,
|
|
107
|
+
identifier = options.identifier,
|
|
108
|
+
startToken = options.startToken,
|
|
109
|
+
inviteCode = options.inviteCode,
|
|
110
|
+
codeChallenge = options.codeChallenge
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
fun selectMethod(methodId: String) {
|
|
115
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
116
|
+
sdk.flow.selectMethod(methodId)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fun submitCode(code: String) {
|
|
120
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
121
|
+
sdk.flow.submitCode(code)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fun submitTotp(code: String) {
|
|
125
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
126
|
+
sdk.flow.submitTotp(code)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fun submitPhone(phone: String) {
|
|
130
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
131
|
+
sdk.flow.submitPhone(phone)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
fun resend(): Boolean {
|
|
135
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
136
|
+
return sdk.flow.resend()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
fun poll() {
|
|
140
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
141
|
+
sdk.flow.poll()
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
fun cancel() {
|
|
145
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
146
|
+
sdk.flow.cancel()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
fun reset() {
|
|
150
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
151
|
+
sdk.reset()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fun approveQr(
|
|
155
|
+
rawPayload: String,
|
|
156
|
+
identifier: String,
|
|
157
|
+
rememberDevice: Boolean,
|
|
158
|
+
completion: (Result<HawcxV6QrApprovalResult>) -> Unit
|
|
159
|
+
) {
|
|
160
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
161
|
+
val payload = HawcxV1QrPayloadParser.parse(rawPayload.trim())
|
|
162
|
+
if (payload == null) {
|
|
163
|
+
completion(Result.failure(IllegalArgumentException("rawPayload must be a valid Hawcx QR payload")))
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
val trimmedIdentifier = identifier.trim()
|
|
168
|
+
if (trimmedIdentifier.isEmpty()) {
|
|
169
|
+
completion(Result.failure(IllegalArgumentException("identifier is required")))
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
val service = sdk.createQrApprovalService()
|
|
174
|
+
if (service == null) {
|
|
175
|
+
completion(Result.failure(IllegalStateException("QR approval is unavailable for the current V6 bridge configuration")))
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
service.approve(
|
|
180
|
+
payload = payload,
|
|
181
|
+
identifier = trimmedIdentifier,
|
|
182
|
+
rememberDevice = rememberDevice
|
|
183
|
+
) { result ->
|
|
184
|
+
completion(result.mapCatching { outcome ->
|
|
185
|
+
when (outcome) {
|
|
186
|
+
HawcxV1QrApprovalOutcome.Approved -> HawcxV6QrApprovalResult(
|
|
187
|
+
outcome = "approved",
|
|
188
|
+
payloadType = payload.type.wireValue
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
is HawcxV1QrApprovalOutcome.Bound -> HawcxV6QrApprovalResult(
|
|
192
|
+
outcome = "bound",
|
|
193
|
+
payloadType = payload.type.wireValue,
|
|
194
|
+
userId = outcome.userid
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
fun handleRedirectUrl(url: String) {
|
|
202
|
+
val sdk = requireNotNull(sdk) { "initialize must be called before using V6 bridge methods" }
|
|
203
|
+
val callback = HawcxV1OAuthCallbackParser.parse(url)
|
|
204
|
+
?: throw IllegalArgumentException("url must be a valid V6 OAuth callback URL")
|
|
205
|
+
sdk.flow.oauthCallback(callback.code, callback.state)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
fun dispose(resetFlow: Boolean) {
|
|
209
|
+
val current = sdk ?: return
|
|
210
|
+
current.flow.onUpdate = null
|
|
211
|
+
if (resetFlow) {
|
|
212
|
+
runCatching { current.reset() }
|
|
213
|
+
.onFailure { error ->
|
|
214
|
+
HawcxReactNativeLogger.w("Failed to reset V6 flow during bridge disposal", error)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
sdk = null
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
internal data class HawcxV6QrApprovalResult(
|
|
223
|
+
val outcome: String,
|
|
224
|
+
val payloadType: String,
|
|
225
|
+
val userId: String? = null
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
private data class HawcxV6EventEnvelope(
|
|
229
|
+
val type: String,
|
|
230
|
+
val payload: WritableMap? = null
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
private object HawcxV6FlowEventCodec {
|
|
234
|
+
fun encode(update: HawcxV1FlowUpdate): HawcxV6EventEnvelope {
|
|
235
|
+
return when (update) {
|
|
236
|
+
is HawcxV1FlowUpdate.Idle -> HawcxV6EventEnvelope(type = "idle")
|
|
237
|
+
is HawcxV1FlowUpdate.Loading -> HawcxV6EventEnvelope(
|
|
238
|
+
type = "loading",
|
|
239
|
+
payload = Arguments.createMap().apply {
|
|
240
|
+
update.session?.takeIf { it.isNotBlank() }?.let { putString("session", it) }
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
is HawcxV1FlowUpdate.Prompt -> HawcxV6EventEnvelope(
|
|
245
|
+
type = "prompt",
|
|
246
|
+
payload = encodePromptPayload(update.context, update.prompt)
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
is HawcxV1FlowUpdate.Completed -> HawcxV6EventEnvelope(
|
|
250
|
+
type = "completed",
|
|
251
|
+
payload = Arguments.createMap().apply {
|
|
252
|
+
putString("session", update.session)
|
|
253
|
+
putString("authCode", update.authCode)
|
|
254
|
+
putString("expiresAt", update.expiresAt)
|
|
255
|
+
update.codeVerifier?.let { putString("codeVerifier", it) }
|
|
256
|
+
putString("traceId", update.meta.traceId)
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
is HawcxV1FlowUpdate.Error -> HawcxV6EventEnvelope(
|
|
261
|
+
type = "error",
|
|
262
|
+
payload = Arguments.createMap().apply {
|
|
263
|
+
update.session?.let { putString("session", it) }
|
|
264
|
+
putString("code", update.code)
|
|
265
|
+
update.action?.let { putString("action", it.wireValue) }
|
|
266
|
+
putString("message", update.message)
|
|
267
|
+
putBoolean("retryable", update.retryable)
|
|
268
|
+
update.meta?.traceId?.let { putString("traceId", it) }
|
|
269
|
+
update.details?.let { putMap("details", encodeErrorDetails(it)) }
|
|
270
|
+
}
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private fun encodePromptPayload(
|
|
276
|
+
context: HawcxV1PromptContext,
|
|
277
|
+
prompt: HawcxV1UserPrompt
|
|
278
|
+
): WritableMap {
|
|
279
|
+
return Arguments.createMap().apply {
|
|
280
|
+
putString("session", context.session)
|
|
281
|
+
putString("traceId", context.meta.traceId)
|
|
282
|
+
putString("expiresAt", context.meta.expiresAt)
|
|
283
|
+
context.stepInfo?.let { putMap("step", encodeStepInfo(it)) }
|
|
284
|
+
context.risk?.let { putMap("risk", encodeRiskInfo(it)) }
|
|
285
|
+
context.codeChannel?.takeIf { it.isNotBlank() }?.let { putString("codeChannel", it) }
|
|
286
|
+
putMap("prompt", encodePrompt(prompt))
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private fun encodePrompt(prompt: HawcxV1UserPrompt): WritableMap {
|
|
291
|
+
return Arguments.createMap().apply {
|
|
292
|
+
when (prompt) {
|
|
293
|
+
is HawcxV1UserPrompt.SelectMethod -> {
|
|
294
|
+
putString("type", "select_method")
|
|
295
|
+
putArray("methods", prompt.methods.toWritableArray { encodeMethod(it) })
|
|
296
|
+
prompt.phase?.takeIf { it.isNotBlank() }?.let { putString("phase", it) }
|
|
297
|
+
}
|
|
298
|
+
is HawcxV1UserPrompt.EnterCode -> {
|
|
299
|
+
putString("type", "enter_code")
|
|
300
|
+
putString("destination", prompt.destination)
|
|
301
|
+
prompt.codeLength?.let { putInt("codeLength", it) }
|
|
302
|
+
prompt.codeFormat?.takeIf { it.isNotBlank() }?.let { putString("codeFormat", it) }
|
|
303
|
+
prompt.codeExpiresAt?.takeIf { it.isNotBlank() }?.let { putString("codeExpiresAt", it) }
|
|
304
|
+
prompt.resendAt?.takeIf { it.isNotBlank() }?.let { putString("resendAt", it) }
|
|
305
|
+
}
|
|
306
|
+
HawcxV1UserPrompt.EnterTotp -> {
|
|
307
|
+
putString("type", "enter_totp")
|
|
308
|
+
}
|
|
309
|
+
is HawcxV1UserPrompt.SetupTotp -> {
|
|
310
|
+
putString("type", "setup_totp")
|
|
311
|
+
putString("secret", prompt.secret)
|
|
312
|
+
putString("otpauthUrl", prompt.otpauthUrl)
|
|
313
|
+
prompt.period?.let { putInt("period", it) }
|
|
314
|
+
}
|
|
315
|
+
is HawcxV1UserPrompt.SetupSms -> {
|
|
316
|
+
putString("type", "setup_sms")
|
|
317
|
+
prompt.existingPhone?.takeIf { it.isNotBlank() }?.let { putString("existingPhone", it) }
|
|
318
|
+
}
|
|
319
|
+
is HawcxV1UserPrompt.Redirect -> {
|
|
320
|
+
putString("type", "redirect")
|
|
321
|
+
putString("url", prompt.url)
|
|
322
|
+
prompt.returnScheme?.takeIf { it.isNotBlank() }?.let { putString("returnScheme", it) }
|
|
323
|
+
}
|
|
324
|
+
is HawcxV1UserPrompt.AwaitApproval -> {
|
|
325
|
+
putString("type", "await_approval")
|
|
326
|
+
prompt.qrData?.takeIf { it.isNotBlank() }?.let { putString("qrData", it) }
|
|
327
|
+
putString("expiresAt", prompt.expiresAt)
|
|
328
|
+
putInt("pollInterval", prompt.pollInterval)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private fun encodeMethod(method: HawcxV1Method): WritableMap {
|
|
335
|
+
return Arguments.createMap().apply {
|
|
336
|
+
putString("id", method.id)
|
|
337
|
+
putString("label", method.label)
|
|
338
|
+
method.icon?.takeIf { it.isNotBlank() }?.let { putString("icon", it) }
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private fun encodeStepInfo(stepInfo: HawcxV1StepInfo): WritableMap {
|
|
343
|
+
return Arguments.createMap().apply {
|
|
344
|
+
putString("id", stepInfo.id)
|
|
345
|
+
stepInfo.label?.takeIf { it.isNotBlank() }?.let { putString("label", it) }
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private fun encodeRiskInfo(risk: HawcxV1RiskInfo): WritableMap {
|
|
350
|
+
return Arguments.createMap().apply {
|
|
351
|
+
putBoolean("detected", risk.detected)
|
|
352
|
+
putArray("reasons", risk.reasons.toStringArray())
|
|
353
|
+
risk.message?.takeIf { it.isNotBlank() }?.let { putString("message", it) }
|
|
354
|
+
risk.location?.let { putMap("location", encodeRiskLocation(it)) }
|
|
355
|
+
risk.riskScore?.let { putDouble("riskScore", it) }
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private fun encodeRiskLocation(location: HawcxV1RiskLocation): WritableMap {
|
|
360
|
+
return Arguments.createMap().apply {
|
|
361
|
+
location.city?.takeIf { it.isNotBlank() }?.let { putString("city", it) }
|
|
362
|
+
location.country?.takeIf { it.isNotBlank() }?.let { putString("country", it) }
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
private fun encodeErrorDetails(details: HawcxV1ErrorDetails): WritableMap {
|
|
367
|
+
return Arguments.createMap().apply {
|
|
368
|
+
details.retryAfterSeconds?.let { putInt("retryAfterSeconds", it) }
|
|
369
|
+
details.retryAt?.takeIf { it.isNotBlank() }?.let { putString("retryAt", it) }
|
|
370
|
+
details.attemptsRemaining?.let { putInt("attemptsRemaining", it) }
|
|
371
|
+
details.errors?.takeIf { it.isNotEmpty() }?.let {
|
|
372
|
+
putArray("errors", it.toWritableArray(::encodeFieldError))
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
private fun encodeFieldError(error: HawcxV1FieldError): WritableMap {
|
|
378
|
+
return Arguments.createMap().apply {
|
|
379
|
+
putString("field", error.field)
|
|
380
|
+
putString("message", error.message)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private fun <T> List<T>.toWritableArray(transform: (T) -> WritableMap): WritableArray {
|
|
385
|
+
return Arguments.createArray().apply {
|
|
386
|
+
forEach { pushMap(transform(it)) }
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
private fun List<String>.toStringArray(): WritableArray {
|
|
391
|
+
return Arguments.createArray().apply {
|
|
392
|
+
this@toStringArray.forEach { pushString(it) }
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private fun ReadableMap.getOptionalString(key: String): String? {
|
|
398
|
+
if (!hasKey(key) || isNull(key)) {
|
|
399
|
+
return null
|
|
400
|
+
}
|
|
401
|
+
return getString(key)?.trim()?.takeUnless { it.isEmpty() }
|
|
402
|
+
}
|
|
@@ -8,32 +8,32 @@
|
|
|
8
8
|
<key>BinaryPath</key>
|
|
9
9
|
<string>HawcxFramework.framework/HawcxFramework</string>
|
|
10
10
|
<key>LibraryIdentifier</key>
|
|
11
|
-
<string>ios-
|
|
11
|
+
<string>ios-arm64</string>
|
|
12
12
|
<key>LibraryPath</key>
|
|
13
13
|
<string>HawcxFramework.framework</string>
|
|
14
14
|
<key>SupportedArchitectures</key>
|
|
15
15
|
<array>
|
|
16
16
|
<string>arm64</string>
|
|
17
|
-
<string>x86_64</string>
|
|
18
17
|
</array>
|
|
19
18
|
<key>SupportedPlatform</key>
|
|
20
19
|
<string>ios</string>
|
|
21
|
-
<key>SupportedPlatformVariant</key>
|
|
22
|
-
<string>simulator</string>
|
|
23
20
|
</dict>
|
|
24
21
|
<dict>
|
|
25
22
|
<key>BinaryPath</key>
|
|
26
23
|
<string>HawcxFramework.framework/HawcxFramework</string>
|
|
27
24
|
<key>LibraryIdentifier</key>
|
|
28
|
-
<string>ios-
|
|
25
|
+
<string>ios-arm64_x86_64-simulator</string>
|
|
29
26
|
<key>LibraryPath</key>
|
|
30
27
|
<string>HawcxFramework.framework</string>
|
|
31
28
|
<key>SupportedArchitectures</key>
|
|
32
29
|
<array>
|
|
33
30
|
<string>arm64</string>
|
|
31
|
+
<string>x86_64</string>
|
|
34
32
|
</array>
|
|
35
33
|
<key>SupportedPlatform</key>
|
|
36
34
|
<string>ios</string>
|
|
35
|
+
<key>SupportedPlatformVariant</key>
|
|
36
|
+
<string>simulator</string>
|
|
37
37
|
</dict>
|
|
38
38
|
</array>
|
|
39
39
|
<key>CFBundlePackageType</key>
|