return-fetch
Version:
A very light and simple library to extend fetch by implementing request, response interceptors.
1 lines • 8.35 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["/**\n * A simple and powerful high order function to extend fetch.\n *\n * @packageDocumentation\n */\n\n/**\n * Arguments of fetch function.\n *\n * @throws {Error} if a first argument of fetch is `Request` object. only string and URL are supported.\n * @see {fetch, RequestInfo, Request}\n *\n * @public\n */\nexport type FetchArgs = [string | URL, RequestInit | undefined];\n\n/**\n * Type of `returnFetch` function.\n * It is useful for whom want to write customized returnFetch function.\n *\n * @public\n */\nexport type ReturnFetch = typeof returnFetch;\n\n/**\n * Options of `returnFetch` function.\n *\n * @public\n */\nexport type ReturnFetchDefaultOptions = {\n /**\n * `fetch` function to be used in `returnFetch` function.\n * If not provided, `fetch` function in global scope will be used.\n * Any fetch implementation can be used, such as `node-fetch`, `cross-fetch`, `isomorphic-fetch`, etc.\n *\n * a `fetch` function created by `returnFetch` also can be used here.\n *\n * @public\n */\n fetch?: ReturnType<ReturnFetch>;\n /**\n * Base URL of fetch. It will be used when the first argument of fetch is relative URL.\n *\n * @public\n */\n baseUrl?: string | URL;\n /**\n * Default headers of fetch. It will be used when the second argument of fetch does not have `headers` property.\n * If it is provided and `headers` also provided when calling a `fetch`, headers will be merged.\n * Priority of headers is `requestInit.headers` > `defaultOptions.headers`. Duplicated headers will be overwritten.\n *\n * @public\n */\n headers?: HeadersInit;\n interceptors?: {\n /**\n * Request interceptor. It will be called before request.\n *\n * @param requestArgs Arguments of fetch function.\n * @param fetch the `fetch` you provided at {@link ReturnFetchDefaultOptions['fetch']}\n *\n * @public\n */\n request?: (\n requestArgs: FetchArgs,\n fetch: NonNullable<ReturnFetchDefaultOptions[\"fetch\"]>,\n ) => Promise<FetchArgs>;\n /**\n * Response interceptor. It will be called after response.\n *\n * @param response Response object received from fetch function.\n * @param requestArgs Arguments of fetch function.\n * @param fetch the `fetch` you provided at {@link ReturnFetchDefaultOptions['fetch']}\n *\n * @public\n */\n response?: (\n response: Response,\n requestArgs: FetchArgs,\n fetch: NonNullable<ReturnFetchDefaultOptions[\"fetch\"]>,\n ) => Promise<Response>;\n };\n};\n\nconst applyDefaultOptions = (\n [input, requestInit]: FetchArgs,\n defaultOptions?: ReturnFetchDefaultOptions,\n): FetchArgs => {\n const headers = new Headers(defaultOptions?.headers);\n new Headers(requestInit?.headers).forEach((value, key) => {\n headers.set(key, value);\n });\n\n let inputToReturn: FetchArgs[0] = input;\n if (defaultOptions?.baseUrl) {\n inputToReturn = new URL(input, defaultOptions.baseUrl);\n }\n\n return [\n inputToReturn,\n {\n ...requestInit,\n headers,\n },\n ];\n};\n\n// To handle Request object we need to read body as ArrayBuffer.\n// If you have a better way, please let me know.\nconst mergeRequestObjectWithRequestInit = async (\n request: Request,\n requestInit?: RequestInit,\n): Promise<RequestInit> => {\n const mergedRequest = new Request(request, requestInit);\n\n const body = await mergedRequest.arrayBuffer();\n\n return {\n method: mergedRequest.method,\n headers: mergedRequest.headers,\n body: body.byteLength ? body : undefined,\n referrer: mergedRequest.referrer,\n referrerPolicy: mergedRequest.referrerPolicy,\n mode: mergedRequest.mode,\n cache: mergedRequest.cache,\n redirect: mergedRequest.redirect,\n credentials: mergedRequest.credentials,\n integrity: mergedRequest.integrity,\n keepalive: mergedRequest.keepalive,\n signal: mergedRequest.signal,\n window: requestInit?.window,\n };\n};\n\nconst normalizeArgs = async (\n ...args: Parameters<typeof fetch>\n): Promise<FetchArgs> => {\n let input: string | URL;\n let requestInit: RequestInit | undefined;\n if (args[0] instanceof Request) {\n input = args[0].url;\n requestInit = await mergeRequestObjectWithRequestInit(args[0], args[1]);\n } else {\n input = args[0];\n requestInit = args[1];\n }\n\n return [input, requestInit];\n};\n\nconst returnFetch =\n (defaultOptions?: ReturnFetchDefaultOptions) =>\n async (...args: Parameters<typeof fetch>): Promise<Response> => {\n const defaultOptionAppliedArgs = applyDefaultOptions(\n await normalizeArgs(...args),\n defaultOptions,\n );\n\n // apply request interceptor\n const fetchProvided = defaultOptions?.fetch || fetch;\n let requestInterceptorAppliedArgs: FetchArgs;\n if (defaultOptions?.interceptors?.request) {\n requestInterceptorAppliedArgs =\n await defaultOptions?.interceptors?.request?.(\n defaultOptionAppliedArgs,\n fetchProvided,\n );\n } else {\n requestInterceptorAppliedArgs = defaultOptionAppliedArgs;\n }\n\n // ajax call\n const response = await fetchProvided(...requestInterceptorAppliedArgs);\n\n // apply response interceptor\n return (\n defaultOptions?.interceptors?.response?.(\n response,\n requestInterceptorAppliedArgs,\n fetchProvided,\n ) || response\n );\n };\n\nexport default returnFetch;\n"],"names":["normalizeArgs","args","input","requestInit","_temp2","slice","call","arguments","_temp","Request","url","Promise","resolve","request","mergedRequest","arrayBuffer","then","body","method","headers","byteLength","undefined","referrer","referrerPolicy","mode","cache","redirect","credentials","integrity","keepalive","signal","window","e","reject","mergeRequestObjectWithRequestInit","_mergeRequestObjectWi","defaultOptions","apply","_normalizeArgs","_temp4","fetchProvided","requestInterceptorAppliedArgs","response","_defaultOptions$inter2","interceptors","defaultOptionAppliedArgs","_ref","Headers","forEach","value","key","set","inputToReturn","baseUrl","URL","_extends","applyDefaultOptions","fetch","_temp3","_defaultOptions$inter3","_defaultOptions$inter4","_defaultOptions$inter"],"mappings":"oOAoFA,IAkDMA,EAAA,WAEkB,IAAA,IADnBC,EAECC,EACAC,EAFkBC,EAAAA,WAWtB,MAAO,CAACF,EAAOC,EAAa,EAZzBF,EAA8B,GAAAI,MAAAC,KAAAC,WAGQ,IAAAC,EACrCP,WAAAA,GAAAA,EAAK,aAAcQ,QACD,OAApBP,EAAQD,EAAK,GAAGS,IAAIC,QAAAC,iBA9BtBC,EACAV,GACwB,IACxB,IAAMW,EAAgB,IAAIL,QAAQI,EAASV,GAAa,OAAAQ,QAAAC,QAErCE,EAAcC,eAAaC,KAAxCC,SAAAA,GAEN,MAAO,CACLC,OAAQJ,EAAcI,OACtBC,QAASL,EAAcK,QACvBF,KAAMA,EAAKG,WAAaH,OAAOI,EAC/BC,SAAUR,EAAcQ,SACxBC,eAAgBT,EAAcS,eAC9BC,KAAMV,EAAcU,KACpBC,MAAOX,EAAcW,MACrBC,SAAUZ,EAAcY,SACxBC,YAAab,EAAca,YAC3BC,UAAWd,EAAcc,UACzBC,UAAWf,EAAce,UACzBC,OAAQhB,EAAcgB,OACtBC,OAAmB,MAAX5B,OAAW,EAAXA,EAAa4B,OACrB,EACJ,CAAC,MAAAC,GAAA,OAAArB,QAAAsB,OAAAD,EAAA,CAAA,CASuBE,CAAkCjC,EAAK,GAAIA,EAAK,KAAGe,KAAAmB,SAAAA,GAAvEhC,EAAWgC,CAA6D,GAExEjC,EAAQD,EAAK,GACbE,EAAcF,EAAK,GALjBA,UAKoBU,QAAAC,QAAAJ,GAAAA,EAAAQ,KAAAR,EAAAQ,KAAAZ,GAAAA,IAI1B,CAAC,MAAA4B,GAAArB,OAAAA,QAAAsB,OAAAD,EAAA,CAAA,iBAGC,SAACI,GAC8D,OAAA,WAAA,IAAAzB,OAAAA,QAAAC,QAErDZ,EAAaqC,gBAAAhC,MAAAC,KAFwCC,aAE/BS,KAAAsB,SAAAA,GAAAC,SAAAA,IAAA5B,OAAAA,QAAAC,QAkBP4B,EAAaH,WAAA,EAAII,IAA8BzB,cAAhE0B,GAAQ,IAAAC,EAGd,OACgB,MAAdP,GAA4B,OAAdO,EAAdP,EAAgBQ,eAAhBD,MAAAA,EAA8BD,cAA9BC,EAAAA,EAA8BD,SAC5BA,EACAD,EACAD,KACGE,CACL,EA5BF,CAAA,IAOID,EAPEI,EArEkB,SAAHC,EAEvBV,GACa,IAFZlC,EAAK4C,EAAA,GAAE3C,EAAW2C,EAAA,GAGb3B,EAAU,IAAI4B,cAAQX,SAAAA,EAAgBjB,SAC5C,IAAI4B,QAAmB,MAAX5C,OAAW,EAAXA,EAAagB,SAAS6B,QAAQ,SAACC,EAAOC,GAChD/B,EAAQgC,IAAID,EAAKD,EACnB,GAEA,IAAIG,EAA8BlD,EAKlC,OAJkB,MAAdkC,GAAAA,EAAgBiB,UAClBD,EAAgB,IAAIE,IAAIpD,EAAOkC,EAAeiB,UAGzC,CACLD,EAAaG,EAAA,CAAA,EAERpD,EAAW,CACdgB,QAAAA,IAGN,CAgDqCqC,CAAmBlB,EAElDF,GAIII,GAAgBJ,MAAAA,OAAAA,EAAAA,EAAgBqB,QAASA,MACFC,WAAAC,GACJC,IAAAA,EADI,GAC3B,MAAdxB,GAAAuB,OAAcA,EAAdvB,EAAgBQ,eAAhBe,EAA8B9C,QAAOF,OAAAA,QAAAC,QAEjB,MAAdwB,GAAAwB,OAAcA,EAAdxB,EAAgBQ,eAAhBgB,MAAAA,EAA8B/C,aAA9B+C,EAAAA,EAA8B/C,QAClCgC,EACAL,IACDxB,KAAA6C,SAAAA,GAJHpB,EAA6BoB,CAIzB,GAEJpB,EAAgCI,CAAyB,IAAA,OAAAa,GAAAA,EAAA1C,KAAA0C,EAAA1C,KAAAuB,GAAAA,GAAA,EAc7D,CAAC,MAAAP,GAAArB,OAAAA,QAAAsB,OAAAD,EAEH,CAAA,CAAA"}