feat(http-recorder): prepare independent beta release

This commit is contained in:
Kit Langton 2026-06-22 18:12:14 -04:00
commit 81eea42e80
17 changed files with 485 additions and 85 deletions

View file

@ -15,4 +15,6 @@ export namespace HttpRecorder {
export type RequestMatcher = import("./types.js").RequestMatcher
/** The normalized HTTP request representation used for matching. */
export type RequestSnapshot = import("./types.js").RequestSnapshot
/** Recorder configuration for a provided Effect WebSocket service. */
export type SocketRecorderOptions = import("./types.js").SocketRecorderOptions
}

View file

@ -7,7 +7,7 @@ import { makeReplayState, resolveAutoMode } from "./recorder.js"
import { make, type Redactor } from "./redactor.js"
import { webSocketInteractions } from "./schema.js"
import type {
RecorderOptions,
SocketRecorderOptions,
WebSocketEvent,
WebSocketInteraction,
WebSocketRecorderOptions,
@ -302,10 +302,17 @@ const recordingLayer = (
* Wraps a provided `Socket.Socket` with cassette recording and replay.
*
* Supply the ordinary URL-bound Effect socket layer beneath this decorator.
* The cassette name identifies the connection; recorder configuration does not
* duplicate the transport URL.
* The cassette name identifies the connection during replay; recorder
* configuration does not duplicate or validate the transport URL.
*
* A recording is committed only after the socket run completes successfully.
* Replay releases server frames in order and waits at each recorded client
* frame until the application writes a matching frame.
*/
export const socket = (name: string, options: RecorderOptions = {}): Layer.Layer<Socket.Socket, never, Socket.Socket> =>
export const socket = (
name: string,
options: SocketRecorderOptions = {},
): Layer.Layer<Socket.Socket, never, Socket.Socket> =>
provideCassette(recordingLayer(name, { url: "" }, { ...options, compareClientMessagesAsJson: true }), options)
/** @internal */

View file

@ -85,6 +85,9 @@ export interface RecorderOptions {
readonly match?: RequestMatcher
}
/** Recorder configuration for a provided Effect WebSocket service. */
export type SocketRecorderOptions = Omit<RecorderOptions, "match">
/** @internal */
export interface WebSocketRequest {
/** WebSocket URL. */
@ -94,15 +97,7 @@ export interface WebSocketRequest {
}
/** @internal */
export interface WebSocketRecorderOptions {
/** Cassette directory. Defaults to `<cwd>/test/fixtures/recordings`. */
readonly directory?: string
/** Additional metadata stored in the cassette. */
readonly metadata?: CassetteMetadata
/** Additive handshake and text-frame redaction policy. */
readonly redact?: RedactOptions
export interface WebSocketRecorderOptions extends SocketRecorderOptions {
/** Compare text client frames as canonical JSON instead of exact strings. */
readonly compareClientMessagesAsJson?: boolean
/** WebSocket subprotocols used by `layerWebSocket`. */
readonly protocols?: string | Array<string>
}