@openapi-qraft/react 2.0.0-next.10 → 2.0.0-next.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @openapi-qraft/react
2
2
 
3
+ ## 2.0.0-next.12
4
+
5
+ ### Minor Changes
6
+
7
+ - a50253a: Responses with the `text/plain` content type are now always processed as plain text, without attempting to fallback to `JSON.parse`.
8
+
9
+ ### Patch Changes
10
+
11
+ - @openapi-qraft/tanstack-query-react-types@2.0.0-next.12
12
+
13
+ ## 2.0.0-next.11
14
+
15
+ ### Patch Changes
16
+
17
+ - 3ed94dc: Implemented support for requests with multiple media types. Now, if an endpoint accepts more than one media type (e.g., JSON and form-data), types will be generated to account for all possible cases, ensuring compatibility with both JSON and form-data input formats.
18
+ - Updated dependencies [3ed94dc]
19
+ - @openapi-qraft/tanstack-query-react-types@2.0.0-next.11
20
+
3
21
  ## 2.0.0-next.10
4
22
 
5
23
  ### Patch Changes
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var responseUtils = require('./responseUtils.cjs');
4
+
3
5
  /**
4
6
  * This function is used to make a request to a specified endpoint.
5
7
  *
@@ -21,7 +23,7 @@
21
23
  }
22
24
  /**
23
25
  * This function is used to make a request to a specified endpoint.
24
- * It's needed to create a custom `requestFn` with a custom `urlSerializer`
26
+ * It's necessary to create a custom `requestFn` with a custom `urlSerializer`
25
27
  * and `bodySerializer`, with the tree-shaking of the default `requestFn`
26
28
  * and its serializers.
27
29
  *
@@ -36,19 +38,16 @@
36
38
  * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.
37
39
  */ async function baseRequestFn(requestSchema, requestInfo, options) {
38
40
  const { parameters, headers, body, ...requestInfoRest } = requestInfo;
39
- const requestBody = options.bodySerializer(requestSchema, requestInfo);
41
+ const requestPayload = options.bodySerializer(requestSchema, body);
40
42
  const baseFetch = options.fetch ?? fetch;
41
43
  return baseFetch(options.urlSerializer(requestSchema, requestInfo), {
42
44
  method: requestSchema.method.toUpperCase(),
43
- body: requestBody,
45
+ body: requestPayload?.body,
44
46
  headers: mergeHeaders({
45
- Accept: 'application/json',
46
- 'Content-Type': requestSchema.mediaType ?? getBodyContentType(body)
47
- }, headers, parameters?.header, requestBody instanceof FormData ? {
48
- 'Content-Type': null
49
- } : undefined),
47
+ Accept: 'application/json'
48
+ }, requestPayload?.headers, headers, parameters?.header),
50
49
  ...requestInfoRest
51
- }).then(processResponse).catch(resolveResponse);
50
+ }).then(responseUtils.processResponse).catch(responseUtils.resolveResponse);
52
51
  }
