@bereasoftware/nexa 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -2,13 +2,13 @@
2
2
  <img src="assets/Logo.png" alt="Nexa Logo" width="120" height="120" />
3
3
  <h1 align="center">@bereasoftware/nexa</h1>
4
4
  <p align="center">
5
- A modern, type-safe HTTP client that combines the power of <code>fetch</code> with the convenience of <code>axios</code> built on SOLID principles.
5
+ A modern, type-safe HTTP client that combines the power of <code>fetch</code> with the convenience of <code>axios</code>, and adds built-in development observability through <code>Dev Overlay</code>.
6
6
  </p>
7
7
  </p>
8
8
 
9
9
  <p align="center">
10
- <a href="#tests"><img src="https://img.shields.io/badge/Tests-213_passing-brightgreen?style=for-the-badge" alt="Tests" /></a>
11
- <a href="#test-coverage"><img src="https://img.shields.io/badge/Coverage-See_report-orange?style=for-the-badge" alt="Coverage" /></a>
10
+ <a href="#tests"><img src="https://img.shields.io/badge/Tests-219_passing-brightgreen?style=for-the-badge" alt="Tests" /></a>
11
+ <a href="#test-coverage"><img src="https://img.shields.io/badge/Coverage-See_report-orange?style=for-the-badge" alt="Coverage" /></a>
12
12
  <a href="https://www.npmjs.com/package/@bereasoftware/nexa"><img src="https://img.shields.io/npm/v/@bereasoftware/nexa?style=for-the-badge" alt="NPM Version" /></a>
13
13
  <a href="https://bundlephobia.com/package/@bereasoftware/nexa"><img src="https://img.shields.io/bundlephobia/minzip/@bereasoftware/nexa?label=Bundle&style=for-the-badge" alt="Bundle Size" /></a>
14
14
  <a href="https://www.npmjs.com/package/@bereasoftware/nexa"><img src="https://img.shields.io/npm/dm/@bereasoftware/nexa?style=for-the-badge" alt="NPM Downloads" /></a>
@@ -37,6 +37,20 @@
37
37
 
38
38
  ---
39
39
 
40
+ ## Positioning
41
+
42
+ Nexa is not trying to be just another `fetch` wrapper.
43
+
44
+ The library is designed to combine three concerns in one package:
45
+
46
+ - a type-safe HTTP API with zero runtime dependencies
47
+ - real extensibility through retries, caching, middleware, and plugins
48
+ - built-in development observability through `Dev Overlay`
49
+
50
+ That makes it useful not only as an HTTP client, but also as a foundation for SDKs, internal tooling, and workflows where debugging experience matters.
51
+
52
+ ---
53
+
40
54
  ## Why Nexa?
41
55
 
42
56
  | Feature | `fetch` | `axios` | **Nexa** |
@@ -954,11 +968,11 @@ manager.register(rateLimitPlugin);
954
968
 
955
969
  ---
956
970
 
957
- ## Dev Overlay
958
-
959
- Built-in visual development tool for debugging and monitoring HTTP requests in real-time.
960
-
961
- > API status: publicly available and intended for browser development flows. It is not designed for SSR or Node runtimes without a DOM.
971
+ ## Dev Overlay
972
+
973
+ Built-in visual development tool for debugging and monitoring HTTP requests in real-time.
974
+
975
+ > API status: publicly available and intended for browser development flows. It is not designed for SSR or Node runtimes without a DOM.
962
976
 
963
977
  ```typescript
964
978
  import { createHttpClient, createDevOverlay } from "@bereasoftware/nexa";
@@ -980,102 +994,106 @@ const client = createHttpClient({
980
994
  const result = await client.get("/users");
981
995
  ```
982
996
 
983
- ### Features
984
-
985
- - **Keyboard toggle** — Press `Ctrl+Shift+N` or `Cmd+Shift+N` to show/hide
986
- - **Request list** — Shows method, status, URL, duration and badges (cache, retries)
987
- - **Real-time metrics** — Total requests, average, throughput, success, failed
988
- - **Search and filter** — Filter by URL, method or status (`Ctrl+F`)
989
- - **Request detail** — Click any request to see headers, body and timing
990
- - **Quick retry** — Replays the selected URL with `fetch` for fast verification
991
- - **Keyboard shortcuts** — `Ctrl+Shift+N` / `Cmd+Shift+N` (toggle), `Escape` (close), `Ctrl+F` / `Cmd+F` (search)
997
+ ### Features
998
+
999
+ - **Keyboard toggle** — Press `Ctrl+Shift+N` or `Cmd+Shift+N` to show/hide
1000
+ - **Request list** — Shows method, status, URL, duration and badges (cache, retries)
1001
+ - **Real-time metrics** — Total requests, average, throughput, success, failed
1002
+ - **Search and filter** — Filter by URL, method or status (`Ctrl+F`)
1003
+ - **Request detail** — Click any request to see headers, body and timing
1004
+ - **Quick retry** — Replays the selected URL with `fetch` for fast verification
1005
+ - **Keyboard shortcuts** — `Ctrl+Shift+N` / `Cmd+Shift+N` (toggle), `Escape` (close), `Ctrl+F` / `Cmd+F` (search)
992
1006
 
