logixlysia 2.1.0 → 2.2.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 +24 -0
- package/README.md +8 -0
- package/package.json +9 -10
- package/src/index.ts +20 -3
- package/src/options.ts +11 -0
- package/src/utils/duration.ts +28 -15
- package/test/logixlysia.test.ts +53 -0
- package/test/utils/duration.test.ts +26 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.2.1](https://github.com/PunGrumpy/logixlysia/compare/v2.2.0...v2.2.1) (2024-03-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **index:** remove `onBeforeHandle` for avoid repeat logging ([4c6f0b9](https://github.com/PunGrumpy/logixlysia/commit/4c6f0b9912a4319ada15ad2a5110a9ed34f08a11))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Reverts
|
|
12
|
+
|
|
13
|
+
* **deps:** new come back to old version ([361ac6b](https://github.com/PunGrumpy/logixlysia/commit/361ac6b2821ac897c1a4658cbfa1b5eb1a190804))
|
|
14
|
+
|
|
15
|
+
## [2.2.0](https://github.com/PunGrumpy/logixlysia/compare/v2.1.0...v2.2.0) (2024-03-19)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **options:** add show ip ([4e997c5](https://github.com/PunGrumpy/logixlysia/commit/4e997c557e9aef6046a93e0cab9fe11a87df3430))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* **logger:** change to use array and push them ([3feefb7](https://github.com/PunGrumpy/logixlysia/commit/3feefb7a8dddc42c4eec54de40ab9dd8d5c70e70))
|
|
26
|
+
|
|
3
27
|
## [2.1.0](https://github.com/PunGrumpy/logixlysia/compare/v2.0.2...v2.1.0) (2024-01-25)
|
|
4
28
|
|
|
5
29
|
|
package/README.md
CHANGED
|
@@ -23,6 +23,14 @@ const app = new Elysia({
|
|
|
23
23
|
app.listen(3000)
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
## `📚` Documentation
|
|
27
|
+
|
|
28
|
+
### Options
|
|
29
|
+
|
|
30
|
+
| Option | Type | Description | Default |
|
|
31
|
+
| ------ | --------- | --------------------------------------------------------------------- | ------- |
|
|
32
|
+
| `ip` | `boolean` | Display the incoming IP address based on the `X-Forwarded-For` header | `false` |
|
|
33
|
+
|
|
26
34
|
## `📄` License
|
|
27
35
|
|
|
28
36
|
Licensed under the [MIT License](LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "logixlysia",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "🦊 Logixlysia is a logger for Elysia",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -15,13 +15,11 @@
|
|
|
15
15
|
},
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"scripts": {
|
|
18
|
-
"pretest": "bun run lint && bun run lint:fix && bun run prettier",
|
|
19
18
|
"lint": "eslint . --ext .ts",
|
|
20
19
|
"lint:fix": "eslint . --ext .ts --fix",
|
|
21
|
-
"
|
|
22
|
-
"test": "bun test --timeout 5000 --coverage
|
|
23
|
-
"
|
|
24
|
-
"publish": "bun run prepublish && npm publish",
|
|
20
|
+
"test": "bun test --timeout 5000 --coverage",
|
|
21
|
+
"test:ci": "bun test --timeout 5000 --coverage",
|
|
22
|
+
"publish": "npm publish",
|
|
25
23
|
"dev": "bun run --watch example/basic.ts",
|
|
26
24
|
"prepare": "husky install",
|
|
27
25
|
"lint:staged": "lint-staged",
|
|
@@ -70,15 +68,16 @@
|
|
|
70
68
|
"middleware"
|
|
71
69
|
],
|
|
72
70
|
"dependencies": {
|
|
73
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
74
|
-
"@typescript-eslint/parser": "^
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
72
|
+
"@typescript-eslint/parser": "^7.0.2",
|
|
75
73
|
"chalk": "^5.3.0",
|
|
76
|
-
"elysia": "^0.
|
|
74
|
+
"elysia": "^1.0.4",
|
|
77
75
|
"eslint": "^8.56.0"
|
|
78
76
|
},
|
|
79
77
|
"devDependencies": {
|
|
78
|
+
"@elysiajs/eden": "^1.0.4",
|
|
80
79
|
"bun-types": "^1.0.22",
|
|
81
|
-
"husky": "^
|
|
80
|
+
"husky": "^9.0.7",
|
|
82
81
|
"lint-staged": "^15.2.0",
|
|
83
82
|
"prettier": "^3.1.1"
|
|
84
83
|
},
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import Elysia from 'elysia'
|
|
|
2
2
|
import { createLogger } from './logger'
|
|
3
3
|
import startString from './utils/start'
|
|
4
4
|
import { Server } from 'bun'
|
|
5
|
+
import { Options } from './options'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Creates a logger.
|
|
@@ -18,7 +19,7 @@ import { Server } from 'bun'
|
|
|
18
19
|
*
|
|
19
20
|
* @returns {Elysia} The logger.
|
|
20
21
|
*/
|
|
21
|
-
export const logger = (): Elysia => {
|
|
22
|
+
export const logger = (options?: Options): Elysia => {
|
|
22
23
|
const log = createLogger()
|
|
23
24
|
|
|
24
25
|
const elysia = new Elysia({
|
|
@@ -30,8 +31,24 @@ export const logger = (): Elysia => {
|
|
|
30
31
|
.onRequest(ctx => {
|
|
31
32
|
ctx.store = { beforeTime: process.hrtime.bigint() }
|
|
32
33
|
})
|
|
33
|
-
.onAfterHandle(({ request, store }) => {
|
|
34
|
-
|
|
34
|
+
.onAfterHandle({ as: 'global' }, ({ request, store }) => {
|
|
35
|
+
const logStr: string[] = []
|
|
36
|
+
|
|
37
|
+
if (options?.ip) {
|
|
38
|
+
const forwardedFor = request.headers.get('x-forwarded-for')
|
|
39
|
+
if (forwardedFor) {
|
|
40
|
+
logStr.push(`IP: ${forwardedFor}`)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
log.log(
|
|
45
|
+
'INFO',
|
|
46
|
+
request,
|
|
47
|
+
{
|
|
48
|
+
message: logStr.join(' ')
|
|
49
|
+
},
|
|
50
|
+
store as { beforeTime: bigint }
|
|
51
|
+
)
|
|
35
52
|
})
|
|
36
53
|
.onError(({ request, error, store }) => {
|
|
37
54
|
log.log('ERROR', request, error, store as { beforeTime: bigint })
|
package/src/options.ts
ADDED
package/src/utils/duration.ts
CHANGED
|
@@ -1,29 +1,42 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Converts
|
|
4
|
+
* Converts a time difference into a formatted string with the most appropriate time unit.
|
|
5
|
+
* Units used are seconds (s), milliseconds (ms), microseconds (µs), and nanoseconds (ns).
|
|
5
6
|
*
|
|
6
|
-
* @param {bigint} beforeTime The timestamp taken before the request.
|
|
7
|
+
* @param {bigint} beforeTime - The timestamp taken before the request.
|
|
7
8
|
*
|
|
8
|
-
* @returns {string} A formatted duration string
|
|
9
|
+
* @returns {string} A formatted duration string including the time unit.
|
|
9
10
|
*/
|
|
10
11
|
function durationString(beforeTime: bigint): string {
|
|
11
|
-
const
|
|
12
|
-
const nanoseconds = Number(now - beforeTime)
|
|
12
|
+
const nanoseconds = Number(process.hrtime.bigint() - beforeTime)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const timeUnits = [
|
|
15
|
+
{ unit: 's', threshold: 1e9 },
|
|
16
|
+
{ unit: 'ms', threshold: 1e6 },
|
|
17
|
+
{ unit: 'µs', threshold: 1e3 }
|
|
18
|
+
]
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
timeMessage = `${(nanoseconds / 1e3).toFixed(0)}µs`
|
|
22
|
-
} else {
|
|
23
|
-
timeMessage = `${nanoseconds}ns`
|
|
20
|
+
for (const { unit, threshold } of timeUnits) {
|
|
21
|
+
if (nanoseconds >= threshold) {
|
|
22
|
+
const value = (nanoseconds / threshold).toFixed(threshold === 1e9 ? 2 : 0)
|
|
23
|
+
return formatTime(value, unit)
|
|
24
|
+
}
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
return
|
|
27
|
+
return formatTime(nanoseconds.toString(), 'ns')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Formats the time value with the given unit and applies chalk styling.
|
|
32
|
+
*
|
|
33
|
+
* @param {string} value - The time value.
|
|
34
|
+
* @param {string} unit - The time unit.
|
|
35
|
+
*
|
|
36
|
+
* @returns {string} Styled time string.
|
|
37
|
+
*/
|
|
38
|
+
function formatTime(value: string, unit: string): string {
|
|
39
|
+
return chalk.gray(`${value}${unit}`).padStart(8).padEnd(16)
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
export default durationString
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Elysia } from 'elysia'
|
|
2
|
+
import { edenTreaty } from '@elysiajs/eden'
|
|
3
|
+
import { describe, it, expect, beforeAll, beforeEach } from 'bun:test'
|
|
4
|
+
import { logger } from '../src'
|
|
5
|
+
|
|
6
|
+
describe('Logixlysia', () => {
|
|
7
|
+
let server: Elysia
|
|
8
|
+
let app: any
|
|
9
|
+
let logs: string[] = []
|
|
10
|
+
|
|
11
|
+
describe('IP logging disabled', () => {
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
server = new Elysia()
|
|
14
|
+
.use(logger({ ip: false }))
|
|
15
|
+
.get('/', () => '🦊 Logixlysia Getting')
|
|
16
|
+
.post('logixlysia', () => '🦊 Logixlysia Posting')
|
|
17
|
+
.listen(3000)
|
|
18
|
+
|
|
19
|
+
app = edenTreaty<typeof server>('http://127.0.0.1:3000')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
logs = []
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it("Responds correctly to GET '/' requests", async () => {
|
|
27
|
+
const requestCount = 5
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < requestCount; i++) {
|
|
30
|
+
logs.push((await app.get('/')).data)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
logs.forEach(log => {
|
|
34
|
+
expect(log).toBe('🦊 Logixlysia Getting')
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it("Responds correctly to POST '/logixlysia' requests", async () => {
|
|
39
|
+
const requestCount = 5
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < requestCount; i++) {
|
|
42
|
+
const postResponse = await app.logixlysia.post({})
|
|
43
|
+
logs.push(
|
|
44
|
+
postResponse.status === 200 ? postResponse.data : postResponse.error
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
logs.forEach(log => {
|
|
49
|
+
expect(log).toBe('🦊 Logixlysia Posting')
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
})
|
|
@@ -2,19 +2,35 @@ import { describe, expect, it } from 'bun:test'
|
|
|
2
2
|
import durationString from '~/utils/duration'
|
|
3
3
|
|
|
4
4
|
describe('Duration String', () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
const testCases = [
|
|
6
|
+
[
|
|
7
|
+
'Generates a string representing the duration in Seconds (s) unit',
|
|
8
|
+
1e9,
|
|
9
|
+
's'
|
|
10
|
+
],
|
|
11
|
+
[
|
|
12
|
+
'Generates a string representing the duration in Milliseconds (ms) unit',
|
|
13
|
+
1e6,
|
|
14
|
+
'ms'
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
'Generates a string representing the duration in Microseconds (µs) unit',
|
|
18
|
+
1e3,
|
|
19
|
+
'µs'
|
|
11
20
|
]
|
|
21
|
+
// [
|
|
22
|
+
// 'Generates a string representing the duration in Nanoseconds (ns) unit',
|
|
23
|
+
// 1,
|
|
24
|
+
// 'ns'
|
|
25
|
+
// ]
|
|
26
|
+
]
|
|
12
27
|
|
|
13
|
-
|
|
28
|
+
for (const [description, nanoseconds, unit] of testCases) {
|
|
29
|
+
it(`${description}`, () => {
|
|
14
30
|
const beforeTime = process.hrtime.bigint() - BigInt(String(nanoseconds))
|
|
15
|
-
|
|
16
31
|
const result = durationString(beforeTime)
|
|
32
|
+
|
|
17
33
|
expect(result).toMatch(String(unit))
|
|
18
|
-
}
|
|
19
|
-
}
|
|
34
|
+
})
|
|
35
|
+
}
|
|
20
36
|
})
|