UNPKG

vite-plugin-mock-dev-server

Version:
810 lines (800 loc) 28.7 kB
const require_dist = require('./dist-DrfpZ4UT.cjs'); const picocolors = require_dist.__toESM(require("picocolors")); const node_fs = require_dist.__toESM(require("node:fs")); const node_path = require_dist.__toESM(require("node:path")); const node_url = require_dist.__toESM(require("node:url")); const node_os = require_dist.__toESM(require("node:os")); const node_querystring = require_dist.__toESM(require("node:querystring")); const debug = require_dist.__toESM(require("debug")); const path_to_regexp = require_dist.__toESM(require("path-to-regexp")); const node_buffer = require_dist.__toESM(require("node:buffer")); const cookies = require_dist.__toESM(require("cookies")); const http_status = require_dist.__toESM(require("http-status")); const mime_types = require_dist.__toESM(require("mime-types")); const co_body = require_dist.__toESM(require("co-body")); const formidable = require_dist.__toESM(require("formidable")); const ws = require_dist.__toESM(require("ws")); //#region src/core/utils.ts function isStream(stream) { return stream !== null && typeof stream === "object" && typeof stream.pipe === "function"; } function isReadableStream(stream) { return isStream(stream) && stream.readable !== false && typeof stream._read === "function" && typeof stream._readableState === "object"; } const debug$1 = (0, debug.default)("vite:mock-dev-server"); function lookupFile(dir, formats, options) { for (const format of formats) { const fullPath = node_path.default.join(dir, format); if (node_fs.default.existsSync(fullPath) && node_fs.default.statSync(fullPath).isFile()) { const result = options?.pathOnly ? fullPath : node_fs.default.readFileSync(fullPath, "utf-8"); if (!options?.predicate || options.predicate(result)) return result; } } const parentDir = node_path.default.dirname(dir); if (parentDir !== dir && (!options?.rootDir || parentDir.startsWith(options?.rootDir))) return lookupFile(parentDir, formats, options); } function ensureProxies(serverProxy = {}) { const httpProxies = []; const wsProxies = []; Object.keys(serverProxy).forEach((key) => { const value = serverProxy[key]; if (typeof value === "string" || !value.ws && !value.target?.toString().startsWith("ws:") && !value.target?.toString().startsWith("wss:")) httpProxies.push(key); else wsProxies.push(key); }); return { httpProxies, wsProxies }; } function doesProxyContextMatchUrl(context, url) { return context[0] === "^" && new RegExp(context).test(url) || url.startsWith(context); } function parseParams(pattern, url) { const urlMatch = (0, path_to_regexp.match)(pattern, { decode: decodeURIComponent })(url) || { params: {} }; return urlMatch.params || {}; } /** * nodejs 从 19.0.0 开始 弃用 url.parse,因此使用 url.parse 来解析 可能会报错, * 使用 URL 来解析 */ function urlParse(input) { const url = new node_url.URL(input, "http://example.com"); const pathname = decodeURIComponent(url.pathname); const query = (0, node_querystring.parse)(url.search.replace(/^\?/, "")); return { pathname, query }; } const windowsSlashRE = /\\/g; const isWindows = node_os.default.platform() === "win32"; function slash(p) { return p.replace(windowsSlashRE, "/"); } function normalizePath(id) { return node_path.default.posix.normalize(isWindows ? slash(id) : id); } //#endregion //#region src/core/matchingWeight.ts const tokensCache = {}; function getTokens(rule) { if (tokensCache[rule]) return tokensCache[rule]; const tks = (0, path_to_regexp.parse)(rule); const tokens = []; for (const tk of tks) if (!require_dist.isString(tk)) tokens.push(tk); else { const hasPrefix = tk[0] === "/"; const subTks = hasPrefix ? tk.slice(1).split("/") : tk.split("/"); tokens.push(`${hasPrefix ? "/" : ""}${subTks[0]}`, ...subTks.slice(1).map((t) => `/${t}`)); } tokensCache[rule] = tokens; return tokens; } function getHighest(rules) { let weights = rules.map((rule) => getTokens(rule).length); weights = weights.length === 0 ? [1] : weights; return Math.max(...weights) + 2; } function sortFn(rule) { const tokens = getTokens(rule); let w = 0; for (let i = 0; i < tokens.length; i++) { const token = tokens[i]; if (!require_dist.isString(token)) w += 10 ** (i + 1); w += 10 ** (i + 1); } return w; } function preSort(rules) { let matched = []; const preMatch = []; for (const rule of rules) { const tokens = getTokens(rule); const len = tokens.filter((token) => typeof token !== "string").length; if (!preMatch[len]) preMatch[len] = []; preMatch[len].push(rule); } for (const match$1 of preMatch.filter((v) => v && v.length > 0)) matched = [...matched, ...require_dist.sortBy(match$1, sortFn).reverse()]; return matched; } function defaultPriority(rules) { const highest = getHighest(rules); return require_dist.sortBy(rules, (rule) => { const tokens = getTokens(rule); const dym = tokens.filter((token) => typeof token !== "string"); if (dym.length === 0) return 0; let weight = dym.length; let exp = 0; for (let i = 0; i < tokens.length; i++) { const token = tokens[i]; const isDynamic = !require_dist.isString(token); const { pattern = "", modifier, prefix, name } = isDynamic ? token : {}; const isGlob = pattern && pattern.includes(".*"); const isSlash = prefix === "/"; const isNamed = require_dist.isString(name); exp += isDynamic && isSlash ? 1 : 0; if (i === tokens.length - 1 && isGlob) weight += 5 * 10 ** (tokens.length === 1 ? highest + 1 : highest); else if (isGlob) weight += 3 * 10 ** (highest - 1); else if (pattern) if (isSlash) weight += (isNamed ? 2 : 1) * 10 ** (exp + 1); else weight -= 1 * 10 ** exp; if (modifier === "+") weight += 1 * 10 ** (highest - 1); if (modifier === "*") weight += 1 * 10 ** (highest - 1) + 1; if (modifier === "?") weight += 1 * 10 ** (exp + (isSlash ? 1 : 0)); } return weight; }); } function matchingWeight(rules, url, priority) { let matched = defaultPriority(preSort(rules.filter((rule) => (0, path_to_regexp.pathToRegexp)(rule).test(url)))); const { global = [], special = {} } = priority; if (global.length === 0 && require_dist.isEmptyObject(special) || matched.length === 0) return matched; const [statics, dynamics] = twoPartMatch(matched); const globalMatch = global.filter((rule) => dynamics.includes(rule)); if (globalMatch.length > 0) matched = require_dist.uniq([ ...statics, ...globalMatch, ...dynamics ]); if (require_dist.isEmptyObject(special)) return matched; const specialRule = Object.keys(special).filter((rule) => matched.includes(rule))[0]; if (!specialRule) return matched; const options = special[specialRule]; const { rules: lowerRules, when } = require_dist.isArray(options) ? { rules: options, when: [] } : options; if (lowerRules.includes(matched[0])) { if (when.length === 0 || when.some((path$1) => (0, path_to_regexp.pathToRegexp)(path$1).test(url))) matched = require_dist.uniq([specialRule, ...matched]); } return matched; } function twoPartMatch(rules) { const statics = []; const dynamics = []; for (const rule of rules) { const tokens = getTokens(rule); const dym = tokens.filter((token) => typeof token !== "string"); if (dym.length > 0) dynamics.push(rule); else statics.push(rule); } return [statics, dynamics]; } //#endregion //#region src/core/parseReqBody.ts const DEFAULT_FORMIDABLE_OPTIONS = { keepExtensions: true, filename(name, ext, part) { return part?.originalFilename || `${name}.${Date.now()}${ext ? `.${ext}` : ""}`; } }; async function parseReqBody(req, formidableOptions, bodyParserOptions = {}) { const method = req.method.toUpperCase(); if (["HEAD", "OPTIONS"].includes(method)) return void 0; const type = req.headers["content-type"]?.toLocaleLowerCase() || ""; const { limit, formLimit, jsonLimit, textLimit,...rest } = bodyParserOptions; try { if (type.startsWith("application/json")) return await co_body.default.json(req, { limit: jsonLimit || limit, ...rest }); if (type.startsWith("application/x-www-form-urlencoded")) return await co_body.default.form(req, { limit: formLimit || limit, ...rest }); if (type.startsWith("text/plain")) return await co_body.default.text(req, { limit: textLimit || limit, ...rest }); if (type.startsWith("multipart/form-data")) return await parseMultipart(req, formidableOptions); } catch (e) { console.error(e); } return void 0; } async function parseMultipart(req, options) { const form = (0, formidable.default)({ ...DEFAULT_FORMIDABLE_OPTIONS, ...options }); return new Promise((resolve, reject) => { form.parse(req, (error, fields, files) => { if (error) { reject(error); return; } resolve({ ...fields, ...files }); }); }); } //#endregion //#region src/core/requestRecovery.ts const cache = /* @__PURE__ */ new WeakMap(); function collectRequest(req) { const chunks = []; req.addListener("data", (chunk) => { chunks.push(node_buffer.Buffer.from(chunk)); }); req.addListener("end", () => { if (chunks.length) cache.set(req, node_buffer.Buffer.concat(chunks)); }); } /** * vite 在 proxy 配置中,允许通过 configure 访问 http-proxy 实例, * 通过 http-proxy 的 proxyReq 事件,重新写入请求流 */ function recoverRequest(config) { if (!config.server) return; const proxies = config.server.proxy || {}; Object.keys(proxies).forEach((key) => { const target = proxies[key]; const options = typeof target === "string" ? { target } : target; if (options.ws) return; const { configure,...rest } = options; proxies[key] = { ...rest, configure(proxy, options$1) { configure?.(proxy, options$1); proxy.on("proxyReq", (proxyReq, req) => { const buffer = cache.get(req); if (buffer) { cache.delete(req); /** * 使用 http-proxy 的 agent 配置会提前写入代理请求流 * https://github.com/http-party/node-http-proxy/issues/1287 */ if (!proxyReq.headersSent) proxyReq.setHeader("Content-Length", buffer.byteLength); if (!proxyReq.writableEnded) proxyReq.write(buffer); } }); } }; }); } //#endregion //#region src/core/validator.ts function validate(request, validator) { return isObjectSubset(request.headers, validator.headers) && isObjectSubset(request.body, validator.body) && isObjectSubset(request.params, validator.params) && isObjectSubset(request.query, validator.query) && isObjectSubset(request.refererQuery, validator.refererQuery); } /** * Checks if target object is a subset of source object. * That is, all properties and their corresponding values in target exist in source. * * 深度比较两个对象之间,target 是否属于 source 的子集, * 即 target 的所有属性和对应的值,都在 source 中, */ function isObjectSubset(source, target) { if (!target) return true; for (const key in target) if (!isIncluded(source[key], target[key])) return false; return true; } function isIncluded(source, target) { if (require_dist.isArray(source) && require_dist.isArray(target)) { const seen = /* @__PURE__ */ new Set(); return target.every((ti) => source.some((si, i) => { if (seen.has(i)) return false; const included = isIncluded(si, ti); if (included) seen.add(i); return included; })); } if (require_dist.isPlainObject(source) && require_dist.isPlainObject(target)) return isObjectSubset(source, target); return Object.is(source, target); } //#endregion //#region src/core/baseMiddleware.ts function baseMiddleware(compiler, { formidableOptions = {}, bodyParserOptions = {}, proxies, cookiesOptions, logger, priority = {} }) { return async function(req, res, next) { const startTime = require_dist.timestamp(); const { query, pathname } = urlParse(req.url); if (!pathname || proxies.length === 0 || !proxies.some((context) => doesProxyContextMatchUrl(context, req.url))) return next(); const mockData = compiler.mockData; const mockUrls = matchingWeight(Object.keys(mockData), pathname, priority); if (mockUrls.length === 0) return next(); collectRequest(req); const { query: refererQuery } = urlParse(req.headers.referer || ""); const reqBody = await parseReqBody(req, formidableOptions, bodyParserOptions); const cookies$1 = new cookies.default(req, res, cookiesOptions); const getCookie = cookies$1.get.bind(cookies$1); const method = req.method.toUpperCase(); let mock; let _mockUrl; for (const mockUrl of mockUrls) { mock = fineMock(mockData[mockUrl], logger, { pathname, method, request: { query, refererQuery, body: reqBody, headers: req.headers, getCookie } }); if (mock) { _mockUrl = mockUrl; break; } } if (!mock) { const matched = mockUrls.map((m) => m === _mockUrl ? picocolors.default.underline(picocolors.default.bold(m)) : picocolors.default.dim(m)).join(", "); logger.warn(`${picocolors.default.green(pathname)} matches ${matched} , but mock data is not found.`); return next(); } const request = req; const response = res; request.body = reqBody; request.query = query; request.refererQuery = refererQuery; request.params = parseParams(mock.url, pathname); request.getCookie = getCookie; response.setCookie = cookies$1.set.bind(cookies$1); const { body, delay, type = "json", response: responseFn, status = 200, statusText, log: logLevel, __filepath__: filepath } = mock; responseStatus(response, status, statusText); await provideHeaders(request, response, mock, logger); await provideCookies(request, response, mock, logger); logger.info(requestLog(request, filepath), logLevel); logger.debug(`${picocolors.default.magenta("DEBUG")} ${picocolors.default.underline(pathname)} matches: [ ${mockUrls.map((m) => m === _mockUrl ? picocolors.default.underline(picocolors.default.bold(m)) : picocolors.default.dim(m)).join(", ")} ]\n`); if (body) { try { const content = require_dist.isFunction(body) ? await body(request) : body; await realDelay(startTime, delay); sendData(response, content, type); } catch (e) { logger.error(`${picocolors.default.red(`mock error at ${pathname}`)}\n${e}\n at body (${picocolors.default.underline(filepath)})`, logLevel); responseStatus(response, 500); res.end(""); } return; } if (responseFn) { try { await realDelay(startTime, delay); await responseFn(request, response, next); } catch (e) { logger.error(`${picocolors.default.red(`mock error at ${pathname}`)}\n${e}\n at response (${picocolors.default.underline(filepath)})`, logLevel); responseStatus(response, 500); res.end(""); } return; } res.end(""); }; } function fineMock(mockList, logger, { pathname, method, request }) { return mockList.find((mock) => { if (!pathname || !mock || !mock.url || mock.ws === true) return false; const methods = mock.method ? require_dist.isArray(mock.method) ? mock.method : [mock.method] : ["GET", "POST"]; if (!methods.includes(method)) return false; const hasMock = (0, path_to_regexp.pathToRegexp)(mock.url).test(pathname); if (hasMock && mock.validator) { const params = parseParams(mock.url, pathname); if (require_dist.isFunction(mock.validator)) return mock.validator({ params, ...request }); else try { return validate({ params, ...request }, mock.validator); } catch (e) { const file = mock.__filepath__; logger.error(`${picocolors.default.red(`mock error at ${pathname}`)}\n${e}\n at validator (${picocolors.default.underline(file)})`, mock.log); return false; } } return hasMock; }); } function responseStatus(response, status = 200, statusText) { response.statusCode = status; response.statusMessage = statusText || getHTTPStatusText(status); } async function provideHeaders(req, res, mock, logger) { const { headers, type = "json" } = mock; const filepath = mock.__filepath__; const contentType = mime_types.contentType(type) || mime_types.contentType(mime_types.lookup(type) || ""); if (contentType) res.setHeader("Content-Type", contentType); res.setHeader("Cache-Control", "no-cache,max-age=0"); res.setHeader("X-Mock-Power-By", "vite-plugin-mock-dev-server"); if (filepath) res.setHeader("X-File-Path", filepath); if (!headers) return; try { const raw = require_dist.isFunction(headers) ? await headers(req) : headers; Object.keys(raw).forEach((key) => { res.setHeader(key, raw[key]); }); } catch (e) { logger.error(`${picocolors.default.red(`mock error at ${req.url.split("?")[0]}`)}\n${e}\n at headers (${picocolors.default.underline(filepath)})`, mock.log); } } async function provideCookies(req, res, mock, logger) { const { cookies: cookies$1 } = mock; const filepath = mock.__filepath__; if (!cookies$1) return; try { const raw = require_dist.isFunction(cookies$1) ? await cookies$1(req) : cookies$1; Object.keys(raw).forEach((key) => { const cookie = raw[key]; if (require_dist.isArray(cookie)) { const [value, options] = cookie; res.setCookie(key, value, options); } else res.setCookie(key, cookie); }); } catch (e) { logger.error(`${picocolors.default.red(`mock error at ${req.url.split("?")[0]}`)}\n${e}\n at cookies (${picocolors.default.underline(filepath)})`, mock.log); } } function sendData(res, raw, type) { if (isReadableStream(raw)) raw.pipe(res); else if (node_buffer.Buffer.isBuffer(raw)) res.end(type === "text" || type === "json" ? raw.toString("utf-8") : raw); else { const content = typeof raw === "string" ? raw : JSON.stringify(raw); res.end(type === "buffer" ? node_buffer.Buffer.from(content) : content); } } async function realDelay(startTime, delay) { if (!delay || typeof delay === "number" && delay <= 0 || require_dist.isArray(delay) && delay.length !== 2) return; let realDelay$1 = 0; if (require_dist.isArray(delay)) { const [min, max] = delay; realDelay$1 = require_dist.random(min, max); } else realDelay$1 = delay - (require_dist.timestamp() - startTime); if (realDelay$1 > 0) await require_dist.sleep(realDelay$1); } function getHTTPStatusText(status) { return http_status.default[status] || "Unknown"; } function requestLog(request, filepath) { const { url, method, query, params, body } = request; let { pathname } = new URL(url, "http://example.com"); pathname = picocolors.default.green(decodeURIComponent(pathname)); const format = (prefix, data) => { return !data || require_dist.isEmptyObject(data) ? "" : ` ${picocolors.default.gray(`${prefix}:`)}${JSON.stringify(data)}`; }; const ms = picocolors.default.magenta(picocolors.default.bold(method)); const qs = format("query", query); const ps = format("params", params); const bs = format("body", body); const file = ` ${picocolors.default.dim(picocolors.default.underline(`(${filepath})`))}`; return `${ms} ${pathname}${qs}${ps}${bs}${file}`; } //#endregion //#region src/core/transform.ts function transformRawData(raw, __filepath__) { let mockConfig; if (require_dist.isArray(raw)) mockConfig = raw.map((item) => ({ ...item, __filepath__ })); else if ("url" in raw) mockConfig = { ...raw, __filepath__ }; else { mockConfig = []; Object.keys(raw).forEach((key) => { const data = raw[key]; if (require_dist.isArray(data)) mockConfig.push(...data.map((item) => ({ ...item, __filepath__ }))); else mockConfig.push({ ...data, __filepath__ }); }); } return mockConfig; } function transformMockData(mockList) { const list = []; for (const [, handle] of mockList.entries()) if (handle) list.push(...require_dist.toArray(handle)); const mocks = {}; list.filter((mock) => require_dist.isPlainObject(mock) && mock.enabled !== false && mock.url).forEach((mock) => { const { pathname, query } = urlParse(mock.url); const list$1 = mocks[pathname] ??= []; const current = { ...mock, url: pathname }; if (current.ws !== true) { const validator = current.validator; if (!require_dist.isEmptyObject(query)) if (require_dist.isFunction(validator)) current.validator = function(request) { return isObjectSubset(request.query, query) && validator(request); }; else if (validator) { current.validator = { ...validator }; current.validator.query = current.validator.query ? { ...query, ...current.validator.query } : query; } else current.validator = { query }; } list$1.push(current); }); Object.keys(mocks).forEach((key) => { mocks[key] = sortByValidator(mocks[key]); }); return mocks; } function sortByValidator(mocks) { return require_dist.sortBy(mocks, (item) => { if (item.ws === true) return 0; const { validator } = item; if (!validator || require_dist.isEmptyObject(validator)) return 2; if (require_dist.isFunction(validator)) return 0; const count = Object.keys(validator).reduce((prev, key) => prev + keysCount(validator[key]), 0); return 1 / count; }); } function keysCount(obj) { if (!obj) return 0; return Object.keys(obj).length; } //#endregion //#region src/core/ws.ts /** * mock websocket */ function mockWebSocket(compiler, server, { wsProxies: proxies, cookiesOptions, logger }) { const hmrMap = /* @__PURE__ */ new Map(); const poolMap = /* @__PURE__ */ new Map(); const wssContextMap = /* @__PURE__ */ new WeakMap(); const getWssMap = (mockUrl) => { let wssMap = poolMap.get(mockUrl); if (!wssMap) poolMap.set(mockUrl, wssMap = /* @__PURE__ */ new Map()); return wssMap; }; const getWss = (wssMap, pathname) => { let wss = wssMap.get(pathname); if (!wss) wssMap.set(pathname, wss = new ws.WebSocketServer({ noServer: true })); return wss; }; const addHmr = (filepath, mockUrl) => { let urlList = hmrMap.get(filepath); if (!urlList) hmrMap.set(filepath, urlList = /* @__PURE__ */ new Set()); urlList.add(mockUrl); }; const setupWss = (wssMap, wss, mock, context, pathname, filepath) => { try { mock.setup?.(wss, context); wss.on("close", () => wssMap.delete(pathname)); wss.on("error", (e) => { logger.error(`${picocolors.default.red(`WebSocket mock error at ${wss.path}`)}\n${e}\n at setup (${filepath})`, mock.log); }); } catch (e) { logger.error(`${picocolors.default.red(`WebSocket mock error at ${wss.path}`)}\n${e}\n at setup (${filepath})`, mock.log); } }; const emitConnection = (wss, ws$1, req, connectionList) => { wss.emit("connection", ws$1, req); ws$1.on("close", () => { const i = connectionList.findIndex((item) => item.ws === ws$1); if (i !== -1) connectionList.splice(i, 1); }); }; const restartWss = (wssMap, wss, mock, pathname, filepath) => { const { cleanupList, connectionList, context } = wssContextMap.get(wss); cleanupRunner(cleanupList); connectionList.forEach(({ ws: ws$1 }) => ws$1.removeAllListeners()); wss.removeAllListeners(); setupWss(wssMap, wss, mock, context, pathname, filepath); connectionList.forEach(({ ws: ws$1, req }) => emitConnection(wss, ws$1, req, connectionList)); }; compiler.on?.("mock:update-end", (filepath) => { if (!hmrMap.has(filepath)) return; const mockUrlList = hmrMap.get(filepath); if (!mockUrlList) return; for (const mockUrl of mockUrlList.values()) for (const mock of compiler.mockData[mockUrl]) { if (!mock.ws || mock.__filepath__ !== filepath) return; const wssMap = getWssMap(mockUrl); for (const [pathname, wss] of wssMap.entries()) restartWss(wssMap, wss, mock, pathname, filepath); } }); server?.on("upgrade", (req, socket, head) => { const { pathname, query } = urlParse(req.url); if (!pathname || proxies.length === 0 || !proxies.some((context) => doesProxyContextMatchUrl(context, req.url))) return; const mockData = compiler.mockData; const mockUrl = Object.keys(mockData).find((key) => { return (0, path_to_regexp.pathToRegexp)(key).test(pathname); }); if (!mockUrl) return; const mock = mockData[mockUrl].find((mock$1) => { return mock$1.url && mock$1.ws && (0, path_to_regexp.pathToRegexp)(mock$1.url).test(pathname); }); if (!mock) return; const filepath = mock.__filepath__; addHmr(filepath, mockUrl); const wssMap = getWssMap(mockUrl); const wss = getWss(wssMap, pathname); let wssContext = wssContextMap.get(wss); if (!wssContext) { const cleanupList = []; const context = { onCleanup: (cleanup) => cleanupList.push(cleanup) }; wssContext = { cleanupList, context, connectionList: [] }; wssContextMap.set(wss, wssContext); setupWss(wssMap, wss, mock, context, pathname, filepath); } const request = req; const cookies$1 = new cookies.default(req, req, cookiesOptions); const { query: refererQuery } = urlParse(req.headers.referer || ""); request.query = query; request.refererQuery = refererQuery; request.params = parseParams(mockUrl, pathname); request.getCookie = cookies$1.get.bind(cookies$1); wss.handleUpgrade(request, socket, head, (ws$1) => { logger.info(`${picocolors.default.magenta(picocolors.default.bold("WebSocket"))} ${picocolors.default.green(req.url)} connected ${picocolors.default.dim(`(${filepath})`)}`, mock.log); wssContext.connectionList.push({ req: request, ws: ws$1 }); emitConnection(wss, ws$1, request, wssContext.connectionList); }); }); server?.on("close", () => { for (const wssMap of poolMap.values()) { for (const wss of wssMap.values()) { const wssContext = wssContextMap.get(wss); cleanupRunner(wssContext.cleanupList); wss.close(); } wssMap.clear(); } poolMap.clear(); hmrMap.clear(); }); } function cleanupRunner(cleanupList) { let cleanup; while (cleanup = cleanupList.shift()) cleanup?.(); } //#endregion //#region src/core/logger.ts const logLevels = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 }; function createLogger(prefix, defaultLevel = "info") { prefix = `[${prefix}]`; function output(type, msg, level) { level = require_dist.isBoolean(level) ? level ? defaultLevel : "error" : level; const thresh = logLevels[level]; if (thresh >= logLevels[type]) { const method = type === "info" || type === "debug" ? "log" : type; const tag = type === "debug" ? picocolors.default.magenta(picocolors.default.bold(prefix)) : type === "info" ? picocolors.default.cyan(picocolors.default.bold(prefix)) : type === "warn" ? picocolors.default.yellow(picocolors.default.bold(prefix)) : picocolors.default.red(picocolors.default.bold(prefix)); const format = `${picocolors.default.dim((/* @__PURE__ */ new Date()).toLocaleTimeString())} ${tag} ${msg}`; console[method](format); } } const logger = { debug(msg, level = defaultLevel) { output("debug", msg, level); }, info(msg, level = defaultLevel) { output("info", msg, level); }, warn(msg, level = defaultLevel) { output("warn", msg, level); }, error(msg, level = defaultLevel) { output("error", msg, level); } }; return logger; } //#endregion Object.defineProperty(exports, 'baseMiddleware', { enumerable: true, get: function () { return baseMiddleware; } }); Object.defineProperty(exports, 'createLogger', { enumerable: true, get: function () { return createLogger; } }); Object.defineProperty(exports, 'debug', { enumerable: true, get: function () { return debug$1; } }); Object.defineProperty(exports, 'doesProxyContextMatchUrl', { enumerable: true, get: function () { return doesProxyContextMatchUrl; } }); Object.defineProperty(exports, 'ensureProxies', { enumerable: true, get: function () { return ensureProxies; } }); Object.defineProperty(exports, 'logLevels', { enumerable: true, get: function () { return logLevels; } }); Object.defineProperty(exports, 'lookupFile', { enumerable: true, get: function () { return lookupFile; } }); Object.defineProperty(exports, 'mockWebSocket', { enumerable: true, get: function () { return mockWebSocket; } }); Object.defineProperty(exports, 'normalizePath', { enumerable: true, get: function () { return normalizePath; } }); Object.defineProperty(exports, 'recoverRequest', { enumerable: true, get: function () { return recoverRequest; } }); Object.defineProperty(exports, 'sortByValidator', { enumerable: true, get: function () { return sortByValidator; } }); Object.defineProperty(exports, 'transformMockData', { enumerable: true, get: function () { return transformMockData; } }); Object.defineProperty(exports, 'transformRawData', { enumerable: true, get: function () { return transformRawData; } }); Object.defineProperty(exports, 'urlParse', { enumerable: true, get: function () { return urlParse; } });