3.4 KiB
protocol
(no submodules)
Purpose
Defines the Zod-validated wire format for log frames travelling from a
worker-isolated plugin to the main-process @suaveplan/logger. Frames
are a small discriminated union — log-batch, goodbye, and control
— so receivers branch on kind and reject malformed input cleanly via
Zod parsing rather than ad-hoc shape checks.
The protocol is bidirectional: workers send log-batch and goodbye
frames to the main, the main sends control frames (disable /
enable) back to the worker so it can stop emitting after the
main-side logger has been disposed (design doc §5.5 dispose-in-reverse).
Features
LOGGER_PROXY_PROTOCOL_VERSION—"1.0.0". Embedded in every frame via thevfield; servers reject on mismatch.LOG_LEVELS/LogLevel—trace | debug | info | warn | error | fatal. Wider thanLoggerLiketo allow forward-compatibility; the main-side server narrows down before dispatch.PluginTag/pluginTagSchema—{ name, version }attached to every batch.WireLogRecord/logRecordSchema— single record:level,msg,ts, optionalctxmap, optionaltrace(trace_id/span_id).LogBatchFrame/logBatchFrameSchema—{ kind: "log-batch", v, plugin, records: WireLogRecord[] }withmin(1)records.ControlFrame/controlFrameSchema—{ kind: "control", v, action: "disable" | "enable" }.parseLoggerProxyFrame(input)— validates and returns the discriminated union; throwsZodErroron malformed input.
Usage: Basic
import {
LOGGER_PROXY_PROTOCOL_VERSION,
parseLoggerProxyFrame,
} from "@suaveplan/api-logger-worker-proxy/protocol";
const frame = parseLoggerProxyFrame({
v: LOGGER_PROXY_PROTOCOL_VERSION,
kind: "log-batch",
plugin: { name: "demo", version: "0.1.0" },
records: [
{
level: "info",
msg: "hello",
ts: new Date().toISOString(),
ctx: { userId: 42 },
},
],
});
Usage: Advanced
Switch over kind with exhaustive narrowing:
import { parseLoggerProxyFrame } from "@suaveplan/api-logger-worker-proxy/protocol";
function handle(input: unknown): void {
const frame = parseLoggerProxyFrame(input);
switch (frame.kind) {
case "log-batch":
for (const r of frame.records) dispatch(r, frame.plugin);
break;
case "control":
applyControl(frame.action);
break;
case "goodbye":
shutdown(frame.reason);
break;
}
}
API Reference
LOG_LEVELS: readonly LogLevel[]— exported tuple for enumeration.logLevelSchema: ZodEnum<LogLevel>— re-use in downstream schemas.logRecordSchema,logBatchFrameSchema,controlFrameSchema,logGoodbyeFrameSchema,loggerProxyFrameSchema— Zod schemas.parseLoggerProxyFrame(input: unknown): LoggerProxyFrame— entry point for receivers. Throws on malformed input.
Implementation Notes
The schema accepts ctx as Record<string, unknown> to keep the
proxy transparent to the application. Main-side redaction normalises
sensitive fields before they reach the sink. ts is required so the
main-side stays a pure forwarder; the worker stamps wall-clock time at
record creation. Frames flow over MessagePort and survive
structured-clone — keeping records as plain data (no Date, no
classes) is intentional.