use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct NotebookDTO {
pub id: Uuid,
pub owner_id: Uuid,
pub name: String,
pub cells: Vec<NotebookCellDTO>,
pub deletable: bool,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct NotebookCellDTO {
pub id: Uuid,
#[serde(rename = "type")]
pub kind: String,
pub name: String,
pub content: String,
}
#[derive(Debug, Deserialize, ToSchema)]
pub struct NotebookDataDTO {
pub name: Option<String>,
#[serde(default)]
pub cells: Vec<NotebookCellDTO>,
}
#[derive(Debug, Deserialize, ToSchema)]
pub struct RunCodeDataDTO {
pub content: String,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct RunCodeOutcomeDTO {
pub result: Vec<serde_json::Value>,
pub error: Option<String>,
}
impl NotebookDTO {
pub fn from_db(nb: cognee_database::Notebook) -> Self {
let cells = nb
.cells
.as_array()
.map(|arr| {
arr.iter()
.filter_map(|v| serde_json::from_value(v.clone()).ok())
.collect()
})
.unwrap_or_default();
Self {
id: nb.id,
owner_id: nb.owner_id,
name: nb.name,
cells,
deletable: nb.deletable,
created_at: nb.created_at,
}
}
}
#[cfg(test)]
#[allow(
clippy::unwrap_used,
clippy::expect_used,
reason = "test code — panics are acceptable failures"
)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn round_trip_notebook_dto() {
let input = json!({
"id": "00000000-0000-0000-0000-000000000001",
"owner_id": "00000000-0000-0000-0000-000000000002",
"name": "My Notebook",
"cells": [
{
"id": "00000000-0000-0000-0000-000000000003",
"type": "markdown",
"name": "intro",
"content": "# hi"
}
],
"deletable": true,
"created_at": "2024-01-01T00:00:00Z"
});
let dto: NotebookDTO =
serde_json::from_value(input.clone()).expect("deserialize NotebookDTO");
let serialized = serde_json::to_value(&dto).expect("serialize NotebookDTO");
assert_eq!(serialized["name"], "My Notebook");
assert_eq!(serialized["cells"][0]["type"], "markdown");
assert_eq!(serialized["deletable"], true);
}
}