@bereasoftware/nexa 0.0.1

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.
@@ -0,0 +1,392 @@
1
+ import { Validator, Transformer, RetryStrategy, HttpErrorDetails, IHttpClient } from '../types';
2
+ /**
3
+ * Schema validator using simple checks (can be replaced with Zod, Yup, etc)
4
+ */
5
+ export declare function createSchemaValidator<T>(schema: Record<keyof T, (value: unknown) => boolean>): Validator;
6
+ /**
7
+ * Validator that ensures response has required fields
8
+ */
9
+ export declare function createRequiredFieldsValidator(fields: string[]): Validator;
10
+ /**
11
+ * Validator that ensures response is an array
12
+ */
13
+ export declare const validatorIsArray: Validator;
14
+ /**
15
+ * Validator that ensures response is an object
16
+ */
17
+ export declare const validatorIsObject: Validator;
18
+ /**
19
+ * Transform that converts snake_case to camelCase (common API pattern)
20
+ */
21
+ export declare const transformSnakeToCamel: Transformer;
22
+ /**
23
+ * Transform that converts camelCase to snake_case
24
+ */
25
+ export declare const transformCamelToSnake: Transformer;
26
+ /**
27
+ * Transform that flattens nested data
28
+ */
29
+ export declare const transformFlatten: Transformer;
30
+ /**
31
+ * Transform that picks specific fields (projection)
32
+ */
33
+ export declare function createProjectionTransformer(fields: string[]): Transformer;
34
+ /**
35
+ * Transform that wraps data in a container
36
+ */
37
+ export declare function createWrapperTransformer(wrapper: string): Transformer;
38
+ /**
39
+ * Aggressive retry: retry all errors up to max attempts
40
+ */
41
+ export declare class AggressiveRetry implements RetryStrategy {
42
+ private maxAttempts;
43
+ constructor(maxAttempts?: number);
44
+ shouldRetry(attempt: number): boolean;
45
+ delayMs(attempt: number): number;
46
+ }
47
+ /**
48
+ * Conservative retry: only retry on specific status codes
49
+ */
50
+ export declare class ConservativeRetry implements RetryStrategy {
51
+ private retryableStatuses;
52
+ private maxAttempts;
53
+ constructor(maxAttempts?: number);
54
+ shouldRetry(attempt: number, error: HttpErrorDetails): boolean;
55
+ delayMs(attempt: number): number;
56
+ }
57
+ /**
58
+ * Circuit breaker pattern: fail fast after threshold
59
+ */
60
+ export declare class CircuitBreakerRetry implements RetryStrategy {
61
+ private failureCount;
62
+ private lastFailureTime;
63
+ private maxAttempts;
64
+ private failureThreshold;
65
+ private resetTimeMs;
66
+ constructor(maxAttempts?: number, failureThreshold?: number, resetTimeMs?: number);
67
+ shouldRetry(attempt: number): boolean;
68
+ delayMs(attempt: number): number;
69
+ reset(): void;
70
+ }
71
+ /**
72
+ * Creates an AbortController with a timeout.
73
+ * Automatically aborts the operation after the specified milliseconds.
74
+ * The timer is cleaned up when the signal is aborted (either by timeout or externally).
75
+ * @param ms - Timeout in milliseconds
76
+ * @returns AbortController that will abort after timeout
77
+ */
78
+ export declare function withTimeout(ms: number): AbortController;
79
+ /**
80
+ * Retry helper function that retries an async operation
81
+ * @param fn - Async function to retry
82
+ * @param retries - Number of retries (default: 3)
83
+ * @returns Result of the function call
84
+ */
85
+ export declare function retry<T>(fn: () => Promise<T>, retries?: number): Promise<T>;
86
+ /**
87
+ * Simple cache store with TTL support
88
+ */
89
+ export declare class CacheStore {
90
+ private cache;
91
+ get<T>(key: string): T | null;
92
+ set<T>(key: string, data: T, ttlMs?: number): void;
93
+ clear(): void;
94
+ has(key: string): boolean;
95
+ delete(key: string): void;
96
+ }
97
+ /**
98
+ * Cache middleware factory - caches HTTP responses with TTL support
99
+ * Automatically skips caching for non-GET requests
100
+ */
101
+ export declare function createCacheMiddleware(options?: {
102
+ cache?: CacheStore;
103
+ ttlMs?: number;
104
+ cacheableStatuses?: number[];
105
+ }): Middleware<HttpContext>;
106
+ /**
107
+ * Pre-configured cache middleware with default 60s TTL
108
+ */
109
+ export declare const cacheMiddleware: Middleware<HttpContext>;
110
+ /**
111
+ * Prevents duplicate requests to the same endpoint
112
+ * Shares pending request promises
113
+ */
114
+ export declare class RequestDeduplicator {
115
+ private pending;
116
+ execute<T>(key: string, fn: () => Promise<T>): Promise<T>;
117
+ clear(): void;
118
+ }
119
+ /**
120
+ * Deduplication middleware factory - shares pending requests to the same URL
121
+ * Prevents duplicate network requests by sharing the same Promise
122
+ */
123
+ export declare function createDedupeMiddleware(options?: {
124
+ deduplicator?: RequestDeduplicator;
125
+ includeBody?: boolean;
126
+ methods?: string[];
127
+ }): Middleware<HttpContext>;
128
+ /**
129
+ * Pre-configured deduplication middleware for GET requests
130
+ */
131
+ export declare const dedupeMiddleware: Middleware<HttpContext>;
132
+ /**
133
+ * HTTP Context passed through middleware chain
134
+ */
135
+ export interface HttpContext {
136
+ request: {
137
+ method: string;
138
+ url: string;
139
+ headers: Record<string, string>;
140
+ body?: unknown;
141
+ };
142
+ response: {
143
+ status: number;
144
+ headers: Record<string, string>;
145
+ body?: unknown;
146
+ };
147
+ state: Record<string, unknown>;
148
+ error?: unknown;
149
+ }
150
+ /**
151
+ * Middleware function type with Express/Koa-like pattern
152
+ * Receives context and next() function to proceed through pipeline
153
+ */
154
+ export type Middleware<T extends HttpContext = HttpContext> = (ctx: T, next: () => Promise<void>) => Promise<void>;
155
+ /**
156
+ * Create a middleware pipeline executor with proper sequencing
157
+ * Prevents multiple next() calls and ensures proper error propagation
158
+ */
159
+ export declare function createPipeline<T extends HttpContext = HttpContext>(middlewares: Middleware<T>[]): (ctx: T) => Promise<void>;
160
+ /**
161
+ * Legacy: MiddlewarePipeline class (backwards compatible)
162
+ * For simpler use cases, kept for compatibility
163
+ */
164
+ export declare class MiddlewarePipeline<T = unknown> {
165
+ private middlewares;
166
+ use(middleware: Middleware<T extends HttpContext ? T : HttpContext> | ((data: T) => T | Promise<T>)): this;
167
+ execute(data: T): Promise<T>;
168
+ clear(): void;
169
+ }
170
+ /**
171
+ * Type-safe response wrapper with automatic type inference
172
+ */
173
+ export interface TypedResponse<T, U = unknown> {
174
+ ok: boolean;
175
+ data?: T;
176
+ error?: U;
177
+ status: number;
178
+ headers: Record<string, string>;
179
+ }
180
+ /**
181
+ * Create a typed response builder
182
+ */
183
+ export declare function createTypedResponse<T, U = unknown>(status: number, data?: T, error?: U, headers?: Record<string, string>): TypedResponse<T, U>;
184
+ /**
185
+ * API Endpoint definition with typed request/response
186
+ */
187
+ export interface ApiEndpoint<TRequest = unknown, TResponse = unknown> {
188
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
189
+ path: string;
190
+ request?: TRequest;
191
+ response: TResponse;
192
+ }
193
+ /**
194
+ * Create a strongly-typed API client method
195
+ */
196
+ export declare function createTypedRequest<TRequest, TResponse>(endpoint: ApiEndpoint<TRequest, TResponse>): (client: IHttpClient, req?: TRequest) => Promise<TResponse>;
197
+ /**
198
+ * API Schema - maps multiple endpoints with automatic type inference
199
+ */
200
+ export type ApiSchema = Record<string, ApiEndpoint>;
201
+ /**
202
+ * Create a typed API client from schema
203
+ */
204
+ export declare function createTypedApiClient<T extends ApiSchema>(schema: T): {
205
+ request: <K extends keyof T>(client: IHttpClient, endpoint: K, data?: T[K] extends ApiEndpoint<infer TReq, any> ? TReq : never) => Promise<T[K] extends ApiEndpoint<any, infer TRes> ? TRes : never>;
206
+ };
207
+ /**
208
+ * Observable-like response wrapper for reactive patterns
209
+ */
210
+ export declare class TypedObservable<T> {
211
+ private subscribers;
212
+ private errorSubscribers;
213
+ private completeSubscribers;
214
+ subscribe(next?: (value: T) => void, error?: (err: unknown) => void, complete?: () => void): {
215
+ unsubscribe: () => void;
216
+ };
217
+ next(value: T): void;
218
+ error(err: unknown): void;
219
+ complete(): void;
220
+ map<U>(fn: (value: T) => U): TypedObservable<U>;
221
+ filter(predicate: (value: T) => boolean): TypedObservable<T>;
222
+ }
223
+ /**
224
+ * Union type helper - extracts success/error types
225
+ */
226
+ export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
227
+ /**
228
+ * Result type extractor for discriminated unions
229
+ */
230
+ export type ResultOf<T extends {
231
+ ok: boolean;
232
+ }> = T extends {
233
+ ok: true;
234
+ } ? Omit<T, 'ok'> : T extends {
235
+ ok: false;
236
+ } ? Omit<T, 'ok'> : never;
237
+ /**
238
+ * Guard function for typing - validates data is T at runtime
239
+ */
240
+ export declare function createTypeGuard<T>(check: (value: unknown) => value is T): (value: unknown) => T;
241
+ /**
242
+ * Branded types for URL safety
243
+ */
244
+ export type Url<T extends string = string> = string & {
245
+ readonly __url: unique symbol;
246
+ readonly __type: T;
247
+ };
248
+ export type ApiUrl = Url<'api'>;
249
+ export type FileUrl = Url<'file'>;
250
+ export declare function createUrl<T extends string = string>(url: string): Url<T>;
251
+ export declare function createApiUrl(path: string): ApiUrl;
252
+ /**
253
+ * Defer pattern for lazy evaluation
254
+ */
255
+ export declare class Defer<T> {
256
+ private _promise;
257
+ private resolveFunc;
258
+ private rejectFunc;
259
+ constructor();
260
+ resolve(value: T): void;
261
+ reject(reason?: unknown): void;
262
+ get promise(): Promise<T>;
263
+ /**
264
+ * @deprecated Use `defer.promise` getter instead
265
+ */
266
+ promise_(): Promise<T>;
267
+ }
268
+ /**
269
+ * Streaming response handler for large files/streams
270
+ */
271
+ export interface StreamOptions {
272
+ chunkSize?: number;
273
+ onChunk?: (chunk: Uint8Array) => void | Promise<void>;
274
+ onProgress?: (loaded: number, total: number) => void;
275
+ }
276
+ /**
277
+ * Handle streaming responses
278
+ */
279
+ export declare function handleStream(response: Response, options?: StreamOptions): Promise<Uint8Array>;
280
+ /**
281
+ * Stream to file (Node.js compatible)
282
+ */
283
+ export declare function streamToFile(response: Response, filePath: string): Promise<void>;
284
+ /**
285
+ * Streaming middleware factory - handles streaming responses with progress tracking
286
+ * Useful for large file downloads, real-time data streaming, etc.
287
+ */
288
+ export declare function createStreamingMiddleware(options?: {
289
+ onChunk?: (chunk: Uint8Array) => void | Promise<void>;
290
+ onProgress?: (loaded: number, total: number) => void;
291
+ }): Middleware<HttpContext>;
292
+ /**
293
+ * Pre-configured streaming middleware with default progress tracking
294
+ */
295
+ export declare const streamingMiddleware: Middleware<HttpContext>;
296
+ /**
297
+ * Plugin interface - plugins can extend HttpClient functionality
298
+ */
299
+ export interface Plugin {
300
+ name: string;
301
+ setup(manager: PluginManager): void | Promise<void>;
302
+ }
303
+ /**
304
+ * Plugin manager for extensible architecture
305
+ * Integrates cache, deduplication, and middleware
306
+ */
307
+ export declare class PluginManager {
308
+ private plugins;
309
+ private cache;
310
+ private deduplicator;
311
+ private middlewares;
312
+ private listeners;
313
+ /**
314
+ * Register a plugin and call its setup method
315
+ */
316
+ register(plugin: Plugin): this;
317
+ /**
318
+ * Add middleware to the pipeline
319
+ */
320
+ addMiddleware(middleware: Middleware<HttpContext>): this;
321
+ /**
322
+ * Get cache store
323
+ */
324
+ getCache(): CacheStore;
325
+ /**
326
+ * Get request deduplicator
327
+ */
328
+ getDeduplicator(): RequestDeduplicator;
329
+ /**
330
+ * Get middleware pipeline executor
331
+ */
332
+ getPipeline(): (ctx: HttpContext) => Promise<void>;
333
+ /**
334
+ * Execute middleware pipeline for a context
335
+ */
336
+ executePipeline(ctx: HttpContext): Promise<void>;
337
+ /**
338
+ * Register event listener
339
+ */
340
+ on(event: string, handler: (...args: unknown[]) => void | Promise<void>): this;
341
+ /**
342
+ * Emit event to all listeners
343
+ */
344
+ emit(event: string, ...args: unknown[]): void;
345
+ /**
346
+ * Unregister event listener
347
+ */
348
+ off(event: string, handler: (...args: unknown[]) => void): this;
349
+ /**
350
+ * Get all registered plugins
351
+ */
352
+ getPlugins(): Plugin[];
353
+ /**
354
+ * Clear all plugins, middlewares, and listeners
355
+ */
356
+ clear(): void;
357
+ }
358
+ /**
359
+ * Example: Logger plugin - logs HTTP requests and responses
360
+ */
361
+ export declare const LoggerPlugin: Plugin;
362
+ /**
363
+ * Example: Metrics plugin - collects request metrics
364
+ */
365
+ export declare class MetricsPlugin implements Plugin {
366
+ name: string;
367
+ private metrics;
368
+ setup(manager: PluginManager): void;
369
+ getMetrics(): {
370
+ requests: number;
371
+ errors: number;
372
+ totalTime: number;
373
+ avgTime: number;
374
+ };
375
+ }
376
+ /**
377
+ * Example: Cache plugin - automatically adds caching middleware
378
+ */
379
+ export declare class CachePlugin implements Plugin {
380
+ name: string;
381
+ ttlMs: number;
382
+ constructor(ttlMs?: number);
383
+ setup(manager: PluginManager): void;
384
+ }
385
+ /**
386
+ * Example: Deduplication plugin - prevents duplicate requests
387
+ */
388
+ export declare class DedupePlugin implements Plugin {
389
+ name: string;
390
+ setup(manager: PluginManager): void;
391
+ }
392
+ export type { HttpErrorDetails };
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@bereasoftware/nexa",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/nexa.cjs.js",
6
+ "module": "./dist/nexa.es.js",
7
+ "types": "./dist/types/index.d.ts",
8
+ "unpkg": "./dist/nexa.umd.js",
9
+ "browser": {
10
+ "./dist/nexa.umd.js": "./dist/nexa.umd.js",
11
+ "./dist/nexa.iife.js": "./dist/nexa.iife.js"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/types/index.d.ts",
16
+ "import": "./dist/nexa.es.js",
17
+ "require": "./dist/nexa.cjs.js",
18
+ "default": "./dist/nexa.umd.js"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "publishConfig": {
25
+ "registry": "https://registry.npmjs.org/",
26
+ "access": "public"
27
+ },
28
+ "keywords": [
29
+ "http",
30
+ "client",
31
+ "typescript",
32
+ "fetch",
33
+ "api",
34
+ "request",
35
+ "library",
36
+ "retry",
37
+ "interceptor",
38
+ "cache",
39
+ "result-type",
40
+ "error-handling",
41
+ "validator",
42
+ "transformer",
43
+ "esm",
44
+ "commonjs",
45
+ "type-safe"
46
+ ],
47
+ "author": "John Andrade <johnandrade@bereasoft.com>",
48
+ "license": "MIT",
49
+ "description": "Nexa is a TypeScript HTTP client library that combines the power of fetch with the convenience of axios, while adhering to SOLID principles. It provides a flexible and extensible API for making HTTP requests, handling retries, caching, and more.",
50
+ "maintainers": [
51
+ {
52
+ "name": "John Andrade",
53
+ "email": "johnandrade@bereasoft.com"
54
+ }
55
+ ],
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "https://github.com/Berea-Soft/nexa.git"
59
+ },
60
+ "bugs": {
61
+ "url": "https://github.com/Berea-Soft/nexa/issues"
62
+ },
63
+ "engines": {
64
+ "node": ">=20.18.0",
65
+ "npm": ">=10.8.2"
66
+ },
67
+ "browserslist": [
68
+ "last 2 versions",
69
+ "not dead",
70
+ "not IE 11",
71
+ "> 1%"
72
+ ],
73
+ "scripts": {
74
+ "dev": "vite",
75
+ "build": "tsc && vite build",
76
+ "test": "vitest run",
77
+ "test:watch": "vitest",
78
+ "test:ui": "vitest --ui",
79
+ "test:coverage": "vitest run --coverage",
80
+ "lint": "tsc --noEmit",
81
+ "prepublishOnly": "npm run build"
82
+ },
83
+ "devDependencies": {
84
+ "@microsoft/api-extractor": "^7.58.0",
85
+ "@semantic-release/changelog": "^6.0.3",
86
+ "@semantic-release/git": "^10.0.1",
87
+ "@semantic-release/github": "^12.0.6",
88
+ "@semantic-release/npm": "^13.1.5",
89
+ "@types/node": "^25.5.0",
90
+ "@vitest/coverage-v8": "^4.1.2",
91
+ "@vitest/ui": "^4.1.2",
92
+ "semantic-release": "^25.0.3",
93
+ "typescript": "~6.0.2",
94
+ "vite": "^8.0.3",
95
+ "vite-plugin-dts": "^4.5.4",
96
+ "vitest": "^4.1.2"
97
+ }
98
+ }