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 { expectTypeOf } from 'vitest'
|
||||||
import { Hono } from '..'
|
import { Hono } from '..'
|
||||||
import { upgradeWebSocket } from '../adapter/deno/websocket'
|
import { upgradeWebSocket } from '../adapter/deno/websocket'
|
||||||
import { hc } from '.'
|
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', () => {
|
describe('WebSockets', () => {
|
||||||
const app = new Hono()
|
const app = new Hono()
|
||||||
@ -57,3 +62,65 @@ describe('with the leading slash', () => {
|
|||||||
expectTypeOf(client.foo[':id'].baz).toHaveProperty('$get')
|
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 { Hono } from '../hono'
|
||||||
import type { Endpoint, ResponseFormat, Schema } from '../types'
|
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'
|
import type { HasRequiredKeys } from '../utils/types'
|
||||||
|
|
||||||
type HonoRequest = (typeof Hono.prototype)['request']
|
type HonoRequest = (typeof Hono.prototype)['request']
|
||||||
@ -63,7 +63,15 @@ type ClientResponseOfEndpoint<T extends Endpoint = Endpoint> = T extends {
|
|||||||
outputFormat: infer F
|
outputFormat: infer F
|
||||||
status: infer S
|
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
|
: never
|
||||||
|
|
||||||
export interface ClientResponse<
|
export interface ClientResponse<
|
||||||
@ -84,11 +92,13 @@ export interface ClientResponse<
|
|||||||
url: string
|
url: string
|
||||||
redirect(url: string, status: number): Response
|
redirect(url: string, status: number): Response
|
||||||
clone(): Response
|
clone(): Response
|
||||||
json(): F extends 'text'
|
json<JSONT>(): F extends 'text'
|
||||||
? Promise<never>
|
? Promise<never>
|
||||||
: F extends 'json'
|
: F extends 'json'
|
||||||
|
? undefined extends JSONT
|
||||||
? Promise<BlankRecordToNever<T>>
|
? Promise<BlankRecordToNever<T>>
|
||||||
: Promise<unknown>
|
: Promise<JSONT>
|
||||||
|
: Promise<T & {}>
|
||||||
text(): F extends 'text' ? (T extends string ? Promise<T> : Promise<never>) : Promise<string>
|
text(): F extends 'text' ? (T extends string ? Promise<T> : Promise<never>) : Promise<string>
|
||||||
blob(): Promise<Blob>
|
blob(): Promise<Blob>
|
||||||
formData(): Promise<FormData>
|
formData(): Promise<FormData>
|
||||||
@ -119,12 +129,14 @@ export type InferResponseType<T, U extends StatusCode = StatusCode> = InferRespo
|
|||||||
U
|
U
|
||||||
>
|
>
|
||||||
|
|
||||||
|
type WithoutEmptyObject<T> = T extends {} ? (keyof T extends never ? never : T) : T
|
||||||
|
|
||||||
type InferResponseTypeFromEndpoint<T extends Endpoint, U extends StatusCode> = T extends {
|
type InferResponseTypeFromEndpoint<T extends Endpoint, U extends StatusCode> = T extends {
|
||||||
output: infer O
|
output: infer O
|
||||||
status: infer S
|
status: infer S
|
||||||
}
|
}
|
||||||
? S extends U
|
? S extends U
|
||||||
? O
|
? WithoutEmptyObject<O>
|
||||||
: never
|
: never
|
||||||
: never
|
: never
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user