cranpose_storekit/lib.rs
1#![deny(missing_docs)]
2
3//! StoreKit 2 backend for [`cranpose_services::purchases`](mod@cranpose_services::purchases).
4//!
5//! StoreKit 2 has no Objective-C surface — `Product`, `Transaction` and the
6//! on-device JWS verification are Swift-only — so this crate compiles a small
7//! Swift shim (`swift/storekit.swift`) in its build script and links it
8//! statically. Apple recommends StoreKit 2 for anything that can require
9//! iOS 15; StoreKit 1 (`SKPaymentQueue`) is the Objective-C fallback and is
10//! deliberately not used here.
11//!
12//! On non-Apple targets the build script is a no-op and every entry point
13//! compiles away, so this crate can sit in an Android/Linux/web dependency
14//! graph unnoticed.
15//!
16//! ```no_run
17//! # #[cfg(any(target_os = "ios", target_os = "macos"))]
18//! # fn demo() {
19//! cranpose_storekit::register();
20//! cranpose_services::purchases::configure(&["com.example.app.pro"]);
21//! # }
22//! ```
23//!
24//! # Threading
25//!
26//! StoreKit answers on Swift concurrency executors, so the Swift shim calls
27//! back from arbitrary threads. All state therefore lives behind a
28//! [`std::sync::Mutex`] here, and [`cranpose_services::purchases::Purchases`]
29//! reads a clone of it from the UI thread.
30
31// The crate root denies unsafe code; `apple` is the one boundary module that
32// opts back in, and it is the only place FFI lives. Same shape as cranpose's
33// own platform modules, and
34// `crates/cranpose/tests/platform_scheduling_static.rs` holds the workspace
35// list of modules allowed to do this.
36#[cfg(any(target_os = "ios", target_os = "macos"))]
37mod apple;
38
39#[cfg(any(target_os = "ios", target_os = "macos"))]
40pub use apple::{StoreKitPurchases, register};
41
42/// Installs the StoreKit backend — a no-op on targets without an App Store.
43///
44/// Call it before
45/// [`configure`](cranpose_services::purchases::configure); apps that also run
46/// on Android or desktop can call it unconditionally.
47#[cfg(not(any(target_os = "ios", target_os = "macos")))]
48pub fn register() {}