simple-web-app

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit aa0015725bc01def0528dd8babfb192da86cb52d
parent 60a5cecddce56036be2d0a950ae7ab819117a90c
Author: Silas Brack <silasbrack@gmail.com>
Date:   Wed, 22 Apr 2026 13:20:05 +0200

feat: generate Rust types from Trailbase schema

- Add scripts/generate-types.sh using quicktype
- Generated types in src/trailbase_types.rs
- Import generated types in trailbase.rs
- Add quicktype to dev shell

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Diffstat:
Mflake.nix | 1+
Aschemas/category.json | 15+++++++++++++++
Aschemas/news_item.json | 37+++++++++++++++++++++++++++++++++++++
Aschemas/news_item_category.json | 20++++++++++++++++++++
Ascripts/generate-types.sh | 41+++++++++++++++++++++++++++++++++++++++++
Msrc/main.rs | 1+
Msrc/trailbase.rs | 18+-----------------
Asrc/trailbase_types.rs | 29+++++++++++++++++++++++++++++
8 files changed, 145 insertions(+), 17 deletions(-)

diff --git a/flake.nix b/flake.nix @@ -165,6 +165,7 @@ cargo-watch cargo-edit rust-analyzer + quicktype # Backend (pkgs.callPackage ./trailbase.nix { }) diff --git a/schemas/category.json b/schemas/category.json @@ -0,0 +1,15 @@ +{ + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id" + ], + "title": "category", + "type": "object" +} diff --git a/schemas/news_item.json b/schemas/news_item.json @@ -0,0 +1,37 @@ +{ + "properties": { + "author": { + "type": "string" + }, + "created_by": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "language": { + "type": "string" + }, + "published": { + "type": "string" + }, + "text": { + "type": "string" + }, + "title": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "id", + "title", + "text", + "published", + "language" + ], + "title": "news_item", + "type": "object" +} diff --git a/schemas/news_item_category.json b/schemas/news_item_category.json @@ -0,0 +1,20 @@ +{ + "properties": { + "category_id": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "news_item_id": { + "type": "integer" + } + }, + "required": [ + "id", + "news_item_id", + "category_id" + ], + "title": "news_item_category", + "type": "object" +} diff --git a/scripts/generate-types.sh b/scripts/generate-types.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +SCHEMA_DIR="$PROJECT_DIR/schemas" +OUTPUT_FILE="$PROJECT_DIR/src/trailbase_types.rs" + +mkdir -p "$SCHEMA_DIR" + +echo "Exporting schemas from Trailbase..." + +# Export schemas for each table (filter out non-JSON lines) +tables=(news_item category news_item_category) +for table in "${tables[@]}"; do + trail schema "$table" --mode select 2>/dev/null | grep -v "^Rust\|^Run " > "$SCHEMA_DIR/${table}.json" + echo " - $table" +done + +echo "Generating Rust types with quicktype..." + +# Generate all types in one file using --src-lang schema +quicktype \ + --src-lang schema \ + --lang rust \ + --visibility public \ + --derive-debug \ + --density dense \ + --src "$SCHEMA_DIR/news_item.json" \ + --src "$SCHEMA_DIR/category.json" \ + --src "$SCHEMA_DIR/news_item_category.json" \ + --out "$OUTPUT_FILE" + +# Add Clone derive to all structs +sed -i 's/#\[derive(Debug, Serialize, Deserialize)\]/#[derive(Debug, Clone, Serialize, Deserialize)]/g' "$OUTPUT_FILE" + +# Remove the example comments and add our module doc +sed -i '1,/^use serde/{ /^use serde/!d }' "$OUTPUT_FILE" +sed -i '1i //! Auto-generated types from Trailbase schema.\n//! Run `./scripts/generate-types.sh` to regenerate.\n' "$OUTPUT_FILE" + +echo "Generated $OUTPUT_FILE" diff --git a/src/main.rs b/src/main.rs @@ -15,6 +15,7 @@ mod routes; mod state; mod templates; mod trailbase; +mod trailbase_types; use config::Config; use state::AppState; diff --git a/src/trailbase.rs b/src/trailbase.rs @@ -2,6 +2,7 @@ use reqwest::Client; use serde::{Deserialize, Serialize}; use crate::config::Config; +pub use crate::trailbase_types::{Category, NewsItem, NewsItemCategory}; #[derive(Clone)] pub struct TrailbaseClient { @@ -10,23 +11,6 @@ pub struct TrailbaseClient { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct NewsItem { - pub id: i64, - pub title: String, - pub text: String, - pub published: String, - pub url: Option<String>, - pub author: Option<String>, - pub language: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Category { - pub id: i64, - pub name: Option<String>, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] pub struct SearchResult { pub title: String, pub text: String, diff --git a/src/trailbase_types.rs b/src/trailbase_types.rs @@ -0,0 +1,29 @@ +//! Auto-generated types from Trailbase schema. +//! Run `./scripts/generate-types.sh` to regenerate. + +use serde::{Serialize, Deserialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NewsItem { + pub author: Option<String>, + pub created_by: Option<String>, + pub id: i64, + pub language: String, + pub published: String, + pub text: String, + pub title: String, + pub url: Option<String>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Category { + pub id: i64, + pub name: Option<String>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NewsItemCategory { + pub category_id: i64, + pub id: i64, + pub news_item_id: i64, +}