refactor: consolidate serde rename attributes using rename_all = camelCase

This commit is contained in:
2026-01-14 10:38:27 -06:00
parent 4299f65665
commit 72f1129555
7 changed files with 30 additions and 71 deletions
+4 -34
View File
@@ -1,42 +1,12 @@
use serde::{Deserialize, Serialize}; use serde::Deserialize;
use uuid::Uuid; use uuid::Uuid;
use crate::cli::client::{ApiClient, ApiError, check_response}; use crate::cli::client::{ApiClient, ApiError, check_response};
use crate::cli::output; use crate::cli::output;
use crate::cli::{ProjectsCommand, TagOp, parse_create_tags, parse_update_tags}; use crate::cli::{ProjectsCommand, TagOp, parse_create_tags, parse_update_tags};
use crate::db::{ApiAdminProject, ApiTag, ProjectStatus}; use crate::db::{
ApiAdminProject, ApiTag, CreateProjectRequest, ProjectStatus, UpdateProjectRequest,
/// Request to create a project };
#[derive(Serialize)]
struct CreateProjectRequest {
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
slug: Option<String>,
short_description: String,
description: String,
status: ProjectStatus,
#[serde(skip_serializing_if = "Option::is_none")]
github_repo: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
demo_url: Option<String>,
tag_ids: Vec<String>,
}
/// Request to update a project
#[derive(Serialize)]
struct UpdateProjectRequest {
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
slug: Option<String>,
short_description: String,
description: String,
status: ProjectStatus,
#[serde(skip_serializing_if = "Option::is_none")]
github_repo: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
demo_url: Option<String>,
tag_ids: Vec<String>,
}
/// Run a projects subcommand /// Run a projects subcommand
pub async fn run( pub async fn run(
+9 -18
View File
@@ -34,29 +34,28 @@ pub struct ApiProjectLink {
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiProject { pub struct ApiProject {
pub id: String, pub id: String,
pub slug: String, pub slug: String,
pub name: String, pub name: String,
#[serde(rename = "shortDescription")]
pub short_description: String, pub short_description: String,
pub links: Vec<ApiProjectLink>, pub links: Vec<ApiProjectLink>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiAdminProject { pub struct ApiAdminProject {
#[serde(flatten)] #[serde(flatten)]
pub project: ApiProject, pub project: ApiProject,
pub tags: Vec<ApiTag>, pub tags: Vec<ApiTag>,
pub status: String, pub status: String,
pub description: String, pub description: String,
#[serde(rename = "githubRepo", skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub github_repo: Option<String>, pub github_repo: Option<String>,
#[serde(rename = "demoUrl", skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub demo_url: Option<String>, pub demo_url: Option<String>,
#[serde(rename = "createdAt")]
pub created_at: String, // ISO 8601 pub created_at: String, // ISO 8601
#[serde(rename = "lastActivity")]
pub last_activity: String, // ISO 8601 pub last_activity: String, // ISO 8601
} }
@@ -110,46 +109,38 @@ impl DbProject {
// Request types for CRUD operations // Request types for CRUD operations
#[derive(Debug, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateProjectRequest { pub struct CreateProjectRequest {
pub name: String, pub name: String,
pub slug: Option<String>, pub slug: Option<String>,
#[serde(rename = "shortDescription")]
pub short_description: String, pub short_description: String,
pub description: String, pub description: String,
pub status: ProjectStatus, pub status: ProjectStatus,
#[serde(rename = "githubRepo")]
pub github_repo: Option<String>, pub github_repo: Option<String>,
#[serde(rename = "demoUrl")]
pub demo_url: Option<String>, pub demo_url: Option<String>,
#[serde(rename = "tagIds")]
pub tag_ids: Vec<String>, // UUID strings pub tag_ids: Vec<String>, // UUID strings
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateProjectRequest { pub struct UpdateProjectRequest {
pub name: String, pub name: String,
pub slug: Option<String>, pub slug: Option<String>,
#[serde(rename = "shortDescription")]
pub short_description: String, pub short_description: String,
pub description: String, pub description: String,
pub status: ProjectStatus, pub status: ProjectStatus,
#[serde(rename = "githubRepo")]
pub github_repo: Option<String>, pub github_repo: Option<String>,
#[serde(rename = "demoUrl")]
pub demo_url: Option<String>, pub demo_url: Option<String>,
#[serde(rename = "tagIds")]
pub tag_ids: Vec<String>, // UUID strings pub tag_ids: Vec<String>, // UUID strings
} }
// Admin stats response // Admin stats response
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AdminStats { pub struct AdminStats {
#[serde(rename = "totalProjects")]
pub total_projects: i32, pub total_projects: i32,
#[serde(rename = "projectsByStatus")]
pub projects_by_status: serde_json::Value, pub projects_by_status: serde_json::Value,
#[serde(rename = "totalTags")]
pub total_tags: i32, pub total_tags: i32,
} }
+6 -8
View File
@@ -31,16 +31,16 @@ pub struct DbSocialLink {
// API response types // API response types
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiSiteIdentity { pub struct ApiSiteIdentity {
#[serde(rename = "displayName")]
pub display_name: String, pub display_name: String,
pub occupation: String, pub occupation: String,
pub bio: String, pub bio: String,
#[serde(rename = "siteTitle")]
pub site_title: String, pub site_title: String,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiSocialLink { pub struct ApiSocialLink {
pub id: String, pub id: String,
pub platform: String, pub platform: String,
@@ -48,29 +48,28 @@ pub struct ApiSocialLink {
pub value: String, pub value: String,
pub icon: String, pub icon: String,
pub visible: bool, pub visible: bool,
#[serde(rename = "displayOrder")]
pub display_order: i32, pub display_order: i32,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiSiteSettings { pub struct ApiSiteSettings {
pub identity: ApiSiteIdentity, pub identity: ApiSiteIdentity,
#[serde(rename = "socialLinks")]
pub social_links: Vec<ApiSocialLink>, pub social_links: Vec<ApiSocialLink>,
} }
// Request types for updates // Request types for updates
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateSiteIdentityRequest { pub struct UpdateSiteIdentityRequest {
#[serde(rename = "displayName")]
pub display_name: String, pub display_name: String,
pub occupation: String, pub occupation: String,
pub bio: String, pub bio: String,
#[serde(rename = "siteTitle")]
pub site_title: String, pub site_title: String,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateSocialLinkRequest { pub struct UpdateSocialLinkRequest {
pub id: String, pub id: String,
pub platform: String, pub platform: String,
@@ -78,14 +77,13 @@ pub struct UpdateSocialLinkRequest {
pub value: String, pub value: String,
pub icon: String, pub icon: String,
pub visible: bool, pub visible: bool,
#[serde(rename = "displayOrder")]
pub display_order: i32, pub display_order: i32,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateSiteSettingsRequest { pub struct UpdateSiteSettingsRequest {
pub identity: UpdateSiteIdentityRequest, pub identity: UpdateSiteIdentityRequest,
#[serde(rename = "socialLinks")]
pub social_links: Vec<UpdateSocialLinkRequest>, pub social_links: Vec<UpdateSocialLinkRequest>,
} }
+3
View File
@@ -31,6 +31,7 @@ pub struct DbTagCooccurrence {
// API response types // API response types
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiTag { pub struct ApiTag {
pub id: String, pub id: String,
pub slug: String, pub slug: String,
@@ -42,6 +43,7 @@ pub struct ApiTag {
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiTagWithCount { pub struct ApiTagWithCount {
#[serde(flatten)] #[serde(flatten)]
pub tag: ApiTag, pub tag: ApiTag,
@@ -49,6 +51,7 @@ pub struct ApiTagWithCount {
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiRelatedTag { pub struct ApiRelatedTag {
#[serde(flatten)] #[serde(flatten)]
pub tag: ApiTag, pub tag: ApiTag,
+3
View File
@@ -4,18 +4,21 @@ use std::sync::Arc;
use crate::{auth, state::AppState}; use crate::{auth, state::AppState};
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LoginRequest { pub struct LoginRequest {
pub username: String, pub username: String,
pub password: String, pub password: String,
} }
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LoginResponse { pub struct LoginResponse {
pub success: bool, pub success: bool,
pub username: String, pub username: String,
} }
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SessionResponse { pub struct SessionResponse {
pub authenticated: bool, pub authenticated: bool,
pub username: String, pub username: String,
+3
View File
@@ -16,6 +16,7 @@ pub use tags::*;
// Request/Response types used by handlers // Request/Response types used by handlers
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateTagRequest { pub struct CreateTagRequest {
pub name: String, pub name: String,
pub slug: Option<String>, pub slug: Option<String>,
@@ -24,6 +25,7 @@ pub struct CreateTagRequest {
} }
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateTagRequest { pub struct UpdateTagRequest {
pub name: String, pub name: String,
pub slug: Option<String>, pub slug: Option<String>,
@@ -32,6 +34,7 @@ pub struct UpdateTagRequest {
} }
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AddProjectTagRequest { pub struct AddProjectTagRequest {
pub tag_id: String, pub tag_id: String,
} }
+1 -10
View File
@@ -80,16 +80,7 @@ export async function deleteAdminProject(id: string): Promise<AdminProject> {
// Admin Tags API // Admin Tags API
export async function getAdminTags(): Promise<AdminTagWithCount[]> { export async function getAdminTags(): Promise<AdminTagWithCount[]> {
const tags = return clientApiFetch<AdminTagWithCount[]>("/api/tags");
await clientApiFetch<Array<AdminTag & { project_count: number }>>(
"/api/tags",
);
// Transform snake_case to camelCase
return tags.map((item) => ({
...item,
projectCount: item.project_count,
}));
} }
export async function createAdminTag(data: CreateTagData): Promise<AdminTag> { export async function createAdminTag(data: CreateTagData): Promise<AdminTag> {