Skip to main content

systemprompt_extension/
traits.rs

1use std::sync::Arc;
2
3use serde_json::Value as JsonValue;
4use systemprompt_provider_contracts::{
5    ComponentRenderer, ContentDataProvider, FrontmatterProcessor, Job, LlmProvider,
6    PageDataProvider, PagePrerenderer, RssFeedProvider, SitemapProvider, TemplateDataExtender,
7    TemplateProvider, ToolProvider,
8};
9
10use crate::asset::{AssetDefinition, AssetPaths};
11use crate::context::ExtensionContext;
12use crate::error::ConfigError;
13use crate::metadata::{ExtensionMetadata, ExtensionRole, SchemaDefinition};
14use crate::migration::Migration;
15#[cfg(feature = "web")]
16use crate::router::ExtensionRouter;
17use crate::router::{ExtensionRouterConfig, SiteAuthConfig};
18
19pub trait Extension: Send + Sync + 'static {
20    fn metadata(&self) -> ExtensionMetadata;
21
22    fn schemas(&self) -> Vec<SchemaDefinition> {
23        vec![]
24    }
25
26    fn migration_weight(&self) -> u32 {
27        100
28    }
29
30    #[cfg(feature = "web")]
31    fn router(&self, ctx: &dyn ExtensionContext) -> Option<ExtensionRouter> {
32        let _ = ctx;
33        None
34    }
35
36    fn router_config(&self) -> Option<ExtensionRouterConfig> {
37        None
38    }
39
40    fn site_auth(&self) -> Option<SiteAuthConfig> {
41        None
42    }
43
44    fn jobs(&self) -> Vec<Arc<dyn Job>> {
45        vec![]
46    }
47
48    fn config_prefix(&self) -> Option<&str> {
49        None
50    }
51
52    fn config_schema(&self) -> Option<JsonValue> {
53        None
54    }
55
56    fn validate_config(&self, config: &JsonValue) -> Result<(), ConfigError> {
57        let _ = config;
58        Ok(())
59    }
60
61    fn llm_providers(&self) -> Vec<Arc<dyn LlmProvider>> {
62        vec![]
63    }
64
65    fn tool_providers(&self) -> Vec<Arc<dyn ToolProvider>> {
66        vec![]
67    }
68
69    fn template_providers(&self) -> Vec<Arc<dyn TemplateProvider>> {
70        vec![]
71    }
72
73    fn component_renderers(&self) -> Vec<Arc<dyn ComponentRenderer>> {
74        vec![]
75    }
76
77    fn template_data_extenders(&self) -> Vec<Arc<dyn TemplateDataExtender>> {
78        vec![]
79    }
80
81    fn page_data_providers(&self) -> Vec<Arc<dyn PageDataProvider>> {
82        vec![]
83    }
84
85    fn page_prerenderers(&self) -> Vec<Arc<dyn PagePrerenderer>> {
86        vec![]
87    }
88
89    fn frontmatter_processors(&self) -> Vec<Arc<dyn FrontmatterProcessor>> {
90        vec![]
91    }
92
93    fn content_data_providers(&self) -> Vec<Arc<dyn ContentDataProvider>> {
94        vec![]
95    }
96
97    fn rss_feed_providers(&self) -> Vec<Arc<dyn RssFeedProvider>> {
98        vec![]
99    }
100
101    fn sitemap_providers(&self) -> Vec<Arc<dyn SitemapProvider>> {
102        vec![]
103    }
104
105    fn required_storage_paths(&self) -> Vec<&'static str> {
106        vec![]
107    }
108
109    fn dependencies(&self) -> Vec<&'static str> {
110        vec![]
111    }
112
113    fn is_required(&self) -> bool {
114        false
115    }
116
117    fn migrations(&self) -> Vec<Migration> {
118        vec![]
119    }
120
121    fn roles(&self) -> Vec<ExtensionRole> {
122        vec![]
123    }
124
125    fn priority(&self) -> u32 {
126        100
127    }
128
129    fn id(&self) -> &'static str {
130        self.metadata().id
131    }
132
133    fn name(&self) -> &'static str {
134        self.metadata().name
135    }
136
137    fn version(&self) -> &'static str {
138        self.metadata().version
139    }
140
141    fn has_schemas(&self) -> bool {
142        !self.schemas().is_empty()
143    }
144
145    #[cfg(feature = "web")]
146    fn has_router(&self, ctx: &dyn ExtensionContext) -> bool {
147        self.router(ctx).is_some()
148    }
149
150    #[cfg(not(feature = "web"))]
151    fn has_router(&self, _ctx: &dyn ExtensionContext) -> bool {
152        false
153    }
154
155    fn has_jobs(&self) -> bool {
156        !self.jobs().is_empty()
157    }
158
159    fn has_config(&self) -> bool {
160        self.config_prefix().is_some()
161    }
162
163    fn has_llm_providers(&self) -> bool {
164        !self.llm_providers().is_empty()
165    }
166
167    fn has_tool_providers(&self) -> bool {
168        !self.tool_providers().is_empty()
169    }
170
171    fn has_template_providers(&self) -> bool {
172        !self.template_providers().is_empty()
173    }
174
175    fn has_component_renderers(&self) -> bool {
176        !self.component_renderers().is_empty()
177    }
178
179    fn has_template_data_extenders(&self) -> bool {
180        !self.template_data_extenders().is_empty()
181    }
182
183    fn has_page_data_providers(&self) -> bool {
184        !self.page_data_providers().is_empty()
185    }
186
187    fn has_page_prerenderers(&self) -> bool {
188        !self.page_prerenderers().is_empty()
189    }
190
191    fn has_frontmatter_processors(&self) -> bool {
192        !self.frontmatter_processors().is_empty()
193    }
194
195    fn has_content_data_providers(&self) -> bool {
196        !self.content_data_providers().is_empty()
197    }
198
199    fn has_rss_feed_providers(&self) -> bool {
200        !self.rss_feed_providers().is_empty()
201    }
202
203    fn has_sitemap_providers(&self) -> bool {
204        !self.sitemap_providers().is_empty()
205    }
206
207    fn has_site_auth(&self) -> bool {
208        self.site_auth().is_some()
209    }
210
211    fn has_storage_paths(&self) -> bool {
212        !self.required_storage_paths().is_empty()
213    }
214
215    fn has_roles(&self) -> bool {
216        !self.roles().is_empty()
217    }
218
219    fn has_migrations(&self) -> bool {
220        !self.migrations().is_empty()
221    }
222
223    fn declares_assets(&self) -> bool {
224        false
225    }
226
227    fn required_assets(&self, _paths: &dyn AssetPaths) -> Vec<AssetDefinition> {
228        vec![]
229    }
230}
231
232#[macro_export]
233macro_rules! register_extension {
234    ($ext_type:ty) => {
235        ::inventory::submit! {
236            $crate::ExtensionRegistration {
237                factory: || ::std::sync::Arc::new(<$ext_type>::default()) as ::std::sync::Arc<dyn $crate::Extension>,
238            }
239        }
240    };
241    ($ext_expr:expr) => {
242        ::inventory::submit! {
243            $crate::ExtensionRegistration {
244                factory: || ::std::sync::Arc::new($ext_expr) as ::std::sync::Arc<dyn $crate::Extension>,
245            }
246        }
247    };
248}