Skip to main content

makeshop_extensions/
lib.rs

1//! SDK for implementing makeshop guest extensions in Rust.
2//!
3//! A guest implements exactly one entrypoint. Enable the Cargo feature for that entrypoint and
4//! annotate its function with [`hook`] or [`event`]; the attribute generates the component
5//! wiring. Enabling several entrypoint features at once fails to build, because their host
6//! imports would be mixed into one component.
7//!
8//! The package is named `makeshop-extensions-sdk` and is imported as `makeshop_extensions`.
9//!
10//! # Hooks and events
11//!
12//! A hook interrupts the surrounding operation: it runs synchronously, and the value it returns
13//! decides what happens next. An event is a delivery: a failed handler is retried, and a handler
14//! that gives up sends the delivery to dead-letter, so an event handler must be idempotent.
15//! Annotating an entrypoint with the wrong attribute is a compile error that names the other one.
16//!
17//! # Contract versions
18//!
19//! The `-vN` suffix of an entrypoint feature is the major version of its contract, which moves
20//! independently of the crate version. A contract is not rewritten in place: a new major arrives
21//! as an additional feature, so migrating changes one line in `Cargo.toml`. There is no
22//! unsuffixed alias meaning "the latest contract", so a rebuild alone never changes the contract
23//! a guest is built against.
24//!
25//! # Host APIs and tests
26//!
27//! [`host`] provides connector calls, execution context, UUID generation, and runtime logging as
28//! canonical SDK types rather than per-entrypoint bindings, so guest code reads the same across
29//! entrypoints. Endpoints, credentials, retries, and default headers come from the deployment
30//! configuration; a guest names a connector and builds a body.
31//!
32//! The attributes expand to component wiring only for `wasm32` targets, so in a native build an
33//! entrypoint stays an ordinary function that `cargo test` can call. [`testing`] provides the
34//! harness that supplies connector responses, an execution context, and log capture.
35
36#![deny(unsafe_code)]
37#![warn(missing_docs)]
38
39pub use makeshop_extensions_macros::{event, hook};
40
41pub mod host;
42
43/// Internal wiring used only by `#[makeshop_extensions::hook]` expansion.
44/// Guest code must not call this module directly.
45#[doc(hidden)]
46pub mod __internal {
47    use std::sync::Once;
48
49    static PANIC_HOOK: Once = Once::new();
50
51    // Installs a hook once to record panic details in the runtime log.
52    pub fn init_panic_hook() {
53        PANIC_HOOK.call_once(|| {
54            std::panic::set_hook(Box::new(|panic_info| {
55                let message = panic_info
56                    .payload()
57                    .downcast_ref::<&str>()
58                    .map(|s| (*s).to_string())
59                    .or_else(|| panic_info.payload().downcast_ref::<String>().cloned())
60                    .unwrap_or_else(|| "non-string panic payload".to_string());
61                let location = panic_info
62                    .location()
63                    .map(|location| format!("{}:{}", location.file(), location.line()))
64                    .unwrap_or_else(|| "unknown".to_string());
65                crate::host::error(
66                    "guest panic",
67                    serde_json::json!({
68                        "panic_message": message,
69                        "location": location,
70                    }),
71                );
72            }));
73        });
74    }
75}
76
77#[cfg(not(target_arch = "wasm32"))]
78pub mod testing;
79
80#[cfg(feature = "order-completed-content-v1")]
81pub use content_blocks;
82
83#[cfg(feature = "finalize-checkout-validation-v1")]
84pub mod finalize_checkout_validation;
85#[cfg(feature = "order-completed-v1")]
86pub mod order_completed;
87#[cfg(feature = "order-completed-content-v1")]
88pub mod order_completed_content;
89
90#[cfg(feature = "finalize-checkout-validation-v1")]
91#[doc(hidden)]
92pub use finalize_checkout_validation::bindings::export_finalize_checkout_validation;
93#[cfg(feature = "order-completed-v1")]
94#[doc(hidden)]
95pub use order_completed::bindings::export_order_completed;
96#[cfg(feature = "order-completed-content-v1")]
97#[doc(hidden)]
98pub use order_completed_content::bindings::export_order_completed_content;