Skip to main content

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