using System.Text.Json;
using System.Text.Json.Serialization;
namespace NucleicBroker;
///
/// NDJSON JSON-RPC 2.0 plumbing (docs/WINDOWS_PORT.md ยง3.3): one JSON object per line,
/// requests flow hostd โ broker only, notifications broker โ hostd only. Binary payloads
/// ride base64 in `b64` fields.
///
public static class Rpc
{
public static readonly JsonSerializerOptions Json = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
};
/// A JSON `null`, used as the response id for unidentifiable requests โ the
/// spec requires `"id": null` to be PRESENT, which the ignore-null policy would drop if
/// we passed a bare null.
private static readonly JsonElement NullId = JsonDocument.Parse("null").RootElement;
// JSON-RPC 2.0 error codes (+ -32000 for structured facade errors, kind in data).
public const int ParseError = -32700;
public const int InvalidRequest = -32600;
public const int MethodNotFound = -32601;
public const int InvalidParams = -32602;
public const int InternalError = -32603;
public const int FacadeError = -32000;
public static string Response(JsonElement id, object result) =>
JsonSerializer.Serialize(new { jsonrpc = "2.0", id, result }, Json);
public static string Error(JsonElement? id, int code, string message, object? data = null) =>
JsonSerializer.Serialize(
new { jsonrpc = "2.0", id = id ?? NullId, error = new { code, message, data } },
Json);
public static string Notification(string method, object @params) =>
JsonSerializer.Serialize(new { jsonrpc = "2.0", method, @params }, Json);
/// Deserialize a request's params object; throws JsonException on a missing or
/// mismatched shape (the dispatcher maps that to InvalidParams). Positional records bind
/// through their constructor, case-insensitively.
public static T Params(JsonElement? @params)
{
if (@params is not { ValueKind: JsonValueKind.Object } p)
throw new JsonException("missing params object");
return JsonSerializer.Deserialize(p.GetRawText(), Json)
?? throw new JsonException("params decoded to null");
}
}