summaryrefslogtreecommitdiffhomepage
path: root/packages/sdk/js/src/gen/client
diff options
context:
space:
mode:
Diffstat (limited to 'packages/sdk/js/src/gen/client')
-rw-r--r--packages/sdk/js/src/gen/client/client.ts195
-rw-r--r--packages/sdk/js/src/gen/client/index.ts22
-rw-r--r--packages/sdk/js/src/gen/client/types.ts222
-rw-r--r--packages/sdk/js/src/gen/client/utils.ts417
4 files changed, 856 insertions, 0 deletions
diff --git a/packages/sdk/js/src/gen/client/client.ts b/packages/sdk/js/src/gen/client/client.ts
new file mode 100644
index 000000000..89d1e3158
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/client.ts
@@ -0,0 +1,195 @@
+import type { Client, Config, RequestOptions } from './types';
+import {
+ buildUrl,
+ createConfig,
+ createInterceptors,
+ getParseAs,
+ mergeConfigs,
+ mergeHeaders,
+ setAuthParams,
+} from './utils';
+
+type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
+ body?: any;
+ headers: ReturnType<typeof mergeHeaders>;
+};
+
+export const createClient = (config: Config = {}): Client => {
+ let _config = mergeConfigs(createConfig(), config);
+
+ const getConfig = (): Config => ({ ..._config });
+
+ const setConfig = (config: Config): Config => {
+ _config = mergeConfigs(_config, config);
+ return getConfig();
+ };
+
+ const interceptors = createInterceptors<
+ Request,
+ Response,
+ unknown,
+ RequestOptions
+ >();
+
+ const request: Client['request'] = async (options) => {
+ const opts = {
+ ..._config,
+ ...options,
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
+ 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);
+ }
+
+ // remove Content-Type header if body is empty to avoid sending invalid requests
+ if (opts.body === undefined || opts.body === '') {
+ opts.headers.delete('Content-Type');
+ }
+
+ const url = buildUrl(opts);
+ const requestInit: ReqInit = {
+ redirect: 'follow',
+ ...opts,
+ };
+
+ let request = new Request(url, requestInit);
+
+ for (const fn of interceptors.request._fns) {
+ if (fn) {
+ request = await fn(request, opts);
+ }
+ }
+
+ // fetch must be assigned here, otherwise it would throw the error:
+ // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
+ const _fetch = opts.fetch!;
+ let response = await _fetch(request);
+
+ for (const fn of interceptors.response._fns) {
+ if (fn) {
+ response = await fn(response, request, opts);
+ }
+ }
+
+ const result = {
+ request,
+ response,
+ };
+
+ if (response.ok) {
+ if (
+ response.status === 204 ||
+ response.headers.get('Content-Length') === '0'
+ ) {
+ return opts.responseStyle === 'data'
+ ? {}
+ : {
+ data: {},
+ ...result,
+ };
+ }
+
+ const parseAs =
+ (opts.parseAs === 'auto'
+ ? getParseAs(response.headers.get('Content-Type'))
+ : opts.parseAs) ?? 'json';
+
+ let data: any;
+ switch (parseAs) {
+ case 'arrayBuffer':
+ case 'blob':
+ case 'formData':
+ case 'json':
+ case 'text':
+ data = await response[parseAs]();
+ break;
+ case 'stream':
+ return opts.responseStyle === 'data'
+ ? response.body
+ : {
+ data: response.body,
+ ...result,
+ };
+ }
+
+ if (parseAs === 'json') {
+ if (opts.responseValidator) {
+ await opts.responseValidator(data);
+ }
+
+ if (opts.responseTransformer) {
+ data = await opts.responseTransformer(data);
+ }
+ }
+
+ return opts.responseStyle === 'data'
+ ? data
+ : {
+ data,
+ ...result,
+ };
+ }
+
+ const textError = await response.text();
+ let jsonError: unknown;
+
+ try {
+ jsonError = JSON.parse(textError);
+ } catch {
+ // noop
+ }
+
+ const error = jsonError ?? textError;
+ let finalError = error;
+
+ for (const fn of interceptors.error._fns) {
+ if (fn) {
+ finalError = (await fn(error, response, request, opts)) as string;
+ }
+ }
+
+ finalError = finalError || ({} as string);
+
+ if (opts.throwOnError) {
+ throw finalError;
+ }
+
+ // TODO: we probably want to return error and improve types
+ return opts.responseStyle === 'data'
+ ? undefined
+ : {
+ error: finalError,
+ ...result,
+ };
+ };
+
+ return {
+ buildUrl,
+ connect: (options) => request({ ...options, method: 'CONNECT' }),
+ delete: (options) => request({ ...options, method: 'DELETE' }),
+ get: (options) => request({ ...options, method: 'GET' }),
+ getConfig,
+ head: (options) => request({ ...options, method: 'HEAD' }),
+ interceptors,
+ options: (options) => request({ ...options, method: 'OPTIONS' }),
+ patch: (options) => request({ ...options, method: 'PATCH' }),
+ post: (options) => request({ ...options, method: 'POST' }),
+ put: (options) => request({ ...options, method: 'PUT' }),
+ request,
+ setConfig,
+ trace: (options) => request({ ...options, method: 'TRACE' }),
+ };
+};
diff --git a/packages/sdk/js/src/gen/client/index.ts b/packages/sdk/js/src/gen/client/index.ts
new file mode 100644
index 000000000..5da1f7aee
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/index.ts
@@ -0,0 +1,22 @@
+export type { Auth } from '../core/auth';
+export type { QuerySerializerOptions } from '../core/bodySerializer';
+export {
+ formDataBodySerializer,
+ jsonBodySerializer,
+ urlSearchParamsBodySerializer,
+} from '../core/bodySerializer';
+export { buildClientParams } from '../core/params';
+export { createClient } from './client';
+export type {
+ Client,
+ ClientOptions,
+ Config,
+ CreateClientConfig,
+ Options,
+ OptionsLegacyParser,
+ RequestOptions,
+ RequestResult,
+ ResponseStyle,
+ TDataShape,
+} from './types';
+export { createConfig, mergeHeaders } from './utils';
diff --git a/packages/sdk/js/src/gen/client/types.ts b/packages/sdk/js/src/gen/client/types.ts
new file mode 100644
index 000000000..85295df07
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/types.ts
@@ -0,0 +1,222 @@
+import type { Auth } from '../core/auth';
+import type {
+ Client as CoreClient,
+ Config as CoreConfig,
+} from '../core/types';
+import type { Middleware } from './utils';
+
+export type ResponseStyle = 'data' | 'fields';
+
+export interface Config<T extends ClientOptions = ClientOptions>
+ extends Omit<RequestInit, 'body' | 'headers' | 'method'>,
+ CoreConfig {
+ /**
+ * Base URL for all requests made by this client.
+ */
+ baseUrl?: T['baseUrl'];
+ /**
+ * Fetch API implementation. You can use this option to provide a custom
+ * fetch instance.
+ *
+ * @default globalThis.fetch
+ */
+ fetch?: (request: Request) => ReturnType<typeof fetch>;
+ /**
+ * Please don't use the Fetch client for Next.js applications. The `next`
+ * options won't have any effect.
+ *
+ * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
+ */
+ next?: never;
+ /**
+ * Return the response data parsed in a specified format. By default, `auto`
+ * will infer the appropriate method from the `Content-Type` response header.
+ * You can override this behavior with any of the {@link Body} methods.
+ * Select `stream` if you don't want to parse response data at all.
+ *
+ * @default 'auto'
+ */
+ parseAs?:
+ | 'arrayBuffer'
+ | 'auto'
+ | 'blob'
+ | 'formData'
+ | 'json'
+ | 'stream'
+ | 'text';
+ /**
+ * Should we return only data or multiple fields (data, error, response, etc.)?
+ *
+ * @default 'fields'
+ */
+ responseStyle?: ResponseStyle;
+ /**
+ * Throw an error instead of returning it in the response?
+ *
+ * @default false
+ */
+ throwOnError?: T['throwOnError'];
+}
+
+export interface RequestOptions<
+ TResponseStyle extends ResponseStyle = 'fields',
+ ThrowOnError extends boolean = boolean,
+ Url extends string = string,
+> extends Config<{
+ responseStyle: TResponseStyle;
+ throwOnError: ThrowOnError;
+ }> {
+ /**
+ * Any body that you want to add to your request.
+ *
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
+ */
+ body?: unknown;
+ path?: Record<string, unknown>;
+ query?: Record<string, unknown>;
+ /**
+ * Security mechanism(s) to use for the request.
+ */
+ security?: ReadonlyArray<Auth>;
+ url: Url;
+}
+
+export type RequestResult<
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = boolean,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = ThrowOnError extends true
+ ? Promise<
+ TResponseStyle extends 'data'
+ ? TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData
+ : {
+ data: TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData;
+ request: Request;
+ response: Response;
+ }
+ >
+ : Promise<
+ TResponseStyle extends 'data'
+ ?
+ | (TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData)
+ | undefined
+ : (
+ | {
+ data: TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData;
+ error: undefined;
+ }
+ | {
+ data: undefined;
+ error: TError extends Record<string, unknown>
+ ? TError[keyof TError]
+ : TError;
+ }
+ ) & {
+ request: Request;
+ response: Response;
+ }
+ >;
+
+export interface ClientOptions {
+ baseUrl?: string;
+ responseStyle?: ResponseStyle;
+ throwOnError?: boolean;
+}
+
+type MethodFn = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = 'fields',
+>(
+ options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'>,
+) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
+
+type RequestFn = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = 'fields',
+>(
+ options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'> &
+ Pick<Required<RequestOptions<TResponseStyle, ThrowOnError>>, 'method'>,
+) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
+
+type BuildUrlFn = <
+ TData extends {
+ body?: unknown;
+ path?: Record<string, unknown>;
+ query?: Record<string, unknown>;
+ url: string;
+ },
+>(
+ options: Pick<TData, 'url'> & Options<TData>,
+) => string;
+
+export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn> & {
+ interceptors: Middleware<Request, Response, unknown, RequestOptions>;
+};
+
+/**
+ * The `createClientConfig()` function will be called on client initialization
+ * and the returned object will become the client's initial configuration.
+ *
+ * You may want to initialize your client this way instead of calling
+ * `setConfig()`. This is useful for example if you're using Next.js
+ * to ensure your client always has the correct values.
+ */
+export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
+ override?: Config<ClientOptions & T>,
+) => Config<Required<ClientOptions> & T>;
+
+export interface TDataShape {
+ body?: unknown;
+ headers?: unknown;
+ path?: unknown;
+ query?: unknown;
+ url: string;
+}
+
+type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
+
+export type Options<
+ TData extends TDataShape = TDataShape,
+ ThrowOnError extends boolean = boolean,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = OmitKeys<
+ RequestOptions<TResponseStyle, ThrowOnError>,
+ 'body' | 'path' | 'query' | 'url'
+> &
+ Omit<TData, 'url'>;
+
+export type OptionsLegacyParser<
+ TData = unknown,
+ ThrowOnError extends boolean = boolean,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = TData extends { body?: any }
+ ? TData extends { headers?: any }
+ ? OmitKeys<
+ RequestOptions<TResponseStyle, ThrowOnError>,
+ 'body' | 'headers' | 'url'
+ > &
+ TData
+ : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'url'> &
+ TData &
+ Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'headers'>
+ : TData extends { headers?: any }
+ ? OmitKeys<
+ RequestOptions<TResponseStyle, ThrowOnError>,
+ 'headers' | 'url'
+ > &
+ TData &
+ Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'body'>
+ : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'url'> & TData;
diff --git a/packages/sdk/js/src/gen/client/utils.ts b/packages/sdk/js/src/gen/client/utils.ts
new file mode 100644
index 000000000..a52e67292
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/utils.ts
@@ -0,0 +1,417 @@
+import { getAuthToken } from '../core/auth';
+import type {
+ QuerySerializer,
+ QuerySerializerOptions,
+} from '../core/bodySerializer';
+import { jsonBodySerializer } from '../core/bodySerializer';
+import {
+ serializeArrayParam,
+ serializeObjectParam,
+ serializePrimitiveParam,
+} from '../core/pathSerializer';
+import type { Client, ClientOptions, Config, RequestOptions } from './types';
+
+interface PathSerializer {
+ path: Record<string, unknown>;
+ url: string;
+}
+
+const PATH_PARAM_RE = /\{[^{}]+\}/g;
+
+type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
+type MatrixStyle = 'label' | 'matrix' | 'simple';
+type ArraySeparatorStyle = ArrayStyle | MatrixStyle;
+
+const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
+ let url = _url;
+ const matches = _url.match(PATH_PARAM_RE);
+ if (matches) {
+ for (const match of matches) {
+ let explode = false;
+ let name = match.substring(1, match.length - 1);
+ let style: ArraySeparatorStyle = 'simple';
+
+ if (name.endsWith('*')) {
+ explode = true;
+ name = name.substring(0, name.length - 1);
+ }
+
+ if (name.startsWith('.')) {
+ name = name.substring(1);
+ style = 'label';
+ } else if (name.startsWith(';')) {
+ name = name.substring(1);
+ style = 'matrix';
+ }
+
+ const value = path[name];
+
+ if (value === undefined || value === null) {
+ continue;
+ }
+
+ if (Array.isArray(value)) {
+ url = url.replace(
+ match,
+ serializeArrayParam({ explode, name, style, value }),
+ );
+ continue;
+ }
+
+ if (typeof value === 'object') {
+ url = url.replace(
+ match,
+ serializeObjectParam({
+ explode,
+ name,
+ style,
+ value: value as Record<string, unknown>,
+ valueOnly: true,
+ }),
+ );
+ continue;
+ }
+
+ if (style === 'matrix') {
+ url = url.replace(
+ match,
+ `;${serializePrimitiveParam({
+ name,
+ value: value as string,
+ })}`,
+ );
+ continue;
+ }
+
+ const replaceValue = encodeURIComponent(
+ style === 'label' ? `.${value as string}` : (value as string),
+ );
+ url = url.replace(match, replaceValue);
+ }
+ }
+ return url;
+};
+
+export const createQuerySerializer = <T = unknown>({
+ allowReserved,
+ array,
+ object,
+}: QuerySerializerOptions = {}) => {
+ const querySerializer = (queryParams: T) => {
+ const search: string[] = [];
+ if (queryParams && typeof queryParams === 'object') {
+ for (const name in queryParams) {
+ const value = queryParams[name];
+
+ if (value === undefined || value === null) {
+ continue;
+ }
+
+ if (Array.isArray(value)) {
+ const serializedArray = serializeArrayParam({
+ allowReserved,
+ explode: true,
+ name,
+ style: 'form',
+ value,
+ ...array,
+ });
+ if (serializedArray) search.push(serializedArray);
+ } else if (typeof value === 'object') {
+ const serializedObject = serializeObjectParam({
+ allowReserved,
+ explode: true,
+ name,
+ style: 'deepObject',
+ value: value as Record<string, unknown>,
+ ...object,
+ });
+ if (serializedObject) search.push(serializedObject);
+ } else {
+ const serializedPrimitive = serializePrimitiveParam({
+ allowReserved,
+ name,
+ value: value as string,
+ });
+ if (serializedPrimitive) search.push(serializedPrimitive);
+ }
+ }
+ }
+ return search.join('&');
+ };
+ return querySerializer;
+};
+
+/**
+ * Infers parseAs value from provided Content-Type header.
+ */
+export const getParseAs = (
+ contentType: string | null,
+): Exclude<Config['parseAs'], 'auto'> => {
+ if (!contentType) {
+ // If no Content-Type header is provided, the best we can do is return the raw response body,
+ // which is effectively the same as the 'stream' option.
+ return 'stream';
+ }
+
+ const cleanContent = contentType.split(';')[0]?.trim();
+
+ if (!cleanContent) {
+ return;
+ }
+
+ if (
+ cleanContent.startsWith('application/json') ||
+ cleanContent.endsWith('+json')
+ ) {
+ return 'json';
+ }
+
+ if (cleanContent === 'multipart/form-data') {
+ return 'formData';
+ }
+
+ if (
+ ['application/', 'audio/', 'image/', 'video/'].some((type) =>
+ cleanContent.startsWith(type),
+ )
+ ) {
+ return 'blob';
+ }
+
+ if (cleanContent.startsWith('text/')) {
+ return 'text';
+ }
+
+ return;
+};
+
+export const setAuthParams = async ({
+ security,
+ ...options
+}: Pick<Required<RequestOptions>, 'security'> &
+ Pick<RequestOptions, 'auth' | 'query'> & {
+ headers: Headers;
+ }) => {
+ for (const auth of security) {
+ const token = await getAuthToken(auth, options.auth);
+
+ if (!token) {
+ continue;
+ }
+
+ const name = auth.name ?? 'Authorization';
+
+ switch (auth.in) {
+ case 'query':
+ if (!options.query) {
+ options.query = {};
+ }
+ options.query[name] = token;
+ break;
+ case 'cookie':
+ options.headers.append('Cookie', `${name}=${token}`);
+ break;
+ case 'header':
+ default:
+ options.headers.set(name, token);
+ break;
+ }
+
+ return;
+ }
+};
+
+export const buildUrl: Client['buildUrl'] = (options) => {
+ const url = getUrl({
+ baseUrl: options.baseUrl as string,
+ path: options.path,
+ query: options.query,
+ querySerializer:
+ typeof options.querySerializer === 'function'
+ ? options.querySerializer
+ : createQuerySerializer(options.querySerializer),
+ url: options.url,
+ });
+ return url;
+};
+
+export const getUrl = ({
+ baseUrl,
+ path,
+ query,
+ querySerializer,
+ url: _url,
+}: {
+ baseUrl?: string;
+ path?: Record<string, unknown>;
+ query?: Record<string, unknown>;
+ querySerializer: QuerySerializer;
+ url: string;
+}) => {
+ const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
+ let url = (baseUrl ?? '') + pathUrl;
+ if (path) {
+ url = defaultPathSerializer({ path, url });
+ }
+ let search = query ? querySerializer(query) : '';
+ if (search.startsWith('?')) {
+ search = search.substring(1);
+ }
+ if (search) {
+ url += `?${search}`;
+ }
+ return url;
+};
+
+export const mergeConfigs = (a: Config, b: Config): Config => {
+ const config = { ...a, ...b };
+ if (config.baseUrl?.endsWith('/')) {
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
+ }
+ config.headers = mergeHeaders(a.headers, b.headers);
+ return config;
+};
+
+export const mergeHeaders = (
+ ...headers: Array<Required<Config>['headers'] | undefined>
+): Headers => {
+ const mergedHeaders = new Headers();
+ for (const header of headers) {
+ if (!header || typeof header !== 'object') {
+ continue;
+ }
+
+ const iterator =
+ header instanceof Headers ? header.entries() : Object.entries(header);
+
+ for (const [key, value] of iterator) {
+ if (value === null) {
+ mergedHeaders.delete(key);
+ } else if (Array.isArray(value)) {
+ for (const v of value) {
+ mergedHeaders.append(key, v as string);
+ }
+ } else if (value !== undefined) {
+ // assume object headers are meant to be JSON stringified, i.e. their
+ // content value in OpenAPI specification is 'application/json'
+ mergedHeaders.set(
+ key,
+ typeof value === 'object' ? JSON.stringify(value) : (value as string),
+ );
+ }
+ }
+ }
+ return mergedHeaders;
+};
+
+type ErrInterceptor<Err, Res, Req, Options> = (
+ error: Err,
+ response: Res,
+ request: Req,
+ options: Options,
+) => Err | Promise<Err>;
+
+type ReqInterceptor<Req, Options> = (
+ request: Req,
+ options: Options,
+) => Req | Promise<Req>;
+
+type ResInterceptor<Res, Req, Options> = (
+ response: Res,
+ request: Req,
+ options: Options,
+) => Res | Promise<Res>;
+
+class Interceptors<Interceptor> {
+ _fns: (Interceptor | null)[];
+
+ constructor() {
+ this._fns = [];
+ }
+
+ clear() {
+ this._fns = [];
+ }
+
+ getInterceptorIndex(id: number | Interceptor): number {
+ if (typeof id === 'number') {
+ return this._fns[id] ? id : -1;
+ } else {
+ return this._fns.indexOf(id);
+ }
+ }
+ exists(id: number | Interceptor) {
+ const index = this.getInterceptorIndex(id);
+ return !!this._fns[index];
+ }
+
+ eject(id: number | Interceptor) {
+ const index = this.getInterceptorIndex(id);
+ if (this._fns[index]) {
+ this._fns[index] = null;
+ }
+ }
+
+ update(id: number | Interceptor, fn: Interceptor) {
+ const index = this.getInterceptorIndex(id);
+ if (this._fns[index]) {
+ this._fns[index] = fn;
+ return id;
+ } else {
+ return false;
+ }
+ }
+
+ use(fn: Interceptor) {
+ this._fns = [...this._fns, fn];
+ return this._fns.length - 1;
+ }
+}
+
+// `createInterceptors()` response, meant for external use as it does not
+// expose internals
+export interface Middleware<Req, Res, Err, Options> {
+ error: Pick<
+ Interceptors<ErrInterceptor<Err, Res, Req, Options>>,
+ 'eject' | 'use'
+ >;
+ request: Pick<Interceptors<ReqInterceptor<Req, Options>>, 'eject' | 'use'>;
+ response: Pick<
+ Interceptors<ResInterceptor<Res, Req, Options>>,
+ 'eject' | 'use'
+ >;
+}
+
+// do not add `Middleware` as return type so we can use _fns internally
+export const createInterceptors = <Req, Res, Err, Options>() => ({
+ error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),
+ request: new Interceptors<ReqInterceptor<Req, Options>>(),
+ response: new Interceptors<ResInterceptor<Res, Req, Options>>(),
+});
+
+const defaultQuerySerializer = createQuerySerializer({
+ allowReserved: false,
+ array: {
+ explode: true,
+ style: 'form',
+ },
+ object: {
+ explode: true,
+ style: 'deepObject',
+ },
+});
+
+const defaultHeaders = {
+ 'Content-Type': 'application/json',
+};
+
+export const createConfig = <T extends ClientOptions = ClientOptions>(
+ override: Config<Omit<ClientOptions, keyof T> & T> = {},
+): Config<Omit<ClientOptions, keyof T> & T> => ({
+ ...jsonBodySerializer,
+ headers: defaultHeaders,
+ parseAs: 'auto',
+ querySerializer: defaultQuerySerializer,
+ ...override,
+});