993
1007
  ### API
994
1008
 
995
1009
  ```typescript
996
- createDevOverlay(config?: DevOverlayConfig): { tracker: RequestTracker; ui: DevOverlayUI }
1010
+ createDevOverlay(config?: DevOverlayConfig): { tracker: RequestTracker; ui: DevOverlayUI; config: Required<DevOverlayConfig> }
1011
+ ```
1012
+
1013
+ **Configuration options:**
1014
+
1015
+ | Option | Type | Default | Description |
1016
+ |--------|------|---------|-------------|
1017
+ | `enabled` | `boolean` | `true` | Tracker-level flag you can use to enable or disable the overlay flow in your app |
1018
+ | `position` | `'top-right' \| 'top-left' \| 'bottom-right' \| 'bottom-left'` | `'bottom-right'` | Overlay position |
1019
+ | `theme` | `'dark' \| 'light'` | `'dark'` | Typed visual theme; the current UI is optimized for dark mode |
1020
+ | `maxHistory` | `number` | `500` | Maximum requests in history |
1021
+ | `keyboardShortcut` | `string` | `'ctrl+shift+n'` | Keyboard shortcut |
1022
+ | `devOnly` | `boolean` | `true` | When true the UI mounts only in development environments (NODE_ENV=development or localhost) |
1023
+ | `floatingButtonSize` | `number` | `64` | Floating button width & height in pixels |
1024
+ | `floatingButtonOffset` | `number` | `24` | Offset from viewport edges in pixels |
1025
+ | `floatingButtonTheme` | `'inherit' \| 'dark' \| 'light'` | `'inherit'` | Floating button theme; `'inherit'` uses the overlay `theme` |
1026
+
1027
+ **Behavior notes:**
1028
+
1029
+ - `createDevOverlay()` is a singleton. Multiple calls reuse the same instance.
1030
+ - The overlay only mounts UI when a DOM is available. In SSR or Node you can import the module safely, but no panel is rendered.
1031
+ - `theme` is typed as `'dark' | 'light'`, but the current UI is primarily designed for dark mode.
1032
+ - The retry button uses direct `fetch()` for quick revalidation; it does not automatically replay interceptors or advanced `HttpClient` configuration.
1033
+ - `destroyDevOverlay()` clears the singleton instance, removes the panel, and unregisters the global listeners used by the overlay.
1034
+
1035
+ **Note:** Advanced request options such as `transformRequest`, `credentials`, `withCredentials`, `debug`, `logger`, `transport`, `nodeOptions`, and `autoFormData` are already typed, but not all of them are fully wired into the main `HttpClient` pipeline in this release.
1036
+
1037
+ **UI methods:**
1038
+
1039
+ ```typescript
1040
+ ui.show() // Show overlay
1041
+ ui.hide() // Hide overlay
1042
+ ui.toggle() // Toggle visibility
1043
+ ui.destroy() // Remove the panel from the DOM
1044
+
1045
+ tracker.clear() // Clear history
1046
+ tracker.getHistory() // Get all requests
1047
+ tracker.getMetrics() // Get metrics
1048
+ tracker.getConfig() // Get resolved config
1049
+ tracker.onChange((request) => {}) // Listen for new tracked requests
1050
+ ```
1051
+
1052
+ **Module methods:**
1053
+
1054
+ ```typescript
1055
+ getDevOverlay() // Get current { tracker, ui } or null if not created yet
1056
+ destroyDevOverlay() // Destroy the current singleton instance
997
1057
  ```
998
1058
 
