@jmlq/logger-plugin-fs 0.1.0-alpha.1 → 0.1.0-alpha.11
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 +551 -0
- package/architecture.md +299 -0
- package/dist/application/dto/index.d.ts +1 -0
- package/dist/application/dto/index.js +17 -0
- package/dist/application/dto/rotate-if-needed.request.d.ts +10 -0
- package/dist/application/dto/rotate-if-needed.request.js +2 -0
- package/dist/application/factory/create-fs-datasource.factory.d.ts +16 -0
- package/dist/application/factory/create-fs-datasource.factory.js +51 -0
- package/dist/application/factory/index.d.ts +1 -0
- package/dist/application/factory/index.js +17 -0
- package/dist/application/types/filesystem-datasource-options.type.d.ts +45 -0
- package/dist/application/types/filesystem-datasource-options.type.js +2 -0
- package/dist/application/types/index.d.ts +1 -0
- package/dist/application/types/index.js +17 -0
- package/dist/application/use-cases/append-log.use-case.d.ts +30 -0
- package/dist/application/use-cases/append-log.use-case.js +39 -0
- package/dist/application/use-cases/ensure-directory.use-case.d.ts +58 -0
- package/dist/application/use-cases/ensure-directory.use-case.js +64 -0
- package/dist/application/use-cases/find-logs-use-case.d.ts +17 -0
- package/dist/application/use-cases/find-logs-use-case.js +64 -0
- package/dist/application/use-cases/index.d.ts +5 -0
- package/dist/application/use-cases/index.js +21 -0
- package/dist/application/use-cases/persist-log.use-case.d.ts +96 -0
- package/dist/application/use-cases/persist-log.use-case.js +105 -0
- package/dist/application/use-cases/rotate-if-needed.use-case.d.ts +55 -0
- package/dist/application/use-cases/rotate-if-needed.use-case.js +61 -0
- package/dist/domain/model/index.d.ts +1 -0
- package/dist/domain/model/index.js +17 -0
- package/dist/domain/model/log-entry.model.d.ts +8 -0
- package/dist/domain/model/log-entry.model.js +2 -0
- package/dist/domain/ports/file/file-path.port.d.ts +38 -0
- package/dist/domain/ports/file/file-path.port.js +2 -0
- package/dist/domain/ports/file/file-rotator.port.d.ts +42 -0
- package/dist/domain/ports/file/file-rotator.port.js +2 -0
- package/dist/domain/ports/file/index.d.ts +2 -0
- package/dist/domain/ports/file/index.js +18 -0
- package/dist/domain/ports/file/log-stream-writer.port.d.ts +70 -0
- package/dist/domain/ports/file/log-stream-writer.port.js +2 -0
- package/dist/domain/ports/filesystem-provider.port.d.ts +61 -0
- package/dist/domain/ports/filesystem-provider.port.js +2 -0
- package/dist/domain/ports/index.d.ts +5 -0
- package/dist/domain/ports/index.js +21 -0
- package/dist/domain/ports/logs/find/index.d.ts +2 -0
- package/dist/domain/ports/logs/find/index.js +18 -0
- package/dist/domain/ports/logs/find/log-file-line-reader.port.d.ts +3 -0
- package/dist/domain/ports/logs/find/log-file-line-reader.port.js +2 -0
- package/dist/domain/ports/logs/find/log-file-numerator.port.d.ts +3 -0
- package/dist/domain/ports/logs/find/log-file-numerator.port.js +2 -0
- package/dist/domain/ports/logs/index.d.ts +2 -0
- package/dist/domain/ports/logs/index.js +18 -0
- package/dist/domain/ports/logs/log-datasource.port.d.ts +10 -0
- package/dist/domain/ports/logs/log-datasource.port.js +2 -0
- package/dist/domain/ports/system-clock.port.d.ts +8 -0
- package/dist/domain/ports/system-clock.port.js +2 -0
- package/dist/domain/request/index.d.ts +2 -0
- package/dist/domain/request/index.js +18 -0
- package/dist/domain/request/log-filter.request.d.ts +9 -0
- package/dist/domain/request/log-filter.request.js +2 -0
- package/dist/domain/request/save-log.request.d.ts +7 -0
- package/dist/domain/request/save-log.request.js +2 -0
- package/dist/domain/response/index.d.ts +1 -0
- package/dist/domain/response/index.js +17 -0
- package/dist/domain/response/log.response.d.ts +8 -0
- package/dist/domain/response/log.response.js +2 -0
- package/dist/domain/types/fs-rotation-by.type.d.ts +8 -0
- package/dist/domain/types/fs-rotation-by.type.js +2 -0
- package/dist/domain/types/index.d.ts +1 -0
- package/dist/domain/types/index.js +17 -0
- package/dist/domain/value-objects/file-name-pattern.vo.d.ts +36 -0
- package/dist/domain/value-objects/file-name-pattern.vo.js +53 -0
- package/dist/domain/value-objects/file-path.vo.d.ts +91 -0
- package/dist/domain/value-objects/file-path.vo.js +100 -0
- package/dist/domain/value-objects/file-rotation-policy.vo.d.ts +51 -0
- package/dist/domain/value-objects/file-rotation-policy.vo.js +76 -0
- package/dist/domain/value-objects/file-size.vo.d.ts +75 -0
- package/dist/domain/value-objects/file-size.vo.js +114 -0
- package/dist/domain/value-objects/index.d.ts +5 -0
- package/dist/domain/value-objects/index.js +21 -0
- package/dist/domain/value-objects/log-level.vo.d.ts +8 -0
- package/dist/domain/value-objects/log-level.vo.js +13 -0
- package/dist/index.d.ts +4 -13
- package/dist/index.js +10 -38
- package/dist/infrastructure/adapters/file-rotator.adapter.d.ts +79 -0
- package/dist/infrastructure/adapters/file-rotator.adapter.js +171 -0
- package/dist/infrastructure/adapters/fileSystem-datasource.adapter.d.ts +26 -0
- package/dist/infrastructure/adapters/fileSystem-datasource.adapter.js +45 -0
- package/dist/infrastructure/adapters/filesystem-log-file-enumerator.adapter.d.ts +6 -0
- package/dist/infrastructure/adapters/filesystem-log-file-enumerator.adapter.js +54 -0
- package/dist/infrastructure/adapters/filesystem-log-file-line-reader.adapter.d.ts +4 -0
- package/dist/infrastructure/adapters/filesystem-log-file-line-reader.adapter.js +53 -0
- package/dist/infrastructure/adapters/filesystem-provider.adapter.d.ts +122 -0
- package/dist/infrastructure/adapters/filesystem-provider.adapter.js +182 -0
- package/dist/infrastructure/adapters/index.d.ts +8 -0
- package/dist/infrastructure/adapters/index.js +24 -0
- package/dist/infrastructure/adapters/log-stream-writer.adapter.d.ts +80 -0
- package/dist/infrastructure/adapters/log-stream-writer.adapter.js +163 -0
- package/dist/infrastructure/adapters/system-clock.adapter.d.ts +25 -0
- package/dist/infrastructure/adapters/system-clock.adapter.js +30 -0
- package/dist/infrastructure/adapters/system-file-path.adapter.d.ts +47 -0
- package/dist/infrastructure/adapters/system-file-path.adapter.js +141 -0
- package/dist/infrastructure/errors/file-operation.error.d.ts +28 -0
- package/dist/infrastructure/errors/file-operation.error.js +54 -0
- package/dist/infrastructure/errors/index.d.ts +1 -0
- package/dist/infrastructure/errors/index.js +17 -0
- package/dist/infrastructure/errors/types/file-operation-error-options.type.d.ts +8 -0
- package/dist/infrastructure/errors/types/file-operation-error-options.type.js +2 -0
- package/dist/infrastructure/errors/types/file-operation.type.d.ts +1 -0
- package/dist/infrastructure/errors/types/file-operation.type.js +2 -0
- package/dist/infrastructure/errors/types/fs-error-scope.type.d.ts +1 -0
- package/dist/infrastructure/errors/types/fs-error-scope.type.js +2 -0
- package/dist/infrastructure/errors/types/index.d.ts +3 -0
- package/dist/infrastructure/errors/types/index.js +19 -0
- package/dist/infrastructure/filesystem/index.d.ts +1 -0
- package/dist/infrastructure/filesystem/index.js +17 -0
- package/dist/infrastructure/filesystem/types/filesystem-rotation.type.d.ts +12 -0
- package/dist/infrastructure/filesystem/types/filesystem-rotation.type.js +2 -0
- package/dist/infrastructure/filesystem/types/index.d.ts +1 -0
- package/dist/infrastructure/filesystem/types/index.js +17 -0
- package/package.json +40 -13
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FilePath = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* FilePath (Value Object)
|
|
6
|
+
* -----------------------------------------------------------------------------
|
|
7
|
+
* Representa una ruta de archivo ya normalizada e inmutable.
|
|
8
|
+
*
|
|
9
|
+
* Características (DDD / Clean Architecture):
|
|
10
|
+
* - Es un Value Object (igualdad por valor).
|
|
11
|
+
* - No depende de Node.js ni del módulo `path`.
|
|
12
|
+
* - No realiza IO ni lógica de infraestructura.
|
|
13
|
+
* - Asume que la normalización fuerte ocurre en adapters.
|
|
14
|
+
*
|
|
15
|
+
* Su responsabilidad es:
|
|
16
|
+
* - Encapsular el concepto de "ruta de archivo válida"
|
|
17
|
+
* - Proteger invariantes básicas (no null, no vacío)
|
|
18
|
+
* - Exponer acceso seguro a sus partes
|
|
19
|
+
*/
|
|
20
|
+
class FilePath {
|
|
21
|
+
/**
|
|
22
|
+
* Crea un FilePath a partir de props ya normalizadas.
|
|
23
|
+
*
|
|
24
|
+
* Nota de diseño:
|
|
25
|
+
* - Este constructor NO calcula rutas ni usa `path`.
|
|
26
|
+
* - Solo valida invariantes mínimas del dominio.
|
|
27
|
+
*/
|
|
28
|
+
constructor(props) {
|
|
29
|
+
const { absolutePath, directory, filename, extension, basename, kind } = props;
|
|
30
|
+
// Validación de ruta absoluta
|
|
31
|
+
if (!absolutePath ||
|
|
32
|
+
typeof absolutePath !== "string" ||
|
|
33
|
+
!absolutePath.trim()) {
|
|
34
|
+
throw new Error("FilePath: absolutePath must be a non-empty string");
|
|
35
|
+
}
|
|
36
|
+
// Validación de directorio
|
|
37
|
+
if (!directory || typeof directory !== "string" || !directory.trim()) {
|
|
38
|
+
throw new Error("FilePath: directory must be a non-empty string");
|
|
39
|
+
}
|
|
40
|
+
if (kind !== "file" && kind !== "dir") {
|
|
41
|
+
throw new Error('FilePath: kind must be "file" or "dir"');
|
|
42
|
+
}
|
|
43
|
+
if (kind === "file") {
|
|
44
|
+
// Validación de filename completo
|
|
45
|
+
if (!filename || typeof filename !== "string" || !filename.trim()) {
|
|
46
|
+
throw new Error("FilePath: filename must be a non-empty string");
|
|
47
|
+
}
|
|
48
|
+
// Validación de extensión (puede ser vacía, pero debe ser string)
|
|
49
|
+
if (typeof extension !== "string") {
|
|
50
|
+
throw new Error("FilePath: extension must be a string");
|
|
51
|
+
}
|
|
52
|
+
// Validación de basename
|
|
53
|
+
if (!basename || typeof basename !== "string" || !basename.trim()) {
|
|
54
|
+
throw new Error("FilePath: basename must be a non-empty string");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Asignación inmutable
|
|
58
|
+
this._absolutePath = absolutePath;
|
|
59
|
+
this._directory = directory;
|
|
60
|
+
this._filename = filename;
|
|
61
|
+
this._extension = extension;
|
|
62
|
+
this._basename = basename;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Valor principal del Value Object.
|
|
66
|
+
* Alias explícito de `absolutePath` para uso genérico.
|
|
67
|
+
*/
|
|
68
|
+
get value() {
|
|
69
|
+
return this._absolutePath;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Ruta absoluta completa del archivo.
|
|
73
|
+
*/
|
|
74
|
+
get absolutePath() {
|
|
75
|
+
return this._absolutePath;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Directorio contenedor del archivo.
|
|
79
|
+
*/
|
|
80
|
+
get directory() {
|
|
81
|
+
return this._directory;
|
|
82
|
+
}
|
|
83
|
+
get filename() {
|
|
84
|
+
return this._filename;
|
|
85
|
+
}
|
|
86
|
+
get extension() {
|
|
87
|
+
return this._extension;
|
|
88
|
+
}
|
|
89
|
+
get basename() {
|
|
90
|
+
return this._basename;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Comparación por valor.
|
|
94
|
+
* Dos FilePath son iguales si representan la misma ruta absoluta.
|
|
95
|
+
*/
|
|
96
|
+
equals(other) {
|
|
97
|
+
return this._absolutePath === other._absolutePath;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.FilePath = FilePath;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { FileSize } from ".";
|
|
2
|
+
import { FsRotationBy } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* FileRotationPolicy (Value Object)
|
|
5
|
+
* -----------------------------------------------------------------------------
|
|
6
|
+
* Encapsula la política de rotación de logs en filesystem.
|
|
7
|
+
*
|
|
8
|
+
* Contiene:
|
|
9
|
+
* - Estrategia de rotación (by): "none" | "day" | "size"
|
|
10
|
+
* - Parámetros opcionales:
|
|
11
|
+
* - maxSize: umbral de tamaño (solo aplica para "size")
|
|
12
|
+
* - maxFiles: máximo de archivos rotados a conservar (opcional)
|
|
13
|
+
*
|
|
14
|
+
* Propiedades del VO:
|
|
15
|
+
* - Inmutable
|
|
16
|
+
* - Valida invariantes en el constructor
|
|
17
|
+
* - Incluye comportamiento de dominio relacionado (ej. rotación por tamaño)
|
|
18
|
+
*/
|
|
19
|
+
export declare class FileRotationPolicy {
|
|
20
|
+
private readonly _by;
|
|
21
|
+
private readonly _maxSize?;
|
|
22
|
+
private readonly _maxFiles?;
|
|
23
|
+
/**
|
|
24
|
+
* Crea una política de rotación.
|
|
25
|
+
*
|
|
26
|
+
* Nota:
|
|
27
|
+
* - maxSizeMB se interpreta en megabytes si la estrategia es "size".
|
|
28
|
+
* - Para otras estrategias, maxSizeMB se ignora.
|
|
29
|
+
*/
|
|
30
|
+
constructor(by: FsRotationBy, maxSize?: number, maxFiles?: number);
|
|
31
|
+
/**
|
|
32
|
+
* Estrategia de rotación configurada.
|
|
33
|
+
*/
|
|
34
|
+
get by(): FsRotationBy;
|
|
35
|
+
/**
|
|
36
|
+
* Umbral de tamaño (solo relevante cuando by === "size").
|
|
37
|
+
*/
|
|
38
|
+
get maxSize(): FileSize | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Máximo de archivos rotados a conservar (opcional).
|
|
41
|
+
*/
|
|
42
|
+
get maxFiles(): number | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Indica si, según esta política, corresponde rotar por tamaño.
|
|
45
|
+
* Regla: rota si currentSize >= maxSize.
|
|
46
|
+
*
|
|
47
|
+
* Nota:
|
|
48
|
+
* - No hace IO; asume que alguien ya consultó el tamaño actual.
|
|
49
|
+
*/
|
|
50
|
+
shouldRotateBySize(currentSize: FileSize): boolean;
|
|
51
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileRotationPolicy = void 0;
|
|
4
|
+
const _1 = require(".");
|
|
5
|
+
/**
|
|
6
|
+
* FileRotationPolicy (Value Object)
|
|
7
|
+
* -----------------------------------------------------------------------------
|
|
8
|
+
* Encapsula la política de rotación de logs en filesystem.
|
|
9
|
+
*
|
|
10
|
+
* Contiene:
|
|
11
|
+
* - Estrategia de rotación (by): "none" | "day" | "size"
|
|
12
|
+
* - Parámetros opcionales:
|
|
13
|
+
* - maxSize: umbral de tamaño (solo aplica para "size")
|
|
14
|
+
* - maxFiles: máximo de archivos rotados a conservar (opcional)
|
|
15
|
+
*
|
|
16
|
+
* Propiedades del VO:
|
|
17
|
+
* - Inmutable
|
|
18
|
+
* - Valida invariantes en el constructor
|
|
19
|
+
* - Incluye comportamiento de dominio relacionado (ej. rotación por tamaño)
|
|
20
|
+
*/
|
|
21
|
+
class FileRotationPolicy {
|
|
22
|
+
/**
|
|
23
|
+
* Crea una política de rotación.
|
|
24
|
+
*
|
|
25
|
+
* Nota:
|
|
26
|
+
* - maxSizeMB se interpreta en megabytes si la estrategia es "size".
|
|
27
|
+
* - Para otras estrategias, maxSizeMB se ignora.
|
|
28
|
+
*/
|
|
29
|
+
constructor(by, maxSize, maxFiles) {
|
|
30
|
+
// Invariante: si se rota por tamaño, se requiere un maxSize positivo
|
|
31
|
+
if (by === "size" && (maxSize == null || maxSize <= 0)) {
|
|
32
|
+
throw new Error("FileRotationPolicy: maxSizeMB must be positive for size rotation");
|
|
33
|
+
}
|
|
34
|
+
// Invariante: si se define maxFiles, debe ser positivo
|
|
35
|
+
if (maxFiles != null && maxFiles <= 0) {
|
|
36
|
+
throw new Error("FileRotationPolicy: maxFiles must be positive");
|
|
37
|
+
}
|
|
38
|
+
this._by = by;
|
|
39
|
+
// Construcción del VO FileSize a partir de MB (si aplica)
|
|
40
|
+
this._maxSize =
|
|
41
|
+
maxSize != null ? _1.FileSize.fromMegabytes(maxSize) : undefined;
|
|
42
|
+
this._maxFiles = maxFiles;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Estrategia de rotación configurada.
|
|
46
|
+
*/
|
|
47
|
+
get by() {
|
|
48
|
+
return this._by;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Umbral de tamaño (solo relevante cuando by === "size").
|
|
52
|
+
*/
|
|
53
|
+
get maxSize() {
|
|
54
|
+
return this._maxSize;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Máximo de archivos rotados a conservar (opcional).
|
|
58
|
+
*/
|
|
59
|
+
get maxFiles() {
|
|
60
|
+
return this._maxFiles;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Indica si, según esta política, corresponde rotar por tamaño.
|
|
64
|
+
* Regla: rota si currentSize >= maxSize.
|
|
65
|
+
*
|
|
66
|
+
* Nota:
|
|
67
|
+
* - No hace IO; asume que alguien ya consultó el tamaño actual.
|
|
68
|
+
*/
|
|
69
|
+
shouldRotateBySize(currentSize) {
|
|
70
|
+
return this._by === "size" && !!this._maxSize
|
|
71
|
+
? currentSize.isGreaterThan(this._maxSize) ||
|
|
72
|
+
currentSize.equals(this._maxSize)
|
|
73
|
+
: false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.FileRotationPolicy = FileRotationPolicy;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FileSize (Value Object)
|
|
3
|
+
* -----------------------------------------------------------------------------
|
|
4
|
+
* Representa el tamaño de un archivo, almacenado internamente en bytes.
|
|
5
|
+
*
|
|
6
|
+
* DDD / Clean Architecture:
|
|
7
|
+
* - Inmutable
|
|
8
|
+
* - Igualdad por valor (bytes)
|
|
9
|
+
* - No depende de infraestructura (fs, streams, etc.)
|
|
10
|
+
* - Expone comportamiento de dominio: conversiones y comparaciones
|
|
11
|
+
*/
|
|
12
|
+
export declare class FileSize {
|
|
13
|
+
/**
|
|
14
|
+
* Valor interno en bytes.
|
|
15
|
+
* Invariante: entero no negativo.
|
|
16
|
+
*/
|
|
17
|
+
private readonly _bytes;
|
|
18
|
+
/**
|
|
19
|
+
* Construye un FileSize desde bytes.
|
|
20
|
+
* - bytes debe ser entero no negativo
|
|
21
|
+
*/
|
|
22
|
+
constructor(bytes: number);
|
|
23
|
+
/**
|
|
24
|
+
* Bytes exactos (unidad base del VO).
|
|
25
|
+
*/
|
|
26
|
+
get bytes(): number;
|
|
27
|
+
/**
|
|
28
|
+
* Tamaño en kilobytes (KiB, base 1024).
|
|
29
|
+
* Nota: retorna number (puede tener decimales).
|
|
30
|
+
*/
|
|
31
|
+
get kilobytes(): number;
|
|
32
|
+
/**
|
|
33
|
+
* Tamaño en megabytes (MiB, base 1024).
|
|
34
|
+
* Nota: retorna number (puede tener decimales).
|
|
35
|
+
*/
|
|
36
|
+
get megabytes(): number;
|
|
37
|
+
/**
|
|
38
|
+
* Tamaño en gigabytes (GiB, base 1024).
|
|
39
|
+
* Nota: retorna number (puede tener decimales).
|
|
40
|
+
*/
|
|
41
|
+
get gigabytes(): number;
|
|
42
|
+
/**
|
|
43
|
+
* Crea un FileSize a partir de megabytes.
|
|
44
|
+
*
|
|
45
|
+
* Nota:
|
|
46
|
+
* - Permite mb con decimales.
|
|
47
|
+
* - Se convierte a bytes y se aplica Math.floor (redondeo hacia abajo).
|
|
48
|
+
*/
|
|
49
|
+
static fromMegabytes(mb: number): FileSize;
|
|
50
|
+
/**
|
|
51
|
+
* Crea un FileSize a partir de kilobytes.
|
|
52
|
+
*
|
|
53
|
+
* Nota:
|
|
54
|
+
* - Permite kb con decimales.
|
|
55
|
+
* - Se convierte a bytes y se aplica Math.floor (redondeo hacia abajo).
|
|
56
|
+
*/
|
|
57
|
+
static fromKilobytes(kb: number): FileSize;
|
|
58
|
+
/**
|
|
59
|
+
* Comparación: this > other
|
|
60
|
+
*/
|
|
61
|
+
isGreaterThan(other: FileSize): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Comparación: this < other
|
|
64
|
+
*/
|
|
65
|
+
isLessThan(other: FileSize): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Igualdad por valor (bytes exactos).
|
|
68
|
+
*/
|
|
69
|
+
equals(other: FileSize): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Representación legible para logs/diagnóstico.
|
|
72
|
+
* Selecciona la unidad más adecuada y muestra 2 decimales en KB/MB/GB.
|
|
73
|
+
*/
|
|
74
|
+
toString(): string;
|
|
75
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileSize = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* FileSize (Value Object)
|
|
6
|
+
* -----------------------------------------------------------------------------
|
|
7
|
+
* Representa el tamaño de un archivo, almacenado internamente en bytes.
|
|
8
|
+
*
|
|
9
|
+
* DDD / Clean Architecture:
|
|
10
|
+
* - Inmutable
|
|
11
|
+
* - Igualdad por valor (bytes)
|
|
12
|
+
* - No depende de infraestructura (fs, streams, etc.)
|
|
13
|
+
* - Expone comportamiento de dominio: conversiones y comparaciones
|
|
14
|
+
*/
|
|
15
|
+
class FileSize {
|
|
16
|
+
/**
|
|
17
|
+
* Construye un FileSize desde bytes.
|
|
18
|
+
* - bytes debe ser entero no negativo
|
|
19
|
+
*/
|
|
20
|
+
constructor(bytes) {
|
|
21
|
+
if (bytes < 0 || !Number.isInteger(bytes)) {
|
|
22
|
+
throw new Error("FileSize: bytes must be a non-negative integer");
|
|
23
|
+
}
|
|
24
|
+
this._bytes = bytes;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Bytes exactos (unidad base del VO).
|
|
28
|
+
*/
|
|
29
|
+
get bytes() {
|
|
30
|
+
return this._bytes;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Tamaño en kilobytes (KiB, base 1024).
|
|
34
|
+
* Nota: retorna number (puede tener decimales).
|
|
35
|
+
*/
|
|
36
|
+
get kilobytes() {
|
|
37
|
+
return this._bytes / 1024;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Tamaño en megabytes (MiB, base 1024).
|
|
41
|
+
* Nota: retorna number (puede tener decimales).
|
|
42
|
+
*/
|
|
43
|
+
get megabytes() {
|
|
44
|
+
return this._bytes / (1024 * 1024);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Tamaño en gigabytes (GiB, base 1024).
|
|
48
|
+
* Nota: retorna number (puede tener decimales).
|
|
49
|
+
*/
|
|
50
|
+
get gigabytes() {
|
|
51
|
+
return this._bytes / (1024 * 1024 * 1024);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Crea un FileSize a partir de megabytes.
|
|
55
|
+
*
|
|
56
|
+
* Nota:
|
|
57
|
+
* - Permite mb con decimales.
|
|
58
|
+
* - Se convierte a bytes y se aplica Math.floor (redondeo hacia abajo).
|
|
59
|
+
*/
|
|
60
|
+
static fromMegabytes(mb) {
|
|
61
|
+
if (mb < 0) {
|
|
62
|
+
throw new Error("FileSize: megabytes must be non-negative");
|
|
63
|
+
}
|
|
64
|
+
return new FileSize(Math.floor(mb * 1024 * 1024));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Crea un FileSize a partir de kilobytes.
|
|
68
|
+
*
|
|
69
|
+
* Nota:
|
|
70
|
+
* - Permite kb con decimales.
|
|
71
|
+
* - Se convierte a bytes y se aplica Math.floor (redondeo hacia abajo).
|
|
72
|
+
*/
|
|
73
|
+
static fromKilobytes(kb) {
|
|
74
|
+
if (kb < 0) {
|
|
75
|
+
throw new Error("FileSize: kilobytes must be non-negative");
|
|
76
|
+
}
|
|
77
|
+
return new FileSize(Math.floor(kb * 1024));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Comparación: this > other
|
|
81
|
+
*/
|
|
82
|
+
isGreaterThan(other) {
|
|
83
|
+
return this._bytes > other._bytes;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Comparación: this < other
|
|
87
|
+
*/
|
|
88
|
+
isLessThan(other) {
|
|
89
|
+
return this._bytes < other._bytes;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Igualdad por valor (bytes exactos).
|
|
93
|
+
*/
|
|
94
|
+
equals(other) {
|
|
95
|
+
return this._bytes === other._bytes;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Representación legible para logs/diagnóstico.
|
|
99
|
+
* Selecciona la unidad más adecuada y muestra 2 decimales en KB/MB/GB.
|
|
100
|
+
*/
|
|
101
|
+
toString() {
|
|
102
|
+
if (this._bytes >= 1024 * 1024 * 1024) {
|
|
103
|
+
return `${(this._bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
|
|
104
|
+
}
|
|
105
|
+
if (this._bytes >= 1024 * 1024) {
|
|
106
|
+
return `${(this._bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
107
|
+
}
|
|
108
|
+
if (this._bytes >= 1024) {
|
|
109
|
+
return `${(this._bytes / 1024).toFixed(2)} KB`;
|
|
110
|
+
}
|
|
111
|
+
return `${this._bytes} bytes`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.FileSize = FileSize;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./file-path.vo"), exports);
|
|
18
|
+
__exportStar(require("./file-size.vo"), exports);
|
|
19
|
+
__exportStar(require("./file-rotation-policy.vo"), exports);
|
|
20
|
+
__exportStar(require("./file-name-pattern.vo"), exports);
|
|
21
|
+
__exportStar(require("./log-level.vo"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LogLevel = void 0;
|
|
4
|
+
var LogLevel;
|
|
5
|
+
(function (LogLevel) {
|
|
6
|
+
// Orden creciente permite comparar por severidad (trace < debug < ...)
|
|
7
|
+
LogLevel[LogLevel["TRACE"] = 10] = "TRACE";
|
|
8
|
+
LogLevel[LogLevel["DEBUG"] = 20] = "DEBUG";
|
|
9
|
+
LogLevel[LogLevel["INFO"] = 30] = "INFO";
|
|
10
|
+
LogLevel[LogLevel["WARN"] = 40] = "WARN";
|
|
11
|
+
LogLevel[LogLevel["ERROR"] = 50] = "ERROR";
|
|
12
|
+
LogLevel[LogLevel["FATAL"] = 60] = "FATAL";
|
|
13
|
+
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
export declare class FileSystemDatasource implements ILogDatasource {
|
|
6
|
-
private readonly opts;
|
|
7
|
-
private stream;
|
|
8
|
-
constructor(opts: FsOpts);
|
|
9
|
-
save(log: Log): Promise<void>;
|
|
10
|
-
flush(): Promise<void>;
|
|
11
|
-
dispose(): Promise<void>;
|
|
12
|
-
}
|
|
13
|
-
export {};
|
|
1
|
+
export { FilePath, FileSize, FileRotationPolicy, FileNamePattern, } from "./domain/value-objects";
|
|
2
|
+
export { createFsDatasource } from "./application/factory";
|
|
3
|
+
export { IFilesystemDatasourceOptions } from "./application/types";
|
|
4
|
+
export { IFileSystemRotationConfig } from "./infrastructure/filesystem";
|
package/dist/index.js
CHANGED
|
@@ -1,40 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
throw new Error("FS stream closed");
|
|
17
|
-
const line = JSON.stringify(log) + "\n";
|
|
18
|
-
if (!this.stream.write(line)) {
|
|
19
|
-
// backpressure: esperar a 'drain'
|
|
20
|
-
await new Promise((resolve) => this.stream.once("drain", resolve));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
async flush() {
|
|
24
|
-
if (!this.stream)
|
|
25
|
-
return;
|
|
26
|
-
if (!this.stream.writableNeedDrain)
|
|
27
|
-
return;
|
|
28
|
-
await new Promise((resolve) => this.stream.once("drain", resolve));
|
|
29
|
-
}
|
|
30
|
-
async dispose() {
|
|
31
|
-
if (!this.stream)
|
|
32
|
-
return;
|
|
33
|
-
await new Promise((resolve, reject) => {
|
|
34
|
-
this.stream.end(() => resolve()); // end -> cierra el fd
|
|
35
|
-
this.stream.once("error", reject);
|
|
36
|
-
});
|
|
37
|
-
this.stream = null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
exports.FileSystemDatasource = FileSystemDatasource;
|
|
3
|
+
exports.createFsDatasource = exports.FileNamePattern = exports.FileRotationPolicy = exports.FileSize = exports.FilePath = void 0;
|
|
4
|
+
// Value Objects
|
|
5
|
+
var value_objects_1 = require("./domain/value-objects");
|
|
6
|
+
Object.defineProperty(exports, "FilePath", { enumerable: true, get: function () { return value_objects_1.FilePath; } });
|
|
7
|
+
Object.defineProperty(exports, "FileSize", { enumerable: true, get: function () { return value_objects_1.FileSize; } });
|
|
8
|
+
Object.defineProperty(exports, "FileRotationPolicy", { enumerable: true, get: function () { return value_objects_1.FileRotationPolicy; } });
|
|
9
|
+
Object.defineProperty(exports, "FileNamePattern", { enumerable: true, get: function () { return value_objects_1.FileNamePattern; } });
|
|
10
|
+
// Factory
|
|
11
|
+
var factory_1 = require("./application/factory");
|
|
12
|
+
Object.defineProperty(exports, "createFsDatasource", { enumerable: true, get: function () { return factory_1.createFsDatasource; } });
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { IFileSystemProviderPort, IFilePathPort, IFileRotatorPort } from "../../domain/ports";
|
|
2
|
+
import { FileSize, FilePath, FileRotationPolicy, FileNamePattern } from "../../domain/value-objects";
|
|
3
|
+
/**
|
|
4
|
+
* Adapter de infraestructura que implementa IFileRotatorPort.
|
|
5
|
+
*
|
|
6
|
+
* Responsabilidad:
|
|
7
|
+
* - Calcular el path esperado del archivo de log en base a una fecha y un FileNamePattern.
|
|
8
|
+
* - Leer metadata real del filesystem (tamaño / listado de archivos).
|
|
9
|
+
* - Decidir si debe rotar (por día o por tamaño) apoyándose en la política del dominio.
|
|
10
|
+
*
|
|
11
|
+
* Nota:
|
|
12
|
+
* - Este adapter mantiene estado mínimo (`currentFilePath`) porque el Port lo requiere.
|
|
13
|
+
* Aun así, evitamos mutaciones ocultas: solo se actualiza desde getExpectedPathForDate().
|
|
14
|
+
*/
|
|
15
|
+
export declare class FileRotatorAdapter implements IFileRotatorPort {
|
|
16
|
+
private readonly fsProvider;
|
|
17
|
+
private readonly filePathAdapter;
|
|
18
|
+
private readonly fileNamePattern;
|
|
19
|
+
private readonly basePath;
|
|
20
|
+
private currentFilePath;
|
|
21
|
+
private readonly baseDir;
|
|
22
|
+
private static readonly TOKEN_REGEX;
|
|
23
|
+
constructor(fsProvider: IFileSystemProviderPort, filePathAdapter: IFilePathPort, fileNamePattern: FileNamePattern, basePath: string);
|
|
24
|
+
/**
|
|
25
|
+
* Devuelve el último archivo considerado “actual” por el rotator.
|
|
26
|
+
* Puede ser null si aún no se ha calculado/solicitado un path.
|
|
27
|
+
*/
|
|
28
|
+
getCurrentPath(): FilePath | null;
|
|
29
|
+
/**
|
|
30
|
+
* Calcula el path esperado para una fecha y lo “marca” como archivo actual.
|
|
31
|
+
* OJO: este es el único método que muta currentFilePath a propósito.
|
|
32
|
+
*/
|
|
33
|
+
getExpectedPathForDate(date: Date): FilePath;
|
|
34
|
+
/**
|
|
35
|
+
* Calcula el FilePath esperado para una fecha usando el patrón.
|
|
36
|
+
* Método “puro”: NO muta estado.
|
|
37
|
+
*/
|
|
38
|
+
private computePathForDate;
|
|
39
|
+
/**
|
|
40
|
+
* Reemplaza tokens de fecha dentro del patrón (ej. {yyyy}{MM}{dd}) por valores reales.
|
|
41
|
+
*/
|
|
42
|
+
private applyDateTokens;
|
|
43
|
+
/**
|
|
44
|
+
* Obtiene el tamaño del archivo (stat) y lo devuelve como FileSize (VO).
|
|
45
|
+
*
|
|
46
|
+
* Decisión de diseño:
|
|
47
|
+
* - Si stat falla (archivo no existe, permisos, etc.), devolvemos tamaño 0.
|
|
48
|
+
* - Esto evita que el flujo de rotación “reviente” por un fallo de I/O puntual.
|
|
49
|
+
* - Si quieres hacer esto más estricto, aquí podrías lanzar un FileOperationError("read"/"stat", ...).
|
|
50
|
+
*/
|
|
51
|
+
getFileSize(filePath: FilePath): Promise<FileSize>;
|
|
52
|
+
/**
|
|
53
|
+
* Decide si debe rotar basándose en la política del dominio y el estado actual.
|
|
54
|
+
*
|
|
55
|
+
* Nota:
|
|
56
|
+
* - Para rotación por día: comparamos el path actual vs el esperado para la fecha actual.
|
|
57
|
+
* - Para rotación por tamaño: consultamos el tamaño real y delegamos la regla al VO.
|
|
58
|
+
*/
|
|
59
|
+
shouldRotate(policy: FileRotationPolicy, currentDate: Date): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Rotación por día:
|
|
62
|
+
* - Si no hay currentFilePath, se considera que “debe rotar/crear” para inicializar.
|
|
63
|
+
* - Si el nombre esperado para la fecha actual difiere del actual, debe rotar.
|
|
64
|
+
*
|
|
65
|
+
* Importante:
|
|
66
|
+
* - Este método NO muta currentFilePath (solo calcula).
|
|
67
|
+
*/
|
|
68
|
+
private shouldRotateByDay;
|
|
69
|
+
/**
|
|
70
|
+
* Rotación por tamaño:
|
|
71
|
+
* - Si no hay currentFilePath, no rotamos (no hay “archivo actual” que evaluar).
|
|
72
|
+
* - Si no hay maxSize en la policy, no rotamos.
|
|
73
|
+
* - Si se puede medir tamaño, delegamos al VO para la regla (>= maxSize).
|
|
74
|
+
*/
|
|
75
|
+
private shouldRotateBySize;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Escapa caracteres especiales para construir RegExp seguro desde strings (basename/ext).
|
|
79
|
+
*/
|