UNPKG

@hey-api/openapi-ts

Version:

🚀 The OpenAPI to TypeScript codegen. Generate clients, SDKs, validators, and more.

214 lines (187 loc) • 5.57 kB
import { useAsyncData, useFetch, useLazyAsyncData, useLazyFetch, } from 'nuxt/app'; import { reactive, ref, watch } from 'vue'; import { createSseClient } from '../core/serverSentEvents'; import type { Client, Config, RequestOptions } from './types'; import { buildUrl, createConfig, executeFetchFn, mergeConfigs, mergeHeaders, mergeInterceptors, serializeBody, setAuthParams, unwrapRefs, } from './utils'; 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 beforeRequest = async (options: RequestOptions) => { const opts = { ..._config, ...options, $fetch: options.$fetch ?? _config.$fetch ?? $fetch, headers: mergeHeaders(_config.headers, options.headers), onRequest: mergeInterceptors(_config.onRequest, options.onRequest), onResponse: mergeInterceptors(_config.onResponse, options.onResponse), }; if (opts.security) { await setAuthParams({ ...opts, security: opts.security, }); } if (opts.requestValidator) { await opts.requestValidator(opts); } const url = buildUrl(opts); return { opts, url }; }; const request: Client['request'] = ({ asyncDataOptions, composable, ...options }) => { const key = options.key; const opts = { ..._config, ...options, $fetch: options.$fetch ?? _config.$fetch ?? $fetch, headers: mergeHeaders(_config.headers, options.headers), onRequest: mergeInterceptors(_config.onRequest, options.onRequest), onResponse: mergeInterceptors(_config.onResponse, options.onResponse), }; const { requestValidator, responseTransformer, responseValidator, security, } = opts; if (requestValidator || security) { // auth must happen in interceptors otherwise we'd need to require // asyncContext enabled // https://nuxt.com/docs/guide/going-further/experimental-features#asynccontext opts.onRequest = [ async ({ options }) => { if (security) { await setAuthParams({ auth: opts.auth, headers: options.headers, query: options.query, security, }); } if (requestValidator) { await requestValidator({ ...options, // @ts-expect-error body: options.rawBody, }); } }, ...opts.onRequest, ]; } if (responseTransformer || responseValidator) { opts.onResponse = [ ...opts.onResponse, async ({ options, response }) => { if (options.responseType && options.responseType !== 'json') { return; } if (!response.ok) { return; } if (responseValidator) { await responseValidator(response._data); } if (responseTransformer) { response._data = await responseTransformer(response._data); } }, ]; } // 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 fetchFn = opts.$fetch; if (composable === '$fetch') { return executeFetchFn( // @ts-expect-error opts, fetchFn, ); } if (composable === 'useFetch' || composable === 'useLazyFetch') { opts.rawBody = opts.body; const bodyParams = reactive({ body: opts.body, bodySerializer: opts.bodySerializer, }); const body = ref(serializeBody(opts)); opts.body = body; watch(bodyParams, (changed) => { body.value = serializeBody(changed); }); return composable === 'useLazyFetch' ? useLazyFetch(() => buildUrl(opts), opts) : useFetch(() => buildUrl(opts), opts); } const handler: any = () => executeFetchFn( // @ts-expect-error opts, fetchFn, ); if (composable === 'useAsyncData') { return key ? useAsyncData(key, handler, asyncDataOptions) : useAsyncData(handler, asyncDataOptions); } if (composable === 'useLazyAsyncData') { return key ? useLazyAsyncData(key, handler, asyncDataOptions) : useLazyAsyncData(handler, asyncDataOptions); } return undefined as any; }; 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({ ...unwrapRefs(opts), body: opts.body as BodyInit | null | undefined, method, signal: unwrapRefs(opts.signal) as AbortSignal, url, }); }; return fn; }; return { buildUrl, connect: makeMethod('CONNECT'), delete: makeMethod('DELETE'), get: makeMethod('GET'), getConfig, head: makeMethod('HEAD'), options: makeMethod('OPTIONS'), patch: makeMethod('PATCH'), post: makeMethod('POST'), put: makeMethod('PUT'), request, setConfig, trace: makeMethod('TRACE'), } as Client; };