999
- **Configuration options:**
1000
-
1001
- | Option | Type | Default | Description |
1002
- |--------|------|---------|-------------|
1003
- | `enabled` | `boolean` | `true` | Tracker-level flag you can use to enable or disable the overlay flow in your app |
1004
- | `position` | `'top-right' \| 'top-left' \| 'bottom-right' \| 'bottom-left'` | `'bottom-right'` | Overlay position |
1005
- | `theme` | `'dark' \| 'light'` | `'dark'` | Typed visual theme; the current UI is optimized for dark mode |
1006
- | `maxHistory` | `number` | `500` | Maximum requests in history |
1007
- | `keyboardShortcut` | `string` | `'ctrl+shift+n'` | Keyboard shortcut |
1008
-
1009
- **Behavior notes:**
1010
-
1011
- - `createDevOverlay()` is a singleton. Multiple calls reuse the same instance.
1012
- - The overlay only mounts UI when a DOM is available. In SSR or Node you can import the module safely, but no panel is rendered.
1013
- - `theme` is typed as `'dark' | 'light'`, but the current UI is primarily designed for dark mode.
1014
- - The retry button uses direct `fetch()` for quick revalidation; it does not automatically replay interceptors or advanced `HttpClient` configuration.
1015
- - `destroyDevOverlay()` clears the singleton instance, removes the panel, and unregisters the global listeners used by the overlay.
1016
-
1017
- **Note:** Advanced request options such as `transformRequest`, `credentials`, `withCredentials`, `debug`, `logger`, `transport`, `nodeOptions`, and `autoFormData` are already typed, but not all of them are fully wired into the main `HttpClient` pipeline in this release.
1018
-
1019
- **UI methods:**
1020
-
1021
- ```typescript
1022
- ui.show() // Show overlay
1023
- ui.hide() // Hide overlay
1024
- ui.toggle() // Toggle visibility
1025
- ui.destroy() // Remove the panel from the DOM
1026
-
1027
- tracker.clear() // Clear history
1028
- tracker.getHistory() // Get all requests
1029
- tracker.getMetrics() // Get metrics
1030
- tracker.getConfig() // Get resolved config
1031
- tracker.onChange((request) => {}) // Listen for new tracked requests
1032
- ```
1033
-
1034
- **Module methods:**
1035
-
1036
- ```typescript
1037
- getDevOverlay() // Get current { tracker, ui } or null if not created yet
1038
- destroyDevOverlay() // Destroy the current singleton instance
1039
- ```
1040
-
1041
- **When to use each export:**
1042
-
1043
- - `createDevOverlay()` creates or reuses the overlay and returns the `tracker` you pass into `createHttpClient({ devTracker })`.
1044
- - `getDevOverlay()` lets you inspect the current instance without creating a new one.
1045
- - `destroyDevOverlay()` is useful for full teardown during hot reloads, tests, or manual cleanup.
1046
- - `RequestTracker` can be used on its own if you want request history and metrics without mounting the UI.
1047
-
1048
- **Exposed data shapes:**
1049
-
1050
- ```typescript
1051
- type TrackedRequest = {
1052
- id: string;
1053
- method: string;
1054
- url: string;
1055
- status?: number;
1056
- duration: number;
1057
- timestamp: number;
1058
- cached: boolean;
1059
- ok: boolean;
1060
- code?: string;
1061
- headers: Record<string, string>;
1062
- body?: unknown;
1063
- responseHeaders?: Record<string, string>;
1064
- retryCount: number;
1065
- };
1066
-
1067
- type DevMetrics = {
1068
- totalRequests: number;
1069
- successfulRequests: number;
1070
- failedRequests: number;
1071
- cachedRequests: number;
1072
- avgDuration: number;
1073
- maxDuration: number;
1074
- minDuration: number;
1075
- requestsPerSecond: number;
1076
- slowestRequests: TrackedRequest[];
1077
- };
1078
- ```
1059
+ **When to use each export:**
1060
+
1061
+ - `createDevOverlay()` creates or reuses the overlay and returns the `tracker` you pass into `createHttpClient({ devTracker })`.
1062
+ - `getDevOverlay()` lets you inspect the current instance without creating a new one.
1063
+ - `destroyDevOverlay()` is useful for full teardown during hot reloads, tests, or manual cleanup.
1064
+ - `RequestTracker` can be used on its own if you want request history and metrics without mounting the UI.
1065
+
1066
+ **Exposed data shapes:**
1067
+
1068
+ ```typescript
1069
+ type TrackedRequest = {
1070
+ id: string;
1071
+ method: string;
1072
+ url: string;
1073
+ status?: number;
1074
+ duration: number;
1075
+ timestamp: number;
1076
+ cached: boolean;
1077
+ ok: boolean;
1078
+ code?: string;
1079
+ headers: Record<string, string>;
1080
+ body?: unknown;
1081
+ responseHeaders?: Record<string, string>;
1082
+ retryCount: number;
1083
+ };
1084
+
1085
+ type DevMetrics = {
1086
+ totalRequests: number;
1087
+ successfulRequests: number;
1088
+ failedRequests: number;
1089
+ cachedRequests: number;
1090
+ avgDuration: number;
1091
+ maxDuration: number;
1092
+ minDuration: number;
1093
+ requestsPerSecond: number;
1094
+ slowestRequests: TrackedRequest[];
1095
+ };
1096
+ ```
1079
1097
 
