@jmlq/logger 0.1.0-alpha.2 → 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 (50) hide show
  1. package/README.md +347 -0
  2. package/dist/application/use-cases/flush-buffers.d.ts +6 -0
  3. package/dist/application/use-cases/flush-buffers.js +13 -0
  4. package/dist/application/use-cases/get-logs.d.ts +7 -0
  5. package/dist/application/use-cases/get-logs.js +24 -0
  6. package/dist/application/use-cases/index.d.ts +3 -0
  7. package/dist/application/use-cases/index.js +19 -0
  8. package/dist/application/use-cases/save-log.d.ts +13 -0
  9. package/dist/application/use-cases/save-log.js +30 -0
  10. package/dist/domain/contracts/index.d.ts +3 -0
  11. package/dist/domain/contracts/index.js +19 -0
  12. package/dist/domain/contracts/log.datasource.d.ts +8 -0
  13. package/dist/{config/interfaces/index.js → domain/contracts/log.datasource.js} +0 -1
  14. package/dist/domain/contracts/logger.d.ts +19 -0
  15. package/dist/domain/contracts/logger.js +2 -0
  16. package/dist/domain/contracts/pii.d.ts +5 -0
  17. package/dist/domain/contracts/pii.js +2 -0
  18. package/dist/domain/services/pii-redactor.d.ts +7 -24
  19. package/dist/domain/services/pii-redactor.js +55 -117
  20. package/dist/domain/types/index.d.ts +1 -0
  21. package/dist/{presentation → domain/types}/index.js +1 -1
  22. package/dist/domain/types/log.types.d.ts +28 -0
  23. package/dist/domain/types/log.types.js +2 -0
  24. package/dist/domain/value-objects/index.d.ts +1 -0
  25. package/dist/domain/{index.js → value-objects/index.js} +1 -1
  26. package/dist/domain/value-objects/log-level.d.ts +9 -0
  27. package/dist/domain/value-objects/log-level.js +37 -0
  28. package/dist/index.d.ts +5 -4
  29. package/dist/index.js +8 -18
  30. package/dist/infrastructure/adapters/composite.datasource.d.ts +11 -0
  31. package/dist/infrastructure/adapters/composite.datasource.js +46 -0
  32. package/dist/infrastructure/adapters/index.d.ts +1 -0
  33. package/dist/{config → infrastructure/adapters}/index.js +1 -2
  34. package/dist/presentation/factory/create-logger.d.ts +2 -0
  35. package/dist/presentation/factory/create-logger.js +29 -0
  36. package/dist/presentation/factory/index.d.ts +1 -2
  37. package/dist/presentation/factory/index.js +15 -72
  38. package/package.json +14 -2
  39. package/dist/Composite/index.d.ts +0 -9
  40. package/dist/Composite/index.js +0 -54
  41. package/dist/Factory/index.d.ts +0 -5
  42. package/dist/Factory/index.js +0 -23
  43. package/dist/config/index.d.ts +0 -2
  44. package/dist/config/interfaces/index.d.ts +0 -67
  45. package/dist/config/types/index.d.ts +0 -10
  46. package/dist/config/types/index.js +0 -13
  47. package/dist/domain/index.d.ts +0 -1
  48. package/dist/interfaces/index.d.ts +0 -35
  49. package/dist/interfaces/index.js +0 -13
  50. package/dist/presentation/index.d.ts +0 -1
@@ -1,139 +1,77 @@
1
1
  "use strict";
2
- /**
3
- * Domain Service: PiiRedactor
4
- *
5
- * Propósito:
6
- * - Redactar/anonimizar PII en strings, objetos y arrays (deep).
7
- * - Permitir que el cliente pase patrones adicionales/propios.
8
- * - Controlar redacción por nombre de clave (whitelist/blacklist).
9
- */
10
2
  Object.defineProperty(exports, "__esModule", { value: true });
11
3
  exports.PiiRedactor = void 0;
