@bota.dev/react-native-app-sdk 2.0.0-beta.6 → 2.0.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@ into the native Apple and Android SDKs.
7
7
 
8
8
  ## Requirements
9
9
 
10
- Unreleased source adds `BotaDeviceSDK.clientPresence.nextReport(deviceId)`.
10
+ App SDK beta.6 and later expose `BotaDeviceSDK.clientPresence.nextReport(deviceId)`.
11
11
  It returns `BotaClientPresenceContext | null` from the native verified connection,
12
12
  preserving native session/sequence while identifying this React Native package
13
13
  and its generated version. It makes no HTTP call or device command. Destroy
@@ -23,13 +23,17 @@ adopting this source API; published-package availability is a separate gate.
23
23
 
24
24
  ## Install
25
25
 
26
- This source prepares synchronized `2.0.0-beta.6`; use the exact pin below after
27
- publication. Version `2.0.0-beta.1` remains the previous published release.
26
+ Published beta.7 remains available. Install this beta.8 source candidate with
27
+ the exact pin below only after its publication is verified.
28
+ Source candidate beta.8 adds Android disconnection events without requiring a
29
+ status subscription. Its [preflight](../../release/evidence/2.0.0-beta.8-preflight.md)
30
+ tracks the separate publication and adoption gates.
28
31
  Remove `@bota.dev/react-native-sdk` before adding the replacement; do not
29
- co-install both. Production maintenance 0.0.x consumers need not migrate.
32
+ co-install both. Standalone maintenance ended September 29, 2026; follow the
33
+ [retirement and migration notice](../../docs/migrations/react-native-sdk-sunset.md).
30
34
 
31
35
  ```bash
32
- npm install --save-exact @bota.dev/react-native-app-sdk@2.0.0-beta.6
36
+ npm install --save-exact @bota.dev/react-native-app-sdk@2.0.0-beta.8
33
37
  npx pod-install
34
38
  ```
35
39
 
@@ -31,6 +31,7 @@ internal interface BotaDeviceSDKAndroidDeviceClient {
31
31
  suspend fun nextClientPresence(deviceId: String): dev.bota.sdk.SDKClientContext?
32
32
 
33
33
  suspend fun statusUpdates(): Flow<DeviceStatus>
34
+ fun connectionUpdates(): Flow<ConnectedDevice?>
34
35
  }
35
36
 
