From 41fae92fc014a587e869fb2deb94e249be956c02 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 02:05:42 +0000 Subject: [PATCH 01/18] feat: introduce `responseValidator` --- src/context.ts | 8 +++ src/types.ts | 22 +++++- src/validator/index.ts | 3 + src/validator/response-validator.test.ts | 23 +++++++ src/validator/response-validator.ts | 85 ++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 src/validator/response-validator.test.ts create mode 100644 src/validator/response-validator.ts diff --git a/src/context.ts b/src/context.ts index a5f6b4c6a..d502ee76f 100644 --- a/src/context.ts +++ b/src/context.ts @@ -862,4 +862,12 @@ export class Context< this.#notFoundHandler ??= () => new Response() return this.#notFoundHandler(this) } + + validateData: unknown + + validate = (body: T): T => { + this.validateData = body + + return body + } } diff --git a/src/types.ts b/src/types.ts index 42b0d3aa2..7b23428c4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,7 +5,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { Context } from './context' +import type { Context, Data } from './context' import type { HonoBase } from './hono-base' import type { CustomHeader, RequestHeader } from './utils/headers' import type { StatusCode } from './utils/http-status' @@ -1933,6 +1933,26 @@ export type ValidationTargets } +//////////////////////////////////////////////// +////// ///// +////// ResponseValidationTargets ///// +////// ///// +//////////////////////////////////////////////// + +export type ResponseValidationTargets = { + body: ReadableStream + text: string + json: any + html: string + header: Record + cookie: Record + status: { + ok: boolean + status: StatusCode + statusText: string + } +} + //////////////////////////////////////// ////// ////// ////// Path parameters ////// diff --git a/src/validator/index.ts b/src/validator/index.ts index 30e10c678..0197bdaf3 100644 --- a/src/validator/index.ts +++ b/src/validator/index.ts @@ -5,3 +5,6 @@ export { validator } from './validator' export type { ValidationFunction } from './validator' + +export { responseValidator } from './response-validator' +export type { ResponseValidationFunction } from './response-validator' diff --git a/src/validator/response-validator.test.ts b/src/validator/response-validator.test.ts new file mode 100644 index 000000000..5abd49e17 --- /dev/null +++ b/src/validator/response-validator.test.ts @@ -0,0 +1,23 @@ +import { responseValidator } from '.' +import { Hono } from '../preset/quick' + +const app = new Hono() + +app + .use( + '*', + responseValidator('text', (value, c) => { + console.log(value) + if (!/\d/.test(value)) { + return c.text('Invalid!', 400) + } + }) + ) + .get('/', (c) => { + return c.text(c.validate('hello world at ' + Date.now())) + }) + .get('/invalid', (c) => { + return c.text(c.validate('hello world at ' + NaN)) + }) + +export default app diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts new file mode 100644 index 000000000..a67524b92 --- /dev/null +++ b/src/validator/response-validator.ts @@ -0,0 +1,85 @@ +import type { Context } from '../context' +import type { Env, MiddlewareHandler, TypedResponse, ResponseValidationTargets } from '../types' + +type ResponseValidationTargetKeys = keyof ResponseValidationTargets + +export type ResponseValidationFunction< + U extends ResponseValidationTargetKeys, + P extends string, + E extends Env = {} +> = ( + value: ResponseValidationTargets[U], + c: Context +) => undefined | Response | Promise + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type ExcludeResponseType = T extends Response & TypedResponse ? never : T + +const textRegex = /^text\/([a-z-\.]+\+)?(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ +const jsonRegex = /^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ +const htmlRegex = /^text\/html(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ + +export const responseValidator = < + U extends ResponseValidationTargetKeys, + P extends string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + E extends Env = any +>( + target: U, + validationFunc: ResponseValidationFunction +): MiddlewareHandler => { + return async (c, next) => { + await next() + + let value: unknown + + const contentType = c.res.headers.get('Content-Type') + + switch (target) { + case 'body': + value = c.res.body + case 'text': + if (!contentType || !textRegex.test(contentType)) { + break + } + + value = c.validateData + break + case 'json': + if (!contentType || !jsonRegex.test(contentType) || typeof c.validateData !== 'object') { + break + } + value = c.validateData + break + case 'html': + if (!contentType || !htmlRegex.test(contentType) || typeof c.validateData !== 'string') { + break + } + value = c.validateData + break + case 'header': + value = Object.fromEntries(c.res.headers.entries()) + break + case 'cookie': + value = c.res.headers.getSetCookie().reduce((acc, cookie) => { + const [name, ...rest] = cookie.split('=') + acc[name] = rest.join('=').split(';')[0] + return acc + }, {} as Record) + break + case 'status': + value = { + ok: c.res.ok, + status: c.res.status, + statusText: c.res.statusText, + } + break + } + + const res = await validationFunc(value as never, c as never) + + if (res instanceof Response) { + c.res = res + } + } +} From ea715b4fcf0b2ae80d4903bb780417b6a9cb6bc4 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 02:08:23 +0000 Subject: [PATCH 02/18] chore: lint --- src/validator/response-validator.test.ts | 2 +- src/validator/response-validator.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/validator/response-validator.test.ts b/src/validator/response-validator.test.ts index 5abd49e17..26167c2aa 100644 --- a/src/validator/response-validator.test.ts +++ b/src/validator/response-validator.test.ts @@ -1,5 +1,5 @@ -import { responseValidator } from '.' import { Hono } from '../preset/quick' +import { responseValidator } from '.' const app = new Hono() diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index a67524b92..ec959bde0 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -12,9 +12,6 @@ export type ResponseValidationFunction< c: Context ) => undefined | Response | Promise -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type ExcludeResponseType = T extends Response & TypedResponse ? never : T - const textRegex = /^text\/([a-z-\.]+\+)?(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ const jsonRegex = /^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ const htmlRegex = /^text\/html(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ @@ -38,6 +35,7 @@ export const responseValidator = < switch (target) { case 'body': value = c.res.body + break case 'text': if (!contentType || !textRegex.test(contentType)) { break From 9f79eb63d5aed8be75fc3ac1ce7b6f3e193c53db Mon Sep 17 00:00:00 2001 From: EdamAmex <121654029+EdamAme-x@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:10:38 +0900 Subject: [PATCH 03/18] chore: limt --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 7b23428c4..8cf0fc89b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,7 +5,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { Context, Data } from './context' +import type { Context } from './context' import type { HonoBase } from './hono-base' import type { CustomHeader, RequestHeader } from './utils/headers' import type { StatusCode } from './utils/http-status' From 51238d5baee488380f95e3d6b78ad37ea7339d79 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 02:21:15 +0000 Subject: [PATCH 04/18] chore: change name of arg --- src/context.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/context.ts b/src/context.ts index d502ee76f..040a436cb 100644 --- a/src/context.ts +++ b/src/context.ts @@ -865,9 +865,9 @@ export class Context< validateData: unknown - validate = (body: T): T => { - this.validateData = body + validate = (data: T): T => { + this.validateData = data - return body + return data } } From adea14db50fbd3bd253b90566f5e8a639dede9fc Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 02:22:32 +0000 Subject: [PATCH 05/18] chore: change file name --- .../{response-validator.test.ts => response-validator.sandbox.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/validator/{response-validator.test.ts => response-validator.sandbox.ts} (100%) diff --git a/src/validator/response-validator.test.ts b/src/validator/response-validator.sandbox.ts similarity index 100% rename from src/validator/response-validator.test.ts rename to src/validator/response-validator.sandbox.ts From c653e87c14c8dcb212920162bed3fc28789beb2e Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 02:26:29 +0000 Subject: [PATCH 06/18] fix: skip when not finalized --- src/validator/response-validator.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index ec959bde0..045f6552f 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -28,6 +28,10 @@ export const responseValidator = < return async (c, next) => { await next() + if (!c.finalized) { + return + } + let value: unknown const contentType = c.res.headers.get('Content-Type') From 4d7a8e46d30a337e225806b02d1322dcb0fe5e9b Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 02:28:26 +0000 Subject: [PATCH 07/18] chore --- src/validator/response-validator.sandbox.ts | 6 +++++- src/validator/response-validator.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/validator/response-validator.sandbox.ts b/src/validator/response-validator.sandbox.ts index 26167c2aa..3d36e0a70 100644 --- a/src/validator/response-validator.sandbox.ts +++ b/src/validator/response-validator.sandbox.ts @@ -1,7 +1,11 @@ import { Hono } from '../preset/quick' import { responseValidator } from '.' -const app = new Hono() +const app = new Hono<{ + Bindings: { + foo: string + } +}>() app .use( diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index 045f6552f..21ced0338 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -6,7 +6,7 @@ type ResponseValidationTargetKeys = keyof ResponseValidationTargets export type ResponseValidationFunction< U extends ResponseValidationTargetKeys, P extends string, - E extends Env = {} + E extends Env > = ( value: ResponseValidationTargets[U], c: Context From 777e0ba1da2f54190eb45f81b8557fa70078bede Mon Sep 17 00:00:00 2001 From: EdamAmex <121654029+EdamAme-x@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:32:26 +0900 Subject: [PATCH 08/18] Update context.ts --- src/context.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/context.ts b/src/context.ts index 040a436cb..e27b0456f 100644 --- a/src/context.ts +++ b/src/context.ts @@ -867,7 +867,6 @@ export class Context< validate = (data: T): T => { this.validateData = data - return data } } From 486645c7af6ac0b04263215c2e86767ec30ed4a7 Mon Sep 17 00:00:00 2001 From: EdamAmex <121654029+EdamAme-x@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:35:16 +0900 Subject: [PATCH 09/18] Update response-validator.ts --- src/validator/response-validator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index 21ced0338..ee88598ba 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -1,5 +1,5 @@ import type { Context } from '../context' -import type { Env, MiddlewareHandler, TypedResponse, ResponseValidationTargets } from '../types' +import type { Env, MiddlewareHandler, ResponseValidationTargets } from '../types' type ResponseValidationTargetKeys = keyof ResponseValidationTargets From d784a7b54ad5b82fc64d5f1bf7165a30dcd95615 Mon Sep 17 00:00:00 2001 From: EdamAmex <121654029+EdamAme-x@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:37:14 +0900 Subject: [PATCH 10/18] Update response-validator.ts --- src/validator/response-validator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index ee88598ba..d5e3beed0 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -41,7 +41,7 @@ export const responseValidator = < value = c.res.body break case 'text': - if (!contentType || !textRegex.test(contentType)) { + if (!contentType || !textRegex.test(contentType) || typeof c.validateData !== 'string') { break } From 4db06f1a71b4815e121ee3ed688fab3420d0f6fb Mon Sep 17 00:00:00 2001 From: EdamAmex <121654029+EdamAme-x@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:43:58 +0900 Subject: [PATCH 11/18] fix: generics --- src/validator/response-validator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index d5e3beed0..a4d9d54fa 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -5,8 +5,8 @@ type ResponseValidationTargetKeys = keyof ResponseValidationTargets export type ResponseValidationFunction< U extends ResponseValidationTargetKeys, + E extends Env = {}, P extends string, - E extends Env > = ( value: ResponseValidationTargets[U], c: Context From 4695a7374382825ef3885d7b07079f71739256a5 Mon Sep 17 00:00:00 2001 From: EdamAmex <121654029+EdamAme-x@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:45:55 +0900 Subject: [PATCH 12/18] Update response-validator.ts --- src/validator/response-validator.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index a4d9d54fa..c38701610 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -19,11 +19,12 @@ const htmlRegex = /^text\/html(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ export const responseValidator = < U extends ResponseValidationTargetKeys, P extends string, + P2 extends string = P, // eslint-disable-next-line @typescript-eslint/no-explicit-any E extends Env = any >( target: U, - validationFunc: ResponseValidationFunction + validationFunc: ResponseValidationFunction ): MiddlewareHandler => { return async (c, next) => { await next() From 1fe23bea6b7e0e8abe8ffc082ae51e77728cd61d Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 06:15:30 +0000 Subject: [PATCH 13/18] chore: format --- src/validator/response-validator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index c38701610..34e4c0f2a 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -6,7 +6,7 @@ type ResponseValidationTargetKeys = keyof ResponseValidationTargets export type ResponseValidationFunction< U extends ResponseValidationTargetKeys, E extends Env = {}, - P extends string, + P extends string = string > = ( value: ResponseValidationTargets[U], c: Context @@ -24,7 +24,7 @@ export const responseValidator = < E extends Env = any >( target: U, - validationFunc: ResponseValidationFunction + validationFunc: ResponseValidationFunction ): MiddlewareHandler => { return async (c, next) => { await next() From 03c789d533001cf83e50905ac1f121f95738a681 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 06:24:08 +0000 Subject: [PATCH 14/18] chore fix --- src/validator/response-validator.sandbox.ts | 7 +++++-- src/validator/response-validator.ts | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/validator/response-validator.sandbox.ts b/src/validator/response-validator.sandbox.ts index 3d36e0a70..88e3e5c96 100644 --- a/src/validator/response-validator.sandbox.ts +++ b/src/validator/response-validator.sandbox.ts @@ -1,5 +1,5 @@ import { Hono } from '../preset/quick' -import { responseValidator } from '.' +import { validator, responseValidator } from '.' const app = new Hono<{ Bindings: { @@ -8,8 +8,11 @@ const app = new Hono<{ }>() app - .use( + .get( '*', + validator('query', (value, c) => { + console.log(value, c) + }), responseValidator('text', (value, c) => { console.log(value) if (!/\d/.test(value)) { diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index 34e4c0f2a..4d2e7ca76 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -17,8 +17,8 @@ const jsonRegex = /^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+)) const htmlRegex = /^text\/html(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/ export const responseValidator = < - U extends ResponseValidationTargetKeys, P extends string, + U extends ResponseValidationTargetKeys, P2 extends string = P, // eslint-disable-next-line @typescript-eslint/no-explicit-any E extends Env = any From 6e67faca6c024afdf3fd8b21ee6fb9ed2682b3d5 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 06:29:55 +0000 Subject: [PATCH 15/18] fix --- src/validator/response-validator.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index 4d2e7ca76..4ae1b3ca2 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -45,7 +45,6 @@ export const responseValidator = < if (!contentType || !textRegex.test(contentType) || typeof c.validateData !== 'string') { break } - value = c.validateData break case 'json': @@ -64,10 +63,10 @@ export const responseValidator = < value = Object.fromEntries(c.res.headers.entries()) break case 'cookie': - value = c.res.headers.getSetCookie().reduce((acc, cookie) => { + value = c.res.headers.getSetCookie().reduce((record, cookie) => { const [name, ...rest] = cookie.split('=') - acc[name] = rest.join('=').split(';')[0] - return acc + record[name] = rest.join('=').split(';')[0] + return record }, {} as Record) break case 'status': @@ -79,7 +78,7 @@ export const responseValidator = < break } - const res = await validationFunc(value as never, c as never) + const res = await validationFunc(value, c) if (res instanceof Response) { c.res = res From 7e9a436d0c07737cb34c91d51255cc7fa986335f Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 06:44:34 +0000 Subject: [PATCH 16/18] wip --- src/types.ts | 2 +- src/validator/response-validator.ts | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/types.ts b/src/types.ts index 8cf0fc89b..fc3f10981 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1940,7 +1940,7 @@ export type ValidationTargets + body: ReadableStream | null text: string json: any html: string diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index 4ae1b3ca2..1c16fcb97 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -1,5 +1,6 @@ import type { Context } from '../context' import type { Env, MiddlewareHandler, ResponseValidationTargets } from '../types' +import { UnofficialStatusCode } from '../utils/http-status' type ResponseValidationTargetKeys = keyof ResponseValidationTargets @@ -39,42 +40,48 @@ export const responseValidator = < switch (target) { case 'body': - value = c.res.body + if (!c.res.body) { + break + } + value = c.res.body satisfies ResponseValidationTargets['body'] break case 'text': if (!contentType || !textRegex.test(contentType) || typeof c.validateData !== 'string') { break } - value = c.validateData + value = c.validateData satisfies ResponseValidationTargets['text'] break case 'json': if (!contentType || !jsonRegex.test(contentType) || typeof c.validateData !== 'object') { break } - value = c.validateData + value = c.validateData satisfies ResponseValidationTargets['json'] break case 'html': if (!contentType || !htmlRegex.test(contentType) || typeof c.validateData !== 'string') { break } - value = c.validateData + value = c.validateData satisfies ResponseValidationTargets['html'] break case 'header': - value = Object.fromEntries(c.res.headers.entries()) + value = Object.fromEntries(c.res.headers.entries()) as Record< + string, + string + > satisfies ResponseValidationTargets['header'] break case 'cookie': value = c.res.headers.getSetCookie().reduce((record, cookie) => { const [name, ...rest] = cookie.split('=') record[name] = rest.join('=').split(';')[0] return record - }, {} as Record) + }, {} as Record) satisfies ResponseValidationTargets['cookie'] break case 'status': value = { ok: c.res.ok, - status: c.res.status, + status: c.res.status as UnofficialStatusCode, statusText: c.res.statusText, - } + } satisfies ResponseValidationTargets['status'] break } From 4f40e58230d9962ad18c198066c5c1a030e9742d Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 06:44:59 +0000 Subject: [PATCH 17/18] todo --- src/validator/response-validator.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index 1c16fcb97..3bf12731f 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -38,6 +38,7 @@ export const responseValidator = < const contentType = c.res.headers.get('Content-Type') + // ToDo: remove satisfies after switch (target) { case 'body': if (!c.res.body) { From 6b87b95169b745560165b900881d259074f31474 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Tue, 21 Jan 2025 06:47:46 +0000 Subject: [PATCH 18/18] revert --- src/validator/response-validator.ts | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/validator/response-validator.ts b/src/validator/response-validator.ts index 3bf12731f..17156085d 100644 --- a/src/validator/response-validator.ts +++ b/src/validator/response-validator.ts @@ -1,6 +1,5 @@ import type { Context } from '../context' import type { Env, MiddlewareHandler, ResponseValidationTargets } from '../types' -import { UnofficialStatusCode } from '../utils/http-status' type ResponseValidationTargetKeys = keyof ResponseValidationTargets @@ -38,51 +37,47 @@ export const responseValidator = < const contentType = c.res.headers.get('Content-Type') - // ToDo: remove satisfies after switch (target) { case 'body': if (!c.res.body) { break } - value = c.res.body satisfies ResponseValidationTargets['body'] + value = c.res.body break case 'text': if (!contentType || !textRegex.test(contentType) || typeof c.validateData !== 'string') { break } - value = c.validateData satisfies ResponseValidationTargets['text'] + value = c.validateData break case 'json': if (!contentType || !jsonRegex.test(contentType) || typeof c.validateData !== 'object') { break } - value = c.validateData satisfies ResponseValidationTargets['json'] + value = c.validateData break case 'html': if (!contentType || !htmlRegex.test(contentType) || typeof c.validateData !== 'string') { break } - value = c.validateData satisfies ResponseValidationTargets['html'] + value = c.validateData break case 'header': - value = Object.fromEntries(c.res.headers.entries()) as Record< - string, - string - > satisfies ResponseValidationTargets['header'] + value = Object.fromEntries(c.res.headers.entries()) as Record break case 'cookie': value = c.res.headers.getSetCookie().reduce((record, cookie) => { const [name, ...rest] = cookie.split('=') record[name] = rest.join('=').split(';')[0] return record - }, {} as Record) satisfies ResponseValidationTargets['cookie'] + }, {} as Record) break case 'status': value = { ok: c.res.ok, - status: c.res.status as UnofficialStatusCode, + status: c.res.status, statusText: c.res.statusText, - } satisfies ResponseValidationTargets['status'] + } break }