diff --git a/.gitignore b/.gitignore index 824b84f..65df6c2 100644 --- a/.gitignore +++ b/.gitignore @@ -174,3 +174,5 @@ dist # Finder (MacOS) folder config .DS_Store + +test.log \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index b22a787..d9a9503 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 369dbd1..5bf3a8d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "type": "module", "scripts": { "build": "rimraf dist && bun build src/index.ts --outdir dist --target bun --minify -e elysia && tsc", - "test": "bun test", + "test": "echo ' ' > test.log && bun test", "prepublishOnly": "bun run build" }, "peerDependencies": { diff --git a/preview/src/index.ts b/preview/src/index.ts index a354ce9..43d89aa 100644 --- a/preview/src/index.ts +++ b/preview/src/index.ts @@ -1,8 +1,17 @@ import { Elysia } from 'elysia'; import { Logestic } from 'logestic'; +const logger = new Logestic().use(['method', 'status']).format({ + onSuccess({ method, status }) { + return `${method} ${status}`; + }, + onFailure({ request, code }) { + return `${request.method} ${code}`; + } +}); + const app = new Elysia() - .use(Logestic.preset('fancy')) + .use(logger) .get('/', () => 'Hello, world!') .get('/hello/:name', ({ params: { name } }) => `Hello, ${name}!`) .get('/returnBad', ({ set, logestic }) => { @@ -16,5 +25,7 @@ const app = new Elysia() return 'Server crashed'; }) .listen(3000, () => { - // console.log('Server is running on port 3000'); + console.log('Server is running on port 3000'); }); + +export default app; diff --git a/src/index.ts b/src/index.ts index ca821af..bbec8e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,7 +60,9 @@ export class Logestic { return; } - // Custom file destination + // Custom file destination // afterAll(async () => { + // await unlink(tempFilePath); + // }); this.createFileIfNotExists(dest) .then(file => (this.dest = file)) .catch(err => { @@ -170,16 +172,12 @@ export class Logestic { const msgNewLine = `${msg}\n`; if (!this.dest.name || !this.dest.name.length) { // This is either stdout or stderr - Bun.write(this.dest, msgNewLine); + await Bun.write(this.dest, msgNewLine); return; } const sanitised = removeAnsi(msgNewLine); - fs.appendFile(this.dest.name, sanitised, err => { - if (err) { - throw err; - } - }); + fs.appendFileSync(this.dest.name, sanitised); } /** diff --git a/src/presets/__tests__/common.test.ts b/src/presets/__tests__/common.test.ts new file mode 100644 index 0000000..74eea2f --- /dev/null +++ b/src/presets/__tests__/common.test.ts @@ -0,0 +1,80 @@ +import { + describe, + test, + expect, + beforeAll, + afterAll, + beforeEach +} from 'bun:test'; +import { unlink } from 'node:fs/promises'; +import { writeFileSync } from 'node:fs'; +import { Logestic } from '../..'; +import Elysia from 'elysia'; +import { edenTreaty } from '@elysiajs/eden'; + +const tempFilePath = 'test.log'; +const tempFile = Bun.file(tempFilePath); +const BASE_URL = 'http://127.0.0.1'; +const PORT = 3000; + +beforeAll(() => { + writeFileSync(tempFilePath, ' \n'); +}); + +afterAll(async () => { + await unlink(tempFilePath); +}); + +describe('Testing common preset', () => { + let client = edenTreaty(`${BASE_URL}:${PORT}`); + let app = new Elysia() + .use( + Logestic.preset('common', { + dest: tempFile + }) + ) + .get('/', () => { + return 'Hello, world!'; + }) + .get('/error', ({ set }) => { + set.status = 400; + }) + .listen(PORT); + + beforeEach(() => { + writeFileSync(tempFilePath, ' \n'); + }); + + test('should log request and response', async () => { + const { error } = await client.index.get(); + expect(error).toBeFalsy(); + + const log = await tempFile.text(); + expect(log).toMatch( + /\[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\] GET \/ 200/ + ); + }); + + test('multiple logs', async () => { + const { error } = await client.index.get(); + expect(error).toBeFalsy(); + + const { error: error2 } = await client.index.get(); + expect(error2).toBeFalsy(); + + const log = await tempFile.text(); + expect(log).toMatch( + /(\s*\[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\] GET \/ 200\s*){2}/ + ); + }); + + test('log error', async () => { + const { error } = await client.error.get(); + expect(error).toBeTruthy(); + + const log = await tempFile.text(); + expect(log).toMatch( + /\[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\] GET \/error 400/ + ); + }); +}); diff --git a/src/presets/__tests__/fancy.test.ts b/src/presets/__tests__/fancy.test.ts new file mode 100644 index 0000000..174fa49 --- /dev/null +++ b/src/presets/__tests__/fancy.test.ts @@ -0,0 +1,80 @@ +import { + describe, + test, + expect, + beforeAll, + afterAll, + beforeEach +} from 'bun:test'; +import { unlink } from 'node:fs/promises'; +import { writeFileSync } from 'node:fs'; +import { Logestic } from '../..'; +import Elysia from 'elysia'; +import { edenTreaty } from '@elysiajs/eden'; + +const tempFilePath = 'test.log'; +const tempFile = Bun.file(tempFilePath); +const BASE_URL = 'http://127.0.0.1'; +const PORT = 3000; + +beforeAll(() => { + writeFileSync(tempFilePath, ' \n'); +}); + +afterAll(async () => { + await unlink(tempFilePath); +}); + +describe('Testing fancy preset', () => { + let client = edenTreaty(`${BASE_URL}:${PORT}`); + let app = new Elysia() + .use( + Logestic.preset('fancy', { + dest: tempFile + }) + ) + .get('/', () => { + return 'Hello, world!'; + }) + .get('/error', ({ set }) => { + set.status = 400; + }) + .listen(PORT); + + beforeEach(() => { + writeFileSync(tempFilePath, ' \n'); + }); + + test('should log request and response', async () => { + const { error } = await client.index.get(); + expect(error).toBeFalsy(); + + const log = await tempFile.text(); + expect(log).toMatch( + /\s*HTTP\s+\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{1,2}:\d{1,2} GET \/ \d{1,4}μs\s*/ + ); + }); + + test('multiple logs', async () => { + const { error } = await client.index.get(); + expect(error).toBeFalsy(); + + const { error: error2 } = await client.index.get(); + expect(error2).toBeFalsy(); + + const log = await tempFile.text(); + expect(log).toMatch( + /(\s*HTTP\s+\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{1,2}:\d{1,2} GET \/ \d{1,4}μs\s*){2}/ + ); + }); + + test('log error', async () => { + const { error } = await client.error.get(); + expect(error).toBeTruthy(); + + const log = await tempFile.text(); + expect(log).toMatch( + /\s*HTTP\s+\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{1,2}:\d{1,2} GET \/error \d{1,4}μs\s*/ + ); + }); +}); diff --git a/test/logestic.test.ts b/test/logestic.test.ts deleted file mode 100644 index f8a0095..0000000 --- a/test/logestic.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { describe, it, expect, beforeAll, beforeEach } from 'bun:test'; -import { Elysia } from 'elysia'; -import { Logestic } from '../src'; -import { edenTreaty } from '@elysiajs/eden'; - -describe('Logestic', () => { - describe('Custom formatting', () => { - let app: Elysia; - let client: any; - let logs: string[] = []; - - beforeAll(() => { - const logestic = new Logestic(msg => logs.push(msg)) - .use('method') - .use('path') - .use('contentLength'); - - const logger = logestic.custom(({ method, path, contentLength }) => { - return `${method} ${path} ${contentLength}`; - }); - - app = new Elysia() - .use(logger) - .get('/api/:id', () => 'Hello, World!') - .listen(3000); - - client = edenTreaty('http://127.0.0.1:3000'); - }); - - beforeEach(() => (logs = [])); - - it('Custom formatting', async () => { - await client.api['hi'].get(); - - console.log('Custom logs', logs); - expect(logs.length).toBe(1); - expect(logs[0]).toBe('GET /api/hi 0'); - }); - }); - - describe('Preset formatting', () => { - let app: Elysia; - let client: any; - let logs: string[] = []; - - beforeAll(() => { - const logger = Logestic.preset('common', msg => logs.push(msg)); - - app = new Elysia() - .use(logger) - .get('/api/:id', () => 'Hello, World!') - .listen(3000); - - client = edenTreaty('http://127.0.0.1:3000'); - }); - - beforeEach(() => (logs = [])); - - it('Preset formatting', async () => { - await client.api['hi'].get(); - - expect(logs.length).toBe(1); - expect(logs[0]).toBe(' GET /api/hi 200 0'); - }); - }); -}); diff --git a/tests/logestic.test.ts b/tests/logestic.test.ts new file mode 100644 index 0000000..9667e69 --- /dev/null +++ b/tests/logestic.test.ts @@ -0,0 +1,7 @@ +import { describe, expect, test } from 'bun:test'; +import preview from '../preview/src'; +import { edenTreaty } from '@elysiajs/eden'; + +describe('Logestic', () => { + const client = edenTreaty('http://127.0.0.1:3000'); +});