Skip to main content

systemprompt_provider_contracts/
component.rs

1use std::path::PathBuf;
2
3use crate::web_config::WebConfig;
4use anyhow::Result;
5use async_trait::async_trait;
6use serde_json::Value;
7
8#[derive(Debug, Clone)]
9pub enum PartialSource {
10    Embedded(&'static str),
11    File(PathBuf),
12}
13
14#[derive(Debug, Clone)]
15pub struct PartialTemplate {
16    pub name: String,
17    pub source: PartialSource,
18}
19
20impl PartialTemplate {
21    #[must_use]
22    pub fn embedded(name: impl Into<String>, content: &'static str) -> Self {
23        Self {
24            name: name.into(),
25            source: PartialSource::Embedded(content),
26        }
27    }
28
29    #[must_use]
30    pub fn file(name: impl Into<String>, path: impl Into<PathBuf>) -> Self {
31        Self {
32            name: name.into(),
33            source: PartialSource::File(path.into()),
34        }
35    }
36}
37
38#[derive(Debug)]
39pub struct ComponentContext<'a> {
40    pub web_config: &'a WebConfig,
41    pub item: Option<&'a Value>,
42    pub all_items: Option<&'a [Value]>,
43    pub popular_ids: Option<&'a [String]>,
44}
45
46impl<'a> ComponentContext<'a> {
47    #[must_use]
48    pub const fn for_page(web_config: &'a WebConfig) -> Self {
49        Self {
50            web_config,
51            item: None,
52            all_items: None,
53            popular_ids: None,
54        }
55    }
56
57    #[must_use]
58    pub const fn for_content(
59        web_config: &'a WebConfig,
60        item: &'a Value,
61        all_items: &'a [Value],
62        popular_ids: &'a [String],
63    ) -> Self {
64        Self {
65            web_config,
66            item: Some(item),
67            all_items: Some(all_items),
68            popular_ids: Some(popular_ids),
69        }
70    }
71
72    #[must_use]
73    pub const fn for_list(web_config: &'a WebConfig, all_items: &'a [Value]) -> Self {
74        Self {
75            web_config,
76            item: None,
77            all_items: Some(all_items),
78            popular_ids: None,
79        }
80    }
81}
82
83#[derive(Debug)]
84pub struct RenderedComponent {
85    pub html: String,
86    pub variable_name: String,
87}
88
89impl RenderedComponent {
90    #[must_use]
91    pub fn new(variable_name: impl Into<String>, html: impl Into<String>) -> Self {
92        Self {
93            html: html.into(),
94            variable_name: variable_name.into(),
95        }
96    }
97}
98
99#[async_trait]
100pub trait ComponentRenderer: Send + Sync {
101    fn component_id(&self) -> &str;
102
103    fn variable_name(&self) -> &str;
104
105    fn applies_to(&self) -> Vec<String> {
106        vec![]
107    }
108
109    fn partial_template(&self) -> Option<PartialTemplate> {
110        None
111    }
112
113    async fn render(&self, ctx: &ComponentContext<'_>) -> Result<RenderedComponent>;
114
115    fn priority(&self) -> u32 {
116        100
117    }
118}