@tryterra/react-native 0.0.0-stage → 2.2.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 (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -2
  3. package/TerraReactNative.podspec +48 -0
  4. package/android/build.gradle +87 -0
  5. package/android/src/bridgeCore/kotlin/README.md +1 -0
  6. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/BridgeBootstrap.kt +133 -0
  7. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/BridgeHost.kt +32 -0
  8. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/Conversions.kt +557 -0
  9. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/LauncherSlots.kt +41 -0
  10. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/ReadConversions.kt +250 -0
  11. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/Rejections.kt +150 -0
  12. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/StreamRegistry.kt +77 -0
  13. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/TerraBridge.kt +86 -0
  14. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/TerraBridgeOpsImpl.kt +300 -0
  15. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/TerraBridgeStreamsImpl.kt +50 -0
  16. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/TokenBroker.kt +198 -0
  17. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/generated/BridgeErrors.kt +217 -0
  18. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/generated/BridgeOps.kt +582 -0
  19. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/generated/BridgeTypes.kt +1569 -0
  20. package/android/src/healthConnectOnly/kotlin/co/tryterra/sdk/reactnative/TerraStores.kt +11 -0
  21. package/android/src/main/AndroidManifest.xml +24 -0
  22. package/android/src/main/java/co/tryterra/sdk/reactnative/TerraBridgeModule.kt +96 -0
  23. package/android/src/main/java/co/tryterra/sdk/reactnative/TerraReactNativePackage.kt +26 -0
  24. package/android/src/main/java/co/tryterra/sdk/reactnative/TerraStartup.kt +46 -0
  25. package/android/src/samsung/kotlin/co/tryterra/sdk/reactnative/TerraStores.kt +13 -0
  26. package/docs/availability.md +396 -0
  27. package/frameworks/TerraSDK.xcframework/Info.plist +48 -0
  28. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Info.plist +0 -0
  29. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.abi.json +82672 -0
  30. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.package.swiftinterface +2186 -0
  31. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +2186 -0
  32. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  33. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.swiftinterface +2163 -0
  34. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/PrivacyInfo.xcprivacy +96 -0
  35. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/TerraSDK +0 -0
  36. package/frameworks/TerraSDK.xcframework/ios-arm64/dSYMs/TerraSDK.framework.dSYM/Contents/Info.plist +20 -0
  37. package/frameworks/TerraSDK.xcframework/ios-arm64/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/DWARF/TerraSDK +0 -0
  38. package/frameworks/TerraSDK.xcframework/ios-arm64/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/TerraSDK.yml +6594 -0
  39. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Info.plist +0 -0
  40. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +82672 -0
  41. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.package.swiftinterface +2186 -0
  42. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +2186 -0
  43. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  44. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +2163 -0
  45. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +82672 -0
  46. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.package.swiftinterface +2186 -0
  47. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +2186 -0
  48. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  49. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +2163 -0
  50. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/PrivacyInfo.xcprivacy +96 -0
  51. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/TerraSDK +0 -0
  52. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/_CodeSignature/CodeResources +223 -0
  53. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Info.plist +20 -0
  54. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/DWARF/TerraSDK +0 -0
  55. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/TerraSDK.yml +6595 -0
  56. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/Relocations/x86_64/TerraSDK.yml +6513 -0
  57. package/ios/TerraBridgeCore/BridgeBootstrap.swift +89 -0
  58. package/ios/TerraBridgeCore/BridgeHost.swift +13 -0
  59. package/ios/TerraBridgeCore/Conversions+Reads.swift +259 -0
  60. package/ios/TerraBridgeCore/Conversions.swift +594 -0
  61. package/ios/TerraBridgeCore/Generated/BridgeErrors.swift +179 -0
  62. package/ios/TerraBridgeCore/Generated/BridgeOps.swift +967 -0
  63. package/ios/TerraBridgeCore/Generated/BridgeTypes.swift +2050 -0
  64. package/ios/TerraBridgeCore/Locked.swift +15 -0
  65. package/ios/TerraBridgeCore/README.md +1 -0
  66. package/ios/TerraBridgeCore/Rejections.swift +130 -0
  67. package/ios/TerraBridgeCore/RuntimeAttachment.swift +60 -0
  68. package/ios/TerraBridgeCore/StreamRegistry.swift +59 -0
  69. package/ios/TerraBridgeCore/TerraBridge.swift +122 -0
  70. package/ios/TerraBridgeCore/TerraBridgeOpsImpl.swift +318 -0
  71. package/ios/TerraBridgeCore/TerraBridgeStreamsImpl.swift +60 -0
  72. package/ios/TerraBridgeCore/TokenBroker.swift +147 -0
  73. package/ios/TerraBridgeModule.mm +79 -0
  74. package/ios/TerraBridgeModuleImpl.swift +49 -0
  75. package/ios/TerraReactNative.swift +19 -0
  76. package/lib/EndUser.d.ts +12 -0
  77. package/lib/EndUser.js +13 -0
  78. package/lib/NativeTerraBridge.d.ts +23 -0
  79. package/lib/NativeTerraBridge.js +13 -0
  80. package/lib/Terra.d.ts +223 -0
  81. package/lib/Terra.js +336 -0
  82. package/lib/TerraError.d.ts +42 -0
  83. package/lib/TerraError.js +95 -0
  84. package/lib/createTerra.d.ts +8 -0
  85. package/lib/createTerra.js +19 -0
  86. package/lib/generated/client.d.ts +128 -0
  87. package/lib/generated/client.js +256 -0
  88. package/lib/generated/codecs.d.ts +219 -0
  89. package/lib/generated/codecs.js +2066 -0
  90. package/lib/generated/errors.d.ts +13 -0
  91. package/lib/generated/errors.js +68 -0
  92. package/lib/generated/ops.d.ts +13 -0
  93. package/lib/generated/ops.js +161 -0
  94. package/lib/generated/streams.d.ts +23 -0
  95. package/lib/generated/streams.js +58 -0
  96. package/lib/generated/types.d.ts +794 -0
  97. package/lib/generated/types.js +224 -0
  98. package/lib/index.d.ts +29 -0
  99. package/lib/index.js +55 -0
  100. package/package.json +71 -4
  101. package/src/EndUser.ts +15 -0
  102. package/src/NativeTerraBridge.ts +27 -0
  103. package/src/Terra.ts +592 -0
  104. package/src/TerraError.ts +116 -0
  105. package/src/createTerra.ts +18 -0
  106. package/src/generated/client.ts +315 -0
  107. package/src/generated/codecs.ts +1989 -0
  108. package/src/generated/errors.ts +113 -0
  109. package/src/generated/ops.ts +233 -0
  110. package/src/generated/streams.ts +74 -0
  111. package/src/generated/types.ts +1222 -0
  112. package/src/index.ts +54 -0
@@ -0,0 +1,11 @@
1
+ package co.tryterra.sdk.reactnative
2
+
3
+ import co.tryterra.sdk.StoreRegistration
4
+
5
+ /**
6
+ * The stores this build registers beyond Health Connect: none. The host did not set
7
+ * `terraSamsungHealth=true`, so `samsungHealth` answers `health_data_unavailable`.
8
+ */
9
+ internal object TerraStores {
10
+ val registration: StoreRegistration.() -> Unit = {}
11
+ }
@@ -0,0 +1,24 @@
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
+ <!--
6
+ The zero-line bootstrap: androidx.startup runs it in every process start, WorkManager's
7
+ included, before Application.onCreate. It reads the host's
8
+ <meta-data android:name="co.tryterra.sdk.DEV_ID">.
9
+
10
+ No health permission is declared here. A host's permission list is exactly what the host asked
11
+ for, because Play reviews each declared type against the app's stated use.
12
+ -->
13
+ <application>
14
+ <provider
15
+ android:name="androidx.startup.InitializationProvider"
16
+ android:authorities="${applicationId}.androidx-startup"
17
+ android:exported="false"
18
+ tools:node="merge">
19
+ <meta-data
20
+ android:name="co.tryterra.sdk.reactnative.TerraStartup"
21
+ android:value="androidx.startup" />
22
+ </provider>
23
+ </application>
24
+ </manifest>
@@ -0,0 +1,96 @@
1
+ package co.tryterra.sdk.reactnative
2
+
3
+ import co.tryterra.sdk.bridge.BridgeBootstrap
4
+ import co.tryterra.sdk.bridge.Rejections
5
+ import co.tryterra.sdk.bridge.TerraBridge
6
+ import co.tryterra.sdk.bridge.generated.BridgeDispatch
7
+ import co.tryterra.sdk.bridge.generated.TerraErrorPayload
8
+ import com.facebook.react.bridge.Arguments
9
+ import com.facebook.react.bridge.Promise
10
+ import com.facebook.react.bridge.ReactApplicationContext
11
+ import com.facebook.react.module.annotations.ReactModule
12
+ import kotlinx.coroutines.CancellationException
13
+ import kotlinx.coroutines.CoroutineScope
14
+ import kotlinx.coroutines.Dispatchers
15
+ import kotlinx.coroutines.SupervisorJob
16
+ import kotlinx.coroutines.cancel
17
+ import kotlinx.coroutines.launch
18
+
19
+ /**
20
+ * The TurboModule: one [TerraBridge] per JavaScript runtime, attached to the client bootstrap
21
+ * parked at process start.
22
+ *
23
+ * A shim. It turns a `Promise` and the codegen'd emitter into what hybrid-common takes, and nothing
24
+ * here knows an op, a code or a data type.
25
+ */
26
+ @ReactModule(name = TerraBridgeModule.NAME)
27
+ class TerraBridgeModule(context: ReactApplicationContext) : NativeTerraBridgeSpec(context) {
28
+
29
+ /** Cancelled with the runtime, which cancels every stream this runtime started. */
30
+ private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
31
+
32
+ private var attached: TerraBridge? = null
33
+
34
+ /**
35
+ * Attached on first use, and a failed attach is not remembered: the next call retries, so a
36
+ * runtime that started before a manual bootstrap recovers without a reload.
37
+ */
38
+ @Synchronized
39
+ private fun bridge(): TerraBridge =
40
+ attached ?: BridgeBootstrap.attach(scope, TerraReactNative.MISSING_LINE, ::emit).also { attached = it }
41
+
42
+ private fun emit(subscriptionId: String, message: String) {
43
+ emitOnMessage(
44
+ Arguments.createMap().apply {
45
+ putString("subscriptionId", subscriptionId)
46
+ putString("message", message)
47
+ },
48
+ )
49
+ }
50
+
51
+ override fun invoke(op: String, payload: String, promise: Promise) {
52
+ scope.launch {
53
+ settle(promise) { bridge().dispatch(op, payload) }
54
+ }
55
+ }
56
+
57
+ override fun subscribe(stream: String, params: String, promise: Promise) {
58
+ scope.launch {
59
+ settle(promise) { bridge().subscribe(stream, params) }
60
+ }
61
+ }
62
+
63
+ override fun unsubscribe(subscriptionId: String) {
64
+ synchronized(this) { attached }?.unsubscribe(subscriptionId)
65
+ }
66
+
67
+ /** The runtime is going away. The client is not: the next runtime attaches to the same one. */
68
+ override fun invalidate() {
69
+ synchronized(this) {
70
+ attached?.invalidate()
71
+ attached = null
72
+ }
73
+ scope.cancel()
74
+ super.invalidate()
75
+ }
76
+
77
+ private suspend fun settle(promise: Promise, work: suspend () -> String) {
78
+ val payload: TerraErrorPayload = try {
79
+ promise.resolve(work())
80
+ return
81
+ } catch (cancelled: CancellationException) {
82
+ throw cancelled
83
+ } catch (rejected: TerraBridge.BridgeRejection) {
84
+ rejected.payload
85
+ } catch (thrown: Throwable) {
86
+ Rejections.of(thrown)
87
+ }
88
+ // A JSON string preserves payload types across the native/JS bridge, unlike a nested map.
89
+ val encoded = BridgeDispatch.defaultJson.encodeToString(TerraErrorPayload.serializer(), payload)
90
+ promise.reject(payload.code, payload.message, null, Arguments.createMap().apply { putString("payload", encoded) })
91
+ }
92
+
93
+ companion object {
94
+ const val NAME: String = NativeTerraBridgeSpec.NAME
95
+ }
96
+ }
@@ -0,0 +1,26 @@
1
+ package co.tryterra.sdk.reactnative
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+
9
+ /** What autolinking adds to the host's package list. */
10
+ class TerraReactNativePackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
12
+ if (name == TerraBridgeModule.NAME) TerraBridgeModule(reactContext) else null
13
+
14
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider {
15
+ mapOf(
16
+ TerraBridgeModule.NAME to ReactModuleInfo(
17
+ name = TerraBridgeModule.NAME,
18
+ className = TerraBridgeModule.NAME,
19
+ canOverrideExistingModule = false,
20
+ needsEagerInit = false,
21
+ isCxxModule = false,
22
+ isTurboModule = true,
23
+ ),
24
+ )
25
+ }
26
+ }
@@ -0,0 +1,46 @@
1
+ package co.tryterra.sdk.reactnative
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import androidx.startup.AppInitializer
6
+ import androidx.startup.Initializer
7
+ import androidx.work.WorkManagerInitializer
8
+ import co.tryterra.sdk.bridge.BridgeBootstrap
9
+
10
+ /**
11
+ * Declaring WorkManager's initializer as a dependency runs it even when the host removed its
12
+ * manifest entry to supply a custom `WorkerFactory`.
13
+ *
14
+ * A host that removed it configures WorkManager in `Application.onCreate`, which has not run yet,
15
+ * so that host bootstraps there instead.
16
+ */
17
+ class TerraStartup : Initializer<Unit> {
18
+ override fun create(context: Context) {
19
+ val startup = AppInitializer.getInstance(context)
20
+ if (!startup.isEagerlyInitialized(WorkManagerInitializer::class.java)) {
21
+ Log.i(TAG, "WorkManager's default initializer is removed: call TerraReactNative.bootstrap(this) at the end of Application.onCreate")
22
+ return
23
+ }
24
+ startup.initializeComponent(WorkManagerInitializer::class.java)
25
+ TerraReactNative.bootstrap(context)
26
+ }
27
+
28
+ override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
29
+
30
+ private companion object {
31
+ const val TAG = "TerraReactNative"
32
+ }
33
+ }
34
+
35
+ /** The manual bootstrap, for a host that opted out of [TerraStartup]. */
36
+ object TerraReactNative {
37
+ /** What `bridge.not_bootstrapped` tells a developer to fix. */
38
+ internal const val MISSING_LINE: String =
39
+ "<meta-data android:name=\"${BridgeBootstrap.DEV_ID_KEY}\" android:value=\"YOUR_DEV_ID\" /> " +
40
+ "in AndroidManifest.xml's <application>"
41
+
42
+ @JvmStatic
43
+ fun bootstrap(context: Context) {
44
+ BridgeBootstrap.bootstrap(context, TerraStores.registration)
45
+ }
46
+ }
@@ -0,0 +1,13 @@
1
+ package co.tryterra.sdk.reactnative
2
+
3
+ import co.tryterra.sdk.StoreRegistration
4
+ import co.tryterra.sdk.health.samsung.samsungHealth
5
+
6
+ /**
7
+ * The stores this build registers beyond Health Connect: Samsung Health, because the host set
8
+ * `terraSamsungHealth=true`. The add-on also claims Samsung's own writes out of Health Connect, so
9
+ * a step counted by Samsung is not uploaded twice.
10
+ */
11
+ internal object TerraStores {
12
+ val registration: StoreRegistration.() -> Unit = { samsungHealth() }
13
+ }
@@ -0,0 +1,396 @@
1
+ <!-- Generated from surface/terra-surface.json by surface/gen. Do not edit by hand.
2
+ Regenerate with: node surface/gen/src/cli.ts generate -->
3
+
4
+ # What exists on which platform
5
+
6
+ Generated from `surface/terra-surface.json`. A row missing from this page is an op no platform
7
+ implements, which the generator refuses to emit, so the page cannot be quietly incomplete.
8
+
9
+ Two kinds of absence appear here and they are not the same thing. A member absent because the
10
+ platform has no model for it is typed optional in TypeScript, so calling it is a type error. A
11
+ member absent because the SDK has not grown it yet rejects with `bridge.unsupported_on_platform`
12
+ at runtime, and becomes available without a breaking change when the SDK catches up.
13
+
14
+ ## Operations
15
+
16
+ | Op | iOS | Android |
17
+ |---|---|---|
18
+ | `client.attach` | yes | yes |
19
+ | `client.connect` | yes | yes |
20
+ | `client.connections` | yes | yes |
21
+ | `client.availability` | yes | yes |
22
+ | `client.disconnect` | yes | yes |
23
+ | `token.setProviderPresent` | yes | yes |
24
+ | `token.resolve` | yes | yes |
25
+ | `token.reject` | yes | yes |
26
+ | `permissions.request` | yes | yes |
27
+ | `permissions.status` | yes | yes |
28
+ | `permissions.writeStatus` | yes | yes |
29
+ | `permissions.requested` | yes | yes |
30
+ | `permissions.statuses` | - | yes |
31
+ | `permissions.backgroundReadStatus` | - | yes |
32
+ | `permissions.historyReadStatus` | - | yes |
33
+ | `diagnostics.state` | yes | yes |
34
+ | `diagnostics.lastDelivery` | yes | yes |
35
+ | `diagnostics.report` | yes | yes |
36
+ | `diagnostics.send` | yes | yes |
37
+ | `background.isRegistered` | yes | yes |
38
+ | `background.cancel` | - | yes |
39
+ | `body.heartRate` | yes | yes |
40
+ | `body.restingHeartRate` | yes | yes |
41
+ | `body.readings` | yes | yes |
42
+ | `body.logHeartRate` | yes | yes |
43
+ | `body.log` | yes | yes |
44
+ | `body.delete` | yes | yes |
45
+ | `daily.steps` | yes | yes |
46
+ | `daily.totals` | yes | yes |
47
+ | `daily.intraday` | yes | yes |
48
+ | `daily.log` | yes | yes |
49
+ | `daily.delete` | yes | yes |
50
+ | `sleep.segments` | yes | yes |
51
+ | `sleep.log` | yes | yes |
52
+ | `sleep.delete` | yes | yes |
53
+ | `activity.workouts` | yes | yes |
54
+ | `activity.routes` | yes | yes |
55
+ | `activity.intensity` | yes | yes |
56
+ | `activity.log` | yes | yes |
57
+ | `activity.delete` | yes | yes |
58
+ | `nutrition.quantities` | yes | yes |
59
+ | `nutrition.log` | yes | yes |
60
+ | `nutrition.delete` | yes | yes |
61
+ | `nutrition.hydration` | yes | yes |
62
+ | `menstruation.flow` | yes | yes |
63
+ | `menstruation.events` | yes | yes |
64
+ | `athlete.profile` | yes | - |
65
+ | `plannedWorkouts.planned` | yes | - |
66
+ | `plannedWorkouts.markComplete` | yes | - |
67
+ | `plannedWorkouts.delete` | yes | - |
68
+ | `plannedWorkouts.schedulingStatus` | yes | - |
69
+ | `plannedWorkouts.requestScheduling` | yes | - |
70
+
71
+ ## Streams
72
+
73
+ | Stream | iOS | Android |
74
+ |---|---|---|
75
+ | `diagnostics.events` | yes | yes |
76
+ | `body.changes` | yes | yes |
77
+ | `daily.changes` | yes | yes |
78
+ | `sleep.changes` | yes | yes |
79
+ | `activity.changes` | yes | yes |
80
+ | `bridge.tokenRequest` | yes | yes |
81
+
82
+ ## Enum cases
83
+
84
+ | Enum | Case | iOS | Android | Status |
85
+ |---|---|---|---|---|
86
+ | `Source` | `health` | yes | yes | supported |
87
+ | `Source` | `samsungHealth` | - | yes | supported |
88
+ | `DataCategory` | `activity` | yes | yes | supported |
89
+ | `DataCategory` | `body` | yes | yes | supported |
90
+ | `DataCategory` | `daily` | yes | yes | supported |
91
+ | `DataCategory` | `sleep` | yes | yes | supported |
92
+ | `DataCategory` | `nutrition` | yes | yes | supported |
93
+ | `DataCategory` | `menstruation` | yes | yes | supported |
94
+ | `DataCategory` | `athlete` | yes | - | supported |
95
+ | `DataCategory` | `healthObservation` | yes | - | excluded |
96
+ | `PermissionStatus` | `granted` | yes | yes | supported |
97
+ | `PermissionStatus` | `denied` | yes | yes | supported |
98
+ | `PermissionStatus` | `notDetermined` | yes | yes | supported |
99
+ | `PermissionStatus` | `notDisclosed` | yes | yes | supported |
100
+ | `PermissionStatus` | `unsupported` | yes | yes | supported |
101
+ | `PermissionStatus` | `unavailable` | yes | - | supported |
102
+ | `MotionContext` | `unknown` | yes | yes | supported |
103
+ | `MotionContext` | `sedentary` | yes | yes | supported |
104
+ | `MotionContext` | `active` | yes | yes | supported |
105
+ | `Nutrient` | `energyConsumed` | yes | yes | supported |
106
+ | `Nutrient` | `protein` | yes | yes | supported |
107
+ | `Nutrient` | `carbohydrates` | yes | yes | supported |
108
+ | `Nutrient` | `fatTotal` | yes | yes | supported |
109
+ | `Nutrient` | `fatSaturated` | yes | yes | supported |
110
+ | `Nutrient` | `fatMonounsaturated` | yes | yes | supported |
111
+ | `Nutrient` | `fatPolyunsaturated` | yes | yes | supported |
112
+ | `Nutrient` | `sugar` | yes | yes | supported |
113
+ | `Nutrient` | `fiber` | yes | yes | supported |
114
+ | `Nutrient` | `cholesterol` | yes | yes | supported |
115
+ | `Nutrient` | `sodium` | yes | yes | supported |
116
+ | `Nutrient` | `potassium` | yes | yes | supported |
117
+ | `Nutrient` | `calcium` | yes | yes | supported |
118
+ | `Nutrient` | `iron` | yes | yes | supported |
119
+ | `Nutrient` | `magnesium` | yes | yes | supported |
120
+ | `Nutrient` | `zinc` | yes | yes | supported |
121
+ | `Nutrient` | `phosphorus` | yes | yes | supported |
122
+ | `Nutrient` | `iodine` | yes | yes | supported |
123
+ | `Nutrient` | `manganese` | yes | yes | supported |
124
+ | `Nutrient` | `molybdenum` | yes | yes | supported |
125
+ | `Nutrient` | `selenium` | yes | yes | supported |
126
+ | `Nutrient` | `copper` | yes | yes | supported |
127
+ | `Nutrient` | `chromium` | yes | yes | supported |
128
+ | `Nutrient` | `chloride` | yes | yes | supported |
129
+ | `Nutrient` | `caffeine` | yes | yes | supported |
130
+ | `Nutrient` | `vitaminA` | yes | yes | supported |
131
+ | `Nutrient` | `vitaminC` | yes | yes | supported |
132
+ | `Nutrient` | `vitaminD` | yes | yes | supported |
133
+ | `Nutrient` | `vitaminE` | yes | yes | supported |
134
+ | `Nutrient` | `vitaminK` | yes | yes | supported |
135
+ | `Nutrient` | `vitaminB6` | yes | yes | supported |
136
+ | `Nutrient` | `vitaminB12` | yes | yes | supported |
137
+ | `Nutrient` | `thiamin` | yes | yes | supported |
138
+ | `Nutrient` | `riboflavin` | yes | yes | supported |
139
+ | `Nutrient` | `niacin` | yes | yes | supported |
140
+ | `Nutrient` | `folate` | yes | yes | supported |
141
+ | `Nutrient` | `biotin` | yes | yes | supported |
142
+ | `Nutrient` | `pantothenicAcid` | yes | yes | supported |
143
+ | `MealType` | `breakfast` | yes | yes | supported |
144
+ | `MealType` | `lunch` | yes | yes | supported |
145
+ | `MealType` | `dinner` | yes | yes | supported |
146
+ | `MealType` | `snack` | yes | yes | supported |
147
+ | `MealType` | `unknown` | yes | yes | supported |
148
+ | `MenstruationFlow` | `unspecified` | yes | yes | supported |
149
+ | `MenstruationFlow` | `light` | yes | yes | supported |
150
+ | `MenstruationFlow` | `medium` | yes | yes | supported |
151
+ | `MenstruationFlow` | `heavy` | yes | yes | supported |
152
+ | `MenstruationFlow` | `none` | yes | yes | supported |
153
+ | `BiologicalSex` | `female` | yes | - | supported |
154
+ | `BiologicalSex` | `male` | yes | - | supported |
155
+ | `BiologicalSex` | `other` | yes | - | supported |
156
+ | `BiologicalSex` | `notSet` | yes | - | supported |
157
+ | `ActivityMoveMode` | `activeEnergy` | yes | - | supported |
158
+ | `ActivityMoveMode` | `appleMoveTime` | yes | - | supported |
159
+ | `BackgroundRestrictionReason` | `oemRestricted` | - | yes | supported |
160
+ | `BackgroundRestrictionReason` | `backgroundReadDenied` | - | yes | supported |
161
+ | `BackgroundRestrictionReason` | `healthConnectFeatureUnavailable` | - | yes | supported |
162
+ | `BackgroundRestrictionReason` | `storeFeatureUnavailable` | - | yes | supported |
163
+ | `BackgroundRestrictionReason` | `ticksNotRunning` | - | yes | supported |
164
+ | `DiagnosticsReason` | `uploadFailed` | yes | yes | supported |
165
+ | `DiagnosticsReason` | `backfillAbandoned` | yes | yes | supported |
166
+ | `DiagnosticsReason` | `backgroundObservationUnavailable` | yes | yes | supported |
167
+ | `DiagnosticsReason` | `backgroundRestricted` | yes | yes | supported |
168
+ | `DiagnosticsReason` | `backgroundRefreshUnscheduled` | yes | yes | supported |
169
+ | `DiagnosticsReason` | `quiet` | yes | yes | supported |
170
+ | `DiagnosticsReason` | `requested` | yes | yes | supported |
171
+ | `DeviceKeyRevokeOutcome` | `revoked` | yes | yes | supported |
172
+ | `DeviceKeyRevokeOutcome` | `alreadyRevoked` | yes | yes | supported |
173
+ | `DeviceKeyRevokeOutcome` | `routeAbsent` | yes | yes | supported |
174
+ | `FailureCode` | `healthDataUnavailable` | yes | yes | supported |
175
+ | `FailureCode` | `notConnected` | yes | yes | supported |
176
+ | `FailureCode` | `tokenUnavailable` | yes | yes | supported |
177
+ | `FailureCode` | `tokenRejected` | yes | yes | supported |
178
+ | `FailureCode` | `tokenProviderFailed` | yes | yes | supported |
179
+ | `FailureCode` | `offline` | yes | yes | supported |
180
+ | `FailureCode` | `timedOut` | yes | yes | supported |
181
+ | `FailureCode` | `serverError` | yes | yes | supported |
182
+ | `FailureCode` | `transport` | yes | yes | supported |
183
+ | `FailureCode` | `malformedResponse` | yes | yes | supported |
184
+ | `FailureCode` | `userLimitReached` | yes | yes | supported |
185
+ | `FailureCode` | `upgradeRequired` | yes | yes | supported |
186
+ | `FailureCode` | `platform` | yes | yes | supported |
187
+ | `FailureCode` | `deviceKeyUnavailable` | yes | yes | supported |
188
+ | `FailureCode` | `signatureRejected` | yes | yes | supported |
189
+ | `FailureCode` | `linkRevoked` | yes | yes | supported |
190
+ | `FailureCode` | `linkConflict` | yes | yes | supported |
191
+ | `FailureCode` | `clockSkewed` | yes | yes | supported |
192
+ | `FailureCode` | `devIDMismatch` | yes | yes | supported |
193
+ | `FailureCode` | `syncAlreadyRunning` | yes | yes | supported |
194
+ | `FailureCode` | `linkAlreadyRunning` | yes | yes | supported |
195
+ | `FailureCode` | `storeLocked` | yes | yes | supported |
196
+ | `FailureCode` | `storeUnreadable` | yes | yes | supported |
197
+ | `FailureCode` | `deadlineExceeded` | yes | yes | supported |
198
+ | `FailureCode` | `permissionDenied` | yes | yes | supported |
199
+ | `FailureCode` | `authorizationNotDetermined` | yes | yes | supported |
200
+ | `FailureCode` | `sampleNotFound` | yes | yes | supported |
201
+ | `FailureCode` | `rollbackIncomplete` | yes | yes | supported |
202
+ | `FailureCode` | `distanceNotAttributable` | yes | yes | supported |
203
+ | `FailureCode` | `bloodPressureIncomplete` | yes | yes | supported |
204
+ | `FailureCode` | `authorizationUnavailableInExtension` | yes | yes | supported |
205
+ | `FailureCode` | `routeAwaitingConverter` | yes | yes | supported |
206
+ | `FailureCode` | `readQuotaExceeded` | - | yes | supported |
207
+ | `FailureCode` | `plannedWorkoutUnnamed` | yes | - | supported |
208
+ | `WorkoutSchedulingStatus` | `unsupported` | yes | - | supported |
209
+ | `WorkoutSchedulingStatus` | `notDetermined` | yes | - | supported |
210
+ | `WorkoutSchedulingStatus` | `denied` | yes | - | supported |
211
+ | `WorkoutSchedulingStatus` | `authorized` | yes | - | supported |
212
+ | `DayTotalMetric` | `distanceWalkingRunning` | yes | yes | supported |
213
+ | `DayTotalMetric` | `distanceCycling` | yes | yes | supported |
214
+ | `DayTotalMetric` | `distanceSwimming` | yes | yes | supported |
215
+ | `DayTotalMetric` | `distanceWheelchair` | yes | yes | supported |
216
+ | `DayTotalMetric` | `activeEnergyBurned` | yes | yes | supported |
217
+ | `DayTotalMetric` | `basalEnergyBurned` | yes | yes | supported |
218
+ | `DayTotalMetric` | `flightsClimbed` | yes | yes | supported |
219
+ | `DayTotalMetric` | `appleExerciseTime` | yes | - | supported |
220
+ | `DayTotalMetric` | `steps` | yes | yes | excluded |
221
+ | `DayTotalMetric` | `swimmingStrokeCount` | yes | yes | excluded |
222
+ | `DayTotalMetric` | `appleMoveTime` | yes | - | excluded |
223
+ | `DayTotalMetric` | `appleStandTime` | yes | - | excluded |
224
+ | `DayTotalMetric` | `appleStandHours` | yes | - | excluded |
225
+ | `IntradayMetric` | `activeEnergy` | yes | yes | supported |
226
+ | `IntradayMetric` | `basalEnergy` | yes | - | supported |
227
+ | `IntradayMetric` | `distance` | yes | yes | supported |
228
+ | `IntradayMetric` | `floorsClimbed` | yes | yes | supported |
229
+ | `WorkoutIntensityMetric` | `speed` | yes | yes | supported |
230
+ | `WorkoutIntensityMetric` | `power` | yes | yes | supported |
231
+ | `WorkoutIntensityMetric` | `cadence` | yes | yes | supported |
232
+ | `BodyMetric` | `weight` | yes | yes | supported |
233
+ | `BodyMetric` | `height` | yes | yes | supported |
234
+ | `BodyMetric` | `bodyFatPercentage` | yes | yes | supported |
235
+ | `BodyMetric` | `leanBodyMass` | yes | yes | supported |
236
+ | `BodyMetric` | `bmi` | yes | - | supported |
237
+ | `BodyMetric` | `waistCircumference` | yes | - | excluded |
238
+ | `BodyMetric` | `boneMass` | - | yes | excluded |
239
+ | `BodyMetric` | `bodyWaterMass` | - | yes | excluded |
240
+ | `BodyMetric` | `basalMetabolicRate` | - | yes | excluded |
241
+ | `BloodGlucoseUnit` | `mg/dL` | yes | yes | supported |
242
+ | `BloodGlucoseUnit` | `mmol/L` | yes | yes | supported |
243
+ | `GlucoseMealTime` | `preprandial` | yes | yes | supported |
244
+ | `GlucoseMealTime` | `postprandial` | yes | yes | supported |
245
+ | `GlucoseMealTime` | `unknown` | yes | yes | supported |
246
+ | `GlucoseSpecimen` | `capillary` | yes | yes | supported |
247
+ | `GlucoseSpecimen` | `interstitial` | yes | yes | supported |
248
+ | `GlucoseSpecimen` | `plasma` | yes | yes | supported |
249
+ | `GlucoseSpecimen` | `serum` | yes | yes | supported |
250
+ | `GlucoseSpecimen` | `tears` | yes | yes | supported |
251
+ | `GlucoseSpecimen` | `wholeBlood` | yes | yes | supported |
252
+ | `GlucoseSpecimen` | `unknown` | yes | yes | supported |
253
+ | `BodyTemperatureMetric` | `body` | yes | yes | supported |
254
+ | `BodyTemperatureMetric` | `basal` | yes | yes | supported |
255
+ | `BodyTemperatureMetric` | `wrist` | yes | - | supported |
256
+ | `BodyTemperatureMetric` | `skin` | yes | yes | supported |
257
+ | `HeartRateVariabilityMetric` | `sdnn` | yes | yes | supported |
258
+ | `HeartRateVariabilityMetric` | `rmssd` | yes | yes | supported |
259
+ | `VO2MaxTestType` | `maxExercise` | yes | yes | supported |
260
+ | `VO2MaxTestType` | `predictedSubMaxExercise` | yes | yes | supported |
261
+ | `VO2MaxTestType` | `predictedNonExercise` | yes | yes | supported |
262
+ | `MenstrualEventKind` | `intermenstrualBleeding` | yes | yes | supported |
263
+ | `MenstrualEventKind` | `ovulationTest` | yes | yes | supported |
264
+ | `MenstrualEventKind` | `cervicalMucus` | yes | yes | supported |
265
+ | `MenstrualEventKind` | `sexualActivity` | yes | yes | excluded |
266
+ | `MenstrualEventKind` | `pregnancyTest` | yes | - | excluded |
267
+ | `MenstrualEventKind` | `progesteroneTest` | yes | - | excluded |
268
+ | `MenstrualEventKind` | `pregnancy` | yes | - | excluded |
269
+ | `MenstrualEventKind` | `lactation` | yes | - | excluded |
270
+ | `MenstrualEventKind` | `contraceptive` | yes | - | excluded |
271
+ | `MenstrualEventKind` | `persistentIntermenstrualBleeding` | yes | - | excluded |
272
+ | `MenstrualEventKind` | `infrequentCycles` | yes | - | excluded |
273
+ | `MenstrualEventKind` | `irregularCycles` | yes | - | excluded |
274
+ | `MenstrualEventKind` | `prolongedPeriods` | yes | - | excluded |
275
+ | `MenstrualEventKind` | `bleedingDuringPregnancy` | yes | - | excluded |
276
+ | `MenstrualEventKind` | `bleedingAfterPregnancy` | yes | - | excluded |
277
+
278
+ ### Why those cases are not in the API
279
+
280
+ Each one exists in at least one native SDK. They are listed rather than dropped, because a
281
+ case that simply went unmentioned is the bug this whole schema exists to prevent.
282
+
283
+ - `DataCategory.healthObservation` (excluded): docs/sdk-reference.md records it as carrying no HealthKit types yet.
284
+ - `DayTotalMetric.steps` (excluded): daily.steps answers steps, split by writer. A merged total beside it would be two step figures for one day.
285
+ - `DayTotalMetric.swimmingStrokeCount` (excluded): Uploaded, and never part of the 1.x daily read this op replaces.
286
+ - `DayTotalMetric.appleMoveTime` (excluded): A ring figure the 1.x daily read never returned. Uploaded.
287
+ - `DayTotalMetric.appleStandTime` (excluded): A ring figure the 1.x daily read never returned. Uploaded.
288
+ - `DayTotalMetric.appleStandHours` (excluded): A ring figure the 1.x daily read never returned. Uploaded.
289
+ - `BodyMetric.waistCircumference` (excluded): Uploaded, and never part of the 1.x body read body.readings replaces.
290
+ - `BodyMetric.boneMass` (excluded): Uploaded, and never part of the 1.x body read body.readings replaces.
291
+ - `BodyMetric.bodyWaterMass` (excluded): Uploaded, and never part of the 1.x body read body.readings replaces.
292
+ - `BodyMetric.basalMetabolicRate` (excluded): Uploaded, and never part of the 1.x body read body.readings replaces.
293
+ - `MenstrualEventKind.sexualActivity` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
294
+ - `MenstrualEventKind.pregnancyTest` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
295
+ - `MenstrualEventKind.progesteroneTest` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
296
+ - `MenstrualEventKind.pregnancy` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
297
+ - `MenstrualEventKind.lactation` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
298
+ - `MenstrualEventKind.contraceptive` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
299
+ - `MenstrualEventKind.persistentIntermenstrualBleeding` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
300
+ - `MenstrualEventKind.infrequentCycles` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
301
+ - `MenstrualEventKind.irregularCycles` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
302
+ - `MenstrualEventKind.prolongedPeriods` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
303
+ - `MenstrualEventKind.bleedingDuringPregnancy` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
304
+ - `MenstrualEventKind.bleedingAfterPregnancy` (excluded): Uploaded, and never part of the 1.x cycle read menstruation.events replaces.
305
+
306
+ ## Events
307
+
308
+ | Kind | iOS | Android |
309
+ |---|---|---|
310
+ | `connected` | yes | yes |
311
+ | `disconnected` | yes | yes |
312
+ | `linkRevoked` | yes | yes |
313
+ | `permissionResult` | yes | yes |
314
+ | `backgroundWake` | yes | yes |
315
+ | `backgroundRefreshUnscheduled` | yes | yes |
316
+ | `uploadBatch` | yes | yes |
317
+ | `uploadFailed` | yes | yes |
318
+ | `retryScheduled` | yes | yes |
319
+ | `backfillProgress` | yes | yes |
320
+ | `serverBackfillQueued` | yes | yes |
321
+ | `serverBackfillCompleted` | yes | yes |
322
+ | `serverBackfillAbandoned` | yes | yes |
323
+ | `serverBackfillRefused` | yes | yes |
324
+ | `serverBackfillUnsupported` | yes | yes |
325
+ | `serverBackfillPollFailed` | yes | yes |
326
+ | `backgroundObservationUnavailable` | yes | yes |
327
+ | `observationDropped` | yes | yes |
328
+ | `samplesLogged` | yes | yes |
329
+ | `sampleDeleted` | yes | yes |
330
+ | `tokenRefreshed` | yes | yes |
331
+ | `deviceKeyRevokeAnswered` | yes | yes |
332
+ | `deviceKeyRevokeFailed` | yes | yes |
333
+ | `diagnosticsReported` | yes | yes |
334
+ | `backgroundWakeRefused` | yes | - |
335
+ | `dailyDayTooLarge` | yes | - |
336
+ | `plannedWorkoutUpdated` | yes | - |
337
+ | `plannedWorkoutsScheduled` | yes | - |
338
+ | `plannedWorkoutScheduleFailed` | yes | - |
339
+ | `sleepWakeDateTooLarge` | yes | - |
340
+ | `backgroundWorkGap` | - | yes |
341
+ | `backgroundWorkReset` | - | yes |
342
+ | `changeTokenExpired` | - | yes |
343
+ | `historyReadUnavailable` | - | yes |
344
+ | `processExitDecided` | - | yes |
345
+ | `readQuotaExceeded` | - | yes |
346
+ | `routeConsentRequired` | - | yes |
347
+
348
+ ## Error codes
349
+
350
+ | Code | Retryable | iOS | Android | Owner |
351
+ |---|---|---|---|---|
352
+ | `health_data_unavailable` | false | yes | yes | sdk |
353
+ | `not_connected` | false | yes | yes | sdk |
354
+ | `route_awaiting_converter` | false | yes | yes | sdk |
355
+ | `token_unavailable` | false | yes | yes | sdk |
356
+ | `token_rejected` | false | yes | yes | sdk |
357
+ | `token_provider_failed` | false | yes | yes | sdk |
358
+ | `user_limit_reached` | false | yes | yes | sdk |
359
+ | `upgrade_required` | false | yes | yes | sdk |
360
+ | `platform` | false | yes | yes | sdk |
361
+ | `device_key_unavailable` | false | yes | yes | sdk |
362
+ | `signature_rejected` | false | yes | yes | sdk |
363
+ | `clock_skewed` | false | yes | yes | sdk |
364
+ | `link_revoked` | false | yes | yes | sdk |
365
+ | `dev_id_mismatch` | false | yes | yes | sdk |
366
+ | `link_conflict` | true | yes | yes | sdk |
367
+ | `sync_already_running` | false | yes | yes | sdk |
368
+ | `link_already_running` | false | yes | yes | sdk |
369
+ | `store_locked` | true | yes | yes | sdk |
370
+ | `store_unreadable` | false | yes | yes | sdk |
371
+ | `deadline_exceeded` | true | yes | yes | sdk |
372
+ | `read_quota_exceeded` | true | - | yes | sdk |
373
+ | `permission_denied` | false | yes | yes | sdk |
374
+ | `authorization_not_determined` | false | yes | yes | sdk |
375
+ | `sample_not_found` | false | yes | yes | sdk |
376
+ | `rollback_incomplete` | false | yes | yes | sdk |
377
+ | `distance_not_attributable` | false | yes | yes | sdk |
378
+ | `blood_pressure_incomplete` | false | yes | yes | sdk |
379
+ | `authorization_unavailable_in_extension` | false | yes | yes | sdk |
380
+ | `planned_workout_unnamed` | false | yes | - | sdk |
381
+ | `network.transport` | true | yes | yes | sdk |
382
+ | `network.throttled` | true | yes | yes | sdk |
383
+ | `network.server_error` | carried | yes | yes | sdk |
384
+ | `network.malformed_response` | false | yes | yes | sdk |
385
+ | `network.offline` | true | yes | - | sdk |
386
+ | `network.timed_out` | true | yes | - | sdk |
387
+ | `bridge.not_bootstrapped` | false | - | - | bridge |
388
+ | `bridge.unsupported_on_platform` | false | - | - | bridge |
389
+ | `bridge.no_activity` | true | - | - | bridge |
390
+ | `bridge.permission_sheet_unavailable` | true | - | - | bridge |
391
+ | `bridge.token_timeout` | false | - | - | bridge |
392
+ | `bridge.invalid_payload` | false | - | - | bridge |
393
+
394
+ The SDK-owned half of that table is `docs/sdk-reference.md`'s, which both native test suites
395
+ read. `surface-gen check` asserts the two agree in both directions, so this page cannot drift
396
+ from the vocabulary the SDKs actually speak.
@@ -0,0 +1,48 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>AvailableLibraries</key>
6
+ <array>
7
+ <dict>
8
+ <key>BinaryPath</key>
9
+ <string>TerraSDK.framework/TerraSDK</string>
10
+ <key>DebugSymbolsPath</key>
11
+ <string>dSYMs</string>
12
+ <key>LibraryIdentifier</key>
13
+ <string>ios-arm64_x86_64-simulator</string>
14
+ <key>LibraryPath</key>
15
+ <string>TerraSDK.framework</string>
16
+ <key>SupportedArchitectures</key>
17
+ <array>
18
+ <string>arm64</string>
19
+ <string>x86_64</string>
20
+ </array>
21
+ <key>SupportedPlatform</key>
22
+ <string>ios</string>
23
+ <key>SupportedPlatformVariant</key>
24
+ <string>simulator</string>
25
+ </dict>
26
+ <dict>
27
+ <key>BinaryPath</key>
28
+ <string>TerraSDK.framework/TerraSDK</string>
29
+ <key>DebugSymbolsPath</key>
30
+ <string>dSYMs</string>
31
+ <key>LibraryIdentifier</key>
32
+ <string>ios-arm64</string>
33
+ <key>LibraryPath</key>
34
+ <string>TerraSDK.framework</string>
35
+ <key>SupportedArchitectures</key>
36
+ <array>
37
+ <string>arm64</string>
38
+ </array>
39
+ <key>SupportedPlatform</key>
40
+ <string>ios</string>
41
+ </dict>
42
+ </array>
43
+ <key>CFBundlePackageType</key>
44
+ <string>XFWK</string>
45
+ <key>XCFrameworkFormatVersion</key>
46
+ <string>1.0</string>
47
+ </dict>
48
+ </plist>