53
52
  /**
54
53
  * Serializes the given schema and request payload into a URL string.
@@ -121,23 +120,68 @@ function mergeHeaders(...allHeaders) {
121
120
  }
122
121
  return headers;
123
122
  }
124
- function bodySerializer(schema, info) {
125
- if (info.body === undefined) return;
126
- if (schema.method === 'get' || schema.method === 'head' || schema.method === 'options') return;
127
- if (schema.mediaType?.includes('/form-data')) return getRequestBodyFormData(info);
128
- if (!schema.mediaType?.includes('/json') && (typeof info.body === 'string' || info.body instanceof Blob || info.body instanceof FormData)) {
129
- return info.body;
123
+ function bodySerializer(schema, body) {
124
+ if (schema.method === 'get' || schema.method === 'head' || schema.method === 'options') return undefined;
125
+ if (body === undefined || body === null) return undefined;
126
+ if (typeof body === 'string') {
127
+ return {
128
+ body,
129
+ headers: {
130
+ 'Content-Type': // prefer text/* media type
131
+ schema.mediaType?.find((mediaType)=>mediaType.includes('text/')) ?? // prefer JSON media type, assume that body is serialized as JSON
132
+ schema.mediaType?.find((mediaType)=>mediaType.includes('/json')) ?? 'text/plain'
133
+ }
134
+ };
135
+ }
136
+ if (body instanceof FormData) {
137
+ return {
138
+ body,
139
+ headers: {
140
+ // remove `Content-Type` if the serialized body is FormData;
141
+ // the browser will correctly set Content-Type & boundary expression
142
+ 'Content-Type': null
143
+ }
144
+ };
145
+ }
146
+ if (body instanceof Blob) {
147
+ return {
148
+ body,
149
+ headers: {
150
+ 'Content-Type': body.type || schema.mediaType?.find((mediaType)=>!(mediaType.includes('text/') && mediaType.includes('/form-data') && mediaType.includes('/json'))) || 'application/octet-stream'
151
+ }
152
+ };
153
+ }
154
+ let jsonMediaType = null;
155
+ let formDataMediaType = null;
156
+ if (schema.mediaType) {
157
+ for(let i = 0; i < schema.mediaType.length; i++){
158
+ const mediaType = schema.mediaType[i];
159
+ if (mediaType.includes('/json')) jsonMediaType = mediaType;
160
+ else if (mediaType.includes('/form-data')) formDataMediaType = mediaType;
161
+ }
162
+ }
163
+ if (formDataMediaType) {
164
+ if (!jsonMediaType || // Prefer FormData serialization if one of the fields is a Blob
165
+ Object.values(body).some((value)=>value instanceof Blob)) {
166
+ return {
167
+ body: getRequestBodyFormData(body),
168
+ headers: {
169
+ // remove `Content-Type` if the serialized body is FormData;
170
+ // the browser will correctly set Content-Type & boundary expression
171
+ 'Content-Type': null
172
+ }
173
+ };
174
+ }
130
175
  }
131
- return JSON.stringify(info.body);
176
+ return {
177
+ body: JSON.stringify(body),
178
+ headers: {
179
+ 'Content-Type': jsonMediaType ?? 'application/json'
180
+ }
181
+ };
132
182
  }
133
- function getRequestBodyFormData({ body }) {
183
+ function getRequestBodyFormData(body) {
134
184
  if (body instanceof FormData) return body;
135
- if (body === null) return;
136
- if (body instanceof Blob) throw new Error('Blob not supported in form-data');
137
- if (body instanceof ArrayBuffer) throw new Error('ArrayBuffer not supported in form-data');
138
- if (body instanceof URLSearchParams) throw new Error('URLSearchParams not supported in form-data');
139
- if (body instanceof ReadableStream) throw new Error('ReadableStream not supported in form-data');
140
- if (typeof body === 'string') throw new Error('String not supported in form-data');
141
185
  if (typeof body !== 'object') throw new Error(`Unsupported body type ${typeof body} in form-data.`);
142
186
  const formData = new FormData();
143
187
  const process = (key, value)=>{
@@ -156,47 +200,6 @@ function getRequestBodyFormData({ body }) {
156
200
  });
157
201
  return formData;
158
202
  }
159
- function getBodyContentType(body) {
160
- if (!body) return;
161
- if (body instanceof Blob) return body.type || 'application/octet-stream';
162
- if (typeof body === 'string') return 'text/plain';
163
- if (!(body instanceof FormData)) return 'application/json';
164
- }
165
- async function processResponse(response) {
166
- if (response.status === 204 || response.headers.get('Content-Length') === '0') return response.ok ? {
167
- data: {},
168
- response
169
- } : {
170
- error: {},
171
- response
172
- };
173
- if (isJsonResponse(response)) {
174
- // clone response before parsing every time to allow multiple reads
175
- const jsonResponse = response.clone().json();
176
- return resolveResponse(response, response.ok ? jsonResponse : Promise.reject(await jsonResponse));
177
- }
178
- const jsonResponse = new Promise((resolve, reject)=>// attempt to parse JSON for successful responses, otherwise fail
179
- response.clone().text().then(JSON.parse).then(resolve, reject));
180
- return resolveResponse(response, response.ok ? jsonResponse : Promise.reject(await jsonResponse));
181
- }
182
- function isJsonResponse(response) {
183
- const contentType = response.headers.get('Content-Type')?.toLowerCase();
184
- return contentType?.includes('/json') || contentType?.includes('+json');
185
- }
186
- function resolveResponse(responseToReturn, responsePromise) {
187
- if (!responsePromise) return Promise.reject({
188
- error: responseToReturn,
189
- response: undefined,
190
- data: undefined
191
- });
192
- return responsePromise.then((data)=>({
193
- data,
194
- response: responseToReturn
195
- })).catch((error)=>({
196
- error,
197
- response: responseToReturn
198
- }));
199
- }
200
203
 
201
204
  exports.baseRequestFn = baseRequestFn;
202
205
  exports.bodySerializer = bodySerializer;
@@ -1 +1 @@
1
- {"version":3,"file":"requestFn.cjs","sources":["../../../src/lib/requestFn.ts"],"sourcesContent":["import type {\n HeadersOptions,\n OperationSchema,\n RequestFnInfo,\n RequestFnOptions,\n RequestFnResponse,\n} from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * This function is used to make a request to a specified endpoint.\n *\n * @template T The expected return type of the request.\n *\n * @param schema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param [options] Optional. Additional options for the request. It includes custom urlSerializer, bodySerializer, and fetch function.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function requestFn<TData, TError>(\n schema: OperationSchema,\n requestInfo: RequestFnInfo,\n options?: RequestFnOptions\n): Promise<RequestFnResponse<TData, TError>> {\n return baseRequestFn<TData, TError>(schema, requestInfo, {\n urlSerializer,\n bodySerializer,\n ...options,\n });\n}\n\n/**\n * This function is used to make a request to a specified endpoint.\n * It's needed to create a custom `requestFn` with a custom `urlSerializer`\n * and `bodySerializer`, with the tree-shaking of the default `requestFn`\n * and its serializers.\n *\n * @template T The expected return type of the request.\n *\n * @param requestSchema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param options The options for the request. It includes urlSerializer, bodySerializer, and fetch function. The 'urlSerializer' and 'bodySerializer' are required.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function baseRequestFn<TData, TError>(\n requestSchema: OperationSchema,\n requestInfo: RequestFnInfo,\n options: WithRequired<RequestFnOptions, 'urlSerializer' | 'bodySerializer'>\n): Promise<RequestFnResponse<TData, TError>> {\n const { parameters, headers, body, ...requestInfoRest } = requestInfo;\n\n const requestBody = options.bodySerializer(requestSchema, requestInfo);\n\n const baseFetch = options.fetch ?? fetch;\n\n return baseFetch(options.urlSerializer(requestSchema, requestInfo), {\n method: requestSchema.method.toUpperCase(),\n body: requestBody,\n headers: mergeHeaders(\n {\n Accept: 'application/json',\n 'Content-Type': requestSchema.mediaType ?? getBodyContentType(body),\n },\n headers,\n parameters?.header,\n requestBody instanceof FormData\n ? // remove `Content-Type` if the serialized body is FormData; the browser will correctly set Content-Type & boundary expression\n { 'Content-Type': null }\n : undefined\n ),\n ...requestInfoRest,\n })\n .then(processResponse as typeof processResponse<TData, TError>)\n .catch(resolveResponse as typeof resolveResponse<TData, TError>);\n}\n\n/**\n * Serializes the given schema and request payload into a URL string.\n *\n * This function is implemented according to the URI Template standard\n * defined in RFC 6570. It supports the expansion of path and query parameters,\n * correctly handling empty arrays, `null`, and `undefined` values by ignoring\n * them during the expansion process, as specified by the standard.\n *\n * For more information, refer to the official documentation:\n * https://datatracker.ietf.org/doc/html/rfc6570\n *\n * @param schema - The operation schema containing the URL template and method.\n * @param info - The request payload including baseUrl, path parameters, and query parameters.\n * @returns The fully constructed URL string.\n */\nexport function urlSerializer(\n schema: OperationSchema,\n info: Pick<RequestFnInfo, 'baseUrl' | 'parameters'>\n): string {\n const path = schema.url.replace(\n /{(.*?)}/g,\n (substring: string, group: string) => {\n if (\n info.parameters?.path &&\n Object.prototype.hasOwnProperty.call(info.parameters.path, group)\n ) {\n return encodeURI(String(info.parameters?.path[group]));\n }\n return substring;\n }\n );\n\n const baseUrl = info.baseUrl ?? '';\n\n if (info.parameters?.query) {\n return `${baseUrl}${path}${getQueryString(info.parameters.query)}`;\n }\n\n return `${baseUrl}${path}`;\n}\n\nfunction getQueryString(params: Record<string, any>): string {\n const qs: string[] = [];\n\n const append = (key: string, value: any) => {\n qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n };\n\n const process = (key: string, value: any) => {\n if (typeof value === 'undefined' || value === null) return;\n\n if (Array.isArray(value)) {\n value.forEach((v) => {\n process(key, v);\n });\n } else if (typeof value === 'object') {\n Object.entries(value).forEach(([k, v]) => {\n process(`${key}[${k}]`, v);\n });\n } else {\n append(key, value);\n }\n };\n\n Object.entries(params).forEach(([key, value]) => {\n process(key, value);\n });\n\n if (qs.length > 0) {\n return `?${qs.join('&')}`;\n }\n\n return '';\n}\n\nexport function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]) {\n const headers = new Headers();\n\n for (const headerSet of allHeaders) {\n if (!headerSet || typeof headerSet !== 'object') {\n continue;\n }\n\n const headersIterator =\n headerSet instanceof Headers\n ? headerSet.entries()\n : Object.entries(headerSet);\n\n for (const [headerKey, headerValue] of headersIterator) {\n if (headerValue === null) {\n headers.delete(headerKey);\n } else if (headerValue !== undefined) {\n headers.set(headerKey, headerValue);\n }\n }\n }\n\n return headers;\n}\n\nexport function bodySerializer(schema: OperationSchema, info: RequestFnInfo) {\n if (info.body === undefined) return;\n\n if (\n schema.method === 'get' ||\n schema.method === 'head' ||\n schema.method === 'options'\n )\n return;\n\n if (schema.mediaType?.includes('/form-data'))\n return getRequestBodyFormData(info);\n\n if (\n !schema.mediaType?.includes('/json') &&\n (typeof info.body === 'string' ||\n info.body instanceof Blob ||\n info.body instanceof FormData)\n ) {\n return info.body;\n }\n\n return JSON.stringify(info.body);\n}\n\nfunction getRequestBodyFormData({\n body,\n}: Pick<RequestFnInfo, 'body'>): FormData | undefined {\n if (body instanceof FormData) return body;\n if (body === null) return;\n\n if (body instanceof Blob) throw new Error('Blob not supported in form-data');\n if (body instanceof ArrayBuffer)\n throw new Error('ArrayBuffer not supported in form-data');\n if (body instanceof URLSearchParams)\n throw new Error('URLSearchParams not supported in form-data');\n if (body instanceof ReadableStream)\n throw new Error('ReadableStream not supported in form-data');\n if (typeof body === 'string')\n throw new Error('String not supported in form-data');\n if (typeof body !== 'object')\n throw new Error(`Unsupported body type ${typeof body} in form-data.`);\n\n const formData = new FormData();\n\n const process = (key: string, value: any) => {\n if (typeof value === 'string' || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, JSON.stringify(value));\n }\n };\n\n Object.entries(body)\n .filter(([_, value]) => typeof value !== 'undefined' && value !== null)\n .forEach(([key, value]) => {\n if (Array.isArray(value)) {\n value.forEach((v) => process(key, v));\n } else {\n process(key, value);\n }\n });\n\n return formData;\n}\n\nfunction getBodyContentType(body: RequestFnInfo['body']) {\n if (!body) return;\n if (body instanceof Blob) return body.type || 'application/octet-stream';\n if (typeof body === 'string') return 'text/plain';\n if (!(body instanceof FormData)) return 'application/json';\n}\n\nasync function processResponse<TData, TError>(\n response: Response\n): Promise<RequestFnResponse<TData, TError>> {\n if (response.status === 204 || response.headers.get('Content-Length') === '0')\n return (\n response.ok ? { data: {}, response } : { error: {}, response }\n ) as RequestFnResponse<TData, TError>;\n\n if (isJsonResponse(response)) {\n // clone response before parsing every time to allow multiple reads\n const jsonResponse = response.clone().json();\n return resolveResponse(\n response,\n response.ok ? jsonResponse : Promise.reject(await jsonResponse)\n );\n }\n\n const jsonResponse = new Promise<TData>((resolve, reject) =>\n // attempt to parse JSON for successful responses, otherwise fail\n response.clone().text().then(JSON.parse).then(resolve, reject)\n );\n\n return resolveResponse(\n response,\n response.ok ? jsonResponse : Promise.reject(await jsonResponse)\n );\n}\n\nfunction isJsonResponse(response: Response) {\n const contentType = response.headers.get('Content-Type')?.toLowerCase();\n return contentType?.includes('/json') || contentType?.includes('+json');\n}\n\nfunction resolveResponse<TData, TError>(\n error: Error\n): Promise<RequestFnResponse<TData, TError>>;\nfunction resolveResponse<TData, TError>(\n responseToReturn: Response,\n responsePromise: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>>;\nfunction resolveResponse<TData, TError>(\n responseToReturn: Response | Error,\n responsePromise?: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>> {\n if (!responsePromise)\n return Promise.reject({\n error: responseToReturn,\n response: undefined,\n data: undefined,\n });\n\n return responsePromise\n .then(\n (data) =>\n ({ data, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n )\n .catch(\n (error) =>\n ({ error, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n );\n}\n\ntype WithRequired<T, K extends keyof T> = T & {\n [_ in K]: {};\n};\n\nexport type {\n RequestFn,\n RequestFnResponse,\n HeadersOptions,\n RequestFnOptions,\n RequestFnInfo,\n OperationSchema,\n} from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * @deprecated use `RequestFnInfo` instead\n */\nexport type RequestFnPayload = RequestFnInfo;\n"],"names":["requestFn","schema","requestInfo","options","baseRequestFn","urlSerializer","bodySerializer","requestSchema","parameters","headers","body","requestInfoRest","requestBody","baseFetch","fetch","method","toUpperCase","mergeHeaders","Accept","mediaType","getBodyContentType","header","FormData","undefined","then","processResponse","catch","resolveResponse","info","path","url","replace","substring","group","Object","prototype","hasOwnProperty","call","encodeURI","String","baseUrl","query","getQueryString","params","qs","append","key","value","push","encodeURIComponent","process","Array","isArray","forEach","v","entries","k","length","join","allHeaders","Headers","headerSet","headersIterator","headerKey","headerValue","delete","set","includes","getRequestBodyFormData","Blob","JSON","stringify","Error","ArrayBuffer","URLSearchParams","ReadableStream","formData","filter","_","type","response","status","get","ok","data","error","isJsonResponse","jsonResponse","clone","json","Promise","reject","resolve","text","parse","contentType","toLowerCase","responseToReturn","responsePromise"],"mappings":"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"}
1
+ {"version":3,"file":"requestFn.cjs","sources":["../../../src/lib/requestFn.ts"],"sourcesContent":["import type {\n HeadersOptions,\n OperationSchema,\n RequestFnInfo,\n RequestFnOptions,\n RequestFnResponse,\n} from '@openapi-qraft/tanstack-query-react-types';\nimport { processResponse, resolveResponse } from './responseUtils.js';\n\n/**\n * This function is used to make a request to a specified endpoint.\n *\n * @template T The expected return type of the request.\n *\n * @param schema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param [options] Optional. Additional options for the request. It includes custom urlSerializer, bodySerializer, and fetch function.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function requestFn<TData, TError>(\n schema: OperationSchema,\n requestInfo: RequestFnInfo,\n options?: RequestFnOptions\n): Promise<RequestFnResponse<TData, TError>> {\n return baseRequestFn<TData, TError>(schema, requestInfo, {\n urlSerializer,\n bodySerializer,\n ...options,\n });\n}\n\n/**\n * This function is used to make a request to a specified endpoint.\n * It's necessary to create a custom `requestFn` with a custom `urlSerializer`\n * and `bodySerializer`, with the tree-shaking of the default `requestFn`\n * and its serializers.\n *\n * @template T The expected return type of the request.\n *\n * @param requestSchema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param options The options for the request. It includes urlSerializer, bodySerializer, and fetch function. The 'urlSerializer' and 'bodySerializer' are required.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function baseRequestFn<TData, TError>(\n requestSchema: OperationSchema,\n requestInfo: RequestFnInfo,\n options: WithRequired<RequestFnOptions, 'urlSerializer' | 'bodySerializer'>\n): Promise<RequestFnResponse<TData, TError>> {\n const { parameters, headers, body, ...requestInfoRest } = requestInfo;\n\n const requestPayload = options.bodySerializer(requestSchema, body);\n\n const baseFetch = options.fetch ?? fetch;\n\n return baseFetch(options.urlSerializer(requestSchema, requestInfo), {\n method: requestSchema.method.toUpperCase(),\n body: requestPayload?.body,\n headers: mergeHeaders(\n { Accept: 'application/json' },\n requestPayload?.headers,\n headers,\n parameters?.header\n ),\n ...requestInfoRest,\n })\n .then(processResponse as typeof processResponse<TData, TError>)\n .catch(resolveResponse as typeof resolveResponse<TData, TError>);\n}\n\n/**\n * Serializes the given schema and request payload into a URL string.\n *\n * This function is implemented according to the URI Template standard\n * defined in RFC 6570. It supports the expansion of path and query parameters,\n * correctly handling empty arrays, `null`, and `undefined` values by ignoring\n * them during the expansion process, as specified by the standard.\n *\n * For more information, refer to the official documentation:\n * https://datatracker.ietf.org/doc/html/rfc6570\n *\n * @param schema - The operation schema containing the URL template and method.\n * @param info - The request payload including baseUrl, path parameters, and query parameters.\n * @returns The fully constructed URL string.\n */\nexport function urlSerializer(\n schema: OperationSchema,\n info: Pick<RequestFnInfo, 'baseUrl' | 'parameters'>\n): string {\n const path = schema.url.replace(\n /{(.*?)}/g,\n (substring: string, group: string) => {\n if (\n info.parameters?.path &&\n Object.prototype.hasOwnProperty.call(info.parameters.path, group)\n ) {\n return encodeURI(String(info.parameters?.path[group]));\n }\n return substring;\n }\n );\n\n const baseUrl = info.baseUrl ?? '';\n\n if (info.parameters?.query) {\n return `${baseUrl}${path}${getQueryString(info.parameters.query)}`;\n }\n\n return `${baseUrl}${path}`;\n}\n\nfunction getQueryString(params: Record<string, any>): string {\n const qs: string[] = [];\n\n const append = (key: string, value: any) => {\n qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n };\n\n const process = (key: string, value: any) => {\n if (typeof value === 'undefined' || value === null) return;\n\n if (Array.isArray(value)) {\n value.forEach((v) => {\n process(key, v);\n });\n } else if (typeof value === 'object') {\n Object.entries(value).forEach(([k, v]) => {\n process(`${key}[${k}]`, v);\n });\n } else {\n append(key, value);\n }\n };\n\n Object.entries(params).forEach(([key, value]) => {\n process(key, value);\n });\n\n if (qs.length > 0) {\n return `?${qs.join('&')}`;\n }\n\n return '';\n}\n\nexport function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]) {\n const headers = new Headers();\n\n for (const headerSet of allHeaders) {\n if (!headerSet || typeof headerSet !== 'object') {\n continue;\n }\n\n const headersIterator =\n headerSet instanceof Headers\n ? headerSet.entries()\n : Object.entries(headerSet);\n\n for (const [headerKey, headerValue] of headersIterator) {\n if (headerValue === null) {\n headers.delete(headerKey);\n } else if (headerValue !== undefined) {\n headers.set(headerKey, headerValue);\n }\n }\n }\n\n return headers;\n}\n\nexport function bodySerializer(\n schema: OperationSchema,\n body: RequestFnInfo['body']\n) {\n if (\n schema.method === 'get' ||\n schema.method === 'head' ||\n schema.method === 'options'\n )\n return undefined;\n\n if (body === undefined || body === null) return undefined;\n\n if (typeof body === 'string') {\n return {\n body,\n headers: {\n 'Content-Type':\n // prefer text/* media type\n schema.mediaType?.find((mediaType) => mediaType.includes('text/')) ??\n // prefer JSON media type, assume that body is serialized as JSON\n schema.mediaType?.find((mediaType) => mediaType.includes('/json')) ??\n 'text/plain',\n },\n };\n }\n\n if (body instanceof FormData) {\n return {\n body,\n headers: {\n // remove `Content-Type` if the serialized body is FormData;\n // the browser will correctly set Content-Type & boundary expression\n 'Content-Type': null,\n },\n };\n }\n\n if (body instanceof Blob) {\n return {\n body,\n headers: {\n 'Content-Type':\n body.type ||\n schema.mediaType?.find(\n (mediaType) =>\n !(\n mediaType.includes('text/') &&\n mediaType.includes('/form-data') &&\n mediaType.includes('/json')\n )\n ) ||\n 'application/octet-stream',\n },\n };\n }\n\n let jsonMediaType: string | null = null;\n let formDataMediaType: string | null = null;\n\n if (schema.mediaType) {\n for (let i = 0; i < schema.mediaType.length; i++) {\n const mediaType = schema.mediaType[i];\n if (mediaType.includes('/json')) jsonMediaType = mediaType;\n else if (mediaType.includes('/form-data')) formDataMediaType = mediaType;\n }\n }\n\n if (formDataMediaType) {\n if (\n !jsonMediaType ||\n // Prefer FormData serialization if one of the fields is a Blob\n Object.values(body).some((value) => value instanceof Blob)\n ) {\n return {\n body: getRequestBodyFormData(body),\n headers: {\n // remove `Content-Type` if the serialized body is FormData;\n // the browser will correctly set Content-Type & boundary expression\n 'Content-Type': null,\n },\n };\n }\n }\n\n return {\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': jsonMediaType ?? 'application/json',\n },\n };\n}\n\nfunction getRequestBodyFormData(\n body: NonNullable<RequestFnInfo['body']>\n): FormData {\n if (body instanceof FormData) return body;\n if (typeof body !== 'object')\n throw new Error(`Unsupported body type ${typeof body} in form-data.`);\n\n const formData = new FormData();\n\n const process = (key: string, value: any) => {\n if (typeof value === 'string' || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, JSON.stringify(value));\n }\n };\n\n Object.entries(body)\n .filter(([_, value]) => typeof value !== 'undefined' && value !== null)\n .forEach(([key, value]) => {\n if (Array.isArray(value)) {\n value.forEach((v) => process(key, v));\n } else {\n process(key, value);\n }\n });\n\n return formData;\n}\n\ntype WithRequired<T, K extends keyof T> = T & {\n [_ in K]: {};\n};\n\nexport type {\n RequestFn,\n RequestFnResponse,\n HeadersOptions,\n RequestFnOptions,\n RequestFnInfo,\n OperationSchema,\n} from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * @deprecated use `RequestFnInfo` instead\n */\nexport type RequestFnPayload = RequestFnInfo;\n"],"names":["requestFn","schema","requestInfo","options","baseRequestFn","urlSerializer","bodySerializer","requestSchema","parameters","headers","body","requestInfoRest","requestPayload","baseFetch","fetch","method","toUpperCase","mergeHeaders","Accept","header","then","processResponse","catch","resolveResponse","info","path","url","replace","substring","group","Object","prototype","hasOwnProperty","call","encodeURI","String","baseUrl","query","getQueryString","params","qs","append","key","value","push","encodeURIComponent","process","Array","isArray","forEach","v","entries","k","length","join","allHeaders","Headers","headerSet","headersIterator","headerKey","headerValue","delete","undefined","set","mediaType","find","includes","FormData","Blob","type","jsonMediaType","formDataMediaType","i","values","some","getRequestBodyFormData","JSON","stringify","Error","formData","filter","_"],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Processes the response from the server.
5
+ * @beta
6
+ */ async function processResponse(response) {
7
+ if (response.status === 204 || response.headers.get('Content-Length') === '0') return response.ok ? {
8
+ data: {},
9
+ response
10
+ } : {
11
+ error: {},
12
+ response
13
+ };
14
+ const contentType = response.headers.get('Content-Type')?.toLowerCase();
15
+ const isJsonResponse = contentType?.includes('/json') || contentType?.includes('+json');
16
+ if (isJsonResponse) {
17
+ // clone response before parsing every time to allow multiple reads
18
+ const jsonResponse = response.clone().json();
19
+ return resolveResponse(response, response.ok ? jsonResponse : Promise.reject(await jsonResponse));
20
+ }
21
+ const textResponse = response.clone().text();
22
+ return resolveResponse(response, response.ok ? textResponse : Promise.reject(await textResponse));
23
+ }
24
+ function resolveResponse(responseToReturn, responsePromise) {
25
+ if (!responsePromise) return Promise.reject({
26
+ error: responseToReturn,
27
+ response: undefined,
28
+ data: undefined
29
+ });
30
+ return responsePromise.then((data)=>({
31
+ data,
32
+ response: responseToReturn
33
+ })).catch((error)=>({
34
+ error,
35
+ response: responseToReturn
36
+ }));
37
+ }
38
+
39
+ exports.processResponse = processResponse;
40
+ exports.resolveResponse = resolveResponse;
41
+ //# sourceMappingURL=responseUtils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseUtils.cjs","sources":["../../../src/lib/responseUtils.ts"],"sourcesContent":["import type { RequestFnResponse } from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * Processes the response from the server.\n * @beta\n */\nexport async function processResponse<TData, TError>(\n response: Response\n): Promise<RequestFnResponse<TData, TError>> {\n if (response.status === 204 || response.headers.get('Content-Length') === '0')\n return (\n response.ok ? { data: {}, response } : { error: {}, response }\n ) as RequestFnResponse<TData, TError>;\n\n const contentType = response.headers.get('Content-Type')?.toLowerCase();\n\n const isJsonResponse =\n contentType?.includes('/json') || contentType?.includes('+json');\n\n if (isJsonResponse) {\n // clone response before parsing every time to allow multiple reads\n const jsonResponse = response.clone().json();\n return resolveResponse(\n response,\n response.ok ? jsonResponse : Promise.reject(await jsonResponse)\n );\n }\n\n const textResponse = response.clone().text() as Promise<TData>;\n\n return resolveResponse(\n response,\n response.ok ? textResponse : Promise.reject(await textResponse)\n );\n}\n\n/**\n * Resolves the response from the server.\n * @beta\n */\nexport function resolveResponse<TData, TError>(\n error: Error\n): Promise<RequestFnResponse<TData, TError>>;\nexport function resolveResponse<TData, TError>(\n responseToReturn: Response,\n responsePromise: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>>;\nexport function resolveResponse<TData, TError>(\n responseToReturn: Response | Error,\n responsePromise?: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>> {\n if (!responsePromise)\n return Promise.reject({\n error: responseToReturn,\n response: undefined,\n data: undefined,\n });\n\n return responsePromise\n .then(\n (data) =>\n ({ data, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n )\n .catch(\n (error) =>\n ({ error, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n );\n}\n"],"names":["processResponse","response","status","headers","get","ok","data","error","contentType","toLowerCase","isJsonResponse","includes","jsonResponse","clone","json","resolveResponse","Promise","reject","textResponse","text","responseToReturn","responsePromise","undefined","then","catch"],"mappings":";;AAEA;;;IAIO,eAAeA,eAAAA,CACpBC,QAAkB,EAAA;AAElB,IAAA,IAAIA,QAASC,CAAAA,MAAM,KAAK,GAAA,IAAOD,SAASE,OAAO,CAACC,GAAG,CAAC,gBAAsB,CAAA,KAAA,GAAA,EACxE,OACEH,QAAAA,CAASI,EAAE,GAAG;AAAEC,QAAAA,IAAAA,EAAM,EAAC;AAAGL,QAAAA,QAAAA;KAAa,GAAA;AAAEM,QAAAA,KAAAA,EAAO,EAAC;AAAGN,QAAAA,QAAAA;AAAS,KAAA,CAAA;AAGjE,IAAA,MAAMO,cAAcP,QAASE,CAAAA,OAAO,CAACC,GAAG,CAAC,cAAiBK,CAAAA,EAAAA,WAAAA,EAAAA,CAAAA;AAE1D,IAAA,MAAMC,cACJF,GAAAA,WAAAA,EAAaG,QAAS,CAAA,OAAA,CAAA,IAAYH,aAAaG,QAAS,CAAA,OAAA,CAAA,CAAA;AAE1D,IAAA,IAAID,cAAgB,EAAA;;AAElB,QAAA,MAAME,YAAeX,GAAAA,QAAAA,CAASY,KAAK,EAAA,CAAGC,IAAI,EAAA,CAAA;QAC1C,OAAOC,eAAAA,CACLd,UACAA,QAASI,CAAAA,EAAE,GAAGO,YAAeI,GAAAA,OAAAA,CAAQC,MAAM,CAAC,MAAML,YAAAA,CAAAA,CAAAA,CAAAA;AAEtD,KAAA;AAEA,IAAA,MAAMM,YAAejB,GAAAA,QAAAA,CAASY,KAAK,EAAA,CAAGM,IAAI,EAAA,CAAA;IAE1C,OAAOJ,eAAAA,CACLd,UACAA,QAASI,CAAAA,EAAE,GAAGa,YAAeF,GAAAA,OAAAA,CAAQC,MAAM,CAAC,MAAMC,YAAAA,CAAAA,CAAAA,CAAAA;AAEtD,CAAA;AAaO,SAASH,eAAAA,CACdK,gBAAkC,EAClCC,eAAgC,EAAA;AAEhC,IAAA,IAAI,CAACA,eAAAA,EACH,OAAOL,OAAAA,CAAQC,MAAM,CAAC;QACpBV,KAAOa,EAAAA,gBAAAA;QACPnB,QAAUqB,EAAAA,SAAAA;QACVhB,IAAMgB,EAAAA,SAAAA;AACR,KAAA,CAAA,CAAA;AAEF,IAAA,OAAOD,eACJE,CAAAA,IAAI,CACH,CAACjB,QACE;AAAEA,YAAAA,IAAAA;YAAML,QAAUmB,EAAAA,gBAAAA;AAAiB,SAAA,CAKvCI,CAAAA,CAAAA,KAAK,CACJ,CAACjB,SACE;AAAEA,YAAAA,KAAAA;YAAON,QAAUmB,EAAAA,gBAAAA;SAAiB,CAAA,CAAA,CAAA;AAK7C;;;;;"}
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var responseUtils = require('./lib/responseUtils.cjs');
4
+
5
+
6
+
7
+ exports.processResponse = responseUtils.processResponse;
8
+ exports.resolveResponse = responseUtils.resolveResponse;
9
+ //# sourceMappingURL=unstable__responseUtils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unstable__responseUtils.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -1,3 +1,5 @@
1
+ import { processResponse, resolveResponse } from './responseUtils.js';
2
+
1
3
  /**
2
4
  * This function is used to make a request to a specified endpoint.
3
5
  *
@@ -19,7 +21,7 @@
19
21
  }
20
22
  /**
21
23
  * This function is used to make a request to a specified endpoint.
22
- * It's needed to create a custom `requestFn` with a custom `urlSerializer`
24
+ * It's necessary to create a custom `requestFn` with a custom `urlSerializer`
23
25
  * and `bodySerializer`, with the tree-shaking of the default `requestFn`
24
26
  * and its serializers.
25
27
  *
@@ -34,17 +36,14 @@
34
36
  * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.
35
37
  */ async function baseRequestFn(requestSchema, requestInfo, options) {
36
38
  const { parameters, headers, body, ...requestInfoRest } = requestInfo;
37
- const requestBody = options.bodySerializer(requestSchema, requestInfo);
39
+ const requestPayload = options.bodySerializer(requestSchema, body);
38
40
  const baseFetch = options.fetch ?? fetch;
39
41
  return baseFetch(options.urlSerializer(requestSchema, requestInfo), {
40
42
  method: requestSchema.method.toUpperCase(),
41
- body: requestBody,
43
+ body: requestPayload?.body,
42
44
  headers: mergeHeaders({
43
- Accept: 'application/json',
44
- 'Content-Type': requestSchema.mediaType ?? getBodyContentType(body)
45
- }, headers, parameters?.header, requestBody instanceof FormData ? {
46
- 'Content-Type': null
47
- } : undefined),
45
+ Accept: 'application/json'
46
+ }, requestPayload?.headers, headers, parameters?.header),
48
47
  ...requestInfoRest
49
48
  }).then(processResponse).catch(resolveResponse);
50
49
  }
@@ -119,23 +118,68 @@ function mergeHeaders(...allHeaders) {
119
118
  }
120
119
  return headers;
121
120
  }
