hono
Version:
Web framework built on Web Standards
107 lines (106 loc) • 4.73 kB
TypeScript
import type { Hono } from '../hono';
import type { HonoBase } from '../hono-base';
import type { Endpoint, ResponseFormat, Schema } from '../types';
import type { StatusCode, SuccessStatusCode } from '../utils/http-status';
import type { HasRequiredKeys } from '../utils/types';
type HonoRequest = (typeof Hono.prototype)["request"];
export type ClientRequestOptions<T = unknown> = {
fetch?: typeof fetch | HonoRequest;
webSocket?: (...args: ConstructorParameters<typeof WebSocket>) => WebSocket;
/**
* Standard `RequestInit`, caution that this take highest priority
* and could be used to overwrite things that Hono sets for you, like `body | method | headers`.
*
* If you want to add some headers, use in `headers` instead of `init`
*/
init?: RequestInit;
} & (keyof T extends never ? {
headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
} : {
headers: T | (() => T | Promise<T>);
});
export type ClientRequest<S extends Schema> = {
[M in keyof S]: S[M] extends Endpoint & {
input: infer R;
} ? R extends object ? HasRequiredKeys<R> extends true ? (args: R, options?: ClientRequestOptions) => Promise<ClientResponseOfEndpoint<S[M]>> : (args?: R, options?: ClientRequestOptions) => Promise<ClientResponseOfEndpoint<S[M]>> : never : never;
} & {
$url: (arg?: S[keyof S] extends {
input: infer R;
} ? R extends {
param: infer P;
} ? R extends {
query: infer Q;
} ? {
param: P;
query: Q;
} : {
param: P;
} : R extends {
query: infer Q;
} ? {
query: Q;
} : {} : {}) => URL;
} & (S["$get"] extends {
outputFormat: "ws";
} ? S["$get"] extends {
input: infer I;
} ? {
$ws: (args?: I) => WebSocket;
} : {} : {});
type ClientResponseOfEndpoint<T extends Endpoint = Endpoint> = T extends {
output: infer O;
outputFormat: infer F;
status: infer S;
} ? ClientResponse<O, S extends number ? S : never, F extends ResponseFormat ? F : never> : never;
export interface ClientResponse<T, U extends number = StatusCode, F extends ResponseFormat = ResponseFormat> extends globalThis.Response {
readonly body: ReadableStream | null;
readonly bodyUsed: boolean;
ok: U extends SuccessStatusCode ? true : U extends Exclude<StatusCode, SuccessStatusCode> ? false : boolean;
status: U;
statusText: string;
headers: Headers;
url: string;
redirect(url: string, status: number): Response;
clone(): Response;
json(): F extends "text" ? Promise<never> : F extends "json" ? Promise<T> : Promise<unknown>;
text(): F extends "text" ? (T extends string ? Promise<T> : Promise<never>) : Promise<string>;
blob(): Promise<Blob>;
formData(): Promise<FormData>;
arrayBuffer(): Promise<ArrayBuffer>;
}
export interface Response extends ClientResponse<unknown> {
}
export type Fetch<T> = (args?: InferRequestType<T>, opt?: ClientRequestOptions) => Promise<ClientResponseOfEndpoint<InferEndpointType<T>>>;
type InferEndpointType<T> = T extends (args: infer R, options: any | undefined) => Promise<infer U> ? U extends ClientResponse<infer O, infer S, infer F> ? {
input: NonNullable<R>;
output: O;
outputFormat: F;
status: S;
} extends Endpoint ? {
input: NonNullable<R>;
output: O;
outputFormat: F;
status: S;
} : never : never : never;
export type InferResponseType<T, U extends StatusCode = StatusCode> = InferResponseTypeFromEndpoint<InferEndpointType<T>, U>;
type InferResponseTypeFromEndpoint<T extends Endpoint, U extends StatusCode> = T extends {
output: infer O;
status: infer S;
} ? S extends U ? O : never : never;
export type InferRequestType<T> = T extends (args: infer R, options: any | undefined) => Promise<ClientResponse<unknown>> ? NonNullable<R> : never;
export type InferRequestOptionsType<T> = T extends (args: any, options: infer R) => Promise<ClientResponse<unknown>> ? NonNullable<R> : never;
type PathToChain<Path extends string, E extends Schema, Original extends string = Path> = Path extends `/${infer P}` ? PathToChain<P, E, Path> : Path extends `${infer P}/${infer R}` ? {
[K in P]: PathToChain<R, E, Original>;
} : {
[K in Path extends "" ? "index" : Path]: ClientRequest<E extends Record<string, unknown> ? E[Original] : never>;
};
export type Client<T> = T extends HonoBase<any, infer S, any> ? S extends Record<infer K, Schema> ? K extends string ? PathToChain<K, S> : never : never : never;
export type Callback = (opts: CallbackOptions) => unknown;
interface CallbackOptions {
path: string[];
args: any[];
}
export type ObjectType<T = unknown> = {
[key: string]: T;
};
export {};