import { EventEmitter } from "node:events"; import Display from "./display.js"; import { EventDefinition, RequestDefinition, EnumDefinition, InterfaceDefinition } from "./definitions.js"; interface AggregateResult { id: number; [e: string]: number | string | boolean | AggregateResult | number[] | string[] | AggregateResult[]; } export default class Wl_interface extends EventEmitter { protected readonly display: Display; /** Interface name */ readonly name: string; /** Interface version number */ readonly version: number; readonly id: number; readonly events: (EventDefinition | undefined)[]; readonly requests: (RequestDefinition | undefined)[]; readonly enums: Record; /** * Interface constructor. * It should normally not be called directly but rather through Display.createInterface(), itself called from Display.bind() or some interface request. * @internal */ constructor(d: Display, id: number, { name, version, requests, events, enums }: InterfaceDefinition); /** * Emits an error event on this interface if it has any error listeners. * Otherwise emit a (fatal) error on the client display interface. * Unless otherwise specified, all errors might be considered fatal. */ emitError(e: Error | any): boolean; /** * Parse an event's message before emitting it * @param evcode event index * @param b message body */ push(evcode: number, b: Buffer): boolean; /** * Get an operation's index (opcode) * using the request's name * Throws if an invalid name is provided */ opcode(rName: RequestDefinition["name"]): number; toString(): string; inspect(): string; /** * Low level catch-all method to aggregate all events * received by this interface over a period of time * into a single object. * * **Prefer `drain()` for most use cases** — it handles cleanup automatically. * * The returned function also implements `Disposable`, so automatic cleanup is * guaranteed with the `using` keyword: * ```javascript * using const end = itf.aggregate(); * await once(itf, "done"); * const infos = end(); * ``` * Without `using`, wrap in a try/finally or call `end()` unconditionally to avoid listener leaks. */ aggregate(): (() => AggregateResult) & Disposable; /** * Collects all events until `until` resolves, then returns the aggregated result. * Defaults to `display.sync()`. * * Prefer passing a **factory function** `() => once(itf, "event")` over a bare promise * so that the `until` listener is registered *after* aggregation begins (no race window): * ```javascript * const result = await itf.drain(() => once(itf, "done")); * ``` * Passing a bare promise also works when the promise is independent of this interface's events (eg: a timeout or a global interface event). */ drain(until?: (() => Promise) | Promise): Promise; } export {};