perspective_viewer/config/
viewer_config.rs1use std::collections::HashMap;
14use std::ops::Deref;
15use std::sync::LazyLock;
16
17use perspective_client::config::*;
18use perspective_js::utils::*;
19use serde::{Deserialize, Deserializer, Serialize};
20use serde_json::Value;
21use ts_rs::TS;
22use wasm_bindgen::prelude::*;
23
24use super::ColumnConfigValues;
25use crate::presentation::ColumnConfigMap;
26
27#[derive(Debug, Default, Serialize, PartialEq)]
30#[serde(deny_unknown_fields)]
31pub struct ViewerConfig<V = String> {
32 pub version: V,
33 pub columns_config: ColumnConfigMap,
34 pub plugin: String,
35 pub plugin_config: Value,
36 pub settings: bool,
37 pub table: Option<String>,
38 pub theme: Option<String>,
39 pub title: Option<String>,
40
41 #[serde(flatten)]
42 pub view_config: ViewConfig,
43}
44
45pub static API_VERSION: LazyLock<&'static str> = LazyLock::new(|| {
46 #[derive(Deserialize)]
47 struct Package {
48 version: &'static str,
49 }
50 let pkg: &'static str = include_str!("../../../package.json");
51 let pkg: Package = serde_json::from_str(pkg).unwrap();
52 pkg.version
53});
54
55impl ViewerConfig {
56 pub fn encode(&self) -> ApiResult<JsValue> {
58 Ok(JsValue::from_serde_ext(self)?)
59 }
60}
61
62#[derive(Clone, Debug, TS, Deserialize, PartialEq, Serialize)]
63#[serde(transparent)]
64pub struct PluginConfig(serde_json::Value);
65
66impl Deref for PluginConfig {
67 type Target = Value;
68
69 fn deref(&self) -> &Self::Target {
70 &self.0
71 }
72}
73
74#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TS)]
75pub struct ViewerConfigUpdate {
76 #[serde(default)]
77 #[ts(as = "Option<_>")]
78 #[ts(optional)]
79 pub version: VersionUpdate,
80
81 #[serde(default)]
82 #[ts(as = "Option<_>")]
83 #[ts(optional)]
84 pub plugin: PluginUpdate,
85
86 #[serde(default)]
87 #[ts(as = "Option<_>")]
88 #[ts(optional)]
89 pub title: TitleUpdate,
90
91 #[serde(default)]
92 #[ts(as = "Option<_>")]
93 #[ts(optional)]
94 pub table: TableUpdate,
95
96 #[serde(default)]
97 #[ts(as = "Option<_>")]
98 #[ts(optional)]
99 pub theme: ThemeUpdate,
100
101 #[serde(default)]
102 #[ts(as = "Option<_>")]
103 #[ts(optional)]
104 pub settings: SettingsUpdate,
105
106 #[serde(default)]
107 #[ts(as = "Option<_>")]
108 #[ts(optional)]
109 pub plugin_config: Option<PluginConfig>,
110
111 #[serde(default)]
112 #[ts(as = "Option<_>")]
113 #[ts(optional)]
114 pub columns_config: ColumnConfigUpdate,
115
116 #[serde(flatten)]
117 pub view_config: ViewConfigUpdate,
118}
119
120impl ViewerConfigUpdate {
121 pub fn decode(update: &JsValue) -> ApiResult<Self> {
124 Ok(update.into_serde_ext()?)
125 }
126
127 pub fn migrate(&self) -> ApiResult<Self> {
128 Ok(self.clone())
130 }
131}
132
133impl std::fmt::Display for ViewerConfigUpdate {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 write!(
136 f,
137 "{}",
138 serde_json::to_string(self).map_err(|_| std::fmt::Error)?
139 )
140 }
141}
142
143#[derive(Clone, Debug, Serialize, PartialEq, TS)]
144#[serde(untagged)]
145pub enum OptionalUpdate<T: Clone> {
147 #[ts(skip)]
148 SetDefault,
149
150 Missing,
153
154 Update(T),
157}
158
159pub type PluginUpdate = OptionalUpdate<String>;
160pub type SettingsUpdate = OptionalUpdate<bool>;
161pub type ThemeUpdate = OptionalUpdate<String>;
162pub type TitleUpdate = OptionalUpdate<String>;
163pub type TableUpdate = OptionalUpdate<String>;
164pub type VersionUpdate = OptionalUpdate<String>;
165pub type ColumnConfigUpdate = OptionalUpdate<HashMap<String, ColumnConfigValues>>;
166
167impl<T: Clone> Default for OptionalUpdate<T> {
169 fn default() -> Self {
170 Self::Missing
171 }
172}
173
174impl<T: Clone> From<Option<T>> for OptionalUpdate<T> {
177 fn from(opt: Option<T>) -> Self {
178 match opt {
179 Some(v) => Self::Update(v),
180 None => Self::SetDefault,
181 }
182 }
183}
184
185impl<'a, T> Deserialize<'a> for OptionalUpdate<T>
188where
189 T: Deserialize<'a> + Clone,
190{
191 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
192 where
193 D: Deserializer<'a>,
194 {
195 Option::deserialize(deserializer).map(Into::into)
196 }
197}