@bota.dev/react-native-app-sdk 2.0.0-beta.0

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 (173) hide show
  1. package/BotaDeviceSDK.podspec +55 -0
  2. package/LICENSE +21 -0
  3. package/README.md +101 -0
  4. package/android/build.gradle +76 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidDevices.kt +172 -0
  7. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidLifecycle.kt +100 -0
  8. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidLogs.kt +82 -0
  9. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidModels.kt +476 -0
  10. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidOTA.kt +58 -0
  11. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordingUploads.kt +180 -0
  12. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordings.kt +751 -0
  13. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidSecurity.kt +509 -0
  14. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidWiFi.kt +125 -0
  15. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKEncryptedUploadV2Materials.kt +46 -0
  16. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKModule.kt +723 -0
  17. package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKPackage.kt +33 -0
  18. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidDevicesTest.kt +211 -0
  19. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidLifecycleTest.kt +132 -0
  20. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidLogsTest.kt +57 -0
  21. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidOTATest.kt +75 -0
  22. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordingUploadsTest.kt +147 -0
  23. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordingsTest.kt +355 -0
  24. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidSecurityTest.kt +523 -0
  25. package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidWiFiTest.kt +100 -0
  26. package/generated/codegen-contract.json +3593 -0
  27. package/ios/BotaDeviceSDK.mm +1300 -0
  28. package/ios/BotaDeviceSDKAppleBridge.swift +2260 -0
  29. package/ios/BotaDeviceSDKAppleDevices.swift +191 -0
  30. package/ios/BotaDeviceSDKAppleLifecycle.swift +167 -0
  31. package/ios/BotaDeviceSDKAppleLogs.swift +79 -0
  32. package/ios/BotaDeviceSDKAppleOTA.swift +73 -0
  33. package/ios/BotaDeviceSDKAppleRecordingUploads.swift +178 -0
  34. package/ios/BotaDeviceSDKAppleRecordings.swift +670 -0
  35. package/ios/BotaDeviceSDKAppleSecurity.swift +586 -0
  36. package/ios/BotaDeviceSDKAppleWiFi.swift +128 -0
  37. package/ios/BotaDeviceSDKEncryptedUploadV2Materials.swift +99 -0
  38. package/lib/commonjs/BotaClient.js +194 -0
  39. package/lib/commonjs/BotaClient.js.map +1 -0
  40. package/lib/commonjs/ble/constants.js +10 -0
  41. package/lib/commonjs/ble/constants.js.map +1 -0
  42. package/lib/commonjs/ble/deviceLogs.js +50 -0
  43. package/lib/commonjs/ble/deviceLogs.js.map +1 -0
  44. package/lib/commonjs/cache/DeviceStateCache.js +6 -0
  45. package/lib/commonjs/cache/DeviceStateCache.js.map +1 -0
  46. package/lib/commonjs/client.js +746 -0
  47. package/lib/commonjs/client.js.map +1 -0
  48. package/lib/commonjs/compatibility/runtime.js +44 -0
  49. package/lib/commonjs/compatibility/runtime.js.map +1 -0
  50. package/lib/commonjs/index.js +123 -0
  51. package/lib/commonjs/index.js.map +1 -0
  52. package/lib/commonjs/managers/DeviceManager.js +647 -0
  53. package/lib/commonjs/managers/DeviceManager.js.map +1 -0
  54. package/lib/commonjs/managers/OTAManager.js +140 -0
  55. package/lib/commonjs/managers/OTAManager.js.map +1 -0
  56. package/lib/commonjs/managers/RecordingManager.js +444 -0
  57. package/lib/commonjs/managers/RecordingManager.js.map +1 -0
  58. package/lib/commonjs/managers/StreamingSession.js +175 -0
  59. package/lib/commonjs/managers/StreamingSession.js.map +1 -0
  60. package/lib/commonjs/managers/types.js +6 -0
  61. package/lib/commonjs/managers/types.js.map +1 -0
  62. package/lib/commonjs/models/Device.js +2 -0
  63. package/lib/commonjs/models/Device.js.map +1 -0
  64. package/lib/commonjs/models/Recording.js +2 -0
  65. package/lib/commonjs/models/Recording.js.map +1 -0
  66. package/lib/commonjs/models/Status.js +6 -0
  67. package/lib/commonjs/models/Status.js.map +1 -0
  68. package/lib/commonjs/package.json +1 -0
  69. package/lib/commonjs/specs/NativeBotaDeviceSDK.js +9 -0
  70. package/lib/commonjs/specs/NativeBotaDeviceSDK.js.map +1 -0
  71. package/lib/commonjs/sync/syncStatus.js +178 -0
  72. package/lib/commonjs/sync/syncStatus.js.map +1 -0
  73. package/lib/commonjs/utils/errors.js +194 -0
  74. package/lib/commonjs/utils/errors.js.map +1 -0
  75. package/lib/commonjs/utils/logger.js +84 -0
  76. package/lib/commonjs/utils/logger.js.map +1 -0
  77. package/lib/module/BotaClient.js +189 -0
  78. package/lib/module/BotaClient.js.map +1 -0
  79. package/lib/module/ble/constants.js +6 -0
  80. package/lib/module/ble/constants.js.map +1 -0
  81. package/lib/module/ble/deviceLogs.js +45 -0
  82. package/lib/module/ble/deviceLogs.js.map +1 -0
  83. package/lib/module/cache/DeviceStateCache.js +4 -0
  84. package/lib/module/cache/DeviceStateCache.js.map +1 -0
  85. package/lib/module/client.js +740 -0
  86. package/lib/module/client.js.map +1 -0
  87. package/lib/module/compatibility/runtime.js +35 -0
  88. package/lib/module/compatibility/runtime.js.map +1 -0
  89. package/lib/module/index.js +17 -0
  90. package/lib/module/index.js.map +1 -0
  91. package/lib/module/managers/DeviceManager.js +641 -0
  92. package/lib/module/managers/DeviceManager.js.map +1 -0
  93. package/lib/module/managers/OTAManager.js +134 -0
  94. package/lib/module/managers/OTAManager.js.map +1 -0
  95. package/lib/module/managers/RecordingManager.js +438 -0
  96. package/lib/module/managers/RecordingManager.js.map +1 -0
  97. package/lib/module/managers/StreamingSession.js +168 -0
  98. package/lib/module/managers/StreamingSession.js.map +1 -0
  99. package/lib/module/managers/types.js +4 -0
  100. package/lib/module/managers/types.js.map +1 -0
  101. package/lib/module/models/Device.js +2 -0
  102. package/lib/module/models/Device.js.map +1 -0
  103. package/lib/module/models/Recording.js +2 -0
  104. package/lib/module/models/Recording.js.map +1 -0
  105. package/lib/module/models/Status.js +4 -0
  106. package/lib/module/models/Status.js.map +1 -0
  107. package/lib/module/specs/NativeBotaDeviceSDK.js +5 -0
  108. package/lib/module/specs/NativeBotaDeviceSDK.js.map +1 -0
  109. package/lib/module/sync/syncStatus.js +174 -0
  110. package/lib/module/sync/syncStatus.js.map +1 -0
  111. package/lib/module/utils/errors.js +183 -0
  112. package/lib/module/utils/errors.js.map +1 -0
  113. package/lib/module/utils/logger.js +80 -0
  114. package/lib/module/utils/logger.js.map +1 -0
  115. package/lib/typescript/BotaClient.d.ts +40 -0
  116. package/lib/typescript/BotaClient.d.ts.map +1 -0
  117. package/lib/typescript/ble/constants.d.ts +4 -0
  118. package/lib/typescript/ble/constants.d.ts.map +1 -0
  119. package/lib/typescript/ble/deviceLogs.d.ts +10 -0
  120. package/lib/typescript/ble/deviceLogs.d.ts.map +1 -0
  121. package/lib/typescript/cache/DeviceStateCache.d.ts +14 -0
  122. package/lib/typescript/cache/DeviceStateCache.d.ts.map +1 -0
  123. package/lib/typescript/client.d.ts +208 -0
  124. package/lib/typescript/client.d.ts.map +1 -0
  125. package/lib/typescript/compatibility/runtime.d.ts +11 -0
  126. package/lib/typescript/compatibility/runtime.d.ts.map +1 -0
  127. package/lib/typescript/index.d.ts +19 -0
  128. package/lib/typescript/index.d.ts.map +1 -0
  129. package/lib/typescript/managers/DeviceManager.d.ts +117 -0
  130. package/lib/typescript/managers/DeviceManager.d.ts.map +1 -0
  131. package/lib/typescript/managers/OTAManager.d.ts +25 -0
  132. package/lib/typescript/managers/OTAManager.d.ts.map +1 -0
  133. package/lib/typescript/managers/RecordingManager.d.ts +54 -0
  134. package/lib/typescript/managers/RecordingManager.d.ts.map +1 -0
  135. package/lib/typescript/managers/StreamingSession.d.ts +35 -0
  136. package/lib/typescript/managers/StreamingSession.d.ts.map +1 -0
  137. package/lib/typescript/managers/types.d.ts +19 -0
  138. package/lib/typescript/managers/types.d.ts.map +1 -0
  139. package/lib/typescript/models/Device.d.ts +392 -0
  140. package/lib/typescript/models/Device.d.ts.map +1 -0
  141. package/lib/typescript/models/Recording.d.ts +259 -0
  142. package/lib/typescript/models/Recording.d.ts.map +1 -0
  143. package/lib/typescript/models/Status.d.ts +106 -0
  144. package/lib/typescript/models/Status.d.ts.map +1 -0
  145. package/lib/typescript/specs/NativeBotaDeviceSDK.d.ts +393 -0
  146. package/lib/typescript/specs/NativeBotaDeviceSDK.d.ts.map +1 -0
  147. package/lib/typescript/sync/syncStatus.d.ts +123 -0
  148. package/lib/typescript/sync/syncStatus.d.ts.map +1 -0
  149. package/lib/typescript/utils/errors.d.ts +83 -0
  150. package/lib/typescript/utils/errors.d.ts.map +1 -0
  151. package/lib/typescript/utils/logger.d.ts +36 -0
  152. package/lib/typescript/utils/logger.d.ts.map +1 -0
  153. package/package.json +100 -0
  154. package/scripts/bota_device_sdk_spm_workaround.rb +53 -0
  155. package/src/BotaClient.ts +231 -0
  156. package/src/ble/constants.ts +3 -0
  157. package/src/ble/deviceLogs.ts +61 -0
  158. package/src/cache/DeviceStateCache.ts +20 -0
  159. package/src/client.ts +1410 -0
  160. package/src/compatibility/runtime.ts +55 -0
  161. package/src/index.ts +146 -0
  162. package/src/managers/DeviceManager.ts +927 -0
  163. package/src/managers/OTAManager.ts +195 -0
  164. package/src/managers/RecordingManager.ts +578 -0
  165. package/src/managers/StreamingSession.ts +212 -0
  166. package/src/managers/types.ts +36 -0
  167. package/src/models/Device.ts +484 -0
  168. package/src/models/Recording.ts +281 -0
  169. package/src/models/Status.ts +128 -0
  170. package/src/specs/NativeBotaDeviceSDK.ts +542 -0
  171. package/src/sync/syncStatus.ts +243 -0
  172. package/src/utils/errors.ts +327 -0
  173. package/src/utils/logger.ts +122 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;AAUtD,cAAM,MAAM;IACV,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,OAAO,CAA2B;IAE1C,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,QAAQ,IAAI,QAAQ;IAIpB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAI5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CACH,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,KAAK,EACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI;IAUP,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY;IAI9B,OAAO,CAAC,KAAK;IAcb,OAAO,CAAC,MAAM;CAQf;AAED,cAAM,YAAY;IAEd,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBADR,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;IAGnC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CACH,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,KAAK,EACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI;CAGR;AAED,eAAO,MAAM,MAAM,QAAe,CAAC;AAEnC,YAAY,EAAE,YAAY,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "@bota.dev/react-native-app-sdk",
