feat(api-client): add Yavsc.Api.Client with Blog + Circle + BlogAcl clients

Creates the high-level HTTP client library the PostIt UI will
consume to manage blog posts, circles, and per-post ACLs.

Clients in this commit:
- BlogApiClient (moved from PostIt/Services; same public surface,
  now depends on IYavscApiClient instead of the concrete class).
- CircleApiClient (new): GET/POST/PUT/DELETE /api/circle. Takes
  the blogs base URL explicitly in its constructor so it doesn't
  need to know about PostIt's Settings type.
- BlogAclApiClient (new): GET/POST/PUT/DELETE /api/blogacl.
  Same conventions as CircleApiClient.

DTOs (Yavsc.Api.Client.Dtos):
- CircleDto: id, name, ownerId, public. Stops short of the
  navigation properties on the server-side Circle (Owner,
  Members), which depend on ApplicationUser and other server
  types we don't want to drag into the client.
- CircleAuthorizationDto: circleId, blogPostId, comment. Same
  reason: the server entity has Target and Allowed navigation
  properties the client never needs.

The clients now require the caller to pass the blogs base URL
explicitly in the constructor (previously the BlogApiClient
sniffed it off YavscApiClient.Settings.BlogsApiUrl, but that
field is PostIt-specific). The one production call site
(App.axaml.cs) and four test call sites are updated to pass
the URL.

Build + 51/51 tests green. The IYavscApiClient abstraction was
landed in the previous commit so this one could be a pure
addition + relocation.
This commit is contained in:
Paul Schneider 2026-08-17 23:50:35 +01:00
commit f835ad42a1
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
11 changed files with 171 additions and 12 deletions

View file

@ -1,4 +1,5 @@
using Yavsc.Blogspot;
using Yavsc.Api.Client;
using PostIt.Services;
using PostIt.ViewModels;
@ -14,7 +15,7 @@ public class PostItViewModelTests
// default; tests construct one with a fake YavscApiClient that
// throws on any call (we never call the API in this test).
var fakeApi = new ThrowingYavscApiClient();
var blog = new BlogApiClient(fakeApi);
var blog = new BlogApiClient(fakeApi, "http://localhost/");
var viewModel = new MainPageViewModel(blog);
viewModel.Posts.Add(new BlogPost { Id = 1, Title = "First post", Article = "Hello world", AuthorId = "alice" });
@ -46,7 +47,7 @@ public class PostItViewModelTests
new() { Id = 2, Title = "World" }
};
var api = new StubYavscApiClient(expected);
var blog = new BlogApiClient(api);
var blog = new BlogApiClient(api, "http://localhost/");
var posts = await blog.GetPostsAsync();