@mks2508/better-logger 0.18.2-alpha.1 → 0.18.3
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.md +38 -336
- package/dist/Logger.d.ts +356 -157
- package/dist/Logger.d.ts.map +1 -1
- package/dist/ScopedLogger.d.ts +549 -9
- package/dist/ScopedLogger.d.ts.map +1 -1
- package/dist/chunks/HookBridge-C-AvXmPD.cjs +504 -0
- package/dist/chunks/HookBridge-C-AvXmPD.cjs.map +1 -0
- package/dist/chunks/HookBridge-CI2PH79S.js +487 -0
- package/dist/chunks/HookBridge-CI2PH79S.js.map +1 -0
- package/dist/chunks/{LogContext-L7HzynFw.cjs → LogContext-BaMXleWj.cjs} +19 -4
- package/dist/chunks/LogContext-BaMXleWj.cjs.map +1 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs +141 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs.map +1 -0
- package/dist/chunks/{LogContext-Cwn-1Zzb.js → LogContext-DjlITOzZ.js} +19 -4
- package/dist/chunks/LogContext-DjlITOzZ.js.map +1 -0
- package/dist/chunks/LogContext-Dyzs61XG.js +136 -0
- package/dist/chunks/LogContext-Dyzs61XG.js.map +1 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js +393 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js.map +1 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs +410 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs.map +1 -0
- package/dist/chunks/{StyleManager-CIpd6wbO.cjs → StyleManager-DQ6UNRB-.cjs} +37 -11
- package/dist/chunks/StyleManager-DQ6UNRB-.cjs.map +1 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js +113 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js.map +1 -0
- package/dist/chunks/{core-PoT7RrTK.js → core-Blfi2klP.js} +1 -4
- package/dist/chunks/core-Blfi2klP.js.map +1 -0
- package/dist/chunks/{core-Dzz7agGa.cjs → core-CqS_UBzJ.cjs} +1 -4
- package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
- package/dist/chunks/{environment-detector-CI3TrWK_.js → environment-detector-7NvnYUfr.js} +11 -11
- package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
- package/dist/chunks/{environment-detector-Cnn6wr6O.cjs → environment-detector-D-tHkKWA.cjs} +11 -11
- package/dist/chunks/environment-detector-D-tHkKWA.cjs.map +1 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs +119 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs.map +1 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js +114 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js.map +1 -0
- package/dist/chunks/{spinner-DNvxbM9a.cjs → spinner-BHyYEXsM.cjs} +319 -37
- package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
- package/dist/chunks/{spinner-D3FsF78o.js → spinner-BtkwpzYv.js} +319 -37
- package/dist/chunks/spinner-BtkwpzYv.js.map +1 -0
- package/dist/chunks/styling-CRw3KQW4.js +1592 -0
- package/dist/chunks/styling-CRw3KQW4.js.map +1 -0
- package/dist/chunks/styling-Cel2wPRy.cjs +1645 -0
- package/dist/chunks/styling-Cel2wPRy.cjs.map +1 -0
- package/dist/chunks/transports-BGfwwakw.js +1237 -0
- package/dist/chunks/transports-BGfwwakw.js.map +1 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs +1450 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs.map +1 -0
- package/dist/chunks/transports-DvaLAeGJ.js +1403 -0
- package/dist/chunks/transports-DvaLAeGJ.js.map +1 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs +1278 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
- package/dist/chunks/{utils-BqlFYocD.cjs → utils-W_cxqriN.cjs} +44 -37
- package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
- package/dist/chunks/{utils-VETbVpkR.js → utils-tKfBAWUM.js} +44 -37
- package/dist/chunks/utils-tKfBAWUM.js.map +1 -0
- package/dist/cli/CommandProcessor.d.ts +166 -19
- package/dist/cli/CommandProcessor.d.ts.map +1 -1
- package/dist/cli/commands/ConfigCommand.d.ts +36 -1
- package/dist/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/dist/cli/commands/ExportCommand.d.ts +49 -3
- package/dist/cli/commands/ExportCommand.d.ts.map +1 -1
- package/dist/cli/commands/ThemeCommand.d.ts +62 -3
- package/dist/cli/commands/ThemeCommand.d.ts.map +1 -1
- package/dist/cli/help.d.ts +30 -2
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.d.ts +29 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli.cjs +2 -2
- package/dist/cli.js +2 -2
- package/dist/context/LogContext.d.ts +167 -70
- package/dist/context/LogContext.d.ts.map +1 -1
- package/dist/context.cjs +1 -1
- package/dist/context.js +1 -1
- package/dist/core.cjs +52 -29
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +50 -27
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +52 -29
- package/dist/core.js.map +1 -1
- package/dist/hooks/HookBridge.d.ts +15 -9
- package/dist/hooks/HookBridge.d.ts.map +1 -1
- package/dist/hooks/HookManager.d.ts +295 -2
- package/dist/hooks/HookManager.d.ts.map +1 -1
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.cjs +1415 -214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1413 -215
- package/dist/index.js.map +1 -1
- package/dist/playground/TerminalBridge.d.ts +23 -16
- package/dist/playground/TerminalBridge.d.ts.map +1 -1
- package/dist/playground/box.d.ts +36 -5
- package/dist/playground/box.d.ts.map +1 -1
- package/dist/playground/cli-table.d.ts +41 -5
- package/dist/playground/cli-table.d.ts.map +1 -1
- package/dist/playground/divider.d.ts +22 -3
- package/dist/playground/divider.d.ts.map +1 -1
- package/dist/playground/header.d.ts +21 -4
- package/dist/playground/header.d.ts.map +1 -1
- package/dist/playground/server-fallback.d.ts +96 -9
- package/dist/playground/server-fallback.d.ts.map +1 -1
- package/dist/playground/spinner.d.ts +159 -10
- package/dist/playground/spinner.d.ts.map +1 -1
- package/dist/playground/step.d.ts +25 -6
- package/dist/playground/step.d.ts.map +1 -1
- package/dist/playground.cjs +1 -1
- package/dist/playground.js +1 -1
- package/dist/serializers/SerializerBridge.d.ts +13 -6
- package/dist/serializers/SerializerBridge.d.ts.map +1 -1
- package/dist/serializers/SerializerRegistry.d.ts +236 -0
- package/dist/serializers/SerializerRegistry.d.ts.map +1 -1
- package/dist/serializers.cjs +1 -1
- package/dist/serializers.js +1 -1
- package/dist/styles/StyleManager.d.ts +138 -31
- package/dist/styles/StyleManager.d.ts.map +1 -1
- package/dist/styles.cjs +2 -2
- package/dist/styles.js +2 -2
- package/dist/styling/SmartPresets.d.ts +100 -6
- package/dist/styling/SmartPresets.d.ts.map +1 -1
- package/dist/styling/StyleBuilder.d.ts +453 -32
- package/dist/styling/StyleBuilder.d.ts.map +1 -1
- package/dist/styling/banners.d.ts +83 -7
- package/dist/styling/banners.d.ts.map +1 -1
- package/dist/styling/themes.d.ts +41 -2
- package/dist/styling/themes.d.ts.map +1 -1
- package/dist/transports/ConsoleTransport.d.ts +95 -0
- package/dist/transports/ConsoleTransport.d.ts.map +1 -1
- package/dist/transports/FileTransport.d.ts +99 -18
- package/dist/transports/FileTransport.d.ts.map +1 -1
- package/dist/transports/HttpTransport.d.ts +135 -22
- package/dist/transports/HttpTransport.d.ts.map +1 -1
- package/dist/transports/OtlpTraceTransport.d.ts +118 -0
- package/dist/transports/OtlpTraceTransport.d.ts.map +1 -0
- package/dist/transports/OtlpTransport.d.ts +80 -37
- package/dist/transports/OtlpTransport.d.ts.map +1 -1
- package/dist/transports/SpanRuntime.d.ts +73 -0
- package/dist/transports/SpanRuntime.d.ts.map +1 -0
- package/dist/transports/TransportBridge.d.ts +19 -13
- package/dist/transports/TransportBridge.d.ts.map +1 -1
- package/dist/transports/TransportManager.d.ts +232 -10
- package/dist/transports/TransportManager.d.ts.map +1 -1
- package/dist/transports/index.d.ts +1 -0
- package/dist/transports/index.d.ts.map +1 -1
- package/dist/transports-module.d.ts +3 -1
- package/dist/transports-module.d.ts.map +1 -1
- package/dist/transports.cjs +2 -1
- package/dist/transports.js +2 -2
- package/dist/types/core.d.ts +155 -59
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +92 -14
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/serializers.d.ts +72 -0
- package/dist/types/serializers.d.ts.map +1 -1
- package/dist/types/transports.d.ts +163 -39
- package/dist/types/transports.d.ts.map +1 -1
- package/dist/utils/ansi-colors.d.ts +15 -15
- package/dist/utils/asyncLocalStorage.d.ts +33 -0
- package/dist/utils/asyncLocalStorage.d.ts.map +1 -0
- package/dist/utils/environment-detector.d.ts +11 -11
- package/dist/utils/formatting.d.ts +8 -8
- package/dist/utils/output.d.ts +9 -9
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/stackTrace.d.ts +2 -2
- package/package.json +24 -25
- package/dist/chunks/HookBridge-CiRfR67f.cjs +0 -190
- package/dist/chunks/HookBridge-CiRfR67f.cjs.map +0 -1
- package/dist/chunks/HookBridge-SgMmbXZB.js +0 -173
- package/dist/chunks/HookBridge-SgMmbXZB.js.map +0 -1
- package/dist/chunks/LogContext-Cwn-1Zzb.js.map +0 -1
- package/dist/chunks/LogContext-L7HzynFw.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs +0 -166
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BkpQu5c9.js +0 -149
- package/dist/chunks/SerializerBridge-BkpQu5c9.js.map +0 -1
- package/dist/chunks/StyleManager-CIpd6wbO.cjs.map +0 -1
- package/dist/chunks/StyleManager-LCvVlVdx.js +0 -87
- package/dist/chunks/StyleManager-LCvVlVdx.js.map +0 -1
- package/dist/chunks/core-Dzz7agGa.cjs.map +0 -1
- package/dist/chunks/core-PoT7RrTK.js.map +0 -1
- package/dist/chunks/environment-detector-CI3TrWK_.js.map +0 -1
- package/dist/chunks/environment-detector-Cnn6wr6O.cjs.map +0 -1
- package/dist/chunks/server-fallback-BUKjdLS7.cjs +0 -42
- package/dist/chunks/server-fallback-BUKjdLS7.cjs.map +0 -1
- package/dist/chunks/server-fallback-BsuWH1Dk.js +0 -37
- package/dist/chunks/server-fallback-BsuWH1Dk.js.map +0 -1
- package/dist/chunks/spinner-D3FsF78o.js.map +0 -1
- package/dist/chunks/spinner-DNvxbM9a.cjs.map +0 -1
- package/dist/chunks/styling-84N8T97t.js +0 -941
- package/dist/chunks/styling-84N8T97t.js.map +0 -1
- package/dist/chunks/styling-Cg5saQ46.cjs +0 -994
- package/dist/chunks/styling-Cg5saQ46.cjs.map +0 -1
- package/dist/chunks/transports-BiDk345e.js +0 -715
- package/dist/chunks/transports-BiDk345e.js.map +0 -1
- package/dist/chunks/transports-COPWmlF1.cjs +0 -756
- package/dist/chunks/transports-COPWmlF1.cjs.map +0 -1
- package/dist/chunks/utils-BqlFYocD.cjs.map +0 -1
- package/dist/chunks/utils-VETbVpkR.js.map +0 -1
- package/dist/example.d.ts +0 -18
- package/dist/example.d.ts.map +0 -1
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
//#region src/serializers/SerializerRegistry.ts
|
|
2
|
+
/**
|
|
3
|
+
* Configuración por defecto del registry. Se merguea con la config que reciba
|
|
4
|
+
* el constructor (gana la del caller).
|
|
5
|
+
*
|
|
6
|
+
* @internal Constante de módulo; no es API pública.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_CONFIG = {
|
|
9
|
+
maxDepth: 5,
|
|
10
|
+
circular: "placeholder",
|
|
11
|
+
preserveUndefined: false
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Registry de serializers tipados por constructor.
|
|
15
|
+
*
|
|
16
|
+
* Mantiene un mapa ordenado por `priority` (mayor primero) de serializers
|
|
17
|
+
* registrados para clases específicas. El método {@link SerializerRegistry.serialize}
|
|
18
|
+
* recorre objetos de forma recursiva aplicando el serializer que matchee por
|
|
19
|
+
* `instanceof`, con dos guardas de seguridad:
|
|
20
|
+
*
|
|
21
|
+
* - **Depth guard**: corta la recursión al llegar a `maxDepth` y emite el
|
|
22
|
+
* placeholder `'[Max Depth]'`.
|
|
23
|
+
* - **Circular ref**: lleva un `WeakSet` de objetos visitados en el path actual;
|
|
24
|
+
* al re-encontrar uno aplica la estrategia de `circular` (`placeholder` por
|
|
25
|
+
* default).
|
|
26
|
+
*
|
|
27
|
+
* Implementa {@link ISerializerRegistry}. Suele usarse vía el singleton de
|
|
28
|
+
* {@link getDefaultSerializerRegistry}, expuesto al Logger a través del
|
|
29
|
+
* {@link SerializerBridge}.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const registry = new SerializerRegistry({ maxDepth: 3 });
|
|
34
|
+
*
|
|
35
|
+
* registry.add(URL, (url: URL) => ({
|
|
36
|
+
* href: url.href,
|
|
37
|
+
* origin: url.origin
|
|
38
|
+
* }), 60);
|
|
39
|
+
*
|
|
40
|
+
* const safe = registry.serialize(someMaybeCyclicObject);
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @see {@link ISerializerRegistry} para el contrato interface.
|
|
44
|
+
* @see {@link SerializerConfig} para las opciones del constructor.
|
|
45
|
+
*/
|
|
46
|
+
var SerializerRegistry = class {
|
|
47
|
+
serializers = /* @__PURE__ */ new Map();
|
|
48
|
+
config;
|
|
49
|
+
/**
|
|
50
|
+
* Crea un registry nuevo con los serializers builtin ya registrados
|
|
51
|
+
* (Error, Date, RegExp, Map, Set, Buffer cuando está disponible).
|
|
52
|
+
*
|
|
53
|
+
* @param {SerializerConfig} config - Overrides sobre {@link DEFAULT_CONFIG}.
|
|
54
|
+
* - `maxDepth` (default `5`): profundidad máxima de anidamiento antes del
|
|
55
|
+
* placeholder `'[Max Depth]'`.
|
|
56
|
+
* - `circular` (default `'placeholder'`): qué hacer ante una referencia
|
|
57
|
+
* circular. `'placeholder'` emite `'[Circular]'`, `'skip'` omite la key
|
|
58
|
+
* (devuelve `undefined`), `'error'` lanza.
|
|
59
|
+
* - `preserveUndefined` (default `false`): si `true` deja `undefined`
|
|
60
|
+
* textual; si `false` lo reemplaza por `'[undefined]'` (más seguro para
|
|
61
|
+
* JSON / transporte).
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* // Defaults (depth 5, circular → placeholder)
|
|
66
|
+
* const a = new SerializerRegistry();
|
|
67
|
+
*
|
|
68
|
+
* // Estricto: lanza ante ciclo, conservar undefined
|
|
69
|
+
* const b = new SerializerRegistry({
|
|
70
|
+
* maxDepth: 10,
|
|
71
|
+
* circular: 'error',
|
|
72
|
+
* preserveUndefined: true
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
constructor(config = {}) {
|
|
77
|
+
this.config = {
|
|
78
|
+
...DEFAULT_CONFIG,
|
|
79
|
+
...config
|
|
80
|
+
};
|
|
81
|
+
this.registerDefaults();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Registra los serializers builtin con sus prioridades. Invocado por el
|
|
85
|
+
* constructor; no es API pública.
|
|
86
|
+
*
|
|
87
|
+
* Defaults (mayor priority = gana primero en `instanceof`):
|
|
88
|
+
*
|
|
89
|
+
* | Tipo | Priority | Salida |
|
|
90
|
+
* |----------|----------|------------------------------------------------|
|
|
91
|
+
* | `Error` | 100 | `{ name, message, stack[], cause? }` |
|
|
92
|
+
* | `Date` | 90 | `{ iso, timestamp }` |
|
|
93
|
+
* | `RegExp` | 90 | `{ pattern, flags }` |
|
|
94
|
+
* | `Map` | 80 | `{ __type:'Map', entries }` |
|
|
95
|
+
* | `Set` | 80 | `{ __type:'Set', values[] }` |
|
|
96
|
+
* | `Buffer` | 70 | `{ __type:'Buffer', length, preview }` (Node) |
|
|
97
|
+
*
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
registerDefaults() {
|
|
101
|
+
this.add(Error, (err) => ({
|
|
102
|
+
name: err.name,
|
|
103
|
+
message: err.message,
|
|
104
|
+
stack: err.stack?.split("\n").slice(0, 10),
|
|
105
|
+
...err.cause ? { cause: this.serialize(err.cause) } : {}
|
|
106
|
+
}), 100);
|
|
107
|
+
this.add(Date, (date) => ({
|
|
108
|
+
iso: date.toISOString(),
|
|
109
|
+
timestamp: date.getTime()
|
|
110
|
+
}), 90);
|
|
111
|
+
this.add(RegExp, (regex) => ({
|
|
112
|
+
pattern: regex.source,
|
|
113
|
+
flags: regex.flags
|
|
114
|
+
}), 90);
|
|
115
|
+
this.add(Map, (map, ctx) => {
|
|
116
|
+
const obj = {};
|
|
117
|
+
map.forEach((value, key) => {
|
|
118
|
+
const keyStr = typeof key === "object" ? JSON.stringify(key) : String(key);
|
|
119
|
+
obj[keyStr] = this.serializeInternal(value, {
|
|
120
|
+
...ctx,
|
|
121
|
+
depth: ctx.depth + 1,
|
|
122
|
+
path: [...ctx.path, keyStr]
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
__type: "Map",
|
|
127
|
+
entries: obj
|
|
128
|
+
};
|
|
129
|
+
}, 80);
|
|
130
|
+
this.add(Set, (set, ctx) => ({
|
|
131
|
+
__type: "Set",
|
|
132
|
+
values: Array.from(set).map((v, i) => this.serializeInternal(v, {
|
|
133
|
+
...ctx,
|
|
134
|
+
depth: ctx.depth + 1,
|
|
135
|
+
path: [...ctx.path, `[${i}]`]
|
|
136
|
+
}))
|
|
137
|
+
}), 80);
|
|
138
|
+
if (typeof Buffer !== "undefined") this.add(Buffer, (buf) => ({
|
|
139
|
+
__type: "Buffer",
|
|
140
|
+
length: buf.length,
|
|
141
|
+
preview: buf.slice(0, 50).toString("hex")
|
|
142
|
+
}), 70);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Registra (o reemplaza) el serializer para una clase constructora.
|
|
146
|
+
*
|
|
147
|
+
* Si ya existía un serializer para `type`, se sobrescribe. La `priority`
|
|
148
|
+
* sólo ordena de cara al lookup por `instanceof` hecho en
|
|
149
|
+
* {@link SerializerRegistry.getAll} — útil cuando una subclass debería
|
|
150
|
+
* matchear antes que su superclass (p.ej. `TypeError` antes que `Error`).
|
|
151
|
+
*
|
|
152
|
+
* @param {new (...args: any[]) => T} type - Constructor de la clase a matchear.
|
|
153
|
+
* @param {SerializerFn<T>} serializer - Función que recibe la instancia y el
|
|
154
|
+
* {@link SerializerContext} (depth, path, seen); devuelve una representación
|
|
155
|
+
* serializable.
|
|
156
|
+
* @param {number} [priority=50] - Orden de lookup (mayor = primero). Los
|
|
157
|
+
* defaults builtin usan 70–100.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* registry.add(
|
|
162
|
+
* URL,
|
|
163
|
+
* (url: URL, ctx) => ({ href: url.href, origin: url.origin }),
|
|
164
|
+
* 60
|
|
165
|
+
* );
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
add(type, serializer, priority = 50) {
|
|
169
|
+
this.serializers.set(type, {
|
|
170
|
+
type,
|
|
171
|
+
serializer,
|
|
172
|
+
priority
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Elimina el serializer registrado para `type`.
|
|
177
|
+
*
|
|
178
|
+
* @param {new (...args: any[]) => T} type - Constructor a remover.
|
|
179
|
+
* @returns `true` si existía y fue removido, `false` si no había registro.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* registry.remove(Date); // → true (estaba registrado por defecto)
|
|
184
|
+
* registry.remove(Date); // → false (ya no está)
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
remove(type) {
|
|
188
|
+
return this.serializers.delete(type);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Indica si hay un serializer registrado para `type`.
|
|
192
|
+
*
|
|
193
|
+
* @param {new (...args: any[]) => T} type - Constructor a consultar.
|
|
194
|
+
* @returns `true` si `type` está registrado.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* if (!registry.has(CustomError)) {
|
|
199
|
+
* registry.add(CustomError, serializeCustomError, 95);
|
|
200
|
+
* }
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
has(type) {
|
|
204
|
+
return this.serializers.has(type);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Devuelve todas las entradas registradas, ordenadas por `priority`
|
|
208
|
+
* descendente (mayor priority primero). Este es el orden en el que
|
|
209
|
+
* {@link SerializerRegistry.serialize} los prueba vía `instanceof`.
|
|
210
|
+
*
|
|
211
|
+
* @returns {SerializerEntry[]} Array de entradas ordenadas por prioridad.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```ts
|
|
215
|
+
* const entries = registry.getAll();
|
|
216
|
+
* console.log(entries.map(e => [e.type.name, e.priority]));
|
|
217
|
+
* // [['Error', 100], ['Date', 90], ['RegExp', 90], ['Map', 80], ...]
|
|
218
|
+
* ```
|
|
219
|
+
*
|
|
220
|
+
* @see {@link SerializerEntry}
|
|
221
|
+
*/
|
|
222
|
+
getAll() {
|
|
223
|
+
return Array.from(this.serializers.values()).sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Busca el primer serializer cuyo `type` matchee `value instanceof type`,
|
|
227
|
+
* recorriendo las entradas en orden de prioridad descendente.
|
|
228
|
+
*
|
|
229
|
+
* @internal Helper del pipeline interno; no es API pública.
|
|
230
|
+
* @param value - Valor a testear.
|
|
231
|
+
* @returns Entrada matcheante, o `null` si ninguna aplica.
|
|
232
|
+
*/
|
|
233
|
+
findSerializer(value) {
|
|
234
|
+
const sorted = this.getAll();
|
|
235
|
+
for (const entry of sorted) if (value instanceof entry.type) return entry;
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Pipeline interno de serialización recursiva. Es el core de
|
|
240
|
+
* {@link SerializerRegistry.serialize}; no es API pública pero se documenta
|
|
241
|
+
* aquí para mantener la semántica del pipeline en un solo lugar.
|
|
242
|
+
*
|
|
243
|
+
* Orden de guardas (cada una corta la recursión):
|
|
244
|
+
*
|
|
245
|
+
* 1. `null` / `undefined` — directo (respeta `preserveUndefined`).
|
|
246
|
+
* 2. `function` — placeholder `'[Function: name]'`.
|
|
247
|
+
* 3. Primitiva no-objeto — se devuelve tal cual.
|
|
248
|
+
* 4. **Depth guard**: si `depth >= maxDepth` → `'[Max Depth]'`.
|
|
249
|
+
* 5. **Circular**: si `value` ya está en el `WeakSet` `seen` del contexto,
|
|
250
|
+
* aplica `circular` (`placeholder` / `skip` / `error`).
|
|
251
|
+
* 6. Se marca en `seen`, se busca serializer por `instanceof`; si matchea,
|
|
252
|
+
* se delega (el serializer puede recursar via `ctx`).
|
|
253
|
+
* 7. Si es array, mapea cada item incrementando depth y extendiendo path.
|
|
254
|
+
* 8. Si es plain object, itera keys recursivamente.
|
|
255
|
+
*
|
|
256
|
+
* @internal
|
|
257
|
+
* @param value - Valor a serializar.
|
|
258
|
+
* @param context - Estado de recursión (depth, path, seen, maxDepth).
|
|
259
|
+
* @returns Valor serializable (puede ser primitiva, objeto, array o placeholder).
|
|
260
|
+
* @throws {Error} Sólo si `circular: 'error'` y se detecta ciclo.
|
|
261
|
+
*/
|
|
262
|
+
serializeInternal(value, context) {
|
|
263
|
+
if (value === null) return null;
|
|
264
|
+
if (value === void 0) return this.config.preserveUndefined ? void 0 : "[undefined]";
|
|
265
|
+
if (typeof value === "function") return `[Function: ${value.name || "anonymous"}]`;
|
|
266
|
+
if (typeof value !== "object") return value;
|
|
267
|
+
if (context.depth >= this.config.maxDepth) return "[Max Depth]";
|
|
268
|
+
if (context.seen.has(value)) switch (this.config.circular) {
|
|
269
|
+
case "error": throw new Error(`Circular reference at ${context.path.join(".")}`);
|
|
270
|
+
case "skip": return;
|
|
271
|
+
default: return "[Circular]";
|
|
272
|
+
}
|
|
273
|
+
context.seen.add(value);
|
|
274
|
+
const serializer = this.findSerializer(value);
|
|
275
|
+
if (serializer) return serializer.serializer(value, context);
|
|
276
|
+
if (Array.isArray(value)) return value.map((item, i) => this.serializeInternal(item, {
|
|
277
|
+
...context,
|
|
278
|
+
depth: context.depth + 1,
|
|
279
|
+
path: [...context.path, `[${i}]`]
|
|
280
|
+
}));
|
|
281
|
+
const result = {};
|
|
282
|
+
for (const [key, val] of Object.entries(value)) result[key] = this.serializeInternal(val, {
|
|
283
|
+
...context,
|
|
284
|
+
depth: context.depth + 1,
|
|
285
|
+
path: [...context.path, key]
|
|
286
|
+
});
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Serializa un valor arbitrario a una representación segura para transporte
|
|
291
|
+
* (JSON, remote log, OTLP, etc.).
|
|
292
|
+
*
|
|
293
|
+
* Entry point público del pipeline. Construye un {@link SerializerContext}
|
|
294
|
+
* fresco (depth 0, path vacío, `WeakSet` nuevo para detección de ciclos),
|
|
295
|
+
* merguea overrides de `config` sobre los del constructor y delega a
|
|
296
|
+
* {@link SerializerRegistry.serializeInternal}.
|
|
297
|
+
*
|
|
298
|
+
* @param {any} value - Valor a serializar. Cualquier tipo.
|
|
299
|
+
* @param {SerializerConfig} [config] - Overrides puntuales para esta llamada
|
|
300
|
+
* (no mutan la config del registry). Útil para, p.ej., subir `maxDepth`
|
|
301
|
+
* sólo en un log concreto.
|
|
302
|
+
* @returns {any} Valor serializable. Para objetos sin serializer registrado
|
|
303
|
+
* se devuelve un plain object; para tipos builtin, la shape definida en
|
|
304
|
+
* {@link SerializerRegistry.registerDefaults}; para los cortes de
|
|
305
|
+
* profundidad o circular, los placeholders `'[Max Depth]'` / `'[Circular]'`.
|
|
306
|
+
* @throws {Error} Sólo si `circular: 'error'` y se detecta una referencia circular.
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* // Objetos simples
|
|
311
|
+
* registry.serialize({ a: 1, b: [2, 3] });
|
|
312
|
+
* // → { a: 1, b: [2, 3] }
|
|
313
|
+
*
|
|
314
|
+
* // Errores (serializer builtin)
|
|
315
|
+
* registry.serialize(new Error('boom'));
|
|
316
|
+
* // → { name: 'Error', message: 'boom', stack: [...] }
|
|
317
|
+
*
|
|
318
|
+
* // Referencia circular → placeholder
|
|
319
|
+
* const o: any = {};
|
|
320
|
+
* o.self = o;
|
|
321
|
+
* registry.serialize(o); // → { self: '[Circular]' }
|
|
322
|
+
*
|
|
323
|
+
* // Override puntual de maxDepth
|
|
324
|
+
* registry.serialize(deepObj, { maxDepth: 2 });
|
|
325
|
+
* ```
|
|
326
|
+
*
|
|
327
|
+
* @see {@link SerializerRegistry.serializeInternal} para el detalle del pipeline.
|
|
328
|
+
*/
|
|
329
|
+
serialize(value, config) {
|
|
330
|
+
const mergedConfig = {
|
|
331
|
+
...this.config,
|
|
332
|
+
...config
|
|
333
|
+
};
|
|
334
|
+
return this.serializeInternal(value, {
|
|
335
|
+
depth: 0,
|
|
336
|
+
maxDepth: mergedConfig.maxDepth,
|
|
337
|
+
path: [],
|
|
338
|
+
seen: /* @__PURE__ */ new WeakSet()
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
/**
|
|
343
|
+
* Cache del singleton de {@link SerializerRegistry}. Module-private.
|
|
344
|
+
*
|
|
345
|
+
* @internal
|
|
346
|
+
*/
|
|
347
|
+
let _defaultRegistry = null;
|
|
348
|
+
/**
|
|
349
|
+
* Devuelve el singleton de {@link SerializerRegistry} (lo crea con config
|
|
350
|
+
* default en la primera llamada). Es la vía canónica de obtener el registry
|
|
351
|
+
* compartido que usa el Logger internamente.
|
|
352
|
+
*
|
|
353
|
+
* @returns {SerializerRegistry} Instancia singleton.
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```ts
|
|
357
|
+
* import { getDefaultSerializerRegistry } from '@mks2508/better-logger/serializers';
|
|
358
|
+
*
|
|
359
|
+
* const registry = getDefaultSerializerRegistry();
|
|
360
|
+
* if (!registry.has(CustomError)) {
|
|
361
|
+
* registry.add(CustomError, (e) => ({ code: e.code, message: e.message }), 95);
|
|
362
|
+
* }
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
365
|
+
function getDefaultSerializerRegistry() {
|
|
366
|
+
if (!_defaultRegistry) _defaultRegistry = new SerializerRegistry();
|
|
367
|
+
return _defaultRegistry;
|
|
368
|
+
}
|
|
369
|
+
//#endregion
|
|
370
|
+
//#region src/serializers/SerializerBridge.ts
|
|
371
|
+
/**
|
|
372
|
+
* Crea una instancia de {@link SerializerBridge}.
|
|
373
|
+
*
|
|
374
|
+
* @internal
|
|
375
|
+
*/
|
|
376
|
+
function createSerializerBridge() {
|
|
377
|
+
const serializerRegistry = new SerializerRegistry();
|
|
378
|
+
return {
|
|
379
|
+
addSerializer(type, serializer, priority) {
|
|
380
|
+
serializerRegistry.add(type, serializer, priority);
|
|
381
|
+
},
|
|
382
|
+
removeSerializer(type) {
|
|
383
|
+
return serializerRegistry.remove(type);
|
|
384
|
+
},
|
|
385
|
+
getSerializerRegistry() {
|
|
386
|
+
return serializerRegistry;
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
//#endregion
|
|
391
|
+
export { SerializerRegistry as n, getDefaultSerializerRegistry as r, createSerializerBridge as t };
|
|
392
|
+
|
|
393
|
+
//# sourceMappingURL=SerializerBridge-Ba43Mk7j.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SerializerBridge-Ba43Mk7j.js","names":[],"sources":["../../src/serializers/SerializerRegistry.ts","../../src/serializers/SerializerBridge.ts"],"sourcesContent":["/**\n * @fileoverview Registry de serializers con control de profundidad, detección\n * de referencias circulares y soporte para tipos builtin (Error, Date, RegExp,\n * Map, Set, Buffer). Implementa {@link ISerializerRegistry}.\n */\nimport type {\n SerializerFn,\n SerializerContext,\n SerializerEntry,\n SerializerConfig,\n ISerializerRegistry\n} from '../types/index.js';\n\n/**\n * Configuración por defecto del registry. Se merguea con la config que reciba\n * el constructor (gana la del caller).\n *\n * @internal Constante de módulo; no es API pública.\n */\nconst DEFAULT_CONFIG: Required<SerializerConfig> = {\n maxDepth: 5,\n circular: 'placeholder',\n preserveUndefined: false\n};\n\n/**\n * Registry de serializers tipados por constructor.\n *\n * Mantiene un mapa ordenado por `priority` (mayor primero) de serializers\n * registrados para clases específicas. El método {@link SerializerRegistry.serialize}\n * recorre objetos de forma recursiva aplicando el serializer que matchee por\n * `instanceof`, con dos guardas de seguridad:\n *\n * - **Depth guard**: corta la recursión al llegar a `maxDepth` y emite el\n * placeholder `'[Max Depth]'`.\n * - **Circular ref**: lleva un `WeakSet` de objetos visitados en el path actual;\n * al re-encontrar uno aplica la estrategia de `circular` (`placeholder` por\n * default).\n *\n * Implementa {@link ISerializerRegistry}. Suele usarse vía el singleton de\n * {@link getDefaultSerializerRegistry}, expuesto al Logger a través del\n * {@link SerializerBridge}.\n *\n * @example\n * ```ts\n * const registry = new SerializerRegistry({ maxDepth: 3 });\n *\n * registry.add(URL, (url: URL) => ({\n * href: url.href,\n * origin: url.origin\n * }), 60);\n *\n * const safe = registry.serialize(someMaybeCyclicObject);\n * ```\n *\n * @see {@link ISerializerRegistry} para el contrato interface.\n * @see {@link SerializerConfig} para las opciones del constructor.\n */\nexport class SerializerRegistry implements ISerializerRegistry {\n private serializers: Map<Function, SerializerEntry> = new Map();\n private config: Required<SerializerConfig>;\n\n /**\n * Crea un registry nuevo con los serializers builtin ya registrados\n * (Error, Date, RegExp, Map, Set, Buffer cuando está disponible).\n *\n * @param {SerializerConfig} config - Overrides sobre {@link DEFAULT_CONFIG}.\n * - `maxDepth` (default `5`): profundidad máxima de anidamiento antes del\n * placeholder `'[Max Depth]'`.\n * - `circular` (default `'placeholder'`): qué hacer ante una referencia\n * circular. `'placeholder'` emite `'[Circular]'`, `'skip'` omite la key\n * (devuelve `undefined`), `'error'` lanza.\n * - `preserveUndefined` (default `false`): si `true` deja `undefined`\n * textual; si `false` lo reemplaza por `'[undefined]'` (más seguro para\n * JSON / transporte).\n *\n * @example\n * ```ts\n * // Defaults (depth 5, circular → placeholder)\n * const a = new SerializerRegistry();\n *\n * // Estricto: lanza ante ciclo, conservar undefined\n * const b = new SerializerRegistry({\n * maxDepth: 10,\n * circular: 'error',\n * preserveUndefined: true\n * });\n * ```\n */\n constructor(config: SerializerConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.registerDefaults();\n }\n\n /**\n * Registra los serializers builtin con sus prioridades. Invocado por el\n * constructor; no es API pública.\n *\n * Defaults (mayor priority = gana primero en `instanceof`):\n *\n * | Tipo | Priority | Salida |\n * |----------|----------|------------------------------------------------|\n * | `Error` | 100 | `{ name, message, stack[], cause? }` |\n * | `Date` | 90 | `{ iso, timestamp }` |\n * | `RegExp` | 90 | `{ pattern, flags }` |\n * | `Map` | 80 | `{ __type:'Map', entries }` |\n * | `Set` | 80 | `{ __type:'Set', values[] }` |\n * | `Buffer` | 70 | `{ __type:'Buffer', length, preview }` (Node) |\n *\n * @internal\n */\n private registerDefaults(): void {\n this.add(Error, (err: Error) => ({\n name: err.name,\n message: err.message,\n stack: err.stack?.split('\\n').slice(0, 10),\n ...(err.cause ? { cause: this.serialize(err.cause) } : {})\n }), 100);\n\n this.add(Date, (date: Date) => ({\n iso: date.toISOString(),\n timestamp: date.getTime()\n }), 90);\n\n this.add(RegExp, (regex: RegExp) => ({\n pattern: regex.source,\n flags: regex.flags\n }), 90);\n\n this.add(Map, (map: Map<any, any>, ctx) => {\n const obj: Record<string, any> = {};\n map.forEach((value, key) => {\n const keyStr = typeof key === 'object' ? JSON.stringify(key) : String(key);\n obj[keyStr] = this.serializeInternal(value, {\n ...ctx,\n depth: ctx.depth + 1,\n path: [...ctx.path, keyStr]\n });\n });\n return { __type: 'Map', entries: obj };\n }, 80);\n\n this.add(Set, (set: Set<any>, ctx) => ({\n __type: 'Set',\n values: Array.from(set).map((v, i) =>\n this.serializeInternal(v, {\n ...ctx,\n depth: ctx.depth + 1,\n path: [...ctx.path, `[${i}]`]\n })\n )\n }), 80);\n\n if (typeof Buffer !== 'undefined') {\n this.add(Buffer as any, (buf: Buffer) => ({\n __type: 'Buffer',\n length: buf.length,\n preview: buf.slice(0, 50).toString('hex')\n }), 70);\n }\n }\n\n /**\n * Registra (o reemplaza) el serializer para una clase constructora.\n *\n * Si ya existía un serializer para `type`, se sobrescribe. La `priority`\n * sólo ordena de cara al lookup por `instanceof` hecho en\n * {@link SerializerRegistry.getAll} — útil cuando una subclass debería\n * matchear antes que su superclass (p.ej. `TypeError` antes que `Error`).\n *\n * @param {new (...args: any[]) => T} type - Constructor de la clase a matchear.\n * @param {SerializerFn<T>} serializer - Función que recibe la instancia y el\n * {@link SerializerContext} (depth, path, seen); devuelve una representación\n * serializable.\n * @param {number} [priority=50] - Orden de lookup (mayor = primero). Los\n * defaults builtin usan 70–100.\n *\n * @example\n * ```ts\n * registry.add(\n * URL,\n * (url: URL, ctx) => ({ href: url.href, origin: url.origin }),\n * 60\n * );\n * ```\n */\n add<T>(\n type: new (...args: any[]) => T,\n serializer: SerializerFn<T>,\n priority: number = 50\n ): void {\n this.serializers.set(type, { type, serializer, priority });\n }\n\n /**\n * Elimina el serializer registrado para `type`.\n *\n * @param {new (...args: any[]) => T} type - Constructor a remover.\n * @returns `true` si existía y fue removido, `false` si no había registro.\n *\n * @example\n * ```ts\n * registry.remove(Date); // → true (estaba registrado por defecto)\n * registry.remove(Date); // → false (ya no está)\n * ```\n */\n remove<T>(type: new (...args: any[]) => T): boolean {\n return this.serializers.delete(type);\n }\n\n /**\n * Indica si hay un serializer registrado para `type`.\n *\n * @param {new (...args: any[]) => T} type - Constructor a consultar.\n * @returns `true` si `type` está registrado.\n *\n * @example\n * ```ts\n * if (!registry.has(CustomError)) {\n * registry.add(CustomError, serializeCustomError, 95);\n * }\n * ```\n */\n has<T>(type: new (...args: any[]) => T): boolean {\n return this.serializers.has(type);\n }\n\n /**\n * Devuelve todas las entradas registradas, ordenadas por `priority`\n * descendente (mayor priority primero). Este es el orden en el que\n * {@link SerializerRegistry.serialize} los prueba vía `instanceof`.\n *\n * @returns {SerializerEntry[]} Array de entradas ordenadas por prioridad.\n *\n * @example\n * ```ts\n * const entries = registry.getAll();\n * console.log(entries.map(e => [e.type.name, e.priority]));\n * // [['Error', 100], ['Date', 90], ['RegExp', 90], ['Map', 80], ...]\n * ```\n *\n * @see {@link SerializerEntry}\n */\n getAll(): SerializerEntry[] {\n return Array.from(this.serializers.values())\n .sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));\n }\n\n /**\n * Busca el primer serializer cuyo `type` matchee `value instanceof type`,\n * recorriendo las entradas en orden de prioridad descendente.\n *\n * @internal Helper del pipeline interno; no es API pública.\n * @param value - Valor a testear.\n * @returns Entrada matcheante, o `null` si ninguna aplica.\n */\n private findSerializer(value: any): SerializerEntry | null {\n const sorted = this.getAll();\n for (const entry of sorted) {\n if (value instanceof entry.type) {\n return entry;\n }\n }\n return null;\n }\n\n /**\n * Pipeline interno de serialización recursiva. Es el core de\n * {@link SerializerRegistry.serialize}; no es API pública pero se documenta\n * aquí para mantener la semántica del pipeline en un solo lugar.\n *\n * Orden de guardas (cada una corta la recursión):\n *\n * 1. `null` / `undefined` — directo (respeta `preserveUndefined`).\n * 2. `function` — placeholder `'[Function: name]'`.\n * 3. Primitiva no-objeto — se devuelve tal cual.\n * 4. **Depth guard**: si `depth >= maxDepth` → `'[Max Depth]'`.\n * 5. **Circular**: si `value` ya está en el `WeakSet` `seen` del contexto,\n * aplica `circular` (`placeholder` / `skip` / `error`).\n * 6. Se marca en `seen`, se busca serializer por `instanceof`; si matchea,\n * se delega (el serializer puede recursar via `ctx`).\n * 7. Si es array, mapea cada item incrementando depth y extendiendo path.\n * 8. Si es plain object, itera keys recursivamente.\n *\n * @internal\n * @param value - Valor a serializar.\n * @param context - Estado de recursión (depth, path, seen, maxDepth).\n * @returns Valor serializable (puede ser primitiva, objeto, array o placeholder).\n * @throws {Error} Sólo si `circular: 'error'` y se detecta ciclo.\n */\n private serializeInternal(value: any, context: SerializerContext): any {\n if (value === null) return null;\n if (value === undefined) return this.config.preserveUndefined ? undefined : '[undefined]';\n if (typeof value === 'function') return `[Function: ${value.name || 'anonymous'}]`;\n if (typeof value !== 'object') return value;\n\n if (context.depth >= this.config.maxDepth) {\n return '[Max Depth]';\n }\n\n if (context.seen.has(value)) {\n switch (this.config.circular) {\n case 'error':\n throw new Error(`Circular reference at ${context.path.join('.')}`);\n case 'skip':\n return undefined;\n case 'placeholder':\n default:\n return '[Circular]';\n }\n }\n context.seen.add(value);\n\n const serializer = this.findSerializer(value);\n if (serializer) {\n return serializer.serializer(value, context);\n }\n\n if (Array.isArray(value)) {\n return value.map((item, i) =>\n this.serializeInternal(item, {\n ...context,\n depth: context.depth + 1,\n path: [...context.path, `[${i}]`]\n })\n );\n }\n\n const result: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.serializeInternal(val, {\n ...context,\n depth: context.depth + 1,\n path: [...context.path, key]\n });\n }\n return result;\n }\n\n /**\n * Serializa un valor arbitrario a una representación segura para transporte\n * (JSON, remote log, OTLP, etc.).\n *\n * Entry point público del pipeline. Construye un {@link SerializerContext}\n * fresco (depth 0, path vacío, `WeakSet` nuevo para detección de ciclos),\n * merguea overrides de `config` sobre los del constructor y delega a\n * {@link SerializerRegistry.serializeInternal}.\n *\n * @param {any} value - Valor a serializar. Cualquier tipo.\n * @param {SerializerConfig} [config] - Overrides puntuales para esta llamada\n * (no mutan la config del registry). Útil para, p.ej., subir `maxDepth`\n * sólo en un log concreto.\n * @returns {any} Valor serializable. Para objetos sin serializer registrado\n * se devuelve un plain object; para tipos builtin, la shape definida en\n * {@link SerializerRegistry.registerDefaults}; para los cortes de\n * profundidad o circular, los placeholders `'[Max Depth]'` / `'[Circular]'`.\n * @throws {Error} Sólo si `circular: 'error'` y se detecta una referencia circular.\n *\n * @example\n * ```ts\n * // Objetos simples\n * registry.serialize({ a: 1, b: [2, 3] });\n * // → { a: 1, b: [2, 3] }\n *\n * // Errores (serializer builtin)\n * registry.serialize(new Error('boom'));\n * // → { name: 'Error', message: 'boom', stack: [...] }\n *\n * // Referencia circular → placeholder\n * const o: any = {};\n * o.self = o;\n * registry.serialize(o); // → { self: '[Circular]' }\n *\n * // Override puntual de maxDepth\n * registry.serialize(deepObj, { maxDepth: 2 });\n * ```\n *\n * @see {@link SerializerRegistry.serializeInternal} para el detalle del pipeline.\n */\n serialize(value: any, config?: SerializerConfig): any {\n const mergedConfig = { ...this.config, ...config };\n return this.serializeInternal(value, {\n depth: 0,\n maxDepth: mergedConfig.maxDepth,\n path: [],\n seen: new WeakSet()\n });\n }\n}\n\n/**\n * Cache del singleton de {@link SerializerRegistry}. Module-private.\n *\n * @internal\n */\nlet _defaultRegistry: SerializerRegistry | null = null;\n\n/**\n * Devuelve el singleton de {@link SerializerRegistry} (lo crea con config\n * default en la primera llamada). Es la vía canónica de obtener el registry\n * compartido que usa el Logger internamente.\n *\n * @returns {SerializerRegistry} Instancia singleton.\n *\n * @example\n * ```ts\n * import { getDefaultSerializerRegistry } from '@mks2508/better-logger/serializers';\n *\n * const registry = getDefaultSerializerRegistry();\n * if (!registry.has(CustomError)) {\n * registry.add(CustomError, (e) => ({ code: e.code, message: e.message }), 95);\n * }\n * ```\n */\nexport function getDefaultSerializerRegistry(): SerializerRegistry {\n if (!_defaultRegistry) {\n _defaultRegistry = new SerializerRegistry();\n }\n return _defaultRegistry;\n}\n","/**\n * @fileoverview SerializerBridge — facade de SerializerRegistry.\n * Encapsula registro, eliminación y acceso al registry de serializers.\n *\n * @internal\n */\n\nimport type { SerializerFn } from '../types/index.js';\nimport { SerializerRegistry } from './index.js';\n\n/**\n * Bridge para la gestión de serializers.\n *\n * @internal\n */\nexport interface SerializerBridge {\n /** Añade un serializer para un tipo. */\n addSerializer<T>(type: new (...args: unknown[]) => T, serializer: SerializerFn<T>, priority?: number): void;\n /** Elimina el serializer asociado a un tipo. Devuelve `true` si se eliminó. */\n removeSerializer<T>(type: new (...args: unknown[]) => T): boolean;\n /** Devuelve el registry subyacente. */\n getSerializerRegistry(): SerializerRegistry;\n}\n\n/**\n * Crea una instancia de {@link SerializerBridge}.\n *\n * @internal\n */\nexport function createSerializerBridge(): SerializerBridge {\n const serializerRegistry = new SerializerRegistry();\n\n return {\n addSerializer<T>(type: new (...args: unknown[]) => T, serializer: SerializerFn<T>, priority?: number): void {\n serializerRegistry.add(type, serializer, priority);\n },\n\n removeSerializer<T>(type: new (...args: unknown[]) => T): boolean {\n return serializerRegistry.remove(type);\n },\n\n getSerializerRegistry(): SerializerRegistry {\n return serializerRegistry;\n }\n };\n}\n"],"mappings":"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"}
|