@nhost/nhost-js
Version:
Nhost JavaScript SDK
98 lines • 3.51 kB
JavaScript
/**
* Creates an enhanced fetch function using a chain of middleware functions.
*
* The fetch chain executes in the order of the array, with each middleware
* wrapping the next one in the chain. This allows each middleware to
* intercept both the request (before calling next) and the response
* (after calling next).
*
* @example
* ```typescript
* // Simple logging middleware
* const loggingMiddleware: ChainFunction = (next) => {
* return async (url, options) => {
* console.log(`Request to ${url}`);
* const response = await next(url, options);
* console.log(`Response from ${url}: ${response.status}`);
* return response;
* };
* };
*
* const enhancedFetch = createEnhancedFetch([loggingMiddleware]);
* const response = await enhancedFetch('https://api.example.com/data');
* ```
*
* @param chainFunctions - Array of chain functions to apply in order
* @returns Enhanced fetch function with all middleware applied
*/
export function createEnhancedFetch(chainFunctions = []) {
// Build the chain starting with vanilla fetch, but apply functions in reverse
// to achieve the desired execution order
return chainFunctions.reduceRight((nextInChain, chainFunction) => chainFunction(nextInChain), fetch);
}
function extractMessage(body) {
if (body && typeof body === 'string') {
return body;
}
if (body && typeof body === 'object') {
const typedBody = body;
if ('message' in typedBody && typeof typedBody['message'] === 'string') {
return typedBody['message'];
}
if ('error' in typedBody && typeof typedBody['error'] === 'string') {
return typedBody['error'];
}
if ('error' in typedBody &&
typedBody['error'] &&
typeof typedBody['error'] === 'object') {
const error = typedBody['error'];
if ('message' in error && typeof error['message'] === 'string') {
return error['message'];
}
}
if ('errors' in typedBody && Array.isArray(typedBody['errors'])) {
const messages = typedBody['errors']
.filter((error) => typeof error === 'object' &&
error !== null &&
'message' in error &&
typeof error['message'] === 'string')
.map((error) => error['message']);
if (messages.length > 0) {
return messages.join(', ');
}
}
}
return 'An unexpected error occurred';
}
/**
* Error class for representing fetch operation failures.
*
* This class extends the standard Error to include additional
* information about failed requests, including the response body,
* status code, and headers. The error message is automatically
* extracted from common error response formats.
*
* @template T - The type of the response body
*/
export class FetchError extends Error {
/** The original response body */
body;
/** HTTP status code of the failed response */
status;
/** Response headers */
headers;
/**
* Creates a new FetchError instance
*
* @param body - The response body from the failed request
* @param status - The HTTP status code
* @param headers - The response headers
*/
constructor(body, status, headers) {
super(extractMessage(body));
this.body = body;
this.status = status;
this.headers = headers;
}
}
//# sourceMappingURL=fetch.js.map