Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: d981de1229ef899957bbe968bc8dcda02a21f477
111 lines
3.7 KiB
TypeScript
111 lines
3.7 KiB
TypeScript
import type { JsonValue } from "@earendil-works/chord";
|
|
import Type, { type Static } from "typebox";
|
|
import { Check } from "typebox/value";
|
|
|
|
export const PROTOCOL_VERSION = 8 as const;
|
|
|
|
const IdSchema = Type.String({ minLength: 1 });
|
|
const OpaqueJsonValueSchema = Type.Unsafe<JsonValue>(Type.Unknown());
|
|
const StrictObject = <const T extends Parameters<typeof Type.Object>[0]>(properties: T) =>
|
|
Type.Object(properties, { additionalProperties: false });
|
|
|
|
const ServerIdSchema = Type.String({
|
|
pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
|
|
});
|
|
export type ServerId = Static<typeof ServerIdSchema>;
|
|
|
|
export function isServerId(value: unknown): value is ServerId {
|
|
return Check(ServerIdSchema, value);
|
|
}
|
|
|
|
const ProtocolErrorSchema = StrictObject({
|
|
code: IdSchema,
|
|
message: Type.String(),
|
|
});
|
|
export type ProtocolErrorCode = string;
|
|
export type ProtocolError = Static<typeof ProtocolErrorSchema>;
|
|
|
|
/** Must be the first frame sent by a client. */
|
|
const ClientHelloSchema = StrictObject({
|
|
type: Type.Literal("hello"),
|
|
version: Type.Integer({ minimum: 0 }),
|
|
});
|
|
export type ClientHello = Static<typeof ClientHelloSchema>;
|
|
|
|
/** A server-wide call, fenced to one logical server. */
|
|
const ServerTargetSchema = StrictObject({
|
|
serverId: ServerIdSchema,
|
|
});
|
|
/** A session call, fenced to one logical server, durable session, and live attachment. */
|
|
const SessionTargetSchema = StrictObject({
|
|
serverId: ServerIdSchema,
|
|
sessionId: IdSchema,
|
|
attachmentId: IdSchema,
|
|
});
|
|
export type SessionTarget = Static<typeof SessionTargetSchema>;
|
|
const RpcTargetSchema = Type.Union([ServerTargetSchema, SessionTargetSchema]);
|
|
export type RpcTarget = Static<typeof RpcTargetSchema>;
|
|
|
|
const RequestEnvelopeSchema = StrictObject({
|
|
type: Type.Literal("request"),
|
|
id: IdSchema,
|
|
target: RpcTargetSchema,
|
|
call: OpaqueJsonValueSchema,
|
|
});
|
|
const CancelEnvelopeSchema = StrictObject({
|
|
type: Type.Literal("cancel"),
|
|
id: IdSchema,
|
|
target: RpcTargetSchema,
|
|
});
|
|
export type RequestEnvelope = Static<typeof RequestEnvelopeSchema>;
|
|
export type CancelEnvelope = Static<typeof CancelEnvelopeSchema>;
|
|
export const ClientMessageSchema = Type.Union([ClientHelloSchema, RequestEnvelopeSchema, CancelEnvelopeSchema]);
|
|
export type ClientMessage = Static<typeof ClientMessageSchema>;
|
|
|
|
const ServerHelloSchema = StrictObject({
|
|
type: Type.Literal("hello"),
|
|
version: Type.Literal(PROTOCOL_VERSION),
|
|
serverId: ServerIdSchema,
|
|
});
|
|
const ServerHelloErrorSchema = StrictObject({
|
|
type: Type.Literal("hello_error"),
|
|
error: ProtocolErrorSchema,
|
|
});
|
|
const ResponseEnvelopeSchema = Type.Union([
|
|
StrictObject({
|
|
type: Type.Literal("response"),
|
|
id: IdSchema,
|
|
ok: Type.Literal(true),
|
|
result: Type.Optional(OpaqueJsonValueSchema),
|
|
}),
|
|
StrictObject({
|
|
type: Type.Literal("response"),
|
|
id: IdSchema,
|
|
ok: Type.Literal(false),
|
|
error: ProtocolErrorSchema,
|
|
}),
|
|
]);
|
|
const ServiceEventEnvelopeSchema = StrictObject({
|
|
type: Type.Literal("service_update"),
|
|
subscriptionId: IdSchema,
|
|
update: OpaqueJsonValueSchema,
|
|
});
|
|
/** Out-of-band update to this presentation's selected Session route. */
|
|
const AttachmentEnvelopeSchema = StrictObject({
|
|
type: Type.Literal("attachment"),
|
|
attachment: Type.Union([SessionTargetSchema, Type.Null()]),
|
|
});
|
|
export const ServerMessageSchema = Type.Union([
|
|
ServerHelloSchema,
|
|
ServerHelloErrorSchema,
|
|
ResponseEnvelopeSchema,
|
|
ServiceEventEnvelopeSchema,
|
|
AttachmentEnvelopeSchema,
|
|
]);
|
|
export type ServerHello = Static<typeof ServerHelloSchema>;
|
|
export type ServerHelloError = Static<typeof ServerHelloErrorSchema>;
|
|
export type ResponseEnvelope = Static<typeof ResponseEnvelopeSchema>;
|
|
export type ServiceEventEnvelope = Static<typeof ServiceEventEnvelopeSchema>;
|
|
export type AttachmentEnvelope = Static<typeof AttachmentEnvelopeSchema>;
|
|
export type ServerMessage = Static<typeof ServerMessageSchema>;
|