grafbase_hooks/
lib.rs

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