UNPKG

fetch-mock-cache

Version:

Caching mock fetch implementation for all runtimes and frameworks.

102 lines (101 loc) 4.1 kB
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()); }); }; const textMimeWhitelist = { application: ["json", "javascript", "xml", "xhtml+xml", "ld+json"], image: ["svg+xml"], text: ["*"], }; function isTextMime(contentType) { const [type, subtype] = contentType.split("/"); if (type in textMimeWhitelist) { const subtypes = textMimeWhitelist[type]; return subtypes.includes("*") || subtypes.includes(subtype); } return false; } function uint8ToBase64(u8) { let binary = ""; const chunkSize = 0x8000; for (let i = 0; i < u8.length; i += chunkSize) { binary += String.fromCharCode(...u8.subarray(i, i + chunkSize)); } return btoa(binary); } const fatalTextDecoder = new TextDecoder("utf-8", { fatal: true }); export function serializeBody(response) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; if (response.body === null) return { body: null }; const contentType = ((_a = response.headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.split(";")[0]) || ""; // Possibly consider honoring this but maybe more useful for our use case to inspect const _nosniff = ((_b = response.headers.get("x-content-type-options")) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === "nosniff"; if (contentType === "application/json") { return response.json().then((bodyJson) => ({ bodyJson })); } else if (isTextMime(contentType)) { return response.text().then((bodyText) => ({ bodyText })); } // Try for text, otherwise encode the bytes as base64 const buffer = yield response.arrayBuffer(); const u8 = new Uint8Array(buffer); // Easy check - any null bytes? if (u8.indexOf(0) !== -1) { return { bodyBase64: uint8ToBase64(u8) }; } let bodyText = ""; try { bodyText = fatalTextDecoder.decode(u8); } catch (_c) { return { bodyBase64: uint8ToBase64(u8) }; } for (let i = 0; i < bodyText.length; i++) { const charCode = bodyText.charCodeAt(i); // Control characters except for common whitespace if ((charCode <= 0x1f && charCode !== 0x09 && charCode !== 0x0a && charCode !== 0x0d) || charCode === 0x7f) { return { bodyBase64: uint8ToBase64(u8) }; } } return { bodyText }; }); } export function deserializeBody(objWithBody) { return __awaiter(this, void 0, void 0, function* () { if ("body" in objWithBody) { if (objWithBody.body === null) { return null; } else { throw new Error("Invalid body: null expected"); } } else if ("bodyText" in objWithBody) { return objWithBody.bodyText; } else if ("bodyJson" in objWithBody) { return JSON.stringify(objWithBody.bodyJson); } else if ("bodyBase64" in objWithBody) { const binary = atob(objWithBody.bodyBase64); const len = binary.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binary.charCodeAt(i); } return bytes; } return null; }); }