3.6 KiB
NullSpritePlaybackAdapter
(no submodules)
Purpose
NullSpritePlaybackAdapter is the recording adapter that conforms to the SpritePlaybackAdapter contract without producing any audio. It is the fixture every test in this package uses, and it is exported so downstream engine adapters can use it as the contract-conformance baseline before plugging in real audio output.
Every method on the adapter appends a typed entry to a public read-only calls array. Every play returns a SpritePlayHandle whose stop, setVolume, and isPlaying invocations are also recorded. The timestamps come from an injectable Clock, so tests using FakeClock (or any deterministic clock) produce identical traces on every run.
Features
- Implements the full
SpritePlaybackAdapterinterface:init,play,dispose. - Records every method call with
{ kind, at, payload }whereatis the clock reading andpayloadcarries the relevant arguments. - Records every handle lifecycle event (
stopwithfadeOutMs,setVolumewith value). - Honours
AbortSignal: throws anabortederror when invoked with an already-aborted signal. - Pure — no platform globals, no side effects beyond the in-memory
callsarray.
Usage: Basic Example
import { NullSpritePlaybackAdapter, createSpritePlayer } from "@suaveplan/audio-sprite-player";
const adapter = new NullSpritePlaybackAdapter();
const player = createSpritePlayer({ adapter });
await player.load(sprite);
await player.play("hit");
console.log(adapter.calls.map((c) => c.kind));
// → ["init", "play"]
Usage: Advanced Example
import {
createNullSpritePlaybackAdapter,
createSpritePlayer,
} from "@suaveplan/audio-sprite-player";
import { FakeClock } from "@suaveplan/testing";
const fakeClock = new FakeClock({ startTime: 1_000_000 });
const adapter = createNullSpritePlaybackAdapter({
clock: () => fakeClock.now(),
});
const player = createSpritePlayer({
adapter,
clock: () => fakeClock.now(),
idGenerator: (() => {
let i = 0;
return () => `id-${++i}`;
})(),
});
await player.load(sprite);
await player.play("hit");
fakeClock.advance(100);
await player.play("hit");
const playRecords = adapter.calls.filter((c) => c.kind === "play");
console.log(playRecords.length); // 2
API Reference
new NullSpritePlaybackAdapter(options?)
options.clock?: Clock — defaults to () => Date.now().
calls: ReadonlyArray<NullCall>
Append-only log. NullCall is { kind: "init" | "play" | "dispose" | "stop" | "setVolume"; at: number; payload?: unknown }.
init(sprite, signal?)
Records { kind: "init" }. Throws if signal.aborted.
play(entry, opts, signal?)
Records { kind: "play", payload: { entryName, id, opts } }. Returns a handle. Throws if signal.aborted.
dispose()
Records { kind: "dispose" }.
createNullSpritePlaybackAdapter(options?)
Functional alias for new NullSpritePlaybackAdapter(options).
Implementation Notes
- The adapter is exported from the package root and from the
./adapter/null/nullsubpath so consumers can import it without pulling the rest of the surface. - It is a valid implementation of
SpritePlaybackAdapterfrom the type level, so theadapter contract compiles from type-only importssmoke test innull.test.tsconfirms a downstream engine could ship an adapter using nothing butimport typefrom this package. - The handle returned by
playcarries the sameidrecorded in theplaycall's payload, so consumers can correlate handle lifecycle calls back to their originatingplaydeterministically.