@hey-api/openapi-ts
Version:
🚀 The OpenAPI to TypeScript codegen. Generate clients, SDKs, validators, and more.
148 lines (128 loc) • 3.92 kB
text/typescript
import type { AxiosError, AxiosInstance, RawAxiosRequestHeaders } from 'axios';
import axios from 'axios';
import { createSseClient } from '../core/serverSentEvents';
import type { Client, Config, RequestOptions } from './types';
import {
buildUrl,
createConfig,
mergeConfigs,
mergeHeaders,
setAuthParams,
} from './utils';
export const createClient = (config: Config = {}): Client => {
let _config = mergeConfigs(createConfig(), config);
let instance: AxiosInstance;
if (_config.axios && !('Axios' in _config.axios)) {
instance = _config.axios;
} else {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { auth, ...configWithoutAuth } = _config;
instance = axios.create(configWithoutAuth);
}
const getConfig = (): Config => ({ ..._config });
const setConfig = (config: Config): Config => {
_config = mergeConfigs(_config, config);
instance.defaults = {
...instance.defaults,
..._config,
// @ts-expect-error
headers: mergeHeaders(instance.defaults.headers, _config.headers),
};
return getConfig();
};
const beforeRequest = async (options: RequestOptions) => {
const opts = {
..._config,
...options,
axios: options.axios ?? _config.axios ?? instance,
headers: mergeHeaders(_config.headers, options.headers),
};
if (opts.security) {
await setAuthParams({
...opts,
security: opts.security,
});
}
if (opts.requestValidator) {
await opts.requestValidator(opts);
}
if (opts.body && opts.bodySerializer) {
opts.body = opts.bodySerializer(opts.body);
}
const url = buildUrl(opts);
return { opts, url };
};
// @ts-expect-error
const request: Client['request'] = async (options) => {
// @ts-expect-error
const { opts, url } = await beforeRequest(options);
try {
// assign Axios here for consistency with fetch
const _axios = opts.axios!;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { auth, ...optsWithoutAuth } = opts;
const response = await _axios({
...optsWithoutAuth,
baseURL: opts.baseURL as string,
data: opts.body,
headers: opts.headers as RawAxiosRequestHeaders,
// let `paramsSerializer()` handle query params if it exists
params: opts.paramsSerializer ? opts.query : undefined,
url,
});
let { data } = response;
if (opts.responseType === 'json') {
if (opts.responseValidator) {
await opts.responseValidator(data);
}
if (opts.responseTransformer) {
data = await opts.responseTransformer(data);
}
}
return {
...response,
data: data ?? {},
};
} catch (error) {
const e = error as AxiosError;
if (opts.throwOnError) {
throw e;
}
// @ts-expect-error
e.error = e.response?.data ?? {};
return e;
}
};
const makeMethod = (method: Required<Config>['method']) => {
const fn = (options: RequestOptions) => request({ ...options, method });
fn.sse = async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
headers: opts.headers as Record<string, string>,
method,
// @ts-expect-error
signal: opts.signal,
url,
});
};
return fn;
};
return {
buildUrl,
connect: makeMethod('CONNECT'),
delete: makeMethod('DELETE'),
get: makeMethod('GET'),
getConfig,
head: makeMethod('HEAD'),
instance,
options: makeMethod('OPTIONS'),
patch: makeMethod('PATCH'),
post: makeMethod('POST'),
put: makeMethod('PUT'),
request,
setConfig,
trace: makeMethod('TRACE'),
} as Client;
};