realtime-voice-agents 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/assets/elevator-jazz.ulaw +1 -0
- package/assets/keyboard-typing.ulaw +1 -0
- package/assets/lofi.ulaw +1 -0
- package/assets/ringing.ulaw +1 -0
- package/assets/thinking-hum.ulaw +1 -0
- package/dist/BackgroundAudioPlayer-iMcivjis.mjs +282 -0
- package/dist/BackgroundAudioPlayer-jfRULWKC.cjs +313 -0
- package/dist/BaseRealtimeProvider-BQigr5mB.mjs +62 -0
- package/dist/BaseRealtimeProvider-BehPNT1r.d.cts +239 -0
- package/dist/BaseRealtimeProvider-ClP8Wx1X.d.mts +239 -0
- package/dist/BaseRealtimeProvider-DI4pKtOb.cjs +91 -0
- package/dist/GeminiLiveProvider-DvkTgzjG.d.cts +101 -0
- package/dist/GeminiLiveProvider-x2nyx5aO.d.mts +101 -0
- package/dist/InMemorySessionStore-B0_i-DOU.cjs +34 -0
- package/dist/InMemorySessionStore-B5_rq61L.d.cts +83 -0
- package/dist/InMemorySessionStore-B5_rq61L.d.mts +83 -0
- package/dist/InMemorySessionStore-DYParOJO.mjs +29 -0
- package/dist/OpenAICompatibleProvider-Bdtl-UXH.mjs +402 -0
- package/dist/OpenAICompatibleProvider-NS4cKVQj.cjs +409 -0
- package/dist/audio.cjs +21 -0
- package/dist/audio.d.cts +165 -0
- package/dist/audio.d.mts +165 -0
- package/dist/audio.mjs +4 -0
- package/dist/env-DSnGaERV.cjs +19 -0
- package/dist/env-DUwUWTsg.mjs +14 -0
- package/dist/events-BUMYdETO.d.cts +24 -0
- package/dist/events-BUMYdETO.d.mts +24 -0
- package/dist/events-BxDTIKKq.cjs +48 -0
- package/dist/events-BylBSBW-.mjs +43 -0
- package/dist/gemini.cjs +401 -0
- package/dist/gemini.d.cts +41 -0
- package/dist/gemini.d.mts +41 -0
- package/dist/gemini.mjs +395 -0
- package/dist/index.cjs +2142 -0
- package/dist/index.d.cts +920 -0
- package/dist/index.d.mts +920 -0
- package/dist/index.mjs +2113 -0
- package/dist/mulaw--cwU2c9L.mjs +64 -0
- package/dist/mulaw-DLUObjdP.cjs +117 -0
- package/dist/openai.cjs +61 -0
- package/dist/openai.d.cts +121 -0
- package/dist/openai.d.mts +121 -0
- package/dist/openai.mjs +53 -0
- package/dist/presets-Bf75YXs5.d.cts +24 -0
- package/dist/presets-Bf75YXs5.d.mts +24 -0
- package/dist/rest-BYqiVOhe.mjs +265 -0
- package/dist/rest-BvUKut_k.cjs +300 -0
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/dist/session-config-BVLl7-ha.mjs +74 -0
- package/dist/session-config-c8sOw1XL.cjs +85 -0
- package/dist/store.cjs +3 -0
- package/dist/store.d.cts +2 -0
- package/dist/store.d.mts +2 -0
- package/dist/store.mjs +2 -0
- package/dist/testing.cjs +544 -0
- package/dist/testing.d.cts +191 -0
- package/dist/testing.d.mts +191 -0
- package/dist/testing.mjs +538 -0
- package/dist/transcode-C9aJG7_W.cjs +215 -0
- package/dist/transcode-CsAp97G9.mjs +198 -0
- package/dist/transport-B_PJFIVd.d.cts +155 -0
- package/dist/transport-CEaLFV4E.d.mts +155 -0
- package/dist/twilio.cjs +8 -0
- package/dist/twilio.d.cts +3 -0
- package/dist/twilio.d.mts +3 -0
- package/dist/twilio.mjs +2 -0
- package/dist/twiml-z9LjoF4_.d.cts +67 -0
- package/dist/twiml-z9LjoF4_.d.mts +67 -0
- package/dist/xai.cjs +92 -0
- package/dist/xai.d.cts +35 -0
- package/dist/xai.d.mts +35 -0
- package/dist/xai.mjs +86 -0
- package/package.json +183 -0
package/dist/audio.d.mts
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { n as BackgroundAudioPreset, r as BackgroundAudioSpec, t as BackgroundAudioOptions } from "./presets-Bf75YXs5.mjs";
|
|
2
|
+
//#region src/audio/mulaw.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* G.711 μ-law codec (the format Twilio Media Streams speak: 8 kHz, 1 byte/sample).
|
|
5
|
+
*
|
|
6
|
+
* Decode uses a 256-entry lookup table; encode uses the canonical Sun g711.c
|
|
7
|
+
* algorithm (bias 0x84, clip 32635). μ-law silence is 0xFF.
|
|
8
|
+
*/
|
|
9
|
+
/** One byte of μ-law silence (encodes linear 0). */
|
|
10
|
+
declare const MULAW_SILENCE_BYTE = 255;
|
|
11
|
+
/** Samples per second on the Twilio media stream. μ-law is 1 byte per sample. */
|
|
12
|
+
declare const MULAW_SAMPLE_RATE = 8000;
|
|
13
|
+
/** Bytes per 20 ms Twilio media frame at 8 kHz μ-law. */
|
|
14
|
+
declare const MULAW_FRAME_BYTES_20MS = 160;
|
|
15
|
+
/** Decode a single μ-law byte to a linear PCM16 sample. */
|
|
16
|
+
declare function mulawDecodeSample(byte: number): number;
|
|
17
|
+
/** Encode a single linear PCM16 sample to a μ-law byte. */
|
|
18
|
+
declare function mulawEncodeSample(sample: number): number;
|
|
19
|
+
/** Decode a μ-law buffer to linear PCM16 samples. */
|
|
20
|
+
declare function mulawToPcm16(mulaw: Uint8Array): Int16Array;
|
|
21
|
+
/** Encode linear PCM16 samples to a μ-law buffer. */
|
|
22
|
+
declare function pcm16ToMulaw(pcm: Int16Array): Uint8Array;
|
|
23
|
+
/** Duration in milliseconds of a μ-law byte count at 8 kHz (1 byte = 125 µs). */
|
|
24
|
+
declare function mulawBytesToMs(bytes: number): number;
|
|
25
|
+
/** Byte length of a base64 string without decoding it. */
|
|
26
|
+
declare function base64ByteLength(base64: string): number;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/audio/resampler.d.ts
|
|
29
|
+
/**
|
|
30
|
+
* Stateful polyphase FIR sample-rate converter.
|
|
31
|
+
*
|
|
32
|
+
* Built for streaming telephony audio: the instance carries the FIR history
|
|
33
|
+
* across process() calls, so chunk boundaries produce bit-identical output to
|
|
34
|
+
* single-pass processing — no per-chunk zero-padding, no boundary clicks.
|
|
35
|
+
* Coefficients are computed once per (from, to, quality) in a module cache.
|
|
36
|
+
*
|
|
37
|
+
* Rational L/M design: the prototype lowpass is a Kaiser-windowed sinc at the
|
|
38
|
+
* upsampled rate (from × L), decomposed into L phases of N/L taps. Each phase
|
|
39
|
+
* is normalized to unit DC gain so constant signals pass through exactly.
|
|
40
|
+
*/
|
|
41
|
+
interface ResamplerOptions {
|
|
42
|
+
/**
|
|
43
|
+
* Prototype filter length multiplier. The prototype has
|
|
44
|
+
* `quality × max(L, M)` taps (rounded up to a multiple of L); higher is
|
|
45
|
+
* cleaner and slower. Default 48 (≈70–80 dB alias rejection for 24k→8k).
|
|
46
|
+
*/
|
|
47
|
+
quality?: number;
|
|
48
|
+
/** Kaiser window beta. Default 8. */
|
|
49
|
+
kaiserBeta?: number;
|
|
50
|
+
/** Passband edge as a fraction of the tighter Nyquist. Default 0.9. */
|
|
51
|
+
rolloff?: number;
|
|
52
|
+
}
|
|
53
|
+
declare class Resampler {
|
|
54
|
+
readonly fromRate: number;
|
|
55
|
+
readonly toRate: number;
|
|
56
|
+
private readonly L;
|
|
57
|
+
private readonly M;
|
|
58
|
+
private readonly bank;
|
|
59
|
+
/** Trailing input samples carried between chunks (tapsPerPhase − 1 long). */
|
|
60
|
+
private hist;
|
|
61
|
+
/** Phase index of the next output sample. */
|
|
62
|
+
private phase;
|
|
63
|
+
/**
|
|
64
|
+
* Input index (relative to the start of the next [hist + chunk] buffer) that
|
|
65
|
+
* the next output sample is anchored on. Always ≥ tapsPerPhase − 1.
|
|
66
|
+
*/
|
|
67
|
+
private kRel;
|
|
68
|
+
constructor(fromRate: number, toRate: number, options?: ResamplerOptions);
|
|
69
|
+
/** True when no rate conversion is needed (input is passed through). */
|
|
70
|
+
get isPassthrough(): boolean;
|
|
71
|
+
process(input: Int16Array): Int16Array;
|
|
72
|
+
/** Drain the filter tail by pushing one phase-length of silence. */
|
|
73
|
+
flush(): Int16Array;
|
|
74
|
+
/** Clear all carried state (history, phase) for reuse on a fresh stream. */
|
|
75
|
+
reset(): void;
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/audio/transcode.d.ts
|
|
79
|
+
/** Twilio → provider: base64 μ-law 8 kHz in, base64 PCM16LE at `outRate` out. */
|
|
80
|
+
declare class InboundTranscoder {
|
|
81
|
+
private readonly resampler;
|
|
82
|
+
constructor(outRate?: number, options?: ResamplerOptions);
|
|
83
|
+
process(base64Mulaw: string): string;
|
|
84
|
+
reset(): void;
|
|
85
|
+
}
|
|
86
|
+
/** Provider → Twilio: base64 PCM16LE at `inRate` in, base64 μ-law 8 kHz out. */
|
|
87
|
+
declare class OutboundTranscoder {
|
|
88
|
+
private readonly resampler;
|
|
89
|
+
/** Dangling byte from a chunk that split a 16-bit sample. */
|
|
90
|
+
private carry;
|
|
91
|
+
constructor(inRate?: number, options?: ResamplerOptions);
|
|
92
|
+
process(base64Pcm16: string): string;
|
|
93
|
+
reset(): void;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/audio/gain.d.ts
|
|
97
|
+
/**
|
|
98
|
+
* Gain application on μ-law frames, used for background-audio fades and volume.
|
|
99
|
+
* μ-law is logarithmic, so gain must ramp in the linear domain:
|
|
100
|
+
* decode → scale → re-encode.
|
|
101
|
+
*/
|
|
102
|
+
/** Scale an entire μ-law frame by a constant linear gain. */
|
|
103
|
+
declare function scaleMulaw(frame: Uint8Array, gain: number): Uint8Array;
|
|
104
|
+
/**
|
|
105
|
+
* Apply a linearly interpolated gain ramp across a μ-law frame
|
|
106
|
+
* (`startGain` at the first sample → `endGain` at the last).
|
|
107
|
+
*/
|
|
108
|
+
declare function fadeMulaw(frame: Uint8Array, startGain: number, endGain: number): Uint8Array;
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/audio/background/BackgroundAudioPlayer.d.ts
|
|
111
|
+
interface BackgroundAudioPlayerDeps {
|
|
112
|
+
sendMedia: (base64Payload: string) => void;
|
|
113
|
+
onStarted?: (info: {
|
|
114
|
+
preset?: string;
|
|
115
|
+
}) => void;
|
|
116
|
+
onStopped?: (info: {
|
|
117
|
+
preset?: string;
|
|
118
|
+
}) => void;
|
|
119
|
+
now?: () => number;
|
|
120
|
+
}
|
|
121
|
+
declare class BackgroundAudioPlayer {
|
|
122
|
+
private readonly deps;
|
|
123
|
+
private readonly now;
|
|
124
|
+
private generation;
|
|
125
|
+
private active;
|
|
126
|
+
private startDelayTimer;
|
|
127
|
+
/** Tool-call ids currently holding the loop. */
|
|
128
|
+
private readonly holders;
|
|
129
|
+
private pendingSpec;
|
|
130
|
+
constructor(deps: BackgroundAudioPlayerDeps);
|
|
131
|
+
get isPlaying(): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Refcounted acquisition (one holder per tool call). The loop starts after
|
|
134
|
+
* `startDelayMs` unless every holder releases first.
|
|
135
|
+
*/
|
|
136
|
+
acquire(holderId: string, spec: BackgroundAudioSpec, options?: BackgroundAudioOptions): void;
|
|
137
|
+
/** Release one holder; the loop stops when the last holder releases. */
|
|
138
|
+
release(holderId: string, opts?: {
|
|
139
|
+
immediate?: boolean;
|
|
140
|
+
}): void;
|
|
141
|
+
/** Direct start (facade `playBackgroundAudio`). Bypasses refcounting. */
|
|
142
|
+
start(spec: BackgroundAudioSpec, options?: BackgroundAudioOptions): void;
|
|
143
|
+
/**
|
|
144
|
+
* Stop the loop. Fade-out is applied when `immediate` is false and a
|
|
145
|
+
* fadeOutMs was configured; agent-audio preemption should pass
|
|
146
|
+
* `immediate: true` (a fade would delay real speech behind it).
|
|
147
|
+
*/
|
|
148
|
+
stop(opts?: {
|
|
149
|
+
immediate?: boolean;
|
|
150
|
+
}): void;
|
|
151
|
+
/** Real agent audio arrived — kill the loop instantly, no fade, no clear. */
|
|
152
|
+
notifyAgentAudio(): void;
|
|
153
|
+
private cancelDelay;
|
|
154
|
+
private startNow;
|
|
155
|
+
private tick;
|
|
156
|
+
/** Wrap-around frame extraction for seamless looping. */
|
|
157
|
+
private extractFrame;
|
|
158
|
+
}
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/audio/background/loader.d.ts
|
|
161
|
+
declare function isPresetName(spec: BackgroundAudioSpec): spec is BackgroundAudioPreset;
|
|
162
|
+
/** Resolve a spec to raw μ-law bytes (cached per preset/path). */
|
|
163
|
+
declare function loadBackgroundAudio(spec: BackgroundAudioSpec): Buffer;
|
|
164
|
+
//#endregion
|
|
165
|
+
export { type BackgroundAudioOptions, BackgroundAudioPlayer, type BackgroundAudioPlayerDeps, type BackgroundAudioPreset, type BackgroundAudioSpec, InboundTranscoder, MULAW_FRAME_BYTES_20MS, MULAW_SAMPLE_RATE, MULAW_SILENCE_BYTE, OutboundTranscoder, Resampler, type ResamplerOptions, base64ByteLength, fadeMulaw, isPresetName, loadBackgroundAudio, mulawBytesToMs, mulawDecodeSample, mulawEncodeSample, mulawToPcm16, pcm16ToMulaw, scaleMulaw };
|
package/dist/audio.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { a as mulawBytesToMs, c as mulawToPcm16, i as base64ByteLength, l as pcm16ToMulaw, n as MULAW_SAMPLE_RATE, o as mulawDecodeSample, r as MULAW_SILENCE_BYTE, s as mulawEncodeSample, t as MULAW_FRAME_BYTES_20MS } from "./mulaw--cwU2c9L.mjs";
|
|
2
|
+
import { a as scaleMulaw, i as fadeMulaw, n as isPresetName, r as loadBackgroundAudio, t as BackgroundAudioPlayer } from "./BackgroundAudioPlayer-iMcivjis.mjs";
|
|
3
|
+
import { n as OutboundTranscoder, r as Resampler, t as InboundTranscoder } from "./transcode-CsAp97G9.mjs";
|
|
4
|
+
export { BackgroundAudioPlayer, InboundTranscoder, MULAW_FRAME_BYTES_20MS, MULAW_SAMPLE_RATE, MULAW_SILENCE_BYTE, OutboundTranscoder, Resampler, base64ByteLength, fadeMulaw, isPresetName, loadBackgroundAudio, mulawBytesToMs, mulawDecodeSample, mulawEncodeSample, mulawToPcm16, pcm16ToMulaw, scaleMulaw };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/internal/env.ts
|
|
2
|
+
/**
|
|
3
|
+
* Resolve an API key: an explicitly passed key always wins; otherwise the
|
|
4
|
+
* first non-empty value among the given environment variable names is used.
|
|
5
|
+
*/
|
|
6
|
+
function resolveApiKey(explicit, envNames) {
|
|
7
|
+
if (explicit) return explicit;
|
|
8
|
+
for (const name of envNames) {
|
|
9
|
+
const value = process.env[name];
|
|
10
|
+
if (value) return value;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
Object.defineProperty(exports, "resolveApiKey", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function() {
|
|
17
|
+
return resolveApiKey;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/internal/env.ts
|
|
2
|
+
/**
|
|
3
|
+
* Resolve an API key: an explicitly passed key always wins; otherwise the
|
|
4
|
+
* first non-empty value among the given environment variable names is used.
|
|
5
|
+
*/
|
|
6
|
+
function resolveApiKey(explicit, envNames) {
|
|
7
|
+
if (explicit) return explicit;
|
|
8
|
+
for (const name of envNames) {
|
|
9
|
+
const value = process.env[name];
|
|
10
|
+
if (value) return value;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { resolveApiKey as t };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/internal/events.d.ts
|
|
2
|
+
type Listener = (...args: any[]) => void;
|
|
3
|
+
/**
|
|
4
|
+
* EventEmitter with a typed event map. Listener errors are contained per
|
|
5
|
+
* Node's usual semantics; `emit` returns whether any listener ran.
|
|
6
|
+
*
|
|
7
|
+
* The constraint deliberately avoids `Record<string, Listener>`: event-map
|
|
8
|
+
* interfaces must NOT carry a string index signature, or `keyof` widens to
|
|
9
|
+
* `string` and misspelled event names compile silently (a listener that can
|
|
10
|
+
* never fire). With the mapped-type constraint, plain interfaces qualify and
|
|
11
|
+
* unknown names are compile-time errors.
|
|
12
|
+
*/
|
|
13
|
+
declare class TypedEmitter<Events extends { [K in keyof Events]: Listener; }> {
|
|
14
|
+
private readonly emitter;
|
|
15
|
+
constructor();
|
|
16
|
+
on<K extends keyof Events & string>(event: K, listener: Events[K]): this;
|
|
17
|
+
once<K extends keyof Events & string>(event: K, listener: Events[K]): this;
|
|
18
|
+
off<K extends keyof Events & string>(event: K, listener: Events[K]): this;
|
|
19
|
+
removeAllListeners(event?: keyof Events & string): this;
|
|
20
|
+
protected emit<K extends keyof Events & string>(event: K, ...args: Parameters<Events[K]>): boolean;
|
|
21
|
+
listenerCount(event: keyof Events & string): number;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { TypedEmitter as t };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/internal/events.d.ts
|
|
2
|
+
type Listener = (...args: any[]) => void;
|
|
3
|
+
/**
|
|
4
|
+
* EventEmitter with a typed event map. Listener errors are contained per
|
|
5
|
+
* Node's usual semantics; `emit` returns whether any listener ran.
|
|
6
|
+
*
|
|
7
|
+
* The constraint deliberately avoids `Record<string, Listener>`: event-map
|
|
8
|
+
* interfaces must NOT carry a string index signature, or `keyof` widens to
|
|
9
|
+
* `string` and misspelled event names compile silently (a listener that can
|
|
10
|
+
* never fire). With the mapped-type constraint, plain interfaces qualify and
|
|
11
|
+
* unknown names are compile-time errors.
|
|
12
|
+
*/
|
|
13
|
+
declare class TypedEmitter<Events extends { [K in keyof Events]: Listener; }> {
|
|
14
|
+
private readonly emitter;
|
|
15
|
+
constructor();
|
|
16
|
+
on<K extends keyof Events & string>(event: K, listener: Events[K]): this;
|
|
17
|
+
once<K extends keyof Events & string>(event: K, listener: Events[K]): this;
|
|
18
|
+
off<K extends keyof Events & string>(event: K, listener: Events[K]): this;
|
|
19
|
+
removeAllListeners(event?: keyof Events & string): this;
|
|
20
|
+
protected emit<K extends keyof Events & string>(event: K, ...args: Parameters<Events[K]>): boolean;
|
|
21
|
+
listenerCount(event: keyof Events & string): number;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { TypedEmitter as t };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
let node_events = require("node:events");
|
|
2
|
+
//#region src/internal/events.ts
|
|
3
|
+
/**
|
|
4
|
+
* EventEmitter with a typed event map. Listener errors are contained per
|
|
5
|
+
* Node's usual semantics; `emit` returns whether any listener ran.
|
|
6
|
+
*
|
|
7
|
+
* The constraint deliberately avoids `Record<string, Listener>`: event-map
|
|
8
|
+
* interfaces must NOT carry a string index signature, or `keyof` widens to
|
|
9
|
+
* `string` and misspelled event names compile silently (a listener that can
|
|
10
|
+
* never fire). With the mapped-type constraint, plain interfaces qualify and
|
|
11
|
+
* unknown names are compile-time errors.
|
|
12
|
+
*/
|
|
13
|
+
var TypedEmitter = class {
|
|
14
|
+
emitter = new node_events.EventEmitter();
|
|
15
|
+
constructor() {
|
|
16
|
+
this.emitter.setMaxListeners(50);
|
|
17
|
+
}
|
|
18
|
+
on(event, listener) {
|
|
19
|
+
this.emitter.on(event, listener);
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
once(event, listener) {
|
|
23
|
+
this.emitter.once(event, listener);
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
off(event, listener) {
|
|
27
|
+
this.emitter.off(event, listener);
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
removeAllListeners(event) {
|
|
31
|
+
this.emitter.removeAllListeners(event);
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
emit(event, ...args) {
|
|
35
|
+
if (event === "error" && this.emitter.listenerCount("error") === 0) return false;
|
|
36
|
+
return this.emitter.emit(event, ...args);
|
|
37
|
+
}
|
|
38
|
+
listenerCount(event) {
|
|
39
|
+
return this.emitter.listenerCount(event);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
Object.defineProperty(exports, "TypedEmitter", {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function() {
|
|
46
|
+
return TypedEmitter;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
//#region src/internal/events.ts
|
|
3
|
+
/**
|
|
4
|
+
* EventEmitter with a typed event map. Listener errors are contained per
|
|
5
|
+
* Node's usual semantics; `emit` returns whether any listener ran.
|
|
6
|
+
*
|
|
7
|
+
* The constraint deliberately avoids `Record<string, Listener>`: event-map
|
|
8
|
+
* interfaces must NOT carry a string index signature, or `keyof` widens to
|
|
9
|
+
* `string` and misspelled event names compile silently (a listener that can
|
|
10
|
+
* never fire). With the mapped-type constraint, plain interfaces qualify and
|
|
11
|
+
* unknown names are compile-time errors.
|
|
12
|
+
*/
|
|
13
|
+
var TypedEmitter = class {
|
|
14
|
+
emitter = new EventEmitter();
|
|
15
|
+
constructor() {
|
|
16
|
+
this.emitter.setMaxListeners(50);
|
|
17
|
+
}
|
|
18
|
+
on(event, listener) {
|
|
19
|
+
this.emitter.on(event, listener);
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
once(event, listener) {
|
|
23
|
+
this.emitter.once(event, listener);
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
off(event, listener) {
|
|
27
|
+
this.emitter.off(event, listener);
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
removeAllListeners(event) {
|
|
31
|
+
this.emitter.removeAllListeners(event);
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
emit(event, ...args) {
|
|
35
|
+
if (event === "error" && this.emitter.listenerCount("error") === 0) return false;
|
|
36
|
+
return this.emitter.emit(event, ...args);
|
|
37
|
+
}
|
|
38
|
+
listenerCount(event) {
|
|
39
|
+
return this.emitter.listenerCount(event);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
export { TypedEmitter as t };
|