@jmlq/logger-plugin-fs 0.1.0-alpha.1 → 0.1.0-alpha.10
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 +229 -0
- package/architecture.md +426 -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/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 +3 -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-datasource-options.type.d.ts +45 -0
- package/dist/infrastructure/filesystem/types/filesystem-datasource-options.type.js +2 -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 +2 -0
- package/dist/infrastructure/filesystem/types/index.js +18 -0
- package/install.md +520 -0
- package/package.json +40 -12
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileNamePattern = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* FileNamePattern (Value Object)
|
|
6
|
+
* -----------------------------------------------------------------------------
|
|
7
|
+
* Representa un patrón de nombrado de archivos de log.
|
|
8
|
+
*
|
|
9
|
+
* Ejemplos:
|
|
10
|
+
* - "app.log"
|
|
11
|
+
* - "app-{yyyy}{MM}{dd}.log"
|
|
12
|
+
*
|
|
13
|
+
* Responsabilidades:
|
|
14
|
+
* - Garantizar invariantes (string no vacío, sin solo espacios)
|
|
15
|
+
* - Exponer el patrón inmutable
|
|
16
|
+
* - Ofrecer operaciones de dominio relacionadas (tokens)
|
|
17
|
+
*/
|
|
18
|
+
class FileNamePattern {
|
|
19
|
+
/**
|
|
20
|
+
* Crea un patrón válido.
|
|
21
|
+
* Invariante: debe ser string no vacío y no solo whitespace.
|
|
22
|
+
*/
|
|
23
|
+
constructor(pattern) {
|
|
24
|
+
if (typeof pattern !== "string") {
|
|
25
|
+
throw new Error("FileNamePattern: pattern must be a non-empty string");
|
|
26
|
+
}
|
|
27
|
+
const trimmed = pattern.trim();
|
|
28
|
+
if (!trimmed) {
|
|
29
|
+
throw new Error("FileNamePattern: pattern must be a non-empty string");
|
|
30
|
+
}
|
|
31
|
+
this._pattern = trimmed;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Retorna el valor inmutable del patrón.
|
|
35
|
+
*/
|
|
36
|
+
get pattern() {
|
|
37
|
+
return this._pattern;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Devuelve todos los tokens encerrados en llaves presentes en el patrón.
|
|
41
|
+
* Ej: "app-{yyyy}{MM}.log" => ["yyyy", "MM"]
|
|
42
|
+
*/
|
|
43
|
+
getTokens() {
|
|
44
|
+
const matches = this._pattern.match(FileNamePattern.TOKEN_REGEX);
|
|
45
|
+
return matches ? matches.map((m) => m.slice(1, -1)) : [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.FileNamePattern = FileNamePattern;
|
|
49
|
+
/**
|
|
50
|
+
* Regex base para capturar tokens: "{...}"
|
|
51
|
+
* Centralizarlo evita inconsistencias entre métodos.
|
|
52
|
+
*/
|
|
53
|
+
FileNamePattern.TOKEN_REGEX = /\{([^}]+)\}/g;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export type FilePathKind = "file" | "dir";
|
|
2
|
+
/**
|
|
3
|
+
* Props requeridas para construir un FilePath.
|
|
4
|
+
*
|
|
5
|
+
* Importante:
|
|
6
|
+
* - Estas props representan una ruta YA normalizada.
|
|
7
|
+
* - La responsabilidad de construir valores coherentes
|
|
8
|
+
* (resolver path, separar directorio, basename, extensión, etc.)
|
|
9
|
+
* recae en la capa de infraestructura (adapters).
|
|
10
|
+
*/
|
|
11
|
+
export interface IFilePathProps {
|
|
12
|
+
/**
|
|
13
|
+
* Ruta absoluta completa del archivo.
|
|
14
|
+
* Ej: "/var/log/app/app-20251215.log"
|
|
15
|
+
*/
|
|
16
|
+
absolutePath: string;
|
|
17
|
+
/**
|
|
18
|
+
* Directorio contenedor del archivo.
|
|
19
|
+
* Ej: "/var/log/app"
|
|
20
|
+
*/
|
|
21
|
+
directory: string;
|
|
22
|
+
/**
|
|
23
|
+
* Nombre completo del archivo (basename + extensión).
|
|
24
|
+
* Ej: "app-20251215.log"
|
|
25
|
+
*/
|
|
26
|
+
filename: string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Extensión del archivo.
|
|
29
|
+
* Regla de dominio: debe ser string (puede ser vacío si no aplica).
|
|
30
|
+
* Ej: "log"
|
|
31
|
+
*/
|
|
32
|
+
extension: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Nombre base del archivo sin extensión.
|
|
35
|
+
* Ej: "app-20251215"
|
|
36
|
+
*/
|
|
37
|
+
basename: string | null;
|
|
38
|
+
kind: FilePathKind;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* FilePath (Value Object)
|
|
42
|
+
* -----------------------------------------------------------------------------
|
|
43
|
+
* Representa una ruta de archivo ya normalizada e inmutable.
|
|
44
|
+
*
|
|
45
|
+
* Características (DDD / Clean Architecture):
|
|
46
|
+
* - Es un Value Object (igualdad por valor).
|
|
47
|
+
* - No depende de Node.js ni del módulo `path`.
|
|
48
|
+
* - No realiza IO ni lógica de infraestructura.
|
|
49
|
+
* - Asume que la normalización fuerte ocurre en adapters.
|
|
50
|
+
*
|
|
51
|
+
* Su responsabilidad es:
|
|
52
|
+
* - Encapsular el concepto de "ruta de archivo válida"
|
|
53
|
+
* - Proteger invariantes básicas (no null, no vacío)
|
|
54
|
+
* - Exponer acceso seguro a sus partes
|
|
55
|
+
*/
|
|
56
|
+
export declare class FilePath {
|
|
57
|
+
private readonly _absolutePath;
|
|
58
|
+
private readonly _directory;
|
|
59
|
+
private readonly _filename;
|
|
60
|
+
private readonly _extension;
|
|
61
|
+
private readonly _basename;
|
|
62
|
+
/**
|
|
63
|
+
* Crea un FilePath a partir de props ya normalizadas.
|
|
64
|
+
*
|
|
65
|
+
* Nota de diseño:
|
|
66
|
+
* - Este constructor NO calcula rutas ni usa `path`.
|
|
67
|
+
* - Solo valida invariantes mínimas del dominio.
|
|
68
|
+
*/
|
|
69
|
+
constructor(props: IFilePathProps);
|
|
70
|
+
/**
|
|
71
|
+
* Valor principal del Value Object.
|
|
72
|
+
* Alias explícito de `absolutePath` para uso genérico.
|
|
73
|
+
*/
|
|
74
|
+
get value(): string;
|
|
75
|
+
/**
|
|
76
|
+
* Ruta absoluta completa del archivo.
|
|
77
|
+
*/
|
|
78
|
+
get absolutePath(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Directorio contenedor del archivo.
|
|
81
|
+
*/
|
|
82
|
+
get directory(): string;
|
|
83
|
+
get filename(): string | null;
|
|
84
|
+
get extension(): string | null;
|
|
85
|
+
get basename(): string | null;
|
|
86
|
+
/**
|
|
87
|
+
* Comparación por valor.
|
|
88
|
+
* Dos FilePath son iguales si representan la misma ruta absoluta.
|
|
89
|
+
*/
|
|
90
|
+
equals(other: FilePath): boolean;
|
|
91
|
+
}
|
|
@@ -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,3 @@
|
|
|
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, 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; } });
|