Skip to main content

spreadsheet_mcp/tools/
write_normalize.rs

1use crate::core::write::{normalize_object_edit, normalize_shorthand_edit};
2use crate::errors::InvalidParamsError;
3use crate::model::Warning;
4use crate::tools::fork::{CellEdit, EditBatchParams};
5use anyhow::Result;
6use schemars::JsonSchema;
7use serde::Deserialize;
8
9#[derive(Debug, Clone, Deserialize, JsonSchema)]
10pub struct EditBatchParamsInput {
11    pub fork_id: String,
12    pub sheet_name: String,
13    pub edits: Vec<CellEditInput>,
14}
15
16#[derive(Debug, Clone, Deserialize, JsonSchema)]
17#[serde(untagged)]
18pub enum CellEditInput {
19    Shorthand(String),
20    Object(CellEditV2),
21}
22
23#[derive(Debug, Clone, Deserialize, JsonSchema)]
24pub struct CellEditV2 {
25    pub address: String,
26    #[serde(default)]
27    pub value: Option<String>,
28    #[serde(default)]
29    pub formula: Option<String>,
30    #[serde(default)]
31    pub is_formula: Option<bool>,
32}
33
34pub fn normalize_edit_batch(
35    params: EditBatchParamsInput,
36) -> Result<(EditBatchParams, Vec<Warning>)> {
37    let mut warnings = Vec::new();
38    let mut edits = Vec::with_capacity(params.edits.len());
39
40    for (idx, edit) in params.edits.into_iter().enumerate() {
41        match edit {
42            CellEditInput::Shorthand(entry) => {
43                let (normalized, core_warnings) =
44                    normalize_shorthand_edit(&entry).map_err(|err| {
45                        InvalidParamsError::new("edit_batch", err.to_string())
46                            .with_path(format!("edits[{idx}]"))
47                    })?;
48                edits.push(CellEdit {
49                    address: normalized.address,
50                    value: normalized.value,
51                    is_formula: normalized.is_formula,
52                });
53                warnings.extend(core_warnings.into_iter().map(|warning| Warning {
54                    code: warning.code,
55                    message: warning.message,
56                }));
57            }
58            CellEditInput::Object(obj) => {
59                let normalized =
60                    normalize_object_edit(&obj.address, obj.value, obj.formula, obj.is_formula)
61                        .map_err(|err| {
62                            let path = if err.to_string().contains("address") {
63                                format!("edits[{idx}].address")
64                            } else {
65                                format!("edits[{idx}]")
66                            };
67                            InvalidParamsError::new("edit_batch", err.to_string()).with_path(path)
68                        })?;
69
70                edits.push(CellEdit {
71                    address: normalized.0.address,
72                    value: normalized.0.value,
73                    is_formula: normalized.0.is_formula,
74                });
75                warnings.extend(normalized.1.into_iter().map(|warning| Warning {
76                    code: warning.code,
77                    message: warning.message,
78                }));
79            }
80        }
81    }
82
83    Ok((
84        EditBatchParams {
85            fork_id: params.fork_id,
86            sheet_name: params.sheet_name,
87            edits,
88        },
89        warnings,
90    ))
91}