36
37
  internal class BotaDeviceSDKSharedAndroidDeviceClient(
@@ -61,6 +62,7 @@ internal class BotaDeviceSDKSharedAndroidDeviceClient(
61
62
  client.clientPresence.nextReport(deviceId)
62
63
 
63
64
  override suspend fun statusUpdates(): Flow<DeviceStatus> = client.devices.statusUpdates()
65
+ override fun connectionUpdates(): Flow<ConnectedDevice?> = client.devices.connectionUpdates()
64
66
  }
65
67
 
66
68
  internal class BotaDeviceSDKAndroidDevices(
@@ -73,6 +75,20 @@ internal class BotaDeviceSDKAndroidDevices(
73
75
  private val statusLock = Any()
74
76
  private var activeScan: Job? = null
75
77
  private var activeStatusUpdates: Job? = null
78
+ private var activeConnectionUpdates: Job? = null
79
+
80
+ suspend fun startConnectionUpdates(onDisconnected: () -> Unit) = operations.withLock {
81
+ activeConnectionUpdates?.cancelAndJoin()
82
+ val stream = client.connectionUpdates()
83
+ activeConnectionUpdates = scope.launch(start = CoroutineStart.UNDISPATCHED) {
84
+ var connected = false
85
+ stream.collect { device ->
86
+ val lost = connected && device == null
87
+ connected = device != null
88
+ if (lost) onDisconnected()
89
+ }
90
+ }
91
+ }
76
92
 
77
93
  suspend fun startScan(
78
94
  timeoutMilliseconds: ULong,
@@ -155,6 +171,8 @@ internal class BotaDeviceSDKAndroidDevices(
155
171
  }
156
172
 
157
173
  suspend fun stopAll() = operations.withLock {
174
+ activeConnectionUpdates?.cancelAndJoin()
175
+ activeConnectionUpdates = null
158
176
  stopScanOwned()
159
177
  stopStatusUpdatesOwned()
160
178
  }
@@ -46,6 +46,9 @@ internal class BotaDeviceSDKModule(
46
46
  launch(promise) {
47
47
  lifecycle.configure(storageDirectory)
48
48
  recordingUploads.configure(storageDirectory)
49
+ devices.startConnectionUpdates {
50
+ emitOnDeviceDisconnected(Arguments.createMap())
51
+ }
49
52
  }
50
53
  }
51
54
 
@@ -22,6 +22,38 @@ import org.junit.Assert.assertEquals
22
22
  import org.junit.Test
23
23
 
24
24
  class BotaDeviceSDKAndroidDevicesTest {
25
+ @Test
26
+ fun transportLossIsForwardedWithoutAStatusSubscription() = runTest {
27
+ val verified = ConnectedDevice(
28
+ id = "selected", serialNumber = "EVFXXW67KP", deviceType = DeviceType.BotaPin,
29
+ firmwareVersion = "1.0.19", isProvisioned = false,
30
+ connectionState = ConnectionState.Connected, mtu = 247,
31
+ )
32
+ val stopped = CompletableDeferred<Unit>()
33
+ val client = FakeDeviceClient(
34
+ DiscoveredDevice("selected", rssi = -30), verified,
35
+ connections = flow {
36
+ try {
37
+ emit(null)
38
+ emit(verified)
39
+ emit(null)
40
+ emit(null)
41
+ awaitCancellation()
42
+ } finally {
43
+ stopped.complete(Unit)
44
+ }
45
+ },
46
+ )
47
+ val devices = BotaDeviceSDKAndroidDevices(client, backgroundScope)
48
+ var losses = 0
49
+ devices.startConnectionUpdates { losses += 1 }
50
+ assertEquals(1, losses)
51
+ assertEquals(0, client.statusReadCount)
52
+ devices.stopAll()
53
+ stopped.await()
54
+ assertEquals(1, losses)
55
+ }
56
+
25
57
  @Test
26
58
  fun unknownPairingStateUsesTheFrozenUnpairedFallback() {
27
59
  assertEquals("unpaired", PairingState.Unknown(0xFFu).toBridgeValue())
@@ -134,7 +166,9 @@ class BotaDeviceSDKAndroidDevicesTest {
134
166
  private val connected: ConnectedDevice,
135
167
  private val scanFailure: Throwable? = null,
136
168
  private val status: DeviceStatus = testDeviceStatus(),
169
+ private val connections: Flow<ConnectedDevice?> = kotlinx.coroutines.flow.emptyFlow(),
137
170
  ) : BotaDeviceSDKAndroidDeviceClient {
171
+ override fun connectionUpdates(): Flow<ConnectedDevice?> = connections
138
172
  override suspend fun nextClientPresence(deviceId: String): dev.bota.sdk.SDKClientContext? = null
139
173
  val scanOptions = mutableListOf<Pair<ULong, Boolean>>()
140
174
  val selectedIds = mutableListOf<String>()
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@bota.dev/react-native-app-sdk",
4
- "packageVersion": "2.0.0-beta.6",
4
+ "packageVersion": "2.0.0-beta.8",
5
5
  "reactNativeVersion": "0.86.3",
6
6
  "codegenLibrary": "BotaDeviceSDKSpec",
7
7
  "nativeModule": "BotaDeviceSDK",
@@ -4149,5 +4149,5 @@
4149
4149
  }
4150
4150
  ]
4151
4151
  },
4152
- "contractDigest": "b4a14c25e9a6292400693ba1d874d088b66043644431f6e49c670640d352cf6d"
4152
+ "contractDigest": "a53fec3bb35db5783a8434ecb69e0ce071c3e2a5d1eff780ae1b453bd1d7b8fe"
4153
4153
  }
@@ -6,5 +6,5 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.SDK_VERSION = exports.SDK_PACKAGE = void 0;
7
7
  // Generated by cargo xtask client-identity generate. Do not edit.
8
8
  const SDK_PACKAGE = exports.SDK_PACKAGE = '@bota.dev/react-native-app-sdk';
9
- const SDK_VERSION = exports.SDK_VERSION = '2.0.0-beta.6';
9
+ const SDK_VERSION = exports.SDK_VERSION = '2.0.0-beta.8';
10
10
  //# sourceMappingURL=sdkIdentity.js.map
@@ -2,5 +2,5 @@
2
2
 
3
3
  // Generated by cargo xtask client-identity generate. Do not edit.
4
4
  export const SDK_PACKAGE = '@bota.dev/react-native-app-sdk';
5
- export const SDK_VERSION = '2.0.0-beta.6';
5
+ export const SDK_VERSION = '2.0.0-beta.8';
6
6
  //# sourceMappingURL=sdkIdentity.js.map
@@ -1,3 +1,3 @@
1
1
  export declare const SDK_PACKAGE = "@bota.dev/react-native-app-sdk";
2
- export declare const SDK_VERSION = "2.0.0-beta.6";
2
+ export declare const SDK_VERSION = "2.0.0-beta.8";
3
3
  //# sourceMappingURL=sdkIdentity.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bota.dev/react-native-app-sdk",
3
- "version": "2.0.0-beta.6",
3
+ "version": "2.0.0-beta.8",
4
4
  "description": "React Native facade for the Bota App SDK",
5
5
  "packageManager": "npm@12.0.2",
6
6
  "main": "lib/commonjs/index.js",
@@ -1,3 +1,3 @@
1
1
  // Generated by cargo xtask client-identity generate. Do not edit.
2
2
  export const SDK_PACKAGE = '@bota.dev/react-native-app-sdk'
3
- export const SDK_VERSION = '2.0.0-beta.6'
3
+ export const SDK_VERSION = '2.0.0-beta.8'