4
+ // Utilidad local: crea RegExp segura desde {pattern, flags}
5
+ function toRegex(p) {
6
+ // new RegExp lanza si el patrón es inválido → try/catch para robustez
7
+ try {
8
+ return new RegExp(p.pattern, p.flags ?? "g");
9
+ }
10
+ catch {
11
+ return /$a/; /* patrón imposible */
12
+ }
13
+ }
12
14
  class PiiRedactor {
13
- constructor(opts = {}) {
14
- const { enabled = true, includeDefaultPatterns = true, patterns = [], redactKeys = [], preserveKeys = [], } = opts;
15
- this.enabled = enabled;
16
- this.patterns = includeDefaultPatterns
17
- ? [...PiiRedactor.defaultPatterns(), ...patterns]
18
- : [...patterns];
19
- this.redactKeys = redactKeys;
20
- this.preserveKeys = preserveKeys;
15
+ constructor(options = {}) {
16
+ this.options = options;
21
17
  }
22
- /** Patrones por defecto (seguros y genéricos). Ajusta según tu dominio/región si lo deseas. */
23
- static defaultPatterns() {
24
- return [
25
- // Tarjetas (13–19 dígitos con espacios o guiones) — patrón simple
26
- {
27
- name: "credit_card",
28
- regex: /\b(?:\d[ -]*?){13,19}\b/g,
29
- replacement: "[REDACTED_CARD]",
30
- },
31
- // Emails
32
- {
33
- name: "email",
34
- regex: /\b[\w._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
35
- replacement: "[REDACTED_EMAIL]",
36
- },
37
- // Teléfonos: 10+ dígitos (ajusta a tu región si hace falta)
38
- {
39
- name: "phone",
40
- regex: /\b\d{10,}\b/g,
41
- replacement: "[REDACTED_PHONE]",
42
- },
43
- // Documento genérico: ABC-123456… o similar
44
- {
45
- name: "document_id",
46
- regex: /\b[A-Z]{1,3}-?\d{6,10}\b/g,
47
- replacement: "[REDACTED_ID]",
48
- },
49
- // IPv4
50
- {
51
- name: "ipv4",
52
- regex: /\b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)(?:\.|$)){4}\b/g,
53
- replacement: "[REDACTED_IP]",
54
- },
55
- ];
18
+ updateOptions(opts) {
19
+ // merge superficial de opciones; no muta referencias externas
20
+ this.options = { ...this.options, ...opts };
56
21
  }
57
- /** Punto de entrada público: redacción deep de cualquier estructura */
58
22
  redact(value) {
59
- if (!this.enabled)
23
+ if (!this.options.enabled)
24
+ return value; // early exit si PII apagado
25
+ if (value == null)
60
26
  return value;
61
- return this.redactValue(value, []);
62
- }
63
- /** === Internos === */
64
- redactValue(value, keyPath) {
65
- // Strings → aplicar patrones
27
+ // Si es string → aplicar patrones
66
28
  if (typeof value === "string") {
67
- return this.applyPatterns(value, keyPath);
68
- }
69
- // Números / boolean / null / undefined → retornar tal cual
70
- if (typeof value === "number" ||
71
- typeof value === "boolean" ||
72
- value === null ||
73
- typeof value === "undefined") {
74
- return value;
75
- }
76
- // Arrays → deep
77
- if (Array.isArray(value)) {
78
- return value.map((v, i) => this.redactValue(v, [...keyPath, String(i)]));
29
+ return this.applyPatterns(value);
79
30
  }
80
- // Objetos deep + reglas por nombre de clave
31
+ // Si es objeto/array redacción profunda si corresponde
81
32
  if (typeof value === "object") {
82
- const src = value;
83
- const out = {};
84
- for (const [k, v] of Object.entries(src)) {
85
- const path = [...keyPath, k];
86
- if (this.isPreservedKey(k)) {
87
- out[k] = this.clone(v); // explícitamente preservado
88
- continue;
89
- }
90
- if (this.isRedactedKey(k)) {
91
- out[k] = this.keyRedactionReplacement(k, path);
92
- continue;
93
- }
94
- out[k] = this.redactValue(v, path);
95
- }
96
- return out;
33
+ return this.redactDeep(value);
97
34
  }
98
- // funciones, símbolos, etc.
35
+ // Otros tipos (number, boolean, function) no se redactan
99
36
  return value;
100
37
  }
101
- applyPatterns(text, keyPath) {
102
- let result = text;
103
- for (const p of this.patterns) {
104
- const replacement = p.replacement ?? "[REDACTED]";
105
- // Soporta función de reemplazo con contexto (ruta de claves)
106
- if (typeof replacement === "function") {
107
- result = result.replace(p.regex, (m) => replacement(m, keyPath));
108
- }
109
- else {
110
- result = result.replace(p.regex, replacement);
111
- }
38
+ applyPatterns(input) {
39
+ const patterns = this.options.patterns ?? [];
40
+ let out = input;
41
+ for (const p of patterns) {
42
+ const rx = toRegex(p);
43
+ // replace con patrón RegExp
44
+ out = out.replace(rx, p.replaceWith);
112
45
  }
113
- return result;
114
- }
115
- isRedactedKey(key) {
116
- return this.redactKeys.some((r) => typeof r === "string" ? r === key : r.test(key));
46
+ return out;
117
47
  }
118
- isPreservedKey(key) {
119
- return this.preserveKeys.some((r) => typeof r === "string" ? r === key : r.test(key));
120
- }
121
- keyRedactionReplacement(_key, _path) {
122
- return "[REDACTED]";
123
- }
124
- clone(v) {
125
- if (v && typeof v === "object") {
126
- try {
127
- return JSON.parse(JSON.stringify(v));
48
+ redactDeep(obj) {
49
+ // Evita mutar el objeto original copia superficial
50
+ const clone = Array.isArray(obj)
51
+ ? [...obj]
52
+ : { ...obj };
53
+ const { whitelistKeys = [], blacklistKeys = [], deep = true, } = this.options;
54
+ for (const key of Object.keys(clone)) {
55
+ const val = clone[key];
56
+ // Si está en whitelist, se respeta siempre
57
+ if (whitelistKeys.includes(key))
58
+ continue;
59
+ // Si está en blacklist y es string → reemplazar completamente
60
+ if (blacklistKeys.includes(key)) {
61
+ clone[key] = "[REDACTED]"; // fuerza redacción total de claves sensibles
62
+ continue;
63
+ }
64
+ // Para strings comunes → aplicar patrones
65
+ if (typeof val === "string") {
66
+ clone[key] = this.applyPatterns(val);
67
+ continue;
128
68
  }
129
- catch {
130
- // fallback shallow
131
- if (Array.isArray(v))
132
- return [...v];
133
- return { ...v };
69
+ // Para objetos/arrays y deep===true → recursión
70
+ if (deep && val && typeof val === "object") {
71
+ clone[key] = this.redactDeep(val);
134
72
  }
135
73
  }
136
- return v;
74
+ return clone;
137
75
  }
138
76
  }
139
77
  exports.PiiRedactor = PiiRedactor;
@@ -0,0 +1 @@
1
+ export * from "./log.types";
@@ -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("./factory"), exports);
17
+ __exportStar(require("./log.types"), exports);
@@ -0,0 +1,28 @@
1
+ import { LogLevel } from "../value-objects";
2
+ export type LogMessage = string | Record<string, unknown> | (() => string | Record<string, unknown>);
3
+ export interface ILog {
4
+ level: LogLevel;
5
+ message: string | Record<string, unknown>;
6
+ meta?: unknown;
7
+ timestamp: number;
8
+ }
9
+ export interface IGetLogsFilter {
10
+ levelMin?: LogLevel;
11
+ since?: number;
12
+ until?: number;
13
+ limit?: number;
14
+ offset?: number;
15
+ query?: string;
16
+ }
17
+ export interface PiiReplacement {
18
+ pattern: string;
19
+ flags?: string;
20
+ replaceWith: string;
21
+ }
22
+ export interface PiiOptions {
23
+ enabled?: boolean;
24
+ whitelistKeys?: string[];
25
+ blacklistKeys?: string[];
26
+ patterns?: PiiReplacement[];
27
+ deep?: boolean;
28
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export * from "./log-level";
@@ -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("./services"), exports);
17
+ __exportStar(require("./log-level"), exports);
@@ -0,0 +1,9 @@
1
+ export declare enum LogLevel {
2
+ TRACE = 10,
3
+ DEBUG = 20,
4
+ INFO = 30,
5
+ WARN = 40,
6
+ ERROR = 50,
7
+ FATAL = 60
8
+ }
9
+ export declare function toLogLevel(level: string | number | undefined, def?: LogLevel): LogLevel;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogLevel = void 0;
4
+ exports.toLogLevel = toLogLevel;
5
+ var LogLevel;
6
+ (function (LogLevel) {
7
+ // Orden creciente permite comparar por severidad (trace < debug < ...)
8
+ LogLevel[LogLevel["TRACE"] = 10] = "TRACE";
9
+ LogLevel[LogLevel["DEBUG"] = 20] = "DEBUG";
10
+ LogLevel[LogLevel["INFO"] = 30] = "INFO";
11
+ LogLevel[LogLevel["WARN"] = 40] = "WARN";
12
+ LogLevel[LogLevel["ERROR"] = 50] = "ERROR";
13
+ LogLevel[LogLevel["FATAL"] = 60] = "FATAL";
14
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
15
+ // Convierte string a LogLevel con fallback seguro
16
+ function toLogLevel(level, def = LogLevel.INFO) {
17
+ if (typeof level === "number")
18
+ return (Object.values(LogLevel).includes(level) ? level : def);
19
+ if (!level)
20
+ return def;
21
+ switch (String(level).toLowerCase()) {
22
+ case "trace":
23
+ return LogLevel.TRACE;
24
+ case "debug":
25
+ return LogLevel.DEBUG;
26
+ case "info":
27
+ return LogLevel.INFO;
28
+ case "warn":
29
+ return LogLevel.WARN;
30
+ case "error":
31
+ return LogLevel.ERROR;
32
+ case "fatal":
33
+ return LogLevel.FATAL;
34
+ default:
35
+ return def; // evita lanzar excepción por valores inesperados
36
+ }
37
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from "./composite";
2
- export * from "./domain";
3
- export * from "./presentation";
4
- export * from "./config";
1
+ export { LogLevel, toLogLevel } from "./domain/value-objects";
2
+ export type { LogMessage, ILog, IGetLogsFilter, PiiOptions, PiiReplacement, } from "./domain/types";
3
+ export type { LogDatasourcePort, ILogger, ICreateLoggerOptions, ILogDatasource, } from "./domain/contracts";
4
+ export { createLogger } from "./presentation/factory";
5
+ export { CompositeDatasource } from "./infrastructure/adapters";
package/dist/index.js CHANGED
@@ -1,20 +1,10 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./composite"), exports);
18
- __exportStar(require("./domain"), exports);
19
- __exportStar(require("./presentation"), exports);
20
- __exportStar(require("./config"), exports);
3
+ exports.CompositeDatasource = exports.createLogger = exports.toLogLevel = exports.LogLevel = void 0;
4
+ var value_objects_1 = require("./domain/value-objects");
5
+ Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return value_objects_1.LogLevel; } });
6
+ Object.defineProperty(exports, "toLogLevel", { enumerable: true, get: function () { return value_objects_1.toLogLevel; } });
7
+ var factory_1 = require("./presentation/factory");
8
+ Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return factory_1.createLogger; } });
9
+ var adapters_1 = require("./infrastructure/adapters");
10
+ Object.defineProperty(exports, "CompositeDatasource", { enumerable: true, get: function () { return adapters_1.CompositeDatasource; } });
@@ -0,0 +1,11 @@
1
+ import { ILogDatasource } from "../../domain/contracts";
2
+ import { IGetLogsFilter, ILog } from "../../domain/types";
3
+ export declare class CompositeDatasource implements ILogDatasource {
4
+ private readonly targets;
5
+ readonly name = "composite";
6
+ constructor(targets: ILogDatasource[]);
7
+ save(log: ILog): Promise<void>;
8
+ find(filter?: IGetLogsFilter): Promise<ILog[]>;
9
+ flush(): Promise<void>;
10
+ dispose(): Promise<void>;
11
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CompositeDatasource = void 0;
4
+ // CompositeDatasource: fan-out hacia múltiples datasources
5
+ class CompositeDatasource {
6
+ constructor(targets) {
7
+ this.targets = targets;
8
+ this.name = "composite";
9
+ // Filtro targets válidos (defensivo). Evita null/undefined
10
+ this.targets = (targets ?? []).filter(Boolean);
11
+ }
12
+ async save(log) {
13
+ // Ejecuta todos en paralelo y NO falla el todo si uno falla
14
+ const results = await Promise.allSettled(this.targets.map((ds) => ds.save(log)));
15
+ // Log de errores silencioso (el logger real no debe auto-dependerse)
16
+ for (let i = 0; i < results.length; i++) {
17
+ const r = results[i];
18
+ if (r.status === "rejected") {
19
+ // Preferible: exponer un hook externo; aquí solo console.warn por simplicidad
20
+ // eslint-disable-next-line no-console
21
+ console.warn(`[CompositeDatasource] save error in ds#${i} (${this.targets[i]?.name ?? "unknown"})`, r.reason);
22
+ }
23
+ }
24
+ }
25
+ async find(filter) {
26
+ // Si varios ds soportan find, se concatena y ordena por timestamp desc
27
+ const results = await Promise.allSettled(this.targets.map((ds) => ds.find?.(filter)));
28
+ const logs = [];
29
+ for (const r of results) {
30
+ if (r.status === "fulfilled" && Array.isArray(r.value))
31
+ logs.push(...r.value);
32
+ }
33
+ // Orden descendente por timestamp (más recientes primero)
34
+ logs.sort((a, b) => b.timestamp - a.timestamp);
35
+ return logs;
36
+ }
37
+ async flush() {
38
+ // Ejecuta flush donde esté disponible
39
+ await Promise.allSettled(this.targets.map((ds) => ds.flush?.()));
40
+ }
41
+ async dispose() {
42
+ // Libera recursos en todos los ds
43
+ await Promise.allSettled(this.targets.map((ds) => ds.dispose?.()));
44
+ }
45
+ }
46
+ exports.CompositeDatasource = CompositeDatasource;
@@ -0,0 +1 @@
1
+ export * from "./composite.datasource";
@@ -14,5 +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("./interfaces"), exports);
18
- __exportStar(require("./types"), exports);
17
+ __exportStar(require("./composite.datasource"), exports);
@@ -0,0 +1,2 @@
1
+ import { ICreateLoggerOptions, ILogDatasource, ILogger } from "../../domain/contracts";
2
+ export declare function createLogger(ds: ILogDatasource, opts?: ICreateLoggerOptions): ILogger;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLogger = createLogger;
4
+ const use_cases_1 = require("../../application/use-cases");
5
+ const services_1 = require("../../domain/services");
6
+ const value_objects_1 = require("../../domain/value-objects");
7
+ // Factoría de logger. Encapsula composición de casos de uso y servicios
8
+ function createLogger(ds, opts = {}) {
9
+ // Resolve minLevel con un default razonable (INFO)
10
+ const minLevel = opts.minLevel ?? value_objects_1.LogLevel.INFO;
11
+ // Mantén compatibilidad con redactPII
12
+ const piiEnabled = opts.pii?.enabled ?? opts.redactPII ?? false;
13
+ const redactor = new services_1.PiiRedactor({ enabled: piiEnabled, ...opts.pii });
14
+ const save = new use_cases_1.SaveLog({ ds, minLevel, redactor });
15
+ const flushUC = new use_cases_1.FlushBuffers(ds);
16
+ // Helper emisor; si en el futuro se necesita encolar, aquí es el lugar
17
+ const emit = (lvl, message, meta) => save.execute(lvl, message, meta);
18
+ return {
19
+ trace: (m, meta) => emit(value_objects_1.LogLevel.TRACE, m, meta),
20
+ debug: (m, meta) => emit(value_objects_1.LogLevel.DEBUG, m, meta),
21
+ info: (m, meta) => emit(value_objects_1.LogLevel.INFO, m, meta),
22
+ warn: (m, meta) => emit(value_objects_1.LogLevel.WARN, m, meta),
23
+ error: (m, meta) => emit(value_objects_1.LogLevel.ERROR, m, meta),
24
+ fatal: (m, meta) => emit(value_objects_1.LogLevel.FATAL, m, meta),
25
+ // Gestión de ciclo de vida → delega en caso de uso / puerto
26
+ flush: () => flushUC.execute(),
27
+ dispose: () => ds.dispose?.() ?? Promise.resolve(),
28
+ };
29
+ }
@@ -1,2 +1 @@
1
- import { ICreateLoggerOptions, ILogDatasource, ILogger } from "../..";
2
- export declare function createLogger(ds: ILogDatasource, opts?: ICreateLoggerOptions): ILogger;
1
+ export * from "./create-logger";
@@ -1,74 +1,17 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLogger = createLogger;
4
- const __1 = require("../..");
5
- /**
6
- * Normaliza cualquier LogMessage a string, aplicando PII (si procede) ANTES de serializar.
7
- */
8
- function normalizeLogMessage(value, redactEnabled, redactor) {
9
- const v = redactEnabled ? redactor.redact(value) : value;
10
- if (typeof v === "string")
11
- return v;
12
- // Si soportas Error en LogMessage, lo serializamos “bonito”
13
- if (v instanceof Error) {
14
- const err = v;
15
- const obj = {
16
- error: err.name || "Error",
17
- message: err.message,
18
- stack: err.stack,
19
- code: err.code,
20
- cause: err.cause,
21
- };
22
- try {
23
- return JSON.stringify(obj);
24
- }
25
- catch {
26
- return `${obj.error}: ${obj.message}`;
27
- }
28
- }
29
- // Objeto → JSON
30
- try {
31
- return JSON.stringify(v);
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]; } };
32
7
  }
33
- catch {
34
- // fallback ultra defensivo
35
- return String(v);
36
- }
37
- }
38
- function createLogger(ds, opts = {}) {
39
- const minLevel = opts.minLevel ?? __1.LogLevel.INFO;
40
- // Compatibilidad: redactPII (boolean) o pii.enabled
41
- const redactEnabled = (opts.redactPII ?? false) || (opts.pii?.enabled ?? false);
42
- // Inicializa redactor con opciones del cliente (incluye defaults por defecto)
43
- const redactor = new __1.PiiRedactor({
44
- enabled: redactEnabled,
45
- includeDefaultPatterns: opts.pii?.includeDefaultPatterns ?? true,
46
- patterns: opts.pii?.patterns,
47
- redactKeys: opts.pii?.redactKeys,
48
- preserveKeys: opts.pii?.preserveKeys,
49
- });
50
- const emit = async (level, message, meta) => {
51
- if (level < minLevel)
52
- return;
53
- const msgStr = normalizeLogMessage(message, redactEnabled, redactor);
54
- const metaVal = redactEnabled ? redactor.redact(meta) : meta;
55
- const payload = {
56
- level,
57
- timestamp: Date.now(),
58
- message: msgStr, // <- garantizamos string
59
- meta: metaVal,
60
- };
61
- await ds.save(payload);
62
- };
63
- const logger = {
64
- trace: (m, meta) => emit(__1.LogLevel.TRACE, m, meta),
65
- debug: (m, meta) => emit(__1.LogLevel.DEBUG, m, meta),
66
- info: (m, meta) => emit(__1.LogLevel.INFO, m, meta),
67
- warn: (m, meta) => emit(__1.LogLevel.WARN, m, meta),
68
- error: (m, meta) => emit(__1.LogLevel.ERROR, m, meta),
69
- fatal: (m, meta) => emit(__1.LogLevel.FATAL, m, meta),
70
- flush: () => ds.flush?.() ?? Promise.resolve(),
71
- dispose: () => ds.dispose?.() ?? Promise.resolve(),
72
- };
73
- return logger;
74
- }
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-logger"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmlq/logger",
3
- "version": "0.1.0-alpha.2",
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,11 +9,23 @@
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": {
18
+ "@swc/core": "^1.13.5",
19
+ "@swc/jest": "^0.2.39",
20
+ "@types/jest": "^30.0.0",
15
21
  "@types/node": "^24.3.0",
