notion_into_sqlite/
notion_database.rs1use anyhow::{anyhow, Result};
2use serde_json::Value;
3use std::collections::HashMap;
4
5#[derive(Debug, PartialEq)]
11pub enum NotionPropertyType {
12 RichText,
13 Number,
14 Select,
15 MultiSelect,
16 Date,
17 Formula,
18 Relation,
19 Rollup,
20 Title,
21 People,
22 Files,
23 Checkbox,
24 Url,
25 Email,
26 PhoneNumber,
27 CreatedTime,
28 CreatedBy,
29 LastEditedTime,
30 LastEditedBy,
31 Other,
32}
33
34#[derive(Debug)]
35pub struct NotionProperty {
36 pub name: String,
37 pub property_type: NotionPropertyType,
38 pub property_raw_type: String,
39}
40
41#[derive(Debug)]
42pub struct NotionDatabaseSchema {
43 pub properties: HashMap<String, NotionProperty>,
44}
45
46pub fn parse_database_schema(database_resp: &Value) -> Result<NotionDatabaseSchema> {
47 validate_object_type(database_resp)?;
48
49 let raw_properties = database_resp
50 .as_object()
51 .and_then(|resp| resp.get("properties"))
52 .and_then(|prop| prop.as_object())
53 .ok_or_else(|| anyhow!(r#"It must have "properties" object."#))?;
54
55 let properties = raw_properties
56 .keys()
57 .filter_map(|key| {
58 let property = raw_properties.get(key)?.as_object()?;
59 let name = property.get("name")?.as_str()?;
60 let property_raw_type = property.get("type")?.as_str()?;
61 let property_type = match property_raw_type {
62 "rich_text" => NotionPropertyType::RichText,
63 "number" => NotionPropertyType::Number,
64 "select" => NotionPropertyType::Select,
65 "multi_select" => NotionPropertyType::MultiSelect,
66 "date" => NotionPropertyType::Date,
67 "formula" => NotionPropertyType::Formula,
68 "relation" => NotionPropertyType::Relation,
69 "rollup" => NotionPropertyType::Rollup,
70 "title" => NotionPropertyType::Title,
71 "people" => NotionPropertyType::People,
72 "files" => NotionPropertyType::Files,
73 "checkbox" => NotionPropertyType::Checkbox,
74 "url" => NotionPropertyType::Url,
75 "email" => NotionPropertyType::Email,
76 "phone_number" => NotionPropertyType::PhoneNumber,
77 "created_time" => NotionPropertyType::CreatedTime,
78 "created_by" => NotionPropertyType::CreatedBy,
79 "last_edited_time" => NotionPropertyType::LastEditedTime,
80 "last_edited_by" => NotionPropertyType::LastEditedBy,
81 _ => NotionPropertyType::Other,
82 };
83 Some((
84 name.to_string(),
85 NotionProperty {
86 name: name.to_string(),
87 property_raw_type: property_raw_type.to_string(),
88 property_type,
89 },
90 ))
91 })
92 .collect::<HashMap<String, NotionProperty>>();
93
94 Ok(NotionDatabaseSchema { properties })
95}
96
97fn validate_object_type(database_resp: &Value) -> Result<()> {
98 let object_field = database_resp
99 .as_object()
100 .and_then(|o| o.get("object"))
101 .and_then(|o| o.as_str())
102 .ok_or_else(|| anyhow!(r#"It must have `"object": "database"`."#.to_string()))?;
103
104 if object_field == "database" {
105 Ok(())
106 } else {
107 Err(anyhow!(
108 r#"It must have `"object": "database"`, but was "{}""#,
109 object_field
110 ))
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_validate_object_type() {
120 let data = r#"
121 {
122 "object": "database"
123 }
124 "#;
125 let json = serde_json::from_str(data).unwrap();
126 assert!(validate_object_type(&json).is_ok());
127
128 let data = r#"
129 {
130 "object": "xxx"
131 }
132 "#;
133 let json = serde_json::from_str(data).unwrap();
134 assert!(validate_object_type(&json).is_err());
135
136 let data = r#"
137 {}
138 "#;
139 let json = serde_json::from_str(data).unwrap();
140 assert!(validate_object_type(&json).is_err());
141 }
142}