mirror of
https://github.com/honojs/hono.git
synced 2024-11-21 18:18:57 +01:00
feat(client): improve handling status code types
This commit is contained in:
parent
8f1680238b
commit
3670716311
@ -1,7 +1,12 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { expectTypeOf } from 'vitest'
|
||||
import { Hono } from '..'
|
||||
import { upgradeWebSocket } from '../adapter/deno/websocket'
|
||||
import { hc } from '.'
|
||||
import { HTTPException } from '../http-exception'
|
||||
import type { Equal, Expect } from '../utils/types'
|
||||
import { setupServer } from 'msw/node'
|
||||
import { HttpResponse, http } from 'msw'
|
||||
|
||||
describe('WebSockets', () => {
|
||||
const app = new Hono()
|
||||
@ -57,3 +62,65 @@ describe('with the leading slash', () => {
|
||||
expectTypeOf(client.foo[':id'].baz).toHaveProperty('$get')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Status Code - test only Types', () => {
|
||||
const server = setupServer(
|
||||
http.get('http://localhost/foo', async () => {
|
||||
return HttpResponse.json({})
|
||||
})
|
||||
)
|
||||
|
||||
beforeAll(() => server.listen())
|
||||
afterEach(() => server.resetHandlers())
|
||||
afterAll(() => server.close())
|
||||
|
||||
const app = new Hono()
|
||||
const flag = {}
|
||||
|
||||
const routes = app.get('/foo', (c) => {
|
||||
if (flag) {
|
||||
throw new HTTPException(500, {
|
||||
message: 'Server Error!',
|
||||
})
|
||||
}
|
||||
if (flag) {
|
||||
return c.json({ message: 'invalid!' }, 401)
|
||||
}
|
||||
if (flag) {
|
||||
return c.redirect('/', 301)
|
||||
}
|
||||
return c.json({ ok: true }, 200)
|
||||
})
|
||||
|
||||
const client = hc<typeof routes>('http://localhost')
|
||||
|
||||
it('Should handle different status codes', async () => {
|
||||
const res = await client.foo.$get()
|
||||
|
||||
if (res.status === 500) {
|
||||
const data = await res.json<{ errorMessage: string }>()
|
||||
type Expected = { errorMessage: string }
|
||||
type verify = Expect<Equal<Expected, typeof data>>
|
||||
}
|
||||
|
||||
if (res.status === 401) {
|
||||
const data = await res.json()
|
||||
type Expected = { message: string }
|
||||
type verify = Expect<Equal<Expected, typeof data>>
|
||||
}
|
||||
|
||||
if (res.status === 200) {
|
||||
const data = await res.json()
|
||||
type Expected = { ok: boolean }
|
||||
type verify = Expect<Equal<Expected, typeof data>>
|
||||
}
|
||||
})
|
||||
|
||||
it('Should infer union types', async () => {
|
||||
const res = await client.foo.$get()
|
||||
|
||||
const data = await res.json()
|
||||
type Expected = { message: string } | { ok: boolean }
|
||||
type verify = Expect<Equal<Expected, typeof data>>
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { Hono } from '../hono'
|
||||
import type { Endpoint, ResponseFormat, Schema } from '../types'
|
||||
import type { StatusCode, SuccessStatusCode } from '../utils/http-status'
|
||||
import type { RedirectStatusCode, StatusCode, SuccessStatusCode } from '../utils/http-status'
|
||||
import type { HasRequiredKeys } from '../utils/types'
|
||||
|
||||
type HonoRequest = (typeof Hono.prototype)['request']
|
||||
@ -63,7 +63,15 @@ type ClientResponseOfEndpoint<T extends Endpoint = Endpoint> = T extends {
|
||||
outputFormat: infer F
|
||||
status: infer S
|
||||
}
|
||||
? ClientResponse<O, S extends number ? S : never, F extends ResponseFormat ? F : never>
|
||||
? F extends 'redirect'
|
||||
? ClientResponse<O, S extends RedirectStatusCode ? S : never, 'redirect'>
|
||||
:
|
||||
| ClientResponse<O, S extends StatusCode ? S : never, F extends ResponseFormat ? F : never>
|
||||
| ClientResponse<
|
||||
{},
|
||||
S extends StatusCode ? Exclude<Exclude<StatusCode, RedirectStatusCode>, S> : never,
|
||||
F extends ResponseFormat ? F : never
|
||||
>
|
||||
: never
|
||||
|
||||
export interface ClientResponse<
|
||||
@ -84,11 +92,13 @@ export interface ClientResponse<
|
||||
url: string
|
||||
redirect(url: string, status: number): Response
|
||||
clone(): Response
|
||||
json(): F extends 'text'
|
||||
json<JSONT>(): F extends 'text'
|
||||
? Promise<never>
|
||||
: F extends 'json'
|
||||
? undefined extends JSONT
|
||||
? Promise<BlankRecordToNever<T>>
|
||||
: Promise<unknown>
|
||||
: Promise<JSONT>
|
||||
: Promise<T & {}>
|
||||
text(): F extends 'text' ? (T extends string ? Promise<T> : Promise<never>) : Promise<string>
|
||||
blob(): Promise<Blob>
|
||||
formData(): Promise<FormData>
|
||||
@ -119,12 +129,14 @@ export type InferResponseType<T, U extends StatusCode = StatusCode> = InferRespo
|
||||
U
|
||||
>
|
||||
|
||||
type WithoutEmptyObject<T> = T extends {} ? (keyof T extends never ? never : T) : T
|
||||
|
||||
type InferResponseTypeFromEndpoint<T extends Endpoint, U extends StatusCode> = T extends {
|
||||
output: infer O
|
||||
status: infer S
|
||||
}
|
||||
? S extends U
|
||||
? O
|
||||
? WithoutEmptyObject<O>
|
||||
: never
|
||||
: never
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user