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#[cfg(any(target_os = "ios", target_os = "macos"))]
32mod apple;
33
34#[cfg(any(target_os = "ios", target_os = "macos"))]
35pub use apple::{StoreKitPurchases, register};
36
37/// Installs the StoreKit backend — a no-op on targets without an App Store.
38///
39/// Call it before
40/// [`configure`](cranpose_services::purchases::configure); apps that also run
41/// on Android or desktop can call it unconditionally.
42#[cfg(not(any(target_os = "ios", target_os = "macos")))]
43pub fn register() {}