UNPKG

@juit/lib-fetch-mock

Version:
225 lines (223 loc) 7.42 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // index.ts var index_exports = {}; __export(index_exports, { FetchMock: () => FetchMock, sendData: () => sendData, sendJson: () => sendJson, sendStatus: () => sendStatus, sendText: () => sendText }); module.exports = __toCommonJS(index_exports); var import_node_assert = __toESM(require("node:assert")); var import_node_http = require("node:http"); var mockSymbol = /* @__PURE__ */ Symbol.for("juit.fetch.mock"); process.on("exit", () => process.exit(process.exitCode)); var FetchMockImpl = class { _handlers = []; _fetch; _baseurl; constructor(baseurl) { this._baseurl = new URL(baseurl || "http://test/"); } /* === FETCH ============================================================== */ async $fetch(info, init) { (0, import_node_assert.default)(this._fetch, "Global `fetch` not available (mock not enabled?)"); const realFetch = this._fetch; const fetchWrapper = (info2, init2) => realFetch.call(globalThis, info2, init2); let response = void 0; for (const handler of this._handlers) { const request = info instanceof URL || typeof info === "string" ? new Request(new URL(info, this._baseurl), init) : new Request(info.url, info); const result = await handler(request, fetchWrapper); if (result === void 0 || result === null) continue; response = typeof result === "number" ? sendStatus(result) : result; break; } if (response) return response; if (this._fetch[mockSymbol]) { return this._fetch[mockSymbol].$fetch(info, init); } return sendStatus(404); } /* === HANDLERS =========================================================== */ on(method, path, handler) { this._handlers.push((request, fetch) => { if (request.method !== method.toUpperCase()) return; const pathname = new URL(request.url).pathname; if (typeof path === "string" && path === pathname || path instanceof RegExp && pathname.match(path)) { return handler(request, fetch); } }); return this; } handle(handler) { this._handlers.push(handler); return this; } reset() { this._handlers = []; return this; } /* === INTERCEPTOR ======================================================== */ intercept() { const queue = []; queue.push(new Deferred()); const next = () => { return new Promise((resolve, reject) => { queue[0].promise.then((request) => { queue.splice(0, 1); resolve(request); }, reject); }); }; this._handlers.push((request, fetch) => { queue.push(new Deferred()); const deferredResponse = new Deferred(); const deferredRequest = new DeferredRequestImpl(request, deferredResponse, fetch); queue[queue.length - 2].resolve(deferredRequest); return deferredResponse.promise; }); return next; } /* === INSTALL / DESTROY ================================================== */ install() { if (mockSymbol in globalThis.fetch) { if (globalThis.fetch[mockSymbol] === this) return this; } let fn = globalThis.fetch; while (fn && fn[mockSymbol]) { if (fn[mockSymbol] === this) { throw new Error("Global `fetch` already mocked by this instance"); } else { fn = fn[mockSymbol]._fetch; } } this._fetch = globalThis.fetch; globalThis.fetch = this.$fetch.bind(this); Object.defineProperty(globalThis.fetch, mockSymbol, { value: this }); return this; } destroy() { if (!(mockSymbol in globalThis.fetch)) return; if (!this._fetch) return; let parent = void 0; let fn = globalThis.fetch; while (fn[mockSymbol]) { if (fn[mockSymbol] === this) { if (!parent) globalThis.fetch = this._fetch; else parent._fetch = this._fetch; break; } else { parent = fn[mockSymbol]; fn = fn[mockSymbol]._fetch; } } this._fetch = void 0; } }; var FetchMock = FetchMockImpl; var Deferred = class { promise; resolve; reject; constructor() { let resolve; let reject; this.promise = new Promise((resolver, rejector) => { resolve = resolver; reject = rejector; }); this.resolve = resolve; this.reject = reject; } }; var DeferredRequestImpl = class extends Request { constructor(request, _deferred, _fetch) { super(request); this._deferred = _deferred; this._fetch = _fetch; } _deferred; _fetch; fail(failure) { this._deferred.reject(failure || new Error(`Error: ${this.url}`)); } fetch(...args) { this._deferred.resolve(this._fetch(...args)); } send(response) { this._deferred.resolve(response || new Response()); } sendStatus(status) { this._deferred.resolve(sendStatus(status)); } sendText(text, status = 200) { this._deferred.resolve(sendText(text, status)); } sendJson(json, status = 200) { this._deferred.resolve(sendJson(json, status)); } sendData(data, status = 200) { this._deferred.resolve(sendData(data, status)); } }; function sendStatus(status, statusText = import_node_http.STATUS_CODES[status]) { return new Response(void 0, { status, statusText }); } function sendText(text, status = 200) { return new Response(text, { headers: { "content-type": "text/plain; charset=utf-8" }, statusText: import_node_http.STATUS_CODES[status], status }); } function sendJson(data, status = 200) { return new Response(JSON.stringify(data), { headers: { "content-type": "application/json; charset=utf-8" }, statusText: import_node_http.STATUS_CODES[status], status }); } function sendData(data, status = 200) { return new Response(Buffer.from(data), { headers: { "content-type": "application/octet-stream" }, statusText: import_node_http.STATUS_CODES[status], status }); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { FetchMock, sendData, sendJson, sendStatus, sendText }); //# sourceMappingURL=index.cjs.map