mirror of
https://github.com/DeBrosOfficial/network-ts-sdk.git
synced 2026-01-29 20:53:04 +00:00
fixes
This commit is contained in:
parent
25303e7913
commit
58097e3ff8
@ -1,11 +1,35 @@
|
||||
import { SDKError } from "../errors";
|
||||
|
||||
/**
|
||||
* Context provided to the onNetworkError callback
|
||||
*/
|
||||
export interface NetworkErrorContext {
|
||||
method: "GET" | "POST" | "PUT" | "DELETE" | "WS";
|
||||
path: string;
|
||||
isRetry: boolean;
|
||||
attempt: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when a network error occurs.
|
||||
* Use this to trigger gateway failover or other error handling.
|
||||
*/
|
||||
export type NetworkErrorCallback = (
|
||||
error: SDKError,
|
||||
context: NetworkErrorContext
|
||||
) => void;
|
||||
|
||||
export interface HttpClientConfig {
|
||||
baseURL: string;
|
||||
timeout?: number;
|
||||
maxRetries?: number;
|
||||
retryDelayMs?: number;
|
||||
fetch?: typeof fetch;
|
||||
/**
|
||||
* Callback invoked on network errors (after all retries exhausted).
|
||||
* Use this to trigger gateway failover at the application layer.
|
||||
*/
|
||||
onNetworkError?: NetworkErrorCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,6 +63,7 @@ export class HttpClient {
|
||||
private fetch: typeof fetch;
|
||||
private apiKey?: string;
|
||||
private jwt?: string;
|
||||
private onNetworkError?: NetworkErrorCallback;
|
||||
|
||||
constructor(config: HttpClientConfig) {
|
||||
this.baseURL = config.baseURL.replace(/\/$/, "");
|
||||
@ -47,6 +72,14 @@ export class HttpClient {
|
||||
this.retryDelayMs = config.retryDelayMs ?? 1000;
|
||||
// Use provided fetch or create one with proper TLS configuration for staging certificates
|
||||
this.fetch = config.fetch ?? createFetchWithTLSConfig();
|
||||
this.onNetworkError = config.onNetworkError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the network error callback
|
||||
*/
|
||||
setOnNetworkError(callback: NetworkErrorCallback | undefined): void {
|
||||
this.onNetworkError = callback;
|
||||
}
|
||||
|
||||
setApiKey(apiKey?: string) {
|
||||
@ -258,6 +291,27 @@ export class HttpClient {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the network error callback if configured
|
||||
// This allows the app to trigger gateway failover
|
||||
if (this.onNetworkError) {
|
||||
// Convert native errors (TypeError, AbortError) to SDKError for the callback
|
||||
const sdkError =
|
||||
error instanceof SDKError
|
||||
? error
|
||||
: new SDKError(
|
||||
error instanceof Error ? error.message : String(error),
|
||||
0, // httpStatus 0 indicates network-level failure
|
||||
"NETWORK_ERROR"
|
||||
);
|
||||
this.onNetworkError(sdkError, {
|
||||
method,
|
||||
path,
|
||||
isRetry: false,
|
||||
attempt: this.maxRetries, // All retries exhausted
|
||||
});
|
||||
}
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
clearTimeout(timeoutId);
|
||||
@ -397,6 +451,25 @@ export class HttpClient {
|
||||
error
|
||||
);
|
||||
}
|
||||
|
||||
// Call the network error callback if configured
|
||||
if (this.onNetworkError) {
|
||||
const sdkError =
|
||||
error instanceof SDKError
|
||||
? error
|
||||
: new SDKError(
|
||||
error instanceof Error ? error.message : String(error),
|
||||
0,
|
||||
"NETWORK_ERROR"
|
||||
);
|
||||
this.onNetworkError(sdkError, {
|
||||
method: "POST",
|
||||
path,
|
||||
isRetry: false,
|
||||
attempt: this.maxRetries,
|
||||
});
|
||||
}
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
clearTimeout(timeoutId);
|
||||
@ -425,17 +498,33 @@ export class HttpClient {
|
||||
const response = await this.fetch(url.toString(), fetchOptions);
|
||||
if (!response.ok) {
|
||||
clearTimeout(timeoutId);
|
||||
const error = await response.json().catch(() => ({
|
||||
const errorBody = await response.json().catch(() => ({
|
||||
error: response.statusText,
|
||||
}));
|
||||
throw SDKError.fromResponse(response.status, error);
|
||||
throw SDKError.fromResponse(response.status, errorBody);
|
||||
}
|
||||
return response;
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
if (error instanceof SDKError) {
|
||||
throw error;
|
||||
|
||||
// Call the network error callback if configured
|
||||
if (this.onNetworkError) {
|
||||
const sdkError =
|
||||
error instanceof SDKError
|
||||
? error
|
||||
: new SDKError(
|
||||
error instanceof Error ? error.message : String(error),
|
||||
0,
|
||||
"NETWORK_ERROR"
|
||||
);
|
||||
this.onNetworkError(sdkError, {
|
||||
method: "GET",
|
||||
path,
|
||||
isRetry: false,
|
||||
attempt: 0,
|
||||
});
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
import WebSocket from "isomorphic-ws";
|
||||
import { SDKError } from "../errors";
|
||||
import { NetworkErrorCallback } from "./http";
|
||||
|
||||
export interface WSClientConfig {
|
||||
wsURL: string;
|
||||
timeout?: number;
|
||||
authToken?: string;
|
||||
WebSocket?: typeof WebSocket;
|
||||
/**
|
||||
* Callback invoked on WebSocket errors.
|
||||
* Use this to trigger gateway failover at the application layer.
|
||||
*/
|
||||
onNetworkError?: NetworkErrorCallback;
|
||||
}
|
||||
|
||||
export type WSMessageHandler = (data: string) => void;
|
||||
@ -23,6 +29,7 @@ export class WSClient {
|
||||
private timeout: number;
|
||||
private authToken?: string;
|
||||
private WebSocketClass: typeof WebSocket;
|
||||
private onNetworkError?: NetworkErrorCallback;
|
||||
|
||||
private ws?: WebSocket;
|
||||
private messageHandlers: Set<WSMessageHandler> = new Set();
|
||||
@ -36,6 +43,14 @@ export class WSClient {
|
||||
this.timeout = config.timeout ?? 30000;
|
||||
this.authToken = config.authToken;
|
||||
this.WebSocketClass = config.WebSocket ?? WebSocket;
|
||||
this.onNetworkError = config.onNetworkError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the network error callback
|
||||
*/
|
||||
setOnNetworkError(callback: NetworkErrorCallback | undefined): void {
|
||||
this.onNetworkError = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,9 +72,19 @@ export class WSClient {
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
this.ws?.close();
|
||||
reject(
|
||||
new SDKError("WebSocket connection timeout", 408, "WS_TIMEOUT")
|
||||
);
|
||||
const error = new SDKError("WebSocket connection timeout", 408, "WS_TIMEOUT");
|
||||
|
||||
// Call the network error callback if configured
|
||||
if (this.onNetworkError) {
|
||||
this.onNetworkError(error, {
|
||||
method: "WS",
|
||||
path: this.wsURL,
|
||||
isRetry: false,
|
||||
attempt: 0,
|
||||
});
|
||||
}
|
||||
|
||||
reject(error);
|
||||
}, this.timeout);
|
||||
|
||||
this.ws.addEventListener("open", () => {
|
||||
@ -78,6 +103,17 @@ export class WSClient {
|
||||
console.error("[WSClient] WebSocket error:", event);
|
||||
clearTimeout(timeout);
|
||||
const error = new SDKError("WebSocket error", 500, "WS_ERROR", event);
|
||||
|
||||
// Call the network error callback if configured
|
||||
if (this.onNetworkError) {
|
||||
this.onNetworkError(error, {
|
||||
method: "WS",
|
||||
path: this.wsURL,
|
||||
isRetry: false,
|
||||
attempt: 0,
|
||||
});
|
||||
}
|
||||
|
||||
this.errorHandlers.forEach((handler) => handler(error));
|
||||
reject(error);
|
||||
});
|
||||
|
||||
10
src/index.ts
10
src/index.ts
@ -1,4 +1,4 @@
|
||||
import { HttpClient, HttpClientConfig } from "./core/http";
|
||||
import { HttpClient, HttpClientConfig, NetworkErrorCallback } from "./core/http";
|
||||
import { AuthClient } from "./auth/client";
|
||||
import { DBClient } from "./db/client";
|
||||
import { PubSubClient } from "./pubsub/client";
|
||||
@ -20,6 +20,11 @@ export interface ClientConfig extends Omit<HttpClientConfig, "fetch"> {
|
||||
wsConfig?: Partial<Omit<WSClientConfig, "wsURL">>;
|
||||
functionsConfig?: FunctionsClientConfig;
|
||||
fetch?: typeof fetch;
|
||||
/**
|
||||
* Callback invoked on network errors (HTTP and WebSocket).
|
||||
* Use this to trigger gateway failover at the application layer.
|
||||
*/
|
||||
onNetworkError?: NetworkErrorCallback;
|
||||
}
|
||||
|
||||
export interface Client {
|
||||
@ -39,6 +44,7 @@ export function createClient(config: ClientConfig): Client {
|
||||
maxRetries: config.maxRetries,
|
||||
retryDelayMs: config.retryDelayMs,
|
||||
fetch: config.fetch,
|
||||
onNetworkError: config.onNetworkError,
|
||||
});
|
||||
|
||||
const auth = new AuthClient({
|
||||
@ -55,6 +61,7 @@ export function createClient(config: ClientConfig): Client {
|
||||
const pubsub = new PubSubClient(httpClient, {
|
||||
...config.wsConfig,
|
||||
wsURL,
|
||||
onNetworkError: config.onNetworkError,
|
||||
});
|
||||
const network = new NetworkClient(httpClient);
|
||||
const cache = new CacheClient(httpClient);
|
||||
@ -73,6 +80,7 @@ export function createClient(config: ClientConfig): Client {
|
||||
}
|
||||
|
||||
export { HttpClient } from "./core/http";
|
||||
export type { NetworkErrorCallback, NetworkErrorContext } from "./core/http";
|
||||
export { WSClient } from "./core/ws";
|
||||
export { AuthClient } from "./auth/client";
|
||||
export { DBClient } from "./db/client";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user