@jmlq/logger 0.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.es.md +140 -0
- package/README.md +140 -0
- package/dist/application/factory/index.d.ts +1 -0
- package/dist/application/factory/index.js +17 -0
- package/dist/application/factory/logger.factory.d.ts +11 -0
- package/dist/application/factory/logger.factory.js +71 -0
- package/dist/application/index.d.ts +2 -0
- package/dist/application/index.js +18 -0
- package/dist/application/types/index.d.ts +1 -0
- package/dist/application/types/index.js +17 -0
- package/dist/application/types/logger-factory-config.type.d.ts +28 -0
- package/dist/application/types/logger-factory-config.type.js +2 -0
- package/dist/application/use-cases/flush-buffers.use-case.d.ts +6 -0
- package/dist/application/use-cases/flush-buffers.use-case.js +13 -0
- package/dist/application/use-cases/get-logs.use-case.d.ts +8 -0
- package/dist/application/use-cases/get-logs.use-case.js +24 -0
- package/dist/application/use-cases/index.d.ts +3 -0
- package/dist/application/use-cases/index.js +19 -0
- package/dist/application/use-cases/save-log/index.d.ts +1 -0
- package/dist/application/use-cases/save-log/index.js +17 -0
- package/dist/application/use-cases/save-log/save-log.props.d.ts +7 -0
- package/dist/application/use-cases/save-log/save-log.props.js +2 -0
- package/dist/application/use-cases/save-log.use-case.d.ts +8 -0
- package/dist/application/use-cases/save-log.use-case.js +27 -0
- package/dist/domain/index.d.ts +8 -0
- package/dist/domain/index.js +24 -0
- package/dist/domain/model/index.d.ts +3 -0
- package/dist/domain/model/index.js +19 -0
- package/dist/domain/model/log-entry.model.d.ts +8 -0
- package/dist/domain/model/log-entry.model.js +2 -0
- package/dist/domain/model/pii-options.model.d.ts +8 -0
- package/dist/domain/model/pii-options.model.js +2 -0
- package/dist/domain/model/pii-replacement-rule.d.ts +5 -0
- package/dist/domain/model/pii-replacement-rule.js +2 -0
- package/dist/domain/ports/create-logger-options.port.d.ts +7 -0
- package/dist/domain/ports/create-logger-options.port.js +2 -0
- package/dist/domain/ports/index.d.ts +4 -0
- package/dist/domain/ports/index.js +20 -0
- package/dist/domain/ports/log-datasource.port.d.ts +10 -0
- package/dist/domain/ports/log-datasource.port.js +2 -0
- package/dist/domain/ports/logger.port.d.ts +15 -0
- package/dist/domain/ports/logger.port.js +2 -0
- package/dist/domain/ports/pii-redactor.port.d.ts +5 -0
- package/dist/domain/ports/pii-redactor.port.js +2 -0
- package/dist/domain/request/index.d.ts +1 -0
- package/dist/domain/request/index.js +17 -0
- package/dist/domain/request/log-filter.request.d.ts +9 -0
- package/dist/domain/request/log-filter.request.js +2 -0
- package/dist/domain/response/index.d.ts +1 -0
- package/dist/domain/response/index.js +17 -0
- package/dist/domain/response/log.response.d.ts +8 -0
- package/dist/domain/response/log.response.js +2 -0
- package/dist/domain/services/index.d.ts +1 -0
- package/dist/domain/services/index.js +17 -0
- package/dist/domain/services/pii-redactor.service.d.ts +10 -0
- package/dist/domain/services/pii-redactor.service.js +68 -0
- package/dist/domain/types/index.d.ts +1 -0
- package/dist/domain/types/index.js +17 -0
- package/dist/domain/types/log-message.type.d.ts +1 -0
- package/dist/domain/types/log-message.type.js +2 -0
- package/dist/domain/utils/index.d.ts +3 -0
- package/dist/domain/utils/index.js +19 -0
- package/dist/domain/utils/normalize-message.util.d.ts +3 -0
- package/dist/domain/utils/normalize-message.util.js +8 -0
- package/dist/domain/utils/parse-log-level.util.d.ts +2 -0
- package/dist/domain/utils/parse-log-level.util.js +27 -0
- package/dist/domain/utils/pii-regex.util.d.ts +2 -0
- package/dist/domain/utils/pii-regex.util.js +13 -0
- package/dist/domain/value-objects/index.d.ts +1 -0
- package/dist/domain/value-objects/index.js +17 -0
- package/dist/domain/value-objects/log-level.vo.d.ts +8 -0
- package/dist/domain/value-objects/log-level.vo.js +13 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +45 -0
- package/dist/infrastructure/index.d.ts +1 -0
- package/dist/infrastructure/index.js +17 -0
- package/dist/infrastructure/services/datasource.service.d.ts +18 -0
- package/dist/infrastructure/services/datasource.service.js +102 -0
- package/dist/infrastructure/services/index.d.ts +1 -0
- package/dist/infrastructure/services/index.js +17 -0
- package/dist/infrastructure/types/index.d.ts +1 -0
- package/dist/infrastructure/types/index.js +17 -0
- package/dist/infrastructure/types/on-data-source-error.type.d.ts +5 -0
- package/dist/infrastructure/types/on-data-source-error.type.js +2 -0
- package/package.json +42 -0
package/README.es.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# @jmlq/logger 🧩
|
|
2
|
+
|
|
3
|
+
## 🎯 Objetivo
|
|
4
|
+
|
|
5
|
+
Proveer un **logger desacoplado del framework** (Express hoy, otro mañana) que:
|
|
6
|
+
|
|
7
|
+
- Expone una API simple (`trace|debug|info|warn|error|fatal`).
|
|
8
|
+
- Persiste logs a través de uno o varios **datasources** (`ILogDatasource`).
|
|
9
|
+
- Permite **redacción de PII** (datos sensibles) antes de persistir.
|
|
10
|
+
|
|
11
|
+
## ⭐ Importancia
|
|
12
|
+
|
|
13
|
+
- **Clean Architecture real**: el core no depende de Express, Mongo, Postgres ni filesystem.
|
|
14
|
+
- **Fan-out** (multi-datasource) sin que el host tenga que duplicar lógica.
|
|
15
|
+
- **PII-by-design**: el mensaje y los metadatos pueden pasar por un redactor antes de salir del proceso.
|
|
16
|
+
|
|
17
|
+
## 🏗️ Arquitectura (visión rápida)
|
|
18
|
+
|
|
19
|
+
➡️ Ver detalle en: [architecture.md](./docs/es/architecture.md)
|
|
20
|
+
|
|
21
|
+
## 🔧 Implementación
|
|
22
|
+
|
|
23
|
+
### 5.1 Instalación
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm i @jmlq/logger
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Para persistencia real, instala un plugin datasource (opcional):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm i @jmlq/logger-plugin-fs
|
|
33
|
+
# o
|
|
34
|
+
npm i @jmlq/logger-plugin-mongo
|
|
35
|
+
# o
|
|
36
|
+
npm i @jmlq/logger-plugin-postgresql
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 5.2 Dependencias
|
|
40
|
+
|
|
41
|
+
- **Runtime**: el core se mantiene minimalista (no integra I/O directamente).
|
|
42
|
+
- **Plugins**: integran con filesystem / MongoDB / PostgreSQL y exponen un `ILogDatasource` compatible.
|
|
43
|
+
|
|
44
|
+
### 5.3 Quickstart (implementación rápida)
|
|
45
|
+
|
|
46
|
+
Ejemplo funcional usando el plugin de filesystem (datasource real):
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { createLogger, LogLevel, type PiiRedactorOptions } from "@jmlq/logger";
|
|
50
|
+
import { createFsDatasource } from "@jmlq/logger-plugin-fs";
|
|
51
|
+
|
|
52
|
+
const pii: PiiRedactorOptions = {
|
|
53
|
+
enabled: true,
|
|
54
|
+
blacklistKeys: ["password", "token"],
|
|
55
|
+
patterns: [
|
|
56
|
+
// email
|
|
57
|
+
{
|
|
58
|
+
pattern: "[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}",
|
|
59
|
+
flags: "ig",
|
|
60
|
+
replaceWith: "[EMAIL]",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
deep: true,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const fsDatasource = createFsDatasource({
|
|
67
|
+
basePath: "./logs",
|
|
68
|
+
mkdir: true,
|
|
69
|
+
rotation: { by: "day" },
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const logger = createLogger({
|
|
73
|
+
datasources: fsDatasource,
|
|
74
|
+
minLevel: LogLevel.INFO,
|
|
75
|
+
redactorOptions: pii,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await logger.info("server.started", {
|
|
79
|
+
port: 3000,
|
|
80
|
+
adminEmail: "admin@example.com",
|
|
81
|
+
});
|
|
82
|
+
await logger.warn(() => ({ msg: "suspicious.payload", token: "secret" }));
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 5.4 Variables de entorno (.env) 📦
|
|
86
|
+
|
|
87
|
+
`@jmlq/logger` **no lee variables de entorno internamente**. La configuración se hace con código, pasando `ILoggerFactoryConfig` a `createLogger()`.
|
|
88
|
+
|
|
89
|
+
Si tu host prefiere configurar por `.env`, un patrón típico es mapear `process.env` → `LoggerFactoryConfig`:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { createLogger, LoggerUtils, LogLevel } from "@jmlq/logger";
|
|
93
|
+
|
|
94
|
+
const minLevel: LogLevel = LoggerUtils.parseLogLevel(
|
|
95
|
+
process.env.LOG_LEVEL,
|
|
96
|
+
LogLevel.INFO,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// ...construye uno o más datasources según tu host
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 5.5 Helpers y funcionalidades clave
|
|
103
|
+
|
|
104
|
+
- **Fan-out multi-datasource**
|
|
105
|
+
- Si pasas `datasources: ILogDatasource[]`, el core compone un datasource “composite” (`DataSourceService`) y hace fan-out a todos los destinos.
|
|
106
|
+
- Además, indexa en memoria lo escrito para soportar `getLogs()` incluso si algún datasource no implementa `find()`.
|
|
107
|
+
|
|
108
|
+
- **PII Redaction (PiiRedactor)**
|
|
109
|
+
- Redacta `message` y `meta`.
|
|
110
|
+
- Soporta `patterns` (RegExp serializable), `whitelistKeys`, `blacklistKeys` y `deep`.
|
|
111
|
+
|
|
112
|
+
- **Mensaje perezoso (lazy message)**
|
|
113
|
+
- `logger.info(() => ({ ... }))` evalúa el mensaje solo si el nivel pasa el filtro.
|
|
114
|
+
|
|
115
|
+
## ✅ Checklist (pasos rápidos)
|
|
116
|
+
|
|
117
|
+
- [Instalar](#51-instalación)
|
|
118
|
+
- [Elegir un datasource](./docs/es/configuration.md#datasources-y-plugins)
|
|
119
|
+
- [Configurar PII](./docs/es/configuration.md#pii-redaction)
|
|
120
|
+
- [Integrar en Express](./docs/es/integration-express.md)
|
|
121
|
+
- [Checklist de troubleshooting](./docs/es/troubleshooting.md)
|
|
122
|
+
|
|
123
|
+
## 📌 Menú
|
|
124
|
+
|
|
125
|
+
- [Arquitectura](./docs/es/architecture.md)
|
|
126
|
+
- [Configuración](./docs/es/configuration.md)
|
|
127
|
+
- [Integración Express](./docs/es/integration-express.md)
|
|
128
|
+
- [Troubleshooting](./docs/es/troubleshooting.md)
|
|
129
|
+
|
|
130
|
+
## 🔗 Referencias
|
|
131
|
+
|
|
132
|
+
Plugins de persistencia:
|
|
133
|
+
|
|
134
|
+
- [`@jmlq/logger-plugin-fs`](https://github.com/MLahuasi/jmlq-logger-plugin-fs#readme)
|
|
135
|
+
- [`@jmlq/logger-plugin-mongo`](https://github.com/MLahuasi/jmlq-logger-plugin-mongo#readme)
|
|
136
|
+
- [`@jmlq/logger-plugin-postgresql`](https://github.com/MLahuasi/jmlq-logger-plugin-postgresql#readme)
|
|
137
|
+
|
|
138
|
+
## ⬅️ 🌐 Ecosistema
|
|
139
|
+
|
|
140
|
+
- [`@jmlq`](https://github.com/MLahuasi/jmlq-ecosystem#readme)
|
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# @jmlq/logger 🧩
|
|
2
|
+
|
|
3
|
+
## 🎯 Objective
|
|
4
|
+
|
|
5
|
+
Provide a **framework-agnostic logger** (Express today, something else tomorrow) that:
|
|
6
|
+
|
|
7
|
+
- Exposes a simple API (`trace|debug|info|warn|error|fatal`)
|
|
8
|
+
- Persists logs through one or more **datasources** (`ILogDatasource`)
|
|
9
|
+
- Supports **PII redaction** (sensitive data) before persisting
|
|
10
|
+
|
|
11
|
+
## ⭐ Importance
|
|
12
|
+
|
|
13
|
+
- **Real Clean Architecture**: the core does not depend on Express, Mongo, Postgres, or filesystem
|
|
14
|
+
- **Fan-out** (multi-datasource) without duplicating logic in the host
|
|
15
|
+
- **PII-by-design**: message and metadata can be processed by a redactor before leaving the process
|
|
16
|
+
|
|
17
|
+
## 🏗️ Architecture (quick view)
|
|
18
|
+
|
|
19
|
+
➡️ See details: [architecture.md](./docs/en/architecture.md)
|
|
20
|
+
|
|
21
|
+
## 🔧 Implementation
|
|
22
|
+
|
|
23
|
+
### 5.1 Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm i @jmlq/logger
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For real persistence, install a datasource plugin (optional):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm i @jmlq/logger-plugin-fs
|
|
33
|
+
# or
|
|
34
|
+
npm i @jmlq/logger-plugin-mongo
|
|
35
|
+
# or
|
|
36
|
+
npm i @jmlq/logger-plugin-postgresql
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 5.2 Dependencies
|
|
40
|
+
|
|
41
|
+
- **Runtime**: the core remains minimal (no direct I/O integration)
|
|
42
|
+
- **Plugins**: integrate with filesystem / MongoDB / PostgreSQL and expose a compatible `ILogDatasource`
|
|
43
|
+
|
|
44
|
+
### 5.3 Quickstart (rapid implementation)
|
|
45
|
+
|
|
46
|
+
Example using the filesystem plugin (real datasource):
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { createLogger, LogLevel, type PiiRedactorOptions } from "@jmlq/logger";
|
|
50
|
+
import { createFsDatasource } from "@jmlq/logger-plugin-fs";
|
|
51
|
+
|
|
52
|
+
const pii: PiiRedactorOptions = {
|
|
53
|
+
enabled: true,
|
|
54
|
+
blacklistKeys: ["password", "token"],
|
|
55
|
+
patterns: [
|
|
56
|
+
// email
|
|
57
|
+
{
|
|
58
|
+
pattern: "[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}",
|
|
59
|
+
flags: "ig",
|
|
60
|
+
replaceWith: "[EMAIL]",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
deep: true,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const fsDatasource = createFsDatasource({
|
|
67
|
+
basePath: "./logs",
|
|
68
|
+
mkdir: true,
|
|
69
|
+
rotation: { by: "day" },
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const logger = createLogger({
|
|
73
|
+
datasources: fsDatasource,
|
|
74
|
+
minLevel: LogLevel.INFO,
|
|
75
|
+
redactorOptions: pii,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await logger.info("server.started", {
|
|
79
|
+
port: 3000,
|
|
80
|
+
adminEmail: "admin@example.com",
|
|
81
|
+
});
|
|
82
|
+
await logger.warn(() => ({ msg: "suspicious.payload", token: "secret" }));
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 5.4 Environment variables (.env) 📦
|
|
86
|
+
|
|
87
|
+
`@jmlq/logger` **does not read environment variables internally**. Configuration is done in code by passing `ILoggerFactoryConfig` to `createLogger()`.
|
|
88
|
+
|
|
89
|
+
If your host prefers `.env`, a typical pattern is mapping `process.env` → `LoggerFactoryConfig`:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { createLogger, LoggerUtils, LogLevel } from "@jmlq/logger";
|
|
93
|
+
|
|
94
|
+
const minLevel: LogLevel = LoggerUtils.parseLogLevel(
|
|
95
|
+
process.env.LOG_LEVEL,
|
|
96
|
+
LogLevel.INFO,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// ...build one or more datasources depending on your host
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 5.5 Helpers and key features
|
|
103
|
+
|
|
104
|
+
- **Multi-datasource fan-out**
|
|
105
|
+
- If you pass `datasources: ILogDatasource[]`, the core composes a “composite” datasource (`DataSourceService`) and fans out to all targets
|
|
106
|
+
- It also keeps an in-memory index of written logs to support `getLogs()` even if a datasource does not implement `find()`
|
|
107
|
+
|
|
108
|
+
- **PII Redaction (PiiRedactor)**
|
|
109
|
+
- Redacts `message` and `meta`
|
|
110
|
+
- Supports `patterns` (serializable RegExp), `whitelistKeys`, `blacklistKeys`, and `deep`
|
|
111
|
+
|
|
112
|
+
- **Lazy message**
|
|
113
|
+
- `logger.info(() => ({ ... }))` evaluates the message only if the level passes the filter
|
|
114
|
+
|
|
115
|
+
## ✅ Checklist (quick steps)
|
|
116
|
+
|
|
117
|
+
- [Install](#51-installation)
|
|
118
|
+
- [Choose a datasource](./docs/en/configuration.md#datasources-and-plugins)
|
|
119
|
+
- [Configure PII](./docs/en/configuration.md#pii-redaction)
|
|
120
|
+
- [Integrate with Express](./docs/en/integration-express.md)
|
|
121
|
+
- [Troubleshooting checklist](./docs/en/troubleshooting.md)
|
|
122
|
+
|
|
123
|
+
## 📌 Menu
|
|
124
|
+
|
|
125
|
+
- [Architecture](./docs/en/architecture.md)
|
|
126
|
+
- [Configuration](./docs/en/configuration.md)
|
|
127
|
+
- [Express Integration](./docs/en/integration-express.md)
|
|
128
|
+
- [Troubleshooting](./docs/en/troubleshooting.md)
|
|
129
|
+
|
|
130
|
+
## 🔗 References
|
|
131
|
+
|
|
132
|
+
Persistence plugins:
|
|
133
|
+
|
|
134
|
+
- [`@jmlq/logger-plugin-fs`](https://github.com/MLahuasi/jmlq-logger-plugin-fs#readme)
|
|
135
|
+
- [`@jmlq/logger-plugin-mongo`](https://github.com/MLahuasi/jmlq-logger-plugin-mongo#readme)
|
|
136
|
+
- [`@jmlq/logger-plugin-postgresql`](https://github.com/MLahuasi/jmlq-logger-plugin-postgresql#readme)
|
|
137
|
+
|
|
138
|
+
## ⬅️ 🌐 Ecosystem
|
|
139
|
+
|
|
140
|
+
- [`@jmlq`](https://github.com/MLahuasi/jmlq-ecosystem#readme)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./logger.factory";
|
|
@@ -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("./logger.factory"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ILogger } from "../../domain/ports";
|
|
2
|
+
import { ILoggerFactoryConfig } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Factory principal de @jmlq/logger.
|
|
5
|
+
* Se encarga de:
|
|
6
|
+
* - Componer datasources (fan-out si hay varios)
|
|
7
|
+
* - Construir el redactor de PII
|
|
8
|
+
* - Instanciar y conectar los casos de uso
|
|
9
|
+
* - Exponer un servicio de logger de alto nivel
|
|
10
|
+
*/
|
|
11
|
+
export declare function createLogger(config: ILoggerFactoryConfig, source?: string): ILogger;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createLogger = createLogger;
|
|
4
|
+
const value_objects_1 = require("../../domain/value-objects");
|
|
5
|
+
const pii_redactor_service_1 = require("../../domain/services/pii-redactor.service");
|
|
6
|
+
const services_1 = require("../../infrastructure/services");
|
|
7
|
+
const use_cases_1 = require("../use-cases");
|
|
8
|
+
/**
|
|
9
|
+
* Factory principal de @jmlq/logger.
|
|
10
|
+
* Se encarga de:
|
|
11
|
+
* - Componer datasources (fan-out si hay varios)
|
|
12
|
+
* - Construir el redactor de PII
|
|
13
|
+
* - Instanciar y conectar los casos de uso
|
|
14
|
+
* - Exponer un servicio de logger de alto nivel
|
|
15
|
+
*/
|
|
16
|
+
function createLogger(config, source = "app-logger") {
|
|
17
|
+
// 1) Normalizar config
|
|
18
|
+
const minLevel = config.minLevel ?? value_objects_1.LogLevel.INFO;
|
|
19
|
+
const datasources = Array.isArray(config.datasources)
|
|
20
|
+
? config.datasources
|
|
21
|
+
: [config.datasources];
|
|
22
|
+
// 2) Componer datasource (si hay varios) con DataSourceService
|
|
23
|
+
const ds = datasources.length === 1
|
|
24
|
+
? datasources[0]
|
|
25
|
+
: new services_1.DataSourceService(datasources);
|
|
26
|
+
// 3) Crear/usar redactor de PII
|
|
27
|
+
const redactor = config.redactor ?? new pii_redactor_service_1.PiiRedactor(config.redactorOptions);
|
|
28
|
+
// 4) Construir casos de uso de Application
|
|
29
|
+
const saveLogUseCase = new use_cases_1.SaveLogUseCase({
|
|
30
|
+
ds,
|
|
31
|
+
minLevel,
|
|
32
|
+
redactor,
|
|
33
|
+
});
|
|
34
|
+
const getLogsUseCase = new use_cases_1.GetLogsUseCase(ds);
|
|
35
|
+
const flushBuffersUseCase = new use_cases_1.FlushBuffersUseCase(ds);
|
|
36
|
+
// 5) Construir facade de servicio de logging
|
|
37
|
+
const service = {
|
|
38
|
+
// Método genérico de logging
|
|
39
|
+
async log(level, message, meta) {
|
|
40
|
+
await saveLogUseCase.execute("app-logger", level, message, meta);
|
|
41
|
+
},
|
|
42
|
+
// Helpers por nivel
|
|
43
|
+
trace(message, meta) {
|
|
44
|
+
return saveLogUseCase.execute(source, value_objects_1.LogLevel.TRACE, message, meta);
|
|
45
|
+
},
|
|
46
|
+
debug(message, meta) {
|
|
47
|
+
return saveLogUseCase.execute(source, value_objects_1.LogLevel.DEBUG, message, meta);
|
|
48
|
+
},
|
|
49
|
+
info(message, meta) {
|
|
50
|
+
return saveLogUseCase.execute(source, value_objects_1.LogLevel.INFO, message, meta);
|
|
51
|
+
},
|
|
52
|
+
warn(message, meta) {
|
|
53
|
+
return saveLogUseCase.execute(source, value_objects_1.LogLevel.WARN, message, meta);
|
|
54
|
+
},
|
|
55
|
+
error(message, meta) {
|
|
56
|
+
return saveLogUseCase.execute(source, value_objects_1.LogLevel.ERROR, message, meta);
|
|
57
|
+
},
|
|
58
|
+
fatal(message, meta) {
|
|
59
|
+
return saveLogUseCase.execute(source, value_objects_1.LogLevel.FATAL, message, meta);
|
|
60
|
+
},
|
|
61
|
+
// Lectura de logs con filtros
|
|
62
|
+
async getLogs(filter) {
|
|
63
|
+
return getLogsUseCase.execute(filter);
|
|
64
|
+
},
|
|
65
|
+
// Flush explícito (si el datasource lo soporta)
|
|
66
|
+
async flush() {
|
|
67
|
+
await flushBuffersUseCase.execute();
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
return service;
|
|
71
|
+
}
|
|
@@ -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("./factory"), exports);
|
|
18
|
+
__exportStar(require("./use-cases"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./logger-factory-config.type";
|
|
@@ -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("./logger-factory-config.type"), exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ILogDatasource, IPiiRedactor } from "../../domain/ports";
|
|
2
|
+
import { PiiOptions } from "../../domain/model";
|
|
3
|
+
import { LogLevel } from "../../domain/value-objects";
|
|
4
|
+
/**
|
|
5
|
+
* Configuración de alto nivel para construir el logger.
|
|
6
|
+
* Es lo que recibe el usuario del paquete npm.
|
|
7
|
+
*/
|
|
8
|
+
export interface ILoggerFactoryConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Datasource(s) concretos donde se van a persistir los logs.
|
|
11
|
+
* Pueden venir uno o varios; si hay más de uno se compone con DataSourceService (fan-out).
|
|
12
|
+
*/
|
|
13
|
+
datasources: ILogDatasource | ILogDatasource[];
|
|
14
|
+
/**
|
|
15
|
+
* Nivel mínimo de logging. Por defecto: INFO.
|
|
16
|
+
*/
|
|
17
|
+
minLevel?: LogLevel;
|
|
18
|
+
/**
|
|
19
|
+
* Instancia de redactor de PII personalizada.
|
|
20
|
+
* Si no se proporciona, se creará internamente un PiiRedactor con las opciones dadas.
|
|
21
|
+
*/
|
|
22
|
+
redactor?: IPiiRedactor;
|
|
23
|
+
/**
|
|
24
|
+
* Opciones para el redactor de PII interno.
|
|
25
|
+
* Solo se usan si no se pasa `redactor` explícito.
|
|
26
|
+
*/
|
|
27
|
+
redactorOptions?: PiiOptions;
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FlushBuffersUseCase = void 0;
|
|
4
|
+
class FlushBuffersUseCase {
|
|
5
|
+
constructor(ds) {
|
|
6
|
+
this.ds = ds;
|
|
7
|
+
}
|
|
8
|
+
async execute() {
|
|
9
|
+
// flush es opcional; si no está implementado, no hace nada
|
|
10
|
+
await this.ds.flush?.();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.FlushBuffersUseCase = FlushBuffersUseCase;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ILogDatasource } from "../../domain/ports";
|
|
2
|
+
import { LogFilterRequest } from "../../domain/request";
|
|
3
|
+
import { ILogResponse } from "../../domain/response";
|
|
4
|
+
export declare class GetLogsUseCase {
|
|
5
|
+
private readonly ds;
|
|
6
|
+
constructor(ds: ILogDatasource);
|
|
7
|
+
execute(filter?: LogFilterRequest): Promise<ILogResponse[]>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetLogsUseCase = void 0;
|
|
4
|
+
class GetLogsUseCase {
|
|
5
|
+
constructor(ds) {
|
|
6
|
+
this.ds = ds;
|
|
7
|
+
}
|
|
8
|
+
async execute(filter) {
|
|
9
|
+
if (!this.ds.find)
|
|
10
|
+
return []; // si el datasource no lo soporta, retorna vacío
|
|
11
|
+
// Sanitiza límites (evita valores negativos o absurdos)
|
|
12
|
+
const safe = filter
|
|
13
|
+
? {
|
|
14
|
+
...filter,
|
|
15
|
+
limit: filter.limit && filter.limit > 0
|
|
16
|
+
? Math.min(filter.limit, 5000)
|
|
17
|
+
: undefined,
|
|
18
|
+
offset: filter.offset && filter.offset >= 0 ? filter.offset : undefined,
|
|
19
|
+
}
|
|
20
|
+
: undefined;
|
|
21
|
+
return this.ds.find(safe);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.GetLogsUseCase = GetLogsUseCase;
|
|
@@ -0,0 +1,19 @@
|
|
|
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("./save-log.use-case"), exports);
|
|
18
|
+
__exportStar(require("./get-logs.use-case"), exports);
|
|
19
|
+
__exportStar(require("./flush-buffers.use-case"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./save-log.props";
|
|
@@ -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("./save-log.props"), exports);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LogMessage } from "../../domain/types";
|
|
2
|
+
import { LogLevel } from "../../domain/value-objects";
|
|
3
|
+
import { SaveLogDependencies } from "./save-log";
|
|
4
|
+
export declare class SaveLogUseCase {
|
|
5
|
+
private readonly props;
|
|
6
|
+
constructor(props: SaveLogDependencies);
|
|
7
|
+
execute(source: string, level: LogLevel, message: LogMessage, meta?: unknown): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SaveLogUseCase = void 0;
|
|
4
|
+
const utils_1 = require("../../domain/utils");
|
|
5
|
+
class SaveLogUseCase {
|
|
6
|
+
constructor(props) {
|
|
7
|
+
this.props = props;
|
|
8
|
+
}
|
|
9
|
+
async execute(source, level, message, meta) {
|
|
10
|
+
// 1) Filtro por nivel (evita hacer trabajo innecesario)
|
|
11
|
+
if (level < this.props.minLevel)
|
|
12
|
+
return; // no se loggea
|
|
13
|
+
// 2) Normalización + PII
|
|
14
|
+
const normalized = (0, utils_1.normalizeMessage)(message, this.props.redactor);
|
|
15
|
+
// 3) Construcción del evento
|
|
16
|
+
const log = {
|
|
17
|
+
source,
|
|
18
|
+
level,
|
|
19
|
+
message: normalized,
|
|
20
|
+
meta: meta === undefined ? undefined : this.props.redactor.redact(meta),
|
|
21
|
+
timestamp: Date.now(),
|
|
22
|
+
};
|
|
23
|
+
// 4) Persistencia (fan-out lo maneja el ds si es composite)
|
|
24
|
+
await this.props.ds.save(log);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.SaveLogUseCase = SaveLogUseCase;
|
|
@@ -0,0 +1,24 @@
|
|
|
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("./ports"), exports);
|
|
18
|
+
__exportStar(require("./request"), exports);
|
|
19
|
+
__exportStar(require("./response"), exports);
|
|
20
|
+
__exportStar(require("./services"), exports);
|
|
21
|
+
__exportStar(require("./types"), exports);
|
|
22
|
+
__exportStar(require("./value-objects"), exports);
|
|
23
|
+
__exportStar(require("./model"), exports);
|
|
24
|
+
__exportStar(require("./utils"), exports);
|