@lssm/lib.logger 1.7.4 → 1.9.0
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 +26 -525
- package/dist/{context.d.ts → context.d.mts} +2 -2
- package/dist/{context.d.cts.map → context.d.mts.map} +1 -1
- package/dist/{context.js → context.mjs} +1 -1
- package/dist/context.mjs.map +1 -0
- package/dist/{elysia-plugin.d.cts → elysia-plugin.d.mts} +3 -3
- package/dist/{elysia-plugin.d.cts.map → elysia-plugin.d.mts.map} +1 -1
- package/dist/elysia-plugin.mjs +2 -0
- package/dist/elysia-plugin.mjs.map +1 -0
- package/dist/{formatters.d.cts → formatters.d.mts} +2 -2
- package/dist/{formatters.d.cts.map → formatters.d.mts.map} +1 -1
- package/dist/{formatters.js → formatters.mjs} +2 -2
- package/dist/formatters.mjs.map +1 -0
- package/dist/{index.d.cts → index.d.mts} +7 -7
- package/dist/index.mjs +1 -0
- package/dist/{logger.d.cts → logger.d.mts} +3 -3
- package/dist/{logger.d.cts.map → logger.d.mts.map} +1 -1
- package/dist/logger.mjs +2 -0
- package/dist/logger.mjs.map +1 -0
- package/dist/{timer.d.ts → timer.d.mts} +2 -2
- package/dist/{timer.d.cts.map → timer.d.mts.map} +1 -1
- package/dist/{timer.js → timer.mjs} +1 -1
- package/dist/timer.mjs.map +1 -0
- package/dist/{tracer.d.cts → tracer.d.mts} +2 -2
- package/dist/{tracer.d.cts.map → tracer.d.mts.map} +1 -1
- package/dist/tracer.mjs +2 -0
- package/dist/tracer.mjs.map +1 -0
- package/dist/{types.d.cts → types.d.mts} +1 -1
- package/dist/{types.d.cts.map → types.d.mts.map} +1 -1
- package/dist/{types.js → types.mjs} +1 -1
- package/dist/types.mjs.map +1 -0
- package/package.json +15 -39
- package/dist/_virtual/rolldown_runtime.cjs +0 -1
- package/dist/context.cjs +0 -1
- package/dist/context.d.cts +0 -44
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js.map +0 -1
- package/dist/elysia-plugin.cjs +0 -1
- package/dist/elysia-plugin.d.ts +0 -64
- package/dist/elysia-plugin.d.ts.map +0 -1
- package/dist/elysia-plugin.js +0 -2
- package/dist/elysia-plugin.js.map +0 -1
- package/dist/formatters.cjs +0 -9
- package/dist/formatters.d.ts +0 -29
- package/dist/formatters.d.ts.map +0 -1
- package/dist/formatters.js.map +0 -1
- package/dist/index.cjs +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -1
- package/dist/logger.cjs +0 -1
- package/dist/logger.d.ts +0 -51
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -2
- package/dist/logger.js.map +0 -1
- package/dist/timer.cjs +0 -1
- package/dist/timer.d.cts +0 -103
- package/dist/timer.d.ts.map +0 -1
- package/dist/timer.js.map +0 -1
- package/dist/tracer.cjs +0 -1
- package/dist/tracer.d.ts +0 -51
- package/dist/tracer.d.ts.map +0 -1
- package/dist/tracer.js +0 -2
- package/dist/tracer.js.map +0 -1
- package/dist/types.cjs +0 -1
- package/dist/types.d.ts +0 -71
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,550 +1,51 @@
|
|
|
1
1
|
# @lssm/lib.logger
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
High-performance logging library optimized for Bun, with native ElysiaJS integration.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Purpose
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- 🚀 **Optimized for Bun** - Uses Bun's native performance APIs and optimized for Bun runtime
|
|
10
|
-
- 🦋 **ElysiaJS Native** - Seamless integration with [ElysiaJS](https://elysiajs.com) lifecycle and context
|
|
11
|
-
- 🔍 **Distributed Tracing** - Track operations across HTTP, WebSocket, cron, and queue processing
|
|
12
|
-
- ⏱️ **Performance Timing** - Built-in high-precision timing for operations
|
|
13
|
-
- 🔄 **Context Management** - Maintain context across async operations (like cls-hooked/nestjs-cls)
|
|
14
|
-
- 🎨 **Environment-aware Output** - Pretty logs in dev, structured JSON in production
|
|
15
|
-
- 🔌 **Easy Integrations** - Built-in middleware for HTTP, WebSocket, cron, and queues
|
|
7
|
+
To provide structured, performant logging with support for request tracing, timing, and varied output formats (JSON/Pretty). It includes a plugin for ElysiaJS to automatically log HTTP requests.
|
|
16
8
|
|
|
17
9
|
## Installation
|
|
18
10
|
|
|
19
11
|
```bash
|
|
12
|
+
npm install @lssm/lib.logger
|
|
13
|
+
# or
|
|
20
14
|
bun add @lssm/lib.logger
|
|
21
|
-
# If using ElysiaJS
|
|
22
|
-
bun add elysia @lssm/lib.logger
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Quick Start
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { logger, Logger, LogLevel } from "@lssm/lib.logger";
|
|
29
|
-
|
|
30
|
-
// Basic logging
|
|
31
|
-
logger.info("Server started", { port: 3000 });
|
|
32
|
-
logger.error("Database error", { table: "users" }, error);
|
|
33
|
-
|
|
34
|
-
// Create a custom logger
|
|
35
|
-
const customLogger = new Logger({
|
|
36
|
-
level: LogLevel.DEBUG,
|
|
37
|
-
environment: "production",
|
|
38
|
-
enableTracing: true,
|
|
39
|
-
});
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Core Logging
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
import { logger } from "@lssm/lib.logger";
|
|
46
|
-
|
|
47
|
-
// Different log levels
|
|
48
|
-
logger.trace("Detailed debug info"); // TRACE level
|
|
49
|
-
logger.debug("Debug information"); // DEBUG level
|
|
50
|
-
logger.info("General information"); // INFO level
|
|
51
|
-
logger.warn("Warning message"); // WARN level
|
|
52
|
-
logger.error("Error occurred", {}, err); // ERROR level
|
|
53
|
-
logger.fatal("Critical error", {}, err); // FATAL level
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Context Management
|
|
57
|
-
|
|
58
|
-
The logger maintains context across async operations using AsyncLocalStorage:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
import { logger } from "@lssm/lib.logger";
|
|
62
|
-
|
|
63
|
-
// Run code within a context
|
|
64
|
-
logger.withContext({ userId: "123", requestId: "abc" }, () => {
|
|
65
|
-
logger.info("Processing user request"); // Will include userId and requestId
|
|
66
|
-
|
|
67
|
-
someAsyncOperation(); // Context is maintained across async calls
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Extend existing context
|
|
71
|
-
logger.extendContext({ operation: "payment" }, () => {
|
|
72
|
-
logger.info("Processing payment"); // Includes all previous context + operation
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// Set individual context values
|
|
76
|
-
logger.setContext("sessionId", "xyz789");
|
|
77
|
-
logger.info("User action"); // Will include sessionId
|
|
78
|
-
|
|
79
|
-
// Get current context
|
|
80
|
-
const context = logger.getContext();
|
|
81
|
-
console.log(context); // { userId: '123', requestId: 'abc', sessionId: 'xyz789' }
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Distributed Tracing
|
|
85
|
-
|
|
86
|
-
Track operations across your application with automatic span management:
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
import { logger } from "@lssm/lib.logger";
|
|
90
|
-
|
|
91
|
-
// Trace an operation
|
|
92
|
-
await logger.trace(
|
|
93
|
-
{
|
|
94
|
-
operationType: "http",
|
|
95
|
-
operationName: "GET /api/users",
|
|
96
|
-
metadata: { userId: "123" },
|
|
97
|
-
tags: ["api", "users"],
|
|
98
|
-
autoTiming: true,
|
|
99
|
-
},
|
|
100
|
-
async () => {
|
|
101
|
-
// Your operation code here
|
|
102
|
-
const users = await fetchUsers();
|
|
103
|
-
return users;
|
|
104
|
-
}
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
// Manual span management
|
|
108
|
-
const span = logger.startSpan({
|
|
109
|
-
operationType: "database",
|
|
110
|
-
operationName: "user-query",
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const result = await database.query("SELECT * FROM users");
|
|
115
|
-
logger.addTraceMetadata("rowCount", result.length);
|
|
116
|
-
logger.addTraceTags("database", "users");
|
|
117
|
-
return result;
|
|
118
|
-
} finally {
|
|
119
|
-
logger.finishSpan(span.spanId);
|
|
120
|
-
}
|
|
121
15
|
```
|
|
122
16
|
|
|
123
|
-
##
|
|
124
|
-
|
|
125
|
-
Measure execution times with high precision:
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
import { logger } from "@lssm/lib.logger";
|
|
17
|
+
## Key Concepts
|
|
129
18
|
|
|
130
|
-
|
|
131
|
-
|
|
19
|
+
- **Structured Logging**: Logs are JSON objects by default for easy parsing.
|
|
20
|
+
- **Context Awareness**: Supports AsyncLocalStorage for request-scoped context (Trace IDs).
|
|
21
|
+
- **Elysia Plugin**: Drop-in middleware for Elysia apps.
|
|
132
22
|
|
|
133
|
-
|
|
23
|
+
## Exports
|
|
134
24
|
|
|
135
|
-
|
|
136
|
-
|
|
25
|
+
- `logger`: The main logger instance.
|
|
26
|
+
- `elysiaPlugin`: Middleware for Elysia.
|
|
27
|
+
- `timer`: Utilities for measuring execution time.
|
|
28
|
+
- `tracer`: Request tracing utilities.
|
|
137
29
|
|
|
138
|
-
|
|
139
|
-
const result = await logger.profile(
|
|
140
|
-
"expensive-calculation",
|
|
141
|
-
async () => {
|
|
142
|
-
return await someExpensiveOperation();
|
|
143
|
-
},
|
|
144
|
-
{ logResult: true, logLevel: LogLevel.INFO }
|
|
145
|
-
);
|
|
30
|
+
## Usage
|
|
146
31
|
|
|
147
|
-
|
|
148
|
-
const timer2 = logger.startTimer("multi-step-process");
|
|
149
|
-
timer2.lap("step-1-complete");
|
|
150
|
-
// ... more work ...
|
|
151
|
-
timer2.lap("step-2-complete");
|
|
152
|
-
const total = timer2.stop();
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## ElysiaJS Integration
|
|
32
|
+
### Basic Logging
|
|
156
33
|
|
|
157
|
-
|
|
34
|
+
```ts
|
|
35
|
+
import { logger } from '@lssm/lib.logger';
|
|
158
36
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
import { elysiaLogger } from "@lssm/lib.logger";
|
|
162
|
-
|
|
163
|
-
const app = new Elysia()
|
|
164
|
-
.use(
|
|
165
|
-
elysiaLogger({
|
|
166
|
-
logRequests: true,
|
|
167
|
-
logResponses: true,
|
|
168
|
-
excludePaths: ["/health", "/metrics"],
|
|
169
|
-
})
|
|
170
|
-
)
|
|
171
|
-
.get("/", ({ logInfo }) => {
|
|
172
|
-
logInfo("Processing request");
|
|
173
|
-
return "Hello World";
|
|
174
|
-
})
|
|
175
|
-
.listen(3000);
|
|
37
|
+
logger.info('Server started', { port: 3000 });
|
|
38
|
+
logger.error('Database connection failed', { error: err });
|
|
176
39
|
```
|
|
177
40
|
|
|
178
|
-
|
|
41
|
+
### With Elysia
|
|
179
42
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
- ✅ Maintains context across async operations
|
|
184
|
-
- ✅ Provides helper functions in route context
|
|
43
|
+
```ts
|
|
44
|
+
import { Elysia } from 'elysia';
|
|
45
|
+
import { elysiaLogger } from '@lssm/lib.logger/elysia-plugin';
|
|
185
46
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
import { Elysia } from "elysia";
|
|
190
|
-
import {
|
|
191
|
-
elysiaLogger,
|
|
192
|
-
createDatabaseUtils,
|
|
193
|
-
Logger,
|
|
194
|
-
LogLevel,
|
|
195
|
-
} from "@lssm/lib.logger";
|
|
196
|
-
|
|
197
|
-
const customLogger = new Logger({
|
|
198
|
-
level: LogLevel.DEBUG,
|
|
199
|
-
environment: "production",
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
const db = createDatabaseUtils(customLogger);
|
|
203
|
-
|
|
204
|
-
const app = new Elysia()
|
|
205
|
-
.use(
|
|
206
|
-
elysiaLogger({
|
|
207
|
-
logger: customLogger,
|
|
208
|
-
maskSensitiveData: true,
|
|
209
|
-
})
|
|
210
|
-
)
|
|
211
|
-
.derive(() => ({ db }))
|
|
212
|
-
.get("/users", async ({ logInfo, traceOperation, db }) => {
|
|
213
|
-
logInfo("Fetching users from database");
|
|
214
|
-
|
|
215
|
-
const users = await traceOperation("fetch-users", async () => {
|
|
216
|
-
return db.query("select-users", () =>
|
|
217
|
-
// Your database query here
|
|
218
|
-
Promise.resolve([{ id: 1, name: "John" }])
|
|
219
|
-
);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
return users;
|
|
223
|
-
})
|
|
224
|
-
.listen(3000);
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### ElysiaJS WebSocket Logging
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
import { Elysia } from "elysia";
|
|
231
|
-
import { elysiaLogger, createWebSocketUtils } from "@lssm/lib.logger";
|
|
232
|
-
|
|
233
|
-
const wsLogger = createWebSocketUtils();
|
|
234
|
-
|
|
235
|
-
const app = new Elysia()
|
|
47
|
+
new Elysia()
|
|
236
48
|
.use(elysiaLogger())
|
|
237
|
-
.
|
|
238
|
-
open(ws) {
|
|
239
|
-
const connectionId = crypto.randomUUID();
|
|
240
|
-
wsLogger.logConnection(connectionId, {
|
|
241
|
-
userAgent: ws.data.headers?.["user-agent"],
|
|
242
|
-
});
|
|
243
|
-
},
|
|
244
|
-
message(ws, message) {
|
|
245
|
-
wsLogger.logMessage(ws.id, typeof message, message.length);
|
|
246
|
-
ws.send(`Echo: ${message}`);
|
|
247
|
-
},
|
|
248
|
-
close(ws, code, reason) {
|
|
249
|
-
wsLogger.logDisconnection(ws.id, code, reason);
|
|
250
|
-
},
|
|
251
|
-
})
|
|
49
|
+
.get('/', () => 'Hello World')
|
|
252
50
|
.listen(3000);
|
|
253
51
|
```
|
|
254
|
-
|
|
255
|
-
### ElysiaJS with Authentication Logging
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
import { Elysia } from "elysia";
|
|
259
|
-
import { elysiaLogger, createAuthUtils } from "@lssm/lib.logger";
|
|
260
|
-
|
|
261
|
-
const authLogger = createAuthUtils();
|
|
262
|
-
|
|
263
|
-
const app = new Elysia()
|
|
264
|
-
.use(elysiaLogger())
|
|
265
|
-
.derive(() => ({ authLogger }))
|
|
266
|
-
.post("/auth/login", async ({ body, authLogger }) => {
|
|
267
|
-
try {
|
|
268
|
-
// Your authentication logic
|
|
269
|
-
const user = await authenticateUser(body.email, body.password);
|
|
270
|
-
|
|
271
|
-
authLogger.logLogin(user.id, {
|
|
272
|
-
email: body.email,
|
|
273
|
-
ip: request.headers.get("x-forwarded-for"),
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
return { success: true, token: generateToken(user) };
|
|
277
|
-
} catch (error) {
|
|
278
|
-
authLogger.logAuthFailure("invalid_credentials", {
|
|
279
|
-
email: body.email,
|
|
280
|
-
});
|
|
281
|
-
throw error;
|
|
282
|
-
}
|
|
283
|
-
})
|
|
284
|
-
.listen(3000);
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Production Configuration for ElysiaJS
|
|
288
|
-
|
|
289
|
-
```typescript
|
|
290
|
-
import { Elysia } from "elysia";
|
|
291
|
-
import { elysiaLogger, Logger, LogLevel } from "@lssm/lib.logger";
|
|
292
|
-
|
|
293
|
-
const productionLogger = new Logger({
|
|
294
|
-
level: LogLevel.INFO,
|
|
295
|
-
environment: "production",
|
|
296
|
-
enableTracing: true,
|
|
297
|
-
enableTiming: true,
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
const app = new Elysia()
|
|
301
|
-
.use(
|
|
302
|
-
elysiaLogger({
|
|
303
|
-
logger: productionLogger,
|
|
304
|
-
logRequests: true,
|
|
305
|
-
logResponses: true,
|
|
306
|
-
excludePaths: ["/health", "/metrics", "/favicon.ico"],
|
|
307
|
-
maskSensitiveData: true,
|
|
308
|
-
})
|
|
309
|
-
)
|
|
310
|
-
.get("/health", () => ({ status: "ok" })) // This won't be logged
|
|
311
|
-
.get("/api/*", ({ logInfo, traceOperation }) => {
|
|
312
|
-
// All API routes automatically logged and traced
|
|
313
|
-
return traceOperation("business-logic", async () => {
|
|
314
|
-
// Your business logic here
|
|
315
|
-
return { success: true };
|
|
316
|
-
});
|
|
317
|
-
})
|
|
318
|
-
.listen(3000);
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
## HTTP Integration (Non-ElysiaJS)
|
|
322
|
-
|
|
323
|
-
### Express/Hono Middleware
|
|
324
|
-
|
|
325
|
-
```typescript
|
|
326
|
-
import { createHttpMiddleware } from "@lssm/lib.logger";
|
|
327
|
-
import express from "express";
|
|
328
|
-
|
|
329
|
-
const app = express();
|
|
330
|
-
|
|
331
|
-
// Add logging middleware
|
|
332
|
-
app.use(createHttpMiddleware()); // Uses default logger
|
|
333
|
-
|
|
334
|
-
// All subsequent requests will have context and tracing
|
|
335
|
-
app.get("/api/users", (req, res) => {
|
|
336
|
-
logger.info("Fetching users"); // Automatically includes request context
|
|
337
|
-
// ... handle request
|
|
338
|
-
});
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### Bun HTTP Server
|
|
342
|
-
|
|
343
|
-
```typescript
|
|
344
|
-
import { createBunHttpHandler } from "@lssm/lib.logger";
|
|
345
|
-
|
|
346
|
-
const handler = createBunHttpHandler(async (req) => {
|
|
347
|
-
// Request is automatically traced and timed
|
|
348
|
-
logger.info("Processing request"); // Includes request context
|
|
349
|
-
|
|
350
|
-
return new Response("Hello World");
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
Bun.serve({
|
|
354
|
-
fetch: handler,
|
|
355
|
-
port: 3000,
|
|
356
|
-
});
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
## WebSocket Integration
|
|
360
|
-
|
|
361
|
-
```typescript
|
|
362
|
-
import { createWebSocketMiddleware } from "@lssm/lib.logger";
|
|
363
|
-
|
|
364
|
-
const wsMiddleware = createWebSocketMiddleware();
|
|
365
|
-
|
|
366
|
-
// WebSocket server setup
|
|
367
|
-
const server = Bun.serve({
|
|
368
|
-
websocket: {
|
|
369
|
-
open: wsMiddleware.onOpen,
|
|
370
|
-
message: wsMiddleware.onMessage,
|
|
371
|
-
close: wsMiddleware.onClose,
|
|
372
|
-
error: wsMiddleware.onError,
|
|
373
|
-
},
|
|
374
|
-
});
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
## Cron Job Integration
|
|
378
|
-
|
|
379
|
-
```typescript
|
|
380
|
-
import { createCronWrapper } from "@lssm/lib.logger";
|
|
381
|
-
|
|
382
|
-
const cronWrapper = createCronWrapper();
|
|
383
|
-
|
|
384
|
-
// Wrap your cron jobs
|
|
385
|
-
const wrappedJob = cronWrapper("daily-cleanup", async () => {
|
|
386
|
-
logger.info("Starting daily cleanup");
|
|
387
|
-
await cleanupOldData();
|
|
388
|
-
logger.info("Cleanup completed");
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
// Schedule with your preferred cron library
|
|
392
|
-
schedule.scheduleJob("0 2 * * *", wrappedJob);
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
## Queue Processing Integration
|
|
396
|
-
|
|
397
|
-
```typescript
|
|
398
|
-
import { createQueueWrapper } from "@lssm/lib.logger";
|
|
399
|
-
|
|
400
|
-
const queueWrapper = createQueueWrapper();
|
|
401
|
-
|
|
402
|
-
// Wrap queue processors
|
|
403
|
-
const processEmailJob = queueWrapper.wrapProcessor(
|
|
404
|
-
"email-queue",
|
|
405
|
-
async (job: EmailJob, jobId: string) => {
|
|
406
|
-
logger.info("Processing email job", { recipient: job.recipient });
|
|
407
|
-
await sendEmail(job);
|
|
408
|
-
return { success: true };
|
|
409
|
-
}
|
|
410
|
-
);
|
|
411
|
-
|
|
412
|
-
// Log queue events
|
|
413
|
-
queueWrapper.logEnqueue("email-queue", "job-123", emailData);
|
|
414
|
-
queueWrapper.logDequeue("email-queue", "job-123");
|
|
415
|
-
queueWrapper.logRetry("email-queue", "job-123", 2, 5);
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
## Database Integration
|
|
419
|
-
|
|
420
|
-
```typescript
|
|
421
|
-
import { createDatabaseWrapper } from "@lssm/lib.logger";
|
|
422
|
-
|
|
423
|
-
const dbWrapper = createDatabaseWrapper();
|
|
424
|
-
|
|
425
|
-
// Wrap database operations
|
|
426
|
-
const users = await dbWrapper.wrapQuery(
|
|
427
|
-
"fetch-users",
|
|
428
|
-
() => prisma.user.findMany(),
|
|
429
|
-
{ table: "users", operation: "findMany" }
|
|
430
|
-
);
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## Configuration
|
|
434
|
-
|
|
435
|
-
```typescript
|
|
436
|
-
import { Logger, LogLevel } from "@lssm/lib.logger";
|
|
437
|
-
|
|
438
|
-
const logger = new Logger({
|
|
439
|
-
level: LogLevel.INFO, // Minimum log level
|
|
440
|
-
environment: "production", // 'development' | 'production' | 'test'
|
|
441
|
-
enableTracing: true, // Enable distributed tracing
|
|
442
|
-
enableTiming: true, // Enable performance timing
|
|
443
|
-
enableContext: true, // Enable context management
|
|
444
|
-
enableColors: true, // Enable colors in dev output
|
|
445
|
-
maxContextDepth: 10, // Max nested context depth
|
|
446
|
-
timestampFormat: "iso", // 'iso' | 'epoch' | 'relative'
|
|
447
|
-
});
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
## Custom Formatters
|
|
451
|
-
|
|
452
|
-
```typescript
|
|
453
|
-
import {
|
|
454
|
-
Logger,
|
|
455
|
-
CustomFormatter,
|
|
456
|
-
DevFormatter,
|
|
457
|
-
ProductionFormatter,
|
|
458
|
-
} from "@lssm/lib.logger";
|
|
459
|
-
|
|
460
|
-
// Use custom formatter
|
|
461
|
-
const customFormatter = new CustomFormatter(
|
|
462
|
-
"{timestamp} [{level}] {traceId} {message}",
|
|
463
|
-
(date) => date.toLocaleDateString()
|
|
464
|
-
);
|
|
465
|
-
|
|
466
|
-
const logger = new Logger();
|
|
467
|
-
logger.setFormatter(customFormatter);
|
|
468
|
-
|
|
469
|
-
// Or create your own
|
|
470
|
-
class MyFormatter implements Formatter {
|
|
471
|
-
format(entry: LogEntry): string {
|
|
472
|
-
return `${entry.timestamp} - ${entry.message}`;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
## Example Output
|
|
478
|
-
|
|
479
|
-
### Development Mode (Pretty)
|
|
480
|
-
|
|
481
|
-
```
|
|
482
|
-
14:32:15.123 ● INFO [trace:a1b2c3d4|span:e5f6g7h8] HTTP request started (12.34ms)
|
|
483
|
-
Context: { userId: "123", requestId: "req-456" }
|
|
484
|
-
Metadata: { method: "GET", url: "/api/users", userAgent: "Mozilla/5.0..." }
|
|
485
|
-
|
|
486
|
-
14:32:15.135 ✖ ERROR Database connection failed (156.78ms)
|
|
487
|
-
Error: ConnectionError: Unable to connect to database
|
|
488
|
-
at DatabaseClient.connect (database.js:45:12)
|
|
489
|
-
at UserService.fetchUsers (user-service.js:23:8)
|
|
490
|
-
at ApiHandler.getUsers (api-handler.js:67:15)
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### Production Mode (JSON)
|
|
494
|
-
|
|
495
|
-
```json
|
|
496
|
-
{"timestamp":"2024-01-15T14:32:15.123Z","level":"info","message":"HTTP request started","traceId":"a1b2c3d4e5f6g7h8","spanId":"e5f6g7h8","duration":12.34,"context":{"userId":"123","requestId":"req-456"},"metadata":{"method":"GET","url":"/api/users"}}
|
|
497
|
-
|
|
498
|
-
{"timestamp":"2024-01-15T14:32:15.135Z","level":"error","message":"Database connection failed","traceId":"a1b2c3d4e5f6g7h8","duration":156.78,"error":{"name":"ConnectionError","message":"Unable to connect to database","stack":"ConnectionError: Unable to connect to database\n at DatabaseClient.connect..."}}
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
## Best Practices
|
|
502
|
-
|
|
503
|
-
1. **Use context for request correlation**:
|
|
504
|
-
|
|
505
|
-
```typescript
|
|
506
|
-
logger.withContext({ requestId, userId }, () => {
|
|
507
|
-
// All logs in this scope will include requestId and userId
|
|
508
|
-
});
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
2. **Trace important operations**:
|
|
512
|
-
|
|
513
|
-
```typescript
|
|
514
|
-
await logger.trace(
|
|
515
|
-
{
|
|
516
|
-
operationType: "database",
|
|
517
|
-
operationName: "user-creation",
|
|
518
|
-
},
|
|
519
|
-
() => createUser(userData)
|
|
520
|
-
);
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
3. **Profile performance-critical code**:
|
|
524
|
-
|
|
525
|
-
```typescript
|
|
526
|
-
const result = await logger.profile("data-processing", () => {
|
|
527
|
-
return processLargeDataset(data);
|
|
528
|
-
});
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
4. **Use appropriate log levels**:
|
|
532
|
-
|
|
533
|
-
- `trace`: Very detailed debugging (typically disabled in production)
|
|
534
|
-
- `debug`: Debugging information
|
|
535
|
-
- `info`: General application flow
|
|
536
|
-
- `warn`: Warning conditions
|
|
537
|
-
- `error`: Error conditions
|
|
538
|
-
- `fatal`: Critical errors that might cause the application to exit
|
|
539
|
-
|
|
540
|
-
5. **Clean up in production**:
|
|
541
|
-
```typescript
|
|
542
|
-
process.on("SIGTERM", async () => {
|
|
543
|
-
await logger.flush();
|
|
544
|
-
process.exit(0);
|
|
545
|
-
});
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
## License
|
|
549
|
-
|
|
550
|
-
MIT
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContextData, TraceContext } from "./types.
|
|
1
|
+
import { ContextData, TraceContext } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/context.d.ts
|
|
4
4
|
declare class LogContext {
|
|
@@ -41,4 +41,4 @@ declare class LogContext {
|
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
43
|
export { LogContext };
|
|
44
|
-
//# sourceMappingURL=context.d.
|
|
44
|
+
//# sourceMappingURL=context.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.
|
|
1
|
+
{"version":3,"file":"context.d.mts","names":[],"sources":["../src/context.ts"],"sourcesContent":[],"mappings":";;;cAQa,UAAA;;EAAA,QAAA,OAAU;EAQC,WAAA,CAAA;EAUN,OAAA,WAAA,CAAA,CAAA,EAVM,UAUN;EAAuB;;;EAWV,GAAA,CAAA,CAAA,CAAA,CAAA,OAAA,EAXb,WAWa,EAAA,EAAA,EAAA,GAAA,GAXU,CAWV,CAAA,EAXc,CAWd;EAAgC;;;EA+B/C,MAAA,CAAA,CAAA,CAAA,CAAA,iBAAA,EA/Be,OA+Bf,CA/BuB,WA+BvB,CAAA,EAAA,EAAA,EAAA,GAAA,GA/B+C,CA+B/C,CAAA,EA/BmD,CA+BnD;EAQE;;;;;;;uBAhBK;;;;gBAQP;;;;kBAQE;;;;qBAUG"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{AsyncLocalStorage as e}from"node:async_hooks";var t=class t{static instance;storage;constructor(){this.storage=new e}static getInstance(){return t.instance||=new t,t.instance}run(e,t){let n={context:{...e},trace:this.getCurrentTrace()};return this.storage.run(n,t)}extend(e,t){let n={...this.getContext(),...e};return this.run(n,t)}set(e,t){let n=this.storage.getStore();n&&(n.context[e]=t)}get(e){return this.storage.getStore()?.context?.[e]}getContext(){return this.storage.getStore()?.context||{}}setTrace(e){let t=this.storage.getStore();t&&(t.trace=e)}getCurrentTrace(){return this.storage.getStore()?.trace}generateId(){return crypto.randomUUID()}};export{t as LogContext};
|
|
2
|
-
//# sourceMappingURL=context.
|
|
2
|
+
//# sourceMappingURL=context.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.mjs","names":["contextData: LogContextData","mergedContext: ContextData"],"sources":["../src/context.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { ContextData, TraceContext } from './types';\n\ninterface LogContextData {\n context: ContextData;\n trace?: TraceContext;\n}\n\nexport class LogContext {\n private static instance: LogContext;\n private storage: AsyncLocalStorage<LogContextData>;\n\n constructor() {\n this.storage = new AsyncLocalStorage<LogContextData>();\n }\n\n static getInstance(): LogContext {\n if (!LogContext.instance) {\n LogContext.instance = new LogContext();\n }\n return LogContext.instance;\n }\n\n /**\n * Run a function with a new context\n */\n run<T>(context: ContextData, fn: () => T): T {\n const contextData: LogContextData = {\n context: { ...context },\n trace: this.getCurrentTrace(),\n };\n return this.storage.run(contextData, fn) as T;\n }\n\n /**\n * Run a function with an extended context (merges with current)\n */\n extend<T>(additionalContext: Partial<ContextData>, fn: () => T): T {\n const currentContext = this.getContext();\n const mergedContext: ContextData = {\n ...currentContext,\n ...additionalContext,\n };\n return this.run(mergedContext, fn);\n }\n\n /**\n * Set context data for the current execution context\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n set(key: string, value: any): void {\n const current = this.storage.getStore();\n if (current) {\n current.context[key] = value;\n }\n }\n\n /**\n * Get a specific context value\n */\n get<T>(key: string): T | undefined {\n const current = this.storage.getStore();\n return current?.context?.[key];\n }\n\n /**\n * Get all context data\n */\n getContext(): ContextData {\n const current = this.storage.getStore();\n return current?.context || {};\n }\n\n /**\n * Set trace context\n */\n setTrace(trace: TraceContext): void {\n const current = this.storage.getStore();\n if (current) {\n current.trace = trace;\n }\n }\n\n /**\n * Get current trace context\n */\n getCurrentTrace(): TraceContext | undefined {\n const current = this.storage.getStore();\n return current?.trace;\n }\n /**\n * Generate a unique ID for requests/operations\n */\n generateId(): string {\n return crypto.randomUUID();\n }\n}\n"],"mappings":"qDAQA,IAAa,EAAb,MAAa,CAAW,CACtB,OAAe,SACf,QAEA,aAAc,CACZ,KAAK,QAAU,IAAI,EAGrB,OAAO,aAA0B,CAI/B,MAHA,CACE,EAAW,WAAW,IAAI,EAErB,EAAW,SAMpB,IAAO,EAAsB,EAAgB,CAC3C,IAAMA,EAA8B,CAClC,QAAS,CAAE,GAAG,EAAS,CACvB,MAAO,KAAK,iBAAiB,CAC9B,CACD,OAAO,KAAK,QAAQ,IAAI,EAAa,EAAG,CAM1C,OAAU,EAAyC,EAAgB,CAEjE,IAAMC,EAA6B,CACjC,GAFqB,KAAK,YAAY,CAGtC,GAAG,EACJ,CACD,OAAO,KAAK,IAAI,EAAe,EAAG,CAOpC,IAAI,EAAa,EAAkB,CACjC,IAAM,EAAU,KAAK,QAAQ,UAAU,CACnC,IACF,EAAQ,QAAQ,GAAO,GAO3B,IAAO,EAA4B,CAEjC,OADgB,KAAK,QAAQ,UAAU,EACvB,UAAU,GAM5B,YAA0B,CAExB,OADgB,KAAK,QAAQ,UAAU,EACvB,SAAW,EAAE,CAM/B,SAAS,EAA2B,CAClC,IAAM,EAAU,KAAK,QAAQ,UAAU,CACnC,IACF,EAAQ,MAAQ,GAOpB,iBAA4C,CAE1C,OADgB,KAAK,QAAQ,UAAU,EACvB,MAKlB,YAAqB,CACnB,OAAO,OAAO,YAAY"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ContextData } from "./types.
|
|
2
|
-
import { Logger } from "./logger.
|
|
1
|
+
import { ContextData } from "./types.mjs";
|
|
2
|
+
import { Logger } from "./logger.mjs";
|
|
3
3
|
import * as elysia0 from "elysia";
|
|
4
4
|
import { Elysia } from "elysia";
|
|
5
5
|
|
|
@@ -61,4 +61,4 @@ declare function elysiaLogger<T extends Elysia>(config?: ElysiaLoggerConfig): (a
|
|
|
61
61
|
declare const createElysiaLogger: typeof elysiaLogger;
|
|
62
62
|
//#endregion
|
|
63
63
|
export { ElysiaLoggerConfig, createElysiaLogger, elysiaLogger };
|
|
64
|
-
//# sourceMappingURL=elysia-plugin.d.
|
|
64
|
+
//# sourceMappingURL=elysia-plugin.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elysia-plugin.d.
|
|
1
|
+
{"version":3,"file":"elysia-plugin.d.mts","names":[],"sources":["../src/elysia-plugin.ts"],"sourcesContent":[],"mappings":";;;;;;UAKiB,kBAAA;WACN;;EADM,YAAA,CAAA,EAAA,OAAkB;EAWnB,YAAA,CAAA,EAAY,MAAA,EAAA;;;;;;iBAAZ,uBAAuB,iBAC7B,2BAYc,MAAC;EA+EqB,SAAA,EAAA,CAAA,CAAA;EAK5B,KAAA,EAAA,CAAA,CAAA;EAEG,MAAA,EAAA,CAAA,CAAA;EAMM,OAAA,EAAA,CAAA,CAAA;CAAY,EAAA;EAAR,OAAA,EAAA,CAAA,CAAA;EACZ,KAAA,EAAA,CAAA,CAAA;CAAR,EAAA;EAdmC,MAAA,EAAA,CAAA,CAAA;EAK5B,gBAAA,EAAA,CAAA,CAAA;EAEG,KAAA,EAAA,CAAA,CAAA;EAMM,OAAA,EAAA,CAAA,CAAA;EAAY,MAAA,EAAA,CAAA,CAAA;EAAR,QAAA,EAAA,CAAA,CAAA;CACZ,EAAA,CAAA,CAAA,EAAA;EAAR,MAAA,EAAA,CAAA,CAAA;EAAO,OAAA,EAAA,CAAA,CAAA;EA7FO,MAAA,EAAA,CAAA,CAAA;EAAA,gBAAA,EAAA,CAAA,CAAA;EA4GZ,QAAA,EAAA,CAAA,CAAA;;;;;;;;;;;mDA7BiC;iDAK5B,kBAEG;2EAMM,MAAI,QAAQ,SAC5B,QAAQ;;;;;YAAD,OAAA,CAAA;mDAd4B;iDAK5B,kBAEG;2EAMM,MAAI,QAAQ,SAC5B,QAAQ;;;cAeN,2BAAkB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{LogContext as e}from"./context.mjs";import{Logger as t}from"./logger.mjs";import{Elysia as n}from"elysia";function r(n={}){let{logger:r=new t,logRequests:i=!0,logResponses:a=!0,excludePaths:o=[`/health`,`/metrics`]}=n,s=e.getInstance();return function(e){return e.derive(e=>{let{request:t,path:n}=e;if(o.some(e=>n.startsWith(e)))return{logger:r};let a=new URL(t.url),c={requestId:s.generateId(),method:t.method,url:t.url,path:a.pathname,userAgent:t.headers.get(`user-agent`)||void 0,timestamp:new Date().toISOString()},l=performance.now();return s.run(c,()=>{i&&r.info(`→ ${t.method} ${n}`,{method:t.method,path:n,userAgent:c.userAgent,requestId:c.requestId})}),{logger:r,requestContext:c,startTime:l}}).onAfterHandle(e=>{let{request:t,startTime:n,requestContext:r,logger:i}=e;if(!n||!r)return;let o=performance.now()-n,s=new URL(t.url).pathname;a&&i.info(`← 200 ${t.method} ${s}`,{method:t.method,path:s,duration:`${o.toFixed(2)}ms`,requestId:r.requestId})}).onError(e=>{let{request:t,error:n,code:r,startTime:i,requestContext:a,logger:o}=e;if(!i||!a)return;let s=performance.now()-i,c=new URL(t.url).pathname;o?.error(`✖ ${r} ${t.method} ${c}`,{method:t.method,path:c,error:n?.toString?.()||`Unknown error`,code:r,duration:`${s.toFixed(2)}ms`,requestId:a.requestId})}).derive(()=>({logInfo:(e,t)=>{r.info(e,t)},logError:(e,t,n)=>{r.error(e,n,t)},traceOperation:async(e,t)=>r.trace({operationType:`custom`,operationName:e,autoTiming:!0},t)}))}}const i=r;export{i as createElysiaLogger,r as elysiaLogger};
|
|
2
|
+
//# sourceMappingURL=elysia-plugin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elysia-plugin.mjs","names":["requestContext: ContextData"],"sources":["../src/elysia-plugin.ts"],"sourcesContent":["import { Logger } from './logger';\nimport { LogContext } from './context';\nimport type { ContextData } from './types';\nimport { Elysia } from 'elysia';\n\nexport interface ElysiaLoggerConfig {\n logger?: Logger;\n logRequests?: boolean;\n logResponses?: boolean;\n excludePaths?: string[];\n}\n\n/**\n * Simple ElysiaJS Logger Plugin\n * Provides automatic request logging and tracing\n */\nexport function elysiaLogger<T extends Elysia>(\n config: ElysiaLoggerConfig = {}\n) {\n const {\n logger = new Logger(),\n logRequests = true,\n logResponses = true,\n excludePaths = ['/health', '/metrics'],\n } = config;\n\n const context = LogContext.getInstance();\n\n // For type compatibility, we use a factory function\n return function (app: T) {\n return app\n .derive((ctx) => {\n const { request, path } = ctx;\n\n // Skip excluded paths\n if (excludePaths.some((excludePath) => path.startsWith(excludePath))) {\n return { logger };\n }\n\n // Create request context\n const url = new URL(request.url);\n const requestContext: ContextData = {\n requestId: context.generateId(),\n method: request.method,\n url: request.url,\n path: url.pathname,\n userAgent: request.headers.get('user-agent') || undefined,\n timestamp: new Date().toISOString(),\n };\n\n const startTime = performance.now();\n\n // Run in context\n context.run(requestContext, () => {\n // Log request\n if (logRequests) {\n logger.info(`→ ${request.method} ${path}`, {\n method: request.method,\n path,\n userAgent: requestContext.userAgent,\n requestId: requestContext.requestId,\n });\n }\n });\n\n return {\n logger,\n requestContext,\n startTime,\n };\n })\n .onAfterHandle((ctx) => {\n const { request, startTime, requestContext, logger } = ctx;\n\n if (!startTime || !requestContext) return;\n\n const duration = performance.now() - startTime;\n const path = new URL(request.url).pathname;\n\n if (logResponses) {\n logger.info(`← 200 ${request.method} ${path}`, {\n method: request.method,\n path,\n duration: `${duration.toFixed(2)}ms`,\n requestId: requestContext.requestId,\n });\n }\n })\n .onError((ctx) => {\n const { request, error, code, startTime, requestContext, logger } = ctx;\n\n if (!startTime || !requestContext) return;\n\n const duration = performance.now() - startTime;\n const path = new URL(request.url).pathname;\n\n logger?.error(`✖ ${code} ${request.method} ${path}`, {\n method: request.method,\n path,\n error: error?.toString?.() || 'Unknown error',\n code,\n duration: `${duration.toFixed(2)}ms`,\n requestId: requestContext.requestId,\n });\n })\n .derive(() => ({\n // Helper functions available in route handlers\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n logInfo: (message: string, metadata?: Record<string, any>) => {\n logger.info(message, metadata);\n },\n logError: (\n message: string,\n error?: Error,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n metadata?: Record<string, any>\n ) => {\n logger.error(message, metadata, error);\n },\n traceOperation: async <T>(\n operationName: string,\n operation: () => T | Promise<T>\n ): Promise<T> => {\n return logger.trace(\n {\n operationType: 'custom',\n operationName,\n autoTiming: true,\n },\n operation\n );\n },\n }));\n };\n}\n\n// Export convenience functions\nexport const createElysiaLogger = elysiaLogger;\n"],"mappings":"iHAgBA,SAAgB,EACd,EAA6B,EAAE,CAC/B,CACA,GAAM,CACJ,SAAS,IAAI,EACb,cAAc,GACd,eAAe,GACf,eAAe,CAAC,UAAW,WAAW,EACpC,EAEE,EAAU,EAAW,aAAa,CAGxC,OAAO,SAAU,EAAQ,CACvB,OAAO,EACJ,OAAQ,GAAQ,CACf,GAAM,CAAE,UAAS,QAAS,EAG1B,GAAI,EAAa,KAAM,GAAgB,EAAK,WAAW,EAAY,CAAC,CAClE,MAAO,CAAE,SAAQ,CAInB,IAAM,EAAM,IAAI,IAAI,EAAQ,IAAI,CAC1BA,EAA8B,CAClC,UAAW,EAAQ,YAAY,CAC/B,OAAQ,EAAQ,OAChB,IAAK,EAAQ,IACb,KAAM,EAAI,SACV,UAAW,EAAQ,QAAQ,IAAI,aAAa,EAAI,IAAA,GAChD,UAAW,IAAI,MAAM,CAAC,aAAa,CACpC,CAEK,EAAY,YAAY,KAAK,CAenC,OAZA,EAAQ,IAAI,MAAsB,CAE5B,GACF,EAAO,KAAK,KAAK,EAAQ,OAAO,GAAG,IAAQ,CACzC,OAAQ,EAAQ,OAChB,OACA,UAAW,EAAe,UAC1B,UAAW,EAAe,UAC3B,CAAC,EAEJ,CAEK,CACL,SACA,iBACA,YACD,EACD,CACD,cAAe,GAAQ,CACtB,GAAM,CAAE,UAAS,YAAW,iBAAgB,OAAA,GAAW,EAEvD,GAAI,CAAC,GAAa,CAAC,EAAgB,OAEnC,IAAM,EAAW,YAAY,KAAK,CAAG,EAC/B,EAAO,IAAI,IAAI,EAAQ,IAAI,CAAC,SAE9B,GACF,EAAO,KAAK,SAAS,EAAQ,OAAO,GAAG,IAAQ,CAC7C,OAAQ,EAAQ,OAChB,OACA,SAAU,GAAG,EAAS,QAAQ,EAAE,CAAC,IACjC,UAAW,EAAe,UAC3B,CAAC,EAEJ,CACD,QAAS,GAAQ,CAChB,GAAM,CAAE,UAAS,QAAO,OAAM,YAAW,iBAAgB,OAAA,GAAW,EAEpE,GAAI,CAAC,GAAa,CAAC,EAAgB,OAEnC,IAAM,EAAW,YAAY,KAAK,CAAG,EAC/B,EAAO,IAAI,IAAI,EAAQ,IAAI,CAAC,SAElC,GAAQ,MAAM,KAAK,EAAK,GAAG,EAAQ,OAAO,GAAG,IAAQ,CACnD,OAAQ,EAAQ,OAChB,OACA,MAAO,GAAO,YAAY,EAAI,gBAC9B,OACA,SAAU,GAAG,EAAS,QAAQ,EAAE,CAAC,IACjC,UAAW,EAAe,UAC3B,CAAC,EACF,CACD,YAAc,CAGb,SAAU,EAAiB,IAAmC,CAC5D,EAAO,KAAK,EAAS,EAAS,EAEhC,UACE,EACA,EAEA,IACG,CACH,EAAO,MAAM,EAAS,EAAU,EAAM,EAExC,eAAgB,MACd,EACA,IAEO,EAAO,MACZ,CACE,cAAe,SACf,gBACA,WAAY,GACb,CACD,EACD,CAEJ,EAAE,EAKT,MAAa,EAAqB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Formatter, LogEntry } from "./types.
|
|
1
|
+
import { Formatter, LogEntry } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/formatters.d.ts
|
|
4
4
|
declare class DevFormatter implements Formatter {
|
|
@@ -26,4 +26,4 @@ declare class CustomFormatter implements Formatter {
|
|
|
26
26
|
}
|
|
27
27
|
//#endregion
|
|
28
28
|
export { CustomFormatter, DevFormatter, ProductionFormatter };
|
|
29
|
-
//# sourceMappingURL=formatters.d.
|
|
29
|
+
//# sourceMappingURL=formatters.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatters.d.
|
|
1
|
+
{"version":3,"file":"formatters.d.mts","names":[],"sources":["../src/formatters.ts"],"sourcesContent":[],"mappings":";;;cAkCa,YAAA,YAAwB;;EAAxB,WAAA,CAAA,YAOG,CAPU,EAOV,OAAA;EAkJH,MAAA,CAAA,KAAA,EAlJG,QAkJiB,CAAA,EAAA,MAAA;EAkDpB,QAAA,eAAgB;EAML,QAAA,eAAA;EAMR,QAAA,cAAA;EAZwB,QAAA,aAAA;EAAS,QAAA,cAAA;;;;;;cAlDpC,mBAAA,YAA+B;gBAC5B;;cAiDH,eAAA,YAA2B;;;qDAMhB;gBAMR"}
|