grafbase_hooks/
lib.rs

1#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
2#![deny(missing_docs)]
3#![expect(unsafe_op_in_unsafe_fn)]
4
5#[cfg(feature = "derive")]
6pub use grafbase_hooks_derive::grafbase_hooks;
7
8mod hooks;
9pub mod host_io;
10
11pub use hooks::{
12    EdgeNodePostExecutionArguments, EdgePostExecutionArguments, EdgePreExecutionArguments, HookExports, HookImpls,
13    Hooks, NodePreExecutionArguments, ParentEdgePostExecutionArguments, hooks,
14};
15pub use wit::{
16    CacheStatus, Context, Error, ErrorResponse, ExecutedHttpRequest, ExecutedOperation, ExecutedSubgraphRequest,
17    FieldError, GraphqlResponseStatus, HeaderError, Headers, LogError, RequestError, SharedContext, SubgraphRequest,
18    SubgraphRequestExecutionKind, SubgraphResponse,
19};
20
21#[doc(hidden)]
22pub fn init_hooks(hooks: fn() -> Box<dyn hooks::Hooks>) {
23    // SAFETY: This function is called by the gateway at startup, and the hooks are initialized only once. There can
24    // be no hook calls during initialization. A hook call is by definition single-threaded.
25    unsafe {
26        hooks::HOOKS = Some(hooks());
27    }
28}
29
30/// Registers the hooks type to the gateway. This macro must be called in the library crate root for the local hooks implementation.
31#[macro_export]
32macro_rules! register_hooks {
33    ($name:ident < ($args:tt)* >) => {
34        #[doc(hidden)]
35        #[unsafe(export_name = "init-hooks")]
36        pub extern "C" fn __init_hooks() -> i64 {
37            grafbase_hooks::init_hooks(|| Box::new(<$name<$($args)*> as grafbase_hooks::Hooks>::new()));
38            grafbase_hooks::hooks().hook_implementations() as i64
39        }
40
41        impl<$($args)*> grafbase_hooks::HookExports for $name<$($args)*> {}
42    };
43    ($hook_type:ty) => {
44        #[doc(hidden)]
45        #[unsafe(export_name = "init-hooks")]
46        pub extern "C" fn __init_hooks() -> i64 {
47            grafbase_hooks::init_hooks(|| Box::new(<$hook_type as grafbase_hooks::Hooks>::new()));
48            grafbase_hooks::hooks().hook_implementations() as i64
49        }
50
51        impl grafbase_hooks::HookExports for $hook_type {}
52    };
53}
54
55mod wit {
56    #![expect(clippy::too_many_arguments, missing_docs)]
57
58    wit_bindgen::generate!({
59        skip: ["init-hooks"],
60        path: "./wit/world.wit",
61    });
62}
63
64struct Component;
65
66wit::export!(Component with_types_in wit);