@jmlq/logger 0.1.0-alpha.11 → 0.1.0-alpha.12
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/dist/index.d.ts +3 -0
- package/dist/index.js +20 -0
- package/package.json +5 -2
- package/dist/examples/data-source-service.example.d.ts +0 -3
- package/dist/examples/data-source-service.example.js +0 -174
- package/dist/examples/flush-buffers-use-case.example.d.ts +0 -3
- package/dist/examples/flush-buffers-use-case.example.js +0 -60
- package/dist/examples/get-logs-use-case.example.d.ts +0 -3
- package/dist/examples/get-logs-use-case.example.js +0 -110
- package/dist/examples/index.example.d.ts +0 -8
- package/dist/examples/index.example.js +0 -116
- package/dist/examples/logger-factory.example.d.ts +0 -39
- package/dist/examples/logger-factory.example.js +0 -158
- package/dist/examples/normalize-message.example.d.ts +0 -3
- package/dist/examples/normalize-message.example.js +0 -80
- package/dist/examples/pii-redactor.example.d.ts +0 -3
- package/dist/examples/pii-redactor.example.js +0 -129
- package/dist/examples/save-log-use-case.example.d.ts +0 -3
- package/dist/examples/save-log-use-case.example.js +0 -150
- package/dist/examples/to-log-level.example.d.ts +0 -3
- package/dist/examples/to-log-level.example.js +0 -49
- package/dist/examples/to-pii-regex.example.d.ts +0 -3
- package/dist/examples/to-pii-regex.example.js +0 -75
- package/dist/src/application/factory/create-logger.d.ts +0 -2
- package/dist/src/application/factory/create-logger.js +0 -29
- package/dist/src/domain/services/pii-redactor.d.ts +0 -10
- package/dist/src/domain/services/pii-redactor.js +0 -68
- package/dist/src/index.d.ts +0 -6
- package/dist/src/index.js +0 -22
- package/dist/src/infrastructure/datasources/in-memory-log.datasource.d.ts +0 -1
- package/dist/src/infrastructure/datasources/in-memory-log.datasource.js +0 -2
- package/dist/src/infrastructure/datasources/index.d.ts +0 -1
- package/dist/src/infrastructure/datasources/index.js +0 -17
- package/dist/tests/application/factory/logger-factory.spec.d.ts +0 -1
- package/dist/tests/application/factory/logger-factory.spec.js +0 -161
- package/dist/tests/application/use-cases/flush-buffers.use-case.spec.d.ts +0 -1
- package/dist/tests/application/use-cases/flush-buffers.use-case.spec.js +0 -38
- package/dist/tests/application/use-cases/get-logs.use-case.spec.d.ts +0 -1
- package/dist/tests/application/use-cases/get-logs.use-case.spec.js +0 -114
- package/dist/tests/application/use-cases/save-log.use-case.spec.d.ts +0 -1
- package/dist/tests/application/use-cases/save-log.use-case.spec.js +0 -138
- package/dist/tests/domain/services/log-level.service.spec.d.ts +0 -1
- package/dist/tests/domain/services/log-level.service.spec.js +0 -68
- package/dist/tests/domain/services/normalize-message.spec.d.ts +0 -1
- package/dist/tests/domain/services/normalize-message.spec.js +0 -83
- package/dist/tests/domain/services/pii-redactor.spec.d.ts +0 -1
- package/dist/tests/domain/services/pii-redactor.spec.js +0 -170
- package/dist/tests/domain/services/to-pii-regex.spec.d.ts +0 -1
- package/dist/tests/domain/services/to-pii-regex.spec.js +0 -82
- package/dist/tests/infrastructure/services/datasource.service.spec.d.ts +0 -1
- package/dist/tests/infrastructure/services/datasource.service.spec.js +0 -128
- package/dist/tests/test-utils/create-pii-redactor-mock.d.ts +0 -5
- package/dist/tests/test-utils/create-pii-redactor-mock.js +0 -10
- /package/dist/{src/application → application}/factory/index.d.ts +0 -0
- /package/dist/{src/application → application}/factory/index.js +0 -0
- /package/dist/{src/application → application}/factory/logger.factory.d.ts +0 -0
- /package/dist/{src/application → application}/factory/logger.factory.js +0 -0
- /package/dist/{src/application → application}/index.d.ts +0 -0
- /package/dist/{src/application → application}/index.js +0 -0
- /package/dist/{src/application → application}/use-cases/flush-buffers.use-case.d.ts +0 -0
- /package/dist/{src/application → application}/use-cases/flush-buffers.use-case.js +0 -0
- /package/dist/{src/application → application}/use-cases/get-logs.use-case.d.ts +0 -0
- /package/dist/{src/application → application}/use-cases/get-logs.use-case.js +0 -0
- /package/dist/{src/application → application}/use-cases/index.d.ts +0 -0
- /package/dist/{src/application → application}/use-cases/index.js +0 -0
- /package/dist/{src/application → application}/use-cases/save-log.use-case.d.ts +0 -0
- /package/dist/{src/application → application}/use-cases/save-log.use-case.js +0 -0
- /package/dist/{src/domain → domain}/index.d.ts +0 -0
- /package/dist/{src/domain → domain}/index.js +0 -0
- /package/dist/{src/domain → domain}/ports/create-logger-options.port.d.ts +0 -0
- /package/dist/{src/domain → domain}/ports/create-logger-options.port.js +0 -0
- /package/dist/{src/domain → domain}/ports/index.d.ts +0 -0
- /package/dist/{src/domain → domain}/ports/index.js +0 -0
- /package/dist/{src/domain → domain}/ports/log-datasource.port.d.ts +0 -0
- /package/dist/{src/domain → domain}/ports/log-datasource.port.js +0 -0
- /package/dist/{src/domain → domain}/ports/logger-factory-config.port.d.ts +0 -0
- /package/dist/{src/domain → domain}/ports/logger-factory-config.port.js +0 -0
- /package/dist/{src/domain → domain}/ports/logger-service.port.d.ts +0 -0
- /package/dist/{src/domain → domain}/ports/logger-service.port.js +0 -0
- /package/dist/{src/domain → domain}/ports/logger.port.d.ts +0 -0
- /package/dist/{src/domain → domain}/ports/logger.port.js +0 -0
- /package/dist/{src/domain → domain}/ports/pii-redactor.port.d.ts +0 -0
- /package/dist/{src/domain → domain}/ports/pii-redactor.port.js +0 -0
- /package/dist/{src/domain → domain}/request/get-logs-filter.props.d.ts +0 -0
- /package/dist/{src/domain → domain}/request/get-logs-filter.props.js +0 -0
- /package/dist/{src/domain → domain}/request/index.d.ts +0 -0
- /package/dist/{src/domain → domain}/request/index.js +0 -0
- /package/dist/{src/domain → domain}/request/log.props.d.ts +0 -0
- /package/dist/{src/domain → domain}/request/log.props.js +0 -0
- /package/dist/{src/domain → domain}/request/pii-options.props.d.ts +0 -0
- /package/dist/{src/domain → domain}/request/pii-options.props.js +0 -0
- /package/dist/{src/domain → domain}/request/pii-replacement.props.d.ts +0 -0
- /package/dist/{src/domain → domain}/request/pii-replacement.props.js +0 -0
- /package/dist/{src/domain → domain}/request/save-log.props.d.ts +0 -0
- /package/dist/{src/domain → domain}/request/save-log.props.js +0 -0
- /package/dist/{src/domain → domain}/response/index.d.ts +0 -0
- /package/dist/{src/domain → domain}/response/index.js +0 -0
- /package/dist/{src/domain → domain}/response/log.response.d.ts +0 -0
- /package/dist/{src/domain → domain}/response/log.response.js +0 -0
- /package/dist/{src/domain → domain}/services/index.d.ts +0 -0
- /package/dist/{src/domain → domain}/services/index.js +0 -0
- /package/dist/{src/domain → domain}/services/log-level.service.d.ts +0 -0
- /package/dist/{src/domain → domain}/services/log-level.service.js +0 -0
- /package/dist/{src/domain → domain}/services/message-normalizer.service.d.ts +0 -0
- /package/dist/{src/domain → domain}/services/message-normalizer.service.js +0 -0
- /package/dist/{src/domain → domain}/services/pii-pattern.service.d.ts +0 -0
- /package/dist/{src/domain → domain}/services/pii-pattern.service.js +0 -0
- /package/dist/{src/domain → domain}/services/pii-redactor.service.d.ts +0 -0
- /package/dist/{src/domain → domain}/services/pii-redactor.service.js +0 -0
- /package/dist/{src/domain → domain}/types/index.d.ts +0 -0
- /package/dist/{src/domain → domain}/types/index.js +0 -0
- /package/dist/{src/domain → domain}/types/log-message.type.d.ts +0 -0
- /package/dist/{src/domain → domain}/types/log-message.type.js +0 -0
- /package/dist/{src/domain → domain}/value-objects/index.d.ts +0 -0
- /package/dist/{src/domain → domain}/value-objects/index.js +0 -0
- /package/dist/{src/domain → domain}/value-objects/log-level.vo.d.ts +0 -0
- /package/dist/{src/domain → domain}/value-objects/log-level.vo.js +0 -0
- /package/dist/{src/infrastructure → infrastructure}/index.d.ts +0 -0
- /package/dist/{src/infrastructure → infrastructure}/index.js +0 -0
- /package/dist/{src/infrastructure → infrastructure}/services/data-source-error-handler.type.d.ts +0 -0
- /package/dist/{src/infrastructure → infrastructure}/services/data-source-error-handler.type.js +0 -0
- /package/dist/{src/infrastructure → infrastructure}/services/datasource.service.d.ts +0 -0
- /package/dist/{src/infrastructure → infrastructure}/services/datasource.service.js +0 -0
- /package/dist/{src/infrastructure → infrastructure}/services/index.d.ts +0 -0
- /package/dist/{src/infrastructure → infrastructure}/services/index.js +0 -0
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const domain_1 = require("src/domain");
|
|
4
|
-
describe("toLogLevel()", () => {
|
|
5
|
-
// --------------------------------------------------------------------------
|
|
6
|
-
// 1. Strings válidos
|
|
7
|
-
// --------------------------------------------------------------------------
|
|
8
|
-
it("debe convertir strings válidos al LogLevel correcto", () => {
|
|
9
|
-
expect((0, domain_1.toLogLevel)("trace")).toBe(domain_1.LogLevel.TRACE);
|
|
10
|
-
expect((0, domain_1.toLogLevel)("debug")).toBe(domain_1.LogLevel.DEBUG);
|
|
11
|
-
expect((0, domain_1.toLogLevel)("info")).toBe(domain_1.LogLevel.INFO);
|
|
12
|
-
expect((0, domain_1.toLogLevel)("warn")).toBe(domain_1.LogLevel.WARN);
|
|
13
|
-
expect((0, domain_1.toLogLevel)("error")).toBe(domain_1.LogLevel.ERROR);
|
|
14
|
-
expect((0, domain_1.toLogLevel)("fatal")).toBe(domain_1.LogLevel.FATAL);
|
|
15
|
-
});
|
|
16
|
-
// --------------------------------------------------------------------------
|
|
17
|
-
// 2. Insensibilidad a mayúsculas/minúsculas
|
|
18
|
-
// --------------------------------------------------------------------------
|
|
19
|
-
it("debe aceptar strings en cualquier tipo de casing", () => {
|
|
20
|
-
expect((0, domain_1.toLogLevel)("TRACE")).toBe(domain_1.LogLevel.TRACE);
|
|
21
|
-
expect((0, domain_1.toLogLevel)("DeBuG")).toBe(domain_1.LogLevel.DEBUG);
|
|
22
|
-
expect((0, domain_1.toLogLevel)("Warn")).toBe(domain_1.LogLevel.WARN);
|
|
23
|
-
});
|
|
24
|
-
// --------------------------------------------------------------------------
|
|
25
|
-
// 3. Valores numéricos válidos
|
|
26
|
-
// --------------------------------------------------------------------------
|
|
27
|
-
it("debe aceptar valores numéricos válidos del enum", () => {
|
|
28
|
-
expect((0, domain_1.toLogLevel)(domain_1.LogLevel.TRACE)).toBe(domain_1.LogLevel.TRACE);
|
|
29
|
-
expect((0, domain_1.toLogLevel)(domain_1.LogLevel.FATAL)).toBe(domain_1.LogLevel.FATAL);
|
|
30
|
-
});
|
|
31
|
-
// --------------------------------------------------------------------------
|
|
32
|
-
// 4. Valores numéricos inválidos
|
|
33
|
-
// --------------------------------------------------------------------------
|
|
34
|
-
it("debe retornar el valor por defecto si el número no pertenece al enum", () => {
|
|
35
|
-
expect((0, domain_1.toLogLevel)(999)).toBe(domain_1.LogLevel.INFO); // default implícito
|
|
36
|
-
expect((0, domain_1.toLogLevel)(999, domain_1.LogLevel.ERROR)).toBe(domain_1.LogLevel.ERROR); // default explícito
|
|
37
|
-
});
|
|
38
|
-
// --------------------------------------------------------------------------
|
|
39
|
-
// 5. Valores undefined o null
|
|
40
|
-
// --------------------------------------------------------------------------
|
|
41
|
-
it("debe usar el valor por defecto si el valor es undefined o null", () => {
|
|
42
|
-
expect((0, domain_1.toLogLevel)(undefined)).toBe(domain_1.LogLevel.INFO);
|
|
43
|
-
expect((0, domain_1.toLogLevel)(null)).toBe(domain_1.LogLevel.INFO);
|
|
44
|
-
expect((0, domain_1.toLogLevel)(undefined, domain_1.LogLevel.WARN)).toBe(domain_1.LogLevel.WARN);
|
|
45
|
-
});
|
|
46
|
-
// --------------------------------------------------------------------------
|
|
47
|
-
// 6. Strings desconocidos
|
|
48
|
-
// --------------------------------------------------------------------------
|
|
49
|
-
it("debe retornar el default si recibe un string no reconocido", () => {
|
|
50
|
-
expect((0, domain_1.toLogLevel)("unknown")).toBe(domain_1.LogLevel.INFO);
|
|
51
|
-
expect((0, domain_1.toLogLevel)("invalid-level", domain_1.LogLevel.ERROR)).toBe(domain_1.LogLevel.ERROR);
|
|
52
|
-
});
|
|
53
|
-
// --------------------------------------------------------------------------
|
|
54
|
-
// 7. Otros tipos no soportados
|
|
55
|
-
// --------------------------------------------------------------------------
|
|
56
|
-
it("debe retornar el default si recibe objetos, booleanos u otros tipos", () => {
|
|
57
|
-
expect((0, domain_1.toLogLevel)({})).toBe(domain_1.LogLevel.INFO);
|
|
58
|
-
expect((0, domain_1.toLogLevel)([])).toBe(domain_1.LogLevel.INFO);
|
|
59
|
-
expect((0, domain_1.toLogLevel)(true)).toBe(domain_1.LogLevel.INFO);
|
|
60
|
-
});
|
|
61
|
-
// --------------------------------------------------------------------------
|
|
62
|
-
// 8. Verifica que el default param funciona correctamente
|
|
63
|
-
// --------------------------------------------------------------------------
|
|
64
|
-
it("debe aplicar correctamente el default proporcionado", () => {
|
|
65
|
-
expect((0, domain_1.toLogLevel)("something", domain_1.LogLevel.WARN)).toBe(domain_1.LogLevel.WARN);
|
|
66
|
-
expect((0, domain_1.toLogLevel)(undefined, domain_1.LogLevel.FATAL)).toBe(domain_1.LogLevel.FATAL);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const domain_1 = require("src/domain");
|
|
4
|
-
describe("normalizeMessage()", () => {
|
|
5
|
-
let redactorMock;
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
redactorMock = {
|
|
8
|
-
redact: jest.fn((value) => value), // por defecto retorna lo mismo
|
|
9
|
-
};
|
|
10
|
-
});
|
|
11
|
-
// -----------------------------------------------------------------------
|
|
12
|
-
// 1️⃣ Si el mensaje es string
|
|
13
|
-
// -----------------------------------------------------------------------
|
|
14
|
-
it("debe redactor un mensaje tipo string", () => {
|
|
15
|
-
const msg = "hello world";
|
|
16
|
-
const result = (0, domain_1.normalizeMessage)(msg, redactorMock);
|
|
17
|
-
expect(redactorMock.redact).toHaveBeenCalledWith("hello world");
|
|
18
|
-
expect(result).toBe("hello world");
|
|
19
|
-
});
|
|
20
|
-
// -----------------------------------------------------------------------
|
|
21
|
-
// 2️⃣ Si el mensaje es objeto
|
|
22
|
-
// -----------------------------------------------------------------------
|
|
23
|
-
it("debe redactor un objeto", () => {
|
|
24
|
-
const msg = { user: "test", email: "a@b.com" };
|
|
25
|
-
const redactedObj = { user: "test", email: "***" };
|
|
26
|
-
// Redactor retorna un valor distinto
|
|
27
|
-
redactorMock.redact.mockReturnValue(redactedObj);
|
|
28
|
-
const result = (0, domain_1.normalizeMessage)(msg, redactorMock);
|
|
29
|
-
expect(redactorMock.redact).toHaveBeenCalledWith(msg);
|
|
30
|
-
expect(result).toEqual(redactedObj);
|
|
31
|
-
});
|
|
32
|
-
// -----------------------------------------------------------------------
|
|
33
|
-
// 3️⃣ Si el mensaje es una función perezosa
|
|
34
|
-
// -----------------------------------------------------------------------
|
|
35
|
-
it("debe evaluar funciones perezosas y redactor su resultado", () => {
|
|
36
|
-
const lazyFn = jest.fn(() => "lazy-result");
|
|
37
|
-
const result = (0, domain_1.normalizeMessage)(lazyFn, redactorMock);
|
|
38
|
-
expect(lazyFn).toHaveBeenCalledTimes(1);
|
|
39
|
-
expect(redactorMock.redact).toHaveBeenCalledWith("lazy-result");
|
|
40
|
-
expect(result).toBe("lazy-result");
|
|
41
|
-
});
|
|
42
|
-
// -----------------------------------------------------------------------
|
|
43
|
-
// 4️⃣ Función perezosa retornando un objeto
|
|
44
|
-
// -----------------------------------------------------------------------
|
|
45
|
-
it("debe procesar funciones perezosas que retornan objetos", () => {
|
|
46
|
-
const lazyObj = jest.fn(() => ({ ok: true }));
|
|
47
|
-
const result = (0, domain_1.normalizeMessage)(lazyObj, redactorMock);
|
|
48
|
-
expect(lazyObj).toHaveBeenCalledTimes(1);
|
|
49
|
-
expect(redactorMock.redact).toHaveBeenCalledWith({ ok: true });
|
|
50
|
-
expect(result).toEqual({ ok: true });
|
|
51
|
-
});
|
|
52
|
-
// -----------------------------------------------------------------------
|
|
53
|
-
// 5️⃣ El redactor puede transformar el valor
|
|
54
|
-
// -----------------------------------------------------------------------
|
|
55
|
-
it("debe retornar el valor transformado por el redactor", () => {
|
|
56
|
-
redactorMock.redact.mockReturnValue("***redacted***");
|
|
57
|
-
const result = (0, domain_1.normalizeMessage)("secret", redactorMock);
|
|
58
|
-
expect(result).toBe("***redacted***");
|
|
59
|
-
});
|
|
60
|
-
// -----------------------------------------------------------------------
|
|
61
|
-
// 6️⃣ Verifica que no ejecuta funciones más de una vez
|
|
62
|
-
// -----------------------------------------------------------------------
|
|
63
|
-
it("solo debe evaluar una vez la función perezosa", () => {
|
|
64
|
-
const lazyFn = jest.fn(() => "value");
|
|
65
|
-
(0, domain_1.normalizeMessage)(lazyFn, redactorMock);
|
|
66
|
-
(0, domain_1.normalizeMessage)(lazyFn, redactorMock);
|
|
67
|
-
// Cada llamada a normalizeMessage ejecuta UNA vez la función
|
|
68
|
-
expect(lazyFn).toHaveBeenCalledTimes(2);
|
|
69
|
-
});
|
|
70
|
-
// -----------------------------------------------------------------------
|
|
71
|
-
// 7️⃣ Mensajes complejos
|
|
72
|
-
// -----------------------------------------------------------------------
|
|
73
|
-
it("debe soportar objetos complejos anidados", () => {
|
|
74
|
-
const complexObj = {
|
|
75
|
-
user: {
|
|
76
|
-
id: 1,
|
|
77
|
-
profile: { email: "a@b.com", phone: "12345" },
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
(0, domain_1.normalizeMessage)(complexObj, redactorMock);
|
|
81
|
-
expect(redactorMock.redact).toHaveBeenCalledWith(complexObj);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const services_1 = require("../../../src/domain/services");
|
|
4
|
-
describe("PiiRedactor", () => {
|
|
5
|
-
// -------------------------------------------------------------------------
|
|
6
|
-
// 1️⃣ Desactivado: debe retornar el valor sin modificar
|
|
7
|
-
// -------------------------------------------------------------------------
|
|
8
|
-
it("debe retornar el valor original si enabled=false", () => {
|
|
9
|
-
const redactor = new services_1.PiiRedactor({ enabled: false });
|
|
10
|
-
expect(redactor.redact("secret 123")).toBe("secret 123");
|
|
11
|
-
expect(redactor.redact({ email: "a@b.com" })).toEqual({
|
|
12
|
-
email: "a@b.com",
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
// -------------------------------------------------------------------------
|
|
16
|
-
// 2️⃣ Aplicación de patrones sobre strings
|
|
17
|
-
// -------------------------------------------------------------------------
|
|
18
|
-
it("debe aplicar patrones sobre strings cuando está enabled", () => {
|
|
19
|
-
const patterns = [
|
|
20
|
-
{ pattern: "\\d+", replaceWith: "[NUM]" },
|
|
21
|
-
{ pattern: "[\\w.-]+@[\\w.-]+\\.[A-Za-z]{2,}", replaceWith: "[EMAIL]" },
|
|
22
|
-
];
|
|
23
|
-
const redactor = new services_1.PiiRedactor({ enabled: true, patterns });
|
|
24
|
-
const result = redactor.redact("Pago 123 por usuario test@example.com");
|
|
25
|
-
expect(result).toBe("Pago [NUM] por usuario [EMAIL]");
|
|
26
|
-
});
|
|
27
|
-
// -------------------------------------------------------------------------
|
|
28
|
-
// 3️⃣ Redacción profunda con objetos anidados
|
|
29
|
-
// -------------------------------------------------------------------------
|
|
30
|
-
it("debe aplicar redacción profunda en objetos con deep=true", () => {
|
|
31
|
-
const patterns = [
|
|
32
|
-
{ pattern: "\\d{10}", replaceWith: "[PHONE]" },
|
|
33
|
-
];
|
|
34
|
-
const redactor = new services_1.PiiRedactor({
|
|
35
|
-
enabled: true,
|
|
36
|
-
deep: true,
|
|
37
|
-
patterns,
|
|
38
|
-
});
|
|
39
|
-
const input = {
|
|
40
|
-
level1: {
|
|
41
|
-
phone: "0987654321",
|
|
42
|
-
nested: {
|
|
43
|
-
phone2: "0987654321",
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
const output = redactor.redact(input);
|
|
48
|
-
expect(output.level1.phone).toBe("[PHONE]");
|
|
49
|
-
expect(output.level1.nested.phone2).toBe("[PHONE]");
|
|
50
|
-
// Verifica que no muta el objeto original
|
|
51
|
-
expect(input.level1.phone).toBe("0987654321");
|
|
52
|
-
});
|
|
53
|
-
// -------------------------------------------------------------------------
|
|
54
|
-
// 4️⃣ whitelistKeys debe impedir redacción
|
|
55
|
-
// -------------------------------------------------------------------------
|
|
56
|
-
it("whitelistKeys debe evitar la redacción de claves específicas", () => {
|
|
57
|
-
const patterns = [
|
|
58
|
-
{ pattern: "\\d+", replaceWith: "*" },
|
|
59
|
-
];
|
|
60
|
-
const redactor = new services_1.PiiRedactor({
|
|
61
|
-
enabled: true,
|
|
62
|
-
patterns,
|
|
63
|
-
whitelistKeys: ["safeField"],
|
|
64
|
-
});
|
|
65
|
-
const input = {
|
|
66
|
-
safeField: "12345",
|
|
67
|
-
normalField: "12345",
|
|
68
|
-
};
|
|
69
|
-
const result = redactor.redact(input);
|
|
70
|
-
expect(result.safeField).toBe("12345"); // No redactor
|
|
71
|
-
expect(result.normalField).toBe("*"); // Sí redactor
|
|
72
|
-
});
|
|
73
|
-
// -------------------------------------------------------------------------
|
|
74
|
-
// 5️⃣ blacklistKeys debe forzar redacción total
|
|
75
|
-
// -------------------------------------------------------------------------
|
|
76
|
-
it("blacklistKeys debe forzar '[REDACTED]'", () => {
|
|
77
|
-
const redactor = new services_1.PiiRedactor({
|
|
78
|
-
enabled: true,
|
|
79
|
-
blacklistKeys: ["password"],
|
|
80
|
-
});
|
|
81
|
-
const input = {
|
|
82
|
-
password: "super-secret",
|
|
83
|
-
other: "hello",
|
|
84
|
-
};
|
|
85
|
-
const result = redactor.redact(input);
|
|
86
|
-
expect(result.password).toBe("[REDACTED]");
|
|
87
|
-
expect(result.other).toBe("hello");
|
|
88
|
-
});
|
|
89
|
-
// -------------------------------------------------------------------------
|
|
90
|
-
// 6️⃣ Redacción profunda con arrays
|
|
91
|
-
// -------------------------------------------------------------------------
|
|
92
|
-
it("debe procesar arrays de forma profunda", () => {
|
|
93
|
-
const patterns = [
|
|
94
|
-
{ pattern: "\\d+", replaceWith: "X" },
|
|
95
|
-
];
|
|
96
|
-
const redactor = new services_1.PiiRedactor({
|
|
97
|
-
enabled: true,
|
|
98
|
-
deep: true,
|
|
99
|
-
patterns,
|
|
100
|
-
});
|
|
101
|
-
const input = {
|
|
102
|
-
arr: ["123", "abc", { phone: "456" }],
|
|
103
|
-
};
|
|
104
|
-
const result = redactor.redact(input);
|
|
105
|
-
expect(result.arr[0]).toBe("X");
|
|
106
|
-
expect(result.arr[1]).toBe("abc");
|
|
107
|
-
expect(result.arr[2]).toEqual({ phone: "X" });
|
|
108
|
-
});
|
|
109
|
-
// -------------------------------------------------------------------------
|
|
110
|
-
// 7️⃣ deep=false → no debe entrar a objetos anidados
|
|
111
|
-
// -------------------------------------------------------------------------
|
|
112
|
-
it("deep=false no debe redactor objetos anidados", () => {
|
|
113
|
-
const patterns = [
|
|
114
|
-
{ pattern: "\\d+", replaceWith: "*" },
|
|
115
|
-
];
|
|
116
|
-
const redactor = new services_1.PiiRedactor({
|
|
117
|
-
enabled: true,
|
|
118
|
-
deep: false,
|
|
119
|
-
patterns,
|
|
120
|
-
});
|
|
121
|
-
const input = {
|
|
122
|
-
inner: {
|
|
123
|
-
code: "123",
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
const result = redactor.redact(input);
|
|
127
|
-
expect(result.inner.code).toBe("123"); // No redactor en objetos internos
|
|
128
|
-
});
|
|
129
|
-
// -------------------------------------------------------------------------
|
|
130
|
-
// 8️⃣ Patrón inválido → no debe romper procesamiento
|
|
131
|
-
// -------------------------------------------------------------------------
|
|
132
|
-
it("si un patrón es inválido debe usar fallback y no romper redacción", () => {
|
|
133
|
-
const patterns = [
|
|
134
|
-
{ pattern: "[invalid", replaceWith: "X" }, // inválido
|
|
135
|
-
{ pattern: "\\d+", replaceWith: "#" },
|
|
136
|
-
];
|
|
137
|
-
const redactor = new services_1.PiiRedactor({
|
|
138
|
-
enabled: true,
|
|
139
|
-
patterns,
|
|
140
|
-
});
|
|
141
|
-
const result = redactor.redact("abc123");
|
|
142
|
-
expect(result).toBe("abc#"); // Se aplicó el patrón válido
|
|
143
|
-
});
|
|
144
|
-
// -------------------------------------------------------------------------
|
|
145
|
-
// 9️⃣ updateOptions debe fusionar superficialmente props
|
|
146
|
-
// -------------------------------------------------------------------------
|
|
147
|
-
it("updateOptions debe fusionar opciones sin mutar referencia previa", () => {
|
|
148
|
-
const redactor = new services_1.PiiRedactor({
|
|
149
|
-
enabled: true,
|
|
150
|
-
deep: false,
|
|
151
|
-
});
|
|
152
|
-
redactor.updateOptions({
|
|
153
|
-
deep: true,
|
|
154
|
-
whitelistKeys: ["email"],
|
|
155
|
-
});
|
|
156
|
-
const after = redactor.props;
|
|
157
|
-
expect(after.enabled).toBe(true);
|
|
158
|
-
expect(after.deep).toBe(true);
|
|
159
|
-
expect(after.whitelistKeys).toEqual(["email"]);
|
|
160
|
-
});
|
|
161
|
-
// -------------------------------------------------------------------------
|
|
162
|
-
// 🔟 Tipos no soportados (number, boolean, function) no se redactan
|
|
163
|
-
// -------------------------------------------------------------------------
|
|
164
|
-
it("no debe redactor tipos primitivos no string/objeto", () => {
|
|
165
|
-
const redactor = new services_1.PiiRedactor({ enabled: true });
|
|
166
|
-
expect(redactor.redact(123)).toBe(123);
|
|
167
|
-
expect(redactor.redact(true)).toBe(true);
|
|
168
|
-
expect(redactor.redact(() => "hi")).toBeInstanceOf(Function);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const services_1 = require("../../../src/domain/services");
|
|
4
|
-
describe("toPiiRegex()", () => {
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
// 1️⃣ Patrón válido con flags por defecto (g)
|
|
7
|
-
// ---------------------------------------------------------------------------
|
|
8
|
-
it("debe crear un RegExp válido con flags 'g' por defecto", () => {
|
|
9
|
-
const props = {
|
|
10
|
-
pattern: "\\d+",
|
|
11
|
-
replaceWith: "[NUM]",
|
|
12
|
-
};
|
|
13
|
-
const regex = (0, services_1.toPiiRegex)(props);
|
|
14
|
-
expect(regex).toBeInstanceOf(RegExp);
|
|
15
|
-
expect(regex.source).toBe("\\d+");
|
|
16
|
-
expect(regex.flags).toBe("g");
|
|
17
|
-
const result = "abc123def456".replace(regex, props.replaceWith);
|
|
18
|
-
expect(result).toBe("abc[NUM]def[NUM]");
|
|
19
|
-
});
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
// 2️⃣ Patrón válido con flags personalizados
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
it("debe respetar los flags personalizados si son válidos", () => {
|
|
24
|
-
const props = {
|
|
25
|
-
pattern: "test",
|
|
26
|
-
flags: "gi",
|
|
27
|
-
replaceWith: "X",
|
|
28
|
-
};
|
|
29
|
-
const regex = (0, services_1.toPiiRegex)(props);
|
|
30
|
-
expect(regex.source).toBe("test");
|
|
31
|
-
expect(regex.flags).toBe("gi");
|
|
32
|
-
expect("TeSt 1, test 2".replace(regex, props.replaceWith)).toBe("X 1, X 2");
|
|
33
|
-
});
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
// 3️⃣ Patrón inválido → debe retornar el RegExp fallback /$a/
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
it("debe retornar un RegExp imposible (/\\$a/) si el patrón es inválido", () => {
|
|
38
|
-
const props = {
|
|
39
|
-
pattern: "[unclosed",
|
|
40
|
-
flags: "g",
|
|
41
|
-
replaceWith: "X",
|
|
42
|
-
};
|
|
43
|
-
const regex = (0, services_1.toPiiRegex)(props);
|
|
44
|
-
// El fallback esperado es /$a/
|
|
45
|
-
expect(regex).toBeInstanceOf(RegExp);
|
|
46
|
-
expect(regex.source).toBe("$a");
|
|
47
|
-
expect(regex.test("cualquier texto")).toBe(false);
|
|
48
|
-
});
|
|
49
|
-
// ---------------------------------------------------------------------------
|
|
50
|
-
// 4️⃣ Flags inválidos → también debe usar el fallback
|
|
51
|
-
// ---------------------------------------------------------------------------
|
|
52
|
-
it("debe usar el fallback si los flags son inválidos", () => {
|
|
53
|
-
const props = {
|
|
54
|
-
pattern: "\\d+",
|
|
55
|
-
flags: "z", // flag inválido
|
|
56
|
-
replaceWith: "X",
|
|
57
|
-
};
|
|
58
|
-
const regex = (0, services_1.toPiiRegex)(props);
|
|
59
|
-
expect(regex.source).toBe("$a");
|
|
60
|
-
expect(regex.test("123")).toBe(false);
|
|
61
|
-
});
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
// 5️⃣ Asegura que el fallback nunca hace match con ejemplos comunes
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
it("el fallback nunca debe hacer match con strings comunes", () => {
|
|
66
|
-
const props = {
|
|
67
|
-
pattern: "\\", // clarísimamente inválido
|
|
68
|
-
replaceWith: "X",
|
|
69
|
-
};
|
|
70
|
-
const regex = (0, services_1.toPiiRegex)(props);
|
|
71
|
-
const samples = [
|
|
72
|
-
"",
|
|
73
|
-
"abc",
|
|
74
|
-
"123",
|
|
75
|
-
"user@test.com",
|
|
76
|
-
"tarjeta 4111-1111-1111-1111",
|
|
77
|
-
];
|
|
78
|
-
for (const s of samples) {
|
|
79
|
-
expect(regex.test(s)).toBe(false);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const infrastructure_1 = require("src/infrastructure");
|
|
4
|
-
const src_1 = require("../../../src");
|
|
5
|
-
describe("DataSourceService", () => {
|
|
6
|
-
const log = {
|
|
7
|
-
level: src_1.LogLevel.INFO,
|
|
8
|
-
message: "test log",
|
|
9
|
-
timestamp: Date.now(),
|
|
10
|
-
meta: {
|
|
11
|
-
userId: "12345",
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
const makeDsMock = () => ({
|
|
15
|
-
name: "mock",
|
|
16
|
-
save: jest.fn(),
|
|
17
|
-
find: jest.fn(),
|
|
18
|
-
flush: jest.fn(),
|
|
19
|
-
dispose: jest.fn(),
|
|
20
|
-
});
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
jest.clearAllMocks();
|
|
23
|
-
});
|
|
24
|
-
// -------------------------------------------------------------------------
|
|
25
|
-
// SAVE
|
|
26
|
-
// -------------------------------------------------------------------------
|
|
27
|
-
test("save() debe ejecutar save en todos los datasources", async () => {
|
|
28
|
-
const ds1 = makeDsMock();
|
|
29
|
-
const ds2 = makeDsMock();
|
|
30
|
-
const service = new infrastructure_1.DataSourceService([ds1, ds2]);
|
|
31
|
-
await service.save(log);
|
|
32
|
-
expect(ds1.save).toHaveBeenCalledWith(log);
|
|
33
|
-
expect(ds2.save).toHaveBeenCalledWith(log);
|
|
34
|
-
expect(ds1.save).toHaveBeenCalledTimes(1);
|
|
35
|
-
expect(ds2.save).toHaveBeenCalledTimes(1);
|
|
36
|
-
});
|
|
37
|
-
test("save() debe continuar incluso si uno de los datasources falla y llamar al error handler", async () => {
|
|
38
|
-
const ds1 = makeDsMock();
|
|
39
|
-
const ds2 = makeDsMock();
|
|
40
|
-
ds1.save.mockResolvedValue(undefined);
|
|
41
|
-
ds2.save.mockRejectedValue(new Error("failure"));
|
|
42
|
-
const onError = jest.fn();
|
|
43
|
-
const service = new infrastructure_1.DataSourceService([ds1, ds2], onError);
|
|
44
|
-
await service.save(log);
|
|
45
|
-
expect(ds1.save).toHaveBeenCalled();
|
|
46
|
-
expect(ds2.save).toHaveBeenCalled();
|
|
47
|
-
expect(onError).toHaveBeenCalledTimes(1);
|
|
48
|
-
expect(onError).toHaveBeenCalledWith(expect.objectContaining({
|
|
49
|
-
operation: "save",
|
|
50
|
-
datasourceName: "mock",
|
|
51
|
-
}));
|
|
52
|
-
// Opcional: validar que la razón sea el Error original
|
|
53
|
-
expect(onError.mock.calls[0][0].reason).toBeInstanceOf(Error);
|
|
54
|
-
expect(onError.mock.calls[0][0].reason.message).toBe("failure");
|
|
55
|
-
});
|
|
56
|
-
// -------------------------------------------------------------------------
|
|
57
|
-
// FIND
|
|
58
|
-
// -------------------------------------------------------------------------
|
|
59
|
-
test("find() debe concatenar resultados de varios datasources y ordenarlos desc por timestamp", async () => {
|
|
60
|
-
const ds1 = makeDsMock();
|
|
61
|
-
const ds2 = makeDsMock();
|
|
62
|
-
const logs1 = [
|
|
63
|
-
{ level: src_1.LogLevel.INFO, message: "a", timestamp: 100 },
|
|
64
|
-
{ level: src_1.LogLevel.WARN, message: "b", timestamp: 300 },
|
|
65
|
-
];
|
|
66
|
-
const logs2 = [
|
|
67
|
-
{ level: src_1.LogLevel.ERROR, message: "c", timestamp: 200 },
|
|
68
|
-
];
|
|
69
|
-
ds1.find.mockResolvedValue(logs1);
|
|
70
|
-
ds2.find.mockResolvedValue(logs2);
|
|
71
|
-
const service = new infrastructure_1.DataSourceService([ds1, ds2]);
|
|
72
|
-
const result = await service.find();
|
|
73
|
-
expect(result).toHaveLength(3);
|
|
74
|
-
expect(result.map((l) => l.timestamp)).toEqual([300, 200, 100]);
|
|
75
|
-
});
|
|
76
|
-
test("find() ignora datasources que retornen error en find() y llama al error handler", async () => {
|
|
77
|
-
const ds1 = makeDsMock();
|
|
78
|
-
const ds2 = makeDsMock();
|
|
79
|
-
ds1.find.mockRejectedValue(new Error("ds1 fail"));
|
|
80
|
-
ds2.find.mockResolvedValue([
|
|
81
|
-
{ id: "1", level: src_1.LogLevel.INFO, message: "ok", timestamp: 123 },
|
|
82
|
-
]);
|
|
83
|
-
const onError = jest.fn();
|
|
84
|
-
const service = new infrastructure_1.DataSourceService([ds1, ds2], onError);
|
|
85
|
-
const result = await service.find();
|
|
86
|
-
// Sigue devolviendo solo los logs válidos
|
|
87
|
-
expect(result).toHaveLength(1);
|
|
88
|
-
expect(result[0].level).toBe(src_1.LogLevel.INFO);
|
|
89
|
-
// Y registra el error del datasource que falló
|
|
90
|
-
expect(onError).toHaveBeenCalledTimes(1);
|
|
91
|
-
expect(onError).toHaveBeenCalledWith(expect.objectContaining({
|
|
92
|
-
operation: "find",
|
|
93
|
-
datasourceName: "mock",
|
|
94
|
-
}));
|
|
95
|
-
expect(onError.mock.calls[0][0].reason).toBeInstanceOf(Error);
|
|
96
|
-
expect(onError.mock.calls[0][0].reason.message).toBe("ds1 fail");
|
|
97
|
-
});
|
|
98
|
-
// -------------------------------------------------------------------------
|
|
99
|
-
// FLUSH
|
|
100
|
-
// -------------------------------------------------------------------------
|
|
101
|
-
test("flush() debe llamar flush en todos los datasources que implementen flush()", async () => {
|
|
102
|
-
const ds1 = makeDsMock();
|
|
103
|
-
const ds2 = makeDsMock();
|
|
104
|
-
const service = new infrastructure_1.DataSourceService([ds1, ds2]);
|
|
105
|
-
await service.flush();
|
|
106
|
-
expect(ds1.flush).toHaveBeenCalledTimes(1);
|
|
107
|
-
expect(ds2.flush).toHaveBeenCalledTimes(1);
|
|
108
|
-
});
|
|
109
|
-
// -------------------------------------------------------------------------
|
|
110
|
-
// DISPOSE
|
|
111
|
-
// -------------------------------------------------------------------------
|
|
112
|
-
test("dispose() debe llamar dispose en todos los datasources", async () => {
|
|
113
|
-
const ds1 = makeDsMock();
|
|
114
|
-
const ds2 = makeDsMock();
|
|
115
|
-
const service = new infrastructure_1.DataSourceService([ds1, ds2]);
|
|
116
|
-
await service.dispose();
|
|
117
|
-
expect(ds1.dispose).toHaveBeenCalledTimes(1);
|
|
118
|
-
expect(ds2.dispose).toHaveBeenCalledTimes(1);
|
|
119
|
-
});
|
|
120
|
-
// -------------------------------------------------------------------------
|
|
121
|
-
// CONSTRUCTOR DEFENSIVO
|
|
122
|
-
// -------------------------------------------------------------------------
|
|
123
|
-
test("constructor debe filtrar targets inválidos (null/undefined)", async () => {
|
|
124
|
-
const ds1 = makeDsMock();
|
|
125
|
-
const service = new infrastructure_1.DataSourceService([ds1, null, undefined]);
|
|
126
|
-
expect(service.targets).toHaveLength(1);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createPiiRedactorMock = createPiiRedactorMock;
|
|
4
|
-
function createPiiRedactorMock() {
|
|
5
|
-
const redact = jest.fn((value) => value);
|
|
6
|
-
return {
|
|
7
|
-
redact,
|
|
8
|
-
updateOptions: jest.fn(),
|
|
9
|
-
};
|
|
10
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|