using System.Net.Http.Json;
using System.Text.Json;
using Elternbeirat.Contracts;
namespace Elternbeirat.PocketBase;
///
/// Reads published content from a PocketBase instance over its REST API.
///
///
///
/// There is one method per collection (pages, posts, events, faqs). Each returns
/// only records with public = true and leaves filtering and sorting to
/// PocketBase via query parameters.
///
///
/// Responses are deserialized with the web defaults. Date conversion from UTC
/// to Berlin wall-clock time is declared on the contracts themselves via
/// [JsonConverter] (e.g. , ),
/// so no serializer options are configured here.
///
///
/// Register the class as a typed client via AddHttpClient, with
/// set to the PocketBase base URL.
///
///
///
/// The HTTP client; its must point to PocketBase.
///
public sealed class PocketBaseClient(HttpClient http)
{
///
/// Gets all public pages, ordered by .
///
///
/// A token to cancel the request.
///
///
/// The public pages, or an empty list if there are none.
///
///
/// PocketBase could not be reached or returned a non-success status code.
///
///
/// The response could not be deserialized.
///
///
/// was canceled or the request timed out.
///
public Task> GetPagesAsync(CancellationToken ct = default)
=> GetRecordsAsync("pages", "order", ct);
///
/// Gets all public posts, ordered by , newest first.
///
///
///
/// The public posts, or an empty list if there are none.
///
///
public Task> GetPostsAsync(CancellationToken ct = default)
=> GetRecordsAsync("posts", "-date", ct);
///
/// Gets all public events, ordered by , earliest first.
///
///
///
/// The public events, or an empty list if there are none.
///
///
public Task> GetEventsAsync(CancellationToken ct = default)
=> GetRecordsAsync("events", "start", ct);
///
/// Gets all public FAQ entries, ordered by .
///
///
///
/// The public FAQ entries, or an empty list if there are none.
///
///
public Task> GetFaqsAsync(CancellationToken ct = default)
=> GetRecordsAsync("faqs", "topic", ct);
///
/// Gets all public records of a collection in a single request.
///
///
/// The record type to deserialize into.
///
///
/// The PocketBase collection name, e.g. "posts".
///
///
/// The PocketBase sort expression; a leading - sorts descending.
///
///
/// A token to cancel the request.
///
///
/// The public records, or an empty list if there are none.
///
private async Task> GetRecordsAsync(
string collection,
string sort,
CancellationToken ct)
{
// filter=public=true keeps drafts out; perPage is large enough to fetch
// every record in a single page given the small content volume.
var url = $"/api/collections/{collection}/records"
+ $"?perPage=500&filter={Uri.EscapeDataString("public=true")}"
+ $"&sort={Uri.EscapeDataString(sort)}";
var result = await http.GetFromJsonAsync>(url, ct);
return result?.Items ?? [];
}
}