UNPKG

@timwheeler/monkey-fetch

Version:

Monkey-patch library for the native fetch API

135 lines (134 loc) 6.25 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MonkeyFetch = void 0; class MonkeyFetch { constructor() { this.debug = false; this.interceptors = { request: (resource, options) => Promise.resolve([resource, options]), requestError: (error) => Promise.reject(error), response: (response) => Promise.resolve(response), responseError: (response) => Promise.reject(response), }; this.getCurrentRuntimeContext(); } /** * @description Determine the current JS runtime context, either Browser or Node.js */ getCurrentRuntimeContext() { const isBrowserExecutionContext = typeof window !== 'undefined'; this.debugLog(isBrowserExecutionContext ? 'Browser runtime' : 'Node Runtime'); if (isBrowserExecutionContext) { require('whatwg-fetch'); } else { require('./fetch-polyfill'); } } /** * @description Applies the default or user-supplied `request` and/or the `requestError` interceptors * @param {[(RequestInfo | URL), RequestInit]} args - the request arguments used to create the monkey-patched request * @returns {Promise<IMonkeyFetchResponse>} - the Promise containing the request arguments after interceptors have been applied */ applyRequestInterceptors(args) { return __awaiter(this, void 0, void 0, function* () { this.debugLog('Initial Request Args:', args); const { request, requestError } = this.interceptors; try { return request(...args); } catch (err) { return requestError(err); } }); } /** * @description Returns the monkey-patched promise that was either resolved or rejected * @param {Function} fetch - the Fetch API for the current JavaScript runtime context * @param {[(RequestInfo | URL), RequestInit]} args - the request arguments used to create the monkey-patched request * @returns {Promise<IMonkeyFetchResponse>} - the Promise containing the response with interceptors applied */ sendInterceptedRequest(fetch, args) { return __awaiter(this, void 0, void 0, function* () { const interceptedRequest = new Request(...args); try { const resolvedResponse = yield fetch(interceptedRequest); resolvedResponse.request = interceptedRequest; this.debugLog('Intercepted Request:', interceptedRequest); this.debugLog('Resolved Response:', resolvedResponse); return resolvedResponse; } catch (error) { error.request = interceptedRequest; return error; } }); } /** * @description Applies the default or user-supplied `response` and `responseError` interceptors * @param {IMonkeyFetchResponse} initialResponse - the initial, unaltered response before interceptors are applied * @returns {Promise<IMonkeyFetchResponse>} - the response with interceptors applied */ applyResponseInterceptors(initialResponse) { return __awaiter(this, void 0, void 0, function* () { const { response, responseError } = this.interceptors; try { const interceptedResponse = response(initialResponse); this.debugLog('Intercepted Response:', interceptedResponse); return yield interceptedResponse; } catch (err) { return yield responseError(err); } }); } /** * @description Applies all interceptors to the request and response objects * @param {Function} fetch - the Fetch API for the current JavaScript runtime context * @param {[(RequestInfo | URL), RequestInit]} args - the request arguments used to create the monkey-patched request * @returns {Promise<IMonkeyFetchResponse>} - the response with all interceptors applied */ applyInterceptors(fetch, ...args) { return __awaiter(this, void 0, void 0, function* () { const monkeyFetchRequestOptions = yield this.applyRequestInterceptors(args); const responseWithoutInterceptors = yield this.sendInterceptedRequest(fetch, monkeyFetchRequestOptions); return yield this.applyResponseInterceptors(responseWithoutInterceptors); }); } /** * Debugging tool for internal logging * @param {any} args - Arbitrary arguments to be emitted via logger * @returns {void} */ debugLog(...args) { if (this.debug) { console.warn(`[DEBUG] @timwheeler/monkey-fetch | `, ...args); } } /** * @description Custom, user-supplied configuration that is applied to `MonkeyFetch` * @param {IMonkeyFetchConfiguration} configuration - Custom configuration applied to all requests and responses * @returns {void} */ configure(configuration) { for (let configurationKey in configuration) { if (configurationKey in this.interceptors) { this.interceptors[configurationKey] = configuration[configurationKey]; } else { this[configurationKey] = configuration[configurationKey]; } } globalThis.fetch = ((fetch) => (...args) => this.applyInterceptors(fetch, ...args))(globalThis.fetch); } } exports.MonkeyFetch = MonkeyFetch;