chore: cleanups and refactorings for cleaner code
This commit is contained in:
@@ -2,7 +2,20 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Tracks content hashes of generated files to skip unchanged writes.
|
||||
/// Matches the `generated_file_hashes` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(
|
||||
table_name = crate::db::schema::generated_file_hashes,
|
||||
check_for_backend(diesel::sqlite::Sqlite)
|
||||
)]
|
||||
pub struct GeneratedFileHash {
|
||||
pub project_id: String,
|
||||
pub relative_path: String,
|
||||
@@ -10,7 +23,10 @@ pub struct GeneratedFileHash {
|
||||
pub updated_at: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow,
|
||||
)]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum NotificationEntity {
|
||||
Post,
|
||||
@@ -19,7 +35,10 @@ pub enum NotificationEntity {
|
||||
Template,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow,
|
||||
)]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum NotificationAction {
|
||||
Created,
|
||||
@@ -27,14 +46,68 @@ pub enum NotificationAction {
|
||||
Deleted,
|
||||
}
|
||||
|
||||
impl std::str::FromStr for NotificationEntity {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"post" => Ok(Self::Post),
|
||||
"media" => Ok(Self::Media),
|
||||
"script" => Ok(Self::Script),
|
||||
"template" => Ok(Self::Template),
|
||||
_ => Err(format!("invalid NotificationEntity: {value}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NotificationEntity {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Post => "post",
|
||||
Self::Media => "media",
|
||||
Self::Script => "script",
|
||||
Self::Template => "template",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for NotificationAction {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"created" => Ok(Self::Created),
|
||||
"updated" => Ok(Self::Updated),
|
||||
"deleted" => Ok(Self::Deleted),
|
||||
_ => Err(format!("invalid NotificationAction: {value}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NotificationAction {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Created => "created",
|
||||
Self::Updated => "updated",
|
||||
Self::Deleted => "deleted",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Notification for CLI-to-app synchronization.
|
||||
/// Matches the `db_notifications` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, diesel::Queryable, diesel::Selectable)]
|
||||
#[diesel(
|
||||
table_name = crate::db::schema::db_notifications,
|
||||
check_for_backend(diesel::sqlite::Sqlite)
|
||||
)]
|
||||
pub struct DbNotification {
|
||||
#[diesel(deserialize_as = i32)]
|
||||
pub id: i64,
|
||||
pub entity_type: NotificationEntity,
|
||||
pub entity_id: String,
|
||||
pub action: NotificationAction,
|
||||
#[diesel(deserialize_as = crate::db::types::DbBool)]
|
||||
pub from_cli: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub seen_at: Option<i64>,
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
use diesel::ExpressionMethods;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A media item (image, video, etc.).
|
||||
/// Matches the `media` table schema.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::media, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct Media {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
@@ -30,6 +42,10 @@ pub struct Media {
|
||||
pub checksum: Option<String>,
|
||||
/// JSON-serialized string array in DB.
|
||||
#[serde(default)]
|
||||
#[diesel(
|
||||
deserialize_as = crate::db::types::DbStringList,
|
||||
serialize_as = crate::db::types::DbStringList
|
||||
)]
|
||||
pub tags: Vec<String>,
|
||||
pub created_at: i64,
|
||||
pub updated_at: i64,
|
||||
@@ -37,7 +53,21 @@ pub struct Media {
|
||||
|
||||
/// A translation of media metadata into another language.
|
||||
/// Matches the `media_translations` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(
|
||||
table_name = crate::db::schema::media_translations,
|
||||
check_for_backend(diesel::sqlite::Sqlite)
|
||||
)]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct MediaTranslation {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
use diesel::ExpressionMethods;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow,
|
||||
)]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum PostStatus {
|
||||
Draft,
|
||||
@@ -9,17 +13,49 @@ pub enum PostStatus {
|
||||
}
|
||||
|
||||
impl PostStatus {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Draft => "draft",
|
||||
Self::Published => "published",
|
||||
Self::Archived => "archived",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this status is valid for a translation (draft or published only).
|
||||
pub fn is_valid_for_translation(&self) -> bool {
|
||||
matches!(self, PostStatus::Draft | PostStatus::Published)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for PostStatus {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"draft" => Ok(Self::Draft),
|
||||
"published" => Ok(Self::Published),
|
||||
"archived" => Ok(Self::Archived),
|
||||
_ => Err(format!("invalid PostStatus: {value}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A blog post. Matches the `posts` table schema.
|
||||
///
|
||||
/// NOTE: `content` is null for published posts — body lives in the filesystem
|
||||
/// `.md` file only. Draft content is stored in DB.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::posts, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct Post {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
@@ -36,6 +72,10 @@ pub struct Post {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub language: Option<String>,
|
||||
#[serde(default)]
|
||||
#[diesel(
|
||||
deserialize_as = crate::db::types::DbBool,
|
||||
serialize_as = crate::db::types::DbBool
|
||||
)]
|
||||
pub do_not_translate: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub template_slug: Option<String>,
|
||||
@@ -44,9 +84,17 @@ pub struct Post {
|
||||
pub checksum: Option<String>,
|
||||
/// JSON-serialized string array in DB.
|
||||
#[serde(default)]
|
||||
#[diesel(
|
||||
deserialize_as = crate::db::types::DbStringList,
|
||||
serialize_as = crate::db::types::DbStringList
|
||||
)]
|
||||
pub tags: Vec<String>,
|
||||
/// JSON-serialized string array in DB.
|
||||
#[serde(default)]
|
||||
#[diesel(
|
||||
deserialize_as = crate::db::types::DbStringList,
|
||||
serialize_as = crate::db::types::DbStringList
|
||||
)]
|
||||
pub categories: Vec<String>,
|
||||
// Published snapshot fields (used for diff detection)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -68,7 +116,21 @@ pub struct Post {
|
||||
|
||||
/// A translation of a post into another language.
|
||||
/// Matches the `post_translations` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(
|
||||
table_name = crate::db::schema::post_translations,
|
||||
check_for_backend(diesel::sqlite::Sqlite)
|
||||
)]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct PostTranslation {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
@@ -91,7 +153,10 @@ pub struct PostTranslation {
|
||||
|
||||
/// A link between two posts (tracked for backlinks).
|
||||
/// Matches the `post_links` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, Deserialize, diesel::Queryable, diesel::Selectable, diesel::Insertable,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::post_links, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct PostLink {
|
||||
pub id: String,
|
||||
pub source_post_id: String,
|
||||
@@ -103,7 +168,10 @@ pub struct PostLink {
|
||||
|
||||
/// Association between a post and media item.
|
||||
/// Matches the `post_media` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, Deserialize, diesel::Queryable, diesel::Selectable, diesel::Insertable,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::post_media, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct PostMedia {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
use diesel::ExpressionMethods;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A bDS project. Matches the `projects` table schema.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::projects, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct Project {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
@@ -10,13 +22,27 @@ pub struct Project {
|
||||
pub description: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub data_path: Option<String>,
|
||||
#[diesel(
|
||||
deserialize_as = crate::db::types::DbBool,
|
||||
serialize_as = crate::db::types::DbBool
|
||||
)]
|
||||
pub is_active: bool,
|
||||
pub created_at: i64,
|
||||
pub updated_at: i64,
|
||||
}
|
||||
|
||||
/// Key-value settings. Matches the `settings` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::settings, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct Setting {
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
use diesel::ExpressionMethods;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow,
|
||||
)]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ScriptKind {
|
||||
Macro,
|
||||
@@ -8,15 +12,73 @@ pub enum ScriptKind {
|
||||
Transform,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow,
|
||||
)]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ScriptStatus {
|
||||
Draft,
|
||||
Published,
|
||||
}
|
||||
|
||||
impl ScriptKind {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Macro => "macro",
|
||||
Self::Utility => "utility",
|
||||
Self::Transform => "transform",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for ScriptKind {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"macro" => Ok(Self::Macro),
|
||||
"utility" => Ok(Self::Utility),
|
||||
"transform" => Ok(Self::Transform),
|
||||
_ => Err(format!("invalid ScriptKind: {value}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ScriptStatus {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Draft => "draft",
|
||||
Self::Published => "published",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for ScriptStatus {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"draft" => Ok(Self::Draft),
|
||||
"published" => Ok(Self::Published),
|
||||
_ => Err(format!("invalid ScriptStatus: {value}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A user-authored script. Matches the `scripts` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::scripts, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct Script {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
@@ -24,6 +86,10 @@ pub struct Script {
|
||||
pub title: String,
|
||||
pub kind: ScriptKind,
|
||||
pub entrypoint: String,
|
||||
#[diesel(
|
||||
deserialize_as = crate::db::types::DbBool,
|
||||
serialize_as = crate::db::types::DbBool
|
||||
)]
|
||||
pub enabled: bool,
|
||||
pub version: i32,
|
||||
pub file_path: String,
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::tags, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct Tag {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
use diesel::ExpressionMethods;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow,
|
||||
)]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TemplateKind {
|
||||
Post,
|
||||
@@ -9,21 +13,85 @@ pub enum TemplateKind {
|
||||
Partial,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow,
|
||||
)]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum TemplateStatus {
|
||||
Draft,
|
||||
Published,
|
||||
}
|
||||
|
||||
impl TemplateKind {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Post => "post",
|
||||
Self::List => "list",
|
||||
Self::NotFound => "not_found",
|
||||
Self::Partial => "partial",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for TemplateKind {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"post" => Ok(Self::Post),
|
||||
"list" => Ok(Self::List),
|
||||
"not_found" | "notFound" | "not-found" => Ok(Self::NotFound),
|
||||
"partial" => Ok(Self::Partial),
|
||||
_ => Err(format!("invalid TemplateKind: {value}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TemplateStatus {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Draft => "draft",
|
||||
Self::Published => "published",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for TemplateStatus {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"draft" => Ok(Self::Draft),
|
||||
"published" => Ok(Self::Published),
|
||||
_ => Err(format!("invalid TemplateStatus: {value}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Liquid template. Matches the `templates` table.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
diesel::Queryable,
|
||||
diesel::Selectable,
|
||||
diesel::Insertable,
|
||||
diesel::AsChangeset,
|
||||
)]
|
||||
#[diesel(table_name = crate::db::schema::templates, check_for_backend(diesel::sqlite::Sqlite))]
|
||||
#[diesel(treat_none_as_default_value = false, treat_none_as_null = true)]
|
||||
pub struct Template {
|
||||
pub id: String,
|
||||
pub project_id: String,
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
pub kind: TemplateKind,
|
||||
#[diesel(
|
||||
deserialize_as = crate::db::types::DbBool,
|
||||
serialize_as = crate::db::types::DbBool
|
||||
)]
|
||||
pub enabled: bool,
|
||||
pub version: i32,
|
||||
pub file_path: String,
|
||||
|
||||
Reference in New Issue
Block a user