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