-
Notifications
You must be signed in to change notification settings - Fork 80
Don't use enums or any #444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds a public Changes
Sequence Diagram(s)(omitted — changes are type/interface declarations only; control flow unchanged) Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/packages/ListenLiveClient.ts(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/packages/ListenLiveClient.ts (6)
src/packages/AbstractLiveClient.ts (1)
AbstractLiveClient(542-542)src/lib/types/LiveTranscriptionEvent.ts (1)
LiveTranscriptionEvent(1-34)src/lib/types/LiveMetadataEvent.ts (1)
LiveMetadataEvent(1-9)src/lib/types/UtteranceEndEvent.ts (1)
UtteranceEndEvent(1-5)src/lib/types/SpeechStartedEvent.ts (1)
SpeechStartedEvent(1-5)src/lib/errors.ts (1)
DeepgramApiError(14-30)
🪛 Biome (2.1.2)
src/packages/ListenLiveClient.ts
[error] 21-21: This class is unsafely merged with an interface.
The interface is declared here.
The TypeScript compiler doesn't check whether properties defined in the interface are initialized in the class.
(lint/suspicious/noUnsafeDeclarationMerging)
🔇 Additional comments (6)
src/packages/ListenLiveClient.ts (6)
3-4: LGTM!The import additions are well-aligned with the strongly-typed interface overloads below. All imported event types are properly utilized.
21-21: LGTM!The eslint-disable directive is appropriate for the declaration merging pattern used here. This allows strongly-typed event listeners without modifying the base class implementation.
150-150: LGTM!The eslint-disable directive is correctly placed for the interface declaration merging.
152-155: LGTM!These event listener overloads correctly match their corresponding implementations in
setupConnectionand provide strong typing for transcript, metadata, utterance end, speech started, and unhandled events.Also applies to: 159-159
157-157: LGTM!The Close event correctly specifies no parameters, which aligns with typical WebSocket close event behavior.
158-158: The Open event correctly receives the client instance parameter.Verification confirms that
AbstractLiveClient.setupConnectionEvents()at line 502 emits the Open event withthis(the client instance) as the parameter:this.emit(events.Open, this). This matches the type signature inListenLiveClientline 158 which expectslistener: (client: ListenLiveClient) => void. The implementation is correct.
| on(eventName: `${LiveTranscriptionEvents.Metadata}`, listener: (data: LiveMetadataEvent) => void): this | ||
| on(eventName: `${LiveTranscriptionEvents.UtteranceEnd}`, listener: (data: UtteranceEndEvent) => void): this | ||
| on(eventName: `${LiveTranscriptionEvents.SpeechStarted}`, listener: (data: SpeechStartedEvent) => void): this | ||
| on(eventName: `${LiveTranscriptionEvents.Error}`, listener: (data: DeepgramApiError) => void): this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Script executed:
#!/bin/bash
# First, find the ListenLiveClient.ts file and examine the Error event listener and implementation
# Find the file
find . -name "ListenLiveClient.ts" -type f
# Read the file to check lines around 79-88 and 156
if [ -f "src/packages/ListenLiveClient.ts" ]; then
echo "=== Lines 70-95 (error emission) ==="
sed -n '70,95p' src/packages/ListenLiveClient.ts
echo ""
echo "=== Lines 150-165 (Error event listener) ==="
sed -n '150,165p' src/packages/ListenLiveClient.ts
fiRepository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
./src/packages/ListenLiveClient.ts
=== Lines 70-95 (error emission) ===
this.emit(LiveTranscriptionEvents.Transcript, data);
} else if (data.type === LiveTranscriptionEvents.UtteranceEnd) {
this.emit(LiveTranscriptionEvents.UtteranceEnd, data);
} else if (data.type === LiveTranscriptionEvents.SpeechStarted) {
this.emit(LiveTranscriptionEvents.SpeechStarted, data);
} else {
this.emit(LiveTranscriptionEvents.Unhandled, data);
}
} catch (error) {
this.emit(LiveTranscriptionEvents.Error, {
event,
message: "Unable to parse `data` as JSON.",
error,
url: this.conn?.url,
readyState: this.conn?.readyState,
data:
event.data?.toString().substring(0, 200) +
(event.data?.toString().length > 200 ? "..." : ""),
});
}
};
}
}
/**
* Sends additional config to the connected session.
=== Lines 150-165 (Error event listener) ===
export { ListenLiveClient as LiveClient };
</shell_result>
Script executed:
#!/bin/bash
# Search for the on method signature and Error event listener
echo "=== Searching for Error event listener in ListenLiveClient ==="
rg -n "on.*Error" src/packages/ListenLiveClient.ts -A 1 -B 1
echo ""
echo "=== Looking for the on method overloads ==="
rg -n "^\s*on\(" src/packages/ListenLiveClient.ts -A 1
echo ""
echo "=== Finding AbstractLiveClient ==="
find . -name "AbstractLiveClient.ts" -type fRepository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Searching for Error event listener in ListenLiveClient ===
49- * - When the connection is closed, it emits the `LiveTranscriptionEvents.Close` event.
50: * - When an error occurs on the connection, it emits the `LiveTranscriptionEvents.Error` event.
51- * - When a message is received, it parses the message and emits the appropriate event based on the message type, such as `LiveTranscriptionEvents.Metadata`, `LiveTranscriptionEvents.Transcript`, `LiveTranscriptionEvents.UtteranceEnd`, and `LiveTranscriptionEvents.SpeechStarted`.
--
57- Close: LiveTranscriptionEvents.Close,
58: Error: LiveTranscriptionEvents.Error,
59- });
--
78- } catch (error) {
79: this.emit(LiveTranscriptionEvents.Error, {
80- event,
=== Looking for the on method overloads ===
=== Finding AbstractLiveClient ===
./src/packages/AbstractLiveClient.ts
</shell_result>
Script executed:
#!/bin/bash
# Check AbstractLiveClient for on method signatures and setupConnectionEvents
echo "=== File size check ==="
wc -l ./src/packages/AbstractLiveClient.ts
echo ""
echo "=== Search for on method overloads with Error event ==="
rg -n "on.*Error" ./src/packages/AbstractLiveClient.ts -A 2 -B 2
echo ""
echo "=== Search for setupConnectionEvents ==="
rg -n "setupConnectionEvents" ./src/packages/AbstractLiveClient.ts -A 15
echo ""
echo "=== Search for all on method signatures ==="
rg -n "^\s*on\(" ./src/packages/AbstractLiveClient.ts -A 1 | head -50Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== File size check ===
542 ./src/packages/AbstractLiveClient.ts
=== Search for on method overloads with Error event ===
294- * ```typescript
295- * // Enhanced error information is now available in error events:
296: * connection.on(LiveTranscriptionEvents.Error, (err) => {
297: * console.error("WebSocket Error:", err.message);
298- *
299- * // Access HTTP status code (e.g., 502, 403, etc.)
--
324- * // Access the enhanced error object for detailed debugging
325- * if (err.error?.name === 'DeepgramWebSocketError') {
326: * console.error("Enhanced Error Details:", err.error.toJSON());
327- * }
328- * });
--
414- ) {
415- // Create the enhanced error for detailed debugging
416: const enhancedError = new DeepgramWebSocketError(
417- (event as ErrorEvent).message || "WebSocket connection error",
418- {
--
497- * @protected
498- */
499: protected setupConnectionEvents(events: { Open: string; Close: string; Error: string }): void {
500- if (this.conn) {
501- this.conn.onopen = () => {
--
507- };
508-
509: this.conn.onerror = (event: ErrorEvent) => {
510: const enhancedInfo = this.extractErrorInformation(event, this.conn || undefined);
511: const enhancedError = this.createEnhancedError(event, enhancedInfo);
512- this.emit(events.Error, enhancedError);
513- };
=== Search for setupConnectionEvents ===
499: protected setupConnectionEvents(events: { Open: string; Close: string; Error: string }): void {
500- if (this.conn) {
501- this.conn.onopen = () => {
502- this.emit(events.Open, this);
503- };
504-
505- this.conn.onclose = (event: any) => {
506- this.emit(events.Close, event);
507- };
508-
509- this.conn.onerror = (event: ErrorEvent) => {
510- const enhancedInfo = this.extractErrorInformation(event, this.conn || undefined);
511- const enhancedError = this.createEnhancedError(event, enhancedInfo);
512- this.emit(events.Error, enhancedError);
513- };
514- }
=== Search for all on method signatures ===
</shell_result>
Script executed:
#!/bin/bash
# Search for on method signatures and error types
echo "=== Search for on method definitions (broader search) ==="
rg -n "^\s*on\(" ./src/packages/AbstractLiveClient.ts -A 1 | head -100
echo ""
echo "=== Search for DeepgramApiError type ==="
rg -n "DeepgramApiError" ./src/packages/AbstractLiveClient.ts -B 2 -A 2
echo ""
echo "=== Search for createEnhancedError method ==="
rg -n "createEnhancedError" ./src/packages/AbstractLiveClient.ts -A 10 | head -30
echo ""
echo "=== Check what DeepgramWebSocketError is ==="
rg -n "class DeepgramWebSocketError" . -A 5
echo ""
echo "=== Look for on method with Error in ListenLiveClient (check full file structure) ==="
head -200 ./src/packages/ListenLiveClient.ts | tail -100Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Search for on method definitions (broader search) ===
=== Search for DeepgramApiError type ===
=== Search for createEnhancedError method ===
405: protected createEnhancedError(
406- event: ErrorEvent | Event,
407- enhancedInfo: {
408- statusCode?: number;
409- requestId?: string;
410- responseHeaders?: Record<string, string>;
411- url?: string;
412- readyState?: number;
413- }
414- ) {
415- // Create the enhanced error for detailed debugging
--
511: const enhancedError = this.createEnhancedError(event, enhancedInfo);
512- this.emit(events.Error, enhancedError);
513- };
514- }
515- }
516-
517- /**
518- * Sets up the connection event handlers.
519- *
520- * @abstract Requires subclasses to set up context aware event handlers.
521- */
=== Check what DeepgramWebSocketError is ===
./src/lib/errors.ts:56:export class DeepgramWebSocketError extends DeepgramError {
./src/lib/errors.ts-57- originalEvent?: ErrorEvent | Event;
./src/lib/errors.ts-58- statusCode?: number;
./src/lib/errors.ts-59- requestId?: string;
./src/lib/errors.ts-60- responseHeaders?: Record<string, string>;
./src/lib/errors.ts-61- url?: string;
=== Look for on method with Error in ListenLiveClient (check full file structure) ===
* - When a message is received, it parses the message and emits the appropriate event based on the message type, such as `LiveTranscriptionEvents.Metadata`, `LiveTranscriptionEvents.Transcript`, `LiveTranscriptionEvents.UtteranceEnd`, and `LiveTranscriptionEvents.SpeechStarted`.
*/
public setupConnection(): void {
// Set up standard connection events (open, close, error) using abstracted method
this.setupConnectionEvents({
Open: LiveTranscriptionEvents.Open,
Close: LiveTranscriptionEvents.Close,
Error: LiveTranscriptionEvents.Error,
});
// Set up message handling specific to transcription
if (this.conn) {
this.conn.onmessage = (event: MessageEvent) => {
try {
const data: any = JSON.parse(event.data.toString());
if (data.type === LiveTranscriptionEvents.Metadata) {
this.emit(LiveTranscriptionEvents.Metadata, data);
} else if (data.type === LiveTranscriptionEvents.Transcript) {
this.emit(LiveTranscriptionEvents.Transcript, data);
} else if (data.type === LiveTranscriptionEvents.UtteranceEnd) {
this.emit(LiveTranscriptionEvents.UtteranceEnd, data);
} else if (data.type === LiveTranscriptionEvents.SpeechStarted) {
this.emit(LiveTranscriptionEvents.SpeechStarted, data);
} else {
this.emit(LiveTranscriptionEvents.Unhandled, data);
}
} catch (error) {
this.emit(LiveTranscriptionEvents.Error, {
event,
message: "Unable to parse `data` as JSON.",
error,
url: this.conn?.url,
readyState: this.conn?.readyState,
data:
event.data?.toString().substring(0, 200) +
(event.data?.toString().length > 200 ? "..." : ""),
});
}
};
}
}
/**
* Sends additional config to the connected session.
*
* @param config - The configuration options to apply to the LiveClient.
* @param config.numerals - We currently only support numerals.
*/
public configure(config: LiveConfigOptions): void {
this.send(
JSON.stringify({
type: "Configure",
processors: config,
})
);
}
/**
* Sends a "KeepAlive" message to the server to maintain the connection.
*/
public keepAlive(): void {
this.send(
JSON.stringify({
type: "KeepAlive",
})
);
}
/**
* Sends a "Finalize" message to flush any transcription sitting in the server's buffer.
*/
public finalize(): void {
this.send(
JSON.stringify({
type: "Finalize",
})
);
}
/**
* @deprecated Since version 3.4. Will be removed in version 4.0. Use `requestClose` instead.
*/
public finish(): void {
this.requestClose();
}
/**
* Requests the server close the connection.
*/
public requestClose(): void {
this.send(
JSON.stringify({
type: "CloseStream",
})
);
}
}
export { ListenLiveClient as LiveClient };
</shell_result>
Script executed:
#!/bin/bash
# Check the class hierarchy and EventEmitter implementation
echo "=== Check ListenLiveClient imports and class definition ==="
head -30 ./src/packages/ListenLiveClient.ts
echo ""
echo "=== Check AbstractLiveClient imports and class definition ==="
head -40 ./src/packages/AbstractLiveClient.ts
echo ""
echo "=== Search for on method with full context in AbstractLiveClient ==="
rg -n "on\s*\(" ./src/packages/AbstractLiveClient.ts | head -20
echo ""
echo "=== Look for EventEmitter or similar pattern ==="
rg -n "EventEmitter\|on\s*\(.*listener.*\)" ./src/packages/ -A 1 | head -40
echo ""
echo "=== Check if there's a types file with event listener definitions ==="
find ./src -name "*.ts" -type f | xargs grep -l "LiveTranscriptionEvents.*Error" | head -5Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Check ListenLiveClient imports and class definition ===
import { AbstractLiveClient } from "./AbstractLiveClient";
import { LiveTranscriptionEvents } from "../lib/enums";
import type { LiveSchema, LiveConfigOptions, DeepgramClientOptions } from "../lib/types";
import { DeepgramError } from "../lib/errors";
/**
* The `ListenLiveClient` class extends the `AbstractLiveClient` class and provides functionality for setting up and managing a WebSocket connection for live transcription.
*
* The constructor takes in `DeepgramClientOptions` and an optional `LiveSchema` object, as well as an optional `endpoint` string. It then calls the `connect` method of the parent `AbstractLiveClient` class to establish the WebSocket connection.
*
* The `setupConnection` method is responsible for handling the various events that can occur on the WebSocket connection, such as opening, closing, and receiving messages. It sets up event handlers for these events and emits the appropriate events based on the message type.
*
* The `configure` method allows you to send additional configuration options to the connected session, such as enabling numerals.
*
* The `keepAlive` method sends a "KeepAlive" message to the server to maintain the connection.
*
* The `requestClose` method requests the server to close the connection.
*
* The `finish` method is deprecated as of version 3.4 and will be removed in version 4.0. Use `requestClose` instead.
*/
export class ListenLiveClient extends AbstractLiveClient {
public namespace: string = "listen";
/**
* Constructs a new `ListenLiveClient` instance with the provided options.
*
* @param options - The `DeepgramClientOptions` to use for the client connection.
* @param transcriptionOptions - An optional `LiveSchema` object containing additional configuration options for the live transcription.
* @param endpoint - An optional string representing the WebSocket endpoint to connect to. Defaults to `:version/listen`.
*/
=== Check AbstractLiveClient imports and class definition ===
import { AbstractClient, noop } from "./AbstractClient";
import { CONNECTION_STATE, SOCKET_STATES } from "../lib/constants";
import type { DeepgramClientOptions, LiveSchema } from "../lib/types";
import type { WebSocket as WSWebSocket } from "ws";
import { isBun } from "../lib/runtime";
import { DeepgramWebSocketError } from "../lib/errors";
/**
* Represents a constructor for a WebSocket-like object that can be used in the application.
* The constructor takes the following parameters:
* @param address - The URL or address of the WebSocket server.
* @param _ignored - An optional parameter that is ignored.
* @param options - An optional object containing headers to be included in the WebSocket connection.
* @returns A WebSocket-like object that implements the WebSocketLike interface.
*/
interface WebSocketLikeConstructor {
new(
address: string | URL,
_ignored?: any,
options?: { headers: object | undefined }
): WebSocketLike;
}
/**
* Represents the types of WebSocket-like connections that can be used in the application.
* This type is used to provide a common interface for different WebSocket implementations,
* such as the native WebSocket API, a WebSocket wrapper library, or a dummy implementation
* for testing purposes.
*/
type WebSocketLike = WebSocket | WSWebSocket | WSWebSocketDummy;
/**
* Represents the types of data that can be sent or received over a WebSocket-like connection.
*/
type SocketDataLike = string | ArrayBufferLike | Blob;
/**
* Represents an error that occurred in a WebSocket-like connection.
* @property {any} error - The underlying error object.
* @property {string} message - A human-readable error message.
=== Search for on method with full context in AbstractLiveClient ===
131: this.setupConnection();
147: this.setupConnection();
160: this.setupConnection();
180: this.setupConnection();
199: this.conn.onclose = function () { }; // noop
296: * connection.on(LiveTranscriptionEvents.Error, (err) => {
335: protected extractErrorInformation(
510: const enhancedInfo = this.extractErrorInformation(event, this.conn || undefined);
522: abstract setupConnection(): void;
=== Look for EventEmitter or similar pattern ===
=== Check if there's a types file with event listener definitions ===
./src/packages/AbstractLiveClient.ts
./src/packages/ListenLiveClient.ts
</shell_result>
Script executed:
#!/bin/bash
# Check AbstractClient for on method
echo "=== Check AbstractClient ==="
find ./src -name "AbstractClient.ts" -type f
echo ""
echo "=== Read AbstractClient to find on method ==="
if [ -f "./src/packages/AbstractClient.ts" ]; then
wc -l ./src/packages/AbstractClient.ts
echo ""
echo "=== Search for on method in AbstractClient ==="
rg -n "on\s*\(" ./src/packages/AbstractClient.ts -B 2 -A 5 | head -100
fi
echo ""
echo "=== Search for event listener type definitions ==="
rg -n "listener.*DeepgramApiError\|listener.*Error" ./src --type ts -B 1 -A 1 | head -50Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Check AbstractClient ===
./src/packages/AbstractClient.ts
=== Read AbstractClient to find on method ===
172 ./src/packages/AbstractClient.ts
=== Search for on method in AbstractClient ===
143- * Version and template the endpoint for input argument..
144- */
145: endpoint = endpoint.replace(/:(\w+)/g, function (_, key) {
146- return fields![key];
147- });
148-
149- /**
150- * Create a URL object.
=== Search for event listener type definitions ===
</shell_result>
Script executed:
#!/bin/bash
# Read full AbstractClient and search for EventEmitter
echo "=== Read full AbstractClient.ts ==="
cat -n ./src/packages/AbstractClient.ts
echo ""
echo "=== Search for EventEmitter in project ==="
rg -n "EventEmitter\|extends.*EventEmitter" ./src --type ts
echo ""
echo "=== Search for on method definition anywhere ==="
rg -n "^\s*(public|protected)?\s*on\s*\(" ./src --type ts -A 2 | head -50Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Read full AbstractClient.ts ===
1 import { EventEmitter } from "events";
2 import { DEFAULT_OPTIONS, DEFAULT_URL } from "../lib/constants";
3 import { DeepgramError } from "../lib/errors";
4 import { appendSearchParams, applyDefaults, convertLegacyOptions } from "../lib/helpers";
5 import type {
6 DeepgramClientOptions,
7 DefaultClientOptions,
8 DefaultNamespaceOptions,
9 NamespaceOptions,
10 } from "../lib/types";
11
12 export const noop = () => {};
13
14 /**
15 * Represents an abstract Deepgram client that provides a base implementation for interacting with the Deepgram API.
16 *
17 * The `AbstractClient` class is responsible for:
18 * - Initializing the Deepgram API key
19 * - Applying default options for the client and namespace
20 * - Providing a namespace for organizing API requests
21 *
22 * Subclasses of `AbstractClient` should implement the specific functionality for interacting with the Deepgram API.
23 */
24 export abstract class AbstractClient extends EventEmitter {
25 protected factory: Function | undefined = undefined;
26 protected key: string | undefined = undefined;
27 protected accessToken: string | undefined = undefined;
28 protected options: DefaultClientOptions;
29 public namespace: string = "global";
30 public version: string = "v1";
31 public baseUrl: string = DEFAULT_URL;
32 public logger: Function = noop;
33
34 /**
35 * Constructs a new instance of the DeepgramClient class with the provided options.
36 *
37 * @param options - The options to configure the DeepgramClient instance.
38 * @param options.key - The Deepgram API key to use for authentication. If not provided, the `DEEPGRAM_API_KEY` environment variable will be used.
39 * @param options.accessToken - The Deepgram access token to use for authentication. If not provided, the `DEEPGRAM_ACCESS_TOKEN` environment variable will be used.
40 * @param options.global - Global options that apply to all requests made by the DeepgramClient instance.
41 * @param options.global.fetch - Options to configure the fetch requests made by the DeepgramClient instance.
42 * @param options.global.fetch.options - Additional options to pass to the fetch function, such as `url` and `headers`.
43 * @param options.namespace - Options specific to a particular namespace within the DeepgramClient instance.
44 */
45 constructor(options: DeepgramClientOptions) {
46 super();
47
48 // run the factory for the access token if it's a function
49 if (typeof options.accessToken === "function") {
50 this.factory = options.accessToken;
51 this.accessToken = this.factory();
52 } else {
53 this.accessToken = options.accessToken;
54 }
55
56 // run the factory for the key if it's a function
57 if (typeof options.key === "function") {
58 this.factory = options.key;
59 this.key = this.factory();
60 } else {
61 this.key = options.key;
62 }
63
64 // implement priority-based credential resolution for environment variables
65 if (!this.key && !this.accessToken) {
66 // check for DEEPGRAM_ACCESS_TOKEN first (higher priority)
67 this.accessToken = process.env.DEEPGRAM_ACCESS_TOKEN as string;
68
69 // if still no access token, fall back to DEEPGRAM_API_KEY (lower priority)
70 if (!this.accessToken) {
71 this.key = process.env.DEEPGRAM_API_KEY as string;
72 }
73 }
74
75 // if we STILL have neither, throw an error
76 if (!this.key && !this.accessToken) {
77 throw new DeepgramError("A deepgram API key or access token is required.");
78 }
79
80 options = convertLegacyOptions(options);
81
82 /**
83 * Apply default options.
84 */
85 this.options = applyDefaults<DeepgramClientOptions, DefaultClientOptions>(
86 options,
87 DEFAULT_OPTIONS
88 );
89 }
90
91 /**
92 * Sets the version for the current instance of the Deepgram API and returns the instance.
93 *
94 * @param version - The version to set for the Deepgram API instance. Defaults to "v1" if not provided.
95 * @returns The current instance of the AbstractClient with the updated version.
96 */
97 public v(version: string = "v1"): this {
98 this.version = version;
99
100 return this;
101 }
102
103 /**
104 * Gets the namespace options for the current instance of the AbstractClient.
105 * The namespace options include the default options merged with the global options,
106 * and the API key for the current instance.
107 *
108 * @returns The namespace options for the current instance.
109 */
110 get namespaceOptions(): DefaultNamespaceOptions {
111 const defaults = applyDefaults<NamespaceOptions, DefaultNamespaceOptions>(
112 (this.options as any)[this.namespace],
113 this.options.global
114 );
115
116 return {
117 ...defaults,
118 key: this.key,
119 };
120 }
121
122 /**
123 * Generates a URL for an API endpoint with optional query parameters and transcription options.
124 *
125 * @param endpoint - The API endpoint URL, which may contain placeholders for fields.
126 * @param fields - An optional object containing key-value pairs to replace placeholders in the endpoint URL.
127 * @param transcriptionOptions - Optional transcription options to include as query parameters in the URL.
128 * @returns A URL object representing the constructed API request URL.
129 */
130 public getRequestUrl(
131 endpoint: string,
132 fields: { [key: string]: string } = { version: this.version },
133 transcriptionOptions?: {
134 [key: string]: unknown;
135 }
136 ): URL {
137 /**
138 * If we pass in fields without a version, set a version.
139 */
140 fields.version = this.version;
141
142 /**
143 * Version and template the endpoint for input argument..
144 */
145 endpoint = endpoint.replace(/:(\w+)/g, function (_, key) {
146 return fields![key];
147 });
148
149 /**
150 * Create a URL object.
151 */
152 const url = new URL(endpoint as string, this.baseUrl);
153
154 /**
155 * If there are transcription options, append them to the request as URL querystring parameters
156 */
157 if (transcriptionOptions) {
158 appendSearchParams(url.searchParams, transcriptionOptions);
159 }
160
161 return url;
162 }
163
164 /**
165 * Logs the message.
166 *
167 * For customized logging, `this.logger` can be overridden.
168 */
169 public log(kind: string, msg: string, data?: any) {
170 this.logger(kind, msg, data);
171 }
172 }
=== Search for EventEmitter in project ===
=== Search for on method definition anywhere ===
</shell_result>
Script executed:
#!/bin/bash
# Search for TypeScript type overloads for on method
echo "=== Search for on method overloads in types files ==="
find ./src -name "*.ts" -type f -exec grep -l "on\s*\(" {} \; | xargs grep -l "eventName\|listener" | head -10
echo ""
echo "=== Search for type definitions with Error listener ==="
rg -n "listener.*Error\|Error.*listener" ./src/lib/types --type ts -B 2 -A 2
echo ""
echo "=== Look for type definitions file ==="
ls -la ./src/lib/types*
echo ""
echo "=== Search for LiveTranscriptionEvents enum ==="
rg -n "LiveTranscriptionEvents" ./src/lib/enums -A 20
echo ""
echo "=== Search for event listener type definitions ==="
rg -n "on\s*\(.*eventName" ./src --type ts -B 1 -A 3 | head -80Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Search for on method overloads in types files ===
=== Search for type definitions with Error listener ===
=== Look for type definitions file ===
total 188
drwxr-xr-x 2 jailuser jailuser 960 Nov 26 18:07 .
drwxr-xr-x 4 jailuser jailuser 200 Nov 26 18:07 ..
-rw-r--r-- 1 jailuser jailuser 2120 Nov 26 18:07 AgentLiveSchema.ts
-rw-r--r-- 1 jailuser jailuser 716 Nov 26 18:07 AnalyzeSchema.ts
-rw-r--r-- 1 jailuser jailuser 64 Nov 26 18:07 AsyncAnalyzeResponse.ts
-rw-r--r-- 1 jailuser jailuser 68 Nov 26 18:07 AsyncPrerecordedResponse.ts
-rw-r--r-- 1 jailuser jailuser 145 Nov 26 18:07 CreateOnPremCredentialsSchema.ts
-rw-r--r-- 1 jailuser jailuser 189 Nov 26 18:07 CreateProjectKeyResponse.ts
-rw-r--r-- 1 jailuser jailuser 362 Nov 26 18:07 CreateProjectKeySchema.ts
-rw-r--r-- 1 jailuser jailuser 2581 Nov 26 18:07 DeepgramClientOptions.ts
-rw-r--r-- 1 jailuser jailuser 245 Nov 26 18:07 DeepgramResponse.ts
-rw-r--r-- 1 jailuser jailuser 303 Nov 26 18:07 DeepgramSource.ts
-rw-r--r-- 1 jailuser jailuser 203 Nov 26 18:07 Fetch.ts
-rw-r--r-- 1 jailuser jailuser 347 Nov 26 18:07 FunctionCallResponse.ts
-rw-r--r-- 1 jailuser jailuser 422 Nov 26 18:07 GetModelsResponse.ts
-rw-r--r-- 1 jailuser jailuser 99 Nov 26 18:07 GetModelsSchema.ts
-rw-r--r-- 1 jailuser jailuser 214 Nov 26 18:07 GetProjectBalancesResponse.ts
-rw-r--r-- 1 jailuser jailuser 124 Nov 26 18:07 GetProjectInvitesResponse.ts
-rw-r--r-- 1 jailuser jailuser 381 Nov 26 18:07 GetProjectKeysResponse.ts
-rw-r--r-- 1 jailuser jailuser 72 Nov 26 18:07 GetProjectMemberScopesResponse.ts
-rw-r--r-- 1 jailuser jailuser 191 Nov 26 18:07 GetProjectMembersResponse.ts
-rw-r--r-- 1 jailuser jailuser 97 Nov 26 18:07 GetProjectResponse.ts
-rw-r--r-- 1 jailuser jailuser 271 Nov 26 18:07 GetProjectUsageFieldsResponse.ts
-rw-r--r-- 1 jailuser jailuser 114 Nov 26 18:07 GetProjectUsageFieldsSchema.ts
-rw-r--r-- 1 jailuser jailuser 1109 Nov 26 18:07 GetProjectUsageRequestsResponse.ts
-rw-r--r-- 1 jailuser jailuser 154 Nov 26 18:07 GetProjectUsageRequestsSchema.ts
-rw-r--r-- 1 jailuser jailuser 291 Nov 26 18:07 GetProjectUsageSummaryResponse.ts
-rw-r--r-- 1 jailuser jailuser 543 Nov 26 18:07 GetProjectUsageSummarySchema.ts
-rw-r--r-- 1 jailuser jailuser 125 Nov 26 18:07 GetProjectsResponse.ts
-rw-r--r-- 1 jailuser jailuser 71 Nov 26 18:07 GetTokenDetailsResponse.ts
-rw-r--r-- 1 jailuser jailuser 86 Nov 26 18:07 GrantTokenResponse.ts
-rw-r--r-- 1 jailuser jailuser 226 Nov 26 18:07 GrantTokenSchema.ts
-rw-r--r-- 1 jailuser jailuser 375 Nov 26 18:07 ListOnPremCredentialsResponse.ts
-rw-r--r-- 1 jailuser jailuser 276 Nov 26 18:07 LiveConfigOptions.ts
-rw-r--r-- 1 jailuser jailuser 185 Nov 26 18:07 LiveMetadataEvent.ts
-rw-r--r-- 1 jailuser jailuser 688 Nov 26 18:07 LiveTranscriptionEvent.ts
-rw-r--r-- 1 jailuser jailuser 56 Nov 26 18:07 MessageResponse.ts
-rw-r--r-- 1 jailuser jailuser 111 Nov 26 18:07 SendProjectInviteSchema.ts
-rw-r--r-- 1 jailuser jailuser 625 Nov 26 18:07 SpeakSchema.ts
-rw-r--r-- 1 jailuser jailuser 107 Nov 26 18:07 SpeechStartedEvent.ts
-rw-r--r-- 1 jailuser jailuser 1462 Nov 26 18:07 SyncAnalyzeResponse.ts
-rw-r--r-- 1 jailuser jailuser 3436 Nov 26 18:07 SyncPrerecordedResponse.ts
-rw-r--r-- 1 jailuser jailuser 4890 Nov 26 18:07 TranscriptionSchema.ts
-rw-r--r-- 1 jailuser jailuser 101 Nov 26 18:07 UpdateProjectMemberScopeSchema.ts
-rw-r--r-- 1 jailuser jailuser 110 Nov 26 18:07 UpdateProjectSchema.ts
-rw-r--r-- 1 jailuser jailuser 109 Nov 26 18:07 UtteranceEndEvent.ts
-rw-r--r-- 1 jailuser jailuser 203 Nov 26 18:07 VoidResponse.ts
-rw-r--r-- 1 jailuser jailuser 1842 Nov 26 18:07 index.ts
=== Search for LiveTranscriptionEvents enum ===
./src/lib/enums/index.ts:3:export * from "./LiveTranscriptionEvents";
./src/lib/enums/index.ts-4-export * from "./LiveTTSEvents";
--
./src/lib/enums/LiveTranscriptionEvents.ts:13:export enum LiveTranscriptionEvents {
./src/lib/enums/LiveTranscriptionEvents.ts-14- /**
./src/lib/enums/LiveTranscriptionEvents.ts-15- * Built in socket events.
./src/lib/enums/LiveTranscriptionEvents.ts-16- */
./src/lib/enums/LiveTranscriptionEvents.ts-17- Open = "open",
./src/lib/enums/LiveTranscriptionEvents.ts-18- Close = "close",
./src/lib/enums/LiveTranscriptionEvents.ts-19- Error = "error",
./src/lib/enums/LiveTranscriptionEvents.ts-20-
./src/lib/enums/LiveTranscriptionEvents.ts-21- /**
./src/lib/enums/LiveTranscriptionEvents.ts-22- * Message { type: string }
./src/lib/enums/LiveTranscriptionEvents.ts-23- */
./src/lib/enums/LiveTranscriptionEvents.ts-24- Transcript = "Results",
./src/lib/enums/LiveTranscriptionEvents.ts-25- Metadata = "Metadata",
./src/lib/enums/LiveTranscriptionEvents.ts-26- UtteranceEnd = "UtteranceEnd",
./src/lib/enums/LiveTranscriptionEvents.ts-27- SpeechStarted = "SpeechStarted",
./src/lib/enums/LiveTranscriptionEvents.ts-28-
./src/lib/enums/LiveTranscriptionEvents.ts-29- /**
./src/lib/enums/LiveTranscriptionEvents.ts-30- * Catch all for any other message event
./src/lib/enums/LiveTranscriptionEvents.ts-31- */
./src/lib/enums/LiveTranscriptionEvents.ts-32- Unhandled = "Unhandled",
./src/lib/enums/LiveTranscriptionEvents.ts-33-}
=== Search for event listener type definitions ===
stderr:
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
grep: Unmatched ( or \(
</shell_result>
Script executed:
#!/bin/bash
# Let me look at the entire ListenLiveClient.ts structure
echo "=== Get line count of ListenLiveClient.ts ==="
wc -l ./src/packages/ListenLiveClient.ts
echo ""
echo "=== Look at lines 150-200 of ListenLiveClient.ts ==="
sed -n '150,200p' ./src/packages/ListenLiveClient.ts
echo ""
echo "=== Search for type/interface definitions in ListenLiveClient ==="
rg -n "interface\|type\|on\(" ./src/packages/ListenLiveClient.ts
echo ""
echo "=== Check for .d.ts files ==="
find ./src -name "*.d.ts" -type f
echo ""
echo "=== Check if there's TypeScript declaration merging for EventEmitter ==="
rg -n "declare\|module augment\|EventEmitter" ./src/packages --type ts -B 1 -A 1Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 1
stdout:
=== Get line count of ListenLiveClient.ts ===
150 ./src/packages/ListenLiveClient.ts
=== Look at lines 150-200 of ListenLiveClient.ts ===
export { ListenLiveClient as LiveClient };
=== Search for type/interface definitions in ListenLiveClient ===
=== Check for .d.ts files ===
=== Check if there's TypeScript declaration merging for EventEmitter ===
</shell_result>
Script executed:
#!/bin/bash
# The file is only 150 lines. Let me see the entire file
echo "=== Read entire ListenLiveClient.ts ==="
cat -n ./src/packages/ListenLiveClient.ts
echo ""
echo "=== Check git history to see if line 156 existed before ==="
cd ./src/packages && git log --oneline ListenLiveClient.ts | head -5
cd - > /dev/null
echo ""
echo "=== Check the PR diff to see what changed ==="
git diff HEAD~1 ./src/packages/ListenLiveClient.ts 2>/dev/null | head -100Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Read entire ListenLiveClient.ts ===
1 import { AbstractLiveClient } from "./AbstractLiveClient";
2 import { LiveTranscriptionEvents } from "../lib/enums";
3 import type { LiveSchema, LiveConfigOptions, DeepgramClientOptions } from "../lib/types";
4 import { DeepgramError } from "../lib/errors";
5
6 /**
7 * The `ListenLiveClient` class extends the `AbstractLiveClient` class and provides functionality for setting up and managing a WebSocket connection for live transcription.
8 *
9 * The constructor takes in `DeepgramClientOptions` and an optional `LiveSchema` object, as well as an optional `endpoint` string. It then calls the `connect` method of the parent `AbstractLiveClient` class to establish the WebSocket connection.
10 *
11 * The `setupConnection` method is responsible for handling the various events that can occur on the WebSocket connection, such as opening, closing, and receiving messages. It sets up event handlers for these events and emits the appropriate events based on the message type.
12 *
13 * The `configure` method allows you to send additional configuration options to the connected session, such as enabling numerals.
14 *
15 * The `keepAlive` method sends a "KeepAlive" message to the server to maintain the connection.
16 *
17 * The `requestClose` method requests the server to close the connection.
18 *
19 * The `finish` method is deprecated as of version 3.4 and will be removed in version 4.0. Use `requestClose` instead.
20 */
21 export class ListenLiveClient extends AbstractLiveClient {
22 public namespace: string = "listen";
23
24 /**
25 * Constructs a new `ListenLiveClient` instance with the provided options.
26 *
27 * @param options - The `DeepgramClientOptions` to use for the client connection.
28 * @param transcriptionOptions - An optional `LiveSchema` object containing additional configuration options for the live transcription.
29 * @param endpoint - An optional string representing the WebSocket endpoint to connect to. Defaults to `:version/listen`.
30 */
31 constructor(
32 options: DeepgramClientOptions,
33 transcriptionOptions: LiveSchema = {},
34 endpoint: string = ":version/listen"
35 ) {
36 super(options);
37
38 if (transcriptionOptions.keyterm?.length && !transcriptionOptions.model?.startsWith("nova-3")) {
39 throw new DeepgramError("Keyterms are only supported with the Nova 3 models.");
40 }
41
42 this.connect(transcriptionOptions, endpoint);
43 }
44
45 /**
46 * Sets up the connection event handlers.
47 * This method is responsible for handling the various events that can occur on the WebSocket connection, such as opening, closing, and receiving messages.
48 * - When the connection is opened, it emits the `LiveTranscriptionEvents.Open` event.
49 * - When the connection is closed, it emits the `LiveTranscriptionEvents.Close` event.
50 * - When an error occurs on the connection, it emits the `LiveTranscriptionEvents.Error` event.
51 * - When a message is received, it parses the message and emits the appropriate event based on the message type, such as `LiveTranscriptionEvents.Metadata`, `LiveTranscriptionEvents.Transcript`, `LiveTranscriptionEvents.UtteranceEnd`, and `LiveTranscriptionEvents.SpeechStarted`.
52 */
53 public setupConnection(): void {
54 // Set up standard connection events (open, close, error) using abstracted method
55 this.setupConnectionEvents({
56 Open: LiveTranscriptionEvents.Open,
57 Close: LiveTranscriptionEvents.Close,
58 Error: LiveTranscriptionEvents.Error,
59 });
60
61 // Set up message handling specific to transcription
62 if (this.conn) {
63 this.conn.onmessage = (event: MessageEvent) => {
64 try {
65 const data: any = JSON.parse(event.data.toString());
66
67 if (data.type === LiveTranscriptionEvents.Metadata) {
68 this.emit(LiveTranscriptionEvents.Metadata, data);
69 } else if (data.type === LiveTranscriptionEvents.Transcript) {
70 this.emit(LiveTranscriptionEvents.Transcript, data);
71 } else if (data.type === LiveTranscriptionEvents.UtteranceEnd) {
72 this.emit(LiveTranscriptionEvents.UtteranceEnd, data);
73 } else if (data.type === LiveTranscriptionEvents.SpeechStarted) {
74 this.emit(LiveTranscriptionEvents.SpeechStarted, data);
75 } else {
76 this.emit(LiveTranscriptionEvents.Unhandled, data);
77 }
78 } catch (error) {
79 this.emit(LiveTranscriptionEvents.Error, {
80 event,
81 message: "Unable to parse `data` as JSON.",
82 error,
83 url: this.conn?.url,
84 readyState: this.conn?.readyState,
85 data:
86 event.data?.toString().substring(0, 200) +
87 (event.data?.toString().length > 200 ? "..." : ""),
88 });
89 }
90 };
91 }
92 }
93
94 /**
95 * Sends additional config to the connected session.
96 *
97 * @param config - The configuration options to apply to the LiveClient.
98 * @param config.numerals - We currently only support numerals.
99 */
100 public configure(config: LiveConfigOptions): void {
101 this.send(
102 JSON.stringify({
103 type: "Configure",
104 processors: config,
105 })
106 );
107 }
108
109 /**
110 * Sends a "KeepAlive" message to the server to maintain the connection.
111 */
112 public keepAlive(): void {
113 this.send(
114 JSON.stringify({
115 type: "KeepAlive",
116 })
117 );
118 }
119
120 /**
121 * Sends a "Finalize" message to flush any transcription sitting in the server's buffer.
122 */
123 public finalize(): void {
124 this.send(
125 JSON.stringify({
126 type: "Finalize",
127 })
128 );
129 }
130
131 /**
132 * @deprecated Since version 3.4. Will be removed in version 4.0. Use `requestClose` instead.
133 */
134 public finish(): void {
135 this.requestClose();
136 }
137
138 /**
139 * Requests the server close the connection.
140 */
141 public requestClose(): void {
142 this.send(
143 JSON.stringify({
144 type: "CloseStream",
145 })
146 );
147 }
148 }
149
150 export { ListenLiveClient as LiveClient };
=== Check git history to see if line 156 existed before ===
6634e40 chore: adds dx code owners (#430)
=== Check the PR diff to see what changed ===
</shell_result>
Script executed:
#!/bin/bash
# Check if there are any type declaration files or if the review might be from staging
echo "=== Search for any on method with Error listener in entire codebase ==="
rg -n "on.*Error.*listener\|listener.*Error" ./src --type ts -B 2 -A 2
echo ""
echo "=== Check if there's a types declaration for ListenLiveClient event listeners ==="
find ./src -type f -name "*.ts" | xargs grep -l "ListenLiveClient" | xargs grep -l "on\|Error"
echo ""
echo "=== Verify the exact error types being emitted ==="
echo "=== From AbstractLiveClient (setupConnectionEvents line 512) ==="
sed -n '510,515p' ./src/packages/AbstractLiveClient.ts
echo ""
echo "=== From ListenLiveClient (setupConnection line 79) ==="
sed -n '78,90p' ./src/packages/ListenLiveClient.tsRepository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Search for any on method with Error listener in entire codebase ===
=== Check if there's a types declaration for ListenLiveClient event listeners ===
./src/packages/ListenClient.ts
./src/packages/ListenLiveClient.ts
=== Verify the exact error types being emitted ===
=== From AbstractLiveClient (setupConnectionEvents line 512) ===
const enhancedInfo = this.extractErrorInformation(event, this.conn || undefined);
const enhancedError = this.createEnhancedError(event, enhancedInfo);
this.emit(events.Error, enhancedError);
};
}
}
=== From ListenLiveClient (setupConnection line 79) ===
} catch (error) {
this.emit(LiveTranscriptionEvents.Error, {
event,
message: "Unable to parse `data` as JSON.",
error,
url: this.conn?.url,
readyState: this.conn?.readyState,
data:
event.data?.toString().substring(0, 200) +
(event.data?.toString().length > 200 ? "..." : ""),
});
}
};
</shell_result>
Script executed:
#!/bin/bash
# Check createEnhancedError return type
echo "=== Check createEnhancedError return type ==="
sed -n '405,425p' ./src/packages/AbstractLiveClient.ts
echo ""
echo "=== Check DeepgramWebSocketError structure ==="
cat -n ./src/lib/errors.ts | sed -n '56,80p'
echo ""
echo "=== Check if there's any type information in comments or code ==="
rg -n "DeepgramApiError\|DeepgramWebSocketError" ./src/packages/ListenLiveClient.ts
echo ""
echo "=== Double-check imports in ListenLiveClient ==="
head -5 ./src/packages/ListenLiveClient.ts
echo ""
echo "=== Check ListenClient.ts to see if it has anything relevant ==="
head -100 ./src/packages/ListenClient.ts | tail -50Repository: deepgram/deepgram-js-sdk
<shell_result>
Repository: deepgram/deepgram-js-sdk
Exit code: 0
stdout:
=== Check createEnhancedError return type ===
protected createEnhancedError(
event: ErrorEvent | Event,
enhancedInfo: {
statusCode?: number;
requestId?: string;
responseHeaders?: Record<string, string>;
url?: string;
readyState?: number;
}
) {
// Create the enhanced error for detailed debugging
const enhancedError = new DeepgramWebSocketError(
(event as ErrorEvent).message || "WebSocket connection error",
{
originalEvent: event,
...enhancedInfo,
}
);
// Return an object that maintains backward compatibility
// while providing enhanced information
=== Check DeepgramWebSocketError structure ===
56 export class DeepgramWebSocketError extends DeepgramError {
57 originalEvent?: ErrorEvent | Event;
58 statusCode?: number;
59 requestId?: string;
60 responseHeaders?: Record<string, string>;
61 url?: string;
62 readyState?: number;
63
64 constructor(
65 message: string,
66 options: {
67 originalEvent?: ErrorEvent | Event;
68 statusCode?: number;
69 requestId?: string;
70 responseHeaders?: Record<string, string>;
71 url?: string;
72 readyState?: number;
73 } = {}
74 ) {
75 super(message);
76 this.name = "DeepgramWebSocketError";
77 this.originalEvent = options.originalEvent;
78 this.statusCode = options.statusCode;
79 this.requestId = options.requestId;
80 this.responseHeaders = options.responseHeaders;
=== Check if there's any type information in comments or code ===
=== Double-check imports in ListenLiveClient ===
import { AbstractLiveClient } from "./AbstractLiveClient";
import { LiveTranscriptionEvents } from "../lib/enums";
import type { LiveSchema, LiveConfigOptions, DeepgramClientOptions } from "../lib/types";
import { DeepgramError } from "../lib/errors";
=== Check ListenClient.ts to see if it has anything relevant ===
import { AbstractClient } from "./AbstractClient";
import { ListenLiveClient } from "./ListenLiveClient";
import { ListenRestClient } from "./ListenRestClient";
import { LiveSchema } from "../lib/types";
/**
* The `ListenClient` class extends the `AbstractClient` class and provides access to the "listen" namespace.
* It exposes two methods:
*
* 1. `prerecorded()`: Returns a `ListenRestClient` instance for interacting with the prerecorded listen API.
* 2. `live(transcriptionOptions: LiveSchema = {}, endpoint = ":version/listen")`: Returns a `ListenLiveClient` instance for interacting with the live listen API, with the provided transcription options and endpoint.
*/
export class ListenClient extends AbstractClient {
public namespace: string = "listen";
/**
* Returns a `ListenRestClient` instance for interacting with the prerecorded listen API.
*/
get prerecorded() {
return new ListenRestClient(this.options);
}
/**
* Returns a `ListenLiveClient` instance for interacting with the live listen API, with the provided transcription options and endpoint.
* @param {LiveSchema} [transcriptionOptions={}] - The transcription options to use for the live listen API.
* @param {string} [endpoint=":version/listen"] - The endpoint to use for the live listen API.
* @returns {ListenLiveClient} - A `ListenLiveClient` instance for interacting with the live listen API.
*/
public live(
transcriptionOptions: LiveSchema = {},
endpoint: string = ":version/listen"
): ListenLiveClient {
return new ListenLiveClient(this.options, transcriptionOptions, endpoint);
}
}
</shell_result>
Based on my verification, I can now generate the corrected review comment. The review identified a real issue but with significant inaccuracies:
Error event emissions have inconsistent types across the class hierarchy.
The Error event emits two different error structures:
- From
AbstractLiveClient.setupConnectionEvents(line 512): EmitsDeepgramWebSocketErrorwith properties{originalEvent, statusCode, requestId, responseHeaders, url, readyState} - From
ListenLiveClient.setupConnection(lines 79-88): Emits a custom object with{event, message, error, url, readyState, data}
This creates a type safety issue where event listeners receive inconsistent error shapes. Since the on() method is inherited from Node's EventEmitter (which uses generic typing), there's no type safety enforcing consistency.
Consider standardizing the error emission to always emit DeepgramWebSocketError, or define a proper union type that handles both error scenarios:
type LiveTranscriptionError = DeepgramWebSocketError | {
event: MessageEvent;
message: string;
error: unknown;
url?: string;
readyState?: number;
data?: string;
};Then apply consistent typing to error emissions throughout both classes.
🤖 Prompt for AI Agents
In src/packages/ListenLiveClient.ts around line 156, the Error event emits
inconsistent error shapes across the class hierarchy which breaks type safety;
standardize by defining a single error type (either use DeepgramWebSocketError
everywhere or create a union type LiveTranscriptionError that includes both
shapes) and update the EventEmitter typings and all emit sites to use that type
consistently (modify ListenLiveClient.setupConnection emits and
AbstractLiveClient.setupConnectionEvents emits to match the chosen type, and
update the on(...) signature to accept the unified type).
Proposed changes
Please don't make me import enums or guess the types
Eslint rule
This ignores eslint rule
@typescript-eslint/no-unsafe-declaration-mergingSince it only changes the type of a method that is already implemented, it's not a case of unsafe declaration merging.
Types of changes
What types of changes does your code introduce to the community JavaScript SDK?
Put an
xin the boxes that applyChecklist
Put an
xin the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.