logixlysia 2.3.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +11 -4
- package/package.json +1 -1
- package/src/index.ts +7 -2
- package/src/logger.ts +55 -13
- package/src/types.ts +2 -0
- package/test/logixlysia.test.ts +18 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.0.1](https://github.com/PunGrumpy/logixlysia/compare/v3.0.0...v3.0.1) (2024-04-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **logger:** use correct status code in error log message ([a3ec49c](https://github.com/PunGrumpy/logixlysia/commit/a3ec49cd3fc1dc7f01a29b21e4de9cf543329c43)), closes [#33](https://github.com/PunGrumpy/logixlysia/issues/33)
|
|
9
|
+
|
|
10
|
+
## [3.0.0](https://github.com/PunGrumpy/logixlysia/compare/v2.3.1...v3.0.0) (2024-04-08)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### ⚠ BREAKING CHANGES
|
|
14
|
+
|
|
15
|
+
* Added support for custom log format in the logger
|
|
16
|
+
* Enhanced flexibility for define thier preferred log message structure
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **options:** add support for custom log format ([acc9380](https://github.com/PunGrumpy/logixlysia/commit/acc9380ea25691e7d7fec175094cb6a9878b6c69))
|
|
21
|
+
|
|
3
22
|
## [2.3.1](https://github.com/PunGrumpy/logixlysia/compare/v2.3.0...v2.3.1) (2024-04-07)
|
|
4
23
|
|
|
5
24
|
|
package/README.md
CHANGED
|
@@ -18,7 +18,13 @@ import { logger } from 'logixlysia'
|
|
|
18
18
|
|
|
19
19
|
const app = new Elysia({
|
|
20
20
|
name: 'Logixlysia Example'
|
|
21
|
-
}).use(
|
|
21
|
+
}).use(
|
|
22
|
+
logger({
|
|
23
|
+
ip: false,
|
|
24
|
+
customLogMessage:
|
|
25
|
+
'🦊 {now} {level} {duration} {method} {pathname} {status} {message} {ip}'
|
|
26
|
+
})
|
|
27
|
+
)
|
|
22
28
|
|
|
23
29
|
app.listen(3000)
|
|
24
30
|
```
|
|
@@ -27,9 +33,10 @@ app.listen(3000)
|
|
|
27
33
|
|
|
28
34
|
### Options
|
|
29
35
|
|
|
30
|
-
| Option
|
|
31
|
-
|
|
|
32
|
-
| `ip`
|
|
36
|
+
| Option | Type | Description | Default |
|
|
37
|
+
| ------------------ | --------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
38
|
+
| `ip` | `boolean` | Display the incoming IP address based on the `X-Forwarded-For` header | `false` |
|
|
39
|
+
| `customLogMessage` | `string` | Custom log message to display | `🦊 {now} {level} {duration} {method} {pathname} {status} {message} {ip}` |
|
|
33
40
|
|
|
34
41
|
## `📄` License
|
|
35
42
|
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import Elysia from 'elysia'
|
|
|
2
2
|
import { createLogger, handleHttpError } from './logger'
|
|
3
3
|
import startString from './utils/start'
|
|
4
4
|
import { Server } from 'bun'
|
|
5
|
-
import { Options } from './types'
|
|
5
|
+
import { HttpError, Options } from './types'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Creates a logger.
|
|
@@ -35,7 +35,12 @@ export const logger = (options?: Options): Elysia => {
|
|
|
35
35
|
log.log('INFO', request, { status: 200 }, store as { beforeTime: bigint })
|
|
36
36
|
})
|
|
37
37
|
.onError({ as: 'global' }, ({ request, error, store }) => {
|
|
38
|
-
handleHttpError(
|
|
38
|
+
handleHttpError(
|
|
39
|
+
request,
|
|
40
|
+
error as HttpError,
|
|
41
|
+
store as { beforeTime: bigint },
|
|
42
|
+
options
|
|
43
|
+
)
|
|
39
44
|
})
|
|
40
45
|
|
|
41
46
|
return elysia
|
package/src/logger.ts
CHANGED
|
@@ -7,17 +7,36 @@ import statusString from './utils/status'
|
|
|
7
7
|
import { HttpError, RequestInfo } from './types'
|
|
8
8
|
import { LogLevel, LogData, Logger, StoreData, Options } from './types'
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Logs a message.
|
|
12
|
+
*
|
|
13
|
+
* @param {LogLevel} level The log level.
|
|
14
|
+
* @param {RequestInfo} request The request.
|
|
15
|
+
* @param {LogData} data The log data.
|
|
16
|
+
* @param {StoreData} store The store data.
|
|
17
|
+
* @param {Options} options The options.
|
|
18
|
+
*/
|
|
19
|
+
function log(
|
|
11
20
|
level: LogLevel,
|
|
12
21
|
request: RequestInfo,
|
|
13
22
|
data: LogData,
|
|
14
23
|
store: StoreData,
|
|
15
24
|
options?: Options
|
|
16
|
-
):
|
|
25
|
+
): void {
|
|
17
26
|
const logMessage = buildLogMessage(level, request, data, store, options)
|
|
18
27
|
console.log(logMessage)
|
|
19
28
|
}
|
|
20
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Builds a log message.
|
|
32
|
+
*
|
|
33
|
+
* @param {LogLevel} level The log level.
|
|
34
|
+
* @param {RequestInfo} request The request.
|
|
35
|
+
* @param {LogData} data The log data.
|
|
36
|
+
* @param {StoreData} store The store data.
|
|
37
|
+
* @param {Options} options The options.
|
|
38
|
+
* @returns {string} The log message.
|
|
39
|
+
*/
|
|
21
40
|
function buildLogMessage(
|
|
22
41
|
level: LogLevel,
|
|
23
42
|
request: RequestInfo,
|
|
@@ -32,31 +51,54 @@ function buildLogMessage(
|
|
|
32
51
|
const pathnameStr = pathString(request)
|
|
33
52
|
const statusStr = statusString(data.status || 200)
|
|
34
53
|
const messageStr = data.message || ''
|
|
54
|
+
const ipStr =
|
|
55
|
+
options?.ip && request.headers.get('x-forwarded-for')
|
|
56
|
+
? `IP: ${request.headers.get('x-forwarded-for')}`
|
|
57
|
+
: ''
|
|
35
58
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
59
|
+
const logFormat =
|
|
60
|
+
options?.customLogFormat ||
|
|
61
|
+
'🦊 {now} {level} {duration} {method} {pathname} {status} {message} {ip}'
|
|
62
|
+
const logMessage = logFormat
|
|
63
|
+
.replace('{now}', nowStr)
|
|
64
|
+
.replace('{level}', levelStr)
|
|
65
|
+
.replace('{duration}', durationStr)
|
|
66
|
+
.replace('{method}', methodStr)
|
|
67
|
+
.replace('{pathname}', pathnameStr || '')
|
|
68
|
+
.replace('{status}', statusStr)
|
|
69
|
+
.replace('{message}', messageStr)
|
|
70
|
+
.replace('{ip}', ipStr || '')
|
|
44
71
|
|
|
45
72
|
return logMessage
|
|
46
73
|
}
|
|
47
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Creates a logger.
|
|
77
|
+
*
|
|
78
|
+
* @param {Options} options The options.
|
|
79
|
+
* @returns {Logger} The logger.
|
|
80
|
+
*/
|
|
48
81
|
export const createLogger = (options?: Options): Logger => ({
|
|
49
82
|
log: (level, request, data, store) =>
|
|
50
|
-
log(level, request, data, store, options)
|
|
83
|
+
log(level, request, data, store, options),
|
|
84
|
+
customLogFormat: options?.customLogFormat
|
|
51
85
|
})
|
|
52
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Handles an HTTP error.
|
|
89
|
+
*
|
|
90
|
+
* @param {RequestInfo} request The request.
|
|
91
|
+
* @param {HttpError} error The HTTP error.
|
|
92
|
+
* @param {StoreData} store The store data.
|
|
93
|
+
* @param {Options} options The options.
|
|
94
|
+
*/
|
|
53
95
|
export const handleHttpError = (
|
|
54
96
|
request: RequestInfo,
|
|
55
|
-
error:
|
|
97
|
+
error: HttpError,
|
|
56
98
|
store: StoreData,
|
|
57
99
|
options?: Options
|
|
58
100
|
): void => {
|
|
59
|
-
const statusCode = error
|
|
101
|
+
const statusCode = error.status || 500
|
|
60
102
|
const logMessage = buildLogMessage(
|
|
61
103
|
'ERROR',
|
|
62
104
|
request,
|
package/src/types.ts
CHANGED
|
@@ -28,6 +28,7 @@ interface Logger {
|
|
|
28
28
|
data: LogData,
|
|
29
29
|
store: StoreData
|
|
30
30
|
): void
|
|
31
|
+
customLogFormat?: string
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
interface StoreData {
|
|
@@ -45,6 +46,7 @@ class HttpError extends Error {
|
|
|
45
46
|
|
|
46
47
|
interface Options {
|
|
47
48
|
ip?: boolean
|
|
49
|
+
customLogFormat?: string
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
export {
|
package/test/logixlysia.test.ts
CHANGED
|
@@ -10,7 +10,13 @@ describe('Logixlysia with IP logging enabled', () => {
|
|
|
10
10
|
|
|
11
11
|
beforeAll(() => {
|
|
12
12
|
server = new Elysia()
|
|
13
|
-
.use(
|
|
13
|
+
.use(
|
|
14
|
+
logger({
|
|
15
|
+
ip: true,
|
|
16
|
+
customLogFormat:
|
|
17
|
+
'🦊 {now} {duration} {level} {method} {pathname} {status} {message} {ip}'
|
|
18
|
+
})
|
|
19
|
+
)
|
|
14
20
|
.get('/', ctx => {
|
|
15
21
|
const ipAddress = ctx.request.headers.get('x-forwarded-for') || 'null'
|
|
16
22
|
return '🦊 Logixlysia Getting'
|
|
@@ -35,7 +41,9 @@ describe('Logixlysia with IP logging enabled', () => {
|
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
logs.forEach(log => {
|
|
38
|
-
expect(log).toMatch(
|
|
44
|
+
expect(log).toMatch(
|
|
45
|
+
/^🦊 .+ INFO .+ .+ GET \/ .+ IP: \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
|
|
46
|
+
)
|
|
39
47
|
})
|
|
40
48
|
})
|
|
41
49
|
|
|
@@ -47,7 +55,7 @@ describe('Logixlysia with IP logging enabled', () => {
|
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
logs.forEach(log => {
|
|
50
|
-
expect(log).
|
|
58
|
+
expect(log).toMatch(/^🦊 .+ INFO .+ .+ GET \/ .+ IP: null$/)
|
|
51
59
|
})
|
|
52
60
|
})
|
|
53
61
|
})
|
|
@@ -59,7 +67,13 @@ describe('Logixlysia with IP logging disabled', () => {
|
|
|
59
67
|
|
|
60
68
|
beforeAll(() => {
|
|
61
69
|
server = new Elysia()
|
|
62
|
-
.use(
|
|
70
|
+
.use(
|
|
71
|
+
logger({
|
|
72
|
+
ip: false,
|
|
73
|
+
customLogFormat:
|
|
74
|
+
'🦊 {now} {duration} {level} {method} {pathname} {status} {message} {ip}'
|
|
75
|
+
})
|
|
76
|
+
)
|
|
63
77
|
.get('/', () => '🦊 Logixlysia Getting')
|
|
64
78
|
.post('logixlysia', () => '🦊 Logixlysia Posting')
|
|
65
79
|
.listen(3000)
|