evlog 0.1.0 → 1.0.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 +75 -12
- package/dist/error.d.mts +21 -11
- package/dist/error.d.ts +21 -11
- package/dist/error.mjs +12 -8
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.mjs +3 -2
- package/dist/logger.d.mts +1 -6
- package/dist/logger.d.ts +1 -6
- package/dist/logger.mjs +1 -4
- package/dist/nitro/plugin.mjs +20 -8
- package/dist/nuxt/module.mjs +11 -7
- package/dist/runtime/client/log.d.mts +9 -0
- package/dist/runtime/client/log.d.ts +9 -0
- package/dist/runtime/{composables → client}/log.mjs +2 -3
- package/dist/runtime/{plugin.client.mjs → client/plugin.mjs} +4 -3
- package/dist/runtime/server/useLogger.d.mts +5 -0
- package/dist/runtime/server/useLogger.d.ts +5 -0
- package/dist/runtime/utils/parseError.d.mts +5 -0
- package/dist/runtime/utils/parseError.d.ts +5 -0
- package/dist/runtime/utils/parseError.mjs +28 -0
- package/dist/types.d.mts +40 -2
- package/dist/types.d.ts +40 -2
- package/dist/utils.d.mts +3 -22
- package/dist/utils.d.ts +3 -22
- package/dist/utils.mjs +4 -1
- package/package.json +7 -3
- package/dist/runtime/composables/index.d.mts +0 -4
- package/dist/runtime/composables/index.d.ts +0 -4
- package/dist/runtime/composables/index.mjs +0 -2
- package/dist/runtime/composables/log.d.mts +0 -18
- package/dist/runtime/composables/log.d.ts +0 -18
- package/dist/runtime/composables/useLogger.d.mts +0 -21
- package/dist/runtime/composables/useLogger.d.ts +0 -21
- /package/dist/runtime/{plugin.client.d.mts → client/plugin.d.mts} +0 -0
- /package/dist/runtime/{plugin.client.d.ts → client/plugin.d.ts} +0 -0
- /package/dist/runtime/{composables → server}/useLogger.mjs +0 -0
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ That's it. Now use `useLogger(event)` in any API route:
|
|
|
104
104
|
|
|
105
105
|
```typescript
|
|
106
106
|
// server/api/checkout.post.ts
|
|
107
|
-
import { useLogger,
|
|
107
|
+
import { useLogger, createError } from 'evlog'
|
|
108
108
|
|
|
109
109
|
export default defineEventHandler(async (event) => {
|
|
110
110
|
const log = useLogger(event)
|
|
@@ -124,8 +124,9 @@ export default defineEventHandler(async (event) => {
|
|
|
124
124
|
} catch (error) {
|
|
125
125
|
log.error(error, { step: 'payment' })
|
|
126
126
|
|
|
127
|
-
throw
|
|
127
|
+
throw createError({
|
|
128
128
|
message: 'Payment failed',
|
|
129
|
+
status: 402,
|
|
129
130
|
why: error.message,
|
|
130
131
|
fix: 'Try a different payment method or contact your bank',
|
|
131
132
|
})
|
|
@@ -173,7 +174,7 @@ Same API, same wide events:
|
|
|
173
174
|
|
|
174
175
|
```typescript
|
|
175
176
|
// routes/api/documents/[id]/export.post.ts
|
|
176
|
-
import { useLogger,
|
|
177
|
+
import { useLogger, createError } from 'evlog'
|
|
177
178
|
|
|
178
179
|
export default defineEventHandler(async (event) => {
|
|
179
180
|
const log = useLogger(event)
|
|
@@ -189,8 +190,9 @@ export default defineEventHandler(async (event) => {
|
|
|
189
190
|
// Load document from database
|
|
190
191
|
const document = await db.documents.findUnique({ where: { id: documentId } })
|
|
191
192
|
if (!document) {
|
|
192
|
-
throw
|
|
193
|
+
throw createError({
|
|
193
194
|
message: 'Document not found',
|
|
195
|
+
status: 404,
|
|
194
196
|
why: `No document with ID "${documentId}" exists`,
|
|
195
197
|
fix: 'Check the document ID and try again',
|
|
196
198
|
})
|
|
@@ -206,8 +208,9 @@ export default defineEventHandler(async (event) => {
|
|
|
206
208
|
} catch (error) {
|
|
207
209
|
log.error(error, { step: 'export-generation' })
|
|
208
210
|
|
|
209
|
-
throw
|
|
211
|
+
throw createError({
|
|
210
212
|
message: 'Export failed',
|
|
213
|
+
status: 500,
|
|
211
214
|
why: `Failed to generate ${body.format} export: ${error.message}`,
|
|
212
215
|
fix: 'Try a different format or contact support',
|
|
213
216
|
})
|
|
@@ -238,7 +241,7 @@ Errors should tell you **what** happened, **why**, and **how to fix it**.
|
|
|
238
241
|
|
|
239
242
|
```typescript
|
|
240
243
|
// server/api/repos/sync.post.ts
|
|
241
|
-
import { useLogger,
|
|
244
|
+
import { useLogger, createError } from 'evlog'
|
|
242
245
|
|
|
243
246
|
export default defineEventHandler(async (event) => {
|
|
244
247
|
const log = useLogger(event)
|
|
@@ -252,8 +255,9 @@ export default defineEventHandler(async (event) => {
|
|
|
252
255
|
} catch (error) {
|
|
253
256
|
log.error(error, { step: 'github-sync' })
|
|
254
257
|
|
|
255
|
-
throw
|
|
258
|
+
throw createError({
|
|
256
259
|
message: 'Failed to sync repository',
|
|
260
|
+
status: 503,
|
|
257
261
|
why: 'GitHub API rate limit exceeded',
|
|
258
262
|
fix: 'Wait 1 hour or use a different token',
|
|
259
263
|
link: 'https://docs.github.com/en/rest/rate-limit',
|
|
@@ -302,7 +306,7 @@ migrationLog.emit()
|
|
|
302
306
|
|
|
303
307
|
```typescript
|
|
304
308
|
// workers/sync-job.ts
|
|
305
|
-
import { initLogger, createRequestLogger,
|
|
309
|
+
import { initLogger, createRequestLogger, createError } from 'evlog'
|
|
306
310
|
|
|
307
311
|
initLogger({
|
|
308
312
|
env: {
|
|
@@ -378,13 +382,18 @@ log.emit() // Emit final event
|
|
|
378
382
|
log.getContext() // Get current context
|
|
379
383
|
```
|
|
380
384
|
|
|
381
|
-
### `
|
|
385
|
+
### `createError(options)`
|
|
382
386
|
|
|
383
|
-
Create a structured error.
|
|
387
|
+
Create a structured error with HTTP status support. Import from `evlog` directly to avoid conflicts with Nuxt/Nitro's `createError`.
|
|
388
|
+
|
|
389
|
+
> **Note**: `createEvlogError` is also available as an auto-imported alias in Nuxt/Nitro to avoid conflicts.
|
|
384
390
|
|
|
385
391
|
```typescript
|
|
386
|
-
|
|
392
|
+
import { createError } from 'evlog'
|
|
393
|
+
|
|
394
|
+
createError({
|
|
387
395
|
message: string // What happened
|
|
396
|
+
status?: number // HTTP status code (default: 500)
|
|
388
397
|
why?: string // Why it happened
|
|
389
398
|
fix?: string // How to fix it
|
|
390
399
|
link?: string // Documentation URL
|
|
@@ -392,6 +401,34 @@ defineError({
|
|
|
392
401
|
})
|
|
393
402
|
```
|
|
394
403
|
|
|
404
|
+
### `parseError(error)`
|
|
405
|
+
|
|
406
|
+
Parse a caught error into a flat structure with all evlog fields. Auto-imported in Nuxt.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import { parseError } from 'evlog'
|
|
410
|
+
|
|
411
|
+
try {
|
|
412
|
+
await $fetch('/api/checkout')
|
|
413
|
+
} catch (err) {
|
|
414
|
+
const error = parseError(err)
|
|
415
|
+
|
|
416
|
+
// Direct access to all fields
|
|
417
|
+
console.log(error.message) // "Payment failed"
|
|
418
|
+
console.log(error.status) // 402
|
|
419
|
+
console.log(error.why) // "Card declined"
|
|
420
|
+
console.log(error.fix) // "Try another card"
|
|
421
|
+
console.log(error.link) // "https://docs.example.com/..."
|
|
422
|
+
|
|
423
|
+
// Use with toast
|
|
424
|
+
toast.add({
|
|
425
|
+
title: error.message,
|
|
426
|
+
description: error.why,
|
|
427
|
+
color: 'error',
|
|
428
|
+
})
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
395
432
|
## Framework Support
|
|
396
433
|
|
|
397
434
|
evlog works with any framework powered by [Nitro](https://nitro.unjs.io/):
|
|
@@ -405,9 +442,35 @@ evlog works with any framework powered by [Nitro](https://nitro.unjs.io/):
|
|
|
405
442
|
| **TanStack Start** | `plugins: ['evlog/nitro']` |
|
|
406
443
|
| **Standalone Nitro** | `plugins: ['evlog/nitro']` |
|
|
407
444
|
|
|
445
|
+
## Agent Skills
|
|
446
|
+
|
|
447
|
+
evlog provides [Agent Skills](https://github.com/boristane/agent-skills) to help AI coding assistants understand and implement proper logging patterns in your codebase.
|
|
448
|
+
|
|
449
|
+
### Installation
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
npx add-skill hugorcd/evlog
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### What it does
|
|
456
|
+
|
|
457
|
+
Once installed, your AI assistant will:
|
|
458
|
+
- Review your logging code and suggest wide event patterns
|
|
459
|
+
- Help refactor scattered `console.log` calls into structured events
|
|
460
|
+
- Guide you to use `createError()` for self-documenting errors
|
|
461
|
+
- Ensure proper use of `useLogger(event)` in Nuxt/Nitro routes
|
|
462
|
+
|
|
463
|
+
### Examples
|
|
464
|
+
|
|
465
|
+
```
|
|
466
|
+
Add logging to this endpoint
|
|
467
|
+
Review my logging code
|
|
468
|
+
Help me set up logging for this service
|
|
469
|
+
```
|
|
470
|
+
|
|
408
471
|
## Philosophy
|
|
409
472
|
|
|
410
|
-
Inspired by [Logging Sucks](https://loggingsucks.com/) by [Boris Tane](https://
|
|
473
|
+
Inspired by [Logging Sucks](https://loggingsucks.com/) by [Boris Tane](https://x.com/boristane).
|
|
411
474
|
|
|
412
475
|
1. **Wide Events**: One log per request with all context
|
|
413
476
|
2. **Structured Errors**: Errors that explain themselves
|
package/dist/error.d.mts
CHANGED
|
@@ -7,6 +7,7 @@ import { ErrorOptions } from './types.mjs';
|
|
|
7
7
|
* ```ts
|
|
8
8
|
* throw new EvlogError({
|
|
9
9
|
* message: 'Failed to sync repository',
|
|
10
|
+
* status: 503,
|
|
10
11
|
* why: 'GitHub API rate limit exceeded',
|
|
11
12
|
* fix: 'Wait 1 hour or use a different token',
|
|
12
13
|
* link: 'https://docs.github.com/en/rest/rate-limit',
|
|
@@ -15,33 +16,42 @@ import { ErrorOptions } from './types.mjs';
|
|
|
15
16
|
* ```
|
|
16
17
|
*/
|
|
17
18
|
declare class EvlogError extends Error {
|
|
19
|
+
readonly status: number;
|
|
18
20
|
readonly why?: string;
|
|
19
21
|
readonly fix?: string;
|
|
20
22
|
readonly link?: string;
|
|
21
23
|
constructor(options: ErrorOptions | string);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
get statusCode(): number;
|
|
25
|
+
get data(): {
|
|
26
|
+
why: string | undefined;
|
|
27
|
+
fix: string | undefined;
|
|
28
|
+
link: string | undefined;
|
|
29
|
+
} | undefined;
|
|
25
30
|
toString(): string;
|
|
26
|
-
/**
|
|
27
|
-
* Convert to plain object for JSON serialization
|
|
28
|
-
*/
|
|
29
31
|
toJSON(): Record<string, unknown>;
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
32
|
-
* Create
|
|
34
|
+
* Create a structured error with context for debugging and user-facing messages.
|
|
33
35
|
*
|
|
34
|
-
*
|
|
36
|
+
* @param options - Error message string or full options object
|
|
37
|
+
* @returns EvlogError instance compatible with Nitro's error handling
|
|
35
38
|
*
|
|
36
39
|
* @example
|
|
37
40
|
* ```ts
|
|
38
|
-
*
|
|
41
|
+
* // Simple error
|
|
42
|
+
* throw createError('Something went wrong')
|
|
43
|
+
*
|
|
44
|
+
* // Structured error with context
|
|
45
|
+
* throw createError({
|
|
39
46
|
* message: 'Payment failed',
|
|
47
|
+
* status: 402,
|
|
40
48
|
* why: 'Card declined by issuer',
|
|
41
49
|
* fix: 'Try a different payment method',
|
|
50
|
+
* link: 'https://docs.example.com/payments',
|
|
42
51
|
* })
|
|
43
52
|
* ```
|
|
44
53
|
*/
|
|
45
|
-
declare function
|
|
54
|
+
declare function createError(options: ErrorOptions | string): EvlogError;
|
|
55
|
+
declare const createEvlogError: typeof createError;
|
|
46
56
|
|
|
47
|
-
export { EvlogError,
|
|
57
|
+
export { EvlogError, createError, createEvlogError };
|
package/dist/error.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { ErrorOptions } from './types.js';
|
|
|
7
7
|
* ```ts
|
|
8
8
|
* throw new EvlogError({
|
|
9
9
|
* message: 'Failed to sync repository',
|
|
10
|
+
* status: 503,
|
|
10
11
|
* why: 'GitHub API rate limit exceeded',
|
|
11
12
|
* fix: 'Wait 1 hour or use a different token',
|
|
12
13
|
* link: 'https://docs.github.com/en/rest/rate-limit',
|
|
@@ -15,33 +16,42 @@ import { ErrorOptions } from './types.js';
|
|
|
15
16
|
* ```
|
|
16
17
|
*/
|
|
17
18
|
declare class EvlogError extends Error {
|
|
19
|
+
readonly status: number;
|
|
18
20
|
readonly why?: string;
|
|
19
21
|
readonly fix?: string;
|
|
20
22
|
readonly link?: string;
|
|
21
23
|
constructor(options: ErrorOptions | string);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
get statusCode(): number;
|
|
25
|
+
get data(): {
|
|
26
|
+
why: string | undefined;
|
|
27
|
+
fix: string | undefined;
|
|
28
|
+
link: string | undefined;
|
|
29
|
+
} | undefined;
|
|
25
30
|
toString(): string;
|
|
26
|
-
/**
|
|
27
|
-
* Convert to plain object for JSON serialization
|
|
28
|
-
*/
|
|
29
31
|
toJSON(): Record<string, unknown>;
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
32
|
-
* Create
|
|
34
|
+
* Create a structured error with context for debugging and user-facing messages.
|
|
33
35
|
*
|
|
34
|
-
*
|
|
36
|
+
* @param options - Error message string or full options object
|
|
37
|
+
* @returns EvlogError instance compatible with Nitro's error handling
|
|
35
38
|
*
|
|
36
39
|
* @example
|
|
37
40
|
* ```ts
|
|
38
|
-
*
|
|
41
|
+
* // Simple error
|
|
42
|
+
* throw createError('Something went wrong')
|
|
43
|
+
*
|
|
44
|
+
* // Structured error with context
|
|
45
|
+
* throw createError({
|
|
39
46
|
* message: 'Payment failed',
|
|
47
|
+
* status: 402,
|
|
40
48
|
* why: 'Card declined by issuer',
|
|
41
49
|
* fix: 'Try a different payment method',
|
|
50
|
+
* link: 'https://docs.example.com/payments',
|
|
42
51
|
* })
|
|
43
52
|
* ```
|
|
44
53
|
*/
|
|
45
|
-
declare function
|
|
54
|
+
declare function createError(options: ErrorOptions | string): EvlogError;
|
|
55
|
+
declare const createEvlogError: typeof createError;
|
|
46
56
|
|
|
47
|
-
export { EvlogError,
|
|
57
|
+
export { EvlogError, createError, createEvlogError };
|
package/dist/error.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { colors, isServer } from './utils.mjs';
|
|
2
2
|
|
|
3
3
|
class EvlogError extends Error {
|
|
4
|
+
status;
|
|
4
5
|
why;
|
|
5
6
|
fix;
|
|
6
7
|
link;
|
|
@@ -8,6 +9,7 @@ class EvlogError extends Error {
|
|
|
8
9
|
const opts = typeof options === "string" ? { message: options } : options;
|
|
9
10
|
super(opts.message, { cause: opts.cause });
|
|
10
11
|
this.name = "EvlogError";
|
|
12
|
+
this.status = opts.status ?? 500;
|
|
11
13
|
this.why = opts.why;
|
|
12
14
|
this.fix = opts.fix;
|
|
13
15
|
this.link = opts.link;
|
|
@@ -15,9 +17,12 @@ class EvlogError extends Error {
|
|
|
15
17
|
Error.captureStackTrace(this, EvlogError);
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
get statusCode() {
|
|
21
|
+
return this.status;
|
|
22
|
+
}
|
|
23
|
+
get data() {
|
|
24
|
+
return this.why || this.fix || this.link ? { why: this.why, fix: this.fix, link: this.link } : void 0;
|
|
25
|
+
}
|
|
21
26
|
toString() {
|
|
22
27
|
const useColors = isServer();
|
|
23
28
|
const red = useColors ? colors.red : "";
|
|
@@ -42,13 +47,11 @@ class EvlogError extends Error {
|
|
|
42
47
|
}
|
|
43
48
|
return lines.join("\n");
|
|
44
49
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Convert to plain object for JSON serialization
|
|
47
|
-
*/
|
|
48
50
|
toJSON() {
|
|
49
51
|
return {
|
|
50
52
|
name: this.name,
|
|
51
53
|
message: this.message,
|
|
54
|
+
status: this.status,
|
|
52
55
|
why: this.why,
|
|
53
56
|
fix: this.fix,
|
|
54
57
|
link: this.link,
|
|
@@ -57,8 +60,9 @@ class EvlogError extends Error {
|
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
|
-
function
|
|
63
|
+
function createError(options) {
|
|
61
64
|
return new EvlogError(options);
|
|
62
65
|
}
|
|
66
|
+
const createEvlogError = createError;
|
|
63
67
|
|
|
64
|
-
export { EvlogError,
|
|
68
|
+
export { EvlogError, createError, createEvlogError };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { EvlogError,
|
|
1
|
+
export { EvlogError, createError, createEvlogError } from './error.mjs';
|
|
2
2
|
export { createRequestLogger, getEnvironment, initLogger, log } from './logger.mjs';
|
|
3
|
-
export { useLogger } from './runtime/
|
|
4
|
-
export {
|
|
5
|
-
|
|
3
|
+
export { useLogger } from './runtime/server/useLogger.mjs';
|
|
4
|
+
export { parseError } from './runtime/utils/parseError.mjs';
|
|
5
|
+
export { BaseWideEvent, EnvironmentContext, ErrorOptions, H3EventContext, Log, LogLevel, LoggerConfig, ParsedError, RequestLogger, RequestLoggerOptions, ServerEvent, WideEvent } from './types.mjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { EvlogError,
|
|
1
|
+
export { EvlogError, createError, createEvlogError } from './error.js';
|
|
2
2
|
export { createRequestLogger, getEnvironment, initLogger, log } from './logger.js';
|
|
3
|
-
export { useLogger } from './runtime/
|
|
4
|
-
export {
|
|
5
|
-
|
|
3
|
+
export { useLogger } from './runtime/server/useLogger.js';
|
|
4
|
+
export { parseError } from './runtime/utils/parseError.js';
|
|
5
|
+
export { BaseWideEvent, EnvironmentContext, ErrorOptions, H3EventContext, Log, LogLevel, LoggerConfig, ParsedError, RequestLogger, RequestLoggerOptions, ServerEvent, WideEvent } from './types.js';
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { EvlogError,
|
|
1
|
+
export { EvlogError, createError, createEvlogError } from './error.mjs';
|
|
2
2
|
export { createRequestLogger, getEnvironment, initLogger, log } from './logger.mjs';
|
|
3
|
-
export { useLogger } from './runtime/
|
|
3
|
+
export { useLogger } from './runtime/server/useLogger.mjs';
|
|
4
|
+
export { parseError } from './runtime/utils/parseError.mjs';
|
|
4
5
|
import './utils.mjs';
|
package/dist/logger.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RequestLogger, EnvironmentContext, LoggerConfig, Log } from './types.mjs';
|
|
1
|
+
import { RequestLoggerOptions, RequestLogger, EnvironmentContext, LoggerConfig, Log } from './types.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Initialize the logger with configuration.
|
|
@@ -15,11 +15,6 @@ declare function initLogger(config?: LoggerConfig): void;
|
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
17
|
declare const log: Log;
|
|
18
|
-
interface RequestLoggerOptions {
|
|
19
|
-
method?: string;
|
|
20
|
-
path?: string;
|
|
21
|
-
requestId?: string;
|
|
22
|
-
}
|
|
23
18
|
/**
|
|
24
19
|
* Create a request-scoped logger for building wide events.
|
|
25
20
|
*
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RequestLogger, EnvironmentContext, LoggerConfig, Log } from './types.js';
|
|
1
|
+
import { RequestLoggerOptions, RequestLogger, EnvironmentContext, LoggerConfig, Log } from './types.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Initialize the logger with configuration.
|
|
@@ -15,11 +15,6 @@ declare function initLogger(config?: LoggerConfig): void;
|
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
17
|
declare const log: Log;
|
|
18
|
-
interface RequestLoggerOptions {
|
|
19
|
-
method?: string;
|
|
20
|
-
path?: string;
|
|
21
|
-
requestId?: string;
|
|
22
|
-
}
|
|
23
18
|
/**
|
|
24
19
|
* Create a request-scoped logger for building wide events.
|
|
25
20
|
*
|
package/dist/logger.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isDev, detectEnvironment, formatDuration, colors, getLevelColor } from './utils.mjs';
|
|
1
|
+
import { isDev, detectEnvironment, formatDuration, getConsoleMethod, colors, getLevelColor } from './utils.mjs';
|
|
2
2
|
|
|
3
3
|
let globalEnv = {
|
|
4
4
|
service: "app",
|
|
@@ -16,9 +16,6 @@ function initLogger(config = {}) {
|
|
|
16
16
|
};
|
|
17
17
|
globalPretty = config.pretty ?? isDev();
|
|
18
18
|
}
|
|
19
|
-
function getConsoleMethod(level) {
|
|
20
|
-
return level === "error" ? "error" : level === "warn" ? "warn" : "log";
|
|
21
|
-
}
|
|
22
19
|
function emitWideEvent(level, event) {
|
|
23
20
|
const formatted = {
|
|
24
21
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
package/dist/nitro/plugin.mjs
CHANGED
|
@@ -3,27 +3,39 @@ import { initLogger, createRequestLogger } from '../logger.mjs';
|
|
|
3
3
|
import '../utils.mjs';
|
|
4
4
|
|
|
5
5
|
function getResponseStatus(event) {
|
|
6
|
-
|
|
6
|
+
if (event.node?.res?.statusCode) {
|
|
7
|
+
return event.node.res.statusCode;
|
|
8
|
+
}
|
|
9
|
+
if (event.response?.status) {
|
|
10
|
+
return event.response.status;
|
|
11
|
+
}
|
|
12
|
+
if (typeof event.context.status === "number") {
|
|
13
|
+
return event.context.status;
|
|
14
|
+
}
|
|
15
|
+
return 200;
|
|
7
16
|
}
|
|
8
17
|
const plugin = defineNitroPlugin((nitroApp) => {
|
|
9
18
|
initLogger();
|
|
10
19
|
nitroApp.hooks.hook("request", (event) => {
|
|
20
|
+
const e = event;
|
|
11
21
|
const log = createRequestLogger({
|
|
12
|
-
method:
|
|
13
|
-
path:
|
|
14
|
-
requestId:
|
|
22
|
+
method: e.method,
|
|
23
|
+
path: e.path,
|
|
24
|
+
requestId: e.context.requestId || crypto.randomUUID()
|
|
15
25
|
});
|
|
16
|
-
|
|
26
|
+
e.context.log = log;
|
|
17
27
|
});
|
|
18
28
|
nitroApp.hooks.hook("afterResponse", (event) => {
|
|
19
|
-
const
|
|
29
|
+
const e = event;
|
|
30
|
+
const log = e.context.log;
|
|
20
31
|
if (log) {
|
|
21
|
-
log.set({ status: getResponseStatus(
|
|
32
|
+
log.set({ status: getResponseStatus(e) });
|
|
22
33
|
log.emit();
|
|
23
34
|
}
|
|
24
35
|
});
|
|
25
36
|
nitroApp.hooks.hook("error", (error, { event }) => {
|
|
26
|
-
const
|
|
37
|
+
const e = event;
|
|
38
|
+
const log = e?.context.log;
|
|
27
39
|
if (log) {
|
|
28
40
|
log.error(error);
|
|
29
41
|
}
|
package/dist/nuxt/module.mjs
CHANGED
|
@@ -4,7 +4,7 @@ const module$1 = defineNuxtModule({
|
|
|
4
4
|
meta: {
|
|
5
5
|
name: "evlog",
|
|
6
6
|
configKey: "evlog",
|
|
7
|
-
docs: "https://
|
|
7
|
+
docs: "https://evlog.dev"
|
|
8
8
|
},
|
|
9
9
|
defaults: {},
|
|
10
10
|
setup(options, nuxt) {
|
|
@@ -15,30 +15,34 @@ const module$1 = defineNuxtModule({
|
|
|
15
15
|
};
|
|
16
16
|
addServerPlugin(resolver.resolve("../nitro/plugin"));
|
|
17
17
|
addPlugin({
|
|
18
|
-
src: resolver.resolve("../runtime/plugin
|
|
18
|
+
src: resolver.resolve("../runtime/client/plugin"),
|
|
19
19
|
mode: "client"
|
|
20
20
|
});
|
|
21
21
|
addImports([
|
|
22
22
|
{
|
|
23
23
|
name: "log",
|
|
24
|
-
from: resolver.resolve("../runtime/
|
|
24
|
+
from: resolver.resolve("../runtime/client/log")
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
name: "
|
|
27
|
+
name: "createEvlogError",
|
|
28
28
|
from: resolver.resolve("../error")
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "parseError",
|
|
32
|
+
from: resolver.resolve("../runtime/utils/parseError")
|
|
29
33
|
}
|
|
30
34
|
]);
|
|
31
35
|
addServerImports([
|
|
32
36
|
{
|
|
33
37
|
name: "useLogger",
|
|
34
|
-
from: resolver.resolve("../runtime/
|
|
38
|
+
from: resolver.resolve("../runtime/server/useLogger")
|
|
35
39
|
},
|
|
36
40
|
{
|
|
37
41
|
name: "log",
|
|
38
|
-
from: resolver.resolve("../runtime/
|
|
42
|
+
from: resolver.resolve("../runtime/client/log")
|
|
39
43
|
},
|
|
40
44
|
{
|
|
41
|
-
name: "
|
|
45
|
+
name: "createEvlogError",
|
|
42
46
|
from: resolver.resolve("../error")
|
|
43
47
|
}
|
|
44
48
|
]);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getConsoleMethod } from '../../utils.mjs';
|
|
2
|
+
|
|
1
3
|
const IS_CLIENT = typeof window !== "undefined";
|
|
2
4
|
let clientPretty = true;
|
|
3
5
|
let clientService = "client";
|
|
@@ -11,9 +13,6 @@ function initLog(options = {}) {
|
|
|
11
13
|
clientPretty = options.pretty ?? true;
|
|
12
14
|
clientService = options.service ?? "client";
|
|
13
15
|
}
|
|
14
|
-
function getConsoleMethod(level) {
|
|
15
|
-
return level === "error" ? "error" : level === "warn" ? "warn" : "log";
|
|
16
|
-
}
|
|
17
16
|
function emitClientWideEvent(level, event) {
|
|
18
17
|
const formatted = {
|
|
19
18
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { initLog } from './
|
|
1
|
+
import { initLog } from './log.mjs';
|
|
2
2
|
import { defineNuxtPlugin, useRuntimeConfig } from '#app';
|
|
3
|
+
import '../../utils.mjs';
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const plugin = defineNuxtPlugin(() => {
|
|
5
6
|
const config = useRuntimeConfig();
|
|
6
7
|
const evlogConfig = config.public?.evlog;
|
|
7
8
|
initLog({
|
|
@@ -10,4 +11,4 @@ const plugin_client = defineNuxtPlugin((_nuxtApp) => {
|
|
|
10
11
|
});
|
|
11
12
|
});
|
|
12
13
|
|
|
13
|
-
export {
|
|
14
|
+
export { plugin as default };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
function parseError(error) {
|
|
2
|
+
if (error && typeof error === "object" && "data" in error) {
|
|
3
|
+
const { data, message: fetchMessage, statusCode: fetchStatusCode } = error;
|
|
4
|
+
const evlogData = data?.data;
|
|
5
|
+
return {
|
|
6
|
+
message: data?.message || fetchMessage || "An error occurred",
|
|
7
|
+
status: data?.statusCode || fetchStatusCode || 500,
|
|
8
|
+
why: evlogData?.why,
|
|
9
|
+
fix: evlogData?.fix,
|
|
10
|
+
link: evlogData?.link,
|
|
11
|
+
raw: error
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
if (error instanceof Error) {
|
|
15
|
+
return {
|
|
16
|
+
message: error.message,
|
|
17
|
+
status: 500,
|
|
18
|
+
raw: error
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
message: String(error),
|
|
23
|
+
status: 500,
|
|
24
|
+
raw: error
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { parseError };
|
package/dist/types.d.mts
CHANGED
|
@@ -116,6 +116,8 @@ interface Log {
|
|
|
116
116
|
interface ErrorOptions {
|
|
117
117
|
/** What actually happened */
|
|
118
118
|
message: string;
|
|
119
|
+
/** HTTP status code (default: 500) */
|
|
120
|
+
status?: number;
|
|
119
121
|
/** Why this error occurred */
|
|
120
122
|
why?: string;
|
|
121
123
|
/** How to fix this issue */
|
|
@@ -125,11 +127,47 @@ interface ErrorOptions {
|
|
|
125
127
|
/** The original error that caused this */
|
|
126
128
|
cause?: Error;
|
|
127
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Options for creating a request logger
|
|
132
|
+
*/
|
|
133
|
+
interface RequestLoggerOptions {
|
|
134
|
+
method?: string;
|
|
135
|
+
path?: string;
|
|
136
|
+
requestId?: string;
|
|
137
|
+
}
|
|
128
138
|
/**
|
|
129
139
|
* H3 event context with evlog logger attached
|
|
130
140
|
*/
|
|
131
|
-
interface
|
|
141
|
+
interface H3EventContext {
|
|
132
142
|
log?: RequestLogger;
|
|
143
|
+
requestId?: string;
|
|
144
|
+
status?: number;
|
|
145
|
+
[key: string]: unknown;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Server event type for Nitro/h3 handlers
|
|
149
|
+
*/
|
|
150
|
+
interface ServerEvent {
|
|
151
|
+
method: string;
|
|
152
|
+
path: string;
|
|
153
|
+
context: H3EventContext;
|
|
154
|
+
node?: {
|
|
155
|
+
res?: {
|
|
156
|
+
statusCode?: number;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
response?: Response;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Parsed evlog error with all fields at the top level
|
|
163
|
+
*/
|
|
164
|
+
interface ParsedError {
|
|
165
|
+
message: string;
|
|
166
|
+
status: number;
|
|
167
|
+
why?: string;
|
|
168
|
+
fix?: string;
|
|
169
|
+
link?: string;
|
|
170
|
+
raw: unknown;
|
|
133
171
|
}
|
|
134
172
|
|
|
135
|
-
export type { BaseWideEvent, EnvironmentContext, ErrorOptions,
|
|
173
|
+
export type { BaseWideEvent, EnvironmentContext, ErrorOptions, H3EventContext, Log, LogLevel, LoggerConfig, ParsedError, RequestLogger, RequestLoggerOptions, ServerEvent, WideEvent };
|
package/dist/types.d.ts
CHANGED
|
@@ -116,6 +116,8 @@ interface Log {
|
|
|
116
116
|
interface ErrorOptions {
|
|
117
117
|
/** What actually happened */
|
|
118
118
|
message: string;
|
|
119
|
+
/** HTTP status code (default: 500) */
|
|
120
|
+
status?: number;
|
|
119
121
|
/** Why this error occurred */
|
|
120
122
|
why?: string;
|
|
121
123
|
/** How to fix this issue */
|
|
@@ -125,11 +127,47 @@ interface ErrorOptions {
|
|
|
125
127
|
/** The original error that caused this */
|
|
126
128
|
cause?: Error;
|
|
127
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Options for creating a request logger
|
|
132
|
+
*/
|
|
133
|
+
interface RequestLoggerOptions {
|
|
134
|
+
method?: string;
|
|
135
|
+
path?: string;
|
|
136
|
+
requestId?: string;
|
|
137
|
+
}
|
|
128
138
|
/**
|
|
129
139
|
* H3 event context with evlog logger attached
|
|
130
140
|
*/
|
|
131
|
-
interface
|
|
141
|
+
interface H3EventContext {
|
|
132
142
|
log?: RequestLogger;
|
|
143
|
+
requestId?: string;
|
|
144
|
+
status?: number;
|
|
145
|
+
[key: string]: unknown;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Server event type for Nitro/h3 handlers
|
|
149
|
+
*/
|
|
150
|
+
interface ServerEvent {
|
|
151
|
+
method: string;
|
|
152
|
+
path: string;
|
|
153
|
+
context: H3EventContext;
|
|
154
|
+
node?: {
|
|
155
|
+
res?: {
|
|
156
|
+
statusCode?: number;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
response?: Response;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Parsed evlog error with all fields at the top level
|
|
163
|
+
*/
|
|
164
|
+
interface ParsedError {
|
|
165
|
+
message: string;
|
|
166
|
+
status: number;
|
|
167
|
+
why?: string;
|
|
168
|
+
fix?: string;
|
|
169
|
+
link?: string;
|
|
170
|
+
raw: unknown;
|
|
133
171
|
}
|
|
134
172
|
|
|
135
|
-
export type { BaseWideEvent, EnvironmentContext, ErrorOptions,
|
|
173
|
+
export type { BaseWideEvent, EnvironmentContext, ErrorOptions, H3EventContext, Log, LogLevel, LoggerConfig, ParsedError, RequestLogger, RequestLoggerOptions, ServerEvent, WideEvent };
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
import { EnvironmentContext } from './types.mjs';
|
|
1
|
+
import { EnvironmentContext, LogLevel } from './types.mjs';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Format duration for display
|
|
5
|
-
* < 1s: shows milliseconds (e.g., "42ms")
|
|
6
|
-
* >= 1s: shows seconds (e.g., "1.5s")
|
|
7
|
-
*/
|
|
8
3
|
declare function formatDuration(ms: number): string;
|
|
9
|
-
/**
|
|
10
|
-
* Check if running on server
|
|
11
|
-
*/
|
|
12
4
|
declare function isServer(): boolean;
|
|
13
|
-
/**
|
|
14
|
-
* Check if running on client
|
|
15
|
-
*/
|
|
16
5
|
declare function isClient(): boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Check if in development mode
|
|
19
|
-
*/
|
|
20
6
|
declare function isDev(): boolean;
|
|
21
|
-
/**
|
|
22
|
-
* Auto-detect environment context from env variables
|
|
23
|
-
*/
|
|
24
7
|
declare function detectEnvironment(): Partial<EnvironmentContext>;
|
|
8
|
+
declare function getConsoleMethod(level: LogLevel): 'log' | 'error' | 'warn';
|
|
25
9
|
declare const colors: {
|
|
26
10
|
readonly reset: "\u001B[0m";
|
|
27
11
|
readonly bold: "\u001B[1m";
|
|
@@ -35,9 +19,6 @@ declare const colors: {
|
|
|
35
19
|
readonly white: "\u001B[37m";
|
|
36
20
|
readonly gray: "\u001B[90m";
|
|
37
21
|
};
|
|
38
|
-
/**
|
|
39
|
-
* Get color for log level
|
|
40
|
-
*/
|
|
41
22
|
declare function getLevelColor(level: string): string;
|
|
42
23
|
|
|
43
|
-
export { colors, detectEnvironment, formatDuration, getLevelColor, isClient, isDev, isServer };
|
|
24
|
+
export { colors, detectEnvironment, formatDuration, getConsoleMethod, getLevelColor, isClient, isDev, isServer };
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
import { EnvironmentContext } from './types.js';
|
|
1
|
+
import { EnvironmentContext, LogLevel } from './types.js';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Format duration for display
|
|
5
|
-
* < 1s: shows milliseconds (e.g., "42ms")
|
|
6
|
-
* >= 1s: shows seconds (e.g., "1.5s")
|
|
7
|
-
*/
|
|
8
3
|
declare function formatDuration(ms: number): string;
|
|
9
|
-
/**
|
|
10
|
-
* Check if running on server
|
|
11
|
-
*/
|
|
12
4
|
declare function isServer(): boolean;
|
|
13
|
-
/**
|
|
14
|
-
* Check if running on client
|
|
15
|
-
*/
|
|
16
5
|
declare function isClient(): boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Check if in development mode
|
|
19
|
-
*/
|
|
20
6
|
declare function isDev(): boolean;
|
|
21
|
-
/**
|
|
22
|
-
* Auto-detect environment context from env variables
|
|
23
|
-
*/
|
|
24
7
|
declare function detectEnvironment(): Partial<EnvironmentContext>;
|
|
8
|
+
declare function getConsoleMethod(level: LogLevel): 'log' | 'error' | 'warn';
|
|
25
9
|
declare const colors: {
|
|
26
10
|
readonly reset: "\u001B[0m";
|
|
27
11
|
readonly bold: "\u001B[1m";
|
|
@@ -35,9 +19,6 @@ declare const colors: {
|
|
|
35
19
|
readonly white: "\u001B[37m";
|
|
36
20
|
readonly gray: "\u001B[90m";
|
|
37
21
|
};
|
|
38
|
-
/**
|
|
39
|
-
* Get color for log level
|
|
40
|
-
*/
|
|
41
22
|
declare function getLevelColor(level: string): string;
|
|
42
23
|
|
|
43
|
-
export { colors, detectEnvironment, formatDuration, getLevelColor, isClient, isDev, isServer };
|
|
24
|
+
export { colors, detectEnvironment, formatDuration, getConsoleMethod, getLevelColor, isClient, isDev, isServer };
|
package/dist/utils.mjs
CHANGED
|
@@ -26,6 +26,9 @@ function detectEnvironment() {
|
|
|
26
26
|
region: env.VERCEL_REGION || env.AWS_REGION || env.FLY_REGION || env.CF_REGION
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
+
function getConsoleMethod(level) {
|
|
30
|
+
return level === "error" ? "error" : level === "warn" ? "warn" : "log";
|
|
31
|
+
}
|
|
29
32
|
const colors = {
|
|
30
33
|
reset: "\x1B[0m",
|
|
31
34
|
bold: "\x1B[1m",
|
|
@@ -54,4 +57,4 @@ function getLevelColor(level) {
|
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
export { colors, detectEnvironment, formatDuration, getLevelColor, isClient, isDev, isServer };
|
|
60
|
+
export { colors, detectEnvironment, formatDuration, getConsoleMethod, getLevelColor, isClient, isDev, isServer };
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evlog",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Wide event logging library with structured error handling. Inspired by LoggingSucks.",
|
|
5
5
|
"author": "HugoRCD <contact@hrcd.fr>",
|
|
6
|
-
"homepage": "https://
|
|
6
|
+
"homepage": "https://evlog.dev",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/HugoRCD/evlog.git"
|
|
@@ -82,7 +82,8 @@
|
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
84
|
"h3": "^1.13.0",
|
|
85
|
-
"nitropack": "^2.
|
|
85
|
+
"nitropack": "^2.13.1",
|
|
86
|
+
"ofetch": "^1.5.1"
|
|
86
87
|
},
|
|
87
88
|
"peerDependenciesMeta": {
|
|
88
89
|
"h3": {
|
|
@@ -90,6 +91,9 @@
|
|
|
90
91
|
},
|
|
91
92
|
"nitropack": {
|
|
92
93
|
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"ofetch": {
|
|
96
|
+
"optional": true
|
|
93
97
|
}
|
|
94
98
|
}
|
|
95
99
|
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Log } from '../../types.mjs';
|
|
2
|
-
|
|
3
|
-
declare function initLog(options?: {
|
|
4
|
-
pretty?: boolean;
|
|
5
|
-
service?: string;
|
|
6
|
-
}): void;
|
|
7
|
-
/**
|
|
8
|
-
* Universal logging API - works on both client and server.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* log.info('auth', 'User logged in')
|
|
13
|
-
* log.info({ action: 'checkout', items: 3 })
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
declare const log: Log;
|
|
17
|
-
|
|
18
|
-
export { initLog, log };
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Log } from '../../types.js';
|
|
2
|
-
|
|
3
|
-
declare function initLog(options?: {
|
|
4
|
-
pretty?: boolean;
|
|
5
|
-
service?: string;
|
|
6
|
-
}): void;
|
|
7
|
-
/**
|
|
8
|
-
* Universal logging API - works on both client and server.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* log.info('auth', 'User logged in')
|
|
13
|
-
* log.info({ action: 'checkout', items: 3 })
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
declare const log: Log;
|
|
17
|
-
|
|
18
|
-
export { initLog, log };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { H3Event } from 'h3';
|
|
2
|
-
import { RequestLogger } from '../../types.mjs';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Get the request-scoped logger from the event context.
|
|
6
|
-
* Must be called within a server handler with an H3 event.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* export default defineEventHandler((event) => {
|
|
11
|
-
* const logger = useLogger(event)
|
|
12
|
-
* logger.set({ userId: '123' })
|
|
13
|
-
* logger.set({ action: 'checkout' })
|
|
14
|
-
* return { ok: true }
|
|
15
|
-
* // emit() is called automatically by the Nitro plugin
|
|
16
|
-
* })
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
declare function useLogger(event: H3Event): RequestLogger;
|
|
20
|
-
|
|
21
|
-
export { useLogger };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { H3Event } from 'h3';
|
|
2
|
-
import { RequestLogger } from '../../types.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Get the request-scoped logger from the event context.
|
|
6
|
-
* Must be called within a server handler with an H3 event.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* export default defineEventHandler((event) => {
|
|
11
|
-
* const logger = useLogger(event)
|
|
12
|
-
* logger.set({ userId: '123' })
|
|
13
|
-
* logger.set({ action: 'checkout' })
|
|
14
|
-
* return { ok: true }
|
|
15
|
-
* // emit() is called automatically by the Nitro plugin
|
|
16
|
-
* })
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
declare function useLogger(event: H3Event): RequestLogger;
|
|
20
|
-
|
|
21
|
-
export { useLogger };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|