diff --git a/runtime-tests/deno/utils.test.ts b/runtime-tests/deno/utils.test.ts new file mode 100644 index 0000000000..8a610429d7 --- /dev/null +++ b/runtime-tests/deno/utils.test.ts @@ -0,0 +1,13 @@ +import { assertEquals } from '@std/assert' +import { Context } from '../../src/context' +import { getColorEnabled } from '../../src/utils/color' + +Deno.test('getColorEnabled() - With colors enabled', () => { + assertEquals(getColorEnabled(), true) +}) + +Deno.test('getColorEnabled() - With Deno.noColor set', () => { + const mockContext = new Context(new Request('http://localhost/')) + + assertEquals(getColorEnabled(mockContext), true) +}) diff --git a/runtime-tests/workerd/index.test.ts b/runtime-tests/workerd/index.test.ts index 2173ce6aed..b7b916eebf 100644 --- a/runtime-tests/workerd/index.test.ts +++ b/runtime-tests/workerd/index.test.ts @@ -67,3 +67,18 @@ describe('workerd with WebSocket', () => { expect(closeHandler).toHaveBeenCalled() }) }) + +describe('worked with getColorEnabled()', async () => { + const worker = await unstable_dev('./runtime-tests/workerd/index.ts', { + experimental: { disableExperimentalWarning: true }, + }) + + it('Should return 200 response with the colorEnabled', async () => { + const res = await worker.fetch('/color') + await worker.stop() + expect(res.status).toBe(200) + expect(await res.json()).toEqual({ + colorEnabled: false, + }) + }) +}) diff --git a/runtime-tests/workerd/index.ts b/runtime-tests/workerd/index.ts index 3c94cec850..aec480c0f7 100644 --- a/runtime-tests/workerd/index.ts +++ b/runtime-tests/workerd/index.ts @@ -1,13 +1,21 @@ import { upgradeWebSocket } from '../../src/adapter/cloudflare-workers' import { env, getRuntimeKey } from '../../src/helper/adapter' import { Hono } from '../../src/hono' +import { getColorEnabled } from '../../src/utils/color' -const app = new Hono() +interface Env { + NO_COLOR: boolean + NAME: string +} + +const app = new Hono<{ + Bindings: Env +}>() app.get('/', (c) => c.text(`Hello from ${getRuntimeKey()}`)) app.get('/env', (c) => { - const { NAME } = env<{ NAME: string }>(c) + const { NAME } = env(c) return c.text(NAME) }) @@ -22,4 +30,11 @@ app.get( }) ) +app.get('/color', (c) => { + c.env.NO_COLOR = true + return c.json({ + colorEnabled: getColorEnabled(c), + }) +}) + export default app diff --git a/src/middleware/logger/index.ts b/src/middleware/logger/index.ts index abcfbec7d3..5502a53961 100644 --- a/src/middleware/logger/index.ts +++ b/src/middleware/logger/index.ts @@ -3,6 +3,7 @@ * Logger Middleware for Hono. */ +import type { Context } from '../../context' import type { MiddlewareHandler } from '../../types' import { getColorEnabled } from '../../utils/color' import { getPath } from '../../utils/url' @@ -26,8 +27,8 @@ const time = (start: number) => { return humanize([delta < 1000 ? delta + 'ms' : Math.round(delta / 1000) + 's']) } -const colorStatus = (status: number) => { - const colorEnabled = getColorEnabled() +const colorStatus = (status: number, c: Context) => { + const colorEnabled = getColorEnabled(c) if (colorEnabled) { switch ((status / 100) | 0) { case 5: // red = error @@ -53,13 +54,14 @@ function log( prefix: string, method: string, path: string, + c: Context, status: number = 0, elapsed?: string ) { const out = prefix === LogPrefix.Incoming ? `${prefix} ${method} ${path}` - : `${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}` + : `${prefix} ${method} ${path} ${colorStatus(status, c)} ${elapsed}` fn(out) } @@ -85,12 +87,12 @@ export const logger = (fn: PrintFunc = console.log): MiddlewareHandler => { const path = getPath(c.req.raw) - log(fn, LogPrefix.Incoming, method, path) + log(fn, LogPrefix.Incoming, method, path, c) const start = Date.now() await next() - log(fn, LogPrefix.Outgoing, method, path, c.res.status, time(start)) + log(fn, LogPrefix.Outgoing, method, path, c, c.res.status, time(start)) } } diff --git a/src/utils/color.test.ts b/src/utils/color.test.ts index 30d7a62133..8c3ba9d7a6 100644 --- a/src/utils/color.test.ts +++ b/src/utils/color.test.ts @@ -1,3 +1,4 @@ +import { Context } from '../context' import { getColorEnabled } from './color' describe('getColorEnabled() - With colors enabled', () => { @@ -7,6 +8,8 @@ describe('getColorEnabled() - With colors enabled', () => { }) describe('getColorEnabled() - With NO_COLOR environment variable set', () => { + const mockContext = new Context(new Request('http://localhost/')) + beforeAll(() => { vi.stubEnv('NO_COLOR', '1') }) @@ -16,6 +19,6 @@ describe('getColorEnabled() - With NO_COLOR environment variable set', () => { }) it('should return false', async () => { - expect(getColorEnabled()).toBe(false) + expect(getColorEnabled(mockContext)).toBe(false) }) }) diff --git a/src/utils/color.ts b/src/utils/color.ts index 522d3460ab..e11f942f2f 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -2,25 +2,28 @@ * @module * Color utility. */ +import type { Context } from '../context' +import { getRuntimeKey, env } from '../helper/adapter' /** * Get whether color change on terminal is enabled or disabled. * If `NO_COLOR` environment variable is set, this function returns `false`. * @see {@link https://no-color.org/} * + * @param {Context} c - the context of request + * * @returns {boolean} */ -export function getColorEnabled(): boolean { +export function getColorEnabled(c?: Context): boolean { // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { process, Deno } = globalThis as any + const { Deno, process } = globalThis as any const isNoColor = - typeof Deno?.noColor === 'boolean' - ? (Deno.noColor as boolean) - : process !== undefined - ? // eslint-disable-next-line no-unsafe-optional-chaining - 'NO_COLOR' in process?.env - : false + getRuntimeKey() === 'deno' + ? Deno?.noColor + : c + ? env(c).NO_COLOR + : process?.env && 'NO_COLOR' in process.env return !isNoColor }