1080
1098
  ---
1081
1099
 
@@ -1336,11 +1354,11 @@ Nexa ships in multiple module formats:
1336
1354
 
1337
1355
  ## Development
1338
1356
 
1339
- ### Tests
1340
-
1341
- ```bash
1342
- # Run all tests
1343
- npm test
1357
+ ### Tests
1358
+
1359
+ ```bash
1360
+ # Run all tests
1361
+ npm test
1344
1362
 
1345
1363
  # Watch mode
1346
1364
  npm run test:watch
@@ -1412,15 +1430,15 @@ See the `examples/` folder for usage examples with different frameworks:
1412
1430
  - `svelte-example.ts` — Usage with Svelte
1413
1431
  - `node-example.ts` — Usage with Node.js
1414
1432
 
1415
- ### Test Coverage
1416
-
1417
- Generate the latest report locally:
1418
-
1419
- ```bash
1420
- npm run test:coverage
1421
- ```
1422
-
1423
- Coverage changes as features evolve, so the generated report should be treated as the source of truth instead of hardcoded percentages in the README.
1433
+ ### Test Coverage
1434
+
1435
+ Generate the latest report locally:
1436
+
1437
+ ```bash
1438
+ npm run test:coverage
1439
+ ```
1440
+
1441
+ Coverage changes as features evolve, so the generated report should be treated as the source of truth instead of hardcoded percentages in the README.
1424
1442
 
1425
1443
  ---
1426
1444
 
package/README.md CHANGED
@@ -2,13 +2,13 @@
2
2
  <img src="src/assets/Logo.png" alt="Nexa Logo" />
3
3
  <h1 align="center">@bereasoftware/nexa</h1>
4
4
  <p align="center">
5
- Un cliente HTTP moderno y type-safe que combina el poder de <code>fetch</code> con la comodidad de <code>axios</code> construido sobre principios SOLID.
5
+ Un cliente HTTP moderno y type-safe que combina el poder de <code>fetch</code> con la comodidad de <code>axios</code>, y añade observabilidad integrada para desarrollo con <code>Dev Overlay</code>.
6
6
  </p>
7
7
  </p>
8
8
 
9
9
  <p align="center">
10
- <a href="#tests"><img src="https://img.shields.io/badge/Tests-213_pasando-brightgreen?style=for-the-badge" alt="Tests" /></a>
11
- <a href="#test-coverage"><img src="https://img.shields.io/badge/Coverage-Ver_reporte-orange?style=for-the-badge" alt="Coverage" /></a>
10
+ <a href="#tests"><img src="https://img.shields.io/badge/Tests-219_pasando-brightgreen?style=for-the-badge" alt="Tests" /></a>
11
+ <a href="#test-coverage"><img src="https://img.shields.io/badge/Coverage-Ver_reporte-orange?style=for-the-badge" alt="Coverage" /></a>
12
12
  <a href="https://www.npmjs.com/package/@bereasoftware/nexa"><img src="https://img.shields.io/npm/v/@bereasoftware/nexa?style=for-the-badge" alt="NPM Version" /></a>
13
13
  <a href="https://bundlephobia.com/package/@bereasoftware/nexa"><img src="https://img.shields.io/bundlephobia/minzip/@bereasoftware/nexa?label=Bundle&style=for-the-badge" alt="Bundle Size" /></a>
14
14
  <a href="https://www.npmjs.com/package/@bereasoftware/nexa"><img src="https://img.shields.io/npm/dm/@bereasoftware/nexa?style=for-the-badge" alt="NPM Downloads" /></a>
@@ -37,6 +37,20 @@
37
37
 
38
38
  ---
39
39
 
40
+ ## Posicionamiento
41
+
42
+ Nexa no busca ser solo otro wrapper de `fetch`.
43
+
44
+ La librería está diseñada para combinar tres cosas en un solo paquete:
45
+
46
+ - una API HTTP type-safe y sin dependencias runtime
47
+ - extensibilidad real con retries, caché, middlewares y plugins
48
+ - observabilidad integrada para desarrollo con `Dev Overlay`
49
+
50
+ Eso la hace útil no solo como cliente HTTP, sino también como base para SDKs, tooling interno y flujos donde la experiencia de depuración importa.
51
+
52
+ ---
53
+
40
54
  ## ¿Por qué Nexa?
