| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- var __defProp = Object.defineProperty;
- var __hasOwnProp = Object.prototype.hasOwnProperty;
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value;
- var __assign = (a, b) => {
- for (var prop in b || (b = {}))
- if (__hasOwnProp.call(b, prop))
- __defNormalProp(a, prop, b[prop]);
- if (__getOwnPropSymbols)
- for (var prop of __getOwnPropSymbols(b)) {
- if (__propIsEnum.call(b, prop))
- __defNormalProp(a, prop, b[prop]);
- }
- return a;
- };
- // src/index.ts
- import path2 from "path";
- // src/utils.ts
- import fs from "fs";
- var toString = Object.prototype.toString;
- function is(val, type) {
- return toString.call(val) === `[object ${type}]`;
- }
- function isFunction(val) {
- return is(val, "Function") || is(val, "AsyncFunction");
- }
- function isArray(val) {
- return val && Array.isArray(val);
- }
- function isRegExp(val) {
- return is(val, "RegExp");
- }
- function sleep(time) {
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve("");
- }, time);
- });
- }
- function fileExists(f) {
- try {
- fs.accessSync(f, fs.constants.W_OK);
- return true;
- } catch (error) {
- return false;
- }
- }
- // src/index.ts
- import {normalizePath} from "vite";
- // src/createMockServer.ts
- import path from "path";
- import fs2 from "fs";
- import chokidar from "chokidar";
- import chalk from "chalk";
- import url from "url";
- import fg from "fast-glob";
- import Mock from "mockjs";
- import {build} from "esbuild";
- import {pathToRegexp, match} from "path-to-regexp";
- import module from "module";
- var mockData = [];
- async function createMockServer(opt = {mockPath: "mock", configPath: "vite.mock.config"}) {
- opt = __assign({
- mockPath: "mock",
- watchFiles: true,
- supportTs: true,
- configPath: "vite.mock.config.ts",
- logger: true
- }, opt);
- if (mockData.length > 0)
- return;
- mockData = await getMockConfig(opt);
- await createWatch(opt);
- }
- async function requestMiddleware(opt) {
- const {logger = true} = opt;
- const middleware = async (req, res, next) => {
- let queryParams = {};
- if (req.url) {
- queryParams = url.parse(req.url, true);
- }
- const reqUrl = queryParams.pathname;
- const matchRequest = mockData.find((item) => {
- if (!reqUrl || !item || !item.url) {
- return false;
- }
- if (item.method && item.method.toUpperCase() !== req.method) {
- return false;
- }
- return pathToRegexp(item.url).test(reqUrl);
- });
- if (matchRequest) {
- const isGet = req.method && req.method.toUpperCase() === "GET";
- const {response, rawResponse, timeout, statusCode, url: url2} = matchRequest;
- if (timeout) {
- await sleep(timeout);
- }
- const urlMatch = match(url2, {decode: decodeURIComponent});
- let query = queryParams.query;
- if (reqUrl) {
- if (isGet && JSON.stringify(query) === "{}" || !isGet) {
- const params = urlMatch(reqUrl).params;
- if (JSON.stringify(params) !== "{}") {
- query = urlMatch(reqUrl).params || {};
- } else {
- query = queryParams.query || {};
- }
- }
- }
- if (isFunction(rawResponse)) {
- await rawResponse(req, res);
- } else {
- const body = await parseJson(req);
- const mockResponse = isFunction(response) ? response({url: req.url, body, query, headers: req.headers}) : response;
- res.setHeader("Content-Type", "application/json");
- res.statusCode = statusCode || 200;
- res.end(JSON.stringify(Mock.mock(mockResponse)));
- }
- logger && loggerOutput("request invoke", req.url);
- return;
- }
- next();
- };
- return middleware;
- }
- function createWatch(opt) {
- const {configPath, logger, watchFiles} = opt;
- if (!watchFiles) {
- return;
- }
- const {absConfigPath, absMockPath} = getPath(opt);
- if (process.env.VITE_DISABLED_WATCH_MOCK === "true") {
- return;
- }
- const watchDir = [];
- const exitsConfigPath = fs2.existsSync(absConfigPath);
- exitsConfigPath && configPath ? watchDir.push(absConfigPath) : watchDir.push(absMockPath);
- const watcher = chokidar.watch(watchDir, {
- ignoreInitial: true
- });
- watcher.on("all", async (event, file) => {
- logger && loggerOutput(`mock file ${event}`, file);
- mockData = await getMockConfig(opt);
- });
- }
- function cleanRequireCache(opt) {
- if (!require.cache) {
- return;
- }
- const {absConfigPath, absMockPath} = getPath(opt);
- Object.keys(require.cache).forEach((file) => {
- if (file === absConfigPath || file.indexOf(absMockPath) > -1) {
- delete require.cache[file];
- }
- });
- }
- function parseJson(req) {
- return new Promise((resolve) => {
- let body = "";
- let jsonStr = "";
- req.on("data", function(chunk) {
- body += chunk;
- });
- req.on("end", function() {
- try {
- jsonStr = JSON.parse(body);
- } catch (err) {
- jsonStr = "";
- }
- resolve(jsonStr);
- return;
- });
- });
- }
- async function getMockConfig(opt) {
- cleanRequireCache(opt);
- const {absConfigPath, absMockPath} = getPath(opt);
- const {ignore, configPath, logger} = opt;
- let ret = [];
- if (configPath && fs2.existsSync(absConfigPath)) {
- logger && loggerOutput(`load mock data from`, absConfigPath);
- ret = await resolveModule(absConfigPath);
- return ret;
- }
- const mockFiles = fg.sync(`**/*.{ts,js}`, {
- cwd: absMockPath
- }).filter((item) => {
- if (!ignore) {
- return true;
- }
- if (isFunction(ignore)) {
- return ignore(item);
- }
- if (isRegExp(ignore)) {
- return !ignore.test(path.basename(item));
- }
- return true;
- });
- try {
- ret = [];
- const resolveModulePromiseList = [];
- for (let index = 0; index < mockFiles.length; index++) {
- const mockFile = mockFiles[index];
- resolveModulePromiseList.push(resolveModule(path.join(absMockPath, mockFile)));
- }
- const loadAllResult = await Promise.all(resolveModulePromiseList);
- for (const resultModule of loadAllResult) {
- let mod = resultModule;
- if (!isArray(mod)) {
- mod = [mod];
- }
- ret = [...ret, ...mod];
- }
- } catch (error) {
- loggerOutput(`mock reload error`, error);
- ret = [];
- }
- return ret;
- }
- async function resolveModule(p) {
- const result = await build({
- entryPoints: [p],
- outfile: "out.js",
- write: false,
- platform: "node",
- bundle: true,
- format: "cjs",
- metafile: true,
- target: "es2015"
- });
- const {text} = result.outputFiles[0];
- return await loadConfigFromBundledFile(p, text);
- }
- function getPath(opt) {
- const {mockPath, configPath} = opt;
- const cwd = process.cwd();
- const absMockPath = path.join(cwd, mockPath || "");
- const absConfigPath = path.join(cwd, configPath || "");
- return {
- absMockPath,
- absConfigPath
- };
- }
- function loggerOutput(title, msg, type = "info") {
- const tag = type === "info" ? chalk.cyan.bold(`[vite:mock]`) : chalk.red.bold(`[vite:mock-server]`);
- return console.log(`${chalk.dim(new Date().toLocaleTimeString())} ${tag} ${chalk.green(title)} ${chalk.dim(msg)}`);
- }
- async function loadConfigFromBundledFile(fileName, bundledCode) {
- const extension = path.extname(fileName);
- const extensions = module.Module._extensions;
- let defaultLoader;
- const isJs = extension === ".js";
- if (isJs) {
- defaultLoader = extensions[extension];
- }
- extensions[extension] = (module2, filename) => {
- if (filename === fileName) {
- module2._compile(bundledCode, filename);
- } else {
- if (!isJs) {
- extensions[extension](module2, filename);
- } else {
- defaultLoader(module2, filename);
- }
- }
- };
- let config;
- try {
- if (isJs && require && require.cache) {
- delete require.cache[fileName];
- }
- const raw = require(fileName);
- config = raw.__esModule ? raw.default : raw;
- if (defaultLoader && isJs) {
- extensions[extension] = defaultLoader;
- }
- } catch (error) {
- console.error(error);
- }
- return config;
- }
- // src/index.ts
- (async () => {
- try {
- await import("mockjs");
- } catch (e) {
- throw new Error("vite-plugin-vue-mock requires mockjs to be present in the dependency tree.");
- }
- })();
- function getDefaultPath(supportTs = true) {
- return path2.resolve(process.cwd(), `src/main.${supportTs ? "ts" : "js"}`);
- }
- function viteMockServe(opt) {
- let defaultPath = getDefaultPath();
- if (!fileExists(defaultPath)) {
- defaultPath = getDefaultPath(false);
- if (!fileExists(defaultPath)) {
- defaultPath = "";
- }
- }
- const defaultEnter = normalizePath(defaultPath);
- const {injectFile = defaultEnter} = opt;
- let isDev = false;
- let config;
- let needSourcemap = false;
- return {
- name: "vite:mock",
- enforce: "pre",
- configResolved(resolvedConfig) {
- config = resolvedConfig;
- isDev = config.command === "serve";
- needSourcemap = !!resolvedConfig.build.sourcemap;
- isDev && createMockServer(opt);
- },
- configureServer: async ({middlewares}) => {
- const {localEnabled = isDev} = opt;
- if (!localEnabled) {
- return;
- }
- const middleware = await requestMiddleware(opt);
- middlewares.use(middleware);
- },
- async transform(code, id) {
- if (isDev || !injectFile || !id.endsWith(injectFile)) {
- return null;
- }
- const {prodEnabled = true, injectCode = ""} = opt;
- if (!prodEnabled) {
- return null;
- }
- return {
- map: needSourcemap ? this.getCombinedSourcemap() : null,
- code: `${code}
- ${injectCode}`
- };
- }
- };
- }
- export {
- viteMockServe
- };
|