UNPKG

@data-client/rest

Version:

Quickly define typed REST resources and endpoints

425 lines 25.1 kB
import type { Denormalize, EndpointExtraOptions, EndpointInstanceInterface, Schema, FetchFunction, ResolveType } from '@data-client/endpoint'; import type { ExtractCollection } from './extractCollection.js'; import { OptionsToBodyArgument, OptionsToFunction } from './OptionsToFunction.js'; import { PathArgs, SoftPathArgs } from './pathTypes.js'; import { EndpointUpdateFunction } from './RestEndpointTypeHelp.js'; export type ContentType = 'json' | 'blob' | 'text' | 'arrayBuffer' | 'stream'; interface ContentTypeMap { blob: Blob; text: string; arrayBuffer: ArrayBuffer; stream: ReadableStream<Uint8Array>; json: any; } type ContentReturnType<C extends ContentType> = ContentTypeMap[C]; type ContentSchemaGuard<O> = O extends { content: 'blob' | 'text' | 'arrayBuffer' | 'stream'; } ? { schema?: undefined; } : {}; export interface RestInstanceBase<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, M extends boolean | undefined = boolean | undefined, O extends { path: string; body?: any; searchParams?: any; method?: string; } = { path: string; }> extends EndpointInstanceInterface<F, S, M> { /** @see https://dataclient.io/rest/api/RestEndpoint#body */ readonly body?: 'body' extends keyof O ? O['body'] : any; /** @see https://dataclient.io/rest/api/RestEndpoint#searchParams */ readonly searchParams?: 'searchParams' extends keyof O ? O['searchParams'] : unknown; /** Pattern to construct url based on Url Parameters * @see https://dataclient.io/rest/api/RestEndpoint#path */ readonly path: O['path']; /** Prepended to all urls * @see https://dataclient.io/rest/api/RestEndpoint#urlPrefix */ readonly urlPrefix: string; readonly requestInit: RequestInit; /** HTTP request method * @see https://dataclient.io/rest/api/RestEndpoint#method */ readonly method: (O & { method: string; })['method']; readonly signal: AbortSignal | undefined; /** @see https://dataclient.io/rest/api/RestEndpoint#paginationField */ readonly paginationField?: string; /** @see https://dataclient.io/rest/api/RestEndpoint#content */ readonly content?: ContentType; /** Builds the URL to fetch * @see https://dataclient.io/rest/api/RestEndpoint#url */ url(...args: Parameters<F>): string; /** Encode the searchParams component of the url * @see https://dataclient.io/rest/api/RestEndpoint#searchToString */ searchToString(searchParams: Record<string, any>): string; /** Prepares RequestInit used in fetch. This is sent to fetchResponse() * @see https://dataclient.io/rest/api/RestEndpoint#getRequestInit */ getRequestInit(this: any, body?: RequestInit['body'] | Record<string, unknown>): Promise<RequestInit> | RequestInit; /** Called by getRequestInit to determine HTTP Headers * @see https://dataclient.io/rest/api/RestEndpoint#getHeaders */ getHeaders(headers: HeadersInit): Promise<HeadersInit> | HeadersInit; /** Performs the fetch call * @see https://dataclient.io/rest/api/RestEndpoint#fetchResponse */ fetchResponse(input: RequestInfo, init: RequestInit): Promise<Response>; /** Takes the Response and parses via .text() or .json() * @see https://dataclient.io/rest/api/RestEndpoint#parseResponse */ parseResponse(response: Response): Promise<any>; /** Perform any transforms with the parsed result. * @see https://dataclient.io/rest/api/RestEndpoint#process */ process(value: any, ...args: Parameters<F>): ResolveType<F>; /** Returns true if the provided (fetch) key matches this endpoint. * @see https://dataclient.io/rest/api/RestEndpoint#testKey */ testKey(key: string): boolean; /** Creates a child endpoint that inherits from this while overriding provided `options`. * @see https://dataclient.io/rest/api/RestEndpoint#extend */ extend<E extends RestInstanceBase, ExtendOptions extends PartialRestGenerics | {}>(this: E, options: Readonly<RestEndpointExtendOptions<ExtendOptions, E, F> & ExtendOptions> & ContentSchemaGuard<ExtendOptions>): RestExtendedEndpoint<ExtendOptions, E>; } export interface RestInstance<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, M extends boolean | undefined = boolean | undefined, O extends { path: string; body?: any; searchParams?: any; method?: string; paginationField?: string; } = { path: string; }> extends RestInstanceBase<F, S, M, O> { /** Creates an Endpoint to append the next page extending a list for pagination * @see https://dataclient.io/rest/api/RestEndpoint#paginated */ paginated<E extends RestInstanceBase<FetchFunction, any, undefined>, A extends any[]>(this: E, removeCursor: (...args: A) => readonly [...Parameters<E>]): PaginationEndpoint<E, A>; paginated<E extends RestInstanceBase<FetchFunction, any, undefined>, C extends string>(this: E, cursorField: C): PaginationFieldEndpoint<E, C>; /** Concatinate the next page of results (GET) * @see https://dataclient.io/rest/api/RestEndpoint#getPage */ getPage: 'paginationField' extends keyof O ? O['paginationField'] extends string ? PaginationFieldEndpoint<F & { schema: S; sideEffect: M; } & O, O['paginationField']> : undefined : undefined; /** Create a new item (POST) and `push` to the end * @see https://dataclient.io/rest/api/RestEndpoint#push */ push: AddEndpoint<F, ExtractCollection<S>['push'], Omit<O, 'body' | 'method'> & { body: OptionsToAdderBodyArgument<O, ExtractCollection<S>['push']> | OptionsToAdderBodyArgument<O, ExtractCollection<S>['push']>[] | FormData; }>; /** Create a new item (POST) and `unshift` to the beginning * @see https://dataclient.io/rest/api/RestEndpoint#unshift */ unshift: AddEndpoint<F, ExtractCollection<S>['unshift'], Omit<O, 'body' | 'method'> & { body: OptionsToAdderBodyArgument<O, ExtractCollection<S>['unshift']> | OptionsToAdderBodyArgument<O, ExtractCollection<S>['unshift']>[] | FormData; }>; /** Create new item(s) (POST) and `Object.assign` merge * @see https://dataclient.io/rest/api/RestEndpoint#assign */ assign: AddEndpoint<F, ExtractCollection<S>, Omit<O, 'body' | 'method'> & { body: Record<string, OptionsToAdderBodyArgument<O, ExtractCollection<S>['assign']>> | FormData; }>; /** Remove item(s) (PATCH) from collection * @see https://dataclient.io/rest/api/RestEndpoint#remove */ remove: RemoveEndpoint<F, ExtractCollection<S>['remove'], Omit<O, 'body' | 'method'> & { body: Partial<OptionsToAdderBodyArgument<O, ExtractCollection<S>['remove']>> | Partial<OptionsToAdderBodyArgument<O, ExtractCollection<S>['remove']>>[] | FormData; }>; /** Move item between collections (PATCH) - removes from old, adds to new * @see https://dataclient.io/rest/api/RestEndpoint#move */ move: MoveEndpoint<F, ExtractCollection<S>['move'], { path: 'movePath' extends keyof O ? O['movePath'] & string : O['path']; body: Partial<OptionsToAdderBodyArgument<O, ExtractCollection<S>['move']>> | FormData; }>; } export type RestEndpointExtendOptions<O extends PartialRestGenerics, E extends { body?: any; path?: string; schema?: Schema; method?: string; }, F extends FetchFunction> = RestEndpointOptions<OptionsToFunction<O, E, F>, 'schema' extends keyof O ? Extract<O['schema'], Schema | undefined> : E['schema']> & Partial<Omit<E, KeyofRestEndpoint | keyof PartialRestGenerics | keyof RestEndpointOptions>>; type OptionsToRestEndpoint<O extends PartialRestGenerics, E extends RestInstanceBase & { body?: any; paginationField?: string; }, F extends FetchFunction> = 'path' extends keyof O ? RestType<'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<O['path'], undefined>> : PathArgs<Exclude<O['path'], undefined>>, OptionsToBodyArgument<'body' extends keyof O ? O : E, 'method' extends keyof O ? O['method'] : E['method']>, 'schema' extends keyof O ? O['schema'] : E['schema'], 'sideEffect' extends keyof O ? Extract<O['sideEffect'], boolean | undefined> : 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], O['process'] extends {} ? ReturnType<O['process']> : 'content' extends keyof O ? ContentReturnType<O['content'] & ContentType> : ResolveType<F>, { path: Exclude<O['path'], undefined>; body: 'body' extends keyof O ? O['body'] : E['body']; searchParams: 'searchParams' extends keyof O ? O['searchParams'] : E['searchParams']; method: 'method' extends keyof O ? O['method'] : E['method']; paginationField: 'paginationField' extends keyof O ? O['paginationField'] : E['paginationField']; }> : 'body' extends keyof O ? RestType<'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<E['path'], undefined>> : PathArgs<Exclude<E['path'], undefined>>, OptionsToBodyArgument<O, 'method' extends keyof O ? O['method'] : E['method']>, 'schema' extends keyof O ? O['schema'] : E['schema'], 'sideEffect' extends keyof O ? Extract<O['sideEffect'], boolean | undefined> : 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], O['process'] extends {} ? ReturnType<O['process']> : 'content' extends keyof O ? ContentReturnType<O['content'] & ContentType> : ResolveType<F>, { path: E['path']; body: O['body']; searchParams: 'searchParams' extends keyof O ? O['searchParams'] : E['searchParams']; method: 'method' extends keyof O ? O['method'] : E['method']; paginationField: 'paginationField' extends keyof O ? O['paginationField'] : Extract<E['paginationField'], string>; }> : 'searchParams' extends keyof O ? RestType<[ O['searchParams'] ] extends [undefined] ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<E['path'], undefined>>, OptionsToBodyArgument<E, 'method' extends keyof O ? O['method'] : E['method']>, 'schema' extends keyof O ? O['schema'] : E['schema'], 'sideEffect' extends keyof O ? Extract<O['sideEffect'], boolean | undefined> : 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], O['process'] extends {} ? ReturnType<O['process']> : 'content' extends keyof O ? ContentReturnType<O['content'] & ContentType> : ResolveType<F>, { path: E['path']; body: E['body']; searchParams: O['searchParams']; method: 'method' extends keyof O ? O['method'] : E['method']; paginationField: 'paginationField' extends keyof O ? O['paginationField'] : Extract<E['paginationField'], string>; }> : RestInstance<F, 'schema' extends keyof O ? O['schema'] : E['schema'], 'sideEffect' extends keyof O ? Extract<O['sideEffect'], boolean | undefined> : 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], { path: 'path' extends keyof O ? Exclude<O['path'], undefined> : E['path']; body: 'body' extends keyof O ? O['body'] : E['body']; searchParams: 'searchParams' extends keyof O ? O['searchParams'] : E['searchParams']; method: 'method' extends keyof O ? O['method'] : E['method']; paginationField: 'paginationField' extends keyof O ? O['paginationField'] : E['paginationField']; }>; export type RestExtendedEndpoint<O extends PartialRestGenerics, E extends RestInstanceBase & { getPage?: unknown; }> = OptionsToRestEndpoint<O, E & (E extends { getPage: { paginationField: string; }; } ? { paginationField: E['getPage']['paginationField']; } : unknown), RestInstance<(...args: Parameters<E>) => O['process'] extends {} ? Promise<ReturnType<O['process']>> : 'content' extends keyof O ? Promise<ContentReturnType<O['content'] & ContentType>> : ReturnType<E>, 'schema' extends keyof O ? O['schema'] : E['schema'], 'sideEffect' extends keyof O ? Extract<O['sideEffect'], boolean | undefined> : 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect']>> & Omit<O, KeyofRestEndpoint> & Omit<E, KeyofRestEndpoint | keyof O>; export interface PartialRestGenerics { /** @see https://dataclient.io/rest/api/RestEndpoint#path */ readonly path?: string; /** @see https://dataclient.io/rest/api/RestEndpoint#schema */ readonly schema?: Schema | undefined; /** @see https://dataclient.io/rest/api/RestEndpoint#method */ readonly method?: string; /** Only used for types */ /** @see https://dataclient.io/rest/api/RestEndpoint#body */ body?: any; /** Only used for types */ /** @see https://dataclient.io/rest/api/RestEndpoint#searchParams */ searchParams?: any; /** @see https://dataclient.io/rest/api/RestEndpoint#paginationfield */ readonly paginationField?: string; /** @see https://dataclient.io/rest/api/RestEndpoint#process */ process?(value: any, ...args: any): any; /** @see https://dataclient.io/rest/api/RestEndpoint#content */ readonly content?: ContentType; } /** Generic types when constructing a RestEndpoint * * @see https://dataclient.io/rest/api/RestEndpoint#inheritance */ export interface RestGenerics extends PartialRestGenerics { readonly path: string; } export type PaginationEndpoint<E extends FetchFunction & RestGenerics & { sideEffect?: boolean | undefined; }, A extends any[]> = RestInstanceBase<ParamFetchNoBody<A[0], ResolveType<E>>, E['schema'], E['sideEffect'], Pick<E, 'path' | 'searchParams' | 'body'> & { searchParams: Omit<A[0], keyof PathArgs<E['path']>>; }>; /** Merge pagination field C into body, making it required */ type PaginationIntoBody<Body, C extends string> = Body & { [K in C]: string | number | boolean; }; /** Paginated searchParams type */ type PaginatedSearchParams<E extends { searchParams?: any; path?: string; }, C extends string> = { [K in C]: string | number | boolean; } & E['searchParams'] & PathArgs<Exclude<E['path'], undefined>>; /** searchParams version: pagination in searchParams, optional body support */ type PaginationFieldInSearchParams<E extends FetchFunction & RestGenerics & { sideEffect?: boolean | undefined; }, C extends string> = RestInstanceBase<ParamFetchNoBody<PaginatedSearchParams<E, C>, ResolveType<E>> | ParamFetchWithBody<PaginatedSearchParams<E, C>, NonNullable<E['body']>, ResolveType<E>>, E['schema'], E['sideEffect'], Pick<E, 'path' | 'searchParams' | 'body'> & { searchParams: { [K in C]: string | number | boolean; } & E['searchParams']; }> & { paginationField: C; }; /** body version: pagination field is in body (body required) */ type PaginationFieldInBody<E extends FetchFunction & RestGenerics & { sideEffect?: boolean | undefined; }, C extends string> = RestInstanceBase<ParamFetchWithBody<E['searchParams'] & PathArgs<Exclude<E['path'], undefined>>, PaginationIntoBody<E['body'], C>, ResolveType<E>>, E['schema'], E['sideEffect'], Pick<E, 'path' | 'searchParams'> & { body: PaginationIntoBody<E['body'], C>; }> & { paginationField: C; }; /** Retrieves the next page of results by pagination field */ export type PaginationFieldEndpoint<E extends FetchFunction & RestGenerics & { sideEffect?: boolean | undefined; }, C extends string> = undefined extends E['body'] ? PaginationFieldInSearchParams<E, C> : C extends keyof E['body'] ? PaginationFieldInBody<E, C> : PaginationFieldInSearchParams<E, C>; export type AddEndpoint<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, O extends { path: string; body: any; searchParams?: any; } = { path: string; body: any; }> = RestInstanceBase<RestFetch<'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<O['path'], undefined>> : PathArgs<Exclude<O['path'], undefined>>, O['body'], ResolveType<F>>, S, true, Omit<O, 'method'> & { method: 'POST'; }>; export type RemoveEndpoint<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, O extends { path: string; body: any; searchParams?: any; } = { path: string; body: any; }> = RestInstanceBase<RestFetch<'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<O['path'], undefined>> : PathArgs<Exclude<O['path'], undefined>>, O['body'], ResolveType<F>>, S, true, Omit<O, 'method'> & { method: 'PATCH'; }>; export type MoveEndpoint<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, O extends { path: string; body: any; } = { path: string; body: any; }> = RestInstanceBase<RestFetch<PathArgs<Exclude<O['path'], undefined>>, O['body'], ResolveType<F>>, S, true, Omit<O, 'method' | 'searchParams'> & { method: 'PATCH'; }>; /** When `method` is omitted from `O`, infer it (must stay aligned with `OptionsToBodyArgument`). */ type InferRestMethodWhenOmitted<O extends RestGenerics> = O extends { sideEffect: true; } ? 'POST' : 'body' extends keyof O ? [ O['body'] ] extends [undefined] ? 'GET' : 'POST' : 'GET'; type MethodArgForBodyInference<O extends RestGenerics> = 'method' extends keyof O ? O['method'] : InferRestMethodWhenOmitted<O>; type OptionsToAdderBodyArgument<O extends { body?: any; }, EntitySchema = any> = 'body' extends keyof O ? O['body'] : Partial<Denormalize<EntitySchema>>; export interface RestEndpointOptions<F extends FetchFunction = FetchFunction, S extends Schema | undefined = undefined> extends EndpointExtraOptions<F> { /** Prepended to all urls * @see https://dataclient.io/rest/api/RestEndpoint#urlPrefix */ urlPrefix?: string; requestInit?: RequestInit; /** Called by getRequestInit to determine HTTP Headers * @see https://dataclient.io/rest/api/RestEndpoint#getHeaders */ getHeaders?(headers: HeadersInit): Promise<HeadersInit> | HeadersInit; /** Prepares RequestInit used in fetch. This is sent to fetchResponse() * @see https://dataclient.io/rest/api/RestEndpoint#getRequestInit */ getRequestInit?(body: any): Promise<RequestInit> | RequestInit; /** Performs the fetch call * @see https://dataclient.io/rest/api/RestEndpoint#fetchResponse */ fetchResponse?(input: RequestInfo, init: RequestInit): Promise<any>; /** Takes the Response and parses via .text() or .json() * @see https://dataclient.io/rest/api/RestEndpoint#parseResponse */ parseResponse?(response: Response): Promise<any>; /** @see https://dataclient.io/rest/api/RestEndpoint#content */ content?: ContentType; sideEffect?: boolean | undefined; name?: string; signal?: AbortSignal; fetch?: F; key?(...args: Parameters<F>): string; url?(...args: Parameters<F>): string; update?: EndpointUpdateFunction<F, S>; } export type RestEndpointConstructorOptions<O extends RestGenerics = any> = RestEndpointOptions<RestFetch<unknown extends O ? any : 'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? SoftPathArgs<O['path']> : O['searchParams'] & SoftPathArgs<O['path']> : SoftPathArgs<O['path']>, OptionsToBodyArgument<O, MethodArgForBodyInference<O>>, O['process'] extends {} ? ReturnType<O['process']> : 'content' extends keyof O ? ContentReturnType<O['content'] & ContentType> : any>, O['schema']>; /** Simplifies endpoint definitions that follow REST patterns * * @see https://dataclient.io/rest/api/RestEndpoint */ export interface RestEndpoint<O extends RestGenerics = any> extends RestInstance<RestFetch<unknown extends O ? any : 'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? PathArgs<O['path']> : O['searchParams'] & PathArgs<O['path']> : PathArgs<O['path']>, OptionsToBodyArgument<O, MethodArgForBodyInference<O>>, O['process'] extends {} ? ReturnType<O['process']> : 'content' extends keyof O ? ContentReturnType<O['content'] & ContentType> : any>, 'schema' extends keyof O ? O['schema'] : undefined, 'sideEffect' extends keyof O ? Extract<O['sideEffect'], boolean | undefined> : MethodToSide<MethodArgForBodyInference<O>>, 'method' extends keyof O ? O : O & { method: InferRestMethodWhenOmitted<O>; }> { } export interface RestEndpointConstructor { /** Simplifies endpoint definitions that follow REST patterns * * @see https://dataclient.io/rest/api/RestEndpoint */ new <O extends RestGenerics = any>({ method, sideEffect, name, ...options }: RestEndpointConstructorOptions<O> & Readonly<O> & ContentSchemaGuard<O>): RestEndpoint<O>; readonly prototype: RestInstanceBase; } export type MethodToSide<M> = M extends string ? M extends 'GET' ? undefined : true : undefined; /** RestEndpoint types simplified */ export type RestType<UrlParams = any, Body = any, S extends Schema | undefined = Schema | undefined, M extends boolean | undefined = boolean | undefined, R = any, O extends { path: string; body?: any; searchParams?: any; paginationField?: string; } = { path: string; paginationField: string; }> = IfTypeScriptLooseNull<RestInstance<RestFetch<UrlParams, Body, R>, S, M, O>, Body extends {} ? RestTypeWithBody<UrlParams, S, M, Body, R, O> : RestTypeNoBody<UrlParams, S, M, R, O>>; export type RestTypeWithBody<UrlParams = any, S extends Schema | undefined = Schema | undefined, M extends boolean | undefined = boolean | undefined, Body = any, R = any, O extends { path: string; body?: any; searchParams?: any; } = { path: string; body: any; }> = RestInstance<ParamFetchWithBody<UrlParams, Body, R>, S, M, O>; export type RestTypeNoBody<UrlParams = any, S extends Schema | undefined = Schema | undefined, M extends boolean | undefined = boolean | undefined, R = any, O extends { path: string; body?: undefined; searchParams?: any; } = { path: string; body: undefined; }> = RestInstance<ParamFetchNoBody<UrlParams, R>, S, M, O>; /** Simple parameters, and body fetch functions */ export type RestFetch<UrlParams, Body = {}, Resolve = any> = IfTypeScriptLooseNull<ParamFetchNoBody<UrlParams, Resolve> | ParamFetchWithBody<UrlParams, Body, Resolve>, Body extends {} ? ParamFetchWithBody<UrlParams, Body, Resolve> : ParamFetchNoBody<UrlParams, Resolve>>; export type ParamFetchWithBody<P, B = {}, R = any> = P extends undefined ? (this: EndpointInstanceInterface, body: B) => Promise<R> : {} extends P ? keyof P extends never ? (this: EndpointInstanceInterface, body: B) => Promise<R> : ((this: EndpointInstanceInterface, params: P, body: B) => Promise<R>) | ((this: EndpointInstanceInterface, body: B) => Promise<R>) : (this: EndpointInstanceInterface, params: P, body: B) => Promise<R>; export type ParamFetchNoBody<P, R = any> = P extends undefined ? (this: EndpointInstanceInterface) => Promise<R> : {} extends P ? keyof P extends never ? (this: EndpointInstanceInterface) => Promise<R> : ((this: EndpointInstanceInterface, params: P) => Promise<R>) | ((this: EndpointInstanceInterface) => Promise<R>) : (this: EndpointInstanceInterface, params: P) => Promise<R>; export type ParamToArgs<P> = P extends undefined ? [] : {} extends P ? keyof P extends never ? [ ] : [] | [P] : [P]; type IfTypeScriptLooseNull<Y, N> = 1 | undefined extends 1 ? Y : N; export type KeyofRestEndpoint = keyof RestInstance; export type FromFallBack<K extends keyof E, O, E> = K extends keyof O ? O[K] : E[K]; export type FetchMutate<A extends readonly any[] = [any, {}] | [{}], R = any> = (this: RestInstance, ...args: A) => Promise<R>; export type FetchGet<A extends readonly any[] = [any], R = any> = (this: RestInstance, ...args: A) => Promise<R>; export type Defaults<O, D> = { [K in keyof O | keyof D]: K extends keyof O ? Exclude<O[K], undefined> : D[Extract<K, keyof D>]; }; export type GetEndpoint<O extends { readonly path: string; readonly schema: Schema; /** Only used for types */ readonly searchParams?: any; readonly paginationField?: string; } = { path: string; schema: Schema; }> = RestTypeNoBody<'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? PathArgs<O['path']> : O['searchParams'] & PathArgs<O['path']> : PathArgs<O['path']>, O['schema'], undefined, any, O & { method: 'GET'; }>; export type MutateEndpoint<O extends { readonly path: string; readonly schema: Schema; /** Only used for types */ readonly searchParams?: any; /** Only used for types */ readonly body?: any; } = { path: string; body: any; schema: Schema; }> = RestTypeWithBody<'searchParams' extends keyof O ? [ O['searchParams'] ] extends [undefined] ? PathArgs<O['path']> : O['searchParams'] & PathArgs<O['path']> : PathArgs<O['path']>, O['schema'], true, O['body'], any, O & { body: any; method: 'POST' | 'PUT' | 'PATCH' | 'DELETE'; }>; export {}; //# sourceMappingURL=RestEndpointTypes.d.ts.map