3
+ "version": "2.0.0-beta.0",
4
+ "description": "React Native facade for the Bota App SDK",
5
+ "packageManager": "npm@12.0.2",
6
+ "main": "lib/commonjs/index.js",
7
+ "module": "lib/module/index.js",
8
+ "types": "lib/typescript/index.d.ts",
9
+ "react-native": "src/index.ts",
10
+ "source": "src/index.ts",
11
+ "files": [
12
+ "BotaDeviceSDK.podspec",
13
+ "LICENSE",
14
+ "README.md",
15
+ "android/",
16
+ "generated/",
17
+ "ios/",
18
+ "lib/",
19
+ "scripts/bota_device_sdk_spm_workaround.rb",
20
+ "src/"
21
+ ],
22
+ "scripts": {
23
+ "build": "bob build",
24
+ "clean": "rm -rf lib generated/build",
25
+ "codegen": "node scripts/verify-codegen.mjs --write",
26
+ "codegen:check": "node scripts/verify-codegen.mjs",
27
+ "license-check": "node ../../scripts/check-licenses.mjs",
28
+ "pretest": "npm run build",
29
+ "test": "node --test test/*.test.mjs",
30
+ "test:apple:integration": "../../tools/react-native/test-apple-adapter.sh",
31
+ "test:apple:lifecycle": "../../tools/apple/build-xcframework.sh && swift test -Xswiftc -strict-concurrency=complete -Xswiftc -warnings-as-errors",
32
+ "test:apple:remote-resolution": "../../tools/react-native/test-apple-adapter.sh remote",
33
+ "test:apple:spm-workaround": "ruby test/apple-spm-workaround.test.rb",
34
+ "typecheck": "tsc --noEmit",
35
+ "verify": "node ../../tools/react-native/verify-package.mjs --workspace-root ../.. --package-root . && npm run codegen:check && npm run typecheck && npm test && npm run license-check"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/bota-dev/app-sdk.git",
40
+ "directory": "frameworks/react-native"
41
+ },
42
+ "homepage": "https://docs.bota.dev",
43
+ "bugs": {
44
+ "url": "https://github.com/bota-dev/app-sdk/issues"
45
+ },
46
+ "author": "Bota",
47
+ "license": "MIT",
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "engines": {
52
+ "node": ">=22"
53
+ },
54
+ "peerDependencies": {
55
+ "react": ">=19.2.3",
56
+ "react-native": ">=0.86.3 <1.0"
57
+ },
58
+ "devDependencies": {
59
+ "@types/react": "19.2.17",
60
+ "react": "19.2.3",
61
+ "react-native": "0.86.3",
62
+ "react-native-builder-bob": "0.43.0",
63
+ "typescript": "6.0.3"
64
+ },
65
+ "codegenConfig": {
66
+ "name": "BotaDeviceSDKSpec",
67
+ "type": "modules",
68
+ "jsSrcsDir": "./src/specs",
69
+ "android": {
70
+ "javaPackageName": "dev.bota.sdk.reactnative"
71
+ }
72
+ },
73
+ "bota": {
74
+ "nativeModuleName": "BotaDeviceSDK",
75
+ "reactNativeFloor": "0.86.3",
76
+ "android": {
77
+ "compileSdkVersion": 36,
78
+ "coroutinesVersion": "1.10.2",
79
+ "kotlinVersion": "2.1.20",
80
+ "mavenCoordinate": "dev.bota:bota-app-sdk",
81
+ "minSdkVersion": 26,
82
+ "namespace": "dev.bota.sdk.reactnative"
83
+ },
84
+ "apple": {
85
+ "podName": "BotaDeviceSDK",
86
+ "moduleName": "BotaDeviceSDK",
87
+ "deploymentTarget": "15.1",
88
+ "swiftVersion": "6.0",
89
+ "cocoapodsVersion": "1.13.0",
90
+ "packageUrl": "https://github.com/bota-dev/app-sdk.git",
91
+ "packageRequirement": "exactVersion",
92
+ "packageProduct": "BotaAppSDK",
93
+ "localPackagePathEnvironment": "BOTA_APPLE_SDK_PACKAGE_PATH"
94
+ }
95
+ },
96
+ "dependencies": {
97
+ "buffer": "6.0.3",
98
+ "eventemitter3": "5.0.1"
99
+ }
100
+ }
@@ -0,0 +1,53 @@
1
+ module BotaDeviceSDKSPMWorkaround
2
+ POD_NAME = "BotaDeviceSDK"
3
+ STATIC_LIBRARY_PRODUCT_TYPE = "com.apple.product-type.library.static"
4
+ SHARED_PRODUCTS_DIRECTORY = "${PODS_CONFIGURATION_BUILD_DIR}"
5
+
6
+ module PostInstallPatch
7
+ def apply_on_post_install(installer)
8
+ super
9
+ BotaDeviceSDKSPMWorkaround.apply(installer)
10
+ end
11
+ end
12
+
13
+ def self.install!(manager)
14
+ singleton = manager.singleton_class
15
+ singleton.prepend(PostInstallPatch) unless singleton.ancestors.include?(PostInstallPatch)
16
+ end
17
+
18
+ def self.apply(installer)
19
+ target = installer.pods_project.targets.find { |candidate| candidate.name == POD_NAME }
20
+ return unless target&.product_type == STATIC_LIBRARY_PRODUCT_TYPE
21
+
22
+ target.build_configurations.each do |configuration|
23
+ target.build_settings(configuration.name)["CONFIGURATION_BUILD_DIR"] =
24
+ SHARED_PRODUCTS_DIRECTORY
25
+ end
26
+
27
+ rewrite_aggregate_modulemap_references(installer)
28
+ end
29
+
30
+ def self.rewrite_aggregate_modulemap_references(installer)
31
+ nested = "${PODS_CONFIGURATION_BUILD_DIR}/#{POD_NAME}/#{POD_NAME}.modulemap"
32
+ flattened = "${PODS_CONFIGURATION_BUILD_DIR}/#{POD_NAME}.modulemap"
33
+
34
+ installer.aggregate_targets.each do |aggregate_target|
35
+ aggregate_target.xcconfigs.each do |configuration_name, config_file|
36
+ changed = false
37
+ %w[OTHER_CFLAGS OTHER_SWIFT_FLAGS].each do |key|
38
+ value = config_file.attributes[key]
39
+ next unless value
40
+
41
+ updated = value.gsub(nested, flattened)
42
+ next if updated == value
43
+
44
+ config_file.attributes[key] = updated
45
+ changed = true
46
+ end
47
+ config_file.save_as(aggregate_target.xcconfig_path(configuration_name)) if changed
48
+ end
49
+ end
50
+ end
51
+
52
+ private_class_method :rewrite_aggregate_modulemap_references
53
+ end
@@ -0,0 +1,231 @@
1
+ import EventEmitter from 'eventemitter3';
2
+
3
+ import type { BotaDeviceSDKClient } from './client';
4
+ import { getCompatibilityClient } from './compatibility/runtime';
5
+ import { DeviceManager } from './managers/DeviceManager';
6
+ import { OTAManager } from './managers/OTAManager';
7
+ import { RecordingManager } from './managers/RecordingManager';
8
+ import type {
9
+ BluetoothState,
10
+ BotaClientEvents,
11
+ BotaConfig,
12
+ LogLevel,
13
+ SdkState,
14
+ } from './models/Status';
15
+ import { BluetoothError, SdkError } from './utils/errors';
16
+ import { logger, type LogHandler } from './utils/logger';
17
+
18
+ const log = logger.tag('BotaClient');
19
+
20
+ const normalizeConfig = (config: BotaConfig): Required<BotaConfig> => ({
21
+ environment: config.environment ?? 'production',
22
+ backgroundSyncEnabled: config.backgroundSyncEnabled ?? true,
23
+ wifiOnlyUpload: config.wifiOnlyUpload ?? false,
24
+ logLevel: config.logLevel ?? 'warn',
25
+ debug: config.debug ?? false,
26
+ });
27
+
28
+ class BotaClientImpl extends EventEmitter<BotaClientEvents> {
29
+ private _config: BotaConfig | null = null;
30
+ private _state: SdkState = 'uninitialized';
31
+ private _bluetoothState: BluetoothState = 'unknown';
32
+ private _client: BotaDeviceSDKClient | null = null;
33
+ private _deviceManager: DeviceManager | null = null;
34
+ private _recordingManager: RecordingManager | null = null;
35
+ private _otaManager: OTAManager | null = null;
36
+ private _nativeOwned = false;
37
+ private _operation: Promise<void> = Promise.resolve();
38
+ private _configurePromise: Promise<void> | null = null;
39
+ private _destroyPromise: Promise<void> | null = null;
40
+
41
+ get state(): SdkState {
42
+ return this._state;
43
+ }
44
+
45
+ get bluetoothState(): BluetoothState {
46
+ return this._bluetoothState;
47
+ }
48
+
49
+ get isBluetoothReady(): boolean {
50
+ return this._bluetoothState === 'poweredOn';
51
+ }
52
+
53
+ get isInitialized(): boolean {
54
+ return this._state === 'ready';
55
+ }
56
+
57
+ get config(): BotaConfig | null {
58
+ return this._config;
59
+ }
60
+
61
+ get devices(): DeviceManager {
62
+ if (!this._deviceManager) throw SdkError.notInitialized();
63
+ return this._deviceManager;
64
+ }
65
+
66
+ get recordings(): RecordingManager {
67
+ if (!this._recordingManager) throw SdkError.notInitialized();
68
+ return this._recordingManager;
69
+ }
70
+
71
+ get ota(): OTAManager {
72
+ if (!this._otaManager) throw SdkError.notInitialized();
73
+ return this._otaManager;
74
+ }
75
+
76
+ configure(config: BotaConfig = {}): Promise<void> {
77
+ if (this._configurePromise && !this._destroyPromise) {
78
+ return this._configurePromise;
79
+ }
80
+ const normalized = normalizeConfig(config);
81
+ const operation = this.enqueue(() => this.performConfigure(normalized));
82
+ this._configurePromise = operation;
83
+ void operation
84
+ .finally(() => {
85
+ if (this._configurePromise === operation) this._configurePromise = null;
86
+ })
87
+ .catch(() => undefined);
88
+ return operation;
89
+ }
90
+
91
+ async waitForBluetooth(timeoutMs: number = 10000): Promise<void> {
92
+ if (!this._client || !this._nativeOwned) throw SdkError.notInitialized();
93
+ if (this._bluetoothState === 'poweredOn') return;
94
+ if (this._bluetoothState === 'unsupported') {
95
+ throw BluetoothError.unavailable();
96
+ }
97
+
98
+ const deadline = Date.now() + timeoutMs;
99
+ while (Date.now() < deadline) {
100
+ await new Promise<void>((resolve) => setTimeout(() => resolve(), 50));
101
+ const capabilities = await this._client.getCapabilities();
102
+ const state: BluetoothState = capabilities.bluetooth
103
+ ? 'poweredOn'
104
+ : 'unsupported';
105
+ this.setBluetoothState(state);
106
+ if (state === 'poweredOn') return;
107
+ if (state === 'unsupported') {
108
+ throw BluetoothError.unavailable();
109
+ }
110
+ }
111
+ throw SdkError.timeout('Bluetooth ready');
112
+ }
113
+
114
+ setLogLevel(level: LogLevel): void {
115
+ logger.setLevel(level);
116
+ if (this._config) this._config.logLevel = level;
117
+ }
118
+
119
+ setLogHandler(handler: LogHandler | null): void {
120
+ logger.setHandler(handler);
121
+ }
122
+
123
+ destroy(): Promise<void> {
124
+ if (this._destroyPromise) return this._destroyPromise;
125
+ const operation = this.enqueue(async () => {
126
+ await this.releaseOwnerGraph();
127
+ this.removeAllListeners();
128
+ });
129
+ this._destroyPromise = operation;
130
+ void operation
131
+ .finally(() => {
132
+ if (this._destroyPromise === operation) this._destroyPromise = null;
133
+ })
134
+ .catch(() => undefined);
135
+ return operation;
136
+ }
137
+
138
+ private enqueue(operation: () => Promise<void>): Promise<void> {
139
+ const queued = this._operation.catch(() => undefined).then(operation);
140
+ this._operation = queued.catch(() => undefined);
141
+ return queued;
142
+ }
143
+
144
+ private async performConfigure(config: Required<BotaConfig>): Promise<void> {
145
+ if (this._state !== 'uninitialized' || this._nativeOwned) {
146
+ log.warn('SDK already configured, reconfiguring');
147
+ await this.releaseOwnerGraph();
148
+ }
149
+
150
+ this._config = config;
151
+ logger.setLevel(config.logLevel);
152
+ this.setState('initializing');
153
+ const client = getCompatibilityClient();
154
+ this._client = client;
155
+ this._nativeOwned = true;
156
+
157
+ let deviceManager: DeviceManager | null = null;
158
+ let recordingManager: RecordingManager | null = null;
159
+ let otaManager: OTAManager | null = null;
160
+ try {
161
+ await client.configure({ logLevel: config.logLevel });
162
+ const nativeState = await client.getState();
163
+ if (nativeState !== 'ready') {
164
+ throw SdkError.invalidState('ready', nativeState);
165
+ }
166
+ const capabilities = await client.getCapabilities();
167
+ this.setBluetoothState(
168
+ capabilities.bluetooth ? 'poweredOn' : 'unsupported'
169
+ );
170
+
171
+ deviceManager = new DeviceManager();
172
+ await deviceManager.initialize();
173
+ recordingManager = new RecordingManager();
174
+ await recordingManager.initialize();
175
+ otaManager = new OTAManager(deviceManager);
176
+
177
+ this._deviceManager = deviceManager;
178
+ this._recordingManager = recordingManager;
179
+ this._otaManager = otaManager;
180
+ this.setState(nativeState);
181
+ log.info('SDK configured successfully', {
182
+ environment: config.environment,
183
+ bluetoothState: this._bluetoothState,
184
+ });
185
+ } catch (error) {
186
+ deviceManager?.destroy();
187
+ recordingManager?.destroy();
188
+ otaManager?.destroy();
189
+ await client.destroy().catch(() => undefined);
190
+ this._nativeOwned = false;
191
+ this._client = null;
192
+ this.setState('error');
193
+ const failure = error instanceof Error ? error : new Error(String(error));
194
+ log.error('Failed to configure SDK', failure);
195
+ this.emit('error', failure);
196
+ throw error;
197
+ }
198
+ }
199
+
200
+ private async releaseOwnerGraph(): Promise<void> {
201
+ this._deviceManager?.destroy();
202
+ this._recordingManager?.destroy();
203
+ this._otaManager?.destroy();
204
+ this._deviceManager = null;
205
+ this._recordingManager = null;
206
+ this._otaManager = null;
207
+
208
+ const client = this._client;
209
+ this._client = null;
210
+ if (client && this._nativeOwned) await client.destroy();
211
+ this._nativeOwned = false;
212
+ this._config = null;
213
+ this.setState('uninitialized');
214
+ }
215
+
216
+ private setState(state: SdkState): void {
217
+ if (state === this._state) return;
218
+ this._state = state;
219
+ this.emit('stateChanged', state);
220
+ }
221
+
222
+ private setBluetoothState(state: BluetoothState): void {
223
+ if (state === this._bluetoothState) return;
224
+ this._bluetoothState = state;
225
+ this.emit('bluetoothStateChanged', state);
226
+ }
227
+ }
228
+
229
+ export const BotaClient = new BotaClientImpl();
230
+
231
+ export type { BluetoothState, BotaConfig, SdkState };
@@ -0,0 +1,3 @@
1
+ export const DEVICE_LOG_FLAG_BACKLOG = 0x01;
2
+ export const DEVICE_LOG_FLAG_DROPPED = 0x02;
3
+ export const BLE_ERROR_STORAGE_KEY_UNAVAILABLE = 0x14;
@@ -0,0 +1,61 @@
1
+ import { Buffer } from 'buffer';
2
+
3
+ import {
4
+ DEVICE_LOG_FLAG_BACKLOG,
5
+ DEVICE_LOG_FLAG_DROPPED,
6
+ } from './constants';
7
+ import type { DeviceLogEvent } from '../models/Device';
8
+
9
+ export type { DeviceLogEvent } from '../models/Device';
10
+
11
+ const PACKET_HEADER_SIZE = 3;
12
+
13
+ export class DeviceLogDecoder {
14
+ private lineBuffer = Buffer.alloc(0);
15
+ private expectedSequence: number | null = null;
16
+
17
+ push(packet: Buffer): DeviceLogEvent[] {
18
+ if (packet.length < PACKET_HEADER_SIZE) {
19
+ return [];
20
+ }
21
+
22
+ const sequence = packet.readUInt16LE(0);
23
+ const flags = packet[2];
24
+ const hasSequenceGap = this.expectedSequence !== null
25
+ && sequence !== this.expectedSequence;
26
+ const hasDroppedBytes = (flags & DEVICE_LOG_FLAG_DROPPED) !== 0;
27
+ const events: DeviceLogEvent[] = [];
28
+
29
+ if (hasSequenceGap || hasDroppedBytes) {
30
+ this.lineBuffer = Buffer.alloc(0);
31
+ }
32
+
33
+ this.expectedSequence = (sequence + 1) & 0xffff;
34
+ this.lineBuffer = Buffer.concat([this.lineBuffer, packet.subarray(PACKET_HEADER_SIZE)]);
35
+
36
+ const isBacklog = (flags & DEVICE_LOG_FLAG_BACKLOG) !== 0;
37
+ let newlineIndex = this.lineBuffer.indexOf(0x0a);
38
+ while (newlineIndex !== -1) {
39
+ let line = this.lineBuffer.subarray(0, newlineIndex);
40
+ if (line.length > 0 && line[line.length - 1] === 0x0d) {
41
+ line = line.subarray(0, line.length - 1);
42
+ }
43
+ events.push({
44
+ level: 'debug',
45
+ message: Buffer.from(line).toString('utf8'),
46
+ isBacklog,
47
+ });
48
+ this.lineBuffer = Buffer.from(
49
+ this.lineBuffer.subarray(newlineIndex + 1)
50
+ );
51
+ newlineIndex = this.lineBuffer.indexOf(0x0a);
52
+ }
53
+
54
+ return events;
55
+ }
56
+
57
+ reset(): void {
58
+ this.lineBuffer = Buffer.alloc(0);
59
+ this.expectedSequence = null;
60
+ }
61
+ }
@@ -0,0 +1,20 @@
1
+ import type { WiFiStatusInfo } from '../models/Device';
2
+
3
+ export interface CachedDeviceState {
4
+ wifiStatus?: WiFiStatusInfo;
5
+ updatedAt: number;
6
+ }
7
+
8
+ export interface DeviceStatePatch {
9
+ wifiStatus?: Partial<WiFiStatusInfo> | null;
10
+ }
11
+
12
+ export interface DeviceStateCacheEvents {
13
+ stateChanged: (
14
+ serialNumber: string,
15
+ patch: DeviceStatePatch,
16
+ state: CachedDeviceState
17
+ ) => void;
18
+ cleared: (serialNumber: string) => void;
19
+ clearedAll: () => void;
20
+ }