@jmlq/logger-plugin-fs 0.1.0-alpha.3 → 0.1.0-alpha.4

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 (60) hide show
  1. package/README.md +137 -241
  2. package/dist/application/dto/index.d.ts +1 -0
  3. package/dist/application/dto/index.js +17 -0
  4. package/dist/application/dto/save-log.dto.d.ts +4 -0
  5. package/dist/application/dto/save-log.dto.js +2 -0
  6. package/dist/application/services/fs-datasource.service.d.ts +9 -0
  7. package/dist/application/services/fs-datasource.service.js +22 -0
  8. package/dist/application/services/index.d.ts +1 -0
  9. package/dist/application/services/index.js +17 -0
  10. package/dist/application/use-cases/append-log.usecase.d.ts +7 -0
  11. package/dist/application/use-cases/append-log.usecase.js +19 -0
  12. package/dist/application/use-cases/index.d.ts +3 -0
  13. package/dist/application/use-cases/index.js +19 -0
  14. package/dist/application/use-cases/persist-log.usecase.d.ts +23 -0
  15. package/dist/application/use-cases/persist-log.usecase.js +74 -0
  16. package/dist/application/use-cases/rotate-if-needed.usecase.d.ts +10 -0
  17. package/dist/application/use-cases/rotate-if-needed.usecase.js +39 -0
  18. package/dist/domain/contracts/clock.contract.d.ts +3 -0
  19. package/dist/domain/contracts/clock.contract.js +2 -0
  20. package/dist/domain/contracts/file-rotator.contract.d.ts +7 -0
  21. package/dist/domain/contracts/file-rotator.contract.js +2 -0
  22. package/dist/domain/contracts/index.d.ts +4 -0
  23. package/dist/domain/contracts/index.js +20 -0
  24. package/dist/domain/contracts/serializer.contract.d.ts +3 -0
  25. package/dist/domain/contracts/serializer.contract.js +2 -0
  26. package/dist/domain/contracts/stream-writer.port.d.ts +6 -0
  27. package/dist/domain/contracts/stream-writer.port.js +2 -0
  28. package/dist/domain/types/index.d.ts +1 -0
  29. package/dist/domain/types/index.js +17 -0
  30. package/dist/domain/types/options.type.d.ts +11 -0
  31. package/dist/domain/types/options.type.js +5 -0
  32. package/dist/domain/value-objects/file-name-pattern.vo.d.ts +4 -0
  33. package/dist/domain/value-objects/file-name-pattern.vo.js +14 -0
  34. package/dist/domain/value-objects/index.d.ts +2 -0
  35. package/dist/domain/value-objects/index.js +18 -0
  36. package/dist/domain/value-objects/rotation-policy.vo.d.ts +7 -0
  37. package/dist/domain/value-objects/rotation-policy.vo.js +20 -0
  38. package/dist/index.d.ts +3 -13
  39. package/dist/index.js +7 -38
  40. package/dist/infrastructure/datasources/fs.datasource.d.ts +17 -0
  41. package/dist/infrastructure/datasources/fs.datasource.js +84 -0
  42. package/dist/infrastructure/datasources/index.d.ts +1 -0
  43. package/dist/infrastructure/datasources/index.js +17 -0
  44. package/dist/infrastructure/fs/file-rotator.adapter.d.ts +22 -0
  45. package/dist/infrastructure/fs/file-rotator.adapter.js +51 -0
  46. package/dist/infrastructure/fs/fs-provider.d.ts +15 -0
  47. package/dist/infrastructure/fs/fs-provider.js +55 -0
  48. package/dist/infrastructure/fs/fs-writer.adapter.d.ts +10 -0
  49. package/dist/infrastructure/fs/fs-writer.adapter.js +26 -0
  50. package/dist/infrastructure/fs/index.d.ts +5 -0
  51. package/dist/infrastructure/fs/index.js +21 -0
  52. package/dist/infrastructure/fs/node-clock.adapter.d.ts +4 -0
  53. package/dist/infrastructure/fs/node-clock.adapter.js +10 -0
  54. package/dist/infrastructure/fs/path-utils.d.ts +6 -0
  55. package/dist/infrastructure/fs/path-utils.js +26 -0
  56. package/dist/presentation/factory/create-fs-datasource.d.ts +15 -0
  57. package/dist/presentation/factory/create-fs-datasource.js +39 -0
  58. package/dist/presentation/factory/index.d.ts +1 -0
  59. package/dist/presentation/factory/index.js +17 -0
  60. package/package.json +15 -3
