@jmlq/logger-plugin-fs 0.1.0-alpha.5 → 0.1.0-alpha.7
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.md +167 -153
- package/architecture.md +426 -0
- package/dist/application/dto/index.d.ts +2 -0
- package/dist/application/dto/index.js +2 -0
- package/dist/application/dto/rotation-check.dto.d.ts +5 -0
- package/dist/application/dto/save-log.dto.d.ts +3 -3
- package/dist/application/dto/write-operation.dto.d.ts +5 -0
- package/dist/application/factory/create-fs-datasource.factory.d.ts +3 -0
- package/dist/application/factory/create-fs-datasource.factory.js +26 -0
- package/dist/application/factory/index.d.ts +1 -0
- package/dist/{presentation → application}/factory/index.js +1 -1
- package/dist/application/services/fs-datasource.service.d.ts +7 -5
- package/dist/application/services/fs-datasource.service.js +6 -9
- package/dist/application/use-cases/append-log.use-case.d.ts +12 -0
- package/dist/application/use-cases/append-log.use-case.js +26 -0
- package/dist/application/use-cases/ensure-directory.use-case.d.ts +11 -0
- package/dist/application/use-cases/ensure-directory.use-case.js +27 -0
- package/dist/application/use-cases/index.d.ts +4 -3
- package/dist/application/use-cases/index.js +4 -3
- package/dist/application/use-cases/persist-log.use-case.d.ts +19 -0
- package/dist/application/use-cases/persist-log.use-case.js +47 -0
- package/dist/application/use-cases/rotate-if-needed.use-case.d.ts +17 -0
- package/dist/application/use-cases/rotate-if-needed.use-case.js +28 -0
- package/dist/domain/ports/clock.port.d.ts +8 -0
- package/dist/domain/ports/file-path-adapter.port.d.ts +33 -0
- package/dist/domain/ports/fs-provider.port.d.ts +61 -0
- package/dist/domain/ports/fs-provider.port.js +2 -0
- package/dist/domain/ports/index.d.ts +4 -0
- package/dist/domain/{contracts → ports}/index.js +3 -3
- package/dist/domain/ports/stream-writer.port.d.ts +42 -0
- package/dist/domain/ports/stream-writer.port.js +2 -0
- package/dist/domain/value-objects/file-path.vo.d.ts +27 -0
- package/dist/domain/value-objects/file-path.vo.js +59 -0
- package/dist/domain/value-objects/file-size.vo.d.ts +14 -0
- package/dist/domain/value-objects/file-size.vo.js +57 -0
- package/dist/domain/value-objects/index.d.ts +2 -2
- package/dist/domain/value-objects/index.js +2 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +14 -5
- package/dist/infrastructure/adapters/file-rotator.adapter.d.ts +20 -0
- package/dist/infrastructure/adapters/file-rotator.adapter.js +105 -0
- package/dist/infrastructure/adapters/fs-provider.adapter.d.ts +17 -0
- package/dist/infrastructure/{fs/fs-provider.js → adapters/fs-provider.adapter.js} +41 -19
- package/dist/infrastructure/adapters/fs-writer.adapter.d.ts +13 -0
- package/dist/infrastructure/adapters/fs-writer.adapter.js +71 -0
- package/dist/infrastructure/{fs → adapters}/index.d.ts +2 -2
- package/dist/infrastructure/{fs → adapters}/index.js +2 -2
- package/dist/infrastructure/adapters/node-clock.adapter.d.ts +4 -0
- package/dist/infrastructure/{fs → adapters}/node-clock.adapter.js +0 -1
- package/dist/infrastructure/adapters/node-file-path.adapter.d.ts +16 -0
- package/dist/infrastructure/adapters/node-file-path.adapter.js +117 -0
- package/dist/infrastructure/filesystem/index.d.ts +4 -0
- package/dist/infrastructure/filesystem/index.js +20 -0
- package/dist/infrastructure/filesystem/polices/index.d.ts +1 -0
- package/dist/infrastructure/filesystem/polices/index.js +5 -0
- package/dist/infrastructure/filesystem/polices/rotation-policy.d.ts +29 -0
- package/dist/infrastructure/filesystem/polices/rotation-policy.js +55 -0
- package/dist/infrastructure/filesystem/ports/file-rotator.port.d.ts +32 -0
- package/dist/infrastructure/filesystem/ports/file-rotator.port.js +2 -0
- package/dist/infrastructure/filesystem/ports/index.d.ts +1 -0
- package/dist/infrastructure/{datasources → filesystem/ports}/index.js +1 -1
- package/dist/infrastructure/filesystem/types/filesystem-datasource-options.type.d.ts +49 -0
- package/dist/infrastructure/filesystem/types/filesystem-datasource-options.type.js +2 -0
- package/dist/infrastructure/filesystem/types/filesystem-rotation.type.d.ts +19 -0
- package/dist/infrastructure/filesystem/types/filesystem-rotation.type.js +2 -0
- package/dist/infrastructure/filesystem/types/filesystem-serializer.type.d.ts +10 -0
- package/dist/infrastructure/filesystem/types/filesystem-serializer.type.js +2 -0
- package/dist/infrastructure/filesystem/types/index.d.ts +3 -0
- package/dist/infrastructure/filesystem/types/index.js +19 -0
- package/dist/infrastructure/filesystem/value-objects/file-name-pattern.vo.d.ts +22 -0
- package/dist/infrastructure/filesystem/value-objects/file-name-pattern.vo.js +37 -0
- package/dist/infrastructure/filesystem/value-objects/index.d.ts +1 -0
- package/dist/{domain/types → infrastructure/filesystem/value-objects}/index.js +1 -1
- package/dist/shared/errors/file-operation.error.d.ts +12 -0
- package/dist/shared/errors/file-operation.error.js +32 -0
- package/dist/shared/errors/fs-plugin.error.d.ts +4 -0
- package/dist/shared/errors/fs-plugin.error.js +11 -0
- package/dist/shared/errors/index.d.ts +3 -0
- package/dist/shared/errors/index.js +19 -0
- package/dist/shared/errors/rotation.error.d.ts +10 -0
- package/dist/shared/errors/rotation.error.js +25 -0
- package/install.md +520 -0
- package/package.json +39 -21
- package/dist/application/use-cases/append-log.usecase.d.ts +0 -7
- package/dist/application/use-cases/append-log.usecase.js +0 -19
- package/dist/application/use-cases/persist-log.usecase.d.ts +0 -23
- package/dist/application/use-cases/persist-log.usecase.js +0 -74
- package/dist/application/use-cases/rotate-if-needed.usecase.d.ts +0 -10
- package/dist/application/use-cases/rotate-if-needed.usecase.js +0 -39
- package/dist/domain/contracts/clock.contract.d.ts +0 -3
- package/dist/domain/contracts/file-rotator.contract.d.ts +0 -7
- package/dist/domain/contracts/index.d.ts +0 -4
- package/dist/domain/contracts/serializer.contract.d.ts +0 -3
- package/dist/domain/contracts/stream-writer.port.d.ts +0 -6
- package/dist/domain/types/index.d.ts +0 -1
- package/dist/domain/types/options.type.d.ts +0 -11
- package/dist/domain/types/options.type.js +0 -5
- package/dist/domain/value-objects/file-name-pattern.vo.d.ts +0 -4
- package/dist/domain/value-objects/file-name-pattern.vo.js +0 -14
- package/dist/domain/value-objects/rotation-policy.vo.d.ts +0 -7
- package/dist/domain/value-objects/rotation-policy.vo.js +0 -20
- package/dist/infrastructure/datasources/fs.datasource.d.ts +0 -17
- package/dist/infrastructure/datasources/fs.datasource.js +0 -84
- package/dist/infrastructure/datasources/index.d.ts +0 -1
- package/dist/infrastructure/fs/file-rotator.adapter.d.ts +0 -22
- package/dist/infrastructure/fs/file-rotator.adapter.js +0 -51
- package/dist/infrastructure/fs/fs-provider.d.ts +0 -15
- package/dist/infrastructure/fs/fs-writer.adapter.d.ts +0 -10
- package/dist/infrastructure/fs/fs-writer.adapter.js +0 -26
- package/dist/infrastructure/fs/node-clock.adapter.d.ts +0 -4
- package/dist/infrastructure/fs/path-utils.d.ts +0 -6
- package/dist/infrastructure/fs/path-utils.js +0 -26
- package/dist/presentation/factory/create-fs-datasource.d.ts +0 -15
- package/dist/presentation/factory/create-fs-datasource.js +0 -39
- package/dist/presentation/factory/index.d.ts +0 -1
- /package/dist/{domain/contracts/clock.contract.js → application/dto/rotation-check.dto.js} +0 -0
- /package/dist/{domain/contracts/file-rotator.contract.js → application/dto/write-operation.dto.js} +0 -0
- /package/dist/domain/{contracts/serializer.contract.js → ports/clock.port.js} +0 -0
- /package/dist/domain/{contracts/stream-writer.port.js → ports/file-path-adapter.port.js} +0 -0
package/README.md
CHANGED
|
@@ -1,208 +1,222 @@
|
|
|
1
1
|
# @jmlq/logger-plugin-fs
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Escribe cada evento de log como **línea** (JSONL por defecto) y soporta `rotación por día` o por `tamaño`, manejo de `backpressure/drain`, `flush()` y `dispose()`.
|
|
5
|
-
|
|
6
|
-
---
|
|
3
|
+
Plugin de **sistema de archivos** para [`@jmlq/logger`](https://www.npmjs.com/package/@jmlq/logger). Permite persistir logs en archivos con soporte para rotación automática, manejo de backpressure y configuración flexible de formato y estructura de archivos.
|
|
7
4
|
|
|
8
5
|
## 📦 Instalación
|
|
9
6
|
|
|
10
7
|
```bash
|
|
11
|
-
|
|
12
|
-
npm i @jmlq/logger @jmlq/logger-plugin-fs
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Este plugin **depende** de [`@jmlq/logger`](https://www.npmjs.com/package/@jmlq/logger). Asegúrate de instalar ambos paquetes.
|
|
17
|
-
|
|
18
|
-
## 🧱 Estructura del paquete
|
|
19
|
-
|
|
20
|
-
### 📝 Resumen rápido
|
|
21
|
-
|
|
22
|
-
> - **`src/domain/`** — Reglas del negocio del plugin (sin dependencias de Node).
|
|
23
|
-
> > - **`contracts/`**
|
|
24
|
-
> > > - `clock.contract.ts` — Puerto que abstrae el tiempo actual (`now()`), permite testear rotación sin depender de `Date.now()`.
|
|
25
|
-
> > > - `file-rotator.port.ts` — Puerto para rotación: calcula path esperado, tamaño, índice, etc.
|
|
26
|
-
> > > - `stream-writer.port.ts` — Puerto para escritura secuencial: `write`, `once("drain")`, `end`.
|
|
27
|
-
> > - **`value-objects/`**
|
|
28
|
-
> > > - `file-name-pattern.vo.ts` — VO que encapsula el patrón de nombres (`{yyyy}{MM}{dd}`) con validación.
|
|
29
|
-
> > > - `rotation-policy.vo.ts` — VO que define estrategia de rotación (`none | day | size`) con invariantes (`maxSizeMB > 0`).
|
|
30
|
-
> > - **`types/`**
|
|
31
|
-
> > > - `options.type.ts` — Define `FsDatasourceOptions` y `IFsSerializer` (contrato de serialización de líneas).
|
|
32
|
-
|
|
33
|
-
> - **`src/application/`** — Casos de uso (orquestan, no dependen de Node).
|
|
34
|
-
> > - **`dto/`**
|
|
35
|
-
> > > - `save-log.dto.ts` — DTO de entrada: `{ log: ILog }`.
|
|
36
|
-
> > - **`use-cases/`**
|
|
37
|
-
> > > - `rotate-if-needed.usecase.ts` — Decide si se rota: compara fecha/tamaño contra `RotationPolicy`.
|
|
38
|
-
> > > - `append-log.usecase.ts` — Serializa y escribe línea; maneja backpressure (`write=false` → espera `drain`).
|
|
39
|
-
> > > - `persist-log.usecase.ts` — Orquesta: asegura writer, rota si corresponde, escribe, dispara hooks.
|
|
40
|
-
> > - **`services/`**
|
|
41
|
-
> > > - `fs-datasource.service.ts` — Implementa `ILogDatasource` del core usando los UC anteriores.
|
|
42
|
-
|
|
43
|
-
> - **`src/infrastructure/`** — Adaptadores técnicos (Node.js).
|
|
44
|
-
> > - **`fs/`**
|
|
45
|
-
> > > - `fs-provider.ts` — Wrapper de `fs`/`fs.promises` (mockeable en tests).
|
|
46
|
-
> > > - `path-utils.ts` — Utilidades para `join`, `splitBaseExt`, `formatPattern` (UTC).
|
|
47
|
-
> > > - `file-rotator.adapter.ts` — Implementa `IFileRotatorPort` usando `fs-provider` y `path-utils`.
|
|
48
|
-
> > > - `fs-writer.adapter.ts` — Implementa `IStreamWriterPort` con `fs.createWriteStream`.
|
|
49
|
-
> > > - `node-clock.adapter.ts` — Implementa `IClock` devolviendo `new Date()`.
|
|
50
|
-
|
|
51
|
-
> - **`src/presentation/`** — API pública (cara del paquete).
|
|
52
|
-
> > - **`factory/`**
|
|
53
|
-
> > > - `create-fs-datasource.ts` — Ensambla VO + adaptadores + casos de uso y devuelve un `ILogDatasource`.
|
|
54
|
-
> > - `index.ts` — Barrel: reexporta la factory y VO/contratos públicos (`RotationPolicy`, `FileNamePattern`).
|
|
55
|
-
|
|
56
|
-
#### [VER MAS](./ARQUITECTURA.md)
|
|
57
|
-
|
|
58
|
-
## 🧩 Configuración
|
|
59
|
-
|
|
60
|
-
### 🔐 Variables de Entorno (.env)
|
|
61
|
-
|
|
62
|
-
```ini
|
|
63
|
-
# Ruta base (carpeta) para los archivos de log
|
|
64
|
-
LOGGER_FS_PATH=./logs
|
|
65
|
-
|
|
66
|
-
# Patrón (opcional). Si omites, usa "app-{yyyy}{MM}{dd}.log"
|
|
67
|
-
LOGGER_FS_PATTERN=app-{yyyy}{MM}{dd}.log
|
|
68
|
-
|
|
69
|
-
# Rotación: "day" | "size" | "none"
|
|
70
|
-
LOGGER_FS_ROTATION=day
|
|
71
|
-
LOGGER_FS_MAX_SIZE_MB=50
|
|
72
|
-
|
|
73
|
-
# Logger core
|
|
74
|
-
LOGGER_LEVEL=info # trace|debug|info|warn|error|fatal
|
|
75
|
-
|
|
8
|
+
npm install @jmlq/logger @jmlq/logger-plugin-fs
|
|
76
9
|
```
|
|
77
10
|
|
|
78
|
-
|
|
11
|
+
> **Nota:** Este plugin requiere [`@jmlq/logger`](https://www.npmjs.com/package/@jmlq/logger) como dependencia principal.
|
|
79
12
|
|
|
80
|
-
|
|
13
|
+
## 🚀 Uso rápido
|
|
81
14
|
|
|
82
|
-
```
|
|
83
|
-
import {
|
|
15
|
+
```typescript
|
|
16
|
+
import { LoggerFactory } from "@jmlq/logger";
|
|
84
17
|
import { createFsDatasource } from "@jmlq/logger-plugin-fs";
|
|
85
18
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
fileNamePattern: "app-{yyyy}{MM}{dd}.log",
|
|
90
|
-
// Alternativa por tamaño:
|
|
91
|
-
// rotation: { by: "size", maxSizeMB: 50 }
|
|
19
|
+
// Crear datasource de filesystem
|
|
20
|
+
const fsDatasource = createFsDatasource({
|
|
21
|
+
basePath: "./logs",
|
|
22
|
+
fileNamePattern: "app-{yyyy}{MM}{dd}.log",
|
|
92
23
|
rotation: { by: "day" },
|
|
93
|
-
// Serializador opcional (por defecto JSON.stringify)
|
|
94
|
-
// serializer: { serialize: (log) => formatMyLine(log) },
|
|
95
|
-
onRotate: (oldP, newP) => console.log("[fs] rotated:", oldP, "->", newP),
|
|
96
|
-
onError: (e) => console.error("[fs] error:", e),
|
|
97
24
|
});
|
|
98
25
|
|
|
99
|
-
|
|
26
|
+
// Crear logger usando la factory
|
|
27
|
+
const logger = LoggerFactory.create([fsDatasource]);
|
|
100
28
|
|
|
101
|
-
|
|
29
|
+
// Usar el logger
|
|
30
|
+
logger.info("Aplicación iniciada", { timestamp: new Date(), pid: process.pid });
|
|
31
|
+
logger.error("Error de conexión", { service: "database", retries: 3 });
|
|
102
32
|
|
|
103
33
|
// Cierre elegante
|
|
104
34
|
process.on("SIGTERM", async () => {
|
|
105
|
-
await logger.flush
|
|
106
|
-
await logger.dispose
|
|
35
|
+
await logger.flush();
|
|
36
|
+
await logger.dispose();
|
|
107
37
|
process.exit(0);
|
|
108
38
|
});
|
|
109
39
|
```
|
|
110
40
|
|
|
111
|
-
|
|
41
|
+
## ⚙️ Configuración del datasource
|
|
112
42
|
|
|
113
|
-
|
|
114
|
-
import { createLogger, LogLevel } from "@jmlq/logger";
|
|
115
|
-
import {
|
|
116
|
-
createFsDatasource,
|
|
117
|
-
RotationPolicy,
|
|
118
|
-
FileNamePattern,
|
|
119
|
-
} from "@jmlq/logger-plugin-fs";
|
|
43
|
+
El datasource de filesystem acepta las siguientes opciones de configuración:
|
|
120
44
|
|
|
121
|
-
|
|
122
|
-
const pt = new FileNamePattern("app-{yyyy}{MM}{dd}.log");
|
|
123
|
-
const rt = new RotationPolicy("size", 50 /* maxSizeMB */);
|
|
45
|
+
### Opciones principales
|
|
124
46
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
47
|
+
| Opción | Tipo | Descripción | Por defecto |
|
|
48
|
+
| ----------------- | ---------------- | ------------------------------------------------------ | --------------------------- |
|
|
49
|
+
| `basePath` | `string` | Directorio base donde se guardarán los archivos de log | `"./logs"` |
|
|
50
|
+
| `fileNamePattern` | `string` | Patrón para nombrar archivos con tokens de fecha | `"app-{yyyy}{MM}{dd}.log"` |
|
|
51
|
+
| `rotation` | `RotationConfig` | Configuración de política de rotación | `{ by: "day" }` |
|
|
52
|
+
| `mkdir` | `boolean` | Crear directorio base si no existe | `true` |
|
|
53
|
+
| `serializer` | `LogSerializer` | Serializador personalizado para el formato de líneas | Serializer JSON por defecto |
|
|
54
|
+
|
|
55
|
+
### Configuración de rotación
|
|
132
56
|
|
|
133
|
-
|
|
57
|
+
```typescript
|
|
58
|
+
interface RotationConfig {
|
|
59
|
+
by: "none" | "day" | "size";
|
|
60
|
+
maxSizeMB?: number; // Para rotación por tamaño
|
|
61
|
+
maxFiles?: number; // Límite de archivos rotados
|
|
62
|
+
}
|
|
134
63
|
```
|
|
135
64
|
|
|
136
|
-
|
|
65
|
+
### Patrones de nombre de archivo
|
|
137
66
|
|
|
138
|
-
|
|
139
|
-
> - `mkdir?: boolean` – crea la carpeta si no existe.
|
|
140
|
-
> - `fileNamePattern?: string` – tokens {yyyy}{MM}{dd} (formateados en UTC).
|
|
141
|
-
> > - Ejemplos: `"app-{yyyy}{MM}{dd}.log"`, `"service.log"`.
|
|
142
|
-
> - `rotation?: { by: "none" | "day" | "size"; maxSizeMB?: number; maxFiles?: number }`
|
|
143
|
-
> > - `day` → rota al cambiar la fecha (UTC).
|
|
144
|
-
> > - `size` → rota al alcanzar `maxSizeMB` (genera app.1.log, app.2.log, …).
|
|
145
|
-
> - `serializer?: { serialize(entry: unknown): string }` – una línea sin `\n`.
|
|
146
|
-
> - `onRotate?: (oldPath, newPath) => void | Promise<void>`
|
|
147
|
-
> - `onError?: (err) => void | Promise<void>`
|
|
67
|
+
Utiliza tokens que se reemplazan con valores de fecha (UTC):
|
|
148
68
|
|
|
149
|
-
|
|
69
|
+
- `{yyyy}` - Año completo (ej: 2024)
|
|
70
|
+
- `{MM}` - Mes con ceros (ej: 01, 12)
|
|
71
|
+
- `{dd}` - Día con ceros (ej: 01, 31)
|
|
150
72
|
|
|
151
|
-
|
|
73
|
+
**Ejemplos:**
|
|
152
74
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
75
|
+
- `"app-{yyyy}{MM}{dd}.log"` → `app-20241201.log`
|
|
76
|
+
- `"service-{yyyy}-{MM}-{dd}.log"` → `service-2024-12-01.log`
|
|
77
|
+
- `"application.log"` → `application.log` (sin rotación por fecha)
|
|
156
78
|
|
|
157
|
-
|
|
79
|
+
## 🔁 Políticas de rotación
|
|
158
80
|
|
|
159
|
-
###
|
|
81
|
+
### Rotación por fecha
|
|
160
82
|
|
|
161
|
-
|
|
83
|
+
Crea un archivo nuevo cada día basado en fecha UTC:
|
|
162
84
|
|
|
163
|
-
|
|
164
|
-
|
|
85
|
+
```typescript
|
|
86
|
+
import { createFsDatasource } from "@jmlq/logger-plugin-fs";
|
|
165
87
|
|
|
166
|
-
|
|
88
|
+
const datasource = createFsDatasource({
|
|
89
|
+
basePath: "./logs",
|
|
90
|
+
fileNamePattern: "app-{yyyy}{MM}{dd}.log",
|
|
91
|
+
rotation: { by: "day" },
|
|
92
|
+
onRotate: (oldPath, newPath) => {
|
|
93
|
+
console.log(
|
|
94
|
+
`Log rotado: ${oldPath.absolutePath} → ${newPath.absolutePath}`
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
```
|
|
167
99
|
|
|
168
|
-
|
|
100
|
+
### Rotación por tamaño
|
|
169
101
|
|
|
170
|
-
|
|
102
|
+
Rota cuando el archivo alcanza el tamaño máximo especificado:
|
|
171
103
|
|
|
172
|
-
|
|
104
|
+
```typescript
|
|
105
|
+
const datasource = createFsDatasource({
|
|
106
|
+
basePath: "./logs",
|
|
107
|
+
fileNamePattern: "app.log",
|
|
108
|
+
rotation: {
|
|
109
|
+
by: "size",
|
|
110
|
+
maxSizeMB: 50, // Rota al alcanzar 50MB
|
|
111
|
+
maxFiles: 10, // Mantiene máximo 10 archivos rotados
|
|
112
|
+
},
|
|
113
|
+
onRotate: (oldPath, newPath) => {
|
|
114
|
+
console.log(
|
|
115
|
+
`Archivo rotado por tamaño: ${oldPath.absolutePath} → ${newPath.absolutePath}`
|
|
116
|
+
);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
```
|
|
173
120
|
|
|
174
|
-
|
|
175
|
-
El plugin:
|
|
121
|
+
### Sin rotación
|
|
176
122
|
|
|
177
|
-
|
|
178
|
-
2. Llama `write(...)`.
|
|
179
|
-
3. Si devuelve `false`, **espera el evento** `drain` antes de continuar.
|
|
180
|
-
4. `flush()` espera a que se libere el buffer si `writableNeedDrain` es `true`.
|
|
181
|
-
5. `dispose()` cierra el stream actual drenando el buffer pendiente.
|
|
123
|
+
Mantiene un único archivo que crece indefinidamente:
|
|
182
124
|
|
|
183
|
-
|
|
125
|
+
```typescript
|
|
126
|
+
const datasource = createFsDatasource({
|
|
127
|
+
basePath: "./logs",
|
|
128
|
+
fileNamePattern: "application.log",
|
|
129
|
+
rotation: { by: "none" },
|
|
130
|
+
});
|
|
131
|
+
```
|
|
184
132
|
|
|
185
|
-
|
|
133
|
+
## 🧩 Ejemplo completo
|
|
186
134
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
> > - Reemplazar el util de formateo si deseas `{…}` en local time.
|
|
135
|
+
```typescript
|
|
136
|
+
import { createFsDatasource } from "@jmlq/logger-plugin-fs";
|
|
137
|
+
import { LogLevel } from "@jmlq/logger";
|
|
191
138
|
|
|
192
|
-
|
|
139
|
+
const datasource = createFsDatasource({
|
|
140
|
+
basePath: "./logs",
|
|
141
|
+
fileNamePattern: "app-{yyyy}-{MM}-{dd}.log",
|
|
142
|
+
rotation: { by: "day" },
|
|
143
|
+
mkdir: true,
|
|
144
|
+
serializer: {
|
|
145
|
+
serialize(log: any) {
|
|
146
|
+
return JSON.stringify(log, null, 2);
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
onRotate: (oldPath, newPath) => {
|
|
150
|
+
console.log(`Rotación: ${oldPath.absolutePath} → ${newPath.absolutePath}`);
|
|
151
|
+
},
|
|
152
|
+
onError: (err) => {
|
|
153
|
+
console.error("Error en datasource:", err.message);
|
|
154
|
+
},
|
|
155
|
+
});
|
|
193
156
|
|
|
194
|
-
|
|
157
|
+
// Guardar logs
|
|
158
|
+
await datasource.save({
|
|
159
|
+
level: LogLevel.INFO,
|
|
160
|
+
message: "Servidor iniciado correctamente",
|
|
161
|
+
timestamp: Date.now(),
|
|
162
|
+
});
|
|
195
163
|
|
|
196
|
-
|
|
197
|
-
|
|
164
|
+
await datasource.save({
|
|
165
|
+
level: LogLevel.DEBUG,
|
|
166
|
+
message: "Conectando a base de datos...",
|
|
167
|
+
timestamp: Date.now(),
|
|
168
|
+
});
|
|
198
169
|
|
|
199
|
-
|
|
200
|
-
|
|
170
|
+
// Cierre
|
|
171
|
+
await datasource.flush();
|
|
172
|
+
await datasource.dispose();
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 🧪 Testing
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { createFsDatasource } from "@jmlq/logger-plugin-fs";
|
|
179
|
+
import * as fs from "fs";
|
|
180
|
+
import * as path from "path";
|
|
181
|
+
|
|
182
|
+
describe("FileSystem Datasource", () => {
|
|
183
|
+
const testLogsPath = "./test-logs";
|
|
184
|
+
|
|
185
|
+
beforeEach(() => {
|
|
186
|
+
if (fs.existsSync(testLogsPath)) {
|
|
187
|
+
fs.rmSync(testLogsPath, { recursive: true });
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("debe crear archivo de log", async () => {
|
|
192
|
+
const datasource = createFsDatasource({
|
|
193
|
+
basePath: testLogsPath,
|
|
194
|
+
fileNamePattern: "test.log",
|
|
195
|
+
rotation: { by: "none" },
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
await datasource.save({
|
|
199
|
+
level: "info",
|
|
200
|
+
message: "Test message",
|
|
201
|
+
timestamp: new Date(),
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
await datasource.flush();
|
|
205
|
+
|
|
206
|
+
const logFile = path.join(testLogsPath, "test.log");
|
|
207
|
+
expect(fs.existsSync(logFile)).toBe(true);
|
|
208
|
+
|
|
209
|
+
const content = fs.readFileSync(logFile, "utf8");
|
|
210
|
+
expect(content).toContain("Test message");
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
```
|
|
201
214
|
|
|
202
|
-
|
|
203
|
-
No out-of-the-box. Puedes implementar un **FileNamePattern** por hora (ej. `app-{yyyy}{MM}{dd}-{HH}.log`) + un `RotateIfNeededUseCase` extendido.
|
|
215
|
+
## 📄 Más Información
|
|
204
216
|
|
|
205
|
-
|
|
217
|
+
- **[Arquitectura Detallada](./architecture.md)** - Documentación técnica completa
|
|
218
|
+
- **[Guía de Instalación](./install.md)** - Configuración paso a paso
|
|
219
|
+
- **[Ejemplos](./examples/)** - Códigos de ejemplo funcionales
|
|
206
220
|
|
|
207
221
|
## 📄 Licencia
|
|
208
222
|
|