122
- function bodySerializer(schema, info) {
123
- if (info.body === undefined) return;
124
- if (schema.method === 'get' || schema.method === 'head' || schema.method === 'options') return;
125
- if (schema.mediaType?.includes('/form-data')) return getRequestBodyFormData(info);
126
- if (!schema.mediaType?.includes('/json') && (typeof info.body === 'string' || info.body instanceof Blob || info.body instanceof FormData)) {
127
- return info.body;
121
+ function bodySerializer(schema, body) {
122
+ if (schema.method === 'get' || schema.method === 'head' || schema.method === 'options') return undefined;
123
+ if (body === undefined || body === null) return undefined;
124
+ if (typeof body === 'string') {
125
+ return {
126
+ body,
127
+ headers: {
128
+ 'Content-Type': // prefer text/* media type
129
+ schema.mediaType?.find((mediaType)=>mediaType.includes('text/')) ?? // prefer JSON media type, assume that body is serialized as JSON
130
+ schema.mediaType?.find((mediaType)=>mediaType.includes('/json')) ?? 'text/plain'
131
+ }
132
+ };
133
+ }
134
+ if (body instanceof FormData) {
135
+ return {
136
+ body,
137
+ headers: {
138
+ // remove `Content-Type` if the serialized body is FormData;
139
+ // the browser will correctly set Content-Type & boundary expression
140
+ 'Content-Type': null
141
+ }
142
+ };
143
+ }
144
+ if (body instanceof Blob) {
145
+ return {
146
+ body,
147
+ headers: {
148
+ 'Content-Type': body.type || schema.mediaType?.find((mediaType)=>!(mediaType.includes('text/') && mediaType.includes('/form-data') && mediaType.includes('/json'))) || 'application/octet-stream'
149
+ }
150
+ };
151
+ }
152
+ let jsonMediaType = null;
153
+ let formDataMediaType = null;
154
+ if (schema.mediaType) {
155
+ for(let i = 0; i < schema.mediaType.length; i++){
156
+ const mediaType = schema.mediaType[i];
157
+ if (mediaType.includes('/json')) jsonMediaType = mediaType;
158
+ else if (mediaType.includes('/form-data')) formDataMediaType = mediaType;
159
+ }
160
+ }
161
+ if (formDataMediaType) {
162
+ if (!jsonMediaType || // Prefer FormData serialization if one of the fields is a Blob
163
+ Object.values(body).some((value)=>value instanceof Blob)) {
164
+ return {
165
+ body: getRequestBodyFormData(body),
166
+ headers: {
167
+ // remove `Content-Type` if the serialized body is FormData;
168
+ // the browser will correctly set Content-Type & boundary expression
169
+ 'Content-Type': null
170
+ }
171
+ };
172
+ }
128
173
  }
129
- return JSON.stringify(info.body);
174
+ return {
175
+ body: JSON.stringify(body),
176
+ headers: {
177
+ 'Content-Type': jsonMediaType ?? 'application/json'
178
+ }
179
+ };
130
180
  }
131
- function getRequestBodyFormData({ body }) {
181
+ function getRequestBodyFormData(body) {
132
182
  if (body instanceof FormData) return body;
133
- if (body === null) return;
134
- if (body instanceof Blob) throw new Error('Blob not supported in form-data');
135
- if (body instanceof ArrayBuffer) throw new Error('ArrayBuffer not supported in form-data');
136
- if (body instanceof URLSearchParams) throw new Error('URLSearchParams not supported in form-data');
137
- if (body instanceof ReadableStream) throw new Error('ReadableStream not supported in form-data');
138
- if (typeof body === 'string') throw new Error('String not supported in form-data');
139
183
  if (typeof body !== 'object') throw new Error(`Unsupported body type ${typeof body} in form-data.`);
140
184
  const formData = new FormData();
141
185
  const process = (key, value)=>{
@@ -154,47 +198,6 @@ function getRequestBodyFormData({ body }) {
154
198
  });
155
199
  return formData;
156
200
  }
157
- function getBodyContentType(body) {
158
- if (!body) return;
159
- if (body instanceof Blob) return body.type || 'application/octet-stream';
160
- if (typeof body === 'string') return 'text/plain';
161
- if (!(body instanceof FormData)) return 'application/json';
162
- }
163
- async function processResponse(response) {
164
- if (response.status === 204 || response.headers.get('Content-Length') === '0') return response.ok ? {
165
- data: {},
166
- response
167
- } : {
168
- error: {},
169
- response
170
- };
171
- if (isJsonResponse(response)) {
172
- // clone response before parsing every time to allow multiple reads
173
- const jsonResponse = response.clone().json();
174
- return resolveResponse(response, response.ok ? jsonResponse : Promise.reject(await jsonResponse));
175
- }
176
- const jsonResponse = new Promise((resolve, reject)=>// attempt to parse JSON for successful responses, otherwise fail
177
- response.clone().text().then(JSON.parse).then(resolve, reject));
178
- return resolveResponse(response, response.ok ? jsonResponse : Promise.reject(await jsonResponse));
179
- }
180
- function isJsonResponse(response) {
181
- const contentType = response.headers.get('Content-Type')?.toLowerCase();
182
- return contentType?.includes('/json') || contentType?.includes('+json');
183
- }
184
- function resolveResponse(responseToReturn, responsePromise) {
185
- if (!responsePromise) return Promise.reject({
186
- error: responseToReturn,
187
- response: undefined,
188
- data: undefined
189
- });
190
- return responsePromise.then((data)=>({
191
- data,
192
- response: responseToReturn
193
- })).catch((error)=>({
194
- error,
195
- response: responseToReturn
196
- }));
197
- }
198
201
 
199
202
  export { baseRequestFn, bodySerializer, mergeHeaders, requestFn, urlSerializer };
200
203
  //# sourceMappingURL=requestFn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"requestFn.js","sources":["../../../src/lib/requestFn.ts"],"sourcesContent":["import type {\n HeadersOptions,\n OperationSchema,\n RequestFnInfo,\n RequestFnOptions,\n RequestFnResponse,\n} from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * This function is used to make a request to a specified endpoint.\n *\n * @template T The expected return type of the request.\n *\n * @param schema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param [options] Optional. Additional options for the request. It includes custom urlSerializer, bodySerializer, and fetch function.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function requestFn<TData, TError>(\n schema: OperationSchema,\n requestInfo: RequestFnInfo,\n options?: RequestFnOptions\n): Promise<RequestFnResponse<TData, TError>> {\n return baseRequestFn<TData, TError>(schema, requestInfo, {\n urlSerializer,\n bodySerializer,\n ...options,\n });\n}\n\n/**\n * This function is used to make a request to a specified endpoint.\n * It's needed to create a custom `requestFn` with a custom `urlSerializer`\n * and `bodySerializer`, with the tree-shaking of the default `requestFn`\n * and its serializers.\n *\n * @template T The expected return type of the request.\n *\n * @param requestSchema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param options The options for the request. It includes urlSerializer, bodySerializer, and fetch function. The 'urlSerializer' and 'bodySerializer' are required.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function baseRequestFn<TData, TError>(\n requestSchema: OperationSchema,\n requestInfo: RequestFnInfo,\n options: WithRequired<RequestFnOptions, 'urlSerializer' | 'bodySerializer'>\n): Promise<RequestFnResponse<TData, TError>> {\n const { parameters, headers, body, ...requestInfoRest } = requestInfo;\n\n const requestBody = options.bodySerializer(requestSchema, requestInfo);\n\n const baseFetch = options.fetch ?? fetch;\n\n return baseFetch(options.urlSerializer(requestSchema, requestInfo), {\n method: requestSchema.method.toUpperCase(),\n body: requestBody,\n headers: mergeHeaders(\n {\n Accept: 'application/json',\n 'Content-Type': requestSchema.mediaType ?? getBodyContentType(body),\n },\n headers,\n parameters?.header,\n requestBody instanceof FormData\n ? // remove `Content-Type` if the serialized body is FormData; the browser will correctly set Content-Type & boundary expression\n { 'Content-Type': null }\n : undefined\n ),\n ...requestInfoRest,\n })\n .then(processResponse as typeof processResponse<TData, TError>)\n .catch(resolveResponse as typeof resolveResponse<TData, TError>);\n}\n\n/**\n * Serializes the given schema and request payload into a URL string.\n *\n * This function is implemented according to the URI Template standard\n * defined in RFC 6570. It supports the expansion of path and query parameters,\n * correctly handling empty arrays, `null`, and `undefined` values by ignoring\n * them during the expansion process, as specified by the standard.\n *\n * For more information, refer to the official documentation:\n * https://datatracker.ietf.org/doc/html/rfc6570\n *\n * @param schema - The operation schema containing the URL template and method.\n * @param info - The request payload including baseUrl, path parameters, and query parameters.\n * @returns The fully constructed URL string.\n */\nexport function urlSerializer(\n schema: OperationSchema,\n info: Pick<RequestFnInfo, 'baseUrl' | 'parameters'>\n): string {\n const path = schema.url.replace(\n /{(.*?)}/g,\n (substring: string, group: string) => {\n if (\n info.parameters?.path &&\n Object.prototype.hasOwnProperty.call(info.parameters.path, group)\n ) {\n return encodeURI(String(info.parameters?.path[group]));\n }\n return substring;\n }\n );\n\n const baseUrl = info.baseUrl ?? '';\n\n if (info.parameters?.query) {\n return `${baseUrl}${path}${getQueryString(info.parameters.query)}`;\n }\n\n return `${baseUrl}${path}`;\n}\n\nfunction getQueryString(params: Record<string, any>): string {\n const qs: string[] = [];\n\n const append = (key: string, value: any) => {\n qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n };\n\n const process = (key: string, value: any) => {\n if (typeof value === 'undefined' || value === null) return;\n\n if (Array.isArray(value)) {\n value.forEach((v) => {\n process(key, v);\n });\n } else if (typeof value === 'object') {\n Object.entries(value).forEach(([k, v]) => {\n process(`${key}[${k}]`, v);\n });\n } else {\n append(key, value);\n }\n };\n\n Object.entries(params).forEach(([key, value]) => {\n process(key, value);\n });\n\n if (qs.length > 0) {\n return `?${qs.join('&')}`;\n }\n\n return '';\n}\n\nexport function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]) {\n const headers = new Headers();\n\n for (const headerSet of allHeaders) {\n if (!headerSet || typeof headerSet !== 'object') {\n continue;\n }\n\n const headersIterator =\n headerSet instanceof Headers\n ? headerSet.entries()\n : Object.entries(headerSet);\n\n for (const [headerKey, headerValue] of headersIterator) {\n if (headerValue === null) {\n headers.delete(headerKey);\n } else if (headerValue !== undefined) {\n headers.set(headerKey, headerValue);\n }\n }\n }\n\n return headers;\n}\n\nexport function bodySerializer(schema: OperationSchema, info: RequestFnInfo) {\n if (info.body === undefined) return;\n\n if (\n schema.method === 'get' ||\n schema.method === 'head' ||\n schema.method === 'options'\n )\n return;\n\n if (schema.mediaType?.includes('/form-data'))\n return getRequestBodyFormData(info);\n\n if (\n !schema.mediaType?.includes('/json') &&\n (typeof info.body === 'string' ||\n info.body instanceof Blob ||\n info.body instanceof FormData)\n ) {\n return info.body;\n }\n\n return JSON.stringify(info.body);\n}\n\nfunction getRequestBodyFormData({\n body,\n}: Pick<RequestFnInfo, 'body'>): FormData | undefined {\n if (body instanceof FormData) return body;\n if (body === null) return;\n\n if (body instanceof Blob) throw new Error('Blob not supported in form-data');\n if (body instanceof ArrayBuffer)\n throw new Error('ArrayBuffer not supported in form-data');\n if (body instanceof URLSearchParams)\n throw new Error('URLSearchParams not supported in form-data');\n if (body instanceof ReadableStream)\n throw new Error('ReadableStream not supported in form-data');\n if (typeof body === 'string')\n throw new Error('String not supported in form-data');\n if (typeof body !== 'object')\n throw new Error(`Unsupported body type ${typeof body} in form-data.`);\n\n const formData = new FormData();\n\n const process = (key: string, value: any) => {\n if (typeof value === 'string' || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, JSON.stringify(value));\n }\n };\n\n Object.entries(body)\n .filter(([_, value]) => typeof value !== 'undefined' && value !== null)\n .forEach(([key, value]) => {\n if (Array.isArray(value)) {\n value.forEach((v) => process(key, v));\n } else {\n process(key, value);\n }\n });\n\n return formData;\n}\n\nfunction getBodyContentType(body: RequestFnInfo['body']) {\n if (!body) return;\n if (body instanceof Blob) return body.type || 'application/octet-stream';\n if (typeof body === 'string') return 'text/plain';\n if (!(body instanceof FormData)) return 'application/json';\n}\n\nasync function processResponse<TData, TError>(\n response: Response\n): Promise<RequestFnResponse<TData, TError>> {\n if (response.status === 204 || response.headers.get('Content-Length') === '0')\n return (\n response.ok ? { data: {}, response } : { error: {}, response }\n ) as RequestFnResponse<TData, TError>;\n\n if (isJsonResponse(response)) {\n // clone response before parsing every time to allow multiple reads\n const jsonResponse = response.clone().json();\n return resolveResponse(\n response,\n response.ok ? jsonResponse : Promise.reject(await jsonResponse)\n );\n }\n\n const jsonResponse = new Promise<TData>((resolve, reject) =>\n // attempt to parse JSON for successful responses, otherwise fail\n response.clone().text().then(JSON.parse).then(resolve, reject)\n );\n\n return resolveResponse(\n response,\n response.ok ? jsonResponse : Promise.reject(await jsonResponse)\n );\n}\n\nfunction isJsonResponse(response: Response) {\n const contentType = response.headers.get('Content-Type')?.toLowerCase();\n return contentType?.includes('/json') || contentType?.includes('+json');\n}\n\nfunction resolveResponse<TData, TError>(\n error: Error\n): Promise<RequestFnResponse<TData, TError>>;\nfunction resolveResponse<TData, TError>(\n responseToReturn: Response,\n responsePromise: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>>;\nfunction resolveResponse<TData, TError>(\n responseToReturn: Response | Error,\n responsePromise?: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>> {\n if (!responsePromise)\n return Promise.reject({\n error: responseToReturn,\n response: undefined,\n data: undefined,\n });\n\n return responsePromise\n .then(\n (data) =>\n ({ data, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n )\n .catch(\n (error) =>\n ({ error, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n );\n}\n\ntype WithRequired<T, K extends keyof T> = T & {\n [_ in K]: {};\n};\n\nexport type {\n RequestFn,\n RequestFnResponse,\n HeadersOptions,\n RequestFnOptions,\n RequestFnInfo,\n OperationSchema,\n} from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * @deprecated use `RequestFnInfo` instead\n */\nexport type RequestFnPayload = RequestFnInfo;\n"],"names":["requestFn","schema","requestInfo","options","baseRequestFn","urlSerializer","bodySerializer","requestSchema","parameters","headers","body","requestInfoRest","requestBody","baseFetch","fetch","method","toUpperCase","mergeHeaders","Accept","mediaType","getBodyContentType","header","FormData","undefined","then","processResponse","catch","resolveResponse","info","path","url","replace","substring","group","Object","prototype","hasOwnProperty","call","encodeURI","String","baseUrl","query","getQueryString","params","qs","append","key","value","push","encodeURIComponent","process","Array","isArray","forEach","v","entries","k","length","join","allHeaders","Headers","headerSet","headersIterator","headerKey","headerValue","delete","set","includes","getRequestBodyFormData","Blob","JSON","stringify","Error","ArrayBuffer","URLSearchParams","ReadableStream","formData","filter","_","type","response","status","get","ok","data","error","isJsonResponse","jsonResponse","clone","json","Promise","reject","resolve","text","parse","contentType","toLowerCase","responseToReturn","responsePromise"],"mappings":"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"}
1
+ {"version":3,"file":"requestFn.js","sources":["../../../src/lib/requestFn.ts"],"sourcesContent":["import type {\n HeadersOptions,\n OperationSchema,\n RequestFnInfo,\n RequestFnOptions,\n RequestFnResponse,\n} from '@openapi-qraft/tanstack-query-react-types';\nimport { processResponse, resolveResponse } from './responseUtils.js';\n\n/**\n * This function is used to make a request to a specified endpoint.\n *\n * @template T The expected return type of the request.\n *\n * @param schema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param [options] Optional. Additional options for the request. It includes custom urlSerializer, bodySerializer, and fetch function.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function requestFn<TData, TError>(\n schema: OperationSchema,\n requestInfo: RequestFnInfo,\n options?: RequestFnOptions\n): Promise<RequestFnResponse<TData, TError>> {\n return baseRequestFn<TData, TError>(schema, requestInfo, {\n urlSerializer,\n bodySerializer,\n ...options,\n });\n}\n\n/**\n * This function is used to make a request to a specified endpoint.\n * It's necessary to create a custom `requestFn` with a custom `urlSerializer`\n * and `bodySerializer`, with the tree-shaking of the default `requestFn`\n * and its serializers.\n *\n * @template T The expected return type of the request.\n *\n * @param requestSchema The schema of the operation to be performed. It includes the OpenAPI path, HTTP method and media type.\n * @param requestInfo The information required to make the request. It includes parameters, headers, body, etc.\n * @param options The options for the request. It includes urlSerializer, bodySerializer, and fetch function. The 'urlSerializer' and 'bodySerializer' are required.\n *\n * @returns {Promise<T>} Returns a promise that resolves with the response of the request.\n *\n * @throws {error: object|string, response: Response} Throws an error if the request fails. The error includes the error message and the response from the server.\n */\nexport async function baseRequestFn<TData, TError>(\n requestSchema: OperationSchema,\n requestInfo: RequestFnInfo,\n options: WithRequired<RequestFnOptions, 'urlSerializer' | 'bodySerializer'>\n): Promise<RequestFnResponse<TData, TError>> {\n const { parameters, headers, body, ...requestInfoRest } = requestInfo;\n\n const requestPayload = options.bodySerializer(requestSchema, body);\n\n const baseFetch = options.fetch ?? fetch;\n\n return baseFetch(options.urlSerializer(requestSchema, requestInfo), {\n method: requestSchema.method.toUpperCase(),\n body: requestPayload?.body,\n headers: mergeHeaders(\n { Accept: 'application/json' },\n requestPayload?.headers,\n headers,\n parameters?.header\n ),\n ...requestInfoRest,\n })\n .then(processResponse as typeof processResponse<TData, TError>)\n .catch(resolveResponse as typeof resolveResponse<TData, TError>);\n}\n\n/**\n * Serializes the given schema and request payload into a URL string.\n *\n * This function is implemented according to the URI Template standard\n * defined in RFC 6570. It supports the expansion of path and query parameters,\n * correctly handling empty arrays, `null`, and `undefined` values by ignoring\n * them during the expansion process, as specified by the standard.\n *\n * For more information, refer to the official documentation:\n * https://datatracker.ietf.org/doc/html/rfc6570\n *\n * @param schema - The operation schema containing the URL template and method.\n * @param info - The request payload including baseUrl, path parameters, and query parameters.\n * @returns The fully constructed URL string.\n */\nexport function urlSerializer(\n schema: OperationSchema,\n info: Pick<RequestFnInfo, 'baseUrl' | 'parameters'>\n): string {\n const path = schema.url.replace(\n /{(.*?)}/g,\n (substring: string, group: string) => {\n if (\n info.parameters?.path &&\n Object.prototype.hasOwnProperty.call(info.parameters.path, group)\n ) {\n return encodeURI(String(info.parameters?.path[group]));\n }\n return substring;\n }\n );\n\n const baseUrl = info.baseUrl ?? '';\n\n if (info.parameters?.query) {\n return `${baseUrl}${path}${getQueryString(info.parameters.query)}`;\n }\n\n return `${baseUrl}${path}`;\n}\n\nfunction getQueryString(params: Record<string, any>): string {\n const qs: string[] = [];\n\n const append = (key: string, value: any) => {\n qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n };\n\n const process = (key: string, value: any) => {\n if (typeof value === 'undefined' || value === null) return;\n\n if (Array.isArray(value)) {\n value.forEach((v) => {\n process(key, v);\n });\n } else if (typeof value === 'object') {\n Object.entries(value).forEach(([k, v]) => {\n process(`${key}[${k}]`, v);\n });\n } else {\n append(key, value);\n }\n };\n\n Object.entries(params).forEach(([key, value]) => {\n process(key, value);\n });\n\n if (qs.length > 0) {\n return `?${qs.join('&')}`;\n }\n\n return '';\n}\n\nexport function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]) {\n const headers = new Headers();\n\n for (const headerSet of allHeaders) {\n if (!headerSet || typeof headerSet !== 'object') {\n continue;\n }\n\n const headersIterator =\n headerSet instanceof Headers\n ? headerSet.entries()\n : Object.entries(headerSet);\n\n for (const [headerKey, headerValue] of headersIterator) {\n if (headerValue === null) {\n headers.delete(headerKey);\n } else if (headerValue !== undefined) {\n headers.set(headerKey, headerValue);\n }\n }\n }\n\n return headers;\n}\n\nexport function bodySerializer(\n schema: OperationSchema,\n body: RequestFnInfo['body']\n) {\n if (\n schema.method === 'get' ||\n schema.method === 'head' ||\n schema.method === 'options'\n )\n return undefined;\n\n if (body === undefined || body === null) return undefined;\n\n if (typeof body === 'string') {\n return {\n body,\n headers: {\n 'Content-Type':\n // prefer text/* media type\n schema.mediaType?.find((mediaType) => mediaType.includes('text/')) ??\n // prefer JSON media type, assume that body is serialized as JSON\n schema.mediaType?.find((mediaType) => mediaType.includes('/json')) ??\n 'text/plain',\n },\n };\n }\n\n if (body instanceof FormData) {\n return {\n body,\n headers: {\n // remove `Content-Type` if the serialized body is FormData;\n // the browser will correctly set Content-Type & boundary expression\n 'Content-Type': null,\n },\n };\n }\n\n if (body instanceof Blob) {\n return {\n body,\n headers: {\n 'Content-Type':\n body.type ||\n schema.mediaType?.find(\n (mediaType) =>\n !(\n mediaType.includes('text/') &&\n mediaType.includes('/form-data') &&\n mediaType.includes('/json')\n )\n ) ||\n 'application/octet-stream',\n },\n };\n }\n\n let jsonMediaType: string | null = null;\n let formDataMediaType: string | null = null;\n\n if (schema.mediaType) {\n for (let i = 0; i < schema.mediaType.length; i++) {\n const mediaType = schema.mediaType[i];\n if (mediaType.includes('/json')) jsonMediaType = mediaType;\n else if (mediaType.includes('/form-data')) formDataMediaType = mediaType;\n }\n }\n\n if (formDataMediaType) {\n if (\n !jsonMediaType ||\n // Prefer FormData serialization if one of the fields is a Blob\n Object.values(body).some((value) => value instanceof Blob)\n ) {\n return {\n body: getRequestBodyFormData(body),\n headers: {\n // remove `Content-Type` if the serialized body is FormData;\n // the browser will correctly set Content-Type & boundary expression\n 'Content-Type': null,\n },\n };\n }\n }\n\n return {\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': jsonMediaType ?? 'application/json',\n },\n };\n}\n\nfunction getRequestBodyFormData(\n body: NonNullable<RequestFnInfo['body']>\n): FormData {\n if (body instanceof FormData) return body;\n if (typeof body !== 'object')\n throw new Error(`Unsupported body type ${typeof body} in form-data.`);\n\n const formData = new FormData();\n\n const process = (key: string, value: any) => {\n if (typeof value === 'string' || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, JSON.stringify(value));\n }\n };\n\n Object.entries(body)\n .filter(([_, value]) => typeof value !== 'undefined' && value !== null)\n .forEach(([key, value]) => {\n if (Array.isArray(value)) {\n value.forEach((v) => process(key, v));\n } else {\n process(key, value);\n }\n });\n\n return formData;\n}\n\ntype WithRequired<T, K extends keyof T> = T & {\n [_ in K]: {};\n};\n\nexport type {\n RequestFn,\n RequestFnResponse,\n HeadersOptions,\n RequestFnOptions,\n RequestFnInfo,\n OperationSchema,\n} from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * @deprecated use `RequestFnInfo` instead\n */\nexport type RequestFnPayload = RequestFnInfo;\n"],"names":["requestFn","schema","requestInfo","options","baseRequestFn","urlSerializer","bodySerializer","requestSchema","parameters","headers","body","requestInfoRest","requestPayload","baseFetch","fetch","method","toUpperCase","mergeHeaders","Accept","header","then","processResponse","catch","resolveResponse","info","path","url","replace","substring","group","Object","prototype","hasOwnProperty","call","encodeURI","String","baseUrl","query","getQueryString","params","qs","append","key","value","push","encodeURIComponent","process","Array","isArray","forEach","v","entries","k","length","join","allHeaders","Headers","headerSet","headersIterator","headerKey","headerValue","delete","undefined","set","mediaType","find","includes","FormData","Blob","type","jsonMediaType","formDataMediaType","i","values","some","getRequestBodyFormData","JSON","stringify","Error","formData","filter","_"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Processes the response from the server.
3
+ * @beta
4
+ */ async function processResponse(response) {
5
+ if (response.status === 204 || response.headers.get('Content-Length') === '0') return response.ok ? {
6
+ data: {},
7
+ response
8
+ } : {
9
+ error: {},
10
+ response
11
+ };
12
+ const contentType = response.headers.get('Content-Type')?.toLowerCase();
13
+ const isJsonResponse = contentType?.includes('/json') || contentType?.includes('+json');
14
+ if (isJsonResponse) {
15
+ // clone response before parsing every time to allow multiple reads
16
+ const jsonResponse = response.clone().json();
17
+ return resolveResponse(response, response.ok ? jsonResponse : Promise.reject(await jsonResponse));
18
+ }
19
+ const textResponse = response.clone().text();
20
+ return resolveResponse(response, response.ok ? textResponse : Promise.reject(await textResponse));
21
+ }
22
+ function resolveResponse(responseToReturn, responsePromise) {
23
+ if (!responsePromise) return Promise.reject({
24
+ error: responseToReturn,
25
+ response: undefined,
26
+ data: undefined
27
+ });
28
+ return responsePromise.then((data)=>({
29
+ data,
30
+ response: responseToReturn
31
+ })).catch((error)=>({
32
+ error,
33
+ response: responseToReturn
34
+ }));
35
+ }
36
+
37
+ export { processResponse, resolveResponse };
38
+ //# sourceMappingURL=responseUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseUtils.js","sources":["../../../src/lib/responseUtils.ts"],"sourcesContent":["import type { RequestFnResponse } from '@openapi-qraft/tanstack-query-react-types';\n\n/**\n * Processes the response from the server.\n * @beta\n */\nexport async function processResponse<TData, TError>(\n response: Response\n): Promise<RequestFnResponse<TData, TError>> {\n if (response.status === 204 || response.headers.get('Content-Length') === '0')\n return (\n response.ok ? { data: {}, response } : { error: {}, response }\n ) as RequestFnResponse<TData, TError>;\n\n const contentType = response.headers.get('Content-Type')?.toLowerCase();\n\n const isJsonResponse =\n contentType?.includes('/json') || contentType?.includes('+json');\n\n if (isJsonResponse) {\n // clone response before parsing every time to allow multiple reads\n const jsonResponse = response.clone().json();\n return resolveResponse(\n response,\n response.ok ? jsonResponse : Promise.reject(await jsonResponse)\n );\n }\n\n const textResponse = response.clone().text() as Promise<TData>;\n\n return resolveResponse(\n response,\n response.ok ? textResponse : Promise.reject(await textResponse)\n );\n}\n\n/**\n * Resolves the response from the server.\n * @beta\n */\nexport function resolveResponse<TData, TError>(\n error: Error\n): Promise<RequestFnResponse<TData, TError>>;\nexport function resolveResponse<TData, TError>(\n responseToReturn: Response,\n responsePromise: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>>;\nexport function resolveResponse<TData, TError>(\n responseToReturn: Response | Error,\n responsePromise?: Promise<TData>\n): Promise<RequestFnResponse<TData, TError>> {\n if (!responsePromise)\n return Promise.reject({\n error: responseToReturn,\n response: undefined,\n data: undefined,\n });\n\n return responsePromise\n .then(\n (data) =>\n ({ data, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n )\n .catch(\n (error) =>\n ({ error, response: responseToReturn }) as RequestFnResponse<\n TData,\n TError\n >\n );\n}\n"],"names":["processResponse","response","status","headers","get","ok","data","error","contentType","toLowerCase","isJsonResponse","includes","jsonResponse","clone","json","resolveResponse","Promise","reject","textResponse","text","responseToReturn","responsePromise","undefined","then","catch"],"mappings":"AAEA;;;IAIO,eAAeA,eAAAA,CACpBC,QAAkB,EAAA;AAElB,IAAA,IAAIA,QAASC,CAAAA,MAAM,KAAK,GAAA,IAAOD,SAASE,OAAO,CAACC,GAAG,CAAC,gBAAsB,CAAA,KAAA,GAAA,EACxE,OACEH,QAAAA,CAASI,EAAE,GAAG;AAAEC,QAAAA,IAAAA,EAAM,EAAC;AAAGL,QAAAA,QAAAA;KAAa,GAAA;AAAEM,QAAAA,KAAAA,EAAO,EAAC;AAAGN,QAAAA,QAAAA;AAAS,KAAA,CAAA;AAGjE,IAAA,MAAMO,cAAcP,QAASE,CAAAA,OAAO,CAACC,GAAG,CAAC,cAAiBK,CAAAA,EAAAA,WAAAA,EAAAA,CAAAA;AAE1D,IAAA,MAAMC,cACJF,GAAAA,WAAAA,EAAaG,QAAS,CAAA,OAAA,CAAA,IAAYH,aAAaG,QAAS,CAAA,OAAA,CAAA,CAAA;AAE1D,IAAA,IAAID,cAAgB,EAAA;;AAElB,QAAA,MAAME,YAAeX,GAAAA,QAAAA,CAASY,KAAK,EAAA,CAAGC,IAAI,EAAA,CAAA;QAC1C,OAAOC,eAAAA,CACLd,UACAA,QAASI,CAAAA,EAAE,GAAGO,YAAeI,GAAAA,OAAAA,CAAQC,MAAM,CAAC,MAAML,YAAAA,CAAAA,CAAAA,CAAAA;AAEtD,KAAA;AAEA,IAAA,MAAMM,YAAejB,GAAAA,QAAAA,CAASY,KAAK,EAAA,CAAGM,IAAI,EAAA,CAAA;IAE1C,OAAOJ,eAAAA,CACLd,UACAA,QAASI,CAAAA,EAAE,GAAGa,YAAeF,GAAAA,OAAAA,CAAQC,MAAM,CAAC,MAAMC,YAAAA,CAAAA,CAAAA,CAAAA;AAEtD,CAAA;AAaO,SAASH,eAAAA,CACdK,gBAAkC,EAClCC,eAAgC,EAAA;AAEhC,IAAA,IAAI,CAACA,eAAAA,EACH,OAAOL,OAAAA,CAAQC,MAAM,CAAC;QACpBV,KAAOa,EAAAA,gBAAAA;QACPnB,QAAUqB,EAAAA,SAAAA;QACVhB,IAAMgB,EAAAA,SAAAA;AACR,KAAA,CAAA,CAAA;AAEF,IAAA,OAAOD,eACJE,CAAAA,IAAI,CACH,CAACjB,QACE;AAAEA,YAAAA,IAAAA;YAAML,QAAUmB,EAAAA,gBAAAA;AAAiB,SAAA,CAKvCI,CAAAA,CAAAA,KAAK,CACJ,CAACjB,SACE;AAAEA,YAAAA,KAAAA;YAAON,QAAUmB,EAAAA,gBAAAA;SAAiB,CAAA,CAAA,CAAA;AAK7C;;;;"}
@@ -0,0 +1,2 @@
1
+ export { processResponse, resolveResponse } from './lib/responseUtils.js';
2
+ //# sourceMappingURL=unstable__responseUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unstable__responseUtils.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -15,7 +15,7 @@ import type { HeadersOptions, OperationSchema, RequestFnInfo, RequestFnOptions,
15
15
  export declare function requestFn<TData, TError>(schema: OperationSchema, requestInfo: RequestFnInfo, options?: RequestFnOptions): Promise<RequestFnResponse<TData, TError>>;
16
16
  /**
17
17
  * This function is used to make a request to a specified endpoint.
18
- * It's needed to create a custom `requestFn` with a custom `urlSerializer`
18
+ * It's necessary to create a custom `requestFn` with a custom `urlSerializer`
19
19
  * and `bodySerializer`, with the tree-shaking of the default `requestFn`
20
20
  * and its serializers.
21
21
  *
@@ -47,7 +47,22 @@ export declare function baseRequestFn<TData, TError>(requestSchema: OperationSch
47
47
  */
48
48
  export declare function urlSerializer(schema: OperationSchema, info: Pick<RequestFnInfo, 'baseUrl' | 'parameters'>): string;
49
49
  export declare function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]): Headers;
50
- export declare function bodySerializer(schema: OperationSchema, info: RequestFnInfo): string | FormData | Blob | undefined;
50
+ export declare function bodySerializer(schema: OperationSchema, body: RequestFnInfo['body']): {
51
+ body: string;
52
+ headers: {
53
+ 'Content-Type': string;
54
+ };
55
+ } | {
56
+ body: FormData;
57
+ headers: {
58
+ 'Content-Type': null;
59
+ };
60
+ } | {
61
+ body: Blob;
62
+ headers: {
63
+ 'Content-Type': string;
64
+ };
65
+ } | undefined;
51
66
  type WithRequired<T, K extends keyof T> = T & {
52
67
  [_ in K]: {};
53
68
  };
@@ -1 +1 @@
1
- {"version":3,"file":"requestFn.d.ts","sourceRoot":"","sources":["../../../src/lib/requestFn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,2CAA2C,CAAC;AAEnD;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAC3C,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,aAAa,EAC1B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAM3C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAC/C,aAAa,EAAE,eAAe,EAC9B,WAAW,EAAE,aAAa,EAC1B,OAAO,EAAE,YAAY,CAAC,gBAAgB,EAAE,eAAe,GAAG,gBAAgB,CAAC,GAC1E,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CA0B3C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,YAAY,CAAC,GAClD,MAAM,CAqBR;AAoCD,wBAAgB,YAAY,CAAC,GAAG,UAAU,EAAE,CAAC,cAAc,GAAG,SAAS,CAAC,EAAE,WAuBzE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,aAAa,wCAuB1E;AAsHD,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG;KAC3C,CAAC,IAAI,CAAC,GAAG,EAAE;CACb,CAAC;AAEF,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,eAAe,GAChB,MAAM,2CAA2C,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC"}
1
+ {"version":3,"file":"requestFn.d.ts","sourceRoot":"","sources":["../../../src/lib/requestFn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,2CAA2C,CAAC;AAGnD;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAC3C,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,aAAa,EAC1B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAM3C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAC/C,aAAa,EAAE,eAAe,EAC9B,WAAW,EAAE,aAAa,EAC1B,OAAO,EAAE,YAAY,CAAC,gBAAgB,EAAE,eAAe,GAAG,gBAAgB,CAAC,GAC1E,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAoB3C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,YAAY,CAAC,GAClD,MAAM,CAqBR;AAoCD,wBAAgB,YAAY,CAAC,GAAG,UAAU,EAAE,CAAC,cAAc,GAAG,SAAS,CAAC,EAAE,WAuBzE;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;cAyF5B;AAgCD,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG;KAC3C,CAAC,IAAI,CAAC,GAAG,EAAE;CACb,CAAC;AAEF,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,eAAe,GAChB,MAAM,2CAA2C,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { RequestFnResponse } from '@openapi-qraft/tanstack-query-react-types';
2
+ /**
3
+ * Processes the response from the server.
4
+ * @beta
5
+ */
6
+ export declare function processResponse<TData, TError>(response: Response): Promise<RequestFnResponse<TData, TError>>;
7
+ /**
8
+ * Resolves the response from the server.
9
+ * @beta
10
+ */
11
+ export declare function resolveResponse<TData, TError>(error: Error): Promise<RequestFnResponse<TData, TError>>;
12
+ export declare function resolveResponse<TData, TError>(responseToReturn: Response, responsePromise: Promise<TData>): Promise<RequestFnResponse<TData, TError>>;
13
+ //# sourceMappingURL=responseUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseUtils.d.ts","sourceRoot":"","sources":["../../../src/lib/responseUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAEnF;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EACjD,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CA0B3C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAC3C,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAC7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAC3C,gBAAgB,EAAE,QAAQ,EAC1B,eAAe,EAAE,OAAO,CAAC,KAAK,CAAC,GAC9B,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { resolveResponse, processResponse } from './lib/responseUtils.js';
2
+ //# sourceMappingURL=unstable__responseUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unstable__responseUtils.d.ts","sourceRoot":"","sources":["../../src/unstable__responseUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openapi-qraft/react",
3
- "version": "2.0.0-next.10",
3
+ "version": "2.0.0-next.12",
4
4
  "description": "OpenAPI client for React, providing type-safe requests and dynamic TanStack Query React Hooks via a modular, Proxy-based architecture.",
5
5
  "scripts": {
6
6
  "build": "NODE_ENV=production rollup --config rollup.config.mjs && tsc --project tsconfig.build.json --emitDeclarationOnly",
@@ -11,18 +11,19 @@
11
11
  "lint": "eslint",
12
12
  "clean": "rimraf dist/",
13
13
  "codegen": "openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript ../test-fixtures/openapi.json -rm -o src/tests/fixtures/api --openapi-types-file-name openapi.ts --explicit-import-extensions --filter-services '/approval_policies/**,/entities/**,/files/**,!/internal/**' --operation-predefined-parameters '/approval_policies/{approval_policy_id}/**:header.x-monite-entity-id' '/entities/{entity_id}/documents:header.x-monite-version' --operation-name-modifier '/files/list:[a-zA-Z]+List ==> findAll' && yarn _prettify-api",
14
+ "codegen2": "openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript http://localhost:3000/api/doc -rm -o src/tests/fixtures/api --openapi-types-file-name openapi.ts --explicit-import-extensions && yarn _prettify-api",
14
15
  "_prettify-api": "prettier --write src/tests/fixtures/api/**/*.ts"
15
16
  },
16
17
  "sideEffects": false,
17
18
  "dependencies": {
18
- "@openapi-qraft/tanstack-query-react-types": "2.0.0-next.10"
19
+ "@openapi-qraft/tanstack-query-react-types": "2.0.0-next.12"
19
20
  },
20
21
  "devDependencies": {
21
- "@openapi-qraft/cli": "2.0.0-next.10",
22
+ "@openapi-qraft/cli": "2.0.0-next.12",
22
23
  "@openapi-qraft/eslint-config": "1.0.0",
23
- "@openapi-qraft/openapi-typescript-plugin": "^1.2.0-next.10",
24
+ "@openapi-qraft/openapi-typescript-plugin": "^1.2.0-next.12",
24
25
  "@openapi-qraft/rollup-config": "1.1.0-next.0",
25
- "@openapi-qraft/tanstack-query-react-plugin": "2.0.0-next.10",
26
+ "@openapi-qraft/tanstack-query-react-plugin": "2.0.0-next.12",
26
27
  "@openapi-qraft/test-fixtures": "1.0.0",
27
28
  "@tanstack/react-query": "^5.56.2",
28
29
  "@testing-library/jest-dom": "^5.17.0",
@@ -41,7 +42,7 @@
41
42
  "query-string": "^8.2.0",
42
43
  "react": "^18.3.1",
43
44
  "rimraf": "^5.0.10",
44
- "rollup": "~4.21.3",
45
+ "rollup": "~4.22.4",
45
46
  "vitest": "^1.6.0"
46
47
  },
47
48
  "peerDependencies": {
@@ -77,6 +78,11 @@
77
78
  "require": "./dist/cjs/qraftPredefinedParametersRequestFn.cjs",
78
79
  "types": "./dist/types/qraftPredefinedParametersRequestFn.d.ts"
79
80
  },
81
+ "./unstable__responseUtils": {
82
+ "import": "./dist/esm/unstable__responseUtils.js",
83
+ "require": "./dist/cjs/unstable__responseUtils.cjs",
84
+ "types": "./dist/types/unstable__responseUtils.d.ts"
85
+ },
80
86
  "./package.json": "./package.json"
81
87
  },
82
88
  "typesVersions": {
@@ -5,6 +5,7 @@ import type {
5
5
  RequestFnOptions,
6
6
  RequestFnResponse,
7
7
  } from '@openapi-qraft/tanstack-query-react-types';
8
+ import { processResponse, resolveResponse } from './responseUtils.js';
8
9
 
9
10
  /**
10
11
  * This function is used to make a request to a specified endpoint.
@@ -33,7 +34,7 @@ export async function requestFn<TData, TError>(
33
34
 
34
35
  /**
35
36
  * This function is used to make a request to a specified endpoint.
36
- * It's needed to create a custom `requestFn` with a custom `urlSerializer`
37
+ * It's necessary to create a custom `requestFn` with a custom `urlSerializer`
37
38
  * and `bodySerializer`, with the tree-shaking of the default `requestFn`
38
39
  * and its serializers.
39
40
  *
@@ -54,24 +55,18 @@ export async function baseRequestFn<TData, TError>(
54
55
  ): Promise<RequestFnResponse<TData, TError>> {
55
56
  const { parameters, headers, body, ...requestInfoRest } = requestInfo;
56
57
 
57
- const requestBody = options.bodySerializer(requestSchema, requestInfo);
58
+ const requestPayload = options.bodySerializer(requestSchema, body);
58
59
 
59
60
  const baseFetch = options.fetch ?? fetch;
60
61
 
61
62
  return baseFetch(options.urlSerializer(requestSchema, requestInfo), {
62
63
  method: requestSchema.method.toUpperCase(),
63
- body: requestBody,
64
+ body: requestPayload?.body,
64
65
  headers: mergeHeaders(
65
- {
66
- Accept: 'application/json',
67
- 'Content-Type': requestSchema.mediaType ?? getBodyContentType(body),
68
- },
66
+ { Accept: 'application/json' },
67
+ requestPayload?.headers,
69
68
  headers,
70
- parameters?.header,
71
- requestBody instanceof FormData
72
- ? // remove `Content-Type` if the serialized body is FormData; the browser will correctly set Content-Type & boundary expression
73
- { 'Content-Type': null }
74
- : undefined
69
+ parameters?.header
75
70
  ),
76
71
  ...requestInfoRest,
77
72
  })
@@ -179,46 +174,103 @@ export function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]) {
179
174
  return headers;
180
175
  }
181
176
 
182
- export function bodySerializer(schema: OperationSchema, info: RequestFnInfo) {
183
- if (info.body === undefined) return;
184
-
177
+ export function bodySerializer(
178
+ schema: OperationSchema,
179
+ body: RequestFnInfo['body']
180
+ ) {
185
181
  if (
186
182
  schema.method === 'get' ||
187
183
  schema.method === 'head' ||
188
184
  schema.method === 'options'
189
185
  )
190
- return;
186
+ return undefined;
187
+
188
+ if (body === undefined || body === null) return undefined;
189
+
190
+ if (typeof body === 'string') {
191
+ return {
192
+ body,
193
+ headers: {
194
+ 'Content-Type':
195
+ // prefer text/* media type
196
+ schema.mediaType?.find((mediaType) => mediaType.includes('text/')) ??
197
+ // prefer JSON media type, assume that body is serialized as JSON
198
+ schema.mediaType?.find((mediaType) => mediaType.includes('/json')) ??
199
+ 'text/plain',
200
+ },
201
+ };
202
+ }
191
203
 
192
- if (schema.mediaType?.includes('/form-data'))
193
- return getRequestBodyFormData(info);
204
+ if (body instanceof FormData) {
205
+ return {
206
+ body,
207
+ headers: {
208
+ // remove `Content-Type` if the serialized body is FormData;
209
+ // the browser will correctly set Content-Type & boundary expression
210
+ 'Content-Type': null,
211
+ },
212
+ };
213
+ }
194
214
 
195
- if (
196
- !schema.mediaType?.includes('/json') &&
197
- (typeof info.body === 'string' ||
198
- info.body instanceof Blob ||
199
- info.body instanceof FormData)
200
- ) {
201
- return info.body;
215
+ if (body instanceof Blob) {
216
+ return {
217
+ body,
218
+ headers: {
219
+ 'Content-Type':
220
+ body.type ||
221
+ schema.mediaType?.find(
222
+ (mediaType) =>
223
+ !(
224
+ mediaType.includes('text/') &&
225
+ mediaType.includes('/form-data') &&
226
+ mediaType.includes('/json')
227
+ )
228
+ ) ||
229
+ 'application/octet-stream',
230
+ },
231
+ };
202
232
  }
203
233
 
204
- return JSON.stringify(info.body);
234
+ let jsonMediaType: string | null = null;
235
+ let formDataMediaType: string | null = null;
236
+
237
+ if (schema.mediaType) {
238
+ for (let i = 0; i < schema.mediaType.length; i++) {
239
+ const mediaType = schema.mediaType[i];
240
+ if (mediaType.includes('/json')) jsonMediaType = mediaType;
241
+ else if (mediaType.includes('/form-data')) formDataMediaType = mediaType;
242
+ }
243
+ }
244
+
245
+ if (formDataMediaType) {
246
+ if (
247
+ !jsonMediaType ||
248
+ // Prefer FormData serialization if one of the fields is a Blob
249
+ Object.values(body).some((value) => value instanceof Blob)
250
+ ) {
251
+ return {
252
+ body: getRequestBodyFormData(body),
253
+ headers: {
254
+ // remove `Content-Type` if the serialized body is FormData;
255
+ // the browser will correctly set Content-Type & boundary expression
256
+ 'Content-Type': null,
257
+ },
258
+ };
259
+ }
260
+ }
261
+
262
+ return {
263
+ body: JSON.stringify(body),
264
+ headers: {
265
+ 'Content-Type': jsonMediaType ?? 'application/json',
266
+ },
267
+ };
205
268
  }
206
269
 
207
- function getRequestBodyFormData({
208
- body,
209
- }: Pick<RequestFnInfo, 'body'>): FormData | undefined {
270
+ function getRequestBodyFormData(
271
+ body: NonNullable<RequestFnInfo['body']>
272
+ ): FormData {
210
273
  if (body instanceof FormData) return body;
211
- if (body === null) return;
212
-
213
- if (body instanceof Blob) throw new Error('Blob not supported in form-data');
214
- if (body instanceof ArrayBuffer)
215
- throw new Error('ArrayBuffer not supported in form-data');
216
- if (body instanceof URLSearchParams)
217
- throw new Error('URLSearchParams not supported in form-data');
218
- if (body instanceof ReadableStream)
219
- throw new Error('ReadableStream not supported in form-data');
220
- if (typeof body === 'string')
221
- throw new Error('String not supported in form-data');
222
274
  if (typeof body !== 'object')
223
275
  throw new Error(`Unsupported body type ${typeof body} in form-data.`);
224
276
 
@@ -245,81 +297,6 @@ function getRequestBodyFormData({
245
297
  return formData;
246
298
  }
247
299
 
248
- function getBodyContentType(body: RequestFnInfo['body']) {
249
- if (!body) return;
250
- if (body instanceof Blob) return body.type || 'application/octet-stream';
251
- if (typeof body === 'string') return 'text/plain';
252
- if (!(body instanceof FormData)) return 'application/json';
253
- }
254
-
255
- async function processResponse<TData, TError>(
256
- response: Response
257
- ): Promise<RequestFnResponse<TData, TError>> {
258
- if (response.status === 204 || response.headers.get('Content-Length') === '0')
259
- return (
260
- response.ok ? { data: {}, response } : { error: {}, response }
261
- ) as RequestFnResponse<TData, TError>;
262
-
263
- if (isJsonResponse(response)) {
264
- // clone response before parsing every time to allow multiple reads
265
- const jsonResponse = response.clone().json();
266
- return resolveResponse(
267
- response,
268
- response.ok ? jsonResponse : Promise.reject(await jsonResponse)
269
- );
270
- }
271
-
272
- const jsonResponse = new Promise<TData>((resolve, reject) =>
273
- // attempt to parse JSON for successful responses, otherwise fail
274
- response.clone().text().then(JSON.parse).then(resolve, reject)
275
- );
276
-
277
- return resolveResponse(
278
- response,
279
- response.ok ? jsonResponse : Promise.reject(await jsonResponse)
280
- );
281
- }
282
-
283
- function isJsonResponse(response: Response) {
284
- const contentType = response.headers.get('Content-Type')?.toLowerCase();
285
- return contentType?.includes('/json') || contentType?.includes('+json');
286
- }
287
-
288
- function resolveResponse<TData, TError>(
289
- error: Error
290
- ): Promise<RequestFnResponse<TData, TError>>;
291
- function resolveResponse<TData, TError>(
292
- responseToReturn: Response,
293
- responsePromise: Promise<TData>
294
- ): Promise<RequestFnResponse<TData, TError>>;
295
- function resolveResponse<TData, TError>(
296
- responseToReturn: Response | Error,
297
- responsePromise?: Promise<TData>
298
- ): Promise<RequestFnResponse<TData, TError>> {
299
- if (!responsePromise)
300
- return Promise.reject({
301
- error: responseToReturn,
302
- response: undefined,
303
- data: undefined,
304
- });
305
-
306
- return responsePromise
307
- .then(
308
- (data) =>
309
- ({ data, response: responseToReturn }) as RequestFnResponse<
310
- TData,
311
- TError
312
- >
313
- )
314
- .catch(
315
- (error) =>
316
- ({ error, response: responseToReturn }) as RequestFnResponse<
317
- TData,
318
- TError
319
- >
320
- );
321
- }
322
-
323
300
  type WithRequired<T, K extends keyof T> = T & {
324
301
  [_ in K]: {};
325
302
  };
@@ -0,0 +1,74 @@
1
+ import type { RequestFnResponse } from '@openapi-qraft/tanstack-query-react-types';
2
+
3
+ /**
4
+ * Processes the response from the server.
5
+ * @beta
6
+ */
7
+ export async function processResponse<TData, TError>(
8
+ response: Response
9
+ ): Promise<RequestFnResponse<TData, TError>> {
10
+ if (response.status === 204 || response.headers.get('Content-Length') === '0')
11
+ return (
12
+ response.ok ? { data: {}, response } : { error: {}, response }
13
+ ) as RequestFnResponse<TData, TError>;
14
+
15
+ const contentType = response.headers.get('Content-Type')?.toLowerCase();
16
+
17
+ const isJsonResponse =
18
+ contentType?.includes('/json') || contentType?.includes('+json');
19
+
20
+ if (isJsonResponse) {
21
+ // clone response before parsing every time to allow multiple reads
22
+ const jsonResponse = response.clone().json();
23
+ return resolveResponse(
24
+ response,
25
+ response.ok ? jsonResponse : Promise.reject(await jsonResponse)
26
+ );
27
+ }
28
+
29
+ const textResponse = response.clone().text() as Promise<TData>;
30
+
31
+ return resolveResponse(
32
+ response,
33
+ response.ok ? textResponse : Promise.reject(await textResponse)
34
+ );
35
+ }
36
+
37
+ /**
38
+ * Resolves the response from the server.
39
+ * @beta
40
+ */
41
+ export function resolveResponse<TData, TError>(
42
+ error: Error
43
+ ): Promise<RequestFnResponse<TData, TError>>;
44
+ export function resolveResponse<TData, TError>(
45
+ responseToReturn: Response,
46
+ responsePromise: Promise<TData>
47
+ ): Promise<RequestFnResponse<TData, TError>>;
48
+ export function resolveResponse<TData, TError>(
49
+ responseToReturn: Response | Error,
50
+ responsePromise?: Promise<TData>
51
+ ): Promise<RequestFnResponse<TData, TError>> {
52
+ if (!responsePromise)
53
+ return Promise.reject({
54
+ error: responseToReturn,
55
+ response: undefined,
56
+ data: undefined,
57
+ });
58
+
59
+ return responsePromise
60
+ .then(
61
+ (data) =>
62
+ ({ data, response: responseToReturn }) as RequestFnResponse<
63
+ TData,
64
+ TError
65
+ >
66
+ )
67
+ .catch(
68
+ (error) =>
69
+ ({ error, response: responseToReturn }) as RequestFnResponse<
70
+ TData,
71
+ TError
72
+ >
73
+ );
74
+ }
@@ -0,0 +1 @@
1
+ export { resolveResponse, processResponse } from './lib/responseUtils.js';