41
55
 
42
56
  | Característica | `fetch` | `axios` | **Nexa** |
@@ -60,11 +74,11 @@
60
74
  | Validadores y transformadores | ❌ | ❌ | ✅ |
61
75
  | Tracking de duración de respuesta | ❌ | ❌ | ✅ |
62
76
  | Detección inteligente de tipo de respuesta | ❌ | ✅ | ✅ |
63
- | WebSocket/SSE con reconexión automática | ❌ | ❌ | ✅ |
64
- | Rate limiting integrado | ❌ | ❌ | ✅ |
65
- | Circuit breaker para fallos en cascada | ❌ | ❌ | ✅ |
66
- | Tree-shakeable | ✅ | ❌ | ✅ |
67
- | Dev Overlay (herramientas de desarrollo) | ❌ | ❌ | ✅ |
77
+ | WebSocket/SSE con reconexión automática | ❌ | ❌ | ✅ |
78
+ | Rate limiting integrado | ❌ | ❌ | ✅ |
79
+ | Circuit breaker para fallos en cascada | ❌ | ❌ | ✅ |
80
+ | Tree-shakeable | ✅ | ❌ | ✅ |
81
+ | Dev Overlay (herramientas de desarrollo) | ❌ | ❌ | ✅ |
68
82
 
69
83
  ---
70
84
 
