@ts-rest/core
Advanced tools
Comparing version 3.36.0 to 3.37.0
# @ts-rest/core | ||
## 3.37.0 | ||
### Minor Changes | ||
- 6a5280c: Allow fetch options to be set and client options to be overridden per request | ||
### Patch Changes | ||
- 77db06b: Fix client not correctly encoding application/x-www-form-urlencoded body | ||
## 3.36.0 | ||
@@ -4,0 +14,0 @@ |
178
index.cjs.js
@@ -199,31 +199,25 @@ 'use strict'; | ||
} | ||
const tsRestFetchApi = async ({ path, method, headers, body, credentials, signal, cache, next, route, }) => { | ||
const tsRestFetchApi = async ({ route, path, method, headers, body, validateResponse, fetchOptions, }) => { | ||
const result = await fetch(path, { | ||
...fetchOptions, | ||
method, | ||
headers, | ||
body, | ||
credentials, | ||
signal, | ||
cache, | ||
next, | ||
}); | ||
const contentType = result.headers.get('content-type'); | ||
if ((contentType === null || contentType === void 0 ? void 0 : contentType.includes('application/')) && (contentType === null || contentType === void 0 ? void 0 : contentType.includes('json'))) { | ||
if (!route.validateResponseOnClient) { | ||
const response = { | ||
status: result.status, | ||
body: await result.json(), | ||
headers: result.headers, | ||
}; | ||
const responseSchema = route.responses[response.status]; | ||
if ((validateResponse !== null && validateResponse !== void 0 ? validateResponse : route.validateResponseOnClient) && | ||
isZodType(responseSchema)) { | ||
return { | ||
status: result.status, | ||
body: await result.json(), | ||
headers: result.headers, | ||
...response, | ||
body: responseSchema.parse(response.body), | ||
}; | ||
} | ||
const jsonData = await result.json(); | ||
const statusCode = result.status; | ||
const response = route.responses[statusCode]; | ||
return { | ||
status: statusCode, | ||
body: response && typeof response !== 'symbol' && 'parse' in response | ||
? response === null || response === void 0 ? void 0 : response.parse(jsonData) | ||
: jsonData, | ||
headers: result.headers, | ||
}; | ||
return response; | ||
} | ||
@@ -258,3 +252,3 @@ if (contentType === null || contentType === void 0 ? void 0 : contentType.includes('text/')) { | ||
}; | ||
const fetchApi = ({ path, clientArgs, route, body, query, extraInputArgs, headers, signal, next, }) => { | ||
const fetchApi = ({ path, clientArgs, route, body, query, extraInputArgs, headers, fetchOptions, }) => { | ||
const apiFetcher = clientArgs.api || tsRestFetchApi; | ||
@@ -270,58 +264,87 @@ const combinedHeaders = { | ||
}); | ||
if (route.method !== 'GET' && route.contentType === 'multipart/form-data') { | ||
return apiFetcher({ | ||
route, | ||
path, | ||
method: route.method, | ||
credentials: clientArgs.credentials, | ||
headers: combinedHeaders, | ||
body: body instanceof FormData ? body : createFormData(body), | ||
rawBody: body, | ||
rawQuery: query, | ||
contentType: 'multipart/form-data', | ||
signal, | ||
next, | ||
...extraInputArgs, | ||
}); | ||
} | ||
if (route.method !== 'GET' && | ||
route.contentType === 'application/x-www-form-urlencoded') { | ||
const headers = { | ||
...combinedHeaders, | ||
'content-type': 'application/x-www-form-urlencoded', | ||
}; | ||
return apiFetcher({ | ||
route, | ||
path, | ||
method: route.method, | ||
credentials: clientArgs.credentials, | ||
headers, | ||
body: body instanceof FormData ? body : createFormData(body), | ||
rawBody: body, | ||
rawQuery: query, | ||
contentType: 'application/x-www-form-urlencoded', | ||
signal, | ||
next, | ||
...extraInputArgs, | ||
}); | ||
} | ||
const includeContentTypeHeader = route.method !== 'GET' && body !== null && body !== undefined; | ||
return apiFetcher({ | ||
let fetcherArgs = { | ||
route, | ||
path, | ||
method: route.method, | ||
credentials: clientArgs.credentials, | ||
headers: { | ||
...(includeContentTypeHeader && { 'content-type': 'application/json' }), | ||
...combinedHeaders, | ||
}, | ||
body: body !== null && body !== undefined ? JSON.stringify(body) : undefined, | ||
headers: combinedHeaders, | ||
body: undefined, | ||
rawBody: body, | ||
rawQuery: query, | ||
contentType: includeContentTypeHeader ? 'application/json' : undefined, | ||
signal, | ||
next, | ||
contentType: undefined, | ||
fetchOptions: { | ||
...(clientArgs.credentials && { credentials: clientArgs.credentials }), | ||
...fetchOptions, | ||
}, | ||
...((fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.signal) && { signal: fetchOptions.signal }), | ||
...((fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.cache) && { cache: fetchOptions.cache }), | ||
...(fetchOptions && | ||
'next' in fetchOptions && | ||
!!(fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.next) && { next: fetchOptions.next }), | ||
}; | ||
if (route.method !== 'GET') { | ||
if (route.contentType === 'multipart/form-data') { | ||
fetcherArgs = { | ||
...fetcherArgs, | ||
contentType: 'multipart/form-data', | ||
body: body instanceof FormData ? body : createFormData(body), | ||
}; | ||
} | ||
else if (route.contentType === 'application/x-www-form-urlencoded') { | ||
fetcherArgs = { | ||
...fetcherArgs, | ||
contentType: 'application/x-www-form-urlencoded', | ||
headers: { | ||
...fetcherArgs.headers, | ||
'content-type': 'application/x-www-form-urlencoded', | ||
}, | ||
body: typeof body === 'string' | ||
? body | ||
: new URLSearchParams(body), | ||
}; | ||
} | ||
else if (body !== null && body !== undefined) { | ||
fetcherArgs = { | ||
...fetcherArgs, | ||
contentType: 'application/json', | ||
headers: { | ||
...fetcherArgs.headers, | ||
'content-type': 'application/json', | ||
}, | ||
body: JSON.stringify(body), | ||
}; | ||
} | ||
} | ||
return apiFetcher({ | ||
...fetcherArgs, | ||
...extraInputArgs, | ||
}); | ||
}; | ||
const evaluateFetchApiArgs = (route, clientArgs, inputArgs) => { | ||
const { query, params, body, headers, extraHeaders, overrideClientOptions, fetchOptions, | ||
cache, | ||
next, | ||
...extraInputArgs } = inputArgs || {}; | ||
const overriddenClientArgs = { | ||
...clientArgs, | ||
...overrideClientOptions, | ||
}; | ||
const completeUrl = getCompleteUrl(query, overriddenClientArgs.baseUrl, params, route, !!overriddenClientArgs.jsonQuery); | ||
return { | ||
path: completeUrl, | ||
clientArgs: overriddenClientArgs, | ||
route, | ||
body, | ||
query, | ||
extraInputArgs, | ||
fetchOptions: { | ||
...(cache && { cache }), | ||
...(next && { next }), | ||
...fetchOptions, | ||
}, | ||
headers: { | ||
...extraHeaders, | ||
...headers, | ||
}, | ||
}; | ||
}; | ||
const getCompleteUrl = (query, baseUrl, params, route, jsonQuery) => { | ||
@@ -338,18 +361,4 @@ const path = insertParamsIntoPath({ | ||
return async (inputArgs) => { | ||
const { query, params, body, headers, extraHeaders, next, ...extraInputArgs } = | ||
inputArgs || {}; | ||
const completeUrl = getCompleteUrl(query, clientArgs.baseUrl, params, route, !!clientArgs.jsonQuery); | ||
const response = await fetchApi({ | ||
path: completeUrl, | ||
clientArgs, | ||
route, | ||
body, | ||
query, | ||
extraInputArgs, | ||
next, | ||
headers: { | ||
...extraHeaders, | ||
...headers, | ||
}, | ||
}); | ||
const fetchApiArgs = evaluateFetchApiArgs(route, clientArgs, inputArgs); | ||
const response = await fetchApi(fetchApiArgs); | ||
if (!clientArgs.throwOnUnknownStatus) { | ||
@@ -419,2 +428,3 @@ return response; | ||
exports.encodeQueryParamsJson = encodeQueryParamsJson; | ||
exports.evaluateFetchApiArgs = evaluateFetchApiArgs; | ||
exports.extractZodObjectShape = extractZodObjectShape; | ||
@@ -421,0 +431,0 @@ exports.fetchApi = fetchApi; |
179
index.esm.js
@@ -195,31 +195,25 @@ const isZodType = (obj) => { | ||
} | ||
const tsRestFetchApi = async ({ path, method, headers, body, credentials, signal, cache, next, route, }) => { | ||
const tsRestFetchApi = async ({ route, path, method, headers, body, validateResponse, fetchOptions, }) => { | ||
const result = await fetch(path, { | ||
...fetchOptions, | ||
method, | ||
headers, | ||
body, | ||
credentials, | ||
signal, | ||
cache, | ||
next, | ||
}); | ||
const contentType = result.headers.get('content-type'); | ||
if ((contentType === null || contentType === void 0 ? void 0 : contentType.includes('application/')) && (contentType === null || contentType === void 0 ? void 0 : contentType.includes('json'))) { | ||
if (!route.validateResponseOnClient) { | ||
const response = { | ||
status: result.status, | ||
body: await result.json(), | ||
headers: result.headers, | ||
}; | ||
const responseSchema = route.responses[response.status]; | ||
if ((validateResponse !== null && validateResponse !== void 0 ? validateResponse : route.validateResponseOnClient) && | ||
isZodType(responseSchema)) { | ||
return { | ||
status: result.status, | ||
body: await result.json(), | ||
headers: result.headers, | ||
...response, | ||
body: responseSchema.parse(response.body), | ||
}; | ||
} | ||
const jsonData = await result.json(); | ||
const statusCode = result.status; | ||
const response = route.responses[statusCode]; | ||
return { | ||
status: statusCode, | ||
body: response && typeof response !== 'symbol' && 'parse' in response | ||
? response === null || response === void 0 ? void 0 : response.parse(jsonData) | ||
: jsonData, | ||
headers: result.headers, | ||
}; | ||
return response; | ||
} | ||
@@ -254,3 +248,3 @@ if (contentType === null || contentType === void 0 ? void 0 : contentType.includes('text/')) { | ||
}; | ||
const fetchApi = ({ path, clientArgs, route, body, query, extraInputArgs, headers, signal, next, }) => { | ||
const fetchApi = ({ path, clientArgs, route, body, query, extraInputArgs, headers, fetchOptions, }) => { | ||
const apiFetcher = clientArgs.api || tsRestFetchApi; | ||
@@ -266,58 +260,87 @@ const combinedHeaders = { | ||
}); | ||
if (route.method !== 'GET' && route.contentType === 'multipart/form-data') { | ||
return apiFetcher({ | ||
route, | ||
path, | ||
method: route.method, | ||
credentials: clientArgs.credentials, | ||
headers: combinedHeaders, | ||
body: body instanceof FormData ? body : createFormData(body), | ||
rawBody: body, | ||
rawQuery: query, | ||
contentType: 'multipart/form-data', | ||
signal, | ||
next, | ||
...extraInputArgs, | ||
}); | ||
} | ||
if (route.method !== 'GET' && | ||
route.contentType === 'application/x-www-form-urlencoded') { | ||
const headers = { | ||
...combinedHeaders, | ||
'content-type': 'application/x-www-form-urlencoded', | ||
}; | ||
return apiFetcher({ | ||
route, | ||
path, | ||
method: route.method, | ||
credentials: clientArgs.credentials, | ||
headers, | ||
body: body instanceof FormData ? body : createFormData(body), | ||
rawBody: body, | ||
rawQuery: query, | ||
contentType: 'application/x-www-form-urlencoded', | ||
signal, | ||
next, | ||
...extraInputArgs, | ||
}); | ||
} | ||
const includeContentTypeHeader = route.method !== 'GET' && body !== null && body !== undefined; | ||
return apiFetcher({ | ||
let fetcherArgs = { | ||
route, | ||
path, | ||
method: route.method, | ||
credentials: clientArgs.credentials, | ||
headers: { | ||
...(includeContentTypeHeader && { 'content-type': 'application/json' }), | ||
...combinedHeaders, | ||
}, | ||
body: body !== null && body !== undefined ? JSON.stringify(body) : undefined, | ||
headers: combinedHeaders, | ||
body: undefined, | ||
rawBody: body, | ||
rawQuery: query, | ||
contentType: includeContentTypeHeader ? 'application/json' : undefined, | ||
signal, | ||
next, | ||
contentType: undefined, | ||
fetchOptions: { | ||
...(clientArgs.credentials && { credentials: clientArgs.credentials }), | ||
...fetchOptions, | ||
}, | ||
...((fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.signal) && { signal: fetchOptions.signal }), | ||
...((fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.cache) && { cache: fetchOptions.cache }), | ||
...(fetchOptions && | ||
'next' in fetchOptions && | ||
!!(fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.next) && { next: fetchOptions.next }), | ||
}; | ||
if (route.method !== 'GET') { | ||
if (route.contentType === 'multipart/form-data') { | ||
fetcherArgs = { | ||
...fetcherArgs, | ||
contentType: 'multipart/form-data', | ||
body: body instanceof FormData ? body : createFormData(body), | ||
}; | ||
} | ||
else if (route.contentType === 'application/x-www-form-urlencoded') { | ||
fetcherArgs = { | ||
...fetcherArgs, | ||
contentType: 'application/x-www-form-urlencoded', | ||
headers: { | ||
...fetcherArgs.headers, | ||
'content-type': 'application/x-www-form-urlencoded', | ||
}, | ||
body: typeof body === 'string' | ||
? body | ||
: new URLSearchParams(body), | ||
}; | ||
} | ||
else if (body !== null && body !== undefined) { | ||
fetcherArgs = { | ||
...fetcherArgs, | ||
contentType: 'application/json', | ||
headers: { | ||
...fetcherArgs.headers, | ||
'content-type': 'application/json', | ||
}, | ||
body: JSON.stringify(body), | ||
}; | ||
} | ||
} | ||
return apiFetcher({ | ||
...fetcherArgs, | ||
...extraInputArgs, | ||
}); | ||
}; | ||
const evaluateFetchApiArgs = (route, clientArgs, inputArgs) => { | ||
const { query, params, body, headers, extraHeaders, overrideClientOptions, fetchOptions, | ||
cache, | ||
next, | ||
...extraInputArgs } = inputArgs || {}; | ||
const overriddenClientArgs = { | ||
...clientArgs, | ||
...overrideClientOptions, | ||
}; | ||
const completeUrl = getCompleteUrl(query, overriddenClientArgs.baseUrl, params, route, !!overriddenClientArgs.jsonQuery); | ||
return { | ||
path: completeUrl, | ||
clientArgs: overriddenClientArgs, | ||
route, | ||
body, | ||
query, | ||
extraInputArgs, | ||
fetchOptions: { | ||
...(cache && { cache }), | ||
...(next && { next }), | ||
...fetchOptions, | ||
}, | ||
headers: { | ||
...extraHeaders, | ||
...headers, | ||
}, | ||
}; | ||
}; | ||
const getCompleteUrl = (query, baseUrl, params, route, jsonQuery) => { | ||
@@ -334,18 +357,4 @@ const path = insertParamsIntoPath({ | ||
return async (inputArgs) => { | ||
const { query, params, body, headers, extraHeaders, next, ...extraInputArgs } = | ||
inputArgs || {}; | ||
const completeUrl = getCompleteUrl(query, clientArgs.baseUrl, params, route, !!clientArgs.jsonQuery); | ||
const response = await fetchApi({ | ||
path: completeUrl, | ||
clientArgs, | ||
route, | ||
body, | ||
query, | ||
extraInputArgs, | ||
next, | ||
headers: { | ||
...extraHeaders, | ||
...headers, | ||
}, | ||
}); | ||
const fetchApiArgs = evaluateFetchApiArgs(route, clientArgs, inputArgs); | ||
const response = await fetchApi(fetchApiArgs); | ||
if (!clientArgs.throwOnUnknownStatus) { | ||
@@ -408,2 +417,2 @@ return response; | ||
export { ContractPlainTypeRuntimeSymbol, ResponseValidationError, UnknownStatusError, checkZodSchema, convertQueryParamsToUrlString, encodeQueryParams, encodeQueryParamsJson, extractZodObjectShape, fetchApi, getCompleteUrl, getRouteQuery, getRouteResponses, initClient, initContract, initTsRest, insertParamsIntoPath, isAppRoute, isAppRouteOtherResponse, isAppRouteResponse, isZodObject, isZodObjectStrict, isZodType, parseJsonQueryObject, tsRestFetchApi, validateResponse, zodErrorResponse, zodMerge }; | ||
export { ContractPlainTypeRuntimeSymbol, ResponseValidationError, UnknownStatusError, checkZodSchema, convertQueryParamsToUrlString, encodeQueryParams, encodeQueryParamsJson, evaluateFetchApiArgs, extractZodObjectShape, fetchApi, getCompleteUrl, getRouteQuery, getRouteResponses, initClient, initContract, initTsRest, insertParamsIntoPath, isAppRoute, isAppRouteOtherResponse, isAppRouteResponse, isZodObject, isZodObjectStrict, isZodType, parseJsonQueryObject, tsRestFetchApi, validateResponse, zodErrorResponse, zodMerge }; |
{ | ||
"name": "@ts-rest/core", | ||
"version": "3.36.0", | ||
"version": "3.37.0", | ||
"description": "RPC-like experience over a regular REST API, with type safe server implementations 🪄", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
import { AppRoute, AppRouteMutation, AppRouter } from './dsl'; | ||
import { AreAllPropertiesOptional, Prettify } from './type-utils'; | ||
import { ClientInferRequest, ClientInferResponses, PartialClientInferRequest, NextClientArgs, Frameworks } from './infer-types'; | ||
import { ClientInferRequest, ClientInferResponses, PartialClientInferRequest } from './infer-types'; | ||
type RecursiveProxyObj<T extends AppRouter, TClientArgs extends ClientArgs> = { | ||
@@ -19,9 +19,13 @@ [TKey in keyof T]: T[TKey] extends AppRoute ? AppRouteFunction<T[TKey], TClientArgs> : T[TKey] extends AppRouter ? RecursiveProxyObj<T[TKey], TClientArgs> : never; | ||
export type AppRouteFunction<TRoute extends AppRoute, TClientArgs extends ClientArgs, TArgs = PartialClientInferRequest<TRoute, TClientArgs>> = AreAllPropertiesOptional<TArgs> extends true ? (args?: Prettify<TArgs>) => Promise<Prettify<ClientInferResponses<TRoute>>> : (args: Prettify<TArgs>) => Promise<Prettify<ClientInferResponses<TRoute>>>; | ||
export interface ClientArgs { | ||
export type FetchOptions = Omit<RequestInit, 'method' | 'headers' | 'body'>; | ||
export interface OverrideableClientArgs { | ||
baseUrl: string; | ||
baseHeaders: Record<string, string>; | ||
api?: ApiFetcher; | ||
credentials?: RequestCredentials; | ||
jsonQuery?: boolean; | ||
validateResponse?: boolean; | ||
} | ||
export interface ClientArgs extends OverrideableClientArgs { | ||
baseHeaders: Record<string, string>; | ||
api?: ApiFetcher; | ||
} | ||
export type ApiFetcherArgs = { | ||
@@ -32,14 +36,27 @@ route: AppRoute; | ||
headers: Record<string, string>; | ||
body: FormData | string | null | undefined; | ||
body: FormData | URLSearchParams | string | null | undefined; | ||
rawBody: unknown; | ||
rawQuery: unknown; | ||
contentType: AppRouteMutation['contentType']; | ||
fetchOptions?: FetchOptions; | ||
validateResponse?: boolean; | ||
/** | ||
* @deprecated Use `fetchOptions.credentials` instead | ||
*/ | ||
credentials?: RequestCredentials; | ||
/** | ||
* @deprecated Use `fetchOptions.signal` instead | ||
*/ | ||
signal?: AbortSignal; | ||
/** | ||
* @deprecated Use `fetchOptions.cache` instead | ||
*/ | ||
cache?: RequestCache; | ||
/** | ||
* Only to be used by `@ts-rest/next`. | ||
* You can obtain a Nextjs Client by calling `initNextClient` | ||
* @deprecated Use `fetchOptions.next` instead | ||
*/ | ||
next?: NextClientArgs['next'] | undefined; | ||
next?: { | ||
revalidate?: number | false; | ||
tags?: string[]; | ||
} | undefined; | ||
}; | ||
@@ -59,3 +76,3 @@ export type ApiFetcher = (args: ApiFetcherArgs) => Promise<{ | ||
export declare const tsRestFetchApi: ApiFetcher; | ||
export declare const fetchApi: ({ path, clientArgs, route, body, query, extraInputArgs, headers, signal, next, }: { | ||
export declare const fetchApi: ({ path, clientArgs, route, body, query, extraInputArgs, headers, fetchOptions, }: { | ||
path: string; | ||
@@ -68,8 +85,3 @@ clientArgs: ClientArgs; | ||
headers: Record<string, string | undefined>; | ||
signal?: AbortSignal | undefined; | ||
/** | ||
* only to be used by @ts-rest/next | ||
* You can obtain a Nextjs Client by calling `initNextClient` | ||
*/ | ||
next?: NextClientArgs['next'] | undefined; | ||
fetchOptions?: FetchOptions | undefined; | ||
}) => Promise<{ | ||
@@ -80,2 +92,12 @@ status: number; | ||
}>; | ||
export declare const evaluateFetchApiArgs: <TAppRoute extends AppRoute>(route: TAppRoute, clientArgs: InitClientArgs, inputArgs?: ClientInferRequest<AppRouteMutation, ClientArgs>) => { | ||
path: string; | ||
clientArgs: ClientArgs; | ||
route: AppRoute; | ||
query: unknown; | ||
body: unknown; | ||
extraInputArgs: Record<string, unknown>; | ||
headers: Record<string, string | undefined>; | ||
fetchOptions?: FetchOptions | undefined; | ||
}; | ||
/** | ||
@@ -85,33 +107,3 @@ * @hidden | ||
export declare const getCompleteUrl: (query: unknown, baseUrl: string, params: unknown, route: AppRoute, jsonQuery: boolean) => string; | ||
export declare const getRouteQuery: <TAppRoute extends AppRoute, Framework extends Frameworks = "none">(route: TAppRoute, clientArgs: InitClientArgs) => (inputArgs?: (Framework extends "nextjs" ? { | ||
headers: { | ||
[x: Lowercase<string>]: any; | ||
}; | ||
body: any; | ||
cache?: RequestCache | undefined; | ||
next?: { | ||
revalidate?: number | false | undefined; | ||
tags?: string[] | undefined; | ||
} | undefined; | ||
params: { | ||
[x: string]: any; | ||
}; | ||
query: any; | ||
extraHeaders?: ({ | ||
[x: Lowercase<string>]: undefined; | ||
} & Record<string, string | undefined>) | undefined; | ||
} : { | ||
headers: { | ||
[x: Lowercase<string>]: any; | ||
}; | ||
body: any; | ||
cache?: RequestCache | undefined; | ||
params: { | ||
[x: string]: any; | ||
}; | ||
query: any; | ||
extraHeaders?: ({ | ||
[x: Lowercase<string>]: undefined; | ||
} & Record<string, string | undefined>) | undefined; | ||
}) | undefined) => Promise<{ | ||
export declare const getRouteQuery: <TAppRoute extends AppRoute>(route: TAppRoute, clientArgs: InitClientArgs) => (inputArgs?: ClientInferRequest<AppRouteMutation, ClientArgs>) => Promise<{ | ||
status: number; | ||
@@ -118,0 +110,0 @@ body: unknown; |
@@ -31,2 +31,5 @@ import { Merge, Opaque, Prettify, WithoutUnknown } from './type-utils'; | ||
metadata?: unknown; | ||
/** | ||
* @deprecated Use `validateResponse` on the client options | ||
*/ | ||
validateResponseOnClient?: boolean; | ||
@@ -89,2 +92,5 @@ }; | ||
pathPrefix?: TPrefix; | ||
/** | ||
* @deprecated Use `validateResponse` on the client options | ||
*/ | ||
validateResponseOnClient?: boolean; | ||
@@ -91,0 +97,0 @@ }; |
import { AppRoute, AppRouteMutation, AppRouter, AppRouteStrictStatusCodes, ContractAnyType, ContractOtherResponse } from './dsl'; | ||
import { HTTPStatusCode } from './status-codes'; | ||
import { And, Extends, LowercaseKeys, Merge, Not, OptionalIfAllOptional, Or, PartialByLooseKeys, Prettify, Without, ZodInferOrType, ZodInputOrType } from './type-utils'; | ||
import { ApiFetcher, ClientArgs } from './client'; | ||
import { ApiFetcher, ClientArgs, OverrideableClientArgs, FetchOptions } from './client'; | ||
import { ParamsFromUrl } from './paths'; | ||
export type Frameworks = 'nextjs' | 'none'; | ||
export type NextClientArgs = { | ||
next?: { | ||
revalidate?: number | false; | ||
tags?: string[]; | ||
} | undefined; | ||
}; | ||
type ExtractExtraParametersFromClientArgs<TClientArgs extends Pick<ClientArgs, 'api'>> = TClientArgs['api'] extends ApiFetcher ? Omit<Parameters<TClientArgs['api']>[0], keyof Parameters<ApiFetcher>[0]> : {}; | ||
@@ -53,9 +46,9 @@ /** | ||
} : never; | ||
type ClientInferRequestBase<Framework extends Frameworks, T extends AppRoute, TClientArgs extends Omit<ClientArgs, 'baseUrl'> = { | ||
type ClientInferRequestBase<T extends AppRoute, TClientArgs extends Omit<ClientArgs, 'baseUrl'> = { | ||
baseHeaders: {}; | ||
}, THeaders = 'headers' extends keyof T ? Prettify<PartialByLooseKeys<LowercaseKeys<ZodInputOrType<T['headers']>>, keyof LowercaseKeys<TClientArgs['baseHeaders']>>> : never> = Prettify<Without<{ | ||
}, THeaders = 'headers' extends keyof T ? Prettify<PartialByLooseKeys<LowercaseKeys<ZodInputOrType<T['headers']>>, keyof LowercaseKeys<TClientArgs['baseHeaders']>>> : never, TFetchOptions extends FetchOptions = FetchOptions> = Prettify<Without<{ | ||
params: [keyof PathParamsWithCustomValidators<T, 'client'>] extends [ | ||
never | ||
] ? never : Prettify<PathParamsWithCustomValidators<T, 'client'>>; | ||
body: T extends AppRouteMutation ? T['body'] extends null ? never : T['contentType'] extends 'multipart/form-data' ? FormData | ZodInputOrType<T['body']> : ZodInputOrType<T['body']> : never; | ||
body: T extends AppRouteMutation ? T['body'] extends null ? never : T['contentType'] extends 'multipart/form-data' ? FormData | ZodInputOrType<T['body']> : T['contentType'] extends 'application/x-www-form-urlencoded' ? string | ZodInputOrType<T['body']> : ZodInputOrType<T['body']> : never; | ||
query: 'query' extends keyof T ? T['query'] extends null ? never : ZodInputOrType<T['query']> : never; | ||
@@ -66,8 +59,16 @@ headers: THeaders; | ||
} & Record<string, string | undefined>; | ||
fetchOptions?: FetchOptions; | ||
overrideClientOptions?: Partial<OverrideableClientArgs>; | ||
/** | ||
* @deprecated Use `fetchOptions.cache` instead | ||
*/ | ||
cache?: RequestCache; | ||
next?: Framework extends 'nextjs' ? NextClientArgs['next'] : never; | ||
/** | ||
* @deprecated Use `fetchOptions.next` instead | ||
*/ | ||
next?: 'next' extends keyof TFetchOptions ? TFetchOptions['next'] : never; | ||
} & ExtractExtraParametersFromClientArgs<TClientArgs>, never>>; | ||
export type ClientInferRequest<T extends AppRoute | AppRouter, TClientArgs extends Omit<ClientArgs, 'baseUrl'> = { | ||
baseHeaders: {}; | ||
}, Framework extends Frameworks = 'none'> = T extends AppRoute ? ClientInferRequestBase<Framework, T, TClientArgs> : T extends AppRouter ? { | ||
}> = T extends AppRoute ? ClientInferRequestBase<T, TClientArgs> : T extends AppRouter ? { | ||
[TKey in keyof T]: ClientInferRequest<T[TKey]>; | ||
@@ -77,3 +78,3 @@ } : never; | ||
baseHeaders: {}; | ||
}, Framework extends Frameworks = 'none'> = OptionalIfAllOptional<ClientInferRequest<TRoute, TClientArgs, Framework>>; | ||
}> = OptionalIfAllOptional<ClientInferRequest<TRoute, TClientArgs>>; | ||
export {}; |
@@ -76,3 +76,2 @@ import { z } from 'zod'; | ||
}[`${B}`]; | ||
export type Promisable<T> = Promise<T> | T; | ||
export {}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79289
1395