@hawcx/react-native-sdk 1.0.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.
Files changed (100) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/HawcxReactNative.podspec +25 -0
  3. package/LICENSE +21 -0
  4. package/README.md +109 -0
  5. package/docs/RELEASE.md +119 -0
  6. package/example/README.md +59 -0
  7. package/example/android/app/build.gradle +126 -0
  8. package/example/android/app/debug.keystore +0 -0
  9. package/example/android/app/proguard-rules.pro +10 -0
  10. package/example/android/app/src/debug/AndroidManifest.xml +9 -0
  11. package/example/android/app/src/main/AndroidManifest.xml +27 -0
  12. package/example/android/app/src/main/java/com/hawcx/example/MainActivity.kt +22 -0
  13. package/example/android/app/src/main/java/com/hawcx/example/MainApplication.kt +45 -0
  14. package/example/android/app/src/main/res/drawable/rn_edit_text_material.xml +36 -0
  15. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  16. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  17. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  18. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  19. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  20. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  21. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  22. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  23. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  24. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  25. package/example/android/app/src/main/res/values/strings.xml +3 -0
  26. package/example/android/app/src/main/res/values/styles.xml +9 -0
  27. package/example/android/build.gradle +23 -0
  28. package/example/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  29. package/example/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  30. package/example/android/gradle.properties +41 -0
  31. package/example/android/gradlew +249 -0
  32. package/example/android/gradlew.bat +92 -0
  33. package/example/android/local.properties +2 -0
  34. package/example/android/settings.gradle +4 -0
  35. package/example/app.json +4 -0
  36. package/example/babel.config.js +3 -0
  37. package/example/e2e/README.md +17 -0
  38. package/example/e2e/hawcx-login.yaml +14 -0
  39. package/example/index.js +5 -0
  40. package/example/ios/.xcode.env +11 -0
  41. package/example/ios/HawcxExampleApp/AppDelegate.h +6 -0
  42. package/example/ios/HawcxExampleApp/AppDelegate.mm +31 -0
  43. package/example/ios/HawcxExampleApp/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  44. package/example/ios/HawcxExampleApp/Images.xcassets/Contents.json +6 -0
  45. package/example/ios/HawcxExampleApp/Info.plist +55 -0
  46. package/example/ios/HawcxExampleApp/LaunchScreen.storyboard +47 -0
  47. package/example/ios/HawcxExampleApp/PrivacyInfo.xcprivacy +37 -0
  48. package/example/ios/HawcxExampleApp/main.m +10 -0
  49. package/example/ios/HawcxExampleApp.xcodeproj/project.pbxproj +704 -0
  50. package/example/ios/HawcxExampleApp.xcodeproj/project.xcworkspace/xcuserdata/agambhullar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  51. package/example/ios/HawcxExampleApp.xcodeproj/xcshareddata/xcschemes/HawcxExampleApp.xcscheme +90 -0
  52. package/example/ios/HawcxExampleApp.xcodeproj/xcuserdata/agambhullar.xcuserdatad/xcschemes/xcschememanagement.plist +16 -0
  53. package/example/ios/HawcxExampleApp.xcworkspace/contents.xcworkspacedata +10 -0
  54. package/example/ios/HawcxExampleAppTests/HawcxExampleAppTests.m +66 -0
  55. package/example/ios/HawcxExampleAppTests/Info.plist +24 -0
  56. package/example/ios/Podfile +55 -0
  57. package/example/ios/Podfile.lock +1290 -0
  58. package/example/metro.config.js +16 -0
  59. package/example/package-lock.json +13220 -0
  60. package/example/package.json +30 -0
  61. package/example/src/App.tsx +552 -0
  62. package/example/src/hawcx.config.ts +41 -0
  63. package/example/tsconfig.json +8 -0
  64. package/ios/Frameworks/.keep +0 -0
  65. package/ios/Frameworks/HawcxFramework.xcframework/Info.plist +44 -0
  66. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/HawcxFramework +0 -0
  67. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Headers/HawcxFramework.h +16 -0
  68. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Info.plist +0 -0
  69. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.abi.json +9794 -0
  70. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.private.swiftinterface +302 -0
  71. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  72. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftinterface +302 -0
  73. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/module.modulemap +6 -0
  74. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/HawcxFramework +0 -0
  75. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Headers/HawcxFramework.h +16 -0
  76. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Info.plist +0 -0
  77. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.abi.json +9794 -0
  78. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +302 -0
  79. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  80. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftinterface +302 -0
  81. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json +9794 -0
  82. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +302 -0
  83. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  84. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +302 -0
  85. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/module.modulemap +6 -0
  86. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/_CodeSignature/CodeResources +234 -0
  87. package/ios/HawcxReactNative.m +51 -0
  88. package/ios/HawcxReactNative.swift +311 -0
  89. package/lib/commonjs/index.js +404 -0
  90. package/lib/commonjs/index.js.map +1 -0
  91. package/lib/module/index.js +375 -0
  92. package/lib/module/index.js.map +1 -0
  93. package/lib/typescript/__tests__/index.test.d.ts +2 -0
  94. package/lib/typescript/__tests__/index.test.d.ts.map +1 -0
  95. package/lib/typescript/index.d.ts +151 -0
  96. package/lib/typescript/index.d.ts.map +1 -0
  97. package/package.json +72 -0
  98. package/react_mobile_sdk_plan.md +240 -0
  99. package/src/__tests__/index.test.ts +163 -0
  100. package/src/index.ts +518 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## [1.0.1] - 2025-11-17