@@ -231,12 +245,12 @@ const client = createHttpClient({
231
245
  | `maxConcurrent` | `number` | `0` (ilimitado) | Máximo de peticiones concurrentes |
232
246
  | `defaultResponseType` | `ResponseType` | `'auto'` | Estrategia de parseo de respuesta por defecto |
233
247
  | `defaultHooks` | `RequestHooks` | `{}` | Hooks de ciclo de vida por defecto para todas las peticiones |
234
- | `debug` | `boolean \| 'verbose'` | `undefined` | Habilita logging de debug para requests/responses. `true` para logs básicos, `'verbose'` para logs detallados. |
235
- | `logger` | `(message: string, data?: unknown) => void` | `undefined` | Función de logging personalizada. Si se proporciona, reemplaza el console.log por defecto con logging personalizado. |
236
-
237
- **Nota:** Las opciones avanzadas `transformRequest`, `credentials`, `withCredentials`, `debug`, `logger`, `transport`, `nodeOptions` y `autoFormData` ya están tipadas, pero no todas están completamente integradas en el pipeline principal de `HttpClient` en esta versión. Úsalas con validación manual hasta que se cierre esa integración.
238
-
239
- ---
248
+ | `debug` | `boolean \| 'verbose'` | `undefined` | Habilita logging de debug para requests/responses. `true` para logs básicos, `'verbose'` para logs detallados. |
249
+ | `logger` | `(message: string, data?: unknown) => void` | `undefined` | Función de logging personalizada. Si se proporciona, reemplaza el console.log por defecto con logging personalizado. |
250
+
251
+ **Nota:** Las opciones avanzadas `transformRequest`, `credentials`, `withCredentials`, `debug`, `logger`, `transport`, `nodeOptions` y `autoFormData` ya están tipadas, pero no todas están completamente integradas en el pipeline principal de `HttpClient` en esta versión. Úsalas con validación manual hasta que se cierre esa integración.
252
+
253
+ ---
240
254
 
241
255
  ## Métodos HTTP
242
256
 
@@ -370,7 +384,7 @@ await client.post('/api', data, { withCredentials: true });
370
384
 
371
385
  // Configuración global
372
386
  const client = createHttpClient({
373
- credentials: 'same-origin',
387
+ credentials: 'same-origin',
374
388
  // o
375
389
  withCredentials: true, // Equivalente a credentials: 'include'
376
390
  });
@@ -604,7 +618,7 @@ await client.post('/api', data, {
604
618
 
605
619
  El logger recibe dos argumentos: el mensaje de log (con prefijo `[Nexa HTTP]`) y un objeto de datos opcional.
606
620
 
607
- ---
621
+ ---
608
622
 
609
623
  ## Estrategias de Reintentos
610
624
 
@@ -1291,11 +1305,11 @@ manager.register(rateLimitPlugin);
1291
1305
 
1292
1306
  ---
1293
1307
 
1294
- ## Dev Overlay
1295
-
1296
- Herramienta visual de desarrollo integrada para depurar y monitorear requests HTTP en tiempo real.
1297
-
1298
- > Estado de API: disponible públicamente y pensada para flujos de desarrollo en navegador. No está orientada a entornos SSR o Node sin DOM.
1308
+ ## Dev Overlay
1309
+
1310
+ Herramienta visual de desarrollo integrada para depurar y monitorear requests HTTP en tiempo real.
1311
+
1312
+ > Estado de API: disponible públicamente y pensada para flujos de desarrollo en navegador. No está orientada a entornos SSR o Node sin DOM.
1299
1313
 
1300
1314
  ```typescript
1301
1315
  import { createHttpClient, createDevOverlay } from "@bereasoftware/nexa";
@@ -1319,98 +1333,115 @@ const result = await client.get("/users");
1319
1333
 
1320
1334
  ### Características
1321
1335
 
1322
- - **Toggle con teclado** — Presiona `Ctrl+Shift+N` o `Cmd+Shift+N` para mostrar/ocultar
1323
- - **Lista de requests** — Muestra método, status, URL, duración y badges (cache, retries)
1324
- - **Métricas en tiempo real** — Total requests, promedio, throughput, éxitos y fallos
1325
- - **Búsqueda y filtro** — Filtra por URL, método o status (`Ctrl+F`)
1326
- - **Detalle de request** — Click en cualquier request para ver headers, body y timing
1327
- - **Retry rápido** — Reejecuta la URL seleccionada con `fetch` para una verificación rápida
1328
- - **Keyboard shortcuts** — `Ctrl+Shift+N` / `Cmd+Shift+N` (toggle), `Escape` (cerrar), `Ctrl+F` / `Cmd+F` (buscar)
1336
+ - **Toggle con teclado** — Presiona `Ctrl+Shift+N` o `Cmd+Shift+N` para mostrar/ocultar
1337
+ - **Lista de requests** — Muestra método, status, URL, duración y badges (cache, retries)
1338
+ - **Métricas en tiempo real** — Total requests, promedio, throughput, éxitos y fallos
1339
+ - **Búsqueda y filtro** — Filtra por URL, método o status (`Ctrl+F`)
1340
+ - **Detalle de request** — Click en cualquier request para ver headers, body y timing
1341
+
1342
+ ### Persistencia de configuración
1343
+
1344
+ El `Dev Overlay` persiste la configuración del usuario (posición, tema, tamaño del botón flotante, etc.) en `localStorage` bajo la clave `nexa.devOverlay.config`.
1345
+
1346
+
1347
+ Al llamar a `createDevOverlay()` la configuración que se aplica sigue el orden de preferencia (los valores persistidos en `localStorage` tienen prioridad por diseño):
1348
+
1349
+ - Valores por defecto ← (`defaultDevOverlayConfig`)
1350
+ - Opciones pasadas a `createDevOverlay()` (argumento `config`)
1351
+ - Valores persistidos en `localStorage` (sobrescriben los anteriores)
1352
+
1353
+ En entornos sin DOM (por ejemplo, durante tests en Node) el componente visual no se monta, pero el `tracker` sigue inicializándose y respeta la carga y persistencia de la configuración.
1354
+ - **Retry rápido** — Reejecuta la URL seleccionada con `fetch` para una verificación rápida
1355
+ - **Keyboard shortcuts** — `Ctrl+Shift+N` / `Cmd+Shift+N` (toggle), `Escape` (cerrar), `Ctrl+F` / `Cmd+F` (buscar)
1329
1356
 
1330
1357
  ### API
1331
1358
 
1332
1359
  ```typescript
1333
- createDevOverlay(config?: DevOverlayConfig): { tracker: RequestTracker; ui: DevOverlayUI }
1334
- ```
1335
-
1336
- **Opciones de configuración:**
1337
-
1338
- | Opción | Tipo | Por defecto | Descripción |
1339
- |--------|------|-------------|-------------|
1340
- | `enabled` | `boolean` | `true` | Flag de configuración almacenado por el tracker para habilitar o deshabilitar el overlay desde tu flujo |
1341
- | `position` | `'top-right' \| 'top-left' \| 'bottom-right' \| 'bottom-left'` | `'bottom-right'` | Posición del overlay |
1342
- | `theme` | `'dark' \| 'light'` | `'dark'` | Tema visual tipado; la UI actual está optimizada para el tema oscuro |
1343
- | `maxHistory` | `number` | `500` |Máximo de requests en historial |
1344
- | `keyboardShortcut` | `string` | `'ctrl+shift+n'` | Atajo de teclado |
1345
-
1346
- **Notas de comportamiento:**
1347
-
1348
- - `createDevOverlay()` es singleton. Si lo llamas varias veces, reutiliza la misma instancia.
1349
- - El overlay solo monta UI cuando hay DOM disponible. En SSR o Node puedes importar el módulo sin romper el proceso, pero no se renderiza panel.
1350
- - `theme` está tipado como `'dark' | 'light'`, pero la UI actual está diseñada principalmente para tema oscuro.
1351
- - El botón de retry del panel usa `fetch()` directo para revalidación rápida; no reaplica automáticamente interceptores ni configuración avanzada del `HttpClient`.
1352
- - `destroyDevOverlay()` limpia la instancia singleton, desmonta el panel y remueve listeners globales registrados por el overlay.
1353
-
1354
- **Métodos del UI:**
1355
-
1356
- ```typescript
1357
- ui.show() // Mostrar overlay
1358
- ui.hide() // Ocultar overlay
1359
- ui.toggle() // Alternar visibilidad
1360
- ui.destroy() // Desmontar el panel del DOM
1361
-
1362
- tracker.clear() // Limpiar historial
1363
- tracker.getHistory() // Obtener todos los requests
1364
- tracker.getMetrics() // Obtener métricas
1365
- tracker.getConfig() // Obtener configuración resuelta
1366
- tracker.onChange((request) => {}) // Escuchar nuevos requests
1367
- ```
1368
-
1369
- **Métodos del módulo:**
1370
-
1371
- ```typescript
1372
- getDevOverlay() // Obtener { tracker, ui } actuales o null si no existen
1373
- destroyDevOverlay() // Destruir la instancia singleton actual
1374
- ```
1375
-
1376
- **Cuándo usar cada export:**
1377
-
1378
- - `createDevOverlay()` crea o reutiliza el overlay y devuelve el `tracker` que debes pasar a `createHttpClient({ devTracker })`.
1379
- - `getDevOverlay()` te permite consultar la instancia actual sin crear una nueva.
1380
- - `destroyDevOverlay()` sirve para cerrar completamente la herramienta en hot reloads, tests o limpieza manual.
1381
- - `RequestTracker` puede usarse por separado si quieres recolectar historial y métricas sin montar la UI.
1382
-
1383
- **Estructuras expuestas:**
1384
-
1385
- ```typescript
1386
- type TrackedRequest = {
1387
- id: string;
1388
- method: string;
1389
- url: string;
1390
- status?: number;
1391
- duration: number;
1392
- timestamp: number;
1393
- cached: boolean;
1394
- ok: boolean;
1395
- code?: string;
1396
- headers: Record<string, string>;
1397
- body?: unknown;
1398
- responseHeaders?: Record<string, string>;
1399
- retryCount: number;
1400
- };
1401
-
1402
- type DevMetrics = {
1403
- totalRequests: number;
1404
- successfulRequests: number;
1405
- failedRequests: number;
1406
- cachedRequests: number;
1407
- avgDuration: number;
1408
- maxDuration: number;
1409
- minDuration: number;
1410
- requestsPerSecond: number;
1411
- slowestRequests: TrackedRequest[];
1412
- };
1413
- ```
1360
+ createDevOverlay(config?: DevOverlayConfig): { tracker: RequestTracker; ui: DevOverlayUI; config: Required<DevOverlayConfig> }
1361
+ ```
1362
+
1363
+ **Opciones de configuración:**
1364
+
1365
+ | Opción | Tipo | Por defecto | Descripción |
1366
+ |--------|------|-------------|-------------|
1367
+ | `enabled` | `boolean` | `true` | Flag de configuración almacenado por el tracker para habilitar o deshabilitar el overlay desde tu flujo |
1368
+ | `position` | `'top-right' \| 'top-left' \| 'bottom-right' \| 'bottom-left'` | `'bottom-right'` | Posición del overlay |
1369
+ | `theme` | `'dark' \| 'light'` | `'dark'` | Tema visual tipado; la UI actual está optimizada para el tema oscuro |
1370
+ | `maxHistory` | `number` | `500` |Máximo de requests en historial |
1371
+ | `keyboardShortcut` | `string` | `'ctrl+shift+n'` | Atajo de teclado |
1372
+ | `devOnly` | `boolean` | `true` | Cuando es true, la UI solo se monta en entornos de desarrollo (NODE_ENV=development o localhost) |
1373
+ | `floatingButtonSize` | `number` | `64` | Tamaño (ancho & alto) del botón flotante en píxeles |
1374
+ | `floatingButtonOffset` | `number` | `24` | Offset desde los bordes de la ventana en píxeles |
1375
+ | `floatingButtonTheme` | `'inherit' \| 'dark' \| 'light'` | `'inherit'` | Tema del botón flotante; `'inherit'` usa el `theme` del overlay |
1376
+
1377
+ **Notas de comportamiento:**
1378
+
1379
+ - `createDevOverlay()` es singleton. Si lo llamas varias veces, reutiliza la misma instancia.
1380
+ - El overlay solo monta UI cuando hay DOM disponible. En SSR o Node puedes importar el módulo sin romper el proceso, pero no se renderiza panel.
1381
+ - `theme` está tipado como `'dark' | 'light'`, pero la UI actual está diseñada principalmente para tema oscuro.
1382
+ - El botón de retry del panel usa `fetch()` directo para revalidación rápida; no reaplica automáticamente interceptores ni configuración avanzada del `HttpClient`.
1383
+ - `destroyDevOverlay()` limpia la instancia singleton, desmonta el panel y remueve listeners globales registrados por el overlay.
1384
+
1385
+ **Métodos del UI:**
1386
+
1387
+ ```typescript
1388
+ ui.show() // Mostrar overlay
1389
+ ui.hide() // Ocultar overlay
1390
+ ui.toggle() // Alternar visibilidad
1391
+ ui.destroy() // Desmontar el panel del DOM
1392
+
1393
+ tracker.clear() // Limpiar historial
1394
+ tracker.getHistory() // Obtener todos los requests
1395
+ tracker.getMetrics() // Obtener métricas
1396
+ tracker.getConfig() // Obtener configuración resuelta
1397
+ tracker.onChange((request) => {}) // Escuchar nuevos requests
1398
+ ```
1399
+
1400
+ **Métodos del módulo:**
1401
+
1402
+ ```typescript
1403
+ getDevOverlay() // Obtener { tracker, ui } actuales o null si no existen
1404
+ destroyDevOverlay() // Destruir la instancia singleton actual
1405
+ ```
1406
+
1407
+ **Cuándo usar cada export:**
1408
+
1409
+ - `createDevOverlay()` crea o reutiliza el overlay y devuelve el `tracker` que debes pasar a `createHttpClient({ devTracker })`.
1410
+ - `getDevOverlay()` te permite consultar la instancia actual sin crear una nueva.
1411
+ - `destroyDevOverlay()` sirve para cerrar completamente la herramienta en hot reloads, tests o limpieza manual.
1412
+ - `RequestTracker` puede usarse por separado si quieres recolectar historial y métricas sin montar la UI.
1413
+
1414
+ **Estructuras expuestas:**
1415
+
1416
+ ```typescript
1417
+ type TrackedRequest = {
1418
+ id: string;
1419
+ method: string;
1420
+ url: string;
1421
+ status?: number;
1422
+ duration: number;
1423
+ timestamp: number;
1424
+ cached: boolean;
1425
+ ok: boolean;
1426
+ code?: string;
1427
+ headers: Record<string, string>;
1428
+ body?: unknown;
1429
+ responseHeaders?: Record<string, string>;
1430
+ retryCount: number;
1431
+ };
1432
+
1433
+ type DevMetrics = {
1434
+ totalRequests: number;
1435
+ successfulRequests: number;
1436
+ failedRequests: number;
1437
+ cachedRequests: number;
1438
+ avgDuration: number;
1439
+ maxDuration: number;
1440
+ minDuration: number;
1441
+ requestsPerSecond: number;
1442
+ slowestRequests: TrackedRequest[];
1443
+ };
1444
+ ```
1414
1445
 
1415
1446
  ---
1416
1447
 
@@ -1564,7 +1595,7 @@ deferred.reject(new Error("falló"));
1564
1595
 
1565
1596
  ### Contexto de Error Enriquecido
1566
1597
 
1567
- `HttpErrorDetails` incluye campos opcionales para `request`, `response` y `config`, pero en esta versión no todos los caminos de error los rellenan de forma consistente. Úsalos como metadatos opcionales, no como garantía fuerte.
1598
+ `HttpErrorDetails` incluye campos opcionales para `request`, `response` y `config`, pero en esta versión no todos los caminos de error los rellenan de forma consistente. Úsalos como metadatos opcionales, no como garantía fuerte.
1568
1599
 
1569
1600
  ```typescript
1570
1601
  const result = await client.get('/api');
@@ -1576,7 +1607,7 @@ if (!result.ok) {
1576
1607
  }
1577
1608
  ```
1578
1609
 
1579
- Si necesitas ese contexto en todos los errores, conviene complementarlo temporalmente con hooks o interceptores propios.
1610
+ Si necesitas ese contexto en todos los errores, conviene complementarlo temporalmente con hooks o interceptores propios.
1580
1611
 
1581
1612
  ### Clase HttpError
1582
1613