@bereasoftware/nexa 1.0.5 → 1.1.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.
@@ -11,18 +11,19 @@ export declare class HttpClient implements IHttpClient {
11
11
  private requestQueue;
12
12
  private pendingRequests;
13
13
  constructor(config?: HttpClientConfig);
14
+ private logDebug;
14
15
  /**
15
16
  * Core request method — all others delegate to this
16
- * Pipeline: hooks → cache → interceptors → fetch → parse → validate → transform → interceptors → cache → hooks
17
+ * Pipeline: hooks → cache → interceptors → transformRequest → fetch → parse → validate → transformResponse → interceptors → cache → hooks
17
18
  */
18
19
  request<T = unknown>(config: HttpRequestConfig): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
19
- get<T = unknown>(url: string, config?: Omit<HttpRequestConfig, 'url' | 'method'>): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
20
- post<T = unknown>(url: string, body?: unknown, config?: Omit<HttpRequestConfig, 'url' | 'method' | 'body'>): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
21
- put<T = unknown>(url: string, body?: unknown, config?: Omit<HttpRequestConfig, 'url' | 'method' | 'body'>): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
22
- patch<T = unknown>(url: string, body?: unknown, config?: Omit<HttpRequestConfig, 'url' | 'method' | 'body'>): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
23
- delete<T = unknown>(url: string, config?: Omit<HttpRequestConfig, 'url' | 'method'>): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
24
- head(url: string, config?: Omit<HttpRequestConfig, 'url' | 'method'>): Promise<Result<HttpResponse<void>, HttpErrorDetails>>;
25
- options(url: string, config?: Omit<HttpRequestConfig, 'url' | 'method'>): Promise<Result<HttpResponse<void>, HttpErrorDetails>>;
20
+ get<T = unknown>(url: string, config?: Omit<HttpRequestConfig, "url" | "method">): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
21
+ post<T = unknown>(url: string, body?: unknown, config?: Omit<HttpRequestConfig, "url" | "method" | "body">): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
22
+ put<T = unknown>(url: string, body?: unknown, config?: Omit<HttpRequestConfig, "url" | "method" | "body">): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
23
+ patch<T = unknown>(url: string, body?: unknown, config?: Omit<HttpRequestConfig, "url" | "method" | "body">): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
24
+ delete<T = unknown>(url: string, config?: Omit<HttpRequestConfig, "url" | "method">): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
25
+ head(url: string, config?: Omit<HttpRequestConfig, "url" | "method">): Promise<Result<HttpResponse<void>, HttpErrorDetails>>;
26
+ options(url: string, config?: Omit<HttpRequestConfig, "url" | "method">): Promise<Result<HttpResponse<void>, HttpErrorDetails>>;
26
27
  addRequestInterceptor(interceptor: RequestInterceptor): Disposer;
27
28
  addResponseInterceptor(interceptor: ResponseInterceptor): Disposer;
28
29
  clearInterceptors(): void;
@@ -64,7 +65,7 @@ export declare class HttpClient implements IHttpClient {
64
65
  * }
65
66
  * ```
66
67
  */
67
- paginate<T = unknown>(url: string, options: PaginateOptions<T>, config?: Omit<HttpRequestConfig, 'url' | 'method'>): AsyncGenerator<T[]>;
68
+ paginate<T = unknown>(url: string, options: PaginateOptions<T>, config?: Omit<HttpRequestConfig, "url" | "method">): AsyncGenerator<T[]>;
68
69
  /**
69
70
  * Poll an endpoint until a condition is met.
70
71
  * Returns the final response that satisfied `until()`.
@@ -79,15 +80,26 @@ export declare class HttpClient implements IHttpClient {
79
80
  * });
80
81
  * ```
81
82
  */
82
- poll<T = unknown>(url: string, options: PollOptions<T>, config?: Omit<HttpRequestConfig, 'url' | 'method'>): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
83
+ poll<T = unknown>(url: string, options: PollOptions<T>, config?: Omit<HttpRequestConfig, "url" | "method">): Promise<Result<HttpResponse<T>, HttpErrorDetails>>;
83
84
  private buildRequest;
84
85
  private buildUrl;
86
+ /**
87
+ * Apply transformRequest functions to the request body and headers.
88
+ * Combines global transformRequest (from client config) and request-specific transformRequest.
89
+ * Mutates headers object in place (axios-style).
90
+ */
91
+ private applyTransformRequestToRequest;
85
92
  private getCacheKey;
86
93
  private fetchWithTimeout;
87
94
  /**
88
95
  * Wraps response body with a progress-tracking ReadableStream
89
96
  */
90
97
  private trackDownloadProgress;
98
+ /**
99
+ * Wraps a promise with a timeout. If the timeout elapses before the promise resolves,
100
+ * rejects with a TimeoutError.
101
+ */
102
+ private withTimeout;
91
103
  private parseResponse;
92
104
  private parseBody;
93
105
  private normalizeError;
@@ -4,4 +4,4 @@
4
4
  export { createHttpClient, HttpClient, HttpError, isHttpError } from './http-client.js';
5
5
  export type { IHttpClient, HttpRequest, HttpRequestConfig, HttpResponse, HttpErrorDetails, RequestInterceptor, ResponseInterceptor, RetryStrategy, CacheStrategy, Validator, Transformer, HttpClientConfig, ResponseType, RequestHooks, ProgressEvent, PaginateOptions, PollOptions, Disposer, Result, } from '../types/index.js';
6
6
  export { Ok, Err } from '../types/index.js';
7
- export { withTimeout, retry, createSchemaValidator, createRequiredFieldsValidator, validatorIsArray, validatorIsObject, transformSnakeToCamel, transformCamelToSnake, transformFlatten, createProjectionTransformer, createWrapperTransformer, AggressiveRetry, ConservativeRetry, CircuitBreakerRetry, CacheStore, createCacheMiddleware, cacheMiddleware, RequestDeduplicator, createDedupeMiddleware, dedupeMiddleware, MiddlewarePipeline, createPipeline, type Middleware, type HttpContext, createTypedResponse, createTypedRequest, createTypedApiClient, createTypeGuard, createUrl, createApiUrl, TypedObservable, Defer, type TypedResponse, type ApiEndpoint, type ApiSchema, type Url, type ApiUrl, type FileUrl, type UnionToIntersection, type ResultOf, handleStream, streamToFile, createStreamingMiddleware, streamingMiddleware, type StreamOptions, PluginManager, LoggerPlugin, MetricsPlugin, CachePlugin, DedupePlugin, type Plugin, } from '../utils';
7
+ export { withTimeout, retry, createSchemaValidator, createRequiredFieldsValidator, validatorIsArray, validatorIsObject, transformSnakeToCamel, transformCamelToSnake, transformFlatten, createProjectionTransformer, createWrapperTransformer, AggressiveRetry, ConservativeRetry, CircuitBreakerRetry, CacheStore, createCacheMiddleware, cacheMiddleware, RequestDeduplicator, createDedupeMiddleware, dedupeMiddleware, createRateLimitMiddleware, rateLimitMiddleware, createCircuitBreakerMiddleware, circuitBreakerMiddleware, MiddlewarePipeline, createPipeline, type Middleware, type HttpContext, createTypedResponse, createTypedRequest, createTypedApiClient, createTypeGuard, createUrl, createApiUrl, TypedObservable, Defer, type TypedResponse, type ApiEndpoint, type ApiSchema, type Url, type ApiUrl, type FileUrl, type UnionToIntersection, type ResultOf, handleStream, streamToFile, createStreamingMiddleware, streamingMiddleware, type StreamOptions, PluginManager, LoggerPlugin, MetricsPlugin, CachePlugin, DedupePlugin, RateLimitPlugin, CircuitBreakerPlugin, type Plugin, } from '../utils';
@@ -0,0 +1,46 @@
1
+ import { NodeTransportOptions } from '../types/index.js';
2
+ declare class Http2SessionPool {
3
+ private sessions;
4
+ private cleanupInterval;
5
+ private readonly maxIdleTime;
6
+ private readonly maxRequestsPerSession;
7
+ constructor();
8
+ private startCleanup;
9
+ private cleanup;
10
+ private closeSession;
11
+ getSession(origin: string, options?: NodeTransportOptions): Promise<import('http2').ClientHttp2Session>;
12
+ releaseSession(origin: string): void;
13
+ getStats(): {
14
+ sessionCount: number;
15
+ origins: string[];
16
+ sessions: {
17
+ origin: string;
18
+ requestCount: number;
19
+ lastUsed: number;
20
+ closing: boolean | undefined;
21
+ sessionAlive: boolean;
22
+ }[];
23
+ };
24
+ closeAll(): void;
25
+ }
26
+ /**
27
+ * Node.js HTTP/1.1 adapter
28
+ */
29
+ export declare function nodeHttpAdapter(input: RequestInfo, init?: RequestInit, options?: NodeTransportOptions): Promise<Response>;
30
+ /**
31
+ * Node.js HTTP/2 adapter (basic implementation)
32
+ */
33
+ export declare function nodeHttp2Adapter(input: RequestInfo, init?: RequestInit, options?: NodeTransportOptions): Promise<Response>;
34
+ /**
35
+ * Close all HTTP/2 sessions in the pool.
36
+ * Useful for cleanup in tests or when shutting down the application.
37
+ */
38
+ export declare function closeHttp2SessionPool(): void;
39
+ /**
40
+ * Get statistics about the HTTP/2 session pool.
41
+ */
42
+ export declare function getHttp2SessionPoolStats(): {
43
+ sessionCount: number;
44
+ origins: string[];
45
+ };
46
+ export { Http2SessionPool };
@@ -3,3 +3,6 @@
3
3
  * Combines fetch power + axios convenience with SOLID principles
4
4
  */
5
5
  export * from './http-client';
6
+ export * from './realtime/index.js';
7
+ export { createMockClient, MockAdapter } from './testing/index.js';
8
+ export type { MockResponse, MockClientOptions } from './testing/index.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Real-time communication clients for WebSocket and Server-Sent Events.
3
+ * Provides unified API for real-time communication with automatic reconnection,
4
+ * heartbeat, and plugin support.
5
+ */
6
+ export type { WebSocketOptions, SSEOptions, RealtimeMessageEvent, IRealtimeClient, IWebSocketClient, ISSEClient, } from '../types/index.js';
7
+ export { createWebSocketClient } from './websocket-client.js';
8
+ export { createSSEClient } from './sse-client.js';
9
+ export { createRealtimePlugin } from './plugin.js';
@@ -0,0 +1,12 @@
1
+ import { Plugin, PluginManager } from '../utils/index.js';
2
+ /**
3
+ * Real-time plugin that adds WebSocket and SSE event listeners to the plugin manager
4
+ */
5
+ export declare class RealtimePlugin implements Plugin {
6
+ name: string;
7
+ setup(manager: PluginManager): void;
8
+ }
9
+ /**
10
+ * Create a realtime plugin instance
11
+ */
12
+ export declare function createRealtimePlugin(): RealtimePlugin;
@@ -0,0 +1,5 @@
1
+ import { SSEOptions, ISSEClient } from '../types/index.js';
2
+ /**
3
+ * Create an SSE client appropriate for the current environment
4
+ */
5
+ export declare function createSSEClient(url: string, options?: SSEOptions): ISSEClient;
@@ -0,0 +1,5 @@
1
+ import { WebSocketOptions, IWebSocketClient } from '../types/index.js';
2
+ /**
3
+ * Create a WebSocket client appropriate for the current environment
4
+ */
5
+ export declare function createWebSocketClient(url: string, options?: WebSocketOptions): IWebSocketClient;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Testing utilities for Nexa HTTP Client
3
+ */
4
+ export { createMockClient, MockAdapter } from './mock-client.js';
5
+ export type { MockResponse, MockClientOptions } from './mock-client.js';
@@ -0,0 +1,152 @@
1
+ import { IHttpClient, HttpRequestConfig } from '../types/index.js';
2
+ /**
3
+ * Configuration for a mocked response
4
+ */
5
+ export interface MockResponse {
6
+ /** HTTP status code (default: 200) */
7
+ status?: number;
8
+ /** HTTP status text (default: 'OK') */
9
+ statusText?: string;
10
+ /** Response headers (default: { 'content-type': 'application/json' }) */
11
+ headers?: Record<string, string>;
12
+ /** Response body (will be JSON.stringified if object/array) */
13
+ data?: any;
14
+ /** Optional delay in milliseconds before responding */
15
+ delay?: number;
16
+ /** Throw a network error instead of returning a response */
17
+ networkError?: boolean;
18
+ /** Error message for network error */
19
+ errorMessage?: string;
20
+ }
21
+ /**
22
+ * Options for creating a mock client
23
+ */
24
+ export interface MockClientOptions {
25
+ /** Base URL to match against (optional) */
26
+ baseURL?: string;
27
+ /** Default delay for all responses (optional) */
28
+ delay?: number;
29
+ /** Whether to pass through unmatched requests to original adapter (default: false) */
30
+ passthrough?: boolean;
31
+ }
32
+ /**
33
+ * Route builder returned by onGet(), onPost(), etc.
34
+ * Allows fluent API like mockAdapter.onGet('/users').reply(200, users)
35
+ */
36
+ declare class RouteBuilder {
37
+ private adapter;
38
+ private method;
39
+ private urlPattern;
40
+ constructor(adapter: MockAdapter, method: string, urlPattern: string | RegExp);
41
+ /**
42
+ * Configure a response for this route
43
+ */
44
+ reply(status: number, data?: any, headers?: Record<string, string>): MockAdapter;
45
+ reply(response: MockResponse): MockAdapter;
46
+ /**
47
+ * Configure a response that will only be used once
48
+ */
49
+ replyOnce(status: number, data?: any, headers?: Record<string, string>): MockAdapter;
50
+ replyOnce(response: MockResponse): MockAdapter;
51
+ /**
52
+ * Configure a network error for this route
53
+ */
54
+ networkError(errorMessage?: string): MockAdapter;
55
+ /**
56
+ * Configure a timeout error for this route
57
+ */
58
+ timeout(): MockAdapter;
59
+ }
60
+ /**
61
+ * Mock adapter that intercepts HTTP requests and returns configured responses.
62
+ * Similar to axios-mock-adapter.
63
+ */
64
+ export declare class MockAdapter {
65
+ private routes;
66
+ private originalAdapter?;
67
+ private mockClient;
68
+ private options;
69
+ private defaultResponse;
70
+ /**
71
+ * Create a new MockAdapter and attach it to a client.
72
+ * The original client is not modified. Instead, a new client with the mock adapter is created.
73
+ * Use the `client` property to access the mock-enabled client.
74
+ */
75
+ constructor(client: IHttpClient, options?: MockClientOptions);
76
+ /**
77
+ * Get the mock-enabled client
78
+ */
79
+ get client(): IHttpClient;
80
+ /**
81
+ * Create a mock adapter that can be used as a standalone adapter.
82
+ * This adapter can be set on any HttpClient via config.adapter.
83
+ */
84
+ createAdapter(): (input: RequestInfo, init?: RequestInit) => Promise<Response>;
85
+ /**
86
+ * Add a route for GET requests
87
+ */
88
+ onGet(urlPattern: string | RegExp): RouteBuilder;
89
+ /**
90
+ * Add a route for POST requests
91
+ */
92
+ onPost(urlPattern: string | RegExp): RouteBuilder;
93
+ /**
94
+ * Add a route for PUT requests
95
+ */
96
+ onPut(urlPattern: string | RegExp): RouteBuilder;
97
+ /**
98
+ * Add a route for PATCH requests
99
+ */
100
+ onPatch(urlPattern: string | RegExp): RouteBuilder;
101
+ /**
102
+ * Add a route for DELETE requests
103
+ */
104
+ onDelete(urlPattern: string | RegExp): RouteBuilder;
105
+ /**
106
+ * Add a route for any HTTP method
107
+ */
108
+ onAny(urlPattern: string | RegExp): RouteBuilder;
109
+ /**
110
+ * Add a route with a specific HTTP method and response
111
+ */
112
+ addRoute(method: string, urlPattern: string | RegExp, response: MockResponse | ((config: HttpRequestConfig) => MockResponse | Promise<MockResponse>), options?: {
113
+ times?: number;
114
+ }): this;
115
+ /**
116
+ * Reset all mock routes
117
+ */
118
+ reset(): void;
119
+ /**
120
+ * Restore original adapter (if any)
121
+ */
122
+ restore(): void;
123
+ /**
124
+ * Helper to create a response configuration
125
+ */
126
+ static reply(status: number, data?: any, headers?: Record<string, string>): MockResponse;
127
+ /**
128
+ * Helper to create a network error response
129
+ */
130
+ static networkError(message?: string): MockResponse;
131
+ private findMatchingRoute;
132
+ }
133
+ /**
134
+ * Create a mock client with axios-mock-adapter-like API
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * import { createHttpClient } from '@bereasoftware/nexa';
139
+ * import { createMockClient } from '@bereasoftware/nexa/testing';
140
+ *
141
+ * const client = createHttpClient({ baseURL: 'https://api.example.com' });
142
+ * const mockClient = createMockClient(client);
143
+ *
144
+ * mockClient.onGet('/users').reply(200, [{ id: 1 }]);
145
+ * mockClient.onPost('/users').reply(201, { id: 2 });
146
+ *
147
+ * // Use mockClient.client for making requests
148
+ * const result = await mockClient.client.get('/users');
149
+ * ```
150
+ */
151
+ export declare function createMockClient(client: IHttpClient, options?: MockClientOptions): MockAdapter;
152
+ export {};