chore: add full posts to api response cfb68a80
Steve Simkins · 2026-04-30 18:43 3 file(s) · +25 −11
apps/posts/src/db.rs +5 −4
214 214
    Ok(posts)
215 215
}
216 216
217 -
pub fn get_published_posts(db: &Db) -> Result<Vec<Post>, DbError> {
217 +
pub fn get_published_posts(db: &Db, limit: Option<i64>) -> Result<Vec<Post>, DbError> {
218 218
    let conn = db.lock().map_err(|_| DbError::LockPoisoned)?;
219 +
    let limit_value = limit.unwrap_or(-1);
219 220
    let mut stmt = conn.prepare(
220 -
        &format!("SELECT {} FROM posts WHERE status = 'published' ORDER BY published_date DESC, id DESC", POST_COLS),
221 +
        &format!("SELECT {} FROM posts WHERE status = 'published' ORDER BY published_date DESC, id DESC LIMIT ?1", POST_COLS),
221 222
    )?;
222 223
    let posts = stmt
223 -
        .query_map([], from_row)?
224 +
        .query_map(params![limit_value], from_row)?
224 225
        .collect::<Result<Vec<_>, _>>()?;
225 226
    Ok(posts)
226 227
}
550 551
        input.published_date = Some("2024-01-01");
551 552
        create_post(&db, &input).unwrap();
552 553
553 -
        let published = get_published_posts(&db).unwrap();
554 +
        let published = get_published_posts(&db, None).unwrap();
554 555
        assert_eq!(published.len(), 1);
555 556
        assert_eq!(published[0].title, "Published");
556 557
    }
apps/posts/src/server/handlers/api.rs +17 −4
1 1
use axum::{
2 2
    Json,
3 -
    extract::{Path, State},
3 +
    extract::{Path, Query, State},
4 4
    http::StatusCode,
5 5
    response::{IntoResponse, Response},
6 6
};
7 -
use serde::Serialize;
7 +
use serde::{Deserialize, Serialize};
8 8
use serde_json::json;
9 9
use std::sync::Arc;
10 +
11 +
const DEFAULT_LIST_LIMIT: i64 = 30;
12 +
13 +
#[derive(Deserialize)]
14 +
pub struct ListPostsQuery {
15 +
    limit: Option<i64>,
16 +
}
10 17
11 18
use super::super::*;
12 19
use crate::db;
22 29
    canonical_url: Option<String>,
23 30
    lang: String,
24 31
    tags: Option<String>,
32 +
    content: String,
25 33
    created_at: String,
26 34
    updated_at: String,
27 35
}
60 68
            canonical_url: p.canonical_url,
61 69
            lang: p.lang,
62 70
            tags: p.tags,
71 +
            content: p.content,
63 72
            created_at: p.created_at,
64 73
            updated_at: p.updated_at,
65 74
        }
86 95
    }
87 96
}
88 97
89 -
pub async fn list_posts(State(state): State<Arc<AppState>>) -> Response {
90 -
    match db::get_published_posts(&state.db) {
98 +
pub async fn list_posts(
99 +
    State(state): State<Arc<AppState>>,
100 +
    Query(params): Query<ListPostsQuery>,
101 +
) -> Response {
102 +
    let limit = params.limit.unwrap_or(DEFAULT_LIST_LIMIT).max(0);
103 +
    match db::get_published_posts(&state.db, Some(limit)) {
91 104
        Ok(posts) => {
92 105
            let posts = posts.into_iter().map(ApiPostSummary::from).collect();
93 106
            Json(ApiPostsList { posts }).into_response()
apps/posts/src/server/handlers/public.rs +3 −3
29 29
    let blog_description = get_setting_or_default(&state.db, "blog_description");
30 30
    let intro_content = get_setting_or_default(&state.db, "intro_content");
31 31
32 -
    match db::get_published_posts(&state.db) {
32 +
    match db::get_published_posts(&state.db, None) {
33 33
        Ok(posts) => {
34 34
            let mut intro_html = render_markdown(&intro_content);
35 35
122 122
pub async fn public_posts_list(State(state): State<Arc<AppState>>) -> Response {
123 123
    let ctx = SiteContext::from_state(&state);
124 124
125 -
    match db::get_published_posts(&state.db) {
125 +
    match db::get_published_posts(&state.db, None) {
126 126
        Ok(posts) => WebTemplate(PostsListTemplate {
127 127
            blog_title: ctx.blog_title,
128 128
            nav_links: ctx.nav_links,
204 204
    let blog_description = get_setting_or_default(&state.db, "blog_description");
205 205
    let site_url = &state.site_url;
206 206
207 -
    let posts = match db::get_published_posts(&state.db) {
207 +
    let posts = match db::get_published_posts(&state.db, None) {
208 208
        Ok(posts) => posts,
209 209
        Err(e) => {
210 210
            tracing::error!("Failed to get posts for RSS: {}", e);