@jmlq/logger-plugin-fs 0.1.0-alpha.7 → 0.1.0-alpha.9

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.
Files changed (144) hide show
  1. package/README.md +6 -0
  2. package/dist/application/dto/index.d.ts +1 -3
  3. package/dist/application/dto/index.js +1 -3
  4. package/dist/application/dto/rotate-if-needed.request.d.ts +10 -0
  5. package/dist/application/factory/create-fs-datasource.factory.d.ts +14 -1
  6. package/dist/application/factory/create-fs-datasource.factory.js +45 -20
  7. package/dist/application/use-cases/append-log.use-case.d.ts +26 -8
  8. package/dist/application/use-cases/append-log.use-case.js +25 -12
  9. package/dist/application/use-cases/ensure-directory.use-case.d.ts +50 -3
  10. package/dist/application/use-cases/ensure-directory.use-case.js +44 -7
  11. package/dist/application/use-cases/find-logs-use-case.d.ts +17 -0
  12. package/dist/application/use-cases/find-logs-use-case.js +64 -0
  13. package/dist/application/use-cases/index.d.ts +1 -0
  14. package/dist/application/use-cases/index.js +1 -0
  15. package/dist/application/use-cases/persist-log.use-case.d.ts +86 -9
  16. package/dist/application/use-cases/persist-log.use-case.js +73 -15
  17. package/dist/application/use-cases/rotate-if-needed.use-case.d.ts +49 -11
  18. package/dist/application/use-cases/rotate-if-needed.use-case.js +41 -8
  19. package/dist/domain/model/index.d.ts +1 -0
  20. package/dist/{infrastructure/filesystem/value-objects → domain/model}/index.js +1 -1
  21. package/dist/domain/model/log-entry.model.d.ts +8 -0
  22. package/dist/domain/ports/file/file-path.port.d.ts +38 -0
  23. package/dist/domain/ports/file/file-rotator.port.d.ts +42 -0
  24. package/dist/{infrastructure/filesystem/ports → domain/ports/file}/index.d.ts +1 -0
  25. package/dist/{infrastructure/filesystem/ports → domain/ports/file}/index.js +1 -0
  26. package/dist/domain/ports/file/log-stream-writer.port.d.ts +70 -0
  27. package/dist/domain/ports/{fs-provider.port.d.ts → filesystem-provider.port.d.ts} +1 -1
  28. package/dist/domain/ports/index.d.ts +5 -4
  29. package/dist/domain/ports/index.js +5 -4
  30. package/dist/domain/ports/logs/find/index.d.ts +2 -0
  31. package/dist/domain/ports/logs/find/index.js +18 -0
  32. package/dist/domain/ports/logs/find/log-file-line-reader.port.d.ts +3 -0
  33. package/dist/domain/ports/logs/find/log-file-numerator.port.d.ts +3 -0
  34. package/dist/domain/ports/logs/index.d.ts +2 -0
  35. package/dist/domain/ports/logs/index.js +18 -0
  36. package/dist/domain/ports/logs/log-datasource.port.d.ts +10 -0
  37. package/dist/domain/ports/{clock.port.d.ts → system-clock.port.d.ts} +1 -1
  38. package/dist/domain/ports/system-clock.port.js +2 -0
  39. package/dist/domain/request/index.d.ts +2 -0
  40. package/dist/domain/request/index.js +18 -0
  41. package/dist/domain/request/log-filter.request.d.ts +9 -0
  42. package/dist/domain/request/log-filter.request.js +2 -0
  43. package/dist/domain/request/save-log.request.d.ts +7 -0
  44. package/dist/domain/request/save-log.request.js +2 -0
  45. package/dist/domain/response/index.d.ts +1 -0
  46. package/dist/{application/services → domain/response}/index.js +1 -1
  47. package/dist/domain/response/log.response.d.ts +8 -0
  48. package/dist/domain/response/log.response.js +2 -0
  49. package/dist/domain/types/fs-rotation-by.type.d.ts +8 -0
  50. package/dist/domain/types/fs-rotation-by.type.js +2 -0
  51. package/dist/domain/types/index.d.ts +1 -0
  52. package/dist/domain/types/index.js +17 -0
  53. package/dist/domain/value-objects/file-name-pattern.vo.d.ts +36 -0
  54. package/dist/domain/value-objects/file-name-pattern.vo.js +53 -0
  55. package/dist/domain/value-objects/file-path.vo.d.ts +73 -9
  56. package/dist/domain/value-objects/file-path.vo.js +54 -13
  57. package/dist/domain/value-objects/file-rotation-policy.vo.d.ts +51 -0
  58. package/dist/domain/value-objects/file-rotation-policy.vo.js +76 -0
  59. package/dist/domain/value-objects/file-size.vo.d.ts +61 -0
  60. package/dist/domain/value-objects/file-size.vo.js +57 -0
  61. package/dist/domain/value-objects/index.d.ts +3 -0
  62. package/dist/domain/value-objects/index.js +3 -0
  63. package/dist/domain/value-objects/log-level.vo.d.ts +8 -0
  64. package/dist/domain/value-objects/log-level.vo.js +13 -0
  65. package/dist/index.d.ts +3 -4
  66. package/dist/index.js +5 -11
  67. package/dist/infrastructure/adapters/file-rotator.adapter.d.ts +67 -8
  68. package/dist/infrastructure/adapters/file-rotator.adapter.js +133 -67
  69. package/dist/infrastructure/adapters/fileSystem-datasource.adapter.d.ts +26 -0
  70. package/dist/infrastructure/adapters/fileSystem-datasource.adapter.js +45 -0
  71. package/dist/infrastructure/adapters/filesystem-log-file-enumerator.adapter.d.ts +6 -0
  72. package/dist/infrastructure/adapters/filesystem-log-file-enumerator.adapter.js +54 -0
  73. package/dist/infrastructure/adapters/filesystem-log-file-line-reader.adapter.d.ts +4 -0
  74. package/dist/infrastructure/adapters/{fs-provider.adapter.js → filesystem-log-file-line-reader.adapter.js} +13 -37
  75. package/dist/infrastructure/adapters/filesystem-provider.adapter.d.ts +122 -0
  76. package/dist/infrastructure/adapters/filesystem-provider.adapter.js +182 -0
  77. package/dist/infrastructure/adapters/index.d.ts +7 -4
  78. package/dist/infrastructure/adapters/index.js +7 -4
  79. package/dist/infrastructure/adapters/log-stream-writer.adapter.d.ts +80 -0
  80. package/dist/infrastructure/adapters/log-stream-writer.adapter.js +163 -0
  81. package/dist/infrastructure/adapters/system-clock.adapter.d.ts +25 -0
  82. package/dist/infrastructure/adapters/system-clock.adapter.js +30 -0
  83. package/dist/infrastructure/adapters/system-file-path.adapter.d.ts +47 -0
  84. package/dist/infrastructure/adapters/system-file-path.adapter.js +141 -0
  85. package/dist/infrastructure/errors/file-operation.error.d.ts +28 -0
  86. package/dist/infrastructure/errors/file-operation.error.js +54 -0
  87. package/dist/infrastructure/errors/index.d.ts +1 -0
  88. package/dist/{shared → infrastructure}/errors/index.js +0 -2
  89. package/dist/infrastructure/errors/types/file-operation-error-options.type.d.ts +8 -0
  90. package/dist/infrastructure/errors/types/file-operation-error-options.type.js +2 -0
  91. package/dist/infrastructure/errors/types/file-operation.type.d.ts +1 -0
  92. package/dist/infrastructure/errors/types/file-operation.type.js +2 -0
  93. package/dist/infrastructure/errors/types/fs-error-scope.type.d.ts +1 -0
  94. package/dist/infrastructure/errors/types/fs-error-scope.type.js +2 -0
  95. package/dist/infrastructure/errors/types/index.d.ts +3 -0
  96. package/dist/infrastructure/errors/types/index.js +19 -0
  97. package/dist/infrastructure/filesystem/index.d.ts +0 -3
  98. package/dist/infrastructure/filesystem/index.js +0 -3
  99. package/dist/infrastructure/filesystem/types/filesystem-datasource-options.type.d.ts +2 -6
  100. package/dist/infrastructure/filesystem/types/filesystem-rotation.type.d.ts +2 -9
  101. package/dist/infrastructure/filesystem/types/index.d.ts +0 -1
  102. package/dist/infrastructure/filesystem/types/index.js +0 -1
  103. package/install.md +1 -1
  104. package/package.json +4 -6
  105. package/dist/application/dto/rotation-check.dto.d.ts +0 -5
  106. package/dist/application/dto/save-log.dto.d.ts +0 -4
  107. package/dist/application/dto/write-operation.dto.d.ts +0 -5
  108. package/dist/application/services/fs-datasource.service.d.ts +0 -11
  109. package/dist/application/services/fs-datasource.service.js +0 -19
  110. package/dist/application/services/index.d.ts +0 -1
  111. package/dist/domain/ports/file-path-adapter.port.d.ts +0 -33
  112. package/dist/domain/ports/stream-writer.port.d.ts +0 -42
  113. package/dist/infrastructure/adapters/fs-provider.adapter.d.ts +0 -17
  114. package/dist/infrastructure/adapters/fs-writer.adapter.d.ts +0 -13
  115. package/dist/infrastructure/adapters/fs-writer.adapter.js +0 -71
  116. package/dist/infrastructure/adapters/node-clock.adapter.d.ts +0 -4
  117. package/dist/infrastructure/adapters/node-clock.adapter.js +0 -9
  118. package/dist/infrastructure/adapters/node-file-path.adapter.d.ts +0 -16
  119. package/dist/infrastructure/adapters/node-file-path.adapter.js +0 -117
  120. package/dist/infrastructure/filesystem/polices/index.d.ts +0 -1
  121. package/dist/infrastructure/filesystem/polices/index.js +0 -5
  122. package/dist/infrastructure/filesystem/polices/rotation-policy.d.ts +0 -29
  123. package/dist/infrastructure/filesystem/polices/rotation-policy.js +0 -55
  124. package/dist/infrastructure/filesystem/ports/file-rotator.port.d.ts +0 -32
  125. package/dist/infrastructure/filesystem/types/filesystem-serializer.type.d.ts +0 -10
  126. package/dist/infrastructure/filesystem/value-objects/file-name-pattern.vo.d.ts +0 -22
  127. package/dist/infrastructure/filesystem/value-objects/file-name-pattern.vo.js +0 -37
  128. package/dist/infrastructure/filesystem/value-objects/index.d.ts +0 -1
  129. package/dist/shared/errors/file-operation.error.d.ts +0 -12
  130. package/dist/shared/errors/file-operation.error.js +0 -32
  131. package/dist/shared/errors/fs-plugin.error.d.ts +0 -4
  132. package/dist/shared/errors/fs-plugin.error.js +0 -11
  133. package/dist/shared/errors/index.d.ts +0 -3
  134. package/dist/shared/errors/rotation.error.d.ts +0 -10
  135. package/dist/shared/errors/rotation.error.js +0 -25
  136. /package/dist/application/dto/{rotation-check.dto.js → rotate-if-needed.request.js} +0 -0
  137. /package/dist/{application/dto/save-log.dto.js → domain/model/log-entry.model.js} +0 -0
  138. /package/dist/{application/dto/write-operation.dto.js → domain/ports/file/file-path.port.js} +0 -0
  139. /package/dist/{infrastructure/filesystem/ports → domain/ports/file}/file-rotator.port.js +0 -0
  140. /package/dist/domain/ports/{clock.port.js → file/log-stream-writer.port.js} +0 -0
  141. /package/dist/domain/ports/{file-path-adapter.port.js → filesystem-provider.port.js} +0 -0
  142. /package/dist/domain/ports/{fs-provider.port.js → logs/find/log-file-line-reader.port.js} +0 -0
  143. /package/dist/domain/ports/{stream-writer.port.js → logs/find/log-file-numerator.port.js} +0 -0
  144. /package/dist/{infrastructure/filesystem/types/filesystem-serializer.type.js → domain/ports/logs/log-datasource.port.js} +0 -0
