1use crate::caps::BackendCaps;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, Default)]
7#[serde(transparent)]
8pub struct WorkbookId(pub String);
9
10impl WorkbookId {
11 pub fn as_str(&self) -> &str {
12 &self.0
13 }
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
17pub struct WorkbookDescriptor {
18 pub workbook_id: WorkbookId,
19 pub short_id: String,
20 pub slug: String,
21 pub folder: Option<String>,
22 pub path: String,
23 pub bytes: u64,
24 pub last_modified: Option<String>,
25 pub caps: BackendCaps,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
29pub struct WorkbookListResponse {
30 pub workbooks: Vec<WorkbookDescriptor>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
34pub struct WorkbookDescription {
35 pub workbook_id: WorkbookId,
36 pub short_id: String,
37 pub slug: String,
38 pub path: String,
39 pub bytes: u64,
40 pub sheet_count: usize,
41 pub defined_names: usize,
42 pub tables: usize,
43 pub macros_present: bool,
44 pub last_modified: Option<String>,
45 pub caps: BackendCaps,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
49pub struct WorkbookSummaryResponse {
50 pub workbook_id: WorkbookId,
51 pub workbook_short_id: String,
52 pub slug: String,
53 pub sheet_count: usize,
54 pub total_cells: u64,
55 pub total_formulas: u64,
56 pub breakdown: WorkbookBreakdown,
57 pub region_counts: RegionCountSummary,
58 pub key_named_ranges: Vec<NamedRangeDescriptor>,
59 pub suggested_entry_points: Vec<EntryPoint>,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
63pub struct WorkbookBreakdown {
64 pub data_sheets: u32,
65 pub calculator_sheets: u32,
66 pub parameter_sheets: u32,
67 pub metadata_sheets: u32,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
71pub struct RegionCountSummary {
72 pub data: u32,
73 pub parameters: u32,
74 pub outputs: u32,
75 pub calculator: u32,
76 pub metadata: u32,
77 pub other: u32,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
81pub struct EntryPoint {
82 pub sheet_name: String,
83 pub region_id: Option<u32>,
84 pub bounds: Option<String>,
85 pub rationale: String,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
89pub struct SheetSummary {
90 pub name: String,
91 pub visible: bool,
92 pub row_count: u32,
93 pub column_count: u32,
94 pub non_empty_cells: u32,
95 pub formula_cells: u32,
96 pub cached_values: u32,
97 pub classification: SheetClassification,
98 pub style_tags: Vec<String>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
102#[serde(rename_all = "snake_case")]
103pub enum SheetClassification {
104 Data,
105 Calculator,
106 Mixed,
107 Metadata,
108 Empty,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
112pub struct SheetListResponse {
113 pub workbook_id: WorkbookId,
114 pub workbook_short_id: String,
115 pub sheets: Vec<SheetSummary>,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
119pub struct SheetOverviewResponse {
120 pub workbook_id: WorkbookId,
121 pub workbook_short_id: String,
122 pub sheet_name: String,
123 pub narrative: String,
124 pub regions: Vec<SheetRegion>,
125 pub detected_regions: Vec<DetectedRegion>,
126 pub key_ranges: Vec<String>,
127 pub formula_ratio: f32,
128 pub notable_features: Vec<String>,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
132pub struct SheetRegion {
133 pub kind: RegionKind,
134 pub address: String,
135 pub description: String,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
139pub enum RegionKind {
140 #[serde(rename = "likely_table")]
141 Table,
142 #[serde(rename = "likely_data")]
143 Data,
144 #[serde(rename = "likely_parameters")]
145 Parameters,
146 #[serde(rename = "likely_outputs")]
147 Outputs,
148 #[serde(rename = "likely_calculator")]
149 Calculator,
150 #[serde(rename = "likely_metadata")]
151 Metadata,
152 #[serde(rename = "likely_styles")]
153 Styles,
154 #[serde(rename = "likely_comments")]
155 Comments,
156 #[serde(rename = "unknown")]
157 Other,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
161pub struct DetectedRegion {
162 pub id: u32,
163 pub bounds: String,
164 pub header_row: Option<u32>,
165 pub headers: Vec<String>,
166 pub row_count: u32,
167 pub classification: RegionKind,
168 pub region_kind: Option<RegionKind>,
169 pub confidence: f32,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
173pub struct SheetPageResponse {
174 pub workbook_id: WorkbookId,
175 pub workbook_short_id: String,
176 pub sheet_name: String,
177 pub rows: Vec<RowSnapshot>,
178 pub has_more: bool,
179 pub next_start_row: Option<u32>,
180 pub header_row: Option<RowSnapshot>,
181 pub compact: Option<SheetPageCompact>,
182 pub values_only: Option<SheetPageValues>,
183 pub format: SheetPageFormat,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
187pub struct RowSnapshot {
188 pub row_index: u32,
189 pub cells: Vec<CellSnapshot>,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
193pub struct CellSnapshot {
194 pub address: String,
195 pub value: Option<CellValue>,
196 pub formula: Option<String>,
197 pub cached_value: Option<CellValue>,
198 pub number_format: Option<String>,
199 pub style_tags: Vec<String>,
200 pub notes: Vec<String>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
204#[serde(tag = "kind", content = "value")]
205pub enum CellValue {
206 Text(String),
207 Number(f64),
208 Bool(bool),
209 Error(String),
210 Date(String),
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
214#[serde(rename_all = "snake_case")]
215#[derive(Default)]
216pub enum SheetPageFormat {
217 #[default]
218 Full,
219 Compact,
220 ValuesOnly,
221}
222
223#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
224pub struct SheetPageCompact {
225 pub headers: Vec<String>,
226 pub header_row: Vec<Option<CellValue>>,
227 pub rows: Vec<Vec<Option<CellValue>>>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
231pub struct SheetPageValues {
232 pub rows: Vec<Vec<Option<CellValue>>>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
236pub struct SheetStatisticsResponse {
237 pub workbook_id: WorkbookId,
238 pub workbook_short_id: String,
239 pub sheet_name: String,
240 pub row_count: u32,
241 pub column_count: u32,
242 pub density: f32,
243 pub numeric_columns: Vec<ColumnSummary>,
244 pub text_columns: Vec<ColumnSummary>,
245 pub null_counts: BTreeMap<String, u32>,
246 pub duplicate_warnings: Vec<String>,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
250pub struct ColumnSummary {
251 pub header: Option<String>,
252 pub column: String,
253 pub samples: Vec<CellValue>,
254 pub min: Option<f64>,
255 pub max: Option<f64>,
256 pub mean: Option<f64>,
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
260pub struct SheetFormulaMapResponse {
261 pub workbook_id: WorkbookId,
262 pub workbook_short_id: String,
263 pub sheet_name: String,
264 pub groups: Vec<FormulaGroup>,
265 pub truncated: bool,
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
269pub struct FormulaGroup {
270 pub fingerprint: String,
271 pub addresses: Vec<String>,
272 pub formula: String,
273 pub is_array: bool,
274 pub is_shared: bool,
275 pub is_volatile: bool,
276}
277
278#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
279pub struct FormulaTraceResponse {
280 pub workbook_id: WorkbookId,
281 pub workbook_short_id: String,
282 pub sheet_name: String,
283 pub origin: String,
284 pub direction: TraceDirection,
285 pub layers: Vec<TraceLayer>,
286 pub next_cursor: Option<TraceCursor>,
287 pub notes: Vec<String>,
288}
289
290#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
291pub struct FormulaTraceEdge {
292 pub from: String,
293 pub to: String,
294 pub formula: Option<String>,
295 pub note: Option<String>,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
299pub struct TraceLayer {
300 pub depth: u32,
301 pub summary: TraceLayerSummary,
302 pub highlights: TraceLayerHighlights,
303 pub edges: Vec<FormulaTraceEdge>,
304 pub has_more: bool,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
308pub struct TraceLayerSummary {
309 pub total_nodes: usize,
310 pub formula_nodes: usize,
311 pub value_nodes: usize,
312 pub blank_nodes: usize,
313 pub external_nodes: usize,
314 pub unique_formula_groups: usize,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
318pub struct TraceLayerHighlights {
319 pub top_ranges: Vec<TraceRangeHighlight>,
320 pub top_formula_groups: Vec<TraceFormulaGroupHighlight>,
321 pub notable_cells: Vec<TraceCellHighlight>,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
325pub struct TraceRangeHighlight {
326 pub start: String,
327 pub end: String,
328 pub count: usize,
329 pub literals: usize,
330 pub formulas: usize,
331 pub blanks: usize,
332 pub sample_values: Vec<CellValue>,
333 pub sample_formulas: Vec<String>,
334 pub sample_addresses: Vec<String>,
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
338pub struct TraceFormulaGroupHighlight {
339 pub fingerprint: String,
340 pub formula: String,
341 pub count: usize,
342 pub sample_addresses: Vec<String>,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
346pub struct TraceCellHighlight {
347 pub address: String,
348 pub kind: TraceCellKind,
349 pub value: Option<CellValue>,
350 pub formula: Option<String>,
351}
352
353#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash)]
354#[serde(rename_all = "snake_case")]
355pub enum TraceCellKind {
356 Formula,
357 Literal,
358 Blank,
359 External,
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
363pub struct TraceCursor {
364 pub depth: u32,
365 pub offset: usize,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
369#[serde(rename_all = "snake_case")]
370pub enum TraceDirection {
371 Precedents,
372 Dependents,
373}
374
375#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
376pub struct NamedRangeDescriptor {
377 pub name: String,
378 pub scope: Option<String>,
379 pub refers_to: String,
380 pub kind: NamedItemKind,
381 pub sheet_name: Option<String>,
382 pub comment: Option<String>,
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
386#[serde(rename_all = "snake_case")]
387pub enum NamedItemKind {
388 NamedRange,
389 Table,
390 Formula,
391 Unknown,
392}
393
394#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
395pub struct NamedRangesResponse {
396 pub workbook_id: WorkbookId,
397 pub workbook_short_id: String,
398 pub items: Vec<NamedRangeDescriptor>,
399}
400
401#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
402pub struct FindFormulaMatch {
403 pub address: String,
404 pub sheet_name: String,
405 pub formula: String,
406 pub cached_value: Option<CellValue>,
407 pub context: Vec<RowSnapshot>,
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
411pub struct FindFormulaResponse {
412 pub workbook_id: WorkbookId,
413 pub workbook_short_id: String,
414 pub matches: Vec<FindFormulaMatch>,
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
418pub struct VolatileScanEntry {
419 pub address: String,
420 pub sheet_name: String,
421 pub function: String,
422 pub note: Option<String>,
423}
424
425#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
426pub struct VolatileScanResponse {
427 pub workbook_id: WorkbookId,
428 pub workbook_short_id: String,
429 pub items: Vec<VolatileScanEntry>,
430 pub truncated: bool,
431}
432
433#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
434pub struct SheetStylesResponse {
435 pub workbook_id: WorkbookId,
436 pub workbook_short_id: String,
437 pub sheet_name: String,
438 pub styles: Vec<StyleSummary>,
439 pub conditional_rules: Vec<String>,
440}
441
442#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
443pub struct StyleSummary {
444 pub style_id: String,
445 pub occurrences: u32,
446 pub tags: Vec<String>,
447 pub example_cells: Vec<String>,
448}
449
450#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
451pub struct ManifestStubResponse {
452 pub workbook_id: WorkbookId,
453 pub workbook_short_id: String,
454 pub slug: String,
455 pub sheets: Vec<ManifestSheetStub>,
456}
457
458#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
459pub struct ManifestSheetStub {
460 pub sheet_name: String,
461 pub classification: SheetClassification,
462 pub candidate_expectations: Vec<String>,
463 pub notes: Vec<String>,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
467#[serde(rename_all = "snake_case")]
468pub enum FindMode {
469 #[default]
470 Value,
471 Label,
472}
473
474#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
475#[serde(rename_all = "snake_case")]
476pub enum LabelDirection {
477 Right,
478 Below,
479 Any,
480}
481
482#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
483pub struct FindValueMatch {
484 pub address: String,
485 pub sheet_name: String,
486 pub value: Option<CellValue>,
487 pub row_context: Option<RowContext>,
488 pub neighbors: Option<NeighborValues>,
489 pub label_hit: Option<LabelHit>,
490}
491
492#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
493pub struct RowContext {
494 pub headers: Vec<String>,
495 pub values: Vec<Option<CellValue>>,
496}
497
498#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
499pub struct NeighborValues {
500 pub left: Option<CellValue>,
501 pub right: Option<CellValue>,
502 pub up: Option<CellValue>,
503 pub down: Option<CellValue>,
504}
505
506#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
507pub struct LabelHit {
508 pub label_address: String,
509 pub label: String,
510}
511
512#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
513pub struct FindValueResponse {
514 pub workbook_id: WorkbookId,
515 pub workbook_short_id: String,
516 pub matches: Vec<FindValueMatch>,
517 pub truncated: bool,
518}
519
520pub type TableRow = BTreeMap<String, Option<CellValue>>;
521
522#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
523pub struct ReadTableResponse {
524 pub workbook_id: WorkbookId,
525 pub workbook_short_id: String,
526 pub sheet_name: String,
527 pub table_name: Option<String>,
528 pub headers: Vec<String>,
529 pub rows: Vec<TableRow>,
530 pub total_rows: u32,
531 pub has_more: bool,
532}
533
534#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
535pub struct ColumnTypeSummary {
536 pub name: String,
537 pub inferred_type: String,
538 pub nulls: u32,
539 pub distinct: u32,
540 pub top_values: Vec<String>,
541 pub min: Option<f64>,
542 pub max: Option<f64>,
543 pub mean: Option<f64>,
544}
545
546#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
547pub struct TableProfileResponse {
548 pub workbook_id: WorkbookId,
549 pub workbook_short_id: String,
550 pub sheet_name: String,
551 pub table_name: Option<String>,
552 pub headers: Vec<String>,
553 pub column_types: Vec<ColumnTypeSummary>,
554 pub row_count: u32,
555 pub samples: Vec<TableRow>,
556 pub notes: Vec<String>,
557}
558
559#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
560pub struct RangeValuesResponse {
561 pub workbook_id: WorkbookId,
562 pub workbook_short_id: String,
563 pub sheet_name: String,
564 pub values: Vec<RangeValuesEntry>,
565}
566
567#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
568pub struct RangeValuesEntry {
569 pub range: String,
570 pub rows: Vec<Vec<Option<CellValue>>>,
571}
572
573#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
574pub struct CloseWorkbookResponse {
575 pub workbook_id: WorkbookId,
576 pub message: String,
577}