@@ -0,0 +1,10 @@
1
+ import { IFsProvider } from ".";
2
+ import type { IStreamWriterPort } from "../../domain/contracts";
3
+ export declare class FsWriterAdapter implements IStreamWriterPort {
4
+ private readonly stream;
5
+ constructor(fs: IFsProvider, path: string);
6
+ write(line: string): boolean;
7
+ once(event: "drain" | "error", cb: (...a: any[]) => void): void;
8
+ get writableNeedDrain(): boolean | undefined;
9
+ end(cb: () => void): void;
10
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FsWriterAdapter = void 0;
4
+ class FsWriterAdapter {
5
+ constructor(fs, path) {
6
+ // Abre el stream en modo append ('a') para no truncar archivos existentes
7
+ this.stream = fs.createWriteStream(path, { flags: "a" });
8
+ }
9
+ write(line) {
10
+ // Escribe la línea; devuelve false si hay backpressure
11
+ return this.stream.write(line);
12
+ }
13
+ once(event, cb) {
14
+ // Suscribe un handler de un solo uso para 'drain' o 'error'
15
+ this.stream.once(event, cb);
16
+ }
17
+ get writableNeedDrain() {
18
+ // expone flag de backpressure si está presente
19
+ return this.stream.writableNeedDrain;
20
+ }
21
+ end(cb) {
22
+ // Cierra el stream drenando el buffer pendiente
23
+ this.stream.end(cb);
24
+ }
25
+ }
26
+ exports.FsWriterAdapter = FsWriterAdapter;
@@ -0,0 +1,5 @@
1
+ export * from "./file-rotator.adapter";
2
+ export * from "./fs-writer.adapter";
3
+ export * from "./fs-provider";
4
+ export * from "./path-utils";
5
+ export * from "./node-clock.adapter";
@@ -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-rotator.adapter"), exports);
18
+ __exportStar(require("./fs-writer.adapter"), exports);
19
+ __exportStar(require("./fs-provider"), exports);
20
+ __exportStar(require("./path-utils"), exports);
21
+ __exportStar(require("./node-clock.adapter"), exports);
@@ -0,0 +1,4 @@
1
+ import { IClock } from "../../domain/contracts";
2
+ export declare class NodeClockAdapter implements IClock {
3
+ now(): Date;
4
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ // Reloj real del sistema.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.NodeClockAdapter = void 0;
5
+ class NodeClockAdapter {
6
+ now() {
7
+ return new Date();
8
+ }
9
+ }
10
+ exports.NodeClockAdapter = NodeClockAdapter;
@@ -0,0 +1,6 @@
1
+ export declare function formatPattern(pattern: string, now: Date): string;
2
+ export declare function splitBaseExt(fileName: string): {
3
+ base: string;
4
+ ext: string;
5
+ };
6
+ export declare function joinBase(basePath: string, fileName: string): string;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ // Utilidades puras de path y formateo de nombre.
3
+ // Cambiamos a getters UTC para evitar desfaces por huso horario.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.formatPattern = formatPattern;
6
+ exports.splitBaseExt = splitBaseExt;
7
+ exports.joinBase = joinBase;
8
+ const path_1 = require("path");
9
+ function formatPattern(pattern, now) {
10
+ // Usar UTC para que "2025-09-09T00:00:00Z" siga siendo 2025-09-09
11
+ const yyyy = now.getUTCFullYear().toString();
12
+ const MM = String(now.getUTCMonth() + 1).padStart(2, "0");
13
+ const dd = String(now.getUTCDate()).padStart(2, "0");
14
+ return pattern
15
+ .replace("{yyyy}", yyyy)
16
+ .replace("{MM}", MM)
17
+ .replace("{dd}", dd);
18
+ }
19
+ function splitBaseExt(fileName) {
20
+ const ext = (0, path_1.extname)(fileName);
21
+ const base = ext ? (0, path_1.basename)(fileName, ext) : fileName;
22
+ return { base, ext };
23
+ }
24
+ function joinBase(basePath, fileName) {
25
+ return (0, path_1.join)(basePath, fileName);
26
+ }
@@ -0,0 +1,15 @@
1
+ import { FsDatasourceService } from "../../application/services";
2
+ import type { IFsSerializer } from "../../domain/contracts";
3
+ export declare function createFsDatasource(input: {
4
+ basePath: string;
5
+ mkdir?: boolean;
6
+ fileNamePattern?: string;
7
+ rotation?: {
8
+ by: "none" | "day" | "size";
9
+ maxSizeMB?: number;
10
+ maxFiles?: number;
11
+ };
12
+ serializer?: IFsSerializer;
13
+ onRotate?: (oldPath: string, newPath: string) => void | Promise<void>;
14
+ onError?: (err: unknown) => void | Promise<void>;
15
+ }): FsDatasourceService;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ // Ensambla el servicio de aplicación (que implementa ILogDatasource)
3
+ // con los adaptadores de infraestructura. Aquí no hay lógica de negocio,
4
+ // sólo wiring + defaults.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createFsDatasource = createFsDatasource;
7
+ const services_1 = require("../../application/services");
8
+ const use_cases_1 = require("../../application/use-cases");
9
+ const value_objects_1 = require("../../domain/value-objects");
10
+ const fs_1 = require("../../infrastructure/fs");
11
+ function createFsDatasource(input) {
12
+ // 1) Defaults de VO y opciones
13
+ const pattern = new value_objects_1.FileNamePattern(input.fileNamePattern ?? "app-{yyyy}{MM}{dd}.log");
14
+ const rotation = input.rotation
15
+ ? new value_objects_1.RotationPolicy(input.rotation.by, input.rotation.maxSizeMB, input.rotation.maxFiles)
16
+ : new value_objects_1.RotationPolicy("day");
17
+ const opts = {
18
+ basePath: input.basePath,
19
+ mkdir: !!input.mkdir,
20
+ pattern,
21
+ rotation,
22
+ serializer: input.serializer ?? { serialize: (x) => JSON.stringify(x) },
23
+ onRotate: input.onRotate,
24
+ onError: input.onError,
25
+ };
26
+ // 2) Adapters de infraestructura
27
+ const fs = (0, fs_1.createFsProvider)();
28
+ const clock = new fs_1.NodeClockAdapter();
29
+ const rotator = new fs_1.FileRotatorAdapter(fs, opts.basePath, clock, opts.pattern, !!opts.mkdir);
30
+ // 3) Casos de uso (application)
31
+ const rotateUC = new use_cases_1.RotateIfNeededUseCase(opts.rotation, rotator, clock);
32
+ const appendUC = new use_cases_1.AppendLogUseCase(opts.serializer);
33
+ // 4) Factory para abrir writers en el path que diga el rotator
34
+ const openWriter = (path) => new fs_1.FsWriterAdapter(fs, path);
35
+ // 5) Orquestador principal (application) que usará core: ILogDatasource
36
+ const persistUC = new use_cases_1.PersistLogUseCase(rotateUC, appendUC, rotator, openWriter, opts.onRotate, opts.onError);
37
+ // 6) Servicio que implementa ILogDatasource (core)
38
+ return new services_1.FsDatasourceService(persistUC);
39
+ }
@@ -0,0 +1 @@
1
+ export * from "./create-fs-datasource";
@@ -0,0 +1,17 @@
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("./create-fs-datasource"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmlq/logger-plugin-fs",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
4
4
  "author": "MLahuasi",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -9,14 +9,26 @@
9
9
  ],
10
10
  "scripts": {
11
11
  "build": "tsc -p tsconfig.json",
12
- "prepublishOnly": "npm run build"
12
+ "prepublishOnly": "npm run build",
13
+ "test": "jest --passWithNoTests",
14
+ "test:watch": "jest --watch",
15
+ "test:cov": "jest --coverage"
13
16
  },
14
17
  "devDependencies": {
15
18
  "@types/node": "^24.3.0",
16
19
  "tsx": "^4.20.5",
17
- "typescript": "^5.9.2"
20
+ "typescript": "^5.9.2",
21
+ "@swc/core": "^1.13.5",
22
+ "@swc/jest": "^0.2.39",
23
+ "@types/jest": "^30.0.0",
24
+ "jest": "^30.1.3"
18
25
  },
19
26
  "dependencies": {
20
27
  "@jmlq/logger": "^0.1.0-alpha.2"
28
+ },
29
+ "overrides": {
30
+ "test-exclude": "^7.0.1",
31
+ "glob": "^10.4.5",
32
+ "minimatch": "^9.0.5"
21
33
  }
22
34
  }