logixlysia 3.1.0 → 3.3.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/.prettierrc +9 -0
- package/CHANGELOG.md +14 -0
- package/README.md +12 -5
- package/eslint.config.js +25 -0
- package/lint-staged.config.cjs +6 -25
- package/package.json +15 -12
- package/src/index.ts +7 -5
- package/src/logger/filter.ts +49 -0
- package/src/logger/handle.ts +30 -0
- package/src/{logger.ts → logger/index.ts} +18 -86
- package/src/types.ts +7 -7
- package/src/utils/colorMapping.ts +8 -7
- package/src/utils/log.ts +8 -12
- package/src/utils/start.ts +2 -2
- package/src/utils/status.ts +13 -14
- package/test/logger/filter.test.ts +62 -0
- package/test/logixlysia.test.ts +13 -19
- package/test/types/ColorMap.test.ts +1 -0
- package/test/types/HttpError.test.ts +1 -0
- package/test/types/Logger.test.ts +2 -1
- package/test/types/RequestInfo.test.ts +1 -0
- package/test/types/Server.test.ts +1 -0
- package/test/types/StoreData.test.ts +1 -0
- package/test/utils/duration.test.ts +1 -0
- package/test/utils/log.test.ts +1 -0
- package/test/utils/method.test.ts +2 -1
- package/test/utils/path.test.ts +1 -0
- package/test/utils/start.test.ts +5 -4
- package/test/utils/status.test.ts +7 -6
- package/eslint.config.cjs +0 -25
- package/prettier.config.cjs +0 -11
package/.prettierrc
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.3.0](https://github.com/PunGrumpy/logixlysia/compare/v3.2.0...v3.3.0) (2024-05-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **color:** new color for methods (matching Postman color) ([0528886](https://github.com/PunGrumpy/logixlysia/commit/0528886ef9fdaa466e4b78b46fb09d31731b0520))
|
|
9
|
+
|
|
10
|
+
## [3.2.0](https://github.com/PunGrumpy/logixlysia/compare/v3.1.0...v3.2.0) (2024-05-07)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* update logger function name for clarity ([9badffc](https://github.com/PunGrumpy/logixlysia/commit/9badffc286fc13feda9eeffd28881990ae437c9f))
|
|
16
|
+
|
|
3
17
|
## [3.1.0](https://github.com/PunGrumpy/logixlysia/compare/v3.0.2...v3.1.0) (2024-04-09)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -14,15 +14,22 @@ bun add logixlysia
|
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
16
|
import { Elysia } from 'elysia'
|
|
17
|
-
import {
|
|
17
|
+
import { logixlysia } from 'logixlysia'
|
|
18
18
|
|
|
19
19
|
const app = new Elysia({
|
|
20
20
|
name: 'Logixlysia Example'
|
|
21
21
|
}).use(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
logixlysia({
|
|
23
|
+
config: {
|
|
24
|
+
ip: true,
|
|
25
|
+
customLogFormat:
|
|
26
|
+
'🦊 {now} {level} {duration} {method} {pathname} {status} {message} {ip}',
|
|
27
|
+
logFilter: {
|
|
28
|
+
level: ['ERROR', 'WARNING'],
|
|
29
|
+
status: [500, 404],
|
|
30
|
+
method: 'GET'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
26
33
|
})
|
|
27
34
|
)
|
|
28
35
|
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import pluginJs from '@eslint/js'
|
|
2
|
+
import eslintPlugin from '@typescript-eslint/eslint-plugin'
|
|
3
|
+
import eslintPluginSimpleImportSort from 'eslint-plugin-simple-import-sort'
|
|
4
|
+
import globals from 'globals'
|
|
5
|
+
import tseslint from 'typescript-eslint'
|
|
6
|
+
|
|
7
|
+
export default [
|
|
8
|
+
pluginJs.configs.recommended,
|
|
9
|
+
...tseslint.configs.recommended,
|
|
10
|
+
{
|
|
11
|
+
languageOptions: {
|
|
12
|
+
globals: globals.browser
|
|
13
|
+
},
|
|
14
|
+
plugins: {
|
|
15
|
+
'@typescript-eslint': eslintPlugin,
|
|
16
|
+
'simple-import-sort': eslintPluginSimpleImportSort
|
|
17
|
+
},
|
|
18
|
+
rules: {
|
|
19
|
+
'no-undef': 'off',
|
|
20
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
21
|
+
'simple-import-sort/imports': 'error',
|
|
22
|
+
'simple-import-sort/exports': 'error'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
]
|
package/lint-staged.config.cjs
CHANGED
|
@@ -1,27 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const isYarn = existsSync(join(process.cwd(), 'yarn.lock'))
|
|
7
|
-
const isPnpm = existsSync(join(process.cwd(), 'pnpm-lock.yaml'))
|
|
8
|
-
|
|
9
|
-
const packageManager = isBun ? 'bun' : isYarn ? 'yarn' : isPnpm ? 'pnpm' : 'npm'
|
|
10
|
-
|
|
11
|
-
const options = {
|
|
12
|
-
// TypeScript & JavaScript files
|
|
13
|
-
'**/*.(ts|tsx)': () => `${packageManager} tsc --noEmit`,
|
|
14
|
-
'**/*.(ts|tsx|js)': filenames => [
|
|
15
|
-
`${packageManager} eslint --fix ${filenames.join(' ')}`,
|
|
16
|
-
`${packageManager} prettier --write ${filenames.join(' ')}`
|
|
1
|
+
module.exports = {
|
|
2
|
+
'**/*.(ts)': () => `bun tsc --noEmit`,
|
|
3
|
+
'**/*.(ts|js|cjs)': filenames => [
|
|
4
|
+
`bun eslint --fix ${filenames.join(' ')}`,
|
|
5
|
+
`bun prettier --write ${filenames.join(' ')}`
|
|
17
6
|
],
|
|
18
|
-
'**/*.(
|
|
19
|
-
`${packageManager} test --timeout 5000 --coverage --update-snapshots ${filenames.join(
|
|
20
|
-
' '
|
|
21
|
-
)}`,
|
|
22
|
-
// Markdown & JSON files
|
|
23
|
-
'**/*.(md|json)': filenames =>
|
|
24
|
-
`${packageManager} prettier --write ${filenames.join(' ')}`
|
|
7
|
+
'**/*.(md|json)': filenames => `bun prettier --write ${filenames.join(' ')}`
|
|
25
8
|
}
|
|
26
|
-
|
|
27
|
-
module.exports = options
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "logixlysia",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "🦊 Logixlysia is a logger for Elysia",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
},
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"scripts": {
|
|
18
|
-
"lint": "eslint
|
|
19
|
-
"lint:fix": "eslint
|
|
18
|
+
"lint": "eslint ..",
|
|
19
|
+
"lint:fix": "eslint .. --fix",
|
|
20
20
|
"test": "bun test --timeout 5000 --coverage",
|
|
21
21
|
"test:ci": "bun test --timeout 5000 --coverage",
|
|
22
22
|
"publish": "npm publish",
|
|
@@ -68,20 +68,23 @@
|
|
|
68
68
|
"middleware"
|
|
69
69
|
],
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@
|
|
72
|
-
"@typescript-eslint/
|
|
71
|
+
"@eslint/js": "^9.3.0",
|
|
72
|
+
"@typescript-eslint/eslint-plugin": "^7.10.0",
|
|
73
|
+
"@typescript-eslint/parser": "^7.10.0",
|
|
73
74
|
"chalk": "^5.3.0",
|
|
74
|
-
"elysia": "^1.0.
|
|
75
|
-
"eslint": "
|
|
75
|
+
"elysia": "^1.0.21",
|
|
76
|
+
"eslint": "9.x",
|
|
77
|
+
"eslint-plugin-simple-import-sort": "^12.1.0",
|
|
78
|
+
"typescript-eslint": "^7.10.0"
|
|
76
79
|
},
|
|
77
80
|
"devDependencies": {
|
|
78
|
-
"@elysiajs/eden": "^1.0.
|
|
79
|
-
"bun-types": "^1.
|
|
81
|
+
"@elysiajs/eden": "^1.0.13",
|
|
82
|
+
"bun-types": "^1.1.9",
|
|
80
83
|
"commitizen": "^4.3.0",
|
|
81
84
|
"cz-conventional-changelog": "^3.3.0",
|
|
82
|
-
"husky": "^9.0.
|
|
83
|
-
"lint-staged": "^15.2.
|
|
84
|
-
"prettier": "^3.
|
|
85
|
+
"husky": "^9.0.11",
|
|
86
|
+
"lint-staged": "^15.2.4",
|
|
87
|
+
"prettier": "^3.2.5"
|
|
85
88
|
},
|
|
86
89
|
"peerDependencies": {
|
|
87
90
|
"typescript": "^5.0.0"
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import Elysia from 'elysia'
|
|
2
|
-
import { createLogger, handleHttpError } from './logger'
|
|
3
|
-
import startString from './utils/start'
|
|
4
1
|
import { Server } from 'bun'
|
|
2
|
+
import Elysia from 'elysia'
|
|
3
|
+
|
|
4
|
+
import { createLogger } from './logger'
|
|
5
|
+
import { handleHttpError } from './logger/handle'
|
|
5
6
|
import { HttpError, Options } from './types'
|
|
7
|
+
import startServer from './utils/start'
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Creates a logger.
|
|
@@ -19,14 +21,14 @@ import { HttpError, Options } from './types'
|
|
|
19
21
|
*
|
|
20
22
|
* @returns {Elysia} The logger.
|
|
21
23
|
*/
|
|
22
|
-
export
|
|
24
|
+
export default function logixlysia(options?: Options): Elysia {
|
|
23
25
|
const log = createLogger(options)
|
|
24
26
|
|
|
25
27
|
const elysia = new Elysia({
|
|
26
28
|
name: 'Logixlysia'
|
|
27
29
|
})
|
|
28
30
|
.onStart(ctx => {
|
|
29
|
-
|
|
31
|
+
startServer(ctx.server as Server)
|
|
30
32
|
})
|
|
31
33
|
.onRequest(ctx => {
|
|
32
34
|
ctx.store = { beforeTime: process.hrtime.bigint() }
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { LogLevel, Options } from '~/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Filters log messages.
|
|
5
|
+
*
|
|
6
|
+
* @param {LogLevel} logLevel The log level.
|
|
7
|
+
* @param {number} status The status code.
|
|
8
|
+
* @param {string} method The method.
|
|
9
|
+
* @param {Options} options The options.
|
|
10
|
+
* @returns {boolean} `true` if the log message should be logged, otherwise `false`.
|
|
11
|
+
*/
|
|
12
|
+
function filterLog(
|
|
13
|
+
logLevel: LogLevel,
|
|
14
|
+
status: number,
|
|
15
|
+
method: string,
|
|
16
|
+
options?: Options
|
|
17
|
+
): boolean {
|
|
18
|
+
const filter = options?.config?.logFilter
|
|
19
|
+
|
|
20
|
+
if (!filter) return true
|
|
21
|
+
|
|
22
|
+
if (filter.level) {
|
|
23
|
+
if (Array.isArray(filter.level)) {
|
|
24
|
+
if (!filter.level.includes(logLevel)) return false
|
|
25
|
+
} else {
|
|
26
|
+
if (filter.level !== logLevel) return false
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (filter.status) {
|
|
31
|
+
if (Array.isArray(filter.status)) {
|
|
32
|
+
if (!filter.status.includes(status)) return false
|
|
33
|
+
} else {
|
|
34
|
+
if (filter.status !== status) return false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (filter.method) {
|
|
39
|
+
if (Array.isArray(filter.method)) {
|
|
40
|
+
if (!filter.method.includes(method)) return false
|
|
41
|
+
} else {
|
|
42
|
+
if (filter.method !== method) return false
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return true
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { filterLog }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { HttpError, Options, RequestInfo, StoreData } from '~/types'
|
|
2
|
+
|
|
3
|
+
import { buildLogMessage } from '.'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handles an HTTP error.
|
|
7
|
+
*
|
|
8
|
+
* @param {RequestInfo} request The request.
|
|
9
|
+
* @param {HttpError} error The HTTP error.
|
|
10
|
+
* @param {StoreData} store The store data.
|
|
11
|
+
* @param {Options} options The options.
|
|
12
|
+
*/
|
|
13
|
+
function handleHttpError(
|
|
14
|
+
request: RequestInfo,
|
|
15
|
+
error: HttpError,
|
|
16
|
+
store: StoreData,
|
|
17
|
+
options?: Options
|
|
18
|
+
): void {
|
|
19
|
+
const statusCode = error.status || 500
|
|
20
|
+
const logMessage = buildLogMessage(
|
|
21
|
+
'ERROR',
|
|
22
|
+
request,
|
|
23
|
+
{ status: statusCode },
|
|
24
|
+
store,
|
|
25
|
+
options
|
|
26
|
+
)
|
|
27
|
+
console.error(logMessage)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { handleHttpError }
|
|
@@ -1,67 +1,20 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
|
-
|
|
3
|
-
import methodString from './utils/method'
|
|
4
|
-
import logString from './utils/log'
|
|
5
|
-
import pathString from './utils/path'
|
|
6
|
-
import statusString from './utils/status'
|
|
2
|
+
|
|
7
3
|
import {
|
|
8
|
-
LogLevel,
|
|
9
4
|
LogData,
|
|
10
5
|
Logger,
|
|
11
|
-
|
|
6
|
+
LogLevel,
|
|
12
7
|
Options,
|
|
13
8
|
RequestInfo,
|
|
14
|
-
|
|
15
|
-
} from '
|
|
9
|
+
StoreData
|
|
10
|
+
} from '~/types'
|
|
11
|
+
import durationString from '~/utils/duration'
|
|
12
|
+
import logString from '~/utils/log'
|
|
13
|
+
import methodString from '~/utils/method'
|
|
14
|
+
import pathString from '~/utils/path'
|
|
15
|
+
import statusString from '~/utils/status'
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
* Filters log messages.
|
|
19
|
-
*
|
|
20
|
-
* @param {LogLevel} logLevel The log level.
|
|
21
|
-
* @param {number} status The status code.
|
|
22
|
-
* @param {string} method The method.
|
|
23
|
-
* @param {Options} options The options.
|
|
24
|
-
* @returns {boolean} `true` if the log message should be logged, otherwise `false`.
|
|
25
|
-
*/
|
|
26
|
-
function filterLog(
|
|
27
|
-
logLevel: LogLevel,
|
|
28
|
-
status: number,
|
|
29
|
-
method: string,
|
|
30
|
-
options?: Options
|
|
31
|
-
): boolean {
|
|
32
|
-
const filter = options?.config?.logFilter
|
|
33
|
-
|
|
34
|
-
if (!filter) return true
|
|
35
|
-
|
|
36
|
-
// Level
|
|
37
|
-
if (filter.level) {
|
|
38
|
-
if (Array.isArray(filter.level)) {
|
|
39
|
-
if (!filter.level.includes(logLevel)) return false
|
|
40
|
-
}
|
|
41
|
-
} else {
|
|
42
|
-
if (filter.level !== logLevel) return false
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Status
|
|
46
|
-
if (filter.status) {
|
|
47
|
-
if (Array.isArray(filter.status)) {
|
|
48
|
-
if (!filter.status.includes(status)) return false
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
if (filter.status !== status) return false
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Method
|
|
55
|
-
if (filter.method) {
|
|
56
|
-
if (Array.isArray(filter.method)) {
|
|
57
|
-
if (!filter.method.includes(method)) return false
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
60
|
-
if (filter.method !== method) return false
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return true
|
|
64
|
-
}
|
|
17
|
+
import { filterLog } from './filter'
|
|
65
18
|
|
|
66
19
|
/**
|
|
67
20
|
* Logs a message.
|
|
@@ -138,33 +91,12 @@ function buildLogMessage(
|
|
|
138
91
|
* @param {Options} options The options.
|
|
139
92
|
* @returns {Logger} The logger.
|
|
140
93
|
*/
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
log(level, request, data, store
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Handles an HTTP error.
|
|
149
|
-
*
|
|
150
|
-
* @param {RequestInfo} request The request.
|
|
151
|
-
* @param {HttpError} error The HTTP error.
|
|
152
|
-
* @param {StoreData} store The store data.
|
|
153
|
-
* @param {Options} options The options.
|
|
154
|
-
*/
|
|
155
|
-
export const handleHttpError = (
|
|
156
|
-
request: RequestInfo,
|
|
157
|
-
error: HttpError,
|
|
158
|
-
store: StoreData,
|
|
159
|
-
options?: Options
|
|
160
|
-
): void => {
|
|
161
|
-
const statusCode = error.status || 500
|
|
162
|
-
const logMessage = buildLogMessage(
|
|
163
|
-
'ERROR',
|
|
164
|
-
request,
|
|
165
|
-
{ status: statusCode },
|
|
166
|
-
store,
|
|
167
|
-
options
|
|
168
|
-
)
|
|
169
|
-
console.error(logMessage)
|
|
94
|
+
function createLogger(options?: Options): Logger {
|
|
95
|
+
return {
|
|
96
|
+
log: (level, request, data, store) =>
|
|
97
|
+
log(level, request, data, store, options),
|
|
98
|
+
customLogFormat: options?.config?.customLogFormat
|
|
99
|
+
}
|
|
170
100
|
}
|
|
101
|
+
|
|
102
|
+
export { buildLogMessage, createLogger, log }
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
interface RequestInfo {
|
|
2
|
-
headers: { get: (key: string) =>
|
|
2
|
+
headers: { get: (key: string) => string | null }
|
|
3
3
|
method: string
|
|
4
4
|
url: string
|
|
5
5
|
}
|
|
@@ -57,13 +57,13 @@ interface Options {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export {
|
|
60
|
-
RequestInfo,
|
|
61
|
-
Server,
|
|
62
60
|
ColorMap,
|
|
63
|
-
|
|
61
|
+
HttpError,
|
|
64
62
|
LogData,
|
|
65
63
|
Logger,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
LogLevel,
|
|
65
|
+
Options,
|
|
66
|
+
RequestInfo,
|
|
67
|
+
Server,
|
|
68
|
+
StoreData
|
|
69
69
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
|
+
|
|
2
3
|
import { ColorMap } from '~/types'
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -22,19 +23,19 @@ const LogLevelColorMap: ColorMap = {
|
|
|
22
23
|
* @property {chalk.Chalk} GET The color for the GET HTTP method.
|
|
23
24
|
* @property {chalk.Chalk} POST The color for the POST HTTP method.
|
|
24
25
|
* @property {chalk.Chalk} PUT The color for the PUT HTTP method.
|
|
25
|
-
* @property {chalk.Chalk} DELETE The color for the DELETE HTTP method.
|
|
26
26
|
* @property {chalk.Chalk} PATCH The color for the PATCH HTTP method.
|
|
27
|
-
* @property {chalk.Chalk}
|
|
27
|
+
* @property {chalk.Chalk} DELETE The color for the DELETE HTTP method.
|
|
28
28
|
* @property {chalk.Chalk} HEAD The color for the HEAD HTTP method.
|
|
29
|
+
* @property {chalk.Chalk} OPTIONS The color for the OPTIONS HTTP method.
|
|
29
30
|
*/
|
|
30
31
|
const HttpMethodColorMap: ColorMap = {
|
|
31
|
-
GET: chalk.
|
|
32
|
+
GET: chalk.green,
|
|
32
33
|
POST: chalk.yellow,
|
|
33
34
|
PUT: chalk.blue,
|
|
35
|
+
PATCH: chalk.magentaBright,
|
|
34
36
|
DELETE: chalk.red,
|
|
35
|
-
|
|
36
|
-
OPTIONS: chalk.
|
|
37
|
-
HEAD: chalk.magenta
|
|
37
|
+
HEAD: chalk.cyan,
|
|
38
|
+
OPTIONS: chalk.magenta
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
export {
|
|
41
|
+
export { HttpMethodColorMap, LogLevelColorMap }
|
package/src/utils/log.ts
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
+
import { LogLevel } from '~/types'
|
|
2
|
+
|
|
1
3
|
import { LogLevelColorMap } from './colorMapping'
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
|
-
* Converts
|
|
5
|
-
*
|
|
6
|
-
* @param {string} log The log level (e.g., 'INFO', 'WARNING').
|
|
6
|
+
* Converts the log level to a string.
|
|
7
7
|
*
|
|
8
|
-
* @
|
|
8
|
+
* @param {LogLevel} level The log level.
|
|
9
|
+
* @returns {string} The log level as a string.
|
|
9
10
|
*/
|
|
10
|
-
function logString(
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
if (colorFunction) {
|
|
14
|
-
return colorFunction(log.padEnd(7))
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return log
|
|
11
|
+
function logString(level: LogLevel): string {
|
|
12
|
+
const levelStr = level.toUpperCase()
|
|
13
|
+
return LogLevelColorMap[levelStr]?.(levelStr.padEnd(7)) || levelStr
|
|
18
14
|
}
|
|
19
15
|
|
|
20
16
|
export default logString
|
package/src/utils/start.ts
CHANGED
|
@@ -21,7 +21,7 @@ function createBoxText(text: string, width: number): string {
|
|
|
21
21
|
*
|
|
22
22
|
* @returns {void} The server string.
|
|
23
23
|
*/
|
|
24
|
-
function
|
|
24
|
+
function startServer(config: Server): void {
|
|
25
25
|
const { hostname, port, protocol } = config
|
|
26
26
|
const ELYSIA_VERSION = import.meta.require('elysia/package.json').version
|
|
27
27
|
const title = `Elysia v${ELYSIA_VERSION}`
|
|
@@ -41,4 +41,4 @@ function startString(config: Server): void {
|
|
|
41
41
|
`)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export default
|
|
44
|
+
export default startServer
|
package/src/utils/status.ts
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Converts the status code to a string.
|
|
5
5
|
*
|
|
6
6
|
* @param {number} status The status code.
|
|
7
7
|
*
|
|
8
|
-
* @returns {string} The status string.
|
|
8
|
+
* @returns {string} The status code as a string.
|
|
9
9
|
*/
|
|
10
10
|
function statusString(status: number): string {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
11
|
+
const color =
|
|
12
|
+
status >= 500
|
|
13
|
+
? 'red'
|
|
14
|
+
: status >= 400
|
|
15
|
+
? 'yellow'
|
|
16
|
+
: status >= 300
|
|
17
|
+
? 'cyan'
|
|
18
|
+
: status >= 200
|
|
19
|
+
? 'green'
|
|
20
|
+
: 'white'
|
|
21
|
+
return chalk[color](status.toString())
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export default statusString
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { filterLog } from '~/logger/filter'
|
|
4
|
+
import { LogLevel, Options } from '~/types'
|
|
5
|
+
|
|
6
|
+
describe('filterLog', () => {
|
|
7
|
+
const logLevel: LogLevel = 'info'
|
|
8
|
+
const status = 200
|
|
9
|
+
const method = 'GET'
|
|
10
|
+
|
|
11
|
+
it('should return true if no filter is provided', () => {
|
|
12
|
+
expect(filterLog(logLevel, status, method)).toBe(true)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('should filter by log level (single value)', () => {
|
|
16
|
+
const options: Options = { config: { logFilter: { level: 'error' } } }
|
|
17
|
+
expect(filterLog(logLevel, status, method, options)).toBe(false)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should filter by log level (array)', () => {
|
|
21
|
+
const options: Options = {
|
|
22
|
+
config: { logFilter: { level: ['error', 'info'] } }
|
|
23
|
+
}
|
|
24
|
+
expect(filterLog(logLevel, status, method, options)).toBe(true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should filter by status (single value)', () => {
|
|
28
|
+
const options: Options = { config: { logFilter: { status: 404 } } }
|
|
29
|
+
expect(filterLog(logLevel, status, method, options)).toBe(false)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should filter by status (array)', () => {
|
|
33
|
+
const options: Options = { config: { logFilter: { status: [200, 404] } } }
|
|
34
|
+
expect(filterLog(logLevel, status, method, options)).toBe(true)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should filter by method (single value)', () => {
|
|
38
|
+
const options: Options = { config: { logFilter: { method: 'POST' } } }
|
|
39
|
+
expect(filterLog(logLevel, status, method, options)).toBe(false)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('should filter by method (array)', () => {
|
|
43
|
+
const options: Options = {
|
|
44
|
+
config: { logFilter: { method: ['GET', 'POST'] } }
|
|
45
|
+
}
|
|
46
|
+
expect(filterLog(logLevel, status, method, options)).toBe(true)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('should return false if any filter condition is not met', () => {
|
|
50
|
+
const options: Options = {
|
|
51
|
+
config: { logFilter: { level: 'info', status: 404, method: 'POST' } }
|
|
52
|
+
}
|
|
53
|
+
expect(filterLog(logLevel, status, method, options)).toBe(false)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('should return true if all filter conditions are met', () => {
|
|
57
|
+
const options: Options = {
|
|
58
|
+
config: { logFilter: { level: 'info', status: 200, method: 'GET' } }
|
|
59
|
+
}
|
|
60
|
+
expect(filterLog(logLevel, status, method, options)).toBe(true)
|
|
61
|
+
})
|
|
62
|
+
})
|
package/test/logixlysia.test.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { Elysia } from 'elysia'
|
|
2
1
|
import { edenTreaty } from '@elysiajs/eden'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { beforeAll, beforeEach, describe, expect, it } from 'bun:test'
|
|
3
|
+
import { Elysia } from 'elysia'
|
|
4
|
+
|
|
5
|
+
import logixlysia from '../src'
|
|
5
6
|
|
|
6
7
|
describe('Logixlysia with IP logging enabled', () => {
|
|
7
8
|
let server: Elysia
|
|
8
|
-
let app: any
|
|
9
|
+
let app: ReturnType<typeof edenTreaty> | any
|
|
9
10
|
let logs: string[] = []
|
|
10
11
|
|
|
11
12
|
beforeAll(() => {
|
|
12
13
|
server = new Elysia()
|
|
13
14
|
.use(
|
|
14
|
-
|
|
15
|
+
logixlysia({
|
|
15
16
|
config: {
|
|
16
17
|
ip: true,
|
|
17
18
|
customLogFormat:
|
|
@@ -19,8 +20,7 @@ describe('Logixlysia with IP logging enabled', () => {
|
|
|
19
20
|
}
|
|
20
21
|
})
|
|
21
22
|
)
|
|
22
|
-
.get('/',
|
|
23
|
-
const ipAddress = ctx.request.headers.get('x-forwarded-for') || 'null'
|
|
23
|
+
.get('/', () => {
|
|
24
24
|
return '🦊 Logixlysia Getting'
|
|
25
25
|
})
|
|
26
26
|
.post('logixlysia', () => '🦊 Logixlysia Posting')
|
|
@@ -50,12 +50,6 @@ describe('Logixlysia with IP logging enabled', () => {
|
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
it("Logs 'null' for GET '/' requests when X-Forwarded-For header is not present", async () => {
|
|
53
|
-
const requestCount = 5
|
|
54
|
-
|
|
55
|
-
for (let i = 0; i < requestCount; i++) {
|
|
56
|
-
const response = await app.get('/')
|
|
57
|
-
}
|
|
58
|
-
|
|
59
53
|
logs.forEach(log => {
|
|
60
54
|
expect(log).toMatch(/^🦊 .+ INFO .+ .+ GET \/ .+ IP: null$/)
|
|
61
55
|
})
|
|
@@ -64,13 +58,13 @@ describe('Logixlysia with IP logging enabled', () => {
|
|
|
64
58
|
|
|
65
59
|
describe('Logixlysia with IP logging disabled', () => {
|
|
66
60
|
let server: Elysia
|
|
67
|
-
let app: any
|
|
61
|
+
let app: ReturnType<typeof edenTreaty> | any
|
|
68
62
|
let logs: string[] = []
|
|
69
63
|
|
|
70
64
|
beforeAll(() => {
|
|
71
65
|
server = new Elysia()
|
|
72
66
|
.use(
|
|
73
|
-
|
|
67
|
+
logixlysia({
|
|
74
68
|
config: {
|
|
75
69
|
ip: false,
|
|
76
70
|
customLogFormat:
|
|
@@ -127,13 +121,13 @@ describe('Logixlysia with IP logging disabled', () => {
|
|
|
127
121
|
|
|
128
122
|
describe('Logixlysia with log filtering enabled', () => {
|
|
129
123
|
let server: Elysia
|
|
130
|
-
let app: any
|
|
124
|
+
let app: ReturnType<typeof edenTreaty> | any
|
|
131
125
|
let logs: string[] = []
|
|
132
126
|
|
|
133
127
|
beforeAll(() => {
|
|
134
128
|
server = new Elysia()
|
|
135
129
|
.use(
|
|
136
|
-
|
|
130
|
+
logixlysia({
|
|
137
131
|
config: {
|
|
138
132
|
logFilter: {
|
|
139
133
|
level: 'INFO',
|
|
@@ -193,13 +187,13 @@ describe('Logixlysia with log filtering enabled', () => {
|
|
|
193
187
|
|
|
194
188
|
describe('Logixlysia with log filtering disabled', () => {
|
|
195
189
|
let server: Elysia
|
|
196
|
-
let app: any
|
|
190
|
+
let app: ReturnType<typeof edenTreaty> | any
|
|
197
191
|
let logs: string[] = []
|
|
198
192
|
|
|
199
193
|
beforeAll(() => {
|
|
200
194
|
server = new Elysia()
|
|
201
195
|
.use(
|
|
202
|
-
|
|
196
|
+
logixlysia({
|
|
203
197
|
config: {
|
|
204
198
|
logFilter: null
|
|
205
199
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, jest } from 'bun:test'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { LogData, RequestInfo, StoreData } from '~/types'
|
|
3
4
|
|
|
4
5
|
interface Logger {
|
|
5
6
|
info(request: RequestInfo, data: LogData, store: StoreData): void
|
package/test/utils/log.test.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { describe, expect, it } from 'bun:test'
|
|
2
2
|
import chalk from 'chalk'
|
|
3
|
+
|
|
3
4
|
import methodString from '~/utils/method'
|
|
4
5
|
|
|
5
6
|
describe('Method String', () => {
|
|
6
7
|
it('Displays a colored string for the GET method', () => {
|
|
7
8
|
const result = methodString('GET')
|
|
8
|
-
expect(result).toBe(chalk.
|
|
9
|
+
expect(result).toBe(chalk.green('GET '))
|
|
9
10
|
})
|
|
10
11
|
|
|
11
12
|
it('Displays a colored string for the POST method', () => {
|
package/test/utils/path.test.ts
CHANGED
package/test/utils/start.test.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, jest } from 'bun:test'
|
|
2
|
+
|
|
2
3
|
import { Server } from '~/types'
|
|
3
|
-
import
|
|
4
|
+
import startServer from '~/utils/start'
|
|
4
5
|
|
|
5
6
|
describe('Start String', () => {
|
|
6
|
-
let originalConsoleLog:
|
|
7
|
+
let originalConsoleLog: typeof console.log
|
|
7
8
|
let mockConsoleLog: jest.Mock
|
|
8
9
|
|
|
9
10
|
beforeEach(() => {
|
|
@@ -23,13 +24,13 @@ describe('Start String', () => {
|
|
|
23
24
|
protocol: 'http'
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
startServer(config)
|
|
27
28
|
|
|
28
29
|
const expectedMessage = `🦊 Elysia is running at http://localhost:3000`
|
|
29
30
|
|
|
30
31
|
// Extract the arguments passed to console.log during the function call
|
|
31
32
|
const logMessage = mockConsoleLog.mock.calls
|
|
32
|
-
.map(
|
|
33
|
+
.map(args => args.join(' '))
|
|
33
34
|
.join(' ')
|
|
34
35
|
|
|
35
36
|
expect(logMessage).toMatch(expectedMessage)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import chalk from 'chalk'
|
|
2
1
|
import { describe, expect, it } from 'bun:test'
|
|
2
|
+
import chalk from 'chalk'
|
|
3
|
+
|
|
3
4
|
import statusString from '~/utils/status'
|
|
4
5
|
|
|
5
6
|
describe('Status String', () => {
|
|
@@ -8,23 +9,23 @@ describe('Status String', () => {
|
|
|
8
9
|
expect(result).toBe(chalk.green('200'))
|
|
9
10
|
})
|
|
10
11
|
|
|
11
|
-
it('Presents the status string in
|
|
12
|
+
it('Presents the status string in cyan for a 301 status code', () => {
|
|
12
13
|
const result = statusString(301)
|
|
13
14
|
expect(result).toBe(chalk.cyan('301'))
|
|
14
15
|
})
|
|
15
16
|
|
|
16
|
-
it('Presents the status string in
|
|
17
|
+
it('Presents the status string in yellow for a 404 status code', () => {
|
|
17
18
|
const result = statusString(404)
|
|
18
19
|
expect(result).toBe(chalk.yellow('404'))
|
|
19
20
|
})
|
|
20
21
|
|
|
21
|
-
it('Presents the status string in
|
|
22
|
+
it('Presents the status string in red for a 500 status code', () => {
|
|
22
23
|
const result = statusString(500)
|
|
23
24
|
expect(result).toBe(chalk.red('500'))
|
|
24
25
|
})
|
|
25
26
|
|
|
26
|
-
it('Presents the status string in
|
|
27
|
+
it('Presents the status string in white for a 100 status code', () => {
|
|
27
28
|
const result = statusString(100)
|
|
28
|
-
expect(result).toBe('100')
|
|
29
|
+
expect(result).toBe(chalk.white('100'))
|
|
29
30
|
})
|
|
30
31
|
})
|
package/eslint.config.cjs
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
env: {
|
|
3
|
-
es2021: true,
|
|
4
|
-
node: true
|
|
5
|
-
},
|
|
6
|
-
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
|
7
|
-
parser: '@typescript-eslint/parser',
|
|
8
|
-
parserOptions: {
|
|
9
|
-
ecmaVersion: 'latest',
|
|
10
|
-
sourceType: 'module'
|
|
11
|
-
},
|
|
12
|
-
plugins: ['@typescript-eslint'],
|
|
13
|
-
rules: {
|
|
14
|
-
'@typescript-eslint/ban-types': 'off',
|
|
15
|
-
'@typescript-eslint/no-explicit-any': 'off',
|
|
16
|
-
'no-mixed-spaces-and-tabs': 'off',
|
|
17
|
-
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
18
|
-
'@typescript-eslint/no-extra-semi': 'off',
|
|
19
|
-
'@typescript-eslint/ban-ts-comment': 'off',
|
|
20
|
-
'@typescript-eslint/no-namespace': 'off',
|
|
21
|
-
'no-case-declarations': 'off',
|
|
22
|
-
'no-extra-semi': 'off'
|
|
23
|
-
},
|
|
24
|
-
ignorePatterns: ['example/*', 'tests/**/*', 'lint-staged.config.js']
|
|
25
|
-
}
|