fetch-mock-cache
Version:
Caching mock fetch implementation for all runtimes and frameworks.
102 lines (101 loc) • 4.1 kB
JavaScript
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;
});
}