import {RequestLens, ResponseLens} from "./lenses"; export type Route = { readonly request: RequestLens; readonly response: ResponseLens; } export type RequestOf = T extends Route ? TRequest : never; export type ResponseOf = T extends Route ? TResponse : never; export function route( request: RequestLens, response: ResponseLens): Route { return { request: request, response: response }; } export type HandlerFn0 = () => Promise; export type HandlerFn1 = (arg: TRequest) => Promise; export type HandlerFn = HandlerFn0 | HandlerFn1 /** * An interface of only arity 1 or zero functions returning Promise */ export type RoutableApi = { [K in keyof TApi]: HandlerFn }; export type Routes = { readonly [k: string]: Route }; export type RouteFor = TApiMethod extends HandlerFn0 ? Route : TApiMethod extends HandlerFn1 ? Route : never; /** * Use as a compile-time check that symmetrical routes are compatible with `TApi` */ export type RoutesFor> = { readonly [K in keyof TApi]: RouteFor }; /** * Uses `TRequestGet` for method parameter and `TResponseSet` for return value */ export type ApiFnFor = TRoute extends Route ? TRequest extends undefined ? HandlerFn0 : HandlerFn1 : never; /** * Uses `TRequestGet` for method parameter and `TResponseSet` for return value */ export type ApiFor = { readonly [K in keyof TRoutes]: ApiFnFor }; export function routes(a: A, b: B): A & B; export function routes(a: A, b: B, c: C): A & B & C; export function routes(a: A, b: B, c: C, d: D): A & B & C & D; export function routes(a: A, b: B, c: C, d: D, e: E): A & B & C & D & E; export function routes(a: A, b: B, c: C, d: D, e: E, f: F): A & B & C & D & E & F; export function routes(a: A, b: B, c: C, d: D, e: E, f: F, g: G): A & B & C & D & E & F & G; export function routes(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): A & B & C & D & E & F & G & H; export function routes(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I): A & B & C & D & E & F & G & H & I; export function routes(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J): A & B & C & D & E & F & G & H & I & J; export function routes(...routes: Routes[]): Routes { return routes.reduce((previousValue, currentValue) => Object.assign({}, previousValue, currentValue)); }