Skip to content

Commit 4d41e12

Browse files
committed
Add uniffi notes to client-patterns
1 parent 2d198c3 commit 4d41e12

2 files changed

Lines changed: 40 additions & 1 deletion

File tree

docs/architecture/sdk/adding-functionality.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ impl FoldersClient {
186186
}
187187
```
188188

189-
The wrapper should convert errors into `BitwardenError`.
189+
The wrapper should convert errors into `BitwardenError`. When introducing a new error type, add a
190+
variant for it in [`bitwarden-uniffi/src/error.rs`][uniffi-error] and implement the `From`
191+
conversion.
190192

191193
## Ownership
192194

@@ -195,6 +197,8 @@ crate, coordinate with the Platform team to establish ownership and review expec
195197

196198
[pm-lib]: https://github.com/bitwarden/sdk-internal/blob/main/crates/bitwarden-pm/src/lib.rs
197199
[state-crate]: https://github.com/bitwarden/sdk-internal/tree/main/crates/bitwarden-state
200+
[uniffi-error]:
201+
https://github.com/bitwarden/sdk-internal/blob/main/crates/bitwarden-uniffi/src/error.rs
198202
[uniffi-lib]: https://github.com/bitwarden/sdk-internal/blob/main/crates/bitwarden-uniffi/src/lib.rs
199203
[uniffi-sends]:
200204
https://github.com/bitwarden/sdk-internal/blob/main/crates/bitwarden-uniffi/src/tool/sends.rs

docs/architecture/sdk/client-patterns.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,38 @@ If the client will be exposed over WASM, annotate both the struct and its `impl`
4242
#[cfg_attr(feature = "wasm", wasm_bindgen)]
4343
```
4444

45+
### UniFFI wrappers
46+
47+
Mobile clients access the SDK through thin wrapper structs in the `bitwarden-uniffi` crate. Each
48+
wrapper holds a `SharedClient` (a type alias for `Arc<Client>`) and delegates to the underlying Rust
49+
client:
50+
51+
```rust
52+
pub struct FoldersClient(pub(crate) SharedClient);
53+
54+
#[uniffi::export]
55+
impl FoldersClient {
56+
pub async fn get(&self, folder_id: FolderId) -> Result<FolderView> {
57+
Ok(self.0.vault().folders().get(folder_id).await?)
58+
}
59+
}
60+
```
61+
62+
The wrapper mirrors the structure of the Rust client hierarchy — parent wrappers expose child
63+
wrappers through accessor methods, just like the application interface clients do. For example, a
64+
`VaultClient` wrapper returns `Arc<FoldersClient>`.
65+
66+
#### Error conversion
67+
68+
UniFFI wrappers use a crate-level `Result<T>` type alias that maps errors to `BitwardenError`. This
69+
ensures all errors crossing the FFI boundary are converted into a type that UniFFI can serialize for
70+
Kotlin and Swift consumers. Use the `?` operator in wrapper methods to automatically convert
71+
domain-specific errors through the `From<E> for BitwardenError` implementations.
72+
73+
When introducing a new error type, add a variant for it in
74+
[`bitwarden-uniffi/src/error.rs`][uniffi-error] and implement the `From` conversion so it can be
75+
propagated with `?`.
76+
4577
## Extension traits
4678

4779
Feature crates connect to the SDK `Client` through extension traits. This keeps feature code
@@ -188,3 +220,6 @@ async fn test_get_folder_not_found() {
188220
assert!(matches!(result.unwrap_err(), GetFolderError::ItemNotFound(_)));
189221
}
190222
```
223+
224+
[uniffi-error]:
225+
https://github.com/bitwarden/sdk-internal/blob/main/crates/bitwarden-uniffi/src/error.rs

0 commit comments

Comments
 (0)