22
+ "jest": "^30.1.3",
16
23
  "tsx": "^4.20.5",
17
24
  "typescript": "^5.9.2"
25
+ },
26
+ "overrides": {
27
+ "test-exclude": "^7.0.1",
28
+ "glob": "^10.4.5",
29
+ "minimatch": "^9.0.5"
18
30
  }
19
31
  }
@@ -1,9 +0,0 @@
1
- import { IGetLogsFilter, ILogDatasource, ILog } from "../config";
2
- export declare class CompositeDatasource implements ILogDatasource {
3
- private readonly datasources;
4
- constructor(datasources: ILogDatasource[]);
5
- save(log: ILog): Promise<void>;
6
- find(filter?: IGetLogsFilter): Promise<ILog[]>;
7
- flush(): Promise<void>;
8
- dispose(): Promise<void>;
9
- }
@@ -1,54 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CompositeDatasource = void 0;
4
- // ---- Composite fan-out ----
5
- class CompositeDatasource {
6
- constructor(datasources) {
7
- this.datasources = datasources;
8
- }
9
- async save(log) {
10
- const results = await Promise.allSettled(this.datasources.map((ds) => ds.save(log)));
11
- for (const r of results) {
12
- if (r.status === "rejected") {
13
- // Evita romper el flujo si un destino falla.
14
- // Aquí podrías enrutar a "dead-letter", métricas, etc.
15
- // eslint-disable-next-line no-console
16
- console.warn("[CompositeDatasource] save failed:", r.reason);
17
- }
18
- }
19
- }
20
- async find(filter = {}) {
21
- for (const ds of this.datasources) {
22
- if (typeof ds.find === "function") {
23
- try {
24
- return await ds.find(filter);
25
- }
26
- catch (e) {
27
- // eslint-disable-next-line no-console
28
- console.warn("[CompositeDatasource] find failed on a datasource:", e);
29
- // probar siguiente datasource
30
- }
31
- }
32
- }
33
- return [];
34
- }
35
- async flush() {
36
- const results = await Promise.allSettled(this.datasources.map((ds) => ds.flush?.() ?? Promise.resolve()));
37
- for (const r of results) {
38
- if (r.status === "rejected") {
39
- // eslint-disable-next-line no-console
40
- console.warn("[CompositeDatasource] flush failed:", r.reason);
41
- }
42
- }
43
- }
44
- async dispose() {
45
- const results = await Promise.allSettled(this.datasources.map((ds) => ds.dispose?.() ?? Promise.resolve()));
46
- for (const r of results) {
47
- if (r.status === "rejected") {
48
- // eslint-disable-next-line no-console
49
- console.warn("[CompositeDatasource] dispose failed:", r.reason);
50
- }
51
- }
52
- }
53
- }
54
- exports.CompositeDatasource = CompositeDatasource;
@@ -1,5 +0,0 @@
1
- import { ILogDatasource, Logger, LogLevel } from "..";
2
- export declare function createLogger(ds: ILogDatasource, opts: {
3
- minLevel: LogLevel;
4
- redactPII?: boolean;
5
- }): Logger;