···33 path::PathBuf,
44};
5566+use dto::{Migrator, MigratorTrait};
67use rand::RngExt;
78use sea_orm::{Database, DatabaseConnection};
89···2627 path.clone().canonicalize().unwrap().to_string_lossy()
2728 );
28292929- Database::connect(db_conn_string).await.unwrap()
3030+ let conn = Database::connect(db_conn_string).await.unwrap();
3131+3232+ // run da migrations every time we connect, just in case
3333+ Migrator::up(&conn, None).await.unwrap();
3434+3535+ conn
3036}
+22
src/cli/mod.rs
···25252626#[derive(Subcommand, Debug)]
2727pub enum Commands {
2828+ /// Manage `Zettel`s
2929+ #[command(subcommand)]
3030+ Zettel(ZettelSubcommand),
3131+2832 // / Manage TARS groups.
2933 // #[command(subcommand)]
3034 // Group(GroupSubcommand),
···5054 // Import(ImportArgs),
5155}
52565757+#[derive(Subcommand, Debug)]
5858+/// Subcommand to manage tars groups.
5959+pub enum ZettelSubcommand {
6060+ /// Add a group.
6161+ New {
6262+ #[arg(short, long)]
6363+ /// The file-path for data to pe put into.
6464+ title: String,
6565+ },
6666+ /// List groups.
6767+ List {
6868+ /// The file-path for data to pe put into.
6969+ #[arg(short = 't', long)]
7070+ by_tag: String,
7171+ },
7272+}
7373+5374// #[derive(Subcommand, Debug)]
5475// /// Subcommand to manage tars groups.
5576// pub enum GroupSubcommand {
···6586// /// The file-path for data to pe put into.
6687// pub out_file: PathBuf,
6788// }
8989+//
68906991const VERSION_MESSAGE: &str = concat!(
7092 env!("CARGO_PKG_VERSION"),
···3838#[expect(dead_code)]
3939pub struct AppConfig {
4040 /// The directory where the single instance of the filaments exists.
4141- pub filaments: PathBuf,
4141+ pub workspace: PathBuf,
4242 #[serde(default)]
4343 pub data: PathBuf,
4444 #[serde(default)]
···4646}
47474848/// Configuration for the App
4949-#[expect(dead_code)]
5049#[derive(Debug, Clone)]
5150pub struct Config {
5251 pub app_config: AppConfig,
···114113115114 Ok(Self {
116115 app_config: AppConfig {
117117- filaments: filaments_dir,
116116+ workspace: filaments_dir,
118117 data: get_data_dir(),
119118 config: get_config_dir(),
120119 },
+4
src/types/mod.rs
···19192020mod workspace;
2121pub use workspace::Workspace;
2222+2323+2424+2525+
+4-2
src/types/workspace.rs
···11use std::path::PathBuf;
2233use color_eyre::eyre::{Context, Result};
44-use dto::{Database, DatabaseConnection};
44+use dto::{Database, DatabaseConnection, Migrator, MigratorTrait};
55use tokio::fs::{File, create_dir_all};
66use tracing::debug;
7788/// The `Workspace` in which the filaments exist.
99-#[expect(dead_code)]
109#[derive(Debug, Clone)]
1110pub struct Workspace {
1211 /// Private field so it can only be instantiated from a `Path`
···3938 let conn = Database::connect(db_conn_string)
4039 .await
4140 .context("Failed to connect to the database in the filaments workspace!")?;
4141+4242+ // run da migrations every time we connect, just in case
4343+ Migrator::up(&conn, None).await?;
42444345 Ok(Self {
4446 _private: (),
+38-2
src/types/zettel.rs
···11+use dto::{TagEntity, ZettelActiveModel, ZettelEntity, ZettelModelEx};
12use std::path::PathBuf;
2333-use dto::{NanoId, ZettelModelEx};
44+use color_eyre::eyre::Result;
55+use dto::NanoId;
66+use tokio::fs::File;
4755-use crate::types::Tag;
88+use crate::types::{Tag, Workspace};
69710/// A `Zettel` is a note about a single idea.
811/// It can have many `Tag`s, just meaning it can fall under many
···1821 /// a workspace-local file path, needs to be canonicalized before usage
1922 pub file_path: PathBuf,
2023 pub tags: Vec<Tag>,
2424+}
2525+2626+impl Zettel {
2727+ pub async fn new(title: impl Into<String>, ws: &Workspace) -> Result<Self> {
2828+ // fn new(title: impl Into<String>) -> Result<Self> {
2929+ let title = title.into();
3030+3131+ // make a file that has a random identifier, and then
3232+ // also has the name "title"
3333+ let nano_id = NanoId::default();
3434+3535+ let local_file_path = format!("{nano_id}.md");
3636+3737+ // now we have to create the file
3838+ File::create_new(ws.root.clone().join(&local_file_path)).await?;
3939+4040+ let inserted = ZettelActiveModel::builder()
4141+ .set_title(title)
4242+ .set_file_path(local_file_path)
4343+ .set_nano_id(nano_id)
4444+ .insert(&ws.db)
4545+ .await?;
4646+4747+ // need to load tags...
4848+ let zettel = ZettelEntity::load()
4949+ .filter_by_nano_id(inserted.nano_id)
5050+ .with(TagEntity)
5151+ .one(&ws.db)
5252+ .await?
5353+ .expect("This must exist since we just inserted it");
5454+5555+ Ok(zettel.into())
5656+ }
2157}
22582359impl From<ZettelModelEx> for Zettel {