@hawcx/react-native-sdk 1.0.2 → 1.0.4

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 (51) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/README.md +6 -1
  3. package/android/build.gradle +145 -0
  4. package/android/consumer-rules.pro +2 -0
  5. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  6. package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  7. package/android/gradle.properties +5 -0
  8. package/android/gradlew +185 -0
  9. package/android/gradlew.bat +89 -0
  10. package/android/libs/hawcx-5.1.1.aar +0 -0
  11. package/android/settings.gradle +53 -0
  12. package/android/src/main/AndroidManifest.xml +4 -0
  13. package/android/src/main/java/com/hawcx/reactnative/AuthCallbackProxy.kt +53 -0
  14. package/android/src/main/java/com/hawcx/reactnative/HawcxEventDispatcher.kt +43 -0
  15. package/android/src/main/java/com/hawcx/reactnative/HawcxReactNativeLogger.kt +19 -0
  16. package/android/src/main/java/com/hawcx/reactnative/HawcxReactNativeModule.kt +387 -0
  17. package/android/src/main/java/com/hawcx/reactnative/HawcxReactNativePackage.kt +16 -0
  18. package/android/src/main/java/com/hawcx/reactnative/PushDelegateProxy.kt +31 -0
  19. package/android/src/main/java/com/hawcx/reactnative/SessionCallbackProxy.kt +35 -0
  20. package/docs/RELEASE.md +13 -2
  21. package/example/README.md +1 -1
  22. package/example/android/build.gradle +12 -0
  23. package/example/android/settings.gradle +34 -0
  24. package/example/ios/HawcxExampleApp.xcodeproj/project.xcworkspace/xcuserdata/agambhullar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  25. package/example/ios/Podfile.lock +2 -2
  26. package/example/package-lock.json +3 -3
  27. package/example/package.json +1 -1
  28. package/example/src/hawcx.config.ts +7 -1
  29. package/ios/Frameworks/HawcxFramework.xcframework/Info.plist +5 -5
  30. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/HawcxFramework +0 -0
  31. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.abi.json +12 -258
  32. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.private.swiftinterface +1 -1
  33. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftinterface +1 -1
  34. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/HawcxFramework +0 -0
  35. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.abi.json +12 -258
  36. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +1 -1
  37. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftinterface +1 -1
  38. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json +12 -258
  39. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +1 -1
  40. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +1 -1
  41. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/_CodeSignature/CodeResources +16 -16
  42. package/ios/HawcxReactNative.swift +23 -1
  43. package/lib/commonjs/index.js +8 -2
  44. package/lib/commonjs/index.js.map +1 -1
  45. package/lib/module/index.js +8 -2
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/typescript/index.d.ts +8 -0
  48. package/lib/typescript/index.d.ts.map +1 -1
  49. package/package.json +2 -1
  50. package/src/__tests__/index.test.ts +4 -0
  51. package/src/index.ts +20 -3
