UNPKG

fake-api-middleware

Version:

Express/Connect middleware for dummy responses

249 lines (240 loc) 7.52 kB
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( isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { debounce: () => debounce, delay: () => delay, isString: () => isString, middleware: () => middleware, vitePlugin: () => vitePlugin }); module.exports = __toCommonJS(src_exports); // src/middleware.ts var import_node_http = require("http"); var querystring = __toESM(require("querystring")); var import_co_body = __toESM(require("co-body")); // src/responsesLoader.ts var import_node_events = require("events"); var chokidar = __toESM(require("chokidar")); // src/helpers.ts var delay = (time) => { return new Promise((r) => { setTimeout(r, time); }); }; var isString = (value) => { return typeof value === "string" || value instanceof String; }; var debounce = (func, wait, immediate = false) => { let timeout = null; return (...args) => { const later = () => { timeout = null; if (!immediate) { func.apply(void 0, args); } }; const callNow = immediate && !timeout; if (timeout) { clearTimeout(timeout); } timeout = setTimeout(later, wait); if (callNow) { func.apply(void 0, args); } }; }; // src/module.ts var path = __toESM(require("path")); var fs = __toESM(require("fs")); var module2 = __toESM(require("module")); var import_esbuild = require("esbuild"); var _require = module2.createRequire(process.cwd()); var executeModule = (filePath, bundledCode) => { filePath = path.resolve(process.cwd(), filePath); const extension = path.extname(filePath); const extensions = module2.Module._extensions; const defaultLoader = extensions[extension]; extensions[extension] = (module3, filename) => { if (filename === filePath) { module3._compile(bundledCode, filename); } else { defaultLoader(module3, filename); } }; if (_require && _require.cache) { delete _require.cache[filePath]; } const raw = _require(filePath); const config = raw.__esModule ? raw.default : raw; if (defaultLoader) { extensions[extension] = defaultLoader; } return config; }; var extendedRequire = async (filePath) => { const pkg = JSON.parse( fs.readFileSync(path.join(process.cwd(), "package.json"), "utf8") ); const srcCode = await (async () => { const result = await (0, import_esbuild.build)({ entryPoints: [filePath], outfile: "out.js", write: false, platform: "node", bundle: true, format: "cjs", metafile: true, target: "es2015", external: [ "esbuild", ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {}), ...Object.keys(pkg.peerDependencies || {}) ], logLevel: "silent" }); const { text } = result.outputFiles[0]; return text; })(); return await executeModule(filePath, srcCode); }; // src/responsesLoader.ts var ResponsesLoader = class extends import_node_events.EventEmitter { constructor({ responsesFile, watchFiles }) { super(); this.responsesFile = responsesFile; if (isString(watchFiles)) { watchFiles = [watchFiles]; } this.watchFiles = watchFiles || []; chokidar.watch([this.responsesFile, ...this.watchFiles]).on( "all", debounce(async () => { try { const responsesConfig = await extendedRequire(this.responsesFile); this.emit("update", responsesConfig); } catch (e) { this.emit("error", e); } }, 100) ); } }; // src/middleware.ts var import_path_to_regexp = require("path-to-regexp"); var middleware = (middlewareOptions) => { const prepareResponses = (responses) => { const result = []; for (const [key, response] of Object.entries(responses)) { const [method, apiPath] = key.split(" "); result.push({ method, apiPath, matchUrlFn: (0, import_path_to_regexp.match)(apiPath, { decode: decodeURIComponent }), response }); } return result; }; let preparedResponses = prepareResponses(middlewareOptions.responses || {}); if (middlewareOptions.responsesFile) { const responsesConfigLoader = new ResponsesLoader({ responsesFile: middlewareOptions.responsesFile, watchFiles: middlewareOptions.watchFiles }); let wasErrorLastTime = false; responsesConfigLoader.on("update", (newResponses) => { preparedResponses = prepareResponses(newResponses); if (wasErrorLastTime) { console.info("[FakeResponses]", "Responses successfully loaded"); } }); responsesConfigLoader.on("error", (err) => { console.error("[FakeResponses]", err); wasErrorLastTime = true; }); } return async (req, res, next) => { if (middlewareOptions.enable !== void 0 && !middlewareOptions.enable) { return next(); } for (const { method, matchUrlFn, response } of preparedResponses) { const [url, queryStr] = req.url.split("?"); const matchResult = matchUrlFn(url); if (matchResult && req.method === method) { if (middlewareOptions.responseDelay) { await delay(middlewareOptions.responseDelay); } let body = {}; try { body = await (0, import_co_body.default)(req); } catch { } if (typeof response === "function") { const responseResult = await response({ body, query: querystring.parse(queryStr), headers: req.headers, params: matchResult.params, req, res }); if (responseResult === void 0) { return; } if (responseResult instanceof import_node_http.ServerResponse) { return responseResult; } res.setHeader("Content-Type", "application/json"); return res.end(JSON.stringify(responseResult)); } res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify(response)); } } return next(); }; }; // src/vitePlugin.ts var vitePlugin = (middlewareOptions) => { return { name: "vite-plugin-fake-response", configureServer(server) { server.middlewares.use(middleware(middlewareOptions)); } }; }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { debounce, delay, isString, middleware, vitePlugin });