Skip to main content

systemprompt_extension/traits/
extension.rs

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