@@ -1,42 +1,100 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PersistLogUseCase = void 0;
4
+ /**
5
+ * PersistLogUseCase
6
+ * -----------------------------------------------------------------------------
7
+ * Caso de uso de Application que orquesta el flujo completo:
8
+ * - asegura el directorio base
9
+ * - decide si rota según política y fecha actual
10
+ * - garantiza que el stream está abierto en el archivo correcto
11
+ * - escribe el log (append)
12
+ *
13
+ * Nota (Clean Architecture):
14
+ * - No hace IO directamente: todo IO va por ports/use-cases delegados.
15
+ * - Centraliza la secuencia y manejo de errores del flujo.
16
+ */
4
17
  class PersistLogUseCase {
5
- constructor(clockPort, fileRotatorPort, streamWriterPort, rotationPolicy, rotateIfNeededUseCase, appendLogUseCase, ensureDirectoryUseCase, onError) {
6
- this.clockPort = clockPort;
7
- this.fileRotatorPort = fileRotatorPort;
8
- this.streamWriterPort = streamWriterPort;
18
+ constructor(
19
+ /**
20
+ * Port para obtener la hora actual
21
+ */
22
+ systemClock,
23
+ /**
24
+ * Port relacionado con rotación/naming (según diseño actual).
25
+ * Idealmente: la parte de naming debería estar separada en un "namer".
26
+ */
27
+ fileRotator,
28
+ /**
29
+ * Writer por stream
30
+ */
31
+ streamWriter,
32
+ /**
33
+ * Política de rotación (VO de dominio).
34
+ */
35
+ rotationPolicy,
36
+ /**
37
+ * Use-case que ejecuta rotación si corresponde
38
+ */
39
+ rotateIfNeededUseCase,
40
+ /**
41
+ * Use-case que serializa y escribe el log al stream.
42
+ */
43
+ appendLogUseCase,
44
+ /**
45
+ * Use-case que asegura que el directorio base exista.
46
+ */
47
+ ensureDirectoryUseCase,
48
+ /**
49
+ * Hook opcional para reportar/registrar errores antes de relanzarlos.
50
+ */
51
+ onError) {
52
+ this.systemClock = systemClock;
53
+ this.fileRotator = fileRotator;
54
+ this.streamWriter = streamWriter;
9
55
  this.rotationPolicy = rotationPolicy;
10
56
  this.rotateIfNeededUseCase = rotateIfNeededUseCase;
11
57
  this.appendLogUseCase = appendLogUseCase;
12
58
  this.ensureDirectoryUseCase = ensureDirectoryUseCase;
13
59
  this.onError = onError;
14
60
  }
61
+ /**
62
+ * Ejecuta el flujo principal de persistencia del log.
63
+ */
15
64
  async execute(dto) {
16
65
  try {
17
- // Asegurar que el directorio existe
66
+ // 1) Asegurar que el directorio base existe (si está habilitado)
18
67
  await this.ensureDirectoryUseCase.execute();
19
- const currentDate = this.clockPort.now();
20
- // Verificar si necesitamos rotar
68
+ // 2) Obtener "ahora" desde un port (testable)
69
+ const currentDate = this.systemClock.now();
70
+ // 3) Verificar si corresponde rotar según política/fecha
21
71
  await this.rotateIfNeededUseCase.execute({
22
72
  currentDate,
23
73
  rotationPolicy: this.rotationPolicy,
24
74
  });
25
- // Asegurar que el stream está abierto en la ruta correcta
26
- const expectedPath = this.fileRotatorPort.getExpectedPathForDate(currentDate);
27
- const currentPath = this.streamWriterPort.getCurrentPath();
28
- if (!this.streamWriterPort.isOpen() ||
75
+ // 4) Asegurar que el stream esté abierto en la ruta esperada
76
+ const expectedPath = this.fileRotator.getExpectedPathForDate(currentDate);
77
+ const currentPath = this.streamWriter.getCurrentPath();
78
+ // Reabrir si:
79
+ // - no está abierto
80
+ // - no hay path actual
81
+ // - el path actual no coincide con el esperado (por fecha/patrón)
82
+ if (
83
+ // Cerrar si estaba abierto (evita handles colgando)
84
+ !this.streamWriter.isOpen() ||
29
85
  !currentPath ||
30
86
  !currentPath.equals(expectedPath)) {
31
- if (this.streamWriterPort.isOpen()) {
32
- await this.streamWriterPort.close();
87
+ if (this.streamWriter.isOpen()) {
88
+ await this.streamWriter.close();
33
89
  }
34
- await this.streamWriterPort.open(expectedPath);
90
+ // Abrir stream al archivo esperado
91
+ await this.streamWriter.open(expectedPath);
35
92
  }
36
- // Escribir el log
93
+ // 5) Escribir el log (serialización + newline + write)
37
94
  await this.appendLogUseCase.execute(dto);
38
95
  }
39
96
  catch (error) {
97
+ // Hook opcional (log/metrics), pero se relanza el error para no ocultarlo
40
98
  if (this.onError) {
41
99
  await this.onError(error);
42
100
  }
@@ -1,17 +1,55 @@
1
- import { IFileRotatorPort, RotationPolicy } from "../../infrastructure/filesystem";
2
- import { IStreamWriterPort } from "../../domain/ports";
1
+ import { ILogStreamWriterPort, IFileRotatorPort } from "../../domain/ports";
3
2
  import { FilePath } from "../../domain/value-objects";
4
- export interface IRotateIfNeededDto {
5
- currentDate: Date;
6
- rotationPolicy: RotationPolicy;
7
- }
3
+ import { RotateIfNeededRequest } from "../dto";
4
+ /**
5
+ * Contrato del caso de uso: retorna el nuevo path si rotó, o null si no rotó.
6
+ */
8
7
  export interface IRotateIfNeededUseCase {
9
- execute(dto: IRotateIfNeededDto): Promise<FilePath | null>;
8
+ execute(dto: RotateIfNeededRequest): Promise<FilePath | null>;
10
9
  }
10
+ /**
11
+ * RotateIfNeededUseCase
12
+ * -----------------------------------------------------------------------------
13
+ * Caso de uso de Application que:
14
+ * - determina si se debe rotar (según policy + fecha)
15
+ * - si aplica, cambia el writer al nuevo archivo (close/open)
16
+ * - ejecuta un hook opcional onRotate(oldPath, newPath)
17
+ *
18
+ * Nota:
19
+ * - Depende de ports (IO indirecto).
20
+ * - Existe potencial de duplicidad si otro use-case también asegura open/close.
21
+ */
11
22
  export declare class RotateIfNeededUseCase implements IRotateIfNeededUseCase {
12
- private readonly fileRotatorPort;
13
- private readonly streamWriterPort;
23
+ /**
24
+ * Componente de rotación/naming (según diseño actual).
25
+ */
26
+ private readonly fileRotator;
27
+ /**
28
+ * Writer por stream usado para cerrar/abrir el archivo activo.
29
+ */
30
+ private readonly fileSystemWriter;
31
+ /**
32
+ * Hook opcional ejecutado cuando efectivamente se rota.
33
+ */
14
34
  private readonly onRotate?;
15
- constructor(fileRotatorPort: IFileRotatorPort, streamWriterPort: IStreamWriterPort, onRotate?: ((oldPath: FilePath, newPath: FilePath) => void | Promise<void>) | undefined);
16
- execute(dto: IRotateIfNeededDto): Promise<FilePath | null>;
35
+ constructor(
36
+ /**
37
+ * Componente de rotación/naming (según diseño actual).
38
+ */
39
+ fileRotator: IFileRotatorPort,
40
+ /**
41
+ * Writer por stream usado para cerrar/abrir el archivo activo.
42
+ */
43
+ fileSystemWriter: ILogStreamWriterPort,
44
+ /**
45
+ * Hook opcional ejecutado cuando efectivamente se rota.
46
+ */
47
+ onRotate?: ((oldPath: FilePath, newPath: FilePath) => void | Promise<void>) | undefined);
48
+ /**
49
+ * Ejecuta el flujo "rotar si hace falta".
50
+ * Retorna:
51
+ * - null si no corresponde rotar
52
+ * - newPath si rotó (o si el expected path es el nuevo destino)
53
+ */
54
+ execute(dto: RotateIfNeededRequest): Promise<FilePath | null>;
17
55
  }
@@ -1,23 +1,56 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RotateIfNeededUseCase = void 0;
4
+ /**
5
+ * RotateIfNeededUseCase
6
+ * -----------------------------------------------------------------------------
7
+ * Caso de uso de Application que:
8
+ * - determina si se debe rotar (según policy + fecha)
9
+ * - si aplica, cambia el writer al nuevo archivo (close/open)
10
+ * - ejecuta un hook opcional onRotate(oldPath, newPath)
11
+ *
12
+ * Nota:
13
+ * - Depende de ports (IO indirecto).
14
+ * - Existe potencial de duplicidad si otro use-case también asegura open/close.
15
+ */
4
16
  class RotateIfNeededUseCase {
5
- constructor(fileRotatorPort, streamWriterPort, onRotate) {
6
- this.fileRotatorPort = fileRotatorPort;
7
- this.streamWriterPort = streamWriterPort;
17
+ constructor(
18
+ /**
19
+ * Componente de rotación/naming (según diseño actual).
20
+ */
21
+ fileRotator,
22
+ /**
23
+ * Writer por stream usado para cerrar/abrir el archivo activo.
24
+ */
25
+ fileSystemWriter,
26
+ /**
27
+ * Hook opcional ejecutado cuando efectivamente se rota.
28
+ */
29
+ onRotate) {
30
+ this.fileRotator = fileRotator;
31
+ this.fileSystemWriter = fileSystemWriter;
8
32
  this.onRotate = onRotate;
9
33
  }
34
+ /**
35
+ * Ejecuta el flujo "rotar si hace falta".
36
+ * Retorna:
37
+ * - null si no corresponde rotar
38
+ * - newPath si rotó (o si el expected path es el nuevo destino)
39
+ */
10
40
  async execute(dto) {
11
41
  const { currentDate, rotationPolicy } = dto;
12
- const shouldRotate = await this.fileRotatorPort.shouldRotate(rotationPolicy, currentDate);
42
+ // Decide si corresponde rotar (según implementación actual del port)
43
+ const shouldRotate = await this.fileRotator.shouldRotate(rotationPolicy, currentDate);
13
44
  if (!shouldRotate) {
14
45
  return null;
15
46
  }
16
- const oldPath = this.fileRotatorPort.getCurrentPath();
17
- const newPath = this.fileRotatorPort.getExpectedPathForDate(currentDate);
47
+ // Path anterior (si existe) y path esperado para la fecha actual
48
+ const oldPath = this.fileRotator.getCurrentPath();
49
+ const newPath = this.fileRotator.getExpectedPathForDate(currentDate);
50
+ // Solo si hay cambio real de archivo, se reabre el writer
18
51
  if (oldPath && !oldPath.equals(newPath)) {
19
- await this.streamWriterPort.close();
20
- await this.streamWriterPort.open(newPath);
52
+ await this.fileSystemWriter.close();
53
+ await this.fileSystemWriter.open(newPath);
21
54
  if (this.onRotate) {
22
55
  await this.onRotate(oldPath, newPath);
23
56
  }
@@ -0,0 +1 @@
1
+ export * from "./log-entry.model";
@@ -14,4 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./file-name-pattern.vo"), exports);
17
+ __exportStar(require("./log-entry.model"), exports);
@@ -0,0 +1,8 @@
1
+ import { LogLevel } from "../value-objects";
2
+ export interface LogEntry {
3
+ source: string;
4
+ level: LogLevel;
5
+ message: string | Record<string, unknown>;
6
+ meta?: unknown;
7
+ timestamp: number;
8
+ }
@@ -0,0 +1,38 @@
1
+ import { FilePath } from "../../value-objects";
2
+ /**
3
+ * IFilePathPort
4
+ * -----------------------------------------------------------------------------
5
+ * Puerto de dominio para:
6
+ * 1) Construir un FilePath (Value Object) desde entradas string externas.
7
+ * 2) Componer rutas a partir de un FilePath existente.
8
+ *
9
+ * Motivación (Clean Architecture):
10
+ * - El dominio/aplicación NO dependen de `node:path` ni de reglas de OS.
11
+ * - Infraestructura provee un adapter (ej. SystemFilePathAdapter) que implementa esto.
12
+ *
13
+ * Nota de consistencia:
14
+ * - Define y respeta si FilePath en tu dominio es SIEMPRE absoluto o puede ser relativo.
15
+ * (Si es siempre absoluto, fromRaw debería resolver a absoluto.)
16
+ */
17
+ export interface IFilePathPort {
18
+ /**
19
+ * Construye un FilePath a partir de una ruta cruda (relativa o absoluta).
20
+ *
21
+ * Responsabilidades del adapter:
22
+ * - Validar input mínimo (string no vacío).
23
+ * - Normalizar separadores / limpiar.
24
+ * - (Opcional según tu modelo) Resolver a ruta absoluta.
25
+ */
26
+ fromRaw(inputPath: string): FilePath;
27
+ /**
28
+ * Une segmentos a partir de un FilePath base y retorna un nuevo FilePath (inmutable).
29
+ *
30
+ * Caso típico:
31
+ * - basePath (FilePath) + "subdir" + "file.log"
32
+ *
33
+ * Responsabilidades del adapter:
34
+ * - Validar segmentos (no vacíos si aplica).
35
+ * - Normalizar la ruta resultante.
36
+ */
37
+ join(filePath: FilePath, ...segments: string[]): FilePath;
38
+ }
@@ -0,0 +1,42 @@
1
+ import { FileSize, FilePath, FileRotationPolicy } from "../../value-objects";
2
+ /**
3
+ * IFileRotatorPort
4
+ * -----------------------------------------------------------------------------
5
+ * Puerto de dominio para consultar información del filesystem necesaria
6
+ * para implementar rotación de archivos (logs) en casos de uso/servicios.
7
+ *
8
+ * Importante (Clean Architecture):
9
+ * - Este port NO debe contener reglas de negocio (p. ej. decidir si rotar).
10
+ * - Debe limitarse a capacidades del mundo externo (filesystem).
11
+ *
12
+ * La decisión de rotación (por fecha/tamaño/política) debe vivir en:
13
+ * - un Domain Service (reglas), o
14
+ * - un Use Case (orquestación), pero no dentro del port.
15
+ */
16
+ export interface IFileRotatorPort {
17
+ /**
18
+ * Obtiene el archivo de log "actual" si existe/está determinado
19
+ * por la implementación (por ejemplo, por configuración).
20
+ *
21
+ * Nota:
22
+ * - Si el "current" depende solo de config, considera eliminar esto
23
+ * y que el caso de uso lo derive desde config/naming.
24
+ */
25
+ getCurrentPath(): FilePath | null;
26
+ /**
27
+ * Calcular cómo se va a llamar el archivo según una fecha
28
+ * @param date Fecha para la que se quiere el path
29
+ */
30
+ getExpectedPathForDate(date: Date): FilePath;
31
+ /**
32
+ * Consulta el tamaño del archivo en filesystem.
33
+ * (IO puro; ideal para políticas de rotación por tamaño).
34
+ */
35
+ getFileSize(filePath: FilePath): Promise<FileSize>;
36
+ /**
37
+ * Decidir si corresponde rotar de acuerdo a una RotationPolicy y la fecha actual
38
+ * @param policy Política de rotación
39
+ * @param currentDate Fecha actual
40
+ */
41
+ shouldRotate(policy: FileRotationPolicy, currentDate: Date): Promise<boolean>;
42
+ }
@@ -1 +1,2 @@
1
+ export * from "./file-path.port";
1
2
  export * from "./file-rotator.port";
@@ -14,4 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./file-path.port"), exports);
17
18
  __exportStar(require("./file-rotator.port"), exports);
@@ -0,0 +1,70 @@
1
+ import { FilePath } from "../../value-objects";
2
+ /**
3
+ * IFileSystemWriterPort
4
+ * -----------------------------------------------------------------------------
5
+ * Puerto de salida (Outbound Port) que abstrae un writer basado en stream.
6
+ *
7
+ * Uso típico:
8
+ * - open(path)
9
+ * - write(line)
10
+ * - flush() (opcional, antes de rotar o cerrar)
11
+ * - close() (cerrar el stream actual, con posibilidad de reabrir)
12
+ * - end() (finalizar definitivamente / liberar recursos)
13
+ *
14
+ * Implementación típica en infraestructura:
15
+ * - Node.js fs.createWriteStream + manejo de backpressure ("drain")
16
+ */
17
+ export interface ILogStreamWriterPort {
18
+ /**
19
+ * Escribe datos al stream actual.
20
+ *
21
+ * Retorna:
22
+ * - true: la escritura fue aceptada sin saturar el buffer
23
+ * - false: hay backpressure (buffer lleno) y conviene esperar antes de seguir
24
+ *
25
+ * Nota de diseño:
26
+ * - Si la implementación "await" internamente hasta que drene, el boolean pierde valor.
27
+ * En ese caso considera devolver Promise<void> y ocultar backpressure.
28
+ */
29
+ write(data: string): Promise<boolean>;
30
+ /**
31
+ * Abre un stream para un archivo específico.
32
+ * Debe dejar el writer listo para recibir write().
33
+ */
34
+ open(filePath: FilePath): Promise<void>;
35
+ /**
36
+ * Cierra el stream actual (si existe) SIN implicar "dispose definitivo".
37
+ * Útil para rotación: cerrar -> renombrar -> open(nuevo).
38
+ *
39
+ * Recomendación:
40
+ * - Define claramente si close() es idempotente (llamar dos veces no falla).
41
+ */
42
+ close(): Promise<void>;
43
+ /**
44
+ * Fuerza a que todo lo pendiente se escriba antes de continuar.
45
+ *
46
+ * Importante:
47
+ * - Define qué garantiza: ¿solo vaciar buffer en memoria? ¿fsync a disco?
48
+ * - Es clave si la rotación requiere consistencia antes de renombrar/mover.
49
+ */
50
+ flush(): Promise<void>;
51
+ /**
52
+ * Indica si el writer está abierto y listo para recibir escrituras.
53
+ * Útil para evitar errores por write() sin open().
54
+ */
55
+ isOpen(): boolean;
56
+ /**
57
+ * Devuelve el FilePath actualmente abierto para escritura, o null si no hay.
58
+ * Útil para diagnóstico o para decidir rotación desde la aplicación.
59
+ */
60
+ getCurrentPath(): FilePath | null;
61
+ /**
62
+ * Finaliza definitivamente el writer.
63
+ * Debe liberar recursos y dejar el objeto en estado no reutilizable
64
+ * (o al menos documentar si se puede reabrir).
65
+ *
66
+ * Recomendación:
67
+ * - Aclara la diferencia exacta con close().
68
+ */
69
+ end(): Promise<void>;
70
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Es una abstracción del sistema de archivos (fs) que la capa de dominio puede solicitar sin depender directamente del módulo fs de Node
3
3
  */
4
- export interface IFsProviderPort {
4
+ export interface IFileSystemProviderPort {
5
5
  /**
6
6
  * Permite saber si un archivo o carpeta existe
7
7
  * @param path Ruta del archivo o directorio
@@ -1,4 +1,5 @@
1
- export * from "./clock.port";
2
- export * from "./fs-provider.port";
3
- export * from "./stream-writer.port";
4
- export * from "./file-path-adapter.port";
1
+ export * from "./system-clock.port";
2
+ export * from "./filesystem-provider.port";
3
+ export * from "./file/log-stream-writer.port";
4
+ export * from "./file";
5
+ export * from "./logs";
@@ -14,7 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./clock.port"), exports);
18
- __exportStar(require("./fs-provider.port"), exports);
19
- __exportStar(require("./stream-writer.port"), exports);
20
- __exportStar(require("./file-path-adapter.port"), exports);
17
+ __exportStar(require("./system-clock.port"), exports);
18
+ __exportStar(require("./filesystem-provider.port"), exports);
19
+ __exportStar(require("./file/log-stream-writer.port"), exports);
20
+ __exportStar(require("./file"), exports);
21
+ __exportStar(require("./logs"), exports);
@@ -0,0 +1,2 @@
1
+ export * from "./log-file-line-reader.port";
2
+ export * from "./log-file-numerator.port";
@@ -0,0 +1,18 @@
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("./log-file-line-reader.port"), exports);
18
+ __exportStar(require("./log-file-numerator.port"), exports);
@@ -0,0 +1,3 @@
1
+ export interface ILogFileLineReaderPort {
2
+ readLines(filePath: string): AsyncIterable<string>;
3
+ }
@@ -0,0 +1,3 @@
1
+ export interface ILogFileEnumeratorPort {
2
+ listLogFiles(): Promise<string[]>;
3
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./find";
2
+ export * from "./log-datasource.port";
@@ -0,0 +1,18 @@
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("./find"), exports);
18
+ __exportStar(require("./log-datasource.port"), exports);
@@ -0,0 +1,10 @@
1
+ import { LogFilterRequest } from "../../request";
2
+ import { LogEntry } from "../../model";
3
+ import { ILogResponse } from "../../response";
4
+ export interface ILogDatasource {
5
+ save(log: LogEntry): Promise<void>;
6
+ find?(filter?: LogFilterRequest): Promise<ILogResponse[]>;
7
+ flush?(): Promise<void>;
8
+ dispose?(): Promise<void>;
9
+ readonly name?: string;
10
+ }
@@ -3,6 +3,6 @@
3
3
  * Su único propósito es permitir que el dominio pueda obtener la hora actual
4
4
  * sin depender directamente de new Date() ni de Date.now()
5
5
  */
6
- export interface IClockPort {
6
+ export interface ISystemClockPort {
7
7
  now(): Date;
8
8
  }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ export * from "./log-filter.request";
2
+ export * from "./save-log.request";
@@ -0,0 +1,18 @@
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("./log-filter.request"), exports);
18
+ __exportStar(require("./save-log.request"), exports);
@@ -0,0 +1,9 @@
1
+ import { LogLevel } from "../value-objects";
2
+ export interface LogFilterRequest {
3
+ levelMin?: LogLevel;
4
+ since?: number;
5
+ until?: number;
6
+ limit?: number;
7
+ offset?: number;
8
+ query?: string;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import { LogEntry } from "../model";
2
+ /**
3
+ * Request model del caso de uso SaveLog.
4
+ */
5
+ export interface SaveLogRequest {
6
+ log: LogEntry;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export * from "./log.response";
@@ -14,4 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./fs-datasource.service"), exports);
17
+ __exportStar(require("./log.response"), exports);
@@ -0,0 +1,8 @@
1
+ import { LogLevel } from "../value-objects";
2
+ export interface ILogResponse {
3
+ source: string;
4
+ level: LogLevel;
5
+ message: string | Record<string, unknown>;
6
+ meta?: unknown;
7
+ timestamp: number;
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Es un tipo discriminado que define cómo se realizará la rotación de logs dentro del sistema.
3
+ * Los valores significan:
4
+ * "none" → Sin rotación. El archivo crece indefinidamente.
5
+ * "day" → Rotación diaria (por fecha).
6
+ * "size" → Rotación por tamaño (normalmente basado en maxSizeMB).
7
+ */
8
+ export type FsRotationBy = "none" | "day" | "size";
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export * from "./fs-rotation-by.type";