systemprompt_provider_contracts/
page.rs1use std::any::Any;
4
5use async_trait::async_trait;
6use serde_json::Value;
7use systemprompt_identifiers::LocaleCode;
8
9use crate::error::ProviderResult;
10use crate::web_config::WebConfig;
11
12pub struct PageContext<'a> {
13 pub page_type: &'a str,
14 pub web_config: &'a WebConfig,
15 pub locale: &'a LocaleCode,
16 content_config: &'a (dyn Any + Send + Sync),
17 db_pool: &'a (dyn Any + Send + Sync),
18 content_item: Option<&'a Value>,
19 all_items: Option<&'a [Value]>,
20}
21
22impl std::fmt::Debug for PageContext<'_> {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 f.debug_struct("PageContext")
25 .field("page_type", &self.page_type)
26 .field("web_config", &"<WebConfig>")
27 .field("content_config", &"<dyn Any>")
28 .field("db_pool", &"<dyn Any>")
29 .field("content_item", &self.content_item.is_some())
30 .field("all_items_count", &self.all_items.map(<[_]>::len))
31 .finish()
32 }
33}
34
35impl<'a> PageContext<'a> {
36 #[must_use]
37 pub fn new(
38 page_type: &'a str,
39 web_config: &'a WebConfig,
40 content_config: &'a (dyn Any + Send + Sync),
41 db_pool: &'a (dyn Any + Send + Sync),
42 ) -> Self {
43 Self {
44 page_type,
45 web_config,
46 locale: &web_config.i18n.default_locale,
47 content_config,
48 db_pool,
49 content_item: None,
50 all_items: None,
51 }
52 }
53
54 #[must_use]
55 pub const fn with_locale(mut self, locale: &'a LocaleCode) -> Self {
56 self.locale = locale;
57 self
58 }
59
60 #[must_use]
61 pub const fn with_content_item(mut self, item: &'a Value) -> Self {
62 self.content_item = Some(item);
63 self
64 }
65
66 #[must_use]
67 pub const fn with_all_items(mut self, items: &'a [Value]) -> Self {
68 self.all_items = Some(items);
69 self
70 }
71
72 #[must_use]
73 pub fn content_config<T: 'static>(&self) -> Option<&T> {
74 self.content_config.downcast_ref::<T>()
75 }
76
77 #[must_use]
78 pub fn db_pool<T: 'static>(&self) -> Option<&T> {
79 self.db_pool.downcast_ref::<T>()
80 }
81
82 #[must_use]
83 pub const fn content_item(&self) -> Option<&Value> {
84 self.content_item
85 }
86
87 #[must_use]
88 pub const fn all_items(&self) -> Option<&[Value]> {
89 self.all_items
90 }
91}
92
93#[async_trait]
97pub trait PageDataProvider: Send + Sync {
98 fn provider_id(&self) -> &'static str;
99
100 fn applies_to_pages(&self) -> Vec<String> {
101 vec![]
102 }
103
104 async fn provide_page_data(&self, ctx: &PageContext<'_>) -> ProviderResult<Value>;
105
106 fn priority(&self) -> u32 {
107 100
108 }
109}