60 lines
2.5 KiB
C#
60 lines
2.5 KiB
C#
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using Elternbeirat.Contracts;
|
|
|
|
namespace Elternbeirat.PocketBase;
|
|
|
|
/// <summary>
|
|
/// Reads published content from a PocketBase instance over its REST API.
|
|
/// <para>
|
|
/// One method per collection (pages, posts, events, faqs). Each returns only
|
|
/// records with <c>public = true</c> and lets PocketBase do the filtering and
|
|
/// sorting via query parameters. The <see cref="HttpClient"/> is expected to have
|
|
/// its <see cref="HttpClient.BaseAddress"/> set to the PocketBase base URL, so it
|
|
/// is registered as a typed client via <c>AddHttpClient</c>.
|
|
/// </para>
|
|
/// </summary>
|
|
public sealed class PocketBaseClient(HttpClient http)
|
|
{
|
|
private static readonly JsonSerializerOptions JsonOptions = CreateJsonOptions();
|
|
|
|
private static JsonSerializerOptions CreateJsonOptions()
|
|
{
|
|
var options = new JsonSerializerOptions
|
|
{
|
|
PropertyNameCaseInsensitive = true,
|
|
};
|
|
options.Converters.Add(new LocalDateTimeConverter());
|
|
options.Converters.Add(new NullableLocalDateTimeConverter());
|
|
return options;
|
|
}
|
|
|
|
/// <summary>Gets all public pages, ordered for navigation.</summary>
|
|
public Task<IReadOnlyList<Page>> GetPagesAsync(CancellationToken ct = default)
|
|
=> GetRecordsAsync<Page>("pages", "order", ct);
|
|
|
|
/// <summary>Gets all public posts, newest first.</summary>
|
|
public Task<IReadOnlyList<Post>> GetPostsAsync(CancellationToken ct = default)
|
|
=> GetRecordsAsync<Post>("posts", "-date", ct);
|
|
|
|
/// <summary>Gets all public events, earliest start first.</summary>
|
|
public Task<IReadOnlyList<Event>> GetEventsAsync(CancellationToken ct = default)
|
|
=> GetRecordsAsync<Event>("events", "start", ct);
|
|
|
|
/// <summary>Gets all public FAQ entries.</summary>
|
|
public Task<IReadOnlyList<Faq>> GetFaqsAsync(CancellationToken ct = default)
|
|
=> GetRecordsAsync<Faq>("faqs", "topic", ct);
|
|
|
|
private async Task<IReadOnlyList<T>> GetRecordsAsync<T>(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<RecordList<T>>(url, JsonOptions, ct);
|
|
return result?.Items ?? [];
|
|
}
|
|
}
|