4
+ - Point native Android/iOS SDKs at new production authentication endpoint
5
+ - Refresh bundled Hawcx Android/iOS binaries for the 1.0.1 cut
6
+ - Harden linting by guarding React imports when running CocoaPods validation
7
+
8
+ ## [0.0.1] - 2025-11-15
9
+ - Initial React Native bridge for Hawcx V5 authentication
10
+ - Added HawcxClient helpers, hooks, push support, and example app
@@ -0,0 +1,25 @@
1
+ require 'json'
2
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
3
+
4
+ Pod::Spec.new do |s|
5
+ s.name = 'HawcxReactNative'
6
+ s.version = package['version']
7
+ s.summary = 'React Native bindings for the Hawcx V5 mobile authentication framework.'
8
+ s.description = <<-DESC
9
+ Production-grade React Native bridge that wraps HawcxFramework (iOS) to expose
10
+ V5 authentication, OTP, push, and web session flows to JavaScript callers.
11
+ DESC
12
+ s.homepage = 'https://github.com/hawcx/react-native-sdk'
13
+ s.license = { :type => 'MIT', :file => 'LICENSE' }
14
+ s.author = { 'Hawcx Engineering' => 'engineering@hawcx.com' }
15
+ s.source = { :git => 'https://github.com/hawcx/react-native-sdk.git', :tag => "v#{s.version}" }
16
+
17
+ s.platform = :ios, '17.5'
18
+ s.swift_version = '5.9'
19
+
20
+ s.source_files = 'ios/**/*.{h,m,mm,swift}'
21
+ s.exclude_files = 'ios/Frameworks/**/*.h'
22
+ s.vendored_frameworks = 'ios/Frameworks/HawcxFramework.xcframework'
23
+
24
+ s.dependency 'React-Core'
25
+ end
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Hawcx
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # Hawcx React Native SDK (iOS)
2
+
3
+ This package provides the React Native wrapper for the Hawcx V5 mobile authentication framework. It reuses the production iOS implementation (`dev_ios/ios_sdk/HawcxFramework`) and exposes a typed JavaScript/TypeScript API for React Native applications.
4
+
5
+ ## Repository Layout
6
+ - `src/` – TypeScript entry point and public API surface.
7
+ - `ios/` – Native bridge sources (Swift) plus the Podspec that embeds `HawcxFramework`.
8
+ - `android/` – React Native Android bridge module (Gradle library) plus the bundled Hawcx SDK AAR.
9
+ - `example/` – Runnable React Native demo app using the SDK (`npm install` -> `npm run ios`).
10
+ - `react_mobile_sdk_plan.md` – Detailed delivery plan and progress tracker. **Always read and update this file when working on the SDK.**
11
+
12
+ ## Scripts
13
+ | Command | Description |
14
+ | --- | --- |
15
+ | `npm run clean` | Removes the build output under `lib/`. |
16
+ | `npm run lint` | Runs ESLint using the React Native + TypeScript rules. |
17
+ | `npm run typecheck` | Executes the TypeScript compiler in `--noEmit` mode. |
18
+ | `npm run build` | Builds distributable bundles via `react-native-builder-bob`. |
19
+
20
+ > Note: Dependencies are declared in `package.json` but not yet installed. Install them once local tooling is in place (`npm install`).
21
+
22
+ ## Android Module (WIP)
23
+ - `android/` hosts the Gradle-based library that React Native autolinks for Android builds. It already references the Hawcx Android SDK via `android/libs/hawcx-5.1.0.aar` and exposes `./gradlew` helpers for linting/publishing.
24
+ - Run Gradle tasks from the repo root with `./gradlew -p android <task>` (for example, `./gradlew -p android :hawcxreactnative:lintRelease`). The first invocation requires network/Gradle cache access for AGP + React Native dependencies.
25
+ - The bridge mirrors the iOS surface: `initialize`, `authenticate`, OTP/session helpers, push lifecycle (`setApnsDeviceToken` on iOS, `setFcmToken` on Android), and emits the same `hawcx.*` events for auth/session/push updates.
26
+ - Android builds require `android/local.properties` pointing at your Android SDK (`sdk.dir=/Users/<you>/Library/Android/sdk`) and target `minSdkVersion` 26 to match the Hawcx AAR.
27
+
28
+ ### Refreshing the Hawcx Android SDK AAR
29
+ 1. Build the native Android SDK (`cd ~/dev_android/android_sdk && ./gradlew :app:assembleRelease`).
30
+ 2. Copy the generated `app/build/outputs/aar/hawcx-<version>.aar` into `android/libs/`, replacing the existing binary.
31
+ 3. Update any documentation or release notes (e.g., `react_mobile_sdk_plan.md`, `CHANGELOG.md`) to reflect the new Hawcx SDK version.
32
+
33
+ ## Usage (WIP)
34
+
35
+ ```ts
36
+ import {
37
+ initialize,
38
+ authenticate,
39
+ submitOtp,
40
+ addAuthListener,
41
+ hawcxClient,
42
+ useHawcxAuth,
43
+ useHawcxWebLogin,
44
+ } from '@hawcx/react-native-sdk';
45
+
46
+ await initialize({ projectApiKey: 'YOUR_PROJECT_KEY' });
47
+
48
+ const subscription = addAuthListener(event => {
49
+ switch (event.type) {
50
+ case 'otp_required':
51
+ // show OTP UI
52
+ break;
53
+ case 'auth_success':
54
+ console.log('Login success', event.payload);
55
+ break;
56
+ case 'auth_error':
57
+ console.error('Auth failed', event.payload.message);
58
+ break;
59
+ }
60
+ });
61
+
62
+ await authenticate('user@example.com');
63
+ await submitOtp('123456');
64
+
65
+ subscription.remove();
66
+
67
+ // HawcxClient helper
68
+ const { promise } = hawcxClient.authenticate('user@example.com', {
69
+ onOtpRequired: () => console.log('show OTP UI'),
70
+ });
71
+ const result = await promise; // -> { accessToken?, refreshToken?, isLoginFlow }
72
+
73
+ // React hook example
74
+ function AuthScreen() {
75
+ const { state, authenticate, submitOtp } = useHawcxAuth();
76
+
77
+ const start = () => authenticate('user@example.com');
78
+ const sendOtp = (otp: string) => submitOtp(otp);
79
+
80
+ return null;
81
+ }
82
+
83
+ function WebLoginScreen() {
84
+ const { state, webLogin, webApprove, getDeviceDetails } = useHawcxWebLogin();
85
+
86
+ const validatePin = (pin: string) => webLogin(pin);
87
+ const approveSession = (token: string) => webApprove(token);
88
+ const refreshDevices = () => getDeviceDetails();
89
+
90
+ return null;
91
+ }
92
+ ```
93
+
94
+ ## Example App & E2E
95
+ - `cd example && npm install` to bootstrap the sample app.
96
+ - Edit `example/src/hawcx.config.ts` with your project API key plus the OAuth client ID, token endpoint, and PEM from `dev_ios/ios_demo_dev`, then run `npm run ios` or `npm run android`.
97
+ - Use `example/e2e/hawcx-login.yaml` with [Maestro](https://maestro.mobile.dev/) to drive a smoke test through OTP login. Adjust selectors to match your bundle ID and UI tweaks.
98
+
99
+ ## Release Process
100
+ Review `docs/RELEASE.md` before publishing. In short:
101
+ 1. Run `npm run lint && npm run typecheck && npm test && npm run build`.
102
+ 2. Update `package.json` + `CHANGELOG.md`.
103
+ 3. Smoke test the example app.
104
+ 4. `npm publish --access public` and `pod repo push trunk HawcxReactNative.podspec`.
105
+ 5. Tag the repo (`git tag vX.Y.Z && git push origin --tags`).
106
+
107
+ ## Next Steps
108
+ 1. Follow `react_mobile_sdk_plan.md` Phase 1+ to implement the native bridge and JS API.
109
+ 2. Keep this README updated with integration steps and release instructions as the SDK matures.
@@ -0,0 +1,119 @@
1
+ # Hawcx React Native SDK Release Guide
2
+
3
+ This document outlines every command, directory, and deliverable required to publish `@hawcx/react-native-sdk` to npm and CocoaPods, tag the release, and hand it off to a customer.
4
+
5
+ ## Prerequisites
6
+ - **npm access**
7
+ 1. Create or use your npmjs.com account.
8
+ 2. Ask an org admin to invite that account to the Hawcx org.
9
+ 3. In the repo root run `npm login` and enter the same username/password + OTP.
10
+ 4. Verify the session any time with `npm whoami`.
11
+ - **CocoaPods trunk access**
12
+ 1. Ensure CocoaPods is installed (`sudo gem install cocoapods`).
13
+ 2. Register once: `pod trunk register you@hawcx.com "Your Name" --description='Hawcx laptop'`.
14
+ 3. Click the verification email from CocoaPods.
15
+ 4. Confirm you’re logged in with `pod trunk me` (shows your sessions).
16
+ - Local environment with Xcode, npm, CocoaPods, and the Hawcx backend dev environment.
17
+ - Clean working tree (`git status` should show no uncommitted changes apart from the release bump you are making).
18
+
19
+ > All commands are run from the repo root (`~/dev_react`) unless a different directory is explicitly mentioned.
20
+
21
+ ## Step-by-step Release Process
22
+
23
+ 1. **Sync and verify**
24
+ ```bash
25
+ git checkout main
26
+ git pull origin main
27
+ git status
28
+ ```
29
+ Ensure only intentional release edits are showing as modified.
30
+
31
+ 2. **Run quality gates (repo root)**
32
+ ```bash
33
+ npm install # ensures deps are fresh
34
+ npm run lint
35
+ npm run typecheck
36
+ npm test
37
+ npm run build # produces lib/
38
+ ./gradlew -p android clean lintRelease testReleaseUnitTest assembleRelease publishToMavenLocal
39
+ pod lib lint HawcxReactNative.podspec
40
+ ```
41
+ - `./gradlew … publishToMavenLocal` validates the Android bridge (with the bundled Hawcx AAR) builds and can be published.
42
+ - `pod lib lint` confirms the Podspec + `HawcxFramework.xcframework` remain valid.
43
+
44
+ 3. **Update version + changelog (repo root)**
45
+ - Edit `package.json` → bump `version` (run `npm install` afterward so `package-lock.json` picks up the new number).
46
+ - Update `android/build.gradle`’s fallback `version` string and `example/package.json` (re-run `npm install` inside `example/` so its lockfile updates).
47
+ - Run `pod install` in `example/ios/` to refresh `Podfile.lock` with the new pod version.
48
+ - Update `CHANGELOG.md` with a new entry (features, fixes, dates, links).
49
+ - Commit these edits once testing passes:
50
+ ```bash
51
+ git add package.json package-lock.json android/build.gradle example/package.json example/package-lock.json example/ios/Podfile.lock CHANGELOG.md
52
+ git commit -m "chore: release vX.Y.Z"
53
+ ```
54
+ Include refreshed native artifacts (`ios/Frameworks/*.xcframework`, `android/libs/*.aar`) in the same commit when they change.
55
+
56
+ 4. **Smoke test the example app**
57
+ ```bash
58
+ cd example
59
+ npm install
60
+ npm run ios
61
+ npm run android
62
+ # Use your dev credentials in example/src/hawcx.config.ts
63
+ cd ..
64
+ ```
65
+ - For Android push validation, drop `google-services.json` under `example/android/app/` and use the push harness card to approve/decline a login request.
66
+ - Resolve any runtime issues before publishing.
67
+
68
+ 5. **Publish to npm (repo root)**
69
+ ```bash
70
+ npm publish --access public
71
+ ```
72
+ Share the published version number with the team.
73
+
74
+ 6. **Publish CocoaPods spec (repo root)**
75
+ ```bash
76
+ pod repo push trunk HawcxReactNative.podspec --allow-warnings
77
+ ```
78
+ Ensure the command finishes without validation errors. If you have trouble with trunk authentication, re-run `pod trunk register`.
79
+
80
+ 7. **Tag and push the release (repo root)**
81
+ ```bash
82
+ git tag vX.Y.Z
83
+ git push origin main
84
+ git push origin vX.Y.Z
85
+ ```
86
+ This creates a signed reference for future diffs.
87
+
88
+ 8. **Customer handoff checklist**
89
+ - Provide the npm version (`@hawcx/react-native-sdk@X.Y.Z`).
90
+ - For iOS, instruct them to run `pod install` after adding the dependency (Podspec is available once trunk syncs).
91
+ - For Android, emphasize that the Hawcx AAR ships inside the npm package—no manual drag/drop is needed. Running `npx pod-install` / Gradle sync is sufficient.
92
+ - Share `README.md` + `example/src/hawcx.config.ts` as guidance for wiring their project key + OAuth values.
93
+ - **Maintainer note:** if the native SDKs change, rebuild and copy the binaries before releasing:
94
+ - **iOS:** rebuild `HawcxFramework.xcframework`, copy it into `ios/Frameworks/`, bump the Podspec version if required, and re-run this release flow.
95
+ - **Android:** assemble the new `hawcx-*.aar` (`dev_android/android_sdk`), copy it into `android/libs/`, update docs/plan, then re-run this release flow.
96
+
97
+ ## Future updates / redeployments
98
+ - Follow the same steps above for each change: bump the version, re-run quality gates, update changelog, publish to npm + trunk, tag, and notify.
99
+ - If the native iOS SDK is updated (new `HawcxFramework.xcframework`), copy it into `ios/Frameworks/`, update `HawcxReactNative.podspec` if needed, and repeat the release flow.
100
+ - Keep `react_mobile_sdk_plan.md` updated with new tasks/decisions so the next engineer understands why the release was cut.
101
+
102
+ ## How customers consume the SDK
103
+ 1. **npm**
104
+ In their React Native project root:
105
+ ```bash
106
+ npm install @hawcx/react-native-sdk@X.Y.Z
107
+ ```
108
+ 2. **iOS pods**
109
+ In their `ios/` folder (after installing npm deps):
110
+ ```bash
111
+ cd ios
112
+ pod install
113
+ ```
114
+ 3. **Initialize the bridge**
115
+ Copy the pattern from `example/src/hawcx.config.ts` to pass their project API key + OAuth config into `initialize()`. The README in this repo explains every exported API (`initialize`, hooks, push helpers, etc.).
116
+
117
+ Following this doc from top to bottom ensures the SDK release, npm publish, Podspec publish, git tagging, and customer delivery are handled consistently.
118
+
119
+ Capture any issues in the changelog and notify the team once the release is live.
@@ -0,0 +1,59 @@
1
+ # Hawcx React Native SDK Example
2
+
3
+ This example demonstrates the cross-platform APIs exported by `@hawcx/react-native-sdk`. It mirrors the flows in the native reference apps (email/OTP login, web PIN validation, and manual push approvals) so you can validate your Hawcx project keys on both iOS and Android.
4
+
5
+ ## Getting Started
6
+
7
+ 1. Install dependencies:
8
+ ```bash
9
+ cd example
10
+ npm install
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.
13
+ 3. **iOS only:** install pods:
14
+ ```bash
15
+ cd ios && pod install && cd ..
16
+ ```
17
+ 4. **Android (optional push support):**
18
+ - Create a Firebase project and enable Cloud Messaging.
19
+ - Download `google-services.json` and drop it into `android/app/`. The Gradle script automatically applies the Google Services plugin when this file exists.
20
+ - If you want to drive push approvals end-to-end, wire your push provider to send Hawcx payloads (see the push harness card in the app for the expected fields).
21
+ 5. Launch the app:
22
+ ```bash
23
+ npm run ios
24
+ # or
25
+ npm run android
26
+ ```
27
+
28
+ ## What It Demonstrates
29
+ - `initialize()` via `hawcx.config.ts` so you can flip credentials without editing the UI.
30
+ - `useHawcxAuth` hook for login + OTP entry.
31
+ - `useHawcxWebLogin` to validate QR/PIN flows.
32
+ - Manual push harness that lets you:
33
+ - Register APNs bytes (iOS) or an FCM token (Android) via `setPushDeviceToken`.
34
+ - Forward arbitrary push payload JSON to the native SDK and see emitted `hawcx.push.event` logs.
35
+ - Approve or decline login requests by submitting the `request_id`.
36
+ - Logging card with an on/off switch so you can inspect auth/session/push events directly in the UI.
37
+
38
+ ## Push Harness Tips
39
+ - On Android, paste the FCM token string and tap **Register Token** followed by **Notify Authenticated** once the user completes login. This calls `setFcmToken` + `userDidAuthenticate` so Hawcx can register for approvals.
40
+ - On iOS, enter the APNs device token as a comma-separated list of byte values (e.g., `42, 13, 255, ...`). The helper converts it into the byte array expected by `setApnsDeviceToken`.
41
+ - Use the payload editor to paste the JSON delivered by Hawcx push notifications—at minimum it must include `request_id`, `ip_address`, `deviceInfo`, and `timestamp`.
42
+
43
+ ## E2E Harness (Maestro)
44
+ `e2e/hawcx-login.yaml` is a starting point for automated smoke tests:
45
+ 1. Launches the sample app (`appId: com.hawcx.example`)
46
+ 2. Types an email address
47
+ 3. Taps **Authenticate**
48
+ 4. Waits for the OTP prompt to appear
49
+
50
+ Run it on either platform:
51
+ ```bash
52
+ # iOS Simulator example
53
+ maestro test e2e/hawcx-login.yaml
54
+
55
+ # Android emulator example
56
+ maestro test --device emulator-5554 e2e/hawcx-login.yaml
57
+ ```
58
+
59
+ Customize the selectors, credentials, and OTP handling to match your environment. This same flow can be extended to cover push approvals, PIN validation, and regression checks on error states.
@@ -0,0 +1,126 @@
1
+ apply plugin: "com.android.application"
2
+ apply plugin: "org.jetbrains.kotlin.android"
3
+ apply plugin: "com.facebook.react"
4
+
5
+ /**
6
+ * This is the configuration block to customize your React Native Android app.
7
+ * By default you don't need to apply any configuration, just uncomment the lines you need.
8
+ */
9
+ react {
10
+ /* Folders */
11
+ // The root of your project, i.e. where "package.json" lives. Default is '..'
12
+ // root = file("../")
13
+ // The folder where the react-native NPM package is. Default is ../node_modules/react-native
14
+ // reactNativeDir = file("../node_modules/react-native")
15
+ // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
16
+ // codegenDir = file("../node_modules/@react-native/codegen")
17
+ // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
18
+ // cliFile = file("../node_modules/react-native/cli.js")
19
+
20
+ /* Variants */
21
+ // The list of variants to that are debuggable. For those we're going to
22
+ // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
23
+ // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
24
+ // debuggableVariants = ["liteDebug", "prodDebug"]
25
+
26
+ /* Bundling */
27
+ // A list containing the node command and its flags. Default is just 'node'.
28
+ // nodeExecutableAndArgs = ["node"]
29
+ //
30
+ // The command to run when bundling. By default is 'bundle'
31
+ // bundleCommand = "ram-bundle"
32
+ //
33
+ // The path to the CLI configuration file. Default is empty.
34
+ // bundleConfig = file(../rn-cli.config.js)
35
+ //
36
+ // The name of the generated asset file containing your JS bundle
37
+ // bundleAssetName = "MyApplication.android.bundle"
38
+ //
39
+ // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
40
+ // entryFile = file("../js/MyApplication.android.js")
41
+ //
42
+ // A list of extra flags to pass to the 'bundle' commands.
43
+ // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
44
+ // extraPackagerArgs = []
45
+
46
+ /* Hermes Commands */
47
+ // The hermes compiler command to run. By default it is 'hermesc'
48
+ // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
49
+ //
50
+ // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
51
+ // hermesFlags = ["-O", "-output-source-map"]
52
+ }
53
+
54
+ /**
55
+ * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
56
+ */
57
+ def enableProguardInReleaseBuilds = false
58
+
59
+ /**
60
+ * The preferred build flavor of JavaScriptCore (JSC)
61
+ *
62
+ * For example, to use the international variant, you can use:
63
+ * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
64
+ *
65
+ * The international variant includes ICU i18n library and necessary data
66
+ * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
67
+ * give correct results when using with locales other than en-US. Note that
68
+ * this variant is about 6MiB larger per architecture than default.
69
+ */
70
+ def jscFlavor = 'org.webkit:android-jsc:+'
71
+
72
+ android {
73
+ ndkVersion rootProject.ext.ndkVersion
74
+ buildToolsVersion rootProject.ext.buildToolsVersion
75
+ compileSdk rootProject.ext.compileSdkVersion
76
+
77
+ namespace "com.hawcx.example"
78
+ defaultConfig {
79
+ applicationId "com.hawcx.example"
80
+ minSdkVersion rootProject.ext.minSdkVersion
81
+ targetSdkVersion rootProject.ext.targetSdkVersion
82
+ versionCode 1
83
+ versionName "1.0"
84
+ }
85
+ signingConfigs {
86
+ debug {
87
+ storeFile file('debug.keystore')
88
+ storePassword 'android'
89
+ keyAlias 'androiddebugkey'
90
+ keyPassword 'android'
91
+ }
92
+ }
93
+ buildTypes {
94
+ debug {
95
+ signingConfig signingConfigs.debug
96
+ }
97
+ release {
98
+ // Caution! In production, you need to generate your own keystore file.
99
+ // see https://reactnative.dev/docs/signed-apk-android.
100
+ signingConfig signingConfigs.debug
101
+ minifyEnabled enableProguardInReleaseBuilds
102
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
103
+ }
104
+ }
105
+ }
106
+
107
+ dependencies {
108
+ // The version of react-native is set by the React Native Gradle Plugin
109
+ implementation("com.facebook.react:react-android")
110
+ implementation("com.facebook.react:flipper-integration")
111
+ implementation(platform("com.google.firebase:firebase-bom:33.1.1"))
112
+ implementation("com.google.firebase:firebase-messaging")
113
+
114
+ if (hermesEnabled.toBoolean()) {
115
+ implementation("com.facebook.react:hermes-android")
116
+ } else {
117
+ implementation jscFlavor
118
+ }
119
+ }
120
+
121
+ apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
122
+
123
+ def googleServicesFile = file("$projectDir/google-services.json")
124
+ if (googleServicesFile.exists()) {
125
+ apply plugin: "com.google.gms.google-services"
126
+ }
@@ -0,0 +1,10 @@
1
+ # Add project specific ProGuard rules here.
2
+ # By default, the flags in this file are appended to flags specified
3
+ # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4
+ # You can edit the include path and order by changing the proguardFiles
5
+ # directive in build.gradle.
6
+ #
7
+ # For more details, see
8
+ # http://developer.android.com/guide/developing/tools/proguard.html
9
+
10
+ # Add any project specific keep options here:
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ xmlns:tools="http://schemas.android.com/tools">
4
+
5
+ <application
6
+ android:usesCleartextTraffic="true"
7
+ tools:targetApi="28"
8
+ tools:ignore="GoogleAppIndexingWarning"/>
9
+ </manifest>
@@ -0,0 +1,27 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ xmlns:tools="http://schemas.android.com/tools">
3
+
4
+ <uses-permission android:name="android.permission.INTERNET" />
5
+
6
+ <application
7
+ android:name=".MainApplication"
8
+ android:label="@string/app_name"
9
+ android:icon="@mipmap/ic_launcher"
10
+ android:roundIcon="@mipmap/ic_launcher_round"
11
+ android:allowBackup="false"
12
+ android:theme="@style/AppTheme"
13
+ tools:replace="android:allowBackup,android:theme">
14
+ <activity
15
+ android:name=".MainActivity"
16
+ android:label="@string/app_name"
17
+ android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
18
+ android:launchMode="singleTask"
19
+ android:windowSoftInputMode="adjustResize"
20
+ android:exported="true">
21
+ <intent-filter>
22
+ <action android:name="android.intent.action.MAIN" />
23
+ <category android:name="android.intent.category.LAUNCHER" />
24
+ </intent-filter>
25
+ </activity>
26
+ </application>
27
+ </manifest>
@@ -0,0 +1,22 @@
1
+ package com.hawcx.example
2
+
3
+ import com.facebook.react.ReactActivity
4
+ import com.facebook.react.ReactActivityDelegate
5
+ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
6
+ import com.facebook.react.defaults.DefaultReactActivityDelegate
7
+
8
+ class MainActivity : ReactActivity() {
9
+
10
+ /**
11
+ * Returns the name of the main component registered from JavaScript. This is used to schedule
12
+ * rendering of the component.
13
+ */
14
+ override fun getMainComponentName(): String = "HawcxExampleApp"
15
+
16
+ /**
17
+ * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
18
+ * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
19
+ */
20
+ override fun createReactActivityDelegate(): ReactActivityDelegate =
21
+ DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
22
+ }
@@ -0,0 +1,45 @@
1
+ package com.hawcx.example
2
+
3
+ import android.app.Application
4
+ import com.facebook.react.PackageList
5
+ import com.facebook.react.ReactApplication
6
+ import com.facebook.react.ReactHost
7
+ import com.facebook.react.ReactNativeHost
8
+ import com.facebook.react.ReactPackage
9
+ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
10
+ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
11
+ import com.facebook.react.defaults.DefaultReactNativeHost
12
+ import com.facebook.react.flipper.ReactNativeFlipper
13
+ import com.facebook.soloader.SoLoader
14
+
15
+ class MainApplication : Application(), ReactApplication {
16
+
17
+ override val reactNativeHost: ReactNativeHost =
18
+ object : DefaultReactNativeHost(this) {
19
+ override fun getPackages(): List<ReactPackage> =
20
+ PackageList(this).packages.apply {
21
+ // Packages that cannot be autolinked yet can be added manually here, for example:
22
+ // add(MyReactNativePackage())
23
+ }
24
+
25
+ override fun getJSMainModuleName(): String = "index"
26
+
27
+ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
28
+
29
+ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
30
+ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
31
+ }
32
+
33
+ override val reactHost: ReactHost
34
+ get() = getDefaultReactHost(this.applicationContext, reactNativeHost)
35
+
36
+ override fun onCreate() {
37
+ super.onCreate()
38
+ SoLoader.init(this, false)
39
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
40
+ // If you opted-in for the New Architecture, we load the native entry point for this app.
41
+ load()
42
+ }
43
+ ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
44
+ }
45
+ }
@@ -0,0 +1,36 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Copyright (C) 2014 The Android Open Source Project
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ -->
16
+ <inset xmlns:android="http://schemas.android.com/apk/res/android"
17
+ android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
18
+ android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
19
+ android:insetTop="@dimen/abc_edit_text_inset_top_material"
20
+ android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
21
+
22
+ <selector>
23
+ <!--
24
+ This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
25
+ The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
26
+ NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
27
+
28
+ <item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
29
+
30
+ For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
31
+ -->
32
+ <item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
33
+ <item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
34
+ </selector>
35
+
36
+ </inset>