@@ -0,0 +1,387 @@
1
+ package com.hawcx.reactnative
2
+
3
+ import android.os.Handler
4
+ import android.os.Looper
5
+ import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.bridge.Promise
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
9
+ import com.facebook.react.bridge.ReactMethod
10
+ import com.facebook.react.bridge.ReadableMap
11
+ import com.facebook.react.module.annotations.ReactModule
12
+ import com.hawcx.internal.HawcxSDK
13
+ import com.hawcx.utils.AuthV5Callback
14
+
15
+ internal const val AUTH_EVENT_NAME = "hawcx.auth.event"
16
+ internal const val SESSION_EVENT_NAME = "hawcx.session.event"
17
+ internal const val PUSH_EVENT_NAME = "hawcx.push.event"
18
+
19
+ @ReactModule(name = HawcxReactNativeModule.NAME)
20
+ class HawcxReactNativeModule(reactContext: ReactApplicationContext) :
21
+ ReactContextBaseJavaModule(reactContext) {
22
+
23
+ companion object {
24
+ const val NAME = "HawcxReactNative"
25
+ private const val CODE_CONFIG = "hawcx.config"
26
+ private const val CODE_SDK = "hawcx.sdk"
27
+ private const val CODE_INPUT = "hawcx.input"
28
+ private const val CODE_STORAGE = "hawcx.storage"
29
+ }
30
+
31
+ private val mainHandler = Handler(Looper.getMainLooper())
32
+ private val applicationContext = reactApplicationContext.applicationContext
33
+
34
+ private val eventDispatcher = HawcxEventDispatcher(reactApplicationContext)
35
+
36
+ @Volatile
37
+ private var hawcxSDK: HawcxSDK? = null
38
+ @Volatile
39
+ private var authCallbackProxy: AuthV5Callback? = null
40
+ @Volatile
41
+ private var sessionCallbackProxy: SessionCallbackProxy? = null
42
+ @Volatile
43
+ private var pushDelegateProxy: PushDelegateProxy? = null
44
+
45
+ override fun getName(): String = NAME
46
+
47
+ @ReactMethod
48
+ fun initialize(config: ReadableMap?, promise: Promise) {
49
+ val configMap = config ?: run {
50
+ promise.reject(CODE_CONFIG, "initialize requires a configuration map")
51
+ return
52
+ }
53
+
54
+ val projectApiKey = configMap.getString("projectApiKey")?.trim().orEmpty()
55
+ if (projectApiKey.isEmpty()) {
56
+ promise.reject(CODE_CONFIG, "projectApiKey is required")
57
+ return
58
+ }
59
+
60
+ val baseUrl = when {
61
+ configMap.hasKey("baseUrl") && !configMap.isNull("baseUrl") ->
62
+ configMap.getString("baseUrl")?.trim().orEmpty()
63
+ configMap.hasKey("endpoints") && !configMap.isNull("endpoints") -> {
64
+ configMap.getMap("endpoints")?.getString("authBaseUrl")?.trim().orEmpty()
65
+ }
66
+ else -> ""
67
+ }
68
+
69
+ if (baseUrl.isEmpty()) {
70
+ promise.reject(CODE_CONFIG, "baseUrl is required")
71
+ return
72
+ }
73
+
74
+ if (configMap.hasKey("oauthConfig") && !configMap.isNull("oauthConfig")) {
75
+ HawcxReactNativeLogger.w(
76
+ "oauthConfig was provided but the Android SDK no longer accepts client credentials on-device. " +
77
+ "Remove this field from initialize()."
78
+ )
79
+ }
80
+
81
+ runOnUiThread {
82
+ try {
83
+ val sdk = HawcxSDK(
84
+ context = applicationContext,
85
+ projectApiKey = projectApiKey,
86
+ baseUrl = baseUrl
87
+ )
88
+ hawcxSDK = sdk
89
+ val authProxy = AuthCallbackProxy(eventDispatcher)
90
+ val sessionProxy = SessionCallbackProxy(eventDispatcher)
91
+ val pushProxy = PushDelegateProxy(eventDispatcher)
92
+ authCallbackProxy = authProxy
93
+ sessionCallbackProxy = sessionProxy
94
+ pushDelegateProxy = pushProxy
95
+ sdk.pushAuthDelegate = pushProxy
96
+ promise.resolve(null)
97
+ } catch (error: Exception) {
98
+ promise.reject(CODE_SDK, error.message, error)
99
+ }
100
+ }
101
+ }
102
+
103
+ @ReactMethod
104
+ fun authenticate(userId: String?, promise: Promise) {
105
+ val sdk = hawcxSDK ?: run {
106
+ promise.reject(CODE_SDK, "initialize must be called before authenticate")
107
+ return
108
+ }
109
+ val callback = authCallbackProxy ?: run {
110
+ promise.reject(CODE_SDK, "Auth callback not configured")
111
+ return
112
+ }
113
+ val sanitizedUserId = userId?.trim().orEmpty()
114
+ if (sanitizedUserId.isEmpty()) {
115
+ promise.reject(CODE_INPUT, "userId cannot be empty")
116
+ return
117
+ }
118
+
119
+ runOnUiThread {
120
+ sdk.authenticateV5(sanitizedUserId, callback)
121
+ promise.resolve(null)
122
+ }
123
+ }
124
+
125
+ @ReactMethod
126
+ fun submitOtp(otp: String?, promise: Promise) {
127
+ val sdk = hawcxSDK ?: run {
128
+ promise.reject(CODE_SDK, "initialize must be called before submitOtp")
129
+ return
130
+ }
131
+ val sanitizedOtp = otp?.trim().orEmpty()
132
+ if (sanitizedOtp.isEmpty()) {
133
+ promise.reject(CODE_INPUT, "otp cannot be empty")
134
+ return
135
+ }
136
+
137
+ runOnUiThread {
138
+ sdk.submitOtpV5(sanitizedOtp)
139
+ promise.resolve(null)
140
+ }
141
+ }
142
+
143
+ @ReactMethod
144
+ fun getDeviceDetails(promise: Promise) {
145
+ val sdk = hawcxSDK ?: run {
146
+ promise.reject(CODE_SDK, "initialize must be called before getDeviceDetails")
147
+ return
148
+ }
149
+ val callback = sessionCallbackProxy ?: run {
150
+ promise.reject(CODE_SDK, "Session callback not configured")
151
+ return
152
+ }
153
+
154
+ runOnUiThread {
155
+ sdk.getDeviceDetails(callback)
156
+ promise.resolve(null)
157
+ }
158
+ }
159
+
160
+ @ReactMethod
161
+ fun webLogin(pin: String?, promise: Promise) {
162
+ val sdk = hawcxSDK ?: run {
163
+ promise.reject(CODE_SDK, "initialize must be called before webLogin")
164
+ return
165
+ }
166
+ val callback = sessionCallbackProxy ?: run {
167
+ promise.reject(CODE_SDK, "Session callback not configured")
168
+ return
169
+ }
170
+ val sanitizedPin = pin?.trim().orEmpty()
171
+ if (sanitizedPin.isEmpty()) {
172
+ promise.reject(CODE_INPUT, "pin cannot be empty")
173
+ return
174
+ }
175
+
176
+ runOnUiThread {
177
+ sdk.webLogin(sanitizedPin, callback)
178
+ promise.resolve(null)
179
+ }
180
+ }
181
+
182
+ @ReactMethod
183
+ fun webApprove(token: String?, promise: Promise) {
184
+ val sdk = hawcxSDK ?: run {
185
+ promise.reject(CODE_SDK, "initialize must be called before webApprove")
186
+ return
187
+ }
188
+ val callback = sessionCallbackProxy ?: run {
189
+ promise.reject(CODE_SDK, "Session callback not configured")
190
+ return
191
+ }
192
+ val sanitizedToken = token?.trim().orEmpty()
193
+ if (sanitizedToken.isEmpty()) {
194
+ promise.reject(CODE_INPUT, "token cannot be empty")
195
+ return
196
+ }
197
+
198
+ runOnUiThread {
199
+ sdk.webApprove(sanitizedToken, callback)
200
+ promise.resolve(null)
201
+ }
202
+ }
203
+
204
+ @ReactMethod
205
+ fun storeBackendOAuthTokens(userId: String?, accessToken: String?, refreshToken: String?, promise: Promise) {
206
+ val sdk = hawcxSDK ?: run {
207
+ promise.reject(CODE_SDK, "initialize must be called before storeBackendOAuthTokens")
208
+ return
209
+ }
210
+ val trimmedUser = userId?.trim().orEmpty()
211
+ if (trimmedUser.isEmpty()) {
212
+ promise.reject(CODE_INPUT, "userId cannot be empty")
213
+ return
214
+ }
215
+
216
+ val trimmedAccess = accessToken?.trim().orEmpty()
217
+ if (trimmedAccess.isEmpty()) {
218
+ promise.reject(CODE_INPUT, "accessToken cannot be empty")
219
+ return
220
+ }
221
+
222
+ val refresh = refreshToken?.trim().orEmpty().ifBlank { null }
223
+
224
+ runCatching {
225
+ sdk.storeBackendOAuthTokens(
226
+ accessToken = trimmedAccess,
227
+ refreshToken = refresh,
228
+ userId = trimmedUser
229
+ )
230
+ }.onSuccess { stored ->
231
+ if (stored) {
232
+ promise.resolve(true)
233
+ } else {
234
+ promise.reject(CODE_STORAGE, "Failed to persist backend-issued tokens")
235
+ }
236
+ }.onFailure { error ->
237
+ promise.reject(CODE_STORAGE, error.message, error)
238
+ }
239
+ }
240
+
241
+ @ReactMethod
242
+ fun getLastLoggedInUser(promise: Promise) {
243
+ val sdk = hawcxSDK ?: run {
244
+ promise.reject(CODE_SDK, "initialize must be called before getLastLoggedInUser")
245
+ return
246
+ }
247
+ promise.resolve(sdk.getLastLoggedInUser())
248
+ }
249
+
250
+ @ReactMethod
251
+ fun clearSessionTokens(userId: String?, promise: Promise) {
252
+ val sdk = hawcxSDK ?: run {
253
+ promise.reject(CODE_SDK, "initialize must be called before clearSessionTokens")
254
+ return
255
+ }
256
+ val sanitizedUserId = userId?.trim().orEmpty()
257
+ if (sanitizedUserId.isEmpty()) {
258
+ promise.reject(CODE_INPUT, "userId cannot be empty")
259
+ return
260
+ }
261
+
262
+ runOnUiThread {
263
+ sdk.clearSessionTokens(sanitizedUserId)
264
+ promise.resolve(null)
265
+ }
266
+ }
267
+
268
+ @ReactMethod
269
+ fun clearUserKeychainData(userId: String?, promise: Promise) {
270
+ val sdk = hawcxSDK ?: run {
271
+ promise.reject(CODE_SDK, "initialize must be called before clearUserKeychainData")
272
+ return
273
+ }
274
+ val sanitizedUserId = userId?.trim().orEmpty()
275
+ if (sanitizedUserId.isEmpty()) {
276
+ promise.reject(CODE_INPUT, "userId cannot be empty")
277
+ return
278
+ }
279
+
280
+ runOnUiThread {
281
+ sdk.clearUserKeychainData(sanitizedUserId)
282
+ promise.resolve(null)
283
+ }
284
+ }
285
+
286
+ @ReactMethod
287
+ fun setFcmToken(token: String?, promise: Promise) {
288
+ val sdk = hawcxSDK ?: run {
289
+ promise.reject(CODE_SDK, "initialize must be called before setFcmToken")
290
+ return
291
+ }
292
+ val sanitizedToken = token?.trim().orEmpty()
293
+ if (sanitizedToken.isEmpty()) {
294
+ promise.reject(CODE_INPUT, "token cannot be empty")
295
+ return
296
+ }
297
+ runOnUiThread {
298
+ sdk.setFcmToken(sanitizedToken)
299
+ promise.resolve(null)
300
+ }
301
+ }
302
+
303
+ @ReactMethod
304
+ fun userDidAuthenticate(promise: Promise) {
305
+ val sdk = hawcxSDK ?: run {
306
+ promise.reject(CODE_SDK, "initialize must be called before userDidAuthenticate")
307
+ return
308
+ }
309
+ runOnUiThread {
310
+ sdk.userDidAuthenticate()
311
+ promise.resolve(null)
312
+ }
313
+ }
314
+
315
+ @ReactMethod
316
+ fun handlePushNotification(payload: ReadableMap?, promise: Promise) {
317
+ val sdk = hawcxSDK ?: run {
318
+ promise.reject(CODE_SDK, "initialize must be called before handlePushNotification")
319
+ return
320
+ }
321
+ val payloadMap = payload ?: run {
322
+ promise.reject(CODE_INPUT, "payload is required")
323
+ return
324
+ }
325
+
326
+ val stringMap = mutableMapOf<String, String>()
327
+ payloadMap.toHashMap().forEach { (key, value) ->
328
+ val valueString = value?.toString()
329
+ if (valueString != null) {
330
+ stringMap[key] = valueString
331
+ }
332
+ }
333
+
334
+ runOnUiThread {
335
+ sdk.handlePushNotification(stringMap)
336
+ promise.resolve(stringMap.containsKey("request_id"))
337
+ }
338
+ }
339
+
340
+ @ReactMethod
341
+ fun approvePushRequest(requestId: String?, promise: Promise) {
342
+ val sdk = hawcxSDK ?: run {
343
+ promise.reject(CODE_SDK, "initialize must be called before approvePushRequest")
344
+ return
345
+ }
346
+ val sanitizedId = requestId?.trim().orEmpty()
347
+ if (sanitizedId.isEmpty()) {
348
+ promise.reject(CODE_INPUT, "requestId cannot be empty")
349
+ return
350
+ }
351
+ sdk.approveLoginRequest(sanitizedId) { error ->
352
+ if (error == null) {
353
+ promise.resolve(null)
354
+ } else {
355
+ promise.reject(CODE_SDK, error.message, error)
356
+ }
357
+ }
358
+ }
359
+
360
+ @ReactMethod
361
+ fun declinePushRequest(requestId: String?, promise: Promise) {
362
+ val sdk = hawcxSDK ?: run {
363
+ promise.reject(CODE_SDK, "initialize must be called before declinePushRequest")
364
+ return
365
+ }
366
+ val sanitizedId = requestId?.trim().orEmpty()
367
+ if (sanitizedId.isEmpty()) {
368
+ promise.reject(CODE_INPUT, "requestId cannot be empty")
369
+ return
370
+ }
371
+ sdk.declineLoginRequest(sanitizedId) { error ->
372
+ if (error == null) {
373
+ promise.resolve(null)
374
+ } else {
375
+ promise.reject(CODE_SDK, error.message, error)
376
+ }
377
+ }
378
+ }
379
+
380
+ private fun runOnUiThread(block: () -> Unit) {
381
+ if (Looper.getMainLooper() == Looper.myLooper()) {
382
+ block()
383
+ } else {
384
+ mainHandler.post(block)
385
+ }
386
+ }
387
+ }
@@ -0,0 +1,16 @@
1
+ package com.hawcx.reactnative
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class HawcxReactNativePackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
+ return listOf(HawcxReactNativeModule(reactContext))
11
+ }
12
+
13
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
14
+ return emptyList()
15
+ }
16
+ }
@@ -0,0 +1,31 @@
1
+ package com.hawcx.reactnative
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.hawcx.model.PushLoginRequestDetails
5
+ import com.hawcx.utils.HawcxPushAuthDelegate
6
+
7
+ internal class PushDelegateProxy(
8
+ private val dispatcher: HawcxEventDispatcher
9
+ ) : HawcxPushAuthDelegate {
10
+
11
+ override fun hawcx(didReceiveLoginRequest: String, details: PushLoginRequestDetails) {
12
+ val payload = Arguments.createMap().apply {
13
+ putString("requestId", didReceiveLoginRequest)
14
+ putString("ipAddress", details.ipAddress)
15
+ putString("deviceInfo", details.deviceInfo)
16
+ putString("timestamp", details.timestamp)
17
+ if (!details.location.isNullOrBlank()) {
18
+ putString("location", details.location)
19
+ }
20
+ }
21
+ dispatcher.emitPushEvent("push_login_request", payload)
22
+ }
23
+
24
+ override fun hawcx(failedToFetchLoginRequestDetails: Throwable) {
25
+ val payload = Arguments.createMap().apply {
26
+ putString("code", "push_error")
27
+ putString("message", failedToFetchLoginRequestDetails.message ?: "Failed to fetch login request details")
28
+ }
29
+ dispatcher.emitPushEvent("push_error", payload)
30
+ }
31
+ }
@@ -0,0 +1,35 @@
1
+ package com.hawcx.reactnative
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.hawcx.utils.DevSessionCallback
5
+ import com.hawcx.utils.WebLoginCallback
6
+ import com.hawcx.utils.WebLoginError
7
+
8
+ internal class SessionCallbackProxy(
9
+ private val dispatcher: HawcxEventDispatcher
10
+ ) : DevSessionCallback, WebLoginCallback {
11
+
12
+ override fun onSuccess() {
13
+ dispatcher.emitSessionEvent("session_success")
14
+ }
15
+
16
+ override fun onError() {
17
+ dispatcher.emitSessionEvent(
18
+ "session_error",
19
+ Arguments.createMap().apply {
20
+ putString("code", "session_error")
21
+ putString("message", "Failed to fetch device session")
22
+ }
23
+ )
24
+ }
25
+
26
+ override fun onError(webLoginErrorCode: WebLoginError, errorMessage: String) {
27
+ dispatcher.emitSessionEvent(
28
+ "session_error",
29
+ Arguments.createMap().apply {
30
+ putString("code", webLoginErrorCode.name)
31
+ putString("message", errorMessage)
32
+ }
33
+ )
34
+ }
35
+ }
package/docs/RELEASE.md CHANGED
@@ -36,11 +36,13 @@ This document outlines every command, directory, and deliverable required to pub
36
36
  npm test
