PrivaPub's own types are read through the shared ClientModels context, and a type without generated metadata no longer falls back to reflection silently: it fails at once in development and on the pasture, and is reported on the console elsewhere. Startup outside production checks that every PrivaPub and Mastodon type the client knows has its metadata. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4YtEJrgxG12Pc39Fai8Bd
This commit is contained in:
1 parent
3bc511421e
commit
dca046e27d
6 files changed
+70
-105
No files matched your search
@@ -259,7 +259,8 @@ Never redeclare the base's members in a component.
|
||||
- The route picks the credentials: `clientapi/` sends the root's JWT, `api/` the current persona's Mastodon token
|
||||
(exchanged when missing, exchanged once more and retried when PrivaPub refuses it), `oauth/` nothing.
|
||||
- It also picks the JSON: `SUtility.MastodonSerializer` (snake_case, `MastodonJsonContext`) for `api/` and `oauth/`,
|
||||
`SUtility.DefaultSerializer` (camelCase, enums by name like PrivaPub, `ClientJsonContext`) for `clientapi/`. A payload
|
||||
`SUtility.DefaultSerializer` (camelCase, enums by name like PrivaPub, `ClientJsonContext` then
|
||||
`ClientModelsJsonContext`) for `clientapi/`. A payload
|
||||
can be an object (JSON), name/value pairs (a form) or a `Func<HttpContent>` (multipart), built once per attempt.
|
||||
- Auth levels: `Get` / `Post` / `Put` / `Patch` / `Delete` need credentials and end the session when PrivaPub refuses
|
||||
them; `GetAnon` adds them when there are some; `*TotallyAnon` send none (the login and the password recovery must
|
||||
@@ -954,14 +955,23 @@ and `ToCssNumber` for values written into a style. Date formats come from `SUtil
|
||||
`dateTimeFormatExt`. Relative times and sizes come from `GetPassedTime` / `GetFileSize`
|
||||
(`Extensions/GenericExtensions.cs`). No inline format strings for display.
|
||||
|
||||
**JSON.** Register every `/clientapi` or localStorage type in `ClientJsonContext.cs` (camelCase: `theme.js` reads
|
||||
`pageSettings` straight from localStorage), every Mastodon API type in `MastodonJsonContext.cs` (snake_case).
|
||||
**JSON (HR0306).** Every type that crosses HTTP or is stored has source-generated metadata:
|
||||
- `PrivaPub.ClientModels` types are registered in that project's `ClientModelsJsonContext`, shared with PrivaPub;
|
||||
- the client's own `/clientapi` and localStorage types in `ClientJsonContext.cs` (camelCase: `theme.js` reads
|
||||
`pageSettings` straight from localStorage);
|
||||
- every Mastodon API type in `MastodonJsonContext.cs` (snake_case).
|
||||
|
||||
There is no silent reflection fallback. The last resolver in each chain, `Helpers/UnregisteredJson`, throws for an
|
||||
unregistered type in Development and the pasture, and elsewhere writes it to the console once and serializes it anyway.
|
||||
At startup outside Production, `UnregisteredJson.Check` fails when a class in `PrivaPub.ClientModels` or
|
||||
`Models/Mastodon/` has no metadata.
|
||||
|
||||
**Wiring a feature to PrivaPub:**
|
||||
1. For `/clientapi`, add the request/response DTOs to `PrivaPub.ClientModels` in the SocialPub repo: `View*` for
|
||||
responses, `*Request` for requests, `*Form` for forms with validation. Lists `= []`, no string defaults. For the
|
||||
Mastodon API, add the shape to `Models/Mastodon/`.
|
||||
2. Register them in `ClientJsonContext` or `MastodonJsonContext`, and the route in `Models/APIs.cs`.
|
||||
2. Register them in `ClientModelsJsonContext` (SocialPub), `ClientJsonContext` or `MastodonJsonContext`, `List<T>` too
|
||||
when a list is read, and the route in `Models/APIs.cs`.
|
||||
3. Add a client service method that calls `IHttpService` against the server's route, following the patterns above.
|
||||
4. Wire the page with early returns, toasts and/or an `ErrorViewer`.
|
||||
|
||||
|
||||
Reference in new issue
Block a user