mockforge_plugin_sdk/macros.rs
1//! Helper macros for plugin development
2
3/// Export a plugin with boilerplate
4///
5/// This macro generates the necessary WASM exports for your plugin.
6///
7/// # Example
8///
9/// ```rust,no_run
10/// use mockforge_plugin_sdk::prelude::*;
11///
12/// #[derive(Debug)]
13/// pub struct MyPlugin;
14///
15/// #[async_trait]
16/// impl AuthPlugin for MyPlugin {
17/// async fn authenticate(&self, context: &PluginContext, credentials: &AuthCredentials) -> PluginResult<AuthResult> {
18/// Ok(AuthResult::authenticated("user123"))
19/// }
20/// }
21///
22/// export_plugin!(MyPlugin);
23/// ```
24#[macro_export]
25macro_rules! export_plugin {
26 ($plugin_type:ty) => {
27 /// Create plugin instance
28 #[no_mangle]
29 pub extern "C" fn create_plugin() -> *mut std::ffi::c_void {
30 let plugin = Box::new(<$plugin_type>::default());
31 Box::into_raw(plugin) as *mut std::ffi::c_void
32 }
33
34 /// Destroy plugin instance
35 #[no_mangle]
36 pub extern "C" fn destroy_plugin(ptr: *mut std::ffi::c_void) {
37 if !ptr.is_null() {
38 unsafe {
39 let _ = Box::from_raw(ptr as *mut $plugin_type);
40 }
41 }
42 }
43 };
44}
45
46/// Generate a plugin configuration struct
47///
48/// # Example
49///
50/// ```rust,no_run
51/// use mockforge_plugin_sdk::plugin_config;
52///
53/// plugin_config! {
54/// id = "my-plugin",
55/// version = "1.0.0",
56/// name = "My Plugin",
57/// description = "A custom plugin",
58/// types = ["auth"],
59/// author = {
60/// name = "Your Name",
61/// email = "your.email@example.com",
62/// },
63/// }
64/// ```
65#[macro_export]
66macro_rules! plugin_config {
67 (
68 id = $id:expr,
69 version = $version:expr,
70 name = $name:expr,
71 description = $desc:expr,
72 types = [$($plugin_type:expr),*],
73 author = {
74 name = $author_name:expr,
75 email = $author_email:expr $(,)?
76 } $(,)?
77 ) => {
78 /// Plugin configuration
79 pub fn plugin_config() -> mockforge_plugin_core::PluginManifest {
80 use mockforge_plugin_core::*;
81
82 let info = PluginInfo::new(
83 PluginId::new($id),
84 PluginVersion::parse($version).expect("Invalid version"),
85 $name,
86 $desc,
87 PluginAuthor::new($author_name).with_email($author_email),
88 );
89
90 let mut manifest = PluginManifest::new(info);
91 $(
92 manifest.types.push($plugin_type.to_string());
93 )*
94 manifest
95 }
96 };
97}
98
99/// Quick test macro for plugin functions
100///
101/// # Example
102///
103/// ```rust,no_run
104/// # use mockforge_plugin_sdk::prelude::*;
105/// # async fn test_auth() {
106/// plugin_test! {
107/// test_name: authenticate_valid_user,
108/// plugin: MyAuthPlugin,
109/// input: AuthCredentials::basic("user", "pass"),
110/// assert: |result| {
111/// assert!(result.is_ok());
112/// }
113/// }
114/// # }
115/// ```
116#[macro_export]
117macro_rules! plugin_test {
118 (
119 test_name: $name:ident,
120 plugin: $plugin:ty,
121 input: $input:expr,
122 assert: $assert:expr
123 ) => {
124 #[tokio::test]
125 async fn $name() {
126 let plugin = <$plugin>::default();
127 let context = mockforge_plugin_core::PluginContext::default();
128 let result = plugin.process(&context, $input).await;
129 ($assert)(result);
130 }
131 };
132}
133
134/// Create a mock plugin context for testing
135///
136/// # Example
137///
138/// ```rust,no_run
139/// # use mockforge_plugin_sdk::prelude::*;
140/// let context = mock_context! {
141/// plugin_id: "test-plugin",
142/// request_id: "req-123",
143/// };
144/// ```
145#[macro_export]
146macro_rules! mock_context {
147 (
148 plugin_id: $plugin_id:expr,
149 request_id: $request_id:expr $(,)?
150 ) => {{
151 use mockforge_plugin_core::PluginContext;
152 PluginContext {
153 plugin_id: $plugin_id.to_string(),
154 request_id: $request_id.to_string(),
155 ..Default::default()
156 }
157 }};
158
159 () => {{
160 mockforge_plugin_core::PluginContext::default()
161 }};
162}
163
164#[cfg(test)]
165mod tests {
166
167 #[test]
168 fn test_macro_compilation() {
169 // Just verify macros compile
170 // Test passes if compilation succeeds
171 }
172}