37
37
  npm run build # produces lib/
38
38
  ./gradlew -p android clean lintRelease testReleaseUnitTest assembleRelease publishToMavenLocal
39
+ Ensure to udpate api("api.hawcx:hawcx:5.1.1") version in dev_react/android/build.gradle if android aar file version changed
40
+ Then run ./gradlew clean assembleRelease --refresh-dependencies to test if android picks up new aar maven release
39
41
  pod lib lint HawcxReactNative.podspec
40
42
  ```
41
43
  - `./gradlew … publishToMavenLocal` validates the Android bridge (with the bundled Hawcx AAR) builds and can be published.
42
44
  - `pod lib lint` confirms the Podspec + `HawcxFramework.xcframework` remain valid.
43
-
45
+
44
46
  3. **Update version + changelog (repo root)**
45
47
  - Edit `package.json` → bump `version` (run `npm install` afterward so `package-lock.json` picks up the new number).
46
48
  - Update `android/build.gradle`’s fallback `version` string and `example/package.json` (re-run `npm install` inside `example/` so its lockfile updates).
@@ -54,10 +56,19 @@ This document outlines every command, directory, and deliverable required to pub
54
56
  Include refreshed native artifacts (`ios/Frameworks/*.xcframework`, `android/libs/*.aar`) in the same commit when they change.
55
57
 
56
58
  4. **Smoke test the example app**
59
+
60
+ rm -rf ~/Library/Developer/Xcode/DerivedData/HawcxExampleApp*
61
+
57
62
  ```bash
58
63
  cd example
59
64
  npm install
60
- npm run ios
65
+ For ios:
66
+ cd example/ios: pod install
67
+ cd ..
68
+ npm run ios or npm run ios -- --no-packager
69
+ For android:
70
+ cd example/android: ./gradlew clean
71
+ cd ..
61
72
  npm run android
62
73
  # Use your dev credentials in example/src/hawcx.config.ts
63
74
  cd ..
package/example/README.md CHANGED
@@ -9,7 +9,7 @@ This example demonstrates the cross-platform APIs exported by `@hawcx/react-nati
9
9
  cd example
10
10
  npm install
11
11
  ```
12
- 2. Configure credentials in `src/hawcx.config.ts`. The file ships with dev defaults—replace the API key and OAuth values with your own.
12
+ 2. Configure credentials in `src/hawcx.config.ts`. The file ships with dev defaults—replace the API key **and** `HAWCX_BASE_URL` host with your tenant’s values.
13
13
  3. **iOS only:** install pods:
14
14
  ```bash
15
15
  cd ios && pod install && cd ..
@@ -21,3 +21,15 @@ buildscript {
21
21
  }
22
22
 
23
23
  apply plugin: "com.facebook.react.rootproject"
24
+
25
+ subprojects { subproject ->
26
+ subproject.configurations.all { config ->
27
+ config.resolutionStrategy.eachDependency { details ->
28
+ if (details.requested.group == "androidx.core" &&
29
+ (details.requested.name == "core" || details.requested.name == "core-ktx")) {
30
+ details.useVersion("1.13.1")
31
+ details.because("core-ktx 1.16.0 requires compileSdk/AGP 35+, but the demo targets 34/AGP 8.1.1")
32
+ }
33
+ }
34
+ }
35
+ }
@@ -1,3 +1,37 @@
1
+ import org.gradle.api.initialization.resolve.RepositoriesMode
2
+
3
+ dependencyResolutionManagement {
4
+ repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
5
+ repositories {
6
+ google()
7
+ mavenCentral()
8
+ maven { url = uri("https://www.jitpack.io") }
9
+ maven {
10
+ url = uri("https://raw.githubusercontent.com/hawcx/hawcx_android_sdk/main/maven")
11
+ content {
12
+ includeGroup("api.hawcx")
13
+ }
14
+ metadataSources {
15
+ mavenPom()
16
+ artifact()
17
+ }
18
+ }
19
+ def localHawcxRepo = new File(rootDir, "../../../prod_android/hawcx_android_sdk/maven")
20
+ if (localHawcxRepo.exists()) {
21
+ maven {
22
+ url = localHawcxRepo.toURI()
23
+ content {
24
+ includeGroup("api.hawcx")
25
+ }
26
+ metadataSources {
27
+ mavenPom()
28
+ artifact()
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+
1
35
  rootProject.name = 'com.hawcx.example'
2
36
  apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3
37
  include ':app'
@@ -11,7 +11,7 @@ PODS:
11
11
  - ReactCommon/turbomodule/core (= 0.73.9)
12
12
  - fmt (6.2.1)
13
13
  - glog (0.3.5)
14
- - HawcxReactNative (1.0.2):
14
+ - HawcxReactNative (1.0.4):
15
15
  - React-Core
16
16
  - hermes-engine (0.73.9):
17
17
  - hermes-engine/Pre-built (= 0.73.9)
@@ -1236,7 +1236,7 @@ SPEC CHECKSUMS:
1236
1236
  FBReactNativeSpec: 4fe1d8c2fadc7949344b197d933f76b40401aac5
1237
1237
  fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
1238
1238
  glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
1239
- HawcxReactNative: f27677aa2158f6d4a0e76629d1776a2e86cda742
1239
+ HawcxReactNative: 089e5e5b790f77ab853f4ff96723c8dd7ad1a02c
1240
1240
  hermes-engine: ed62e0dcd013bf4a3b487f164feec1c4e705b5b5
1241
1241
  libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
1242
1242
  RCT-Folly: cd21f1661364f975ae76b3308167ad66b09f53f5
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "hawcx-react-native-sdk-example",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "hawcx-react-native-sdk-example",
9
- "version": "1.0.2",
9
+ "version": "1.0.4",
10
10
  "dependencies": {
11
11
  "@hawcx/react-native-sdk": "file:..",
12
12
  "react": "18.2.0",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "..": {
31
31
  "name": "@hawcx/react-native-sdk",
32
- "version": "1.0.2",
32
+ "version": "1.0.4",
33
33
  "license": "MIT",
34
34
  "devDependencies": {
35
35
  "@react-native/eslint-config": "^0.74.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hawcx-react-native-sdk-example",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "start": "react-native start",
@@ -4,15 +4,21 @@ import type { HawcxInitializeConfig } from '@hawcx/react-native-sdk';
4
4
  * Populate the API key locally for testing or use the in-app form.
5
5
  * Leaving it blank ensures we never ship real credentials in git history.
6
6
  */
7
- export const HAWCX_PROJECT_API_KEY = 'YOUR_API_KEY';
7
+ export const HAWCX_PROJECT_API_KEY = 'ceasar2';
8
+ export const HAWCX_BASE_URL = 'https://ceasar-api.hawcx.com';
8
9
 
9
10
  const buildDefaultConfig = (): HawcxInitializeConfig | null => {
10
11
  const trimmedKey = HAWCX_PROJECT_API_KEY.trim();
11
12
  if (!trimmedKey) {
12
13
  return null;
13
14
  }
15
+ const trimmedBase = HAWCX_BASE_URL.trim();
16
+ if (!trimmedBase) {
17
+ return null;
18
+ }
14
19
  return {
15
20
  projectApiKey: trimmedKey,
21
+ baseUrl: trimmedBase,
16
22
  };
17
23
  };
18
24
 
@@ -8,32 +8,32 @@
8
8
  <key>BinaryPath</key>
9
9
  <string>HawcxFramework.framework/HawcxFramework</string>
10
10
  <key>LibraryIdentifier</key>
11
- <string>ios-arm64_x86_64-simulator</string>
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-arm64</string>
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>