logixlysia 4.1.1 → 4.2.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/CHANGELOG.md +34 -0
- package/README.md +1 -31
- package/package.json +14 -28
- package/src/extensions/index.ts +1 -0
- package/src/{plugins/startServer.ts → extensions/start-server.ts} +1 -1
- package/src/{utils/colorMapping.ts → helpers/color-mapping.ts} +1 -1
- package/src/{utils → helpers}/index.ts +1 -1
- package/src/{utils → helpers}/log.ts +2 -2
- package/src/{utils → helpers}/method.ts +1 -1
- package/src/{utils → helpers}/path.ts +1 -1
- package/src/{utils → helpers}/status.ts +18 -6
- package/src/{utils → helpers}/timestamp.ts +1 -1
- package/src/index.ts +10 -8
- package/src/{types → interfaces}/index.ts +9 -11
- package/src/{core/buildLogMessage.ts → logger/build-log-message.ts} +10 -10
- package/src/{core/createLogger.ts → logger/create-logger.ts} +10 -9
- package/src/{core → logger}/filter.ts +5 -3
- package/src/{core/handleHttpError.ts → logger/handle-http-error.ts} +4 -4
- package/src/logger/index.ts +2 -0
- package/src/{transports → output}/console.ts +8 -2
- package/src/{transports → output}/file.ts +11 -6
- package/.gitmodules +0 -3
- package/src/core/index.ts +0 -2
- package/src/plugins/index.ts +0 -1
- package/tests/__mocks__/fs.ts +0 -9
- package/tests/core/buildLogMessage.test.ts +0 -45
- package/tests/core/filter.test.ts +0 -35
- package/tests/helpers.ts +0 -19
- package/tests/logixlysia.test.ts +0 -8
- package/tests/transports/logToTransports.test.ts +0 -29
- package/tests/utils/status.test.ts +0 -46
- package/tests/utils/timestamp.test.ts +0 -35
- /package/src/{utils → helpers}/duration.ts +0 -0
- /package/src/{transports → output}/index.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.2.0](https://github.com/PunGrumpy/logixlysia/compare/v4.1.2...v4.2.0) (2025-04-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **docs:** add screenshot to documentation introduction ([800bb17](https://github.com/PunGrumpy/logixlysia/commit/800bb17dcfda88699cd7a0a2dc2e199e5704ce61))
|
|
9
|
+
* **website:** add new components and integrate react-fast-marquee ([6332f62](https://github.com/PunGrumpy/logixlysia/commit/6332f622c22fccf4cbadfb2a0099b9fac723f61a))
|
|
10
|
+
* **website:** add Open Graph image for enhanced social sharing ([de35d41](https://github.com/PunGrumpy/logixlysia/commit/de35d413bf6a10b06933eb2619d3cb6459618c3e))
|
|
11
|
+
* **website:** add transparent mode to navigation title ([9c01757](https://github.com/PunGrumpy/logixlysia/commit/9c01757f8808b5792b792fc1ed56e5b6e26603d2))
|
|
12
|
+
* **website:** add website documentation ([82e281c](https://github.com/PunGrumpy/logixlysia/commit/82e281cd5c08fa948ecf103eb70f218e61029142))
|
|
13
|
+
* **website:** enhance logging features and update documentation ([fa7ea45](https://github.com/PunGrumpy/logixlysia/commit/fa7ea45ae8c535a22b52e94a46df5931009e013f))
|
|
14
|
+
* **website:** initialize new documentation website with Fumadocs ([c864d9f](https://github.com/PunGrumpy/logixlysia/commit/c864d9f00ea6d0250f2db8b20a994975da18185e))
|
|
15
|
+
* **website:** integrate GitHub info component into layout ([5cd282c](https://github.com/PunGrumpy/logixlysia/commit/5cd282c072e56d90a7554a78dad1f27e8eb13400))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **docs:** correct license information in documentation ([e64f156](https://github.com/PunGrumpy/logixlysia/commit/e64f1565a2100a08ee324ddf68769726dcc6d9ff))
|
|
21
|
+
* **docs:** update file logging examples for clarity and consistency ([1d8653f](https://github.com/PunGrumpy/logixlysia/commit/1d8653f5aa97f8b6d829a10c0a510fc5a5b7dcae))
|
|
22
|
+
* **docs:** update help section for user support ([84e5052](https://github.com/PunGrumpy/logixlysia/commit/84e5052ddf4ef8e636d68be113d866df2d13fd09))
|
|
23
|
+
* **playground:** correct class name syntax for overflow visibility ([25ed919](https://github.com/PunGrumpy/logixlysia/commit/25ed919c1592129d8495afbc2927befb0c431fa0))
|
|
24
|
+
* **website:** adjust z-index for background image and hero component ([af593a7](https://github.com/PunGrumpy/logixlysia/commit/af593a709d625df06f2f0e7ecff55764be46cdd5))
|
|
25
|
+
* **website:** adjust z-index for hero component to improve visibility ([4cc144e](https://github.com/PunGrumpy/logixlysia/commit/4cc144e50c5e0e869e62c3821edd2216acf4cacd))
|
|
26
|
+
* **website:** simplify sidebar configuration in layout component ([dc7e479](https://github.com/PunGrumpy/logixlysia/commit/dc7e47962085c4922dcfaad83e1ce0e38dcfeff0))
|
|
27
|
+
* **website:** update logo assets and adjust class names ([18c8c57](https://github.com/PunGrumpy/logixlysia/commit/18c8c57a2337f3242e77eb0234afee487039f554))
|
|
28
|
+
* **website:** update sidebar configuration to include collapsible property ([2d27ee3](https://github.com/PunGrumpy/logixlysia/commit/2d27ee31b3eeb79505a70dee2fef214a45fb1a9e))
|
|
29
|
+
|
|
30
|
+
## [4.1.2](https://github.com/PunGrumpy/logixlysia/compare/v4.1.1...v4.1.2) (2025-02-24)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Bug Fixes
|
|
34
|
+
|
|
35
|
+
* **logixlysia:** ensure message is a string in response headers ([2f9eeee](https://github.com/PunGrumpy/logixlysia/commit/2f9eeeeb1ec1ab7454e6633c28aa112963f54ed6)), closes [#74](https://github.com/PunGrumpy/logixlysia/issues/74)
|
|
36
|
+
|
|
3
37
|
## [4.1.1](https://github.com/PunGrumpy/logixlysia/compare/v4.1.0...v4.1.1) (2025-01-31)
|
|
4
38
|
|
|
5
39
|
|
package/README.md
CHANGED
|
@@ -42,39 +42,9 @@ const app = new Elysia({
|
|
|
42
42
|
app.listen(3000)
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
> [!NOTE]
|
|
46
|
-
> You can discover more about example in the [example](example) directory.
|
|
47
|
-
|
|
48
|
-
> [!TIP]
|
|
49
|
-
> Also, you can play my example with Swagger UI on `http://localhost:3000/swagger`.
|
|
50
|
-
|
|
51
45
|
## `📚` Documentation
|
|
52
46
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
| Option | Type | Description | Default |
|
|
56
|
-
| ---------------------- | ------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
57
|
-
| `showStartupMessage` | `boolean` | Display the startup message | `true` |
|
|
58
|
-
| `startupMessageFormat` | `"banner"` \| `"simple"` | Choose the startup message format | `"banner"` |
|
|
59
|
-
| `timestamp` | `object` | Display the timestamp in the logs | `{ translateTime: 'yyyy-mm-dd HH:MM:ss' }` |
|
|
60
|
-
| `ip` | `boolean` | Display the incoming IP address based on the `X-Forwarded-For` header | `false` |
|
|
61
|
-
| `customLogMessage` | `string` | Custom log message to display | `🦊 {now} {level} {duration} {method} {pathname} {status} {message} {ip}` |
|
|
62
|
-
| `logFilter` | `object` | Filter the logs based on the level, method, and status | `null` |
|
|
63
|
-
| `logFilePath` | `string` | Path to the log file | `./logs/elysia.log` |
|
|
64
|
-
|
|
65
|
-
### Custom Log Message
|
|
66
|
-
|
|
67
|
-
| Placeholder | Description |
|
|
68
|
-
| ------------ | --------------------------------------------------------------------------- |
|
|
69
|
-
| `{now}` | Current date and time in `YYYY-MM-DD HH:mm:ss` format |
|
|
70
|
-
| `{level}` | Log level (`INFO`, `WARNING`, `ERROR`) |
|
|
71
|
-
| `{duration}` | Request duration in milliseconds |
|
|
72
|
-
| `{method}` | Request method (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`) |
|
|
73
|
-
| `{pathname}` | Request pathname |
|
|
74
|
-
| `{status}` | Response status code |
|
|
75
|
-
| `{message}` | Custom message |
|
|
76
|
-
| `{ip}` | Incoming IP address |
|
|
77
|
-
| `{epoch}` | Current date and time in Unix epoch format (seconds since January 1, 1970 |
|
|
47
|
+
Check out the [website](https://logixlysia.vercel.app) for more detailed documentation and examples.
|
|
78
48
|
|
|
79
49
|
## `📄` License
|
|
80
50
|
|
package/package.json
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "logixlysia",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "🦊 Logixlysia is a logger for Elysia",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.ts",
|
|
7
7
|
"main": "src/index.ts",
|
|
8
8
|
"author": "PunGrumpy",
|
|
9
9
|
"publisher": "PunGrumpy",
|
|
10
|
-
"maintainers": [
|
|
11
|
-
"PunGrumpy"
|
|
12
|
-
],
|
|
10
|
+
"maintainers": ["PunGrumpy"],
|
|
13
11
|
"contributors": [
|
|
14
12
|
{
|
|
15
13
|
"name": "n0ky4",
|
|
@@ -21,23 +19,17 @@
|
|
|
21
19
|
},
|
|
22
20
|
"license": "MIT",
|
|
23
21
|
"scripts": {
|
|
24
|
-
"lint": "
|
|
25
|
-
"
|
|
26
|
-
"test": "bun test --timeout 5000
|
|
22
|
+
"lint": "ultracite lint",
|
|
23
|
+
"format": "ultracite format",
|
|
24
|
+
"test": "bun test --timeout 5000",
|
|
27
25
|
"test:ci": "bun test --timeout 5000 --coverage --coverage-reporter=lcov",
|
|
28
26
|
"publish": "npm publish",
|
|
29
|
-
"dev": "
|
|
27
|
+
"dev": "cd website && bun dev",
|
|
30
28
|
"prepare": "husky",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"trunk:check": "trunk check",
|
|
34
|
-
"trunk:fmt": "trunk fmt"
|
|
29
|
+
"test:coverage": "bun test --timeout 5000 --coverage",
|
|
30
|
+
"clean": "git clean -fdx && rm -rf node_modules && rm -rf logs && cd website && rm -rf node_modules && rm -rf .next && rm -rf .source"
|
|
35
31
|
},
|
|
36
|
-
"os": [
|
|
37
|
-
"darwin",
|
|
38
|
-
"linux",
|
|
39
|
-
"win32"
|
|
40
|
-
],
|
|
32
|
+
"os": ["darwin", "linux", "win32"],
|
|
41
33
|
"badges": [
|
|
42
34
|
{
|
|
43
35
|
"name": "npm",
|
|
@@ -65,7 +57,7 @@
|
|
|
65
57
|
"bugs": {
|
|
66
58
|
"url": "https://github.com/PunGrumpy/logixlysia/issues"
|
|
67
59
|
},
|
|
68
|
-
"homepage": "https://
|
|
60
|
+
"homepage": "https://logixlysia.vercel.app",
|
|
69
61
|
"keywords": [
|
|
70
62
|
"web",
|
|
71
63
|
"logging",
|
|
@@ -80,19 +72,13 @@
|
|
|
80
72
|
"elysia": "^1.1.23"
|
|
81
73
|
},
|
|
82
74
|
"devDependencies": {
|
|
83
|
-
"@
|
|
75
|
+
"@biomejs/biome": "^1.9.4",
|
|
84
76
|
"@elysiajs/eden": "^1.1.3",
|
|
85
|
-
"@
|
|
86
|
-
"@trunkio/launcher": "^1.3.2",
|
|
87
|
-
"@typescript-eslint/eslint-plugin": "^8.11.0",
|
|
88
|
-
"@typescript-eslint/parser": "^8.11.0",
|
|
77
|
+
"@elysiajs/swagger": "^1.2.0",
|
|
89
78
|
"bun-types": "^1.1.33",
|
|
90
|
-
"
|
|
91
|
-
"globals": "^15.11.0",
|
|
79
|
+
"globals": "^16.0.0",
|
|
92
80
|
"husky": "^9.1.6",
|
|
93
|
-
"
|
|
94
|
-
"prettier": "^3.3.3",
|
|
95
|
-
"typescript-eslint": "^8.11.0"
|
|
81
|
+
"ultracite": "^4.2.1"
|
|
96
82
|
},
|
|
97
83
|
"peerDependencies": {
|
|
98
84
|
"typescript": "^5.2.2"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as startServer } from './start-server'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { HttpMethodColorMap, LogLevelColorMap } from './
|
|
1
|
+
export { HttpMethodColorMap, LogLevelColorMap } from './color-mapping'
|
|
2
2
|
export { default as durationString } from './duration'
|
|
3
3
|
export { default as logString } from './log'
|
|
4
4
|
export { default as methodString } from './method'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { LogLevel } from '../
|
|
2
|
-
import { LogLevelColorMap } from './
|
|
1
|
+
import type { LogLevel } from '../interfaces'
|
|
2
|
+
import { LogLevelColorMap } from './color-mapping'
|
|
3
3
|
|
|
4
4
|
export default function logString(level: LogLevel, useColors: boolean): string {
|
|
5
5
|
const levelStr = level.toUpperCase()
|
|
@@ -2,7 +2,9 @@ import chalk from 'chalk'
|
|
|
2
2
|
import { StatusMap } from 'elysia'
|
|
3
3
|
|
|
4
4
|
export function getStatusCode(status: string | number): number {
|
|
5
|
-
if (typeof status === 'number')
|
|
5
|
+
if (typeof status === 'number') {
|
|
6
|
+
return status
|
|
7
|
+
}
|
|
6
8
|
return (StatusMap as Record<string, number>)[status] || 500
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -11,11 +13,21 @@ export default function statusString(
|
|
|
11
13
|
useColors: boolean
|
|
12
14
|
): string {
|
|
13
15
|
const statusStr = status.toString()
|
|
14
|
-
if (!useColors)
|
|
16
|
+
if (!useColors) {
|
|
17
|
+
return statusStr
|
|
18
|
+
}
|
|
15
19
|
|
|
16
|
-
if (status >= 500)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (status >=
|
|
20
|
+
if (status >= 500) {
|
|
21
|
+
return chalk.red(statusStr)
|
|
22
|
+
}
|
|
23
|
+
if (status >= 400) {
|
|
24
|
+
return chalk.yellow(statusStr)
|
|
25
|
+
}
|
|
26
|
+
if (status >= 300) {
|
|
27
|
+
return chalk.cyan(statusStr)
|
|
28
|
+
}
|
|
29
|
+
if (status >= 200) {
|
|
30
|
+
return chalk.green(statusStr)
|
|
31
|
+
}
|
|
20
32
|
return chalk.white(statusStr)
|
|
21
33
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Elysia } from 'elysia'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { HttpError, Options, Server } from './
|
|
6
|
-
import {
|
|
3
|
+
import { startServer } from './extensions'
|
|
4
|
+
import { getStatusCode } from './helpers/status'
|
|
5
|
+
import type { HttpError, Options, Server } from './interfaces'
|
|
6
|
+
import { createLogger } from './logger'
|
|
7
7
|
|
|
8
8
|
export default function logixlysia(options?: Options): Elysia {
|
|
9
9
|
const log = createLogger(options)
|
|
@@ -13,7 +13,9 @@ export default function logixlysia(options?: Options): Elysia {
|
|
|
13
13
|
})
|
|
14
14
|
.onStart(ctx => {
|
|
15
15
|
const showStartupMessage = options?.config?.showStartupMessage ?? true
|
|
16
|
-
if (showStartupMessage)
|
|
16
|
+
if (showStartupMessage) {
|
|
17
|
+
startServer(ctx.server as Server, options)
|
|
18
|
+
}
|
|
17
19
|
})
|
|
18
20
|
.onRequest(ctx => {
|
|
19
21
|
ctx.store = { beforeTime: process.hrtime.bigint() }
|
|
@@ -25,7 +27,7 @@ export default function logixlysia(options?: Options): Elysia {
|
|
|
25
27
|
request,
|
|
26
28
|
{
|
|
27
29
|
status,
|
|
28
|
-
message: set.headers?.['x-message'] || ''
|
|
30
|
+
message: String(set.headers?.['x-message'] || '')
|
|
29
31
|
},
|
|
30
32
|
store as { beforeTime: bigint }
|
|
31
33
|
)
|
|
@@ -40,5 +42,5 @@ export default function logixlysia(options?: Options): Elysia {
|
|
|
40
42
|
})
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
export { createLogger, handleHttpError } from './
|
|
44
|
-
export { logToTransports } from './
|
|
45
|
+
export { createLogger, handleHttpError } from './logger'
|
|
46
|
+
export { logToTransports } from './output'
|
|
@@ -61,17 +61,15 @@ export class HttpError extends Error {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
): Promise<void> | void
|
|
74
|
-
}
|
|
64
|
+
export type TransportFunction = (
|
|
65
|
+
level: LogLevel,
|
|
66
|
+
message: string,
|
|
67
|
+
meta: {
|
|
68
|
+
request: RequestInfo
|
|
69
|
+
data: LogData
|
|
70
|
+
store: StoreData
|
|
71
|
+
}
|
|
72
|
+
) => Promise<void> | void
|
|
75
73
|
|
|
76
74
|
export interface Transport {
|
|
77
75
|
log: TransportFunction
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
LogComponents,
|
|
5
|
-
LogData,
|
|
6
|
-
LogLevel,
|
|
7
|
-
Options,
|
|
8
|
-
RequestInfo,
|
|
9
|
-
StoreData
|
|
10
|
-
} from '../types'
|
|
11
3
|
import {
|
|
12
4
|
durationString,
|
|
13
5
|
formatTimestamp,
|
|
@@ -15,7 +7,15 @@ import {
|
|
|
15
7
|
methodString,
|
|
16
8
|
pathString,
|
|
17
9
|
statusString
|
|
18
|
-
} from '../
|
|
10
|
+
} from '../helpers'
|
|
11
|
+
import type {
|
|
12
|
+
LogComponents,
|
|
13
|
+
LogData,
|
|
14
|
+
LogLevel,
|
|
15
|
+
Options,
|
|
16
|
+
RequestInfo,
|
|
17
|
+
StoreData
|
|
18
|
+
} from '../interfaces'
|
|
19
19
|
|
|
20
20
|
const defaultLogFormat =
|
|
21
21
|
'🦊 {now} {level} {duration} {method} {pathname} {status} {message} {ip}'
|
|
@@ -33,7 +33,7 @@ export function buildLogMessage(
|
|
|
33
33
|
data: LogData,
|
|
34
34
|
store: StoreData,
|
|
35
35
|
options?: Options,
|
|
36
|
-
useColors
|
|
36
|
+
useColors = true
|
|
37
37
|
): string {
|
|
38
38
|
const actuallyUseColors = shouldUseColors(useColors, options)
|
|
39
39
|
const now = new Date()
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { logToFile } from '../transports'
|
|
3
|
-
import {
|
|
1
|
+
import type {
|
|
4
2
|
LogData,
|
|
5
|
-
Logger,
|
|
6
3
|
LogLevel,
|
|
4
|
+
Logger,
|
|
7
5
|
Options,
|
|
8
6
|
RequestInfo,
|
|
9
7
|
StoreData
|
|
10
|
-
} from '../
|
|
11
|
-
import {
|
|
8
|
+
} from '../interfaces'
|
|
9
|
+
import { logToFile, logToTransports } from '../output'
|
|
10
|
+
import { buildLogMessage } from './build-log-message'
|
|
12
11
|
import { filterLog } from './filter'
|
|
13
|
-
import { handleHttpError } from './
|
|
12
|
+
import { handleHttpError } from './handle-http-error'
|
|
14
13
|
|
|
15
14
|
async function log(
|
|
16
15
|
level: LogLevel,
|
|
@@ -19,12 +18,14 @@ async function log(
|
|
|
19
18
|
store: StoreData,
|
|
20
19
|
options?: Options
|
|
21
20
|
): Promise<void> {
|
|
22
|
-
if (!filterLog(level, data.status || 200, request.method, options))
|
|
21
|
+
if (!filterLog(level, data.status || 200, request.method, options)) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
23
24
|
|
|
24
25
|
const logMessage = buildLogMessage(level, request, data, store, options, true)
|
|
25
26
|
console.log(logMessage)
|
|
26
27
|
|
|
27
|
-
const promises = []
|
|
28
|
+
const promises: Promise<void>[] = []
|
|
28
29
|
|
|
29
30
|
if (options?.config?.logFilePath) {
|
|
30
31
|
promises.push(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LogLevel, Options } from '../
|
|
1
|
+
import type { LogLevel, Options } from '../interfaces'
|
|
2
2
|
|
|
3
|
-
const checkFilter = (filterValue:
|
|
3
|
+
const checkFilter = (filterValue: unknown, value: unknown) =>
|
|
4
4
|
Array.isArray(filterValue)
|
|
5
5
|
? filterValue.includes(value)
|
|
6
6
|
: filterValue === value
|
|
@@ -12,7 +12,9 @@ export function filterLog(
|
|
|
12
12
|
options?: Options
|
|
13
13
|
): boolean {
|
|
14
14
|
const filter = options?.config?.logFilter
|
|
15
|
-
if (!filter)
|
|
15
|
+
if (!filter) {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
16
18
|
|
|
17
19
|
return (
|
|
18
20
|
(!filter.level || checkFilter(filter.level, logLevel)) &&
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { buildLogMessage } from './
|
|
1
|
+
import type { HttpError, Options, RequestInfo, StoreData } from '../interfaces'
|
|
2
|
+
import { logToFile } from '../output'
|
|
3
|
+
import { buildLogMessage } from './build-log-message'
|
|
4
4
|
|
|
5
5
|
export function handleHttpError(
|
|
6
6
|
request: RequestInfo,
|
|
@@ -13,7 +13,7 @@ export function handleHttpError(
|
|
|
13
13
|
buildLogMessage('ERROR', request, { status: statusCode }, store, options)
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
-
const promises = []
|
|
16
|
+
const promises: Promise<void>[] = []
|
|
17
17
|
|
|
18
18
|
if (options?.config?.logFilePath) {
|
|
19
19
|
promises.push(
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
LogData,
|
|
3
|
+
LogLevel,
|
|
4
|
+
Options,
|
|
5
|
+
RequestInfo,
|
|
6
|
+
StoreData
|
|
7
|
+
} from '../interfaces'
|
|
8
|
+
import { buildLogMessage } from '../logger/build-log-message'
|
|
3
9
|
|
|
4
10
|
export async function logToTransports(
|
|
5
11
|
level: LogLevel,
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import { dirname } from 'path'
|
|
1
|
+
import { promises as fs } from 'node:fs'
|
|
2
|
+
import { dirname } from 'node:path'
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import type {
|
|
5
|
+
LogData,
|
|
6
|
+
LogLevel,
|
|
7
|
+
Options,
|
|
8
|
+
RequestInfo,
|
|
9
|
+
StoreData
|
|
10
|
+
} from '../interfaces'
|
|
11
|
+
import { buildLogMessage } from '../logger/build-log-message'
|
|
6
12
|
|
|
7
13
|
const dirCache = new Set<string>()
|
|
8
14
|
|
|
@@ -23,7 +29,6 @@ export async function logToFile(
|
|
|
23
29
|
options?: Options
|
|
24
30
|
): Promise<void> {
|
|
25
31
|
await ensureDirectoryExists(filePath)
|
|
26
|
-
const logMessage =
|
|
27
|
-
buildLogMessage(level, request, data, store, options, false) + '\n'
|
|
32
|
+
const logMessage = `${buildLogMessage(level, request, data, store, options, false)}\n`
|
|
28
33
|
await fs.appendFile(filePath, logMessage, { flag: 'a' })
|
|
29
34
|
}
|
package/.gitmodules
DELETED
package/src/core/index.ts
DELETED
package/src/plugins/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as startServer } from './startServer'
|
package/tests/__mocks__/fs.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { buildLogMessage } from '../../src/core/buildLogMessage'
|
|
4
|
-
import { LogData, LogLevel, Options, StoreData } from '../../src/types'
|
|
5
|
-
import { createMockRequest } from '../helpers'
|
|
6
|
-
|
|
7
|
-
test('buildLogMessage', () => {
|
|
8
|
-
const level: LogLevel = 'INFO'
|
|
9
|
-
const request = createMockRequest()
|
|
10
|
-
const data: LogData = { status: 200, message: 'Test message' }
|
|
11
|
-
const store: StoreData = { beforeTime: BigInt(0) }
|
|
12
|
-
const options: Options = {
|
|
13
|
-
config: {
|
|
14
|
-
ip: true,
|
|
15
|
-
customLogFormat: '{level} {message} {ip}'
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const message = buildLogMessage(level, request, data, store, options, false)
|
|
20
|
-
expect(message).toContain('INFO')
|
|
21
|
-
expect(message).toContain('Test message')
|
|
22
|
-
expect(message).toContain('127.0.0.1')
|
|
23
|
-
|
|
24
|
-
const colorMessage = buildLogMessage(
|
|
25
|
-
level,
|
|
26
|
-
request,
|
|
27
|
-
data,
|
|
28
|
-
store,
|
|
29
|
-
options,
|
|
30
|
-
true
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
expect(colorMessage).toContain('INFO')
|
|
34
|
-
expect(colorMessage).toContain('Test message')
|
|
35
|
-
expect(colorMessage).toContain('127.0.0.1')
|
|
36
|
-
|
|
37
|
-
const hasAnsiCodes = /\\x1B\[[0-9;]*m/.test(colorMessage)
|
|
38
|
-
if (hasAnsiCodes) {
|
|
39
|
-
expect(colorMessage).not.toBe(message)
|
|
40
|
-
} else {
|
|
41
|
-
console.warn(
|
|
42
|
-
'No ANSI color codes detected. Colors might be disabled in this environment.'
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { filterLog } from '../../src/core/filter'
|
|
4
|
-
import { Options } from '../../src/types'
|
|
5
|
-
|
|
6
|
-
test('filterLog', () => {
|
|
7
|
-
const options: Options = {
|
|
8
|
-
config: {
|
|
9
|
-
logFilter: {
|
|
10
|
-
level: 'ERROR',
|
|
11
|
-
method: 'POST',
|
|
12
|
-
status: 500
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
expect(filterLog('ERROR', 500, 'POST', options)).toBe(true)
|
|
18
|
-
expect(filterLog('INFO', 200, 'GET', options)).toBe(false)
|
|
19
|
-
expect(filterLog('WARNING', 400, 'PUT', options)).toBe(false)
|
|
20
|
-
|
|
21
|
-
// Test with array filters
|
|
22
|
-
const arrayOptions: Options = {
|
|
23
|
-
config: {
|
|
24
|
-
logFilter: {
|
|
25
|
-
level: ['ERROR', 'WARNING'],
|
|
26
|
-
method: ['POST', 'PUT'],
|
|
27
|
-
status: [500, 400]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
expect(filterLog('ERROR', 500, 'POST', arrayOptions)).toBe(true)
|
|
33
|
-
expect(filterLog('WARNING', 400, 'PUT', arrayOptions)).toBe(true)
|
|
34
|
-
expect(filterLog('INFO', 200, 'GET', arrayOptions)).toBe(false)
|
|
35
|
-
})
|
package/tests/helpers.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { mock } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { RequestInfo } from '../src/types'
|
|
4
|
-
|
|
5
|
-
export function createMockRequest(
|
|
6
|
-
method: string = 'GET',
|
|
7
|
-
url: string = 'http://localhost:3000/'
|
|
8
|
-
): RequestInfo {
|
|
9
|
-
return {
|
|
10
|
-
headers: {
|
|
11
|
-
get: (key: string) => (key === 'x-forwarded-for' ? '127.0.0.1' : null)
|
|
12
|
-
},
|
|
13
|
-
method,
|
|
14
|
-
url
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const mockConsoleLog = mock(() => {})
|
|
19
|
-
export const mockConsoleError = mock(() => {})
|
package/tests/logixlysia.test.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { expect, mock, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { logToTransports } from '../../src/transports'
|
|
4
|
-
import { LogData, LogLevel, Options, StoreData } from '../../src/types'
|
|
5
|
-
import { createMockRequest } from '../helpers'
|
|
6
|
-
|
|
7
|
-
test('logToTransports', async () => {
|
|
8
|
-
const level: LogLevel = 'INFO'
|
|
9
|
-
const request = createMockRequest()
|
|
10
|
-
const data: LogData = { status: 200, message: 'Test message' }
|
|
11
|
-
const store: StoreData = { beforeTime: BigInt(0) }
|
|
12
|
-
|
|
13
|
-
const mockTransport = {
|
|
14
|
-
log: mock(() => Promise.resolve())
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const options: Options = {
|
|
18
|
-
config: {
|
|
19
|
-
transports: [mockTransport]
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
await logToTransports(level, request, data, store, options)
|
|
24
|
-
expect(mockTransport.log).toHaveBeenCalled()
|
|
25
|
-
|
|
26
|
-
// Test with no transports
|
|
27
|
-
await logToTransports(level, request, data, store, {})
|
|
28
|
-
expect(mockTransport.log).toHaveBeenCalledTimes(1) // Should not be called again
|
|
29
|
-
})
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
import { Elysia } from 'elysia'
|
|
3
|
-
|
|
4
|
-
import logixlysia from '../../src/index'
|
|
5
|
-
|
|
6
|
-
test('handles numeric status codes', async () => {
|
|
7
|
-
const app = new Elysia().use(logixlysia()).get('/rate-limited', ({ set }) => {
|
|
8
|
-
set.status = 429
|
|
9
|
-
return 'Rate Limited'
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
const res = await app.handle(new Request('http://localhost/rate-limited'))
|
|
13
|
-
expect(res.status).toBe(429)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
test('handles string status codes', async () => {
|
|
17
|
-
const app = new Elysia().use(logixlysia()).get('/not-found', ({ set }) => {
|
|
18
|
-
set.status = 'Not Found'
|
|
19
|
-
return 'Resource not found'
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
const res = await app.handle(new Request('http://localhost/not-found'))
|
|
23
|
-
expect(res.status).toBe(404)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
test('handles custom error status', async () => {
|
|
27
|
-
const app = new Elysia().use(logixlysia()).get('/error', ({ set }) => {
|
|
28
|
-
set.status = 418
|
|
29
|
-
const error = new Error('Custom error')
|
|
30
|
-
throw error
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
const res = await app.handle(new Request('http://localhost/error'))
|
|
34
|
-
expect(res.status).toBe(418)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
test('handles custom error status with message', async () => {
|
|
38
|
-
const app = new Elysia().use(logixlysia()).get('/error', ({ set }) => {
|
|
39
|
-
set.status = "I'm a teapot"
|
|
40
|
-
const error = new Error('Custom error')
|
|
41
|
-
throw error
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
const res = await app.handle(new Request('http://localhost/error'))
|
|
45
|
-
expect(res.status).toBe(418)
|
|
46
|
-
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { formatTimestamp } from '../../src/utils/timestamp'
|
|
4
|
-
|
|
5
|
-
test('formatTimestamp with different configurations', () => {
|
|
6
|
-
const testDate = new Date('2024-01-15T14:30:45.123Z')
|
|
7
|
-
|
|
8
|
-
// Test default format
|
|
9
|
-
expect(formatTimestamp(testDate)).toBe(testDate.toISOString())
|
|
10
|
-
|
|
11
|
-
// Test system time format
|
|
12
|
-
expect(formatTimestamp(testDate, { translateTime: true })).toMatch(
|
|
13
|
-
/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}$/
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
// Test custom format
|
|
17
|
-
expect(
|
|
18
|
-
formatTimestamp(testDate, {
|
|
19
|
-
translateTime: 'yyyy-mm-dd HH:MM:ss.SSS'
|
|
20
|
-
})
|
|
21
|
-
).toMatch(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}$/)
|
|
22
|
-
|
|
23
|
-
// Test different custom formats
|
|
24
|
-
expect(
|
|
25
|
-
formatTimestamp(testDate, {
|
|
26
|
-
translateTime: 'HH:MM:ss'
|
|
27
|
-
})
|
|
28
|
-
).toMatch(/^\d{2}:\d{2}:\d{2}$/)
|
|
29
|
-
|
|
30
|
-
expect(
|
|
31
|
-
formatTimestamp(testDate, {
|
|
32
|
-
translateTime: 'yyyy/mm/dd'
|
|
33
|
-
})
|
|
34
|
-
).toMatch(/^\d{4}\/\d{2}\/\d{2}$/)
|
|
35
|
-
})
|
|
File without changes
|
|
File without changes
|