@fairys/mocker-cli 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,6 @@
1
1
  # mocker-cli
2
2
 
3
- 用于界面配置生成mock数据和mock服务
4
-
5
- [ ] 直接当 mock 服务
6
- [ ] 生成 mock 数据
7
- [ ] 服务 + 数据
3
+ 功能强大的 Mock 数据生成和代理转发工具
8
4
 
9
5
  ## 安装
10
6
 
@@ -19,20 +15,31 @@ Usage:
19
15
  $ fairys-mocker
20
16
 
21
17
  Options:
22
- --root 设置根目录路径(默认取环境变量中的`FAIRYS_MOCKER_ROOT_DIR`)
23
- --dir 设置目录名(默认取环境变量中的`FAIRYS_MOCKER_DIR`)
24
- --file 设置文件名(默认取环境变量中的`FAIRYS_MOCKER_FILE`)
25
- --file2 设置文件名2(默认取环境变量中的`FAIRYS_MOCKER_PROXY_FILE`)
26
- --static 设置静态文件目录
27
- --static-prefix 设置静态文件路径前缀
18
+ --root 设置根目录路径(默认取环境变量中的`FAIRYS_MOCKER_ROOT_DIR`)
19
+ --dir 设置目录名(默认取环境变量中的`FAIRYS_MOCKER_DIR`)
20
+ --file 设置文件名(默认取环境变量中的`FAIRYS_MOCKER_FILE`)
21
+ --file2 设置文件名2(默认取环境变量中的`FAIRYS_MOCKER_PROXY_FILE`)
22
+ --static 设置静态文件目录
23
+ --static-prefix 设置静态文件路径前缀
24
+ --is-mock-file 是否生成mock数据文件,默认生成.
25
+ --is-proxy-file 是否生成proxy数据文件,默认生成.
26
+ --is-connect 是否是connect服务.默认express.
28
27
  ```
29
28
 
30
29
  **参数说明**
31
30
 
32
- `FAIRYS_MOCKER_ROOT_DIR`或`root`:未设置时,取当前执行命令目录
33
- `FAIRYS_MOCKER_DIR`或者`dir`:未设置时,取当前执行命令目录的`mock`文件夹
34
- `FAIRYS_MOCKER_FILE`或者`file`:未设置时,取当前执行命令目录的`mock`文件夹下的`index.mock.cache.json`文件
35
- `FAIRYS_MOCKER_PROXY_FILE`或者`file2`:未设置时,取当前执行命令目录的`mock`文件夹下的`proxy.cache.json`文件
31
+ - `FAIRYS_MOCKER_ROOT_DIR`或`root`:未设置时,取当前执行命令目录
32
+ - `FAIRYS_MOCKER_DIR`或者`dir`:未设置时,取当前执行命令目录的`mock`文件夹
33
+ - `FAIRYS_MOCKER_FILE`或者`file`:未设置时,取当前执行命令目录的`mock`文件夹下的`index.mock.cache.json`文件
34
+ - `FAIRYS_MOCKER_PROXY_FILE`或者`file2`:未设置时,取当前执行命令目录的`mock`文件夹下的`proxy.cache.json`文件
35
+
36
+ :::tip
37
+
38
+ `file`和`file2`值为移除`.cache.json`的文件名,不是完整的文件名,
39
+
40
+ 例如`file=index.mock`, `file2=proxy` 内部会进行转换为 `index.mock.cache.json`、`index.mock.ts`、`proxy.cache.json`、`proxy.ts` 这4个文件名称
41
+
42
+ :::
36
43
 
37
44
  在使用的过程中会生成4个文件
38
45
 
package/esm/ci.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import yargs_parser from "yargs-parser";
2
2
  import { fairysMockerExpress } from "./main.js";
3
3
  import { fairysMockerConnect } from "./connect.js";
4
- import { utils } from "./utils/utils.js";
4
+ import { utilsGlobalVariable } from "./utils/utils.js";
5
5
  function help() {
6
6
  console.log('\n Usage: \x1b[34;1fairys-mocker\x1b[0m [--help|h|--root|--dir|--file|--file2|--static|--static-prefix|--is-mock-file|--is-proxy-file]');
7
7
  console.log('\n Displays help information.');
@@ -36,12 +36,12 @@ const argv = yargs_parser(process.argv.slice(2), {
36
36
  });
37
37
  const CI = (app)=>{
38
38
  if (argv.help | argv.h) return void help();
39
- utils.setRootDir(argv.root);
40
- utils.setDir(argv.dir);
41
- utils.setFile(argv.file);
42
- utils.setProxyFile(argv.file2);
43
- utils.setIsCreateMockDataFile(argv['is-mock-file']);
44
- utils.setIsCreateProxyDataFile(argv['is-proxy-file']);
39
+ utilsGlobalVariable.setRootDir(argv.root);
40
+ utilsGlobalVariable.setDir(argv.dir);
41
+ utilsGlobalVariable.setFile(argv.file);
42
+ utilsGlobalVariable.setProxyFile(argv.file2);
43
+ utilsGlobalVariable.setIsCreateMockDataFile(argv['is-mock-file']);
44
+ utilsGlobalVariable.setIsCreateProxyDataFile(argv['is-proxy-file']);
45
45
  app.start(()=>{
46
46
  if (!argv.static) return;
47
47
  app.staticServer(argv.static, argv['static-prefix']);
@@ -1,6 +1,6 @@
1
1
  import node_fs from "node:fs";
2
2
  import { Controller, Get, Post } from "../utils/decorator.js";
3
- import { utils } from "../utils/index.js";
3
+ import { utilsGlobalVariable } from "../utils/index.js";
4
4
  import { MockRouter } from "../router/mock.js";
5
5
  import { BaseController } from "./base.js";
6
6
  import { createMockFile, getMcokFile } from "../utils/mcok.proxy.js";
@@ -370,8 +370,8 @@ class MockRouterController extends (_BaseController = BaseController) {
370
370
  post_mock(req, res) {
371
371
  try {
372
372
  const { mockList, dir, fileName = 'index.mock', rootDir } = req.body;
373
- let _rootDir = rootDir || utils.rootDir;
374
- if (rootDir && !node_fs.existsSync(rootDir)) _rootDir = utils.rootDir;
373
+ let _rootDir = rootDir || utilsGlobalVariable.rootDir;
374
+ if (rootDir && !node_fs.existsSync(rootDir)) _rootDir = utilsGlobalVariable.rootDir;
375
375
  const mockData = createMockFile(mockList, _rootDir, dir, fileName);
376
376
  if (mockData?.mockConfig) {
377
377
  if (this.router?.isEnabled) this.router?.load(mockData.mockConfig);
@@ -1,6 +1,6 @@
1
1
  import node_fs from "node:fs";
2
2
  import { Controller, Get, Post } from "../utils/decorator.js";
3
- import { utils } from "../utils/index.js";
3
+ import { utilsGlobalVariable } from "../utils/utils.js";
4
4
  import { ProxyRouter } from "../router/proxy.js";
5
5
  import { BaseController } from "./base.js";
6
6
  import { createProxyFile, getProxyFile } from "../utils/mcok.proxy.js";
@@ -370,8 +370,8 @@ class ProxyRouterController extends (_BaseController = BaseController) {
370
370
  post_proxy(req, res) {
371
371
  try {
372
372
  const { proxyList, dir, fileName = 'proxy', rootDir } = req.body;
373
- let _rootDir = rootDir || utils.rootDir;
374
- if (rootDir && !node_fs.existsSync(rootDir)) _rootDir = utils.rootDir;
373
+ let _rootDir = rootDir || utilsGlobalVariable.rootDir;
374
+ if (rootDir && !node_fs.existsSync(rootDir)) _rootDir = utilsGlobalVariable.rootDir;
375
375
  const proxyData = createProxyFile(proxyList, _rootDir, dir, fileName);
376
376
  if (proxyData?.proxyConfig) {
377
377
  if (this.router?.isEnabled) this.router?.load(proxyList);
@@ -439,9 +439,10 @@ class ProxyRouterController extends (_BaseController = BaseController) {
439
439
  const proxyData = getProxyFile(rootDir, savePath, saveFileName);
440
440
  if (proxyData?.proxyList) {
441
441
  this.router?.load(proxyData.proxyList);
442
+ const msg = utilsGlobalVariable.isEnableWebsocket ? '启动代理服务成功' : '非websocket服务代理启动成功';
442
443
  res.json({
443
444
  code: 200,
444
- message: '启动代理服务成功',
445
+ message: msg,
445
446
  data: proxyData.proxyList,
446
447
  rootDir: rootDir,
447
448
  dir: proxyData.dir,
@@ -1,9 +1,11 @@
1
1
  import { fairysMockerBase } from "../base.js";
2
+ import { utilsGlobalVariable } from "../utils/utils.js";
2
3
  const fairysMockerRsbuildPlugin = ()=>({
3
4
  setup (api) {
4
5
  api.onBeforeStartDevServer(({ server })=>{
5
6
  fairysMockerBase.initApp(server.middlewares, ()=>{
6
7
  fairysMockerBase.logServer(server.port);
8
+ utilsGlobalVariable.isEnableWebsocket = false;
7
9
  });
8
10
  fairysMockerBase.server = server.httpServer;
9
11
  });
@@ -3,6 +3,7 @@ import { BaseRouter } from "./base.js";
3
3
  import { createProxyMiddleware } from "http-proxy-middleware";
4
4
  import chalk from "chalk";
5
5
  import { fairysMockerBase } from "../base.js";
6
+ import { utilsGlobalVariable } from "../utils/utils.js";
6
7
  class ProxyRouter extends BaseRouter {
7
8
  router = null;
8
9
  wsProxyList = [];
@@ -30,7 +31,7 @@ class ProxyRouter extends BaseRouter {
30
31
  }
31
32
  console.log(chalk.hex('#AF52DE')(chalk.bold(` 🍇 proxy代理启动:\t${chalk.yellow(protocol)}\t${proxyItem.path} ===> ${_target}\t`)));
32
33
  if (!proxyItem.path.startsWith('^')) _path = new RegExp('^' + proxyItem.path);
33
- if (proxyItem.ws) {
34
+ if (proxyItem.ws) if (utilsGlobalVariable.isEnableWebsocket) {
34
35
  const wsProxy = createProxyMiddleware({
35
36
  target: proxyItem.target,
36
37
  pathRewrite: proxyItem.pathRewrite,
@@ -40,7 +41,8 @@ class ProxyRouter extends BaseRouter {
40
41
  _that.wsProxyList.push(wsProxy);
41
42
  router.all(_path, wsProxy);
42
43
  if (fairysMockerBase.server) fairysMockerBase.server?.on('upgrade', wsProxy.upgrade);
43
- } else router.all(_path, createProxyMiddleware({
44
+ } else console.log(chalk.red(`rsbuild/vite等自带websocket服务的环境下无法代理websocket服务:${proxyItem.path}`));
45
+ else router.all(_path, createProxyMiddleware({
44
46
  target: proxyItem.target,
45
47
  pathRewrite: proxyItem.pathRewrite,
46
48
  ws: proxyItem.ws,
@@ -1,11 +1,11 @@
1
1
  import node_path from "node:path";
2
2
  import node_fs from "node:fs";
3
- import { utils } from "./utils.js";
3
+ import { utilsGlobalVariable } from "./utils.js";
4
4
  import { createMockData, createProxyData } from "@fairys/create-mock-data";
5
5
  const getProxyFile = (rootDir, dir, fileName)=>{
6
- const _rootDir = rootDir?.trim() || utils.rootDir;
7
- const _dir = dir?.trim() || utils.dir;
8
- const _fileName = fileName?.trim() || utils.proxyFile;
6
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
7
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
8
+ const _fileName = fileName?.trim() || utilsGlobalVariable.proxyFile;
9
9
  const proxyDir = node_path.join(_rootDir, _dir);
10
10
  const cacheFilePath = node_path.join(proxyDir, _fileName + '.cache.json');
11
11
  if (node_fs.existsSync(cacheFilePath)) {
@@ -22,15 +22,15 @@ const getProxyFile = (rootDir, dir, fileName)=>{
22
22
  }
23
23
  };
24
24
  const createProxyFile = (proxyList, rootDir, dir, fileName)=>{
25
- const _rootDir = rootDir?.trim() || utils.rootDir;
26
- const _dir = dir?.trim() || utils.dir;
27
- const _fileName = fileName?.trim() || utils.proxyFile;
25
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
26
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
27
+ const _fileName = fileName?.trim() || utilsGlobalVariable.proxyFile;
28
28
  const proxyDir = node_path.join(_rootDir, _dir);
29
29
  if (!node_fs.existsSync(proxyDir)) node_fs.mkdirSync(proxyDir, {
30
30
  recursive: true
31
31
  });
32
32
  const proxyConfig = createProxyData(proxyList);
33
- if (utils.isCreateProxyDataFile) {
33
+ if (utilsGlobalVariable.isCreateProxyDataFile) {
34
34
  const proxyFilePath = node_path.join(proxyDir, `${_fileName}.ts`);
35
35
  const proxyFileContent = `// 代理配置文件
36
36
  // 自动生成于 ${new Date().toISOString()}
@@ -70,9 +70,9 @@ export default proxyConfig;
70
70
  };
71
71
  };
72
72
  const getMcokFile = (rootDir, dir, fileName)=>{
73
- const _rootDir = rootDir?.trim() || utils.rootDir;
74
- const _dir = dir?.trim() || utils.dir;
75
- const _fileName = fileName?.trim() || utils.file;
73
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
74
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
75
+ const _fileName = fileName?.trim() || utilsGlobalVariable.file;
76
76
  const mockDir = node_path.join(_rootDir, _dir);
77
77
  const cacheFilePath = node_path.join(mockDir, _fileName + '.cache.json');
78
78
  if (node_fs.existsSync(cacheFilePath)) {
@@ -89,15 +89,15 @@ const getMcokFile = (rootDir, dir, fileName)=>{
89
89
  }
90
90
  };
91
91
  const createMockFile = (mockList, rootDir, dir, fileName)=>{
92
- const _rootDir = rootDir?.trim() || utils.rootDir;
93
- const _dir = dir?.trim() || utils.dir;
94
- const _fileName = fileName?.trim() || utils.file;
92
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
93
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
94
+ const _fileName = fileName?.trim() || utilsGlobalVariable.file;
95
95
  const mockDir = node_path.join(_rootDir, _dir);
96
96
  if (!node_fs.existsSync(mockDir)) node_fs.mkdirSync(mockDir, {
97
97
  recursive: true
98
98
  });
99
99
  const mockConfig = createMockData(mockList);
100
- if (utils.isCreateMockDataFile) {
100
+ if (utilsGlobalVariable.isCreateMockDataFile) {
101
101
  const mockFilePath = node_path.join(mockDir, `${_fileName}.ts`);
102
102
  const mockFileContent = `// Mock 配置文件
103
103
  // 自动生成于 ${new Date().toISOString()}
@@ -1,4 +1,4 @@
1
- declare class Utils {
1
+ declare class UtilsGlobalVariable {
2
2
  /**根目录*/
3
3
  rootDir: string;
4
4
  /**目录名*/
@@ -11,6 +11,8 @@ declare class Utils {
11
11
  isCreateMockDataFile: boolean;
12
12
  /**是否生成proxy数据文件*/
13
13
  isCreateProxyDataFile: boolean;
14
+ /**是否可以启用 websocket 服务(在rsbuild/vite等自带websocket服务的环境下无法使用)*/
15
+ isEnableWebsocket: boolean;
14
16
  /**设置根目录*/
15
17
  setRootDir: (value?: string) => void;
16
18
  /**设置目录名*/
@@ -24,5 +26,5 @@ declare class Utils {
24
26
  /**设置 是否生成proxy数据文件*/
25
27
  setIsCreateProxyDataFile: (fig?: boolean) => void;
26
28
  }
27
- export declare const utils: Utils;
29
+ export declare const utilsGlobalVariable: UtilsGlobalVariable;
28
30
  export {};
@@ -1,13 +1,14 @@
1
1
  import chalk from "chalk";
2
2
  import node_fs from "node:fs";
3
3
  import node_path from "node:path";
4
- class Utils {
4
+ class UtilsGlobalVariable {
5
5
  rootDir = process.cwd();
6
6
  dir = 'mock';
7
7
  file = 'index.mock';
8
8
  proxyFile = 'proxy';
9
9
  isCreateMockDataFile = true;
10
10
  isCreateProxyDataFile = true;
11
+ isEnableWebsocket = true;
11
12
  setRootDir = (value)=>{
12
13
  if (value && node_fs.existsSync(value)) this.rootDir = value;
13
14
  else {
@@ -35,5 +36,5 @@ class Utils {
35
36
  if ("boolean" == typeof fig) this.isCreateProxyDataFile = fig;
36
37
  };
37
38
  }
38
- const utils = new Utils();
39
- export { utils };
39
+ const utilsGlobalVariable = new UtilsGlobalVariable();
40
+ export { utilsGlobalVariable };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairys/mocker-cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Fairys Mocker CLI for mock data generation",
5
5
  "author": "SunLxy <1011771396@qq.com>",
6
6
  "homepage": "https://github.com/autumn-fairy-tales/fairys-mocker",
@@ -26,7 +26,7 @@
26
26
  "fairys-mocker": "bin/fairys-mocker"
27
27
  },
28
28
  "dependencies": {
29
- "@fairys/create-mock-data": "^0.0.2",
29
+ "@fairys/create-mock-data": "^0.0.3",
30
30
  "body-parser": "2.2.2",
31
31
  "chalk": "^5.6.2",
32
32
  "connect": "^3.7.0",
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><link rel="icon" href="/_fairys_mocker/favicon.png"><title>Fairys Mocker</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/_fairys_mocker/static/js/lib-react.2748fa4b.js"></script><script defer src="/_fairys_mocker/static/js/514.950758f1.js"></script><script defer src="/_fairys_mocker/static/js/index.f70ed1dc.js"></script><link href="/_fairys_mocker/static/css/index.2ba69ff5.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
1
+ <!DOCTYPE html><html><head><link rel="icon" href="/_fairys_mocker/favicon.png"><title>Fairys Mocker</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/_fairys_mocker/static/js/lib-react.2748fa4b.js"></script><script defer src="/_fairys_mocker/static/js/514.950758f1.js"></script><script defer src="/_fairys_mocker/static/js/index.ef2bf9b4.js"></script><link href="/_fairys_mocker/static/css/index.2ba69ff5.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
@@ -0,0 +1 @@
1
+ (()=>{"use strict";var e,t,r,n,s={711(e,t,r){var n=r(85),s=r(873),o=r(41),a=r(424),i=r.n(a),l=r(346),c=r(990);class d extends l.ProxyInstanceObject{constructor(...e){var t;super(...e),t=this,(0,c._)(this,"open",function(e,r){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3,s=new Date().valueOf().toString();t.store.messageList.push((0,l.ref)({type:e,message:r,id:s}));let o=setTimeout(()=>{t.store.messageList=t.store.messageList.filter(e=>e.id!==s),clearTimeout(o)},n)})}}let x=new d()._ctor({tabKey:"mock",messageList:[],isServer:!0}),{MainProxyProvider:u,useMainProxyStore:m}=(0,l.createCommonMainStore)({proxyInstance:x,namespace:"global"}),b=window.location.origin;function h(e){let{columns:t,dataSource:r,rowKey:s}=e,a=(0,o.useMemo)(()=>(0,n.jsx)("tr",{className:"bg-zinc-100 dark:bg-zinc-800 sticky -top-px z-10",children:t.map((e,t)=>(0,n.jsx)("th",{className:"px-2 py-2 text-left text-xs font-medium text-zinc-700 dark:text-zinc-300 border-b border-zinc-200 dark:border-zinc-700",children:e.title},e.dataIndex||t))}),[t]);return(0,n.jsx)("div",{className:"flex-1 flex flex-col box-border overflow-auto",children:(0,n.jsxs)("table",{className:"border-collapse min-w-full border border-zinc-200 dark:border-zinc-700 relative",children:[(0,n.jsx)("thead",{children:a}),(0,n.jsx)("tbody",{children:r.map((e,r)=>{let o="function"==typeof s?s(e):s?e[s]:r;return(0,n.jsx)("tr",{className:"hover:bg-zinc-50 dark:hover:bg-zinc-800",children:t.map(t=>{let s=t.dataIndex?e[t.dataIndex]:e;if(t.isIndex&&(s=r+1),t.render){var a;s=null==(a=t.render)?void 0:a.call(t,e,r)}return(0,n.jsx)("td",{className:`px-2 py-2 border-b border-zinc-200 dark:border-zinc-700 ${t.tdClassName||""}`,children:s},`${o}-${t.dataIndex}`)})},o)})})]})})}var p=r(224);let f=e=>{let{value:t,onChange:r,placeholder:s,className:o}=e;return(0,n.jsx)(p.A,{value:t,language:"json",placeholder:s,onChange:e=>null==r?void 0:r(e.target.value),padding:15,className:o,style:{fontFamily:"ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",minHeight:280}})};var g=r(144);function y(){let{state:e,proxyInstance:t}=m(),r=e.isServer,{state:s,dispatch:a,proxyInstance:c}=(0,l.useProxyStore)({rootDir:"",dir:"mock",fileName:"index.mock",mockList:[],response:"",isModalOpen:!1,currentIndex:null,modalBody:"",isEnabledStart:!1},{sync:!0}),d=s.mockList,x=s.response,u=s.isModalOpen,p=s.currentIndex,y=s.modalBody,k=s.rootDir,v=s.dir,j=s.fileName,z=s.isEnabledStart,N=async()=>{try{let e=await fetch(`${b}/_fairys/_mock/_is_enabled`).then(e=>e.json());200===e.code&&a({isEnabledStart:e.data})}catch(e){console.error("检查 mock 配置服务是否启用失败:",e)}};(0,o.useEffect)(()=>{N()},[]);let w=async()=>{try{let e=await fetch(`${b}/_fairys/_mock/_destroy`).then(e=>e.json());200===e.code?(a({isEnabledStart:!1}),t.open("success","销毁 Mock 数据服务成功")):t.open("error",e.message||"销毁 Mock 数据服务失败")}catch(e){console.error("销毁 mock 数据服务失败:",e)}},C=async()=>{try{let e=await fetch(`${b}/_fairys/_mock/_start`).then(e=>e.json());200===e.code?(t.open("success","加载 Mock 数据服务成功"),a({isEnabledStart:!0})):t.open("error",e.message||"加载 Mock 数据服务失败")}catch(e){console.error("加载 mock 数据服务失败:",e)}},S=async e=>{try{let t;if(!0===e)t=await fetch(`${b}/_fairys/_mock`);else{let e=`dir=${decodeURIComponent(v)}&fileName=${decodeURIComponent(j)}&rootDir=${decodeURIComponent(k)}`;t=await fetch(`${b}/_fairys/_mock?${e}`)}let r=await t.json();200===r.code?a({mockList:r.data,dir:r.dir,fileName:r.fileName,rootDir:r.rootDir}):a({mockList:[]})}catch(e){t.store.isServer=!1,console.error("获取缓存数据失败:",e)}};(0,o.useEffect)(()=>{S(!0)},[]);let O=(e,t,r)=>{a({mockList:(c.store.mockList||[]).map((n,s)=>s===e?{...n,[t]:r}:n)})},_=async e=>{e.preventDefault();let s=!0,o="";for(let e=0;e<d.length;e++){let t=d[e];if(!t.url.trim()){s=!1,o=`接口配置 #${e+1} 的 接口地址 不能为空`;break}if(!t.method){s=!1,o=`接口配置 #${e+1} 的 请求方法 不能为空`;break}if(!t.status.trim()){s=!1,o=`接口配置 #${e+1} 的 状态码 不能为空`;break}if(!t.body){s=!1,o=`接口配置 #${e+1} 的 响应体 不能为空`;break}}if(!s)return void t.open("error",o);let l=new Map;for(let e=0;e<d.length;e++){let t=d[e],r=`${t.url.trim()}:${t.method}`;if(l.has(r)){var c;null==(c=l.get(r))||c.push(e+1)}else l.set(r,[e+1])}if(l.size>0){let e=[];for(let[t,r]of l)r.length>1&&e.push((0,n.jsxs)("div",{children:["第 ",r.join(",")," 行数据 接口地址和请求方法 组合重复;"]},t));if(e.length>0)return void t.open("error",e,5e3)}try{if(r){let e=await fetch(`${b}/_fairys/_mock`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({mockList:d,dir:v,fileName:j,rootDir:k})}),r=await e.json();d.length>0?a({response:JSON.stringify(r,null,2)}):200===r.code&&t.open("success","保存成功"),a({rootDir:r.rootDir})}else if(d.length>0){let e=d.map(e=>(function(e){let{data:t,...r}={...e.body},n={},s=Object.keys(t),o=e.listCount||20;for(let e=0;e<s.length;e++){let r=s[e],a=t[r];if(/^(\_\|)/.test(r)){let[e,t,s]=r.split("|"),l=`${s||""}`.trim();a&&(n[t]=Array.from({length:l?Number(l):o},()=>i().mock(a)))}else Object.assign(n,i().mock({[r]:a}))}r.data=n;let a=0;if(Array.isArray(e.delay)){let[t,r]=e.delay;a=Math.floor(Math.random()*(r-t+1))+t}else a=e.delay;return{...e,body:r,delay:a}})(e));a({response:JSON.stringify(e,null,2)})}else t.open("success","操作成功")}catch(e){a({response:"Error: "+e.message})}},I=()=>{a({currentIndex:void 0,modalBody:"",isModalOpen:!1}),document.body.style.overflow="auto"};return(0,n.jsxs)("div",{className:"space-y-6 flex-1 flex flex-col box-border overflow-hidden",children:[(0,n.jsxs)("div",{className:"mb-6 text-xs text-zinc-600 dark:text-zinc-300 box-border flex justify-between",children:[(0,n.jsxs)("div",{children:["当前配置总条数: ",d.length]}),r?(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsxs)("button",{type:"button",onClick:C,className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:[z?"重启":"启动"," mock 数据服务"]}),z?(0,n.jsx)("button",{type:"button",onClick:w,className:"px-3 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"销毁 mock 数据服务"}):(0,n.jsx)(o.Fragment,{})]}):(0,n.jsx)(o.Fragment,{})]}),(0,n.jsxs)("div",{className:"mb-6",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"数据保存到本地"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"根目录"}),(0,n.jsx)("input",{type:"text",value:k,onChange:e=>{a({rootDir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"目录名"}),(0,n.jsx)("input",{type:"text",value:v,onChange:e=>{a({dir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"文件名"}),(0,n.jsx)("input",{type:"text",value:j,onChange:e=>{a({fileName:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsx)("button",{type:"button",onClick:()=>S(!1),className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors whitespace-nowrap text-xs",children:"查询"})]}),(0,n.jsx)("p",{className:"text-xs text-zinc-500 dark:text-zinc-400 mt-1",children:"默认保存到当前工作目录的 mock 文件夹"})]}),d.length>0?(0,n.jsx)("div",{className:"flex-1 flex flex-col box-border overflow-auto",children:(0,n.jsx)(h,{columns:[{title:"#",isIndex:!0,tdClassName:"px-2 py-2 text-xs text-zinc-800 dark:text-zinc-100 border-b border-zinc-200 dark:border-zinc-700"},{title:"接口地址",dataIndex:"url",render:(e,t)=>(0,n.jsx)("input",{type:"text",placeholder:"请输入接口地址",value:e.url,onChange:e=>O(t,"url",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})},{title:"请求方法",dataIndex:"method",render:(e,t)=>(0,n.jsxs)("select",{value:e.method,onChange:e=>O(t,"method",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",children:[(0,n.jsx)("option",{value:"GET",children:"GET"}),(0,n.jsx)("option",{value:"POST",children:"POST"}),(0,n.jsx)("option",{value:"PUT",children:"PUT"}),(0,n.jsx)("option",{value:"DELETE",children:"DELETE"}),(0,n.jsx)("option",{value:"PATCH",children:"PATCH"}),(0,n.jsx)("option",{value:"HEAD",children:"HEAD"}),(0,n.jsx)("option",{value:"OPTIONS",children:"OPTIONS"})]})},{title:"状态码",dataIndex:"status",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:e.status,onChange:e=>O(t,"status",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",placeholder:"例如: 200, 400, 500"})},{title:"响应延迟时间(ms)",dataIndex:"delay",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:Array.isArray(e.delay)?`${e.delay[0]},${e.delay[1]}`:e.delay||"",onChange:e=>{let r=e.target.value;if(r.includes(",")){let[e,n]=r.split(",").map(Number);O(t,"delay",[e,n])}else O(t,"delay",parseInt(r)||0)},className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",placeholder:"例如: 1000 或 500,2000"})},{title:"生成数据条数",dataIndex:"listCount",render:(e,t)=>(0,n.jsx)("input",{type:"number",value:e.listCount,onChange:e=>O(t,"listCount",parseInt(e.target.value)||1),min:"1",max:"100",className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})},{title:"响应体数据",dataIndex:"body",render:e=>(0,n.jsx)("div",{className:"text-zinc-500 dark:text-zinc-400 text-xs w-[400px]",children:JSON.stringify(e.body,null,2)})},{title:"操作",dataIndex:"operation",render:(e,t)=>(0,n.jsxs)("div",{className:"flex space-x-1",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{a({currentIndex:t,modalBody:JSON.stringify(d[t].body,null,2),isModalOpen:!0}),document.body.style.overflow="hidden"},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"编辑响应体数据"}),(0,n.jsx)("button",{type:"button",onClick:()=>{a({mockList:(c.store.mockList||[]).filter((e,r)=>r!==t)})},className:"px-2 py-0.5 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"删除"})]})}],dataSource:d})}):(0,n.jsx)("div",{className:"text-center py-8 text-zinc-500 dark:text-zinc-400",children:'暂无接口配置,请点击"添加接口配置"按钮添加'}),(0,n.jsxs)("div",{className:"flex justify-center",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{a({mockList:[...c.store.mockList||[]].concat([{url:"",method:"POST",status:"200",delay:0,body:{code:200,data:{id:"@id",name:"@name",email:"@email"},message:"success"},listCount:20}])})},className:"px-3 py-1 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors mr-4 text-xs",children:"添加接口配置"}),(0,n.jsx)("button",{type:"button",onClick:_,className:"px-4 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存配置"})]}),x&&(0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 flex flex-col w-full max-w-2xl max-h-[80%]",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-2",children:[(0,n.jsx)("h2",{className:"text-sm font-medium text-zinc-800 dark:text-zinc-100",children:"mock 数据"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsx)("button",{type:"button",title:"复制",onClick:()=>{navigator.clipboard.writeText(x),t.open("success","复制成功")},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"复制"}),(0,n.jsx)("button",{type:"button",onClick:()=>a({response:""}),className:"px-2 py-0.5 bg-gray-500 text-white rounded-md hover:bg-gray-600 transition-colors text-xs",children:"关闭"})]})]}),(0,n.jsx)("pre",{className:"flex-1 overflow-auto bg-zinc-100 dark:bg-zinc-800 p-3 rounded-md overflow-x-auto text-xs text-zinc-800 dark:text-zinc-100",children:x})]})}),u&&null!==p&&(null==d?void 0:d[p])&&(0,g.createPortal)((0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50 box-border",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 w-full max-w-2xl box-border",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-3 box-border",children:[(0,n.jsxs)("h2",{className:"text-sm font-medium text-zinc-700 dark:text-zinc-300",children:["编辑响应体数据 - 接口配置 #",p+1]}),(0,n.jsx)("button",{type:"button",onClick:I,className:"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200",children:"\xd7"})]}),(0,n.jsxs)("div",{className:"space-y-3",children:[(0,n.jsx)("div",{children:(0,n.jsxs)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:["响应体格式 ",(0,n.jsx)("span",{className:"text-red-500",children:"*"})]})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"生成数据条数"}),(0,n.jsx)("input",{type:"number",value:d[p].listCount,onChange:e=>O(p,"listCount",parseInt(e.target.value)||1),min:"1",max:"100",className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{children:[(0,n.jsxs)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:["响应体 JSON ",(0,n.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,n.jsx)(f,{value:y,onChange:e=>a({modalBody:e}),placeholder:'例如: {"code": 200, "data": {"id": "@id", "name": "@name"}, "message": "success"} 或 {"code": 200, "data": {"rows": [{"id": "@id", "name": "@name"}], "total": "@integer(20, 100)"}, "message": "success"}',className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white min-h-[300px] text-xs"})]})]}),(0,n.jsxs)("div",{className:"text-xs text-zinc-500 dark:text-zinc-400 mt-1",children:["支持使用 ",(0,n.jsx)("a",{href:"http://mockjs.com/examples.html",target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline",children:"Mock.js 语法"}),",如 @id, @name, @email 等,",(0,n.jsxs)("div",{className:"text-red-500",children:["数组数据为特殊处理,使用`_|`开头,后面拼接字段:",(0,n.jsx)("b",{children:"_|字段|条数"})," 或者 ",(0,n.jsx)("b",{children:"_|字段"})]})]}),(0,n.jsxs)("div",{className:"flex justify-end space-x-2 mt-3 box-border",children:[(0,n.jsx)("button",{type:"button",onClick:I,className:"px-3 py-1 border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-700 text-zinc-800 dark:text-zinc-200 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-600 transition-colors text-xs",children:"取消"}),(0,n.jsx)("button",{type:"button",onClick:()=>{if(null!==p)try{let e=Function("return "+y)();O(p,"body",e),I()}catch(e){t.open("error","JSON 格式错误,请检查输入")}},className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存"})]})]})}),document.body)]})}function k(){let{state:e,proxyInstance:t}=m(),r=e.isServer,{state:s,dispatch:a,proxyInstance:i}=(0,l.useProxyStore)({rootDir:"",dir:"mock",fileName:"proxy",proxyList:[],response:"",isModalOpen:!1,currentIndex:null,modalBody:"",isEnabledStart:!1},{sync:!0}),c=s.proxyList,d=s.response,x=s.isModalOpen,u=s.currentIndex,p=s.modalBody,y=s.rootDir,k=s.dir,v=s.fileName,j=s.isEnabledStart,z=async()=>{try{let e=await fetch(`${b}/_fairys/_proxy/_is_enabled`).then(e=>e.json());200===e.code&&a({isEnabledStart:e.data})}catch(e){console.error("检查 Proxy 配置服务是否启用失败:",e)}};(0,o.useEffect)(()=>{z()},[]);let N=async()=>{try{let e=await fetch(`${b}/_fairys/_proxy/_destroy`).then(e=>e.json());200===e.code?(a({isEnabledStart:!1}),t.open("success",e.message||"销毁 Proxy 服务成功")):t.open("error",e.message||"销毁 Proxy 服务失败")}catch(e){console.error("销毁 Proxy 服务失败:",e)}},w=async()=>{try{let e=await fetch(`${b}/_fairys/_proxy/_start`).then(e=>e.json());200===e.code?(t.open("success",e.message||"加载 Proxy 服务成功"),a({isEnabledStart:!0})):t.open("error",e.message||"加载 Proxy 服务失败")}catch(e){console.error("加载 Proxy 服务失败:",e)}},C=async()=>{try{let e=`dir=${decodeURIComponent(k)}&fileName=${decodeURIComponent(v)}&rootDir=${decodeURIComponent(y)}`,t=await fetch(`${b}/_fairys/_proxy?${e}`),r=await t.json();if(200===r.code){let e=r.data;Array.isArray(r.data)||(e=[]),a({proxyList:e,dir:r.dir,fileName:r.fileName,rootDir:r.rootDir})}else a({proxyList:[]})}catch(e){t.store.isServer=!1,console.error("获取缓存数据失败:",e)}};(0,o.useEffect)(()=>{C()},[]);let S=(e,t,r)=>{a({proxyList:(i.store.proxyList||[]).map((n,s)=>s===e?{...n,[t]:r}:n)})},O=async e=>{e.preventDefault();let s=!0,o="";for(let e=0;e<c.length;e++){let t=c[e];if(!t.path.trim()){s=!1,o=`代理配置 #${e+1} 的 接口地址 不能为空`;break}if(!t.target.trim()){s=!1,o=`代理配置 #${e+1} 的 目标地址 不能为空`;break}}if(!s)return void t.open("error",o);let i=new Map;for(let e=0;e<c.length;e++){let t=c[e],r=`${t.path.trim()}`;if(i.has(r)){var l;null==(l=i.get(r))||l.push(e+1)}else i.set(r,[e+1])}if(i.size>0){let e=[];for(let[t,r]of i)r.length>1&&e.push((0,n.jsxs)("div",{children:["第 ",r.join(",")," 行数据 接口地址重复;"]},t));if(e.length>0)return void t.open("error",e,5e3)}try{if(r){let e=await fetch(`${b}/_fairys/_proxy`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({proxyList:c,dir:k,fileName:v,rootDir:y})}),r=await e.json();c.length>0?a({response:JSON.stringify(r,null,2)}):200===r.code&&t.open("success","保存成功"),a({rootDir:r.rootDir})}else if(c.length>0){let e=c.reduce((e,t)=>{let{path:r,...n}={...t};return{...e,[r]:n}},{});a({response:JSON.stringify(e,null,2)})}else t.open("success","操作成功")}catch(e){a({response:"Error: "+e.message})}},_=()=>{a({currentIndex:void 0,modalBody:"",isModalOpen:!1}),document.body.style.overflow="auto"};return(0,n.jsxs)("div",{className:"space-y-6 flex-1 flex flex-col box-border overflow-hidden",children:[(0,n.jsxs)("div",{className:"mb-6 text-xs text-zinc-600 dark:text-zinc-300 box-border flex justify-between",children:[(0,n.jsxs)("div",{children:["当前配置总条数: ",c.length]}),r?(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsxs)("button",{type:"button",onClick:w,className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:[j?"重启":"启动"," proxy 服务"]}),j?(0,n.jsx)("button",{type:"button",onClick:N,className:"px-3 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"销毁 proxy 服务"}):(0,n.jsx)(o.Fragment,{})]}):(0,n.jsx)(o.Fragment,{})]}),(0,n.jsxs)("div",{className:"mb-6",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"数据保存到本地"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"根目录"}),(0,n.jsx)("input",{type:"text",value:y,onChange:e=>{a({rootDir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"目录名"}),(0,n.jsx)("input",{type:"text",value:k,onChange:e=>{a({dir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"文件名"}),(0,n.jsx)("input",{type:"text",value:v,onChange:e=>{a({fileName:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsx)("button",{type:"button",onClick:()=>C(),className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors whitespace-nowrap text-xs",children:"查询"})]}),(0,n.jsx)("p",{className:"text-xs text-zinc-500 dark:text-zinc-400 mt-1",children:"默认保存到当前工作目录的 mock 文件夹"})]}),c.length>0?(0,n.jsx)("div",{className:"flex-1 flex flex-col box-border overflow-auto",children:(0,n.jsx)(h,{columns:[{title:"#",tdClassName:"px-2 py-2 text-xs text-zinc-800 dark:text-zinc-100 border-b border-zinc-200 dark:border-zinc-700",isIndex:!0},{title:"接口地址",dataIndex:"path",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:e.path,placeholder:"请使用 ^ 开头",onChange:e=>S(t,"path",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})},{title:"目标地址",dataIndex:"target",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:e.target,onChange:e=>{S(t,"target",e.target.value||"")},className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",placeholder:"目标地址"})},{title:"启用 WebSocket",dataIndex:"enableWebSocket",render:(e,t)=>(0,n.jsx)("input",{type:"checkbox",checked:e.ws||!1,onChange:e=>{S(t,"ws",e.target.checked)},className:"mr-2"})},{title:"路径重写数据",dataIndex:"pathRewrite",render:e=>(0,n.jsx)("div",{className:"text-zinc-500 dark:text-zinc-400 text-xs w-[250px]",children:JSON.stringify(e.pathRewrite,null,2)})},{title:"操作",dataIndex:"operation",render:(e,t)=>(0,n.jsxs)("div",{className:"flex space-x-1",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{a({currentIndex:t,modalBody:JSON.stringify(c[t].pathRewrite,null,2),isModalOpen:!0}),document.body.style.overflow="hidden"},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"编辑路径重写数据"}),(0,n.jsx)("button",{type:"button",onClick:()=>{a({proxyList:(i.store.proxyList||[]).filter((e,r)=>r!==t)})},className:"px-2 py-0.5 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"删除"})]})}],dataSource:c})}):(0,n.jsx)("div",{className:"text-center py-8 text-zinc-500 dark:text-zinc-400",children:'暂无接口配置,请点击"添加接口配置"按钮添加'}),(0,n.jsxs)("div",{className:"flex justify-center",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{a({proxyList:[...i.store.proxyList||[]].concat([{path:"",target:""}])})},className:"px-3 py-1 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors mr-4 text-xs",children:"添加接口配置"}),(0,n.jsx)("button",{type:"button",onClick:O,className:"px-4 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存配置"})]}),d&&(0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 flex flex-col w-full max-w-2xl max-h-[80%]",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-2",children:[(0,n.jsx)("h2",{className:"text-sm font-medium text-zinc-800 dark:text-zinc-100",children:"proxy 数据"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsx)("button",{type:"button",title:"复制",onClick:()=>{navigator.clipboard.writeText(d),t.open("success","复制成功")},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"复制"}),(0,n.jsx)("button",{type:"button",onClick:()=>a({response:""}),className:"px-2 py-0.5 bg-gray-500 text-white rounded-md hover:bg-gray-600 transition-colors text-xs",children:"关闭"})]})]}),(0,n.jsx)("pre",{className:"flex-1 overflow-auto bg-zinc-100 dark:bg-zinc-800 p-3 rounded-md overflow-x-auto text-xs text-zinc-800 dark:text-zinc-100",children:d})]})}),x&&null!==u&&(null==c?void 0:c[u])&&(0,g.createPortal)((0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 w-full max-w-2xl",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-3",children:[(0,n.jsxs)("h2",{className:"text-sm font-medium text-zinc-700 dark:text-zinc-300",children:["编辑响应体数据 - 接口配置 #",u+1]}),(0,n.jsx)("button",{type:"button",onClick:_,className:"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200",children:"\xd7"})]}),(0,n.jsx)("div",{className:"space-y-3",children:(0,n.jsxs)("div",{children:[(0,n.jsxs)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:["路径重写 JSON ",(0,n.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,n.jsx)(f,{value:p,onChange:e=>a({modalBody:e}),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white min-h-[300px] text-xs",placeholder:'例如: { "^/api":"" , "^/api/test":"/api" }'})]})}),(0,n.jsxs)("div",{className:"flex justify-end space-x-2 mt-3 box-border",children:[(0,n.jsx)("button",{type:"button",onClick:_,className:"px-3 py-1 border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-700 text-zinc-800 dark:text-zinc-200 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-600 transition-colors text-xs",children:"取消"}),(0,n.jsx)("button",{type:"button",onClick:()=>{if(null!==u)try{let e=Function("return "+p)();S(u,"pathRewrite",e),_()}catch(e){t.open("error","JSON 格式错误,请检查输入")}},className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存"})]})]})}),document.body)]})}let v={success:"text-green-500",info:"text-blue-500",error:"text-red-500",warning:"text-orange-500"},j={info:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{viewBox:"64 64 896 896",focusable:"false","data-icon":"info-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"})})}),success:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{viewBox:"64 64 896 896",focusable:"false","data-icon":"check-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"})})}),error:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{fillRule:"evenodd",viewBox:"64 64 896 896",focusable:"false","data-icon":"close-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm127.98 274.82h-.04l-.08.06L512 466.75 384.14 338.88c-.04-.05-.06-.06-.08-.06a.12.12 0 00-.07 0c-.03 0-.05.01-.09.05l-45.02 45.02a.2.2 0 00-.05.09.12.12 0 000 .07v.02a.27.27 0 00.06.06L466.75 512 338.88 639.86c-.05.04-.06.06-.06.08a.12.12 0 000 .07c0 .03.01.05.05.09l45.02 45.02a.2.2 0 00.09.05.12.12 0 00.07 0c.02 0 .04-.01.08-.05L512 557.25l127.86 127.87c.04.04.06.05.08.05a.12.12 0 00.07 0c.03 0 .05-.01.09-.05l45.02-45.02a.2.2 0 00.05-.09.12.12 0 000-.07v-.02a.27.27 0 00-.05-.06L557.25 512l127.87-127.86c.04-.04.05-.06.05-.08a.12.12 0 000-.07c0-.03-.01-.05-.05-.09l-45.02-45.02a.2.2 0 00-.09-.05.12.12 0 00-.07 0z"})})}),warning:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{viewBox:"64 64 896 896",focusable:"false","data-icon":"exclamation-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"})})})},z=document.getElementById("root");z&&s.createRoot(z).render((0,n.jsxs)(u,{children:[(0,n.jsx)(function(){let{state:e,dispatch:t}=m(),[r,s]=(0,o.useState)({mock:!0,proxy:!1}),a=e.tabKey,i=e=>{s(t=>({...t,[e]:!0})),t({tabKey:e})};return(0,n.jsx)("div",{className:"h-full bg-zinc-50 dark:bg-black p-4 sm:p-6 box-border overflow-hidden flex flex-col",children:(0,n.jsxs)("div",{className:"flex-1 w-full bg-white dark:bg-zinc-900 rounded-lg shadow-md p-6 box-border flex flex-col overflow-hidden",children:[(0,n.jsxs)("div",{className:"flex border-b border-zinc-200 dark:border-zinc-700 mb-6",children:[(0,n.jsx)("button",{className:`px-4 py-2 text-xs font-medium transition-colors ${"mock"===a?"border-b-2 border-blue-500 text-blue-600 dark:text-blue-400":"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200"}`,onClick:()=>i("mock"),children:"Mocker 数据配置"}),(0,n.jsx)("button",{className:`px-4 py-2 text-xs font-medium transition-colors ${"proxy"===a?"border-b-2 border-blue-500 text-blue-600 dark:text-blue-400":"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200"}`,onClick:()=>i("proxy"),children:"代理配置"})]}),(0,n.jsxs)("div",{className:"flex-1 relative overflow-hidden",children:[r.mock&&(0,n.jsx)("div",{className:`absolute inset-0 flex flex-col box-border overflow-hidden transition-all duration-300 ease-in-out ${"mock"===a?"opacity-100 translate-x-0":"opacity-0 translate-x-4 pointer-events-none"}`,children:(0,n.jsx)(y,{})}),r.proxy&&(0,n.jsx)("div",{className:`absolute inset-0 flex flex-col box-border overflow-hidden transition-all duration-300 ease-in-out ${"proxy"===a?"opacity-100 translate-x-0":"opacity-0 translate-x-4 pointer-events-none"}`,children:(0,n.jsx)(k,{})})]})]})})},{}),(0,n.jsx)(()=>{let{state:e}=m(),t=e.messageList;return Array.isArray(t)&&t.length?(0,n.jsx)("div",{className:"fixed inset-0 flex flex-col items-center z-90 gap-2 py-2 box-border pointer-events-none",children:t.map(e=>{let t=j[e.type],r=v[e.type];return(0,n.jsxs)("div",{className:"shadow-md py-2 px-4 box-border rounded-lg bg-white text-xs flex items-center gap-2 flex-wrap",children:[t?(0,n.jsx)(t,{className:r}):(0,n.jsx)(n.Fragment,{}),(0,n.jsx)("div",{children:e.message})]},e.id)})}):(0,n.jsx)(n.Fragment,{})},{})]}))}},o={};function a(e){var t=o[e];if(void 0!==t)return t.exports;var r=o[e]={exports:{}};return s[e].call(r.exports,r,r.exports,a),r.exports}a.m=s,a.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var r in t)a.o(t,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},e=[],a.O=(t,r,n,s)=>{if(r){s=s||0;for(var o=e.length;o>0&&e[o-1][2]>s;o--)e[o]=e[o-1];e[o]=[r,n,s];return}for(var i=1/0,o=0;o<e.length;o++){for(var[r,n,s]=e[o],l=!0,c=0;c<r.length;c++)(!1&s||i>=s)&&Object.keys(a.O).every(e=>a.O[e](r[c]))?r.splice(c--,1):(l=!1,s<i&&(i=s));if(l){e.splice(o--,1);var d=n();void 0!==d&&(t=d)}}return t},t={410:0},a.O.j=e=>0===t[e],r=(e,r)=>{var n,s,[o,i,l]=r,c=0;if(o.some(e=>0!==t[e])){for(n in i)a.o(i,n)&&(a.m[n]=i[n]);if(l)var d=l(a)}for(e&&e(r);c<o.length;c++)s=o[c],a.o(t,s)&&t[s]&&t[s][0](),t[s]=0;return a.O(d)},(n=self.webpackChunk_fairys_mocker_ui=self.webpackChunk_fairys_mocker_ui||[]).forEach(r.bind(null,0)),n.push=r.bind(null,n.push.bind(n));var i=a.O(void 0,["783","514"],()=>a(711));i=a.O(i)})();
package/src/base.ts CHANGED
@@ -28,7 +28,6 @@ export class FairysMockerBase {
28
28
  mainApp: express.Express | connect.Server | undefined = undefined;
29
29
  /**类*/
30
30
  controller: ClassStruct[] = [MockRouterController, ProxyRouterController];
31
-
32
31
  /**静态文件服务列表*/
33
32
  staticServerList: string[] = [];
34
33
 
package/src/ci.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import parser, { Arguments } from 'yargs-parser'
2
2
  import { fairysMockerExpress, FairysMockerExpress } from "./main.js"
3
3
  import { fairysMockerConnect, FairysMockerConnect } from "./connect.js"
4
- import { utils } from "./utils/utils.js"
4
+ import { utilsGlobalVariable } from "./utils/utils.js"
5
5
 
6
6
  function help() {
7
7
  console.log('\n Usage: \x1b[34;1fairys-mocker\x1b[0m [--help|h|--root|--dir|--file|--file2|--static|--static-prefix|--is-mock-file|--is-proxy-file]');
@@ -32,12 +32,12 @@ export const CI = (app: FairysMockerExpress | FairysMockerConnect) => {
32
32
  help();
33
33
  return;
34
34
  } else {
35
- utils.setRootDir(argv.root);
36
- utils.setDir(argv.dir);
37
- utils.setFile(argv.file);
38
- utils.setProxyFile(argv.file2);
39
- utils.setIsCreateMockDataFile(argv['is-mock-file'])
40
- utils.setIsCreateProxyDataFile(argv['is-proxy-file'])
35
+ utilsGlobalVariable.setRootDir(argv.root);
36
+ utilsGlobalVariable.setDir(argv.dir);
37
+ utilsGlobalVariable.setFile(argv.file);
38
+ utilsGlobalVariable.setProxyFile(argv.file2);
39
+ utilsGlobalVariable.setIsCreateMockDataFile(argv['is-mock-file'])
40
+ utilsGlobalVariable.setIsCreateProxyDataFile(argv['is-proxy-file'])
41
41
  // 1. 直接当 mock 服务,
42
42
  // 2. 生成 mock 数据
43
43
  // 3. mock 服务 + 数据
@@ -1,7 +1,7 @@
1
1
  import express from 'express';
2
2
  import fs from 'node:fs';
3
3
  import { Get, Post, Controller } from "../utils/decorator.js"
4
- import { utils } from "../utils/index.js"
4
+ import { utilsGlobalVariable } from "../utils/index.js"
5
5
  import { MockRouter } from "../router/mock.js"
6
6
  import { BaseController } from "./base.js"
7
7
  import { getMcokFile, createMockFile } from '../utils/mcok.proxy.js';
@@ -23,9 +23,9 @@ export class MockRouterController extends BaseController {
23
23
  // 定义接口
24
24
  try {
25
25
  const { mockList, dir, fileName = 'index.mock', rootDir } = req.body;
26
- let _rootDir = rootDir || utils.rootDir;
26
+ let _rootDir = rootDir || utilsGlobalVariable.rootDir;
27
27
  if (rootDir && !fs.existsSync(rootDir)) {
28
- _rootDir = utils.rootDir;
28
+ _rootDir = utilsGlobalVariable.rootDir;
29
29
  }
30
30
  const mockData = createMockFile(mockList, _rootDir, dir, fileName)
31
31
  if (mockData?.mockConfig) {
@@ -1,9 +1,7 @@
1
1
  import express from 'express';
2
2
  import fs from 'node:fs';
3
- import nodePath from "node:path"
4
- import { createProxyData } from '@fairys/create-mock-data';
5
3
  import { Get, Post, Controller } from "../utils/decorator.js"
6
- import { utils } from "../utils/index.js"
4
+ import { utilsGlobalVariable } from "../utils/utils.js"
7
5
  import { ProxyRouter } from '../router/proxy.js';
8
6
  import { BaseController } from './base.js';
9
7
  import { getProxyFile, createProxyFile } from '../utils/mcok.proxy.js';
@@ -24,9 +22,9 @@ export class ProxyRouterController extends BaseController {
24
22
  post_proxy(req: express.Request, res: express.Response) {
25
23
  try {
26
24
  const { proxyList, dir, fileName = 'proxy', rootDir } = req.body;
27
- let _rootDir = rootDir || utils.rootDir;
25
+ let _rootDir = rootDir || utilsGlobalVariable.rootDir;
28
26
  if (rootDir && !fs.existsSync(rootDir)) {
29
- _rootDir = utils.rootDir;
27
+ _rootDir = utilsGlobalVariable.rootDir;
30
28
  }
31
29
  const proxyData = createProxyFile(proxyList, _rootDir, dir, fileName)
32
30
  if (proxyData?.proxyConfig) {
@@ -110,9 +108,10 @@ export class ProxyRouterController extends BaseController {
110
108
  const proxyData = getProxyFile(rootDir, savePath, saveFileName);
111
109
  if (proxyData?.proxyList) {
112
110
  this.router?.load(proxyData.proxyList);
111
+ const msg = utilsGlobalVariable.isEnableWebsocket ? '启动代理服务成功' : '非websocket服务代理启动成功'
113
112
  res.json({
114
113
  code: 200,
115
- message: '启动代理服务成功',
114
+ message: msg,
116
115
  data: proxyData.proxyList,
117
116
  rootDir: rootDir,
118
117
  dir: proxyData.dir,
@@ -1,11 +1,14 @@
1
1
  import type { RsbuildPlugin } from '@rsbuild/core';
2
2
  import { fairysMockerBase } from '../base.js';
3
+ import { utilsGlobalVariable } from '../utils/utils.js';
3
4
 
4
5
  export const fairysMockerRsbuildPlugin = () => ({
5
6
  setup(api) {
6
7
  api.onBeforeStartDevServer(({ server }) => {
7
8
  fairysMockerBase.initApp(server.middlewares, () => {
8
9
  fairysMockerBase.logServer(server.port);
10
+ // rsbuild/vite等自带websocket服务的环境下无法使用websocket服务
11
+ utilsGlobalVariable.isEnableWebsocket = false;
9
12
  });
10
13
  // @ts-ignore
11
14
  fairysMockerBase.server = server.httpServer
@@ -4,6 +4,7 @@ import { BaseRouter } from "./base.js"
4
4
  import { createProxyMiddleware, RequestHandler } from "http-proxy-middleware"
5
5
  import chalk from "chalk"
6
6
  import { fairysMockerBase } from "../base.js"
7
+ import { utilsGlobalVariable } from "../utils/utils.js"
7
8
 
8
9
  /**代理 路由器实例*/
9
10
  export class ProxyRouter extends BaseRouter<ProxyItem> {
@@ -39,18 +40,21 @@ export class ProxyRouter extends BaseRouter<ProxyItem> {
39
40
  _path = new RegExp('^' + proxyItem.path)
40
41
  }
41
42
  if (proxyItem.ws) {
42
- const wsProxy = createProxyMiddleware({
43
- target: proxyItem.target,
44
- pathRewrite: proxyItem.pathRewrite,
45
- ws: proxyItem.ws,
46
- changeOrigin: true,
47
- })
48
- _that.wsProxyList.push(wsProxy)
49
- router.all(_path, wsProxy)
50
- // 这个地方有个问题,如果在 rsbuild 中使用,websocket 会有问题
51
- if (fairysMockerBase.server) {
52
- // 升级 WebSocket 处理
53
- fairysMockerBase.server?.on('upgrade', wsProxy.upgrade)
43
+ if (utilsGlobalVariable.isEnableWebsocket) {
44
+ const wsProxy = createProxyMiddleware({
45
+ target: proxyItem.target,
46
+ pathRewrite: proxyItem.pathRewrite,
47
+ ws: proxyItem.ws,
48
+ changeOrigin: true,
49
+ })
50
+ _that.wsProxyList.push(wsProxy)
51
+ router.all(_path, wsProxy)
52
+ if (fairysMockerBase.server) {
53
+ // 升级 WebSocket 处理
54
+ fairysMockerBase.server?.on('upgrade', wsProxy.upgrade)
55
+ }
56
+ } else {
57
+ console.log(chalk.red(`rsbuild/vite等自带websocket服务的环境下无法代理websocket服务:${proxyItem.path}`))
54
58
  }
55
59
  } else {
56
60
  // 这个不生效问题
@@ -2,13 +2,13 @@
2
2
  /**保存配置和读取配置*/
3
3
  import nodePath from "node:path"
4
4
  import fs from 'node:fs';
5
- import { utils } from "./utils.js";
5
+ import { utilsGlobalVariable } from "./utils.js";
6
6
  import { createProxyData, createMockData, ProxyList, DefineMockList } from "@fairys/create-mock-data";
7
7
 
8
8
  export const getProxyFile = (rootDir?: string, dir?: string, fileName?: string) => {
9
- const _rootDir = rootDir?.trim() || utils.rootDir;
10
- const _dir = dir?.trim() || utils.dir;
11
- const _fileName = fileName?.trim() || utils.proxyFile;
9
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
10
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
11
+ const _fileName = fileName?.trim() || utilsGlobalVariable.proxyFile;
12
12
  // 读取 .cache.json 文件
13
13
  const proxyDir = nodePath.join(_rootDir, _dir);
14
14
  const cacheFilePath = nodePath.join(proxyDir, _fileName + '.cache.json');
@@ -28,9 +28,9 @@ export const getProxyFile = (rootDir?: string, dir?: string, fileName?: string)
28
28
  }
29
29
 
30
30
  export const createProxyFile = (proxyList: ProxyList, rootDir?: string, dir?: string, fileName?: string) => {
31
- const _rootDir = rootDir?.trim() || utils.rootDir;
32
- const _dir = dir?.trim() || utils.dir;
33
- const _fileName = fileName?.trim() || utils.proxyFile;
31
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
32
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
33
+ const _fileName = fileName?.trim() || utilsGlobalVariable.proxyFile;
34
34
  // 读取 .cache.json 文件
35
35
  const proxyDir = nodePath.join(_rootDir, _dir);
36
36
 
@@ -38,7 +38,7 @@ export const createProxyFile = (proxyList: ProxyList, rootDir?: string, dir?: st
38
38
  fs.mkdirSync(proxyDir, { recursive: true });
39
39
  }
40
40
  const proxyConfig = createProxyData(proxyList)
41
- if (utils.isCreateProxyDataFile) {
41
+ if (utilsGlobalVariable.isCreateProxyDataFile) {
42
42
  const proxyFilePath = nodePath.join(proxyDir, `${_fileName}.ts`);
43
43
  const proxyFileContent = `// 代理配置文件
44
44
  // 自动生成于 ${new Date().toISOString()}
@@ -82,9 +82,9 @@ export default proxyConfig;
82
82
  }
83
83
 
84
84
  export const getMcokFile = (rootDir?: string, dir?: string, fileName?: string) => {
85
- const _rootDir = rootDir?.trim() || utils.rootDir;
86
- const _dir = dir?.trim() || utils.dir;
87
- const _fileName = fileName?.trim() || utils.file;
85
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
86
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
87
+ const _fileName = fileName?.trim() || utilsGlobalVariable.file;
88
88
  // 读取 .cache.json 文件
89
89
  const mockDir = nodePath.join(_rootDir, _dir);
90
90
  const cacheFilePath = nodePath.join(mockDir, _fileName + '.cache.json');
@@ -104,9 +104,9 @@ export const getMcokFile = (rootDir?: string, dir?: string, fileName?: string) =
104
104
  }
105
105
 
106
106
  export const createMockFile = (mockList: DefineMockList, rootDir?: string, dir?: string, fileName?: string) => {
107
- const _rootDir = rootDir?.trim() || utils.rootDir;
108
- const _dir = dir?.trim() || utils.dir;
109
- const _fileName = fileName?.trim() || utils.file;
107
+ const _rootDir = rootDir?.trim() || utilsGlobalVariable.rootDir;
108
+ const _dir = dir?.trim() || utilsGlobalVariable.dir;
109
+ const _fileName = fileName?.trim() || utilsGlobalVariable.file;
110
110
  // 读取 .cache.json 文件
111
111
  const mockDir = nodePath.join(_rootDir, _dir);
112
112
 
@@ -114,7 +114,7 @@ export const createMockFile = (mockList: DefineMockList, rootDir?: string, dir?:
114
114
  fs.mkdirSync(mockDir, { recursive: true });
115
115
  }
116
116
  const mockConfig = createMockData(mockList)
117
- if (utils.isCreateMockDataFile) {
117
+ if (utilsGlobalVariable.isCreateMockDataFile) {
118
118
  const mockFilePath = nodePath.join(mockDir, `${_fileName}.ts`);
119
119
  const mockFileContent = `// Mock 配置文件
120
120
  // 自动生成于 ${new Date().toISOString()}
@@ -3,7 +3,7 @@ import chalk from 'chalk';
3
3
  import fs from 'node:fs';
4
4
  import path from "node:path"
5
5
 
6
- class Utils {
6
+ class UtilsGlobalVariable {
7
7
  /**根目录*/
8
8
  public rootDir = process.cwd();
9
9
  /**目录名*/
@@ -16,6 +16,8 @@ class Utils {
16
16
  public isCreateMockDataFile = true;
17
17
  /**是否生成proxy数据文件*/
18
18
  public isCreateProxyDataFile = true;
19
+ /**是否可以启用 websocket 服务(在rsbuild/vite等自带websocket服务的环境下无法使用)*/
20
+ public isEnableWebsocket: boolean = true;
19
21
 
20
22
  /**设置根目录*/
21
23
  setRootDir = (value?: string) => {
@@ -59,7 +61,6 @@ class Utils {
59
61
  this.isCreateProxyDataFile = fig
60
62
  }
61
63
  }
62
-
63
64
  }
64
65
 
65
- export const utils = new Utils()
66
+ export const utilsGlobalVariable = new UtilsGlobalVariable()
@@ -1 +0,0 @@
1
- (()=>{"use strict";var e,t,r,n,s={711(e,t,r){var n=r(85),s=r(873),o=r(41),i=r(424),a=r.n(i),l=r(346),c=r(990);class d extends l.ProxyInstanceObject{constructor(...e){var t;super(...e),t=this,(0,c._)(this,"open",function(e,r){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3,s=new Date().valueOf().toString();t.store.messageList.push((0,l.ref)({type:e,message:r,id:s}));let o=setTimeout(()=>{t.store.messageList=t.store.messageList.filter(e=>e.id!==s),clearTimeout(o)},n)})}}let x=new d()._ctor({tabKey:"mock",messageList:[],isServer:!0}),{MainProxyProvider:u,useMainProxyStore:m}=(0,l.createCommonMainStore)({proxyInstance:x,namespace:"global"}),b=window.location.origin;function h(e){let{columns:t,dataSource:r,rowKey:s}=e,i=(0,o.useMemo)(()=>(0,n.jsx)("tr",{className:"bg-zinc-100 dark:bg-zinc-800 sticky -top-px z-10",children:t.map((e,t)=>(0,n.jsx)("th",{className:"px-2 py-2 text-left text-xs font-medium text-zinc-700 dark:text-zinc-300 border-b border-zinc-200 dark:border-zinc-700",children:e.title},e.dataIndex||t))}),[t]);return(0,n.jsx)("div",{className:"flex-1 flex flex-col box-border overflow-auto",children:(0,n.jsxs)("table",{className:"border-collapse min-w-full border border-zinc-200 dark:border-zinc-700 relative",children:[(0,n.jsx)("thead",{children:i}),(0,n.jsx)("tbody",{children:r.map((e,r)=>{let o="function"==typeof s?s(e):s?e[s]:r;return(0,n.jsx)("tr",{className:"hover:bg-zinc-50 dark:hover:bg-zinc-800",children:t.map(t=>{let s=t.dataIndex?e[t.dataIndex]:e;if(t.isIndex&&(s=r+1),t.render){var i;s=null==(i=t.render)?void 0:i.call(t,e,r)}return(0,n.jsx)("td",{className:`px-2 py-2 border-b border-zinc-200 dark:border-zinc-700 ${t.tdClassName||""}`,children:s},`${o}-${t.dataIndex}`)})},o)})})]})})}var p=r(224);let f=e=>{let{value:t,onChange:r,placeholder:s,className:o}=e;return(0,n.jsx)(p.A,{value:t,language:"json",placeholder:s,onChange:e=>null==r?void 0:r(e.target.value),padding:15,className:o,style:{fontFamily:"ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",minHeight:280}})};var g=r(144);function y(){let{state:e,proxyInstance:t}=m(),r=e.isServer,{state:s,dispatch:i,proxyInstance:c}=(0,l.useProxyStore)({rootDir:"",dir:"mock",fileName:"index.mock",mockList:[],response:"",isModalOpen:!1,currentIndex:null,modalBody:"",isEnabledStart:!1},{sync:!0}),d=s.mockList,x=s.response,u=s.isModalOpen,p=s.currentIndex,y=s.modalBody,k=s.rootDir,v=s.dir,j=s.fileName,z=s.isEnabledStart,N=async()=>{try{let e=await fetch(`${b}/_fairys/_mock/_is_enabled`).then(e=>e.json());200===e.code&&i({isEnabledStart:e.data})}catch(e){console.error("检查 mock 配置服务是否启用失败:",e)}};(0,o.useEffect)(()=>{N()},[]);let w=async()=>{try{let e=await fetch(`${b}/_fairys/_mock/_destroy`).then(e=>e.json());200===e.code?(i({isEnabledStart:!1}),t.open("success","销毁 Mock 数据服务成功")):t.open("error",e.message||"销毁 Mock 数据服务失败")}catch(e){console.error("销毁 mock 数据服务失败:",e)}},C=async()=>{try{let e=await fetch(`${b}/_fairys/_mock/_start`).then(e=>e.json());200===e.code?(t.open("success","加载 Mock 数据服务成功"),i({isEnabledStart:!0})):t.open("error",e.message||"加载 Mock 数据服务失败")}catch(e){console.error("加载 mock 数据服务失败:",e)}},S=async e=>{try{let t;if(!0===e)t=await fetch(`${b}/_fairys/_mock`);else{let e=`dir=${decodeURIComponent(v)}&fileName=${decodeURIComponent(j)}&rootDir=${decodeURIComponent(k)}`;t=await fetch(`${b}/_fairys/_mock?${e}`)}let r=await t.json();200===r.code?i({mockList:r.data,dir:r.dir,fileName:r.fileName,rootDir:r.rootDir}):i({mockList:[]})}catch(e){t.store.isServer=!1,console.error("获取缓存数据失败:",e)}};(0,o.useEffect)(()=>{S(!0)},[]);let O=(e,t,r)=>{i({mockList:(c.store.mockList||[]).map((n,s)=>s===e?{...n,[t]:r}:n)})},_=async e=>{e.preventDefault();let s=!0,o="";for(let e=0;e<d.length;e++){let t=d[e];if(!t.url.trim()){s=!1,o=`接口配置 #${e+1} 的 接口地址 不能为空`;break}if(!t.method){s=!1,o=`接口配置 #${e+1} 的 请求方法 不能为空`;break}if(!t.status.trim()){s=!1,o=`接口配置 #${e+1} 的 状态码 不能为空`;break}if(!t.body){s=!1,o=`接口配置 #${e+1} 的 响应体 不能为空`;break}}if(!s)return void t.open("error",o);let l=new Map;for(let e=0;e<d.length;e++){let t=d[e],r=`${t.url.trim()}:${t.method}`;if(l.has(r)){var c;null==(c=l.get(r))||c.push(e+1)}else l.set(r,[e+1])}if(l.size>0){let e=[];for(let[t,r]of l)r.length>1&&e.push((0,n.jsxs)("div",{children:["第 ",r.join(",")," 行数据 接口地址和请求方法 组合重复;"]},t));if(e.length>0)return void t.open("error",e,5e3)}try{if(r){let e=await fetch(`${b}/_fairys/_mock`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({mockList:d,dir:v,fileName:j,rootDir:k})}),r=await e.json();d.length>0?i({response:JSON.stringify(r,null,2)}):200===r.code&&t.open("success","保存成功"),i({rootDir:r.rootDir})}else if(d.length>0){let e=d.map(e=>(function(e){let{data:t,...r}={...e.body},n={},s=Object.keys(t),o=e.listCount||20;for(let e=0;e<s.length;e++){let r=s[e],i=t[r];if(/^(\_\|)/.test(r)){let[e,t,s]=r.split("|"),l=`${s||""}`.trim();i&&(n[t]=Array.from({length:l?Number(l):o},()=>a().mock(i)))}else Object.assign(n,a().mock({[r]:i}))}r.data=n;let i=0;if(Array.isArray(e.delay)){let[t,r]=e.delay;i=Math.floor(Math.random()*(r-t+1))+t}else i=e.delay;return{...e,body:r,delay:i}})(e));i({response:JSON.stringify(e,null,2)})}else t.open("success","操作成功")}catch(e){i({response:"Error: "+e.message})}},I=()=>{i({currentIndex:void 0,modalBody:"",isModalOpen:!1}),document.body.style.overflow="auto"};return(0,n.jsxs)("div",{className:"space-y-6 flex-1 flex flex-col box-border overflow-hidden",children:[(0,n.jsxs)("div",{className:"mb-6 text-xs text-zinc-600 dark:text-zinc-300 box-border flex justify-between",children:[(0,n.jsxs)("div",{children:["当前配置总条数: ",d.length]}),r?(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsxs)("button",{type:"button",onClick:C,className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:[z?"重启":"启动"," mock 数据服务"]}),z?(0,n.jsx)("button",{type:"button",onClick:w,className:"px-3 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"销毁 mock 数据服务"}):(0,n.jsx)(o.Fragment,{})]}):(0,n.jsx)(o.Fragment,{})]}),(0,n.jsxs)("div",{className:"mb-6",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"数据保存到本地"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"根目录"}),(0,n.jsx)("input",{type:"text",value:k,onChange:e=>{i({rootDir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"目录名"}),(0,n.jsx)("input",{type:"text",value:v,onChange:e=>{i({dir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"文件名"}),(0,n.jsx)("input",{type:"text",value:j,onChange:e=>{i({fileName:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsx)("button",{type:"button",onClick:()=>S(!1),className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors whitespace-nowrap text-xs",children:"查询"})]}),(0,n.jsx)("p",{className:"text-xs text-zinc-500 dark:text-zinc-400 mt-1",children:"默认保存到当前工作目录的 mock 文件夹"})]}),d.length>0?(0,n.jsx)("div",{className:"flex-1 flex flex-col box-border overflow-auto",children:(0,n.jsx)(h,{columns:[{title:"#",isIndex:!0,tdClassName:"px-2 py-2 text-xs text-zinc-800 dark:text-zinc-100 border-b border-zinc-200 dark:border-zinc-700"},{title:"接口地址",dataIndex:"url",render:(e,t)=>(0,n.jsx)("input",{type:"text",placeholder:"请输入接口地址",value:e.url,onChange:e=>O(t,"url",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})},{title:"请求方法",dataIndex:"method",render:(e,t)=>(0,n.jsxs)("select",{value:e.method,onChange:e=>O(t,"method",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",children:[(0,n.jsx)("option",{value:"GET",children:"GET"}),(0,n.jsx)("option",{value:"POST",children:"POST"}),(0,n.jsx)("option",{value:"PUT",children:"PUT"}),(0,n.jsx)("option",{value:"DELETE",children:"DELETE"}),(0,n.jsx)("option",{value:"PATCH",children:"PATCH"}),(0,n.jsx)("option",{value:"HEAD",children:"HEAD"}),(0,n.jsx)("option",{value:"OPTIONS",children:"OPTIONS"})]})},{title:"状态码",dataIndex:"status",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:e.status,onChange:e=>O(t,"status",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",placeholder:"例如: 200, 400, 500"})},{title:"响应延迟时间(ms)",dataIndex:"delay",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:Array.isArray(e.delay)?`${e.delay[0]},${e.delay[1]}`:e.delay||"",onChange:e=>{let r=e.target.value;if(r.includes(",")){let[e,n]=r.split(",").map(Number);O(t,"delay",[e,n])}else O(t,"delay",parseInt(r)||0)},className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",placeholder:"例如: 1000 或 500,2000"})},{title:"生成数据条数",dataIndex:"listCount",render:(e,t)=>(0,n.jsx)("input",{type:"number",value:e.listCount,onChange:e=>O(t,"listCount",parseInt(e.target.value)||1),min:"1",max:"100",className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})},{title:"响应体数据",dataIndex:"body",render:e=>(0,n.jsx)("div",{className:"text-zinc-500 dark:text-zinc-400 text-xs w-[400px]",children:JSON.stringify(e.body,null,2)})},{title:"操作",dataIndex:"operation",render:(e,t)=>(0,n.jsxs)("div",{className:"flex space-x-1",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{i({currentIndex:t,modalBody:JSON.stringify(d[t].body,null,2),isModalOpen:!0}),document.body.style.overflow="hidden"},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"编辑响应体数据"}),(0,n.jsx)("button",{type:"button",onClick:()=>{i({mockList:(c.store.mockList||[]).filter((e,r)=>r!==t)})},className:"px-2 py-0.5 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"删除"})]})}],dataSource:d})}):(0,n.jsx)("div",{className:"text-center py-8 text-zinc-500 dark:text-zinc-400",children:'暂无接口配置,请点击"添加接口配置"按钮添加'}),(0,n.jsxs)("div",{className:"flex justify-center",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{i({mockList:[...c.store.mockList||[]].concat([{url:"",method:"POST",status:"200",delay:0,body:{code:200,data:{id:"@id",name:"@name",email:"@email"},message:"success"},listCount:20}])})},className:"px-3 py-1 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors mr-4 text-xs",children:"添加接口配置"}),(0,n.jsx)("button",{type:"button",onClick:_,className:"px-4 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存配置"})]}),x&&(0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 flex flex-col w-full max-w-2xl max-h-[80%]",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-2",children:[(0,n.jsx)("h2",{className:"text-sm font-medium text-zinc-800 dark:text-zinc-100",children:"mock 数据"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsx)("button",{type:"button",title:"复制",onClick:()=>{navigator.clipboard.writeText(x),t.open("success","复制成功")},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"复制"}),(0,n.jsx)("button",{type:"button",onClick:()=>i({response:""}),className:"px-2 py-0.5 bg-gray-500 text-white rounded-md hover:bg-gray-600 transition-colors text-xs",children:"关闭"})]})]}),(0,n.jsx)("pre",{className:"flex-1 overflow-auto bg-zinc-100 dark:bg-zinc-800 p-3 rounded-md overflow-x-auto text-xs text-zinc-800 dark:text-zinc-100",children:x})]})}),u&&null!==p&&(null==d?void 0:d[p])&&(0,g.createPortal)((0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50 box-border",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 w-full max-w-2xl box-border",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-3 box-border",children:[(0,n.jsxs)("h2",{className:"text-sm font-medium text-zinc-700 dark:text-zinc-300",children:["编辑响应体数据 - 接口配置 #",p+1]}),(0,n.jsx)("button",{type:"button",onClick:I,className:"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200",children:"\xd7"})]}),(0,n.jsxs)("div",{className:"space-y-3",children:[(0,n.jsx)("div",{children:(0,n.jsxs)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:["响应体格式 ",(0,n.jsx)("span",{className:"text-red-500",children:"*"})]})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"生成数据条数"}),(0,n.jsx)("input",{type:"number",value:d[p].listCount,onChange:e=>O(p,"listCount",parseInt(e.target.value)||1),min:"1",max:"100",className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{children:[(0,n.jsxs)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:["响应体 JSON ",(0,n.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,n.jsx)(f,{value:y,onChange:e=>i({modalBody:e}),placeholder:'例如: {"code": 200, "data": {"id": "@id", "name": "@name"}, "message": "success"} 或 {"code": 200, "data": {"rows": [{"id": "@id", "name": "@name"}], "total": "@integer(20, 100)"}, "message": "success"}',className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white min-h-[300px] text-xs"})]})]}),(0,n.jsxs)("div",{className:"text-xs text-zinc-500 dark:text-zinc-400 mt-1",children:["支持使用 ",(0,n.jsx)("a",{href:"http://mockjs.com/examples.html",target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline",children:"Mock.js 语法"}),",如 @id, @name, @email 等,",(0,n.jsxs)("div",{className:"text-red-500",children:["数组数据为特殊处理,使用`_|`开头,后面拼接字段:",(0,n.jsx)("b",{children:"_|字段|条数"})," 或者 ",(0,n.jsx)("b",{children:"_|字段"})]})]}),(0,n.jsxs)("div",{className:"flex justify-end space-x-2 mt-3 box-border",children:[(0,n.jsx)("button",{type:"button",onClick:I,className:"px-3 py-1 border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-700 text-zinc-800 dark:text-zinc-200 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-600 transition-colors text-xs",children:"取消"}),(0,n.jsx)("button",{type:"button",onClick:()=>{if(null!==p)try{let e=Function("return "+y)();O(p,"body",e),I()}catch(e){t.open("error","JSON 格式错误,请检查输入")}},className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存"})]})]})}),document.body)]})}function k(){let{state:e,proxyInstance:t}=m(),r=e.isServer,{state:s,dispatch:i,proxyInstance:a}=(0,l.useProxyStore)({rootDir:"",dir:"mock",fileName:"proxy",proxyList:[],response:"",isModalOpen:!1,currentIndex:null,modalBody:"",isEnabledStart:!1},{sync:!0}),c=s.proxyList,d=s.response,x=s.isModalOpen,u=s.currentIndex,p=s.modalBody,y=s.rootDir,k=s.dir,v=s.fileName,j=s.isEnabledStart,z=async()=>{try{let e=await fetch(`${b}/_fairys/_proxy/_is_enabled`).then(e=>e.json());200===e.code&&i({isEnabledStart:e.data})}catch(e){console.error("检查 Proxy 配置服务是否启用失败:",e)}};(0,o.useEffect)(()=>{z()},[]);let N=async()=>{try{let e=await fetch(`${b}/_fairys/_proxy/_destroy`).then(e=>e.json());200===e.code?(i({isEnabledStart:!1}),t.open("success","销毁 Proxy 服务成功")):t.open("error",e.message||"销毁 Proxy 服务失败")}catch(e){console.error("销毁 Proxy 服务失败:",e)}},w=async()=>{try{let e=await fetch(`${b}/_fairys/_proxy/_start`).then(e=>e.json());200===e.code?(t.open("success","加载 Proxy 服务成功"),i({isEnabledStart:!0})):t.open("error",e.message||"加载 Proxy 服务失败")}catch(e){console.error("加载 Proxy 服务失败:",e)}},C=async()=>{try{let e=`dir=${decodeURIComponent(k)}&fileName=${decodeURIComponent(v)}&rootDir=${decodeURIComponent(y)}`,t=await fetch(`${b}/_fairys/_proxy?${e}`),r=await t.json();if(200===r.code){let e=r.data;Array.isArray(r.data)||(e=[]),i({proxyList:e,dir:r.dir,fileName:r.fileName,rootDir:r.rootDir})}else i({proxyList:[]})}catch(e){t.store.isServer=!1,console.error("获取缓存数据失败:",e)}};(0,o.useEffect)(()=>{C()},[]);let S=(e,t,r)=>{i({proxyList:(a.store.proxyList||[]).map((n,s)=>s===e?{...n,[t]:r}:n)})},O=async e=>{e.preventDefault();let s=!0,o="";for(let e=0;e<c.length;e++){let t=c[e];if(!t.path.trim()){s=!1,o=`代理配置 #${e+1} 的 接口地址 不能为空`;break}if(!t.target.trim()){s=!1,o=`代理配置 #${e+1} 的 目标地址 不能为空`;break}}if(!s)return void t.open("error",o);let a=new Map;for(let e=0;e<c.length;e++){let t=c[e],r=`${t.path.trim()}`;if(a.has(r)){var l;null==(l=a.get(r))||l.push(e+1)}else a.set(r,[e+1])}if(a.size>0){let e=[];for(let[t,r]of a)r.length>1&&e.push((0,n.jsxs)("div",{children:["第 ",r.join(",")," 行数据 接口地址重复;"]},t));if(e.length>0)return void t.open("error",e,5e3)}try{if(r){let e=await fetch(`${b}/_fairys/_proxy`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({proxyList:c,dir:k,fileName:v,rootDir:y})}),r=await e.json();c.length>0?i({response:JSON.stringify(r,null,2)}):200===r.code&&t.open("success","保存成功"),i({rootDir:r.rootDir})}else if(c.length>0){let e=c.reduce((e,t)=>{let{path:r,...n}={...t};return{...e,[r]:n}},{});i({response:JSON.stringify(e,null,2)})}else t.open("success","操作成功")}catch(e){i({response:"Error: "+e.message})}},_=()=>{i({currentIndex:void 0,modalBody:"",isModalOpen:!1}),document.body.style.overflow="auto"};return(0,n.jsxs)("div",{className:"space-y-6 flex-1 flex flex-col box-border overflow-hidden",children:[(0,n.jsxs)("div",{className:"mb-6 text-xs text-zinc-600 dark:text-zinc-300 box-border flex justify-between",children:[(0,n.jsxs)("div",{children:["当前配置总条数: ",c.length]}),r?(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsxs)("button",{type:"button",onClick:w,className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:[j?"重启":"启动"," proxy 服务"]}),j?(0,n.jsx)("button",{type:"button",onClick:N,className:"px-3 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"销毁 proxy 服务"}):(0,n.jsx)(o.Fragment,{})]}):(0,n.jsx)(o.Fragment,{})]}),(0,n.jsxs)("div",{className:"mb-6",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"数据保存到本地"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"根目录"}),(0,n.jsx)("input",{type:"text",value:y,onChange:e=>{i({rootDir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"目录名"}),(0,n.jsx)("input",{type:"text",value:k,onChange:e=>{i({dir:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsxs)("div",{className:"flex-1 flex items-center gap-2",children:[(0,n.jsx)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:"文件名"}),(0,n.jsx)("input",{type:"text",value:v,onChange:e=>{i({fileName:e.target.value})},className:"flex-1 px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})]}),(0,n.jsx)("button",{type:"button",onClick:()=>C(),className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors whitespace-nowrap text-xs",children:"查询"})]}),(0,n.jsx)("p",{className:"text-xs text-zinc-500 dark:text-zinc-400 mt-1",children:"默认保存到当前工作目录的 mock 文件夹"})]}),c.length>0?(0,n.jsx)("div",{className:"flex-1 flex flex-col box-border overflow-auto",children:(0,n.jsx)(h,{columns:[{title:"#",tdClassName:"px-2 py-2 text-xs text-zinc-800 dark:text-zinc-100 border-b border-zinc-200 dark:border-zinc-700",isIndex:!0},{title:"接口地址",dataIndex:"path",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:e.path,placeholder:"请使用 ^ 开头",onChange:e=>S(t,"path",e.target.value),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs"})},{title:"目标地址",dataIndex:"target",render:(e,t)=>(0,n.jsx)("input",{type:"text",value:e.target,onChange:e=>{S(t,"target",e.target.value||"")},className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white text-xs",placeholder:"目标地址"})},{title:"启用 WebSocket",dataIndex:"enableWebSocket",render:(e,t)=>(0,n.jsx)("input",{type:"checkbox",checked:e.ws||!1,onChange:e=>{S(t,"ws",e.target.checked)},className:"mr-2"})},{title:"路径重写数据",dataIndex:"pathRewrite",render:e=>(0,n.jsx)("div",{className:"text-zinc-500 dark:text-zinc-400 text-xs w-[250px]",children:JSON.stringify(e.pathRewrite,null,2)})},{title:"操作",dataIndex:"operation",render:(e,t)=>(0,n.jsxs)("div",{className:"flex space-x-1",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{i({currentIndex:t,modalBody:JSON.stringify(c[t].pathRewrite,null,2),isModalOpen:!0}),document.body.style.overflow="hidden"},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"编辑路径重写数据"}),(0,n.jsx)("button",{type:"button",onClick:()=>{i({proxyList:(a.store.proxyList||[]).filter((e,r)=>r!==t)})},className:"px-2 py-0.5 bg-red-500 text-white rounded-md hover:bg-red-600 transition-colors text-xs",children:"删除"})]})}],dataSource:c})}):(0,n.jsx)("div",{className:"text-center py-8 text-zinc-500 dark:text-zinc-400",children:'暂无接口配置,请点击"添加接口配置"按钮添加'}),(0,n.jsxs)("div",{className:"flex justify-center",children:[(0,n.jsx)("button",{type:"button",onClick:()=>{i({proxyList:[...a.store.proxyList||[]].concat([{path:"",target:""}])})},className:"px-3 py-1 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors mr-4 text-xs",children:"添加接口配置"}),(0,n.jsx)("button",{type:"button",onClick:O,className:"px-4 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存配置"})]}),d&&(0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 flex flex-col w-full max-w-2xl max-h-[80%]",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-2",children:[(0,n.jsx)("h2",{className:"text-sm font-medium text-zinc-800 dark:text-zinc-100",children:"proxy 数据"}),(0,n.jsxs)("div",{className:"flex gap-4",children:[(0,n.jsx)("button",{type:"button",title:"复制",onClick:()=>{navigator.clipboard.writeText(d),t.open("success","复制成功")},className:"px-2 py-0.5 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"复制"}),(0,n.jsx)("button",{type:"button",onClick:()=>i({response:""}),className:"px-2 py-0.5 bg-gray-500 text-white rounded-md hover:bg-gray-600 transition-colors text-xs",children:"关闭"})]})]}),(0,n.jsx)("pre",{className:"flex-1 overflow-auto bg-zinc-100 dark:bg-zinc-800 p-3 rounded-md overflow-x-auto text-xs text-zinc-800 dark:text-zinc-100",children:d})]})}),x&&null!==u&&(null==c?void 0:c[u])&&(0,g.createPortal)((0,n.jsx)("div",{className:"fixed inset-0 bg-black/30 flex items-center justify-center z-50",children:(0,n.jsxs)("div",{className:"bg-white/90 dark:bg-zinc-900/90 backdrop-blur-sm rounded-lg shadow-xl p-4 w-full max-w-2xl",children:[(0,n.jsxs)("div",{className:"flex justify-between items-center mb-3",children:[(0,n.jsxs)("h2",{className:"text-sm font-medium text-zinc-700 dark:text-zinc-300",children:["编辑响应体数据 - 接口配置 #",u+1]}),(0,n.jsx)("button",{type:"button",onClick:_,className:"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200",children:"\xd7"})]}),(0,n.jsx)("div",{className:"space-y-3",children:(0,n.jsxs)("div",{children:[(0,n.jsxs)("label",{className:"block text-xs font-medium text-zinc-700 dark:text-zinc-300 mb-1",children:["路径重写 JSON ",(0,n.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,n.jsx)(f,{value:p,onChange:e=>i({modalBody:e}),className:"w-full px-2 py-1 border border-zinc-300 dark:border-zinc-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-zinc-800 dark:text-white min-h-[300px] text-xs",placeholder:'例如: { "^/api":"" , "^/api/test":"/api" }'})]})}),(0,n.jsxs)("div",{className:"flex justify-end space-x-2 mt-3 box-border",children:[(0,n.jsx)("button",{type:"button",onClick:_,className:"px-3 py-1 border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-700 text-zinc-800 dark:text-zinc-200 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-600 transition-colors text-xs",children:"取消"}),(0,n.jsx)("button",{type:"button",onClick:()=>{if(null!==u)try{let e=Function("return "+p)();S(u,"pathRewrite",e),_()}catch(e){t.open("error","JSON 格式错误,请检查输入")}},className:"px-3 py-1 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors text-xs",children:"保存"})]})]})}),document.body)]})}let v={success:"text-green-500",info:"text-blue-500",error:"text-red-500",warning:"text-orange-500"},j={info:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{viewBox:"64 64 896 896",focusable:"false","data-icon":"info-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"})})}),success:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{viewBox:"64 64 896 896",focusable:"false","data-icon":"check-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"})})}),error:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{fillRule:"evenodd",viewBox:"64 64 896 896",focusable:"false","data-icon":"close-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm127.98 274.82h-.04l-.08.06L512 466.75 384.14 338.88c-.04-.05-.06-.06-.08-.06a.12.12 0 00-.07 0c-.03 0-.05.01-.09.05l-45.02 45.02a.2.2 0 00-.05.09.12.12 0 000 .07v.02a.27.27 0 00.06.06L466.75 512 338.88 639.86c-.05.04-.06.06-.06.08a.12.12 0 000 .07c0 .03.01.05.05.09l45.02 45.02a.2.2 0 00.09.05.12.12 0 00.07 0c.02 0 .04-.01.08-.05L512 557.25l127.86 127.87c.04.04.06.05.08.05a.12.12 0 00.07 0c.03 0 .05-.01.09-.05l45.02-45.02a.2.2 0 00.05-.09.12.12 0 000-.07v-.02a.27.27 0 00-.05-.06L557.25 512l127.87-127.86c.04-.04.05-.06.05-.08a.12.12 0 000-.07c0-.03-.01-.05-.05-.09l-45.02-45.02a.2.2 0 00-.09-.05.12.12 0 00-.07 0z"})})}),warning:e=>(0,n.jsx)("span",{...e,children:(0,n.jsx)("svg",{viewBox:"64 64 896 896",focusable:"false","data-icon":"exclamation-circle",width:"1em",height:"1em",fill:"currentColor",children:(0,n.jsx)("path",{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"})})})},z=document.getElementById("root");z&&s.createRoot(z).render((0,n.jsxs)(u,{children:[(0,n.jsx)(function(){let{state:e,dispatch:t}=m(),[r,s]=(0,o.useState)({mock:!0,proxy:!1}),i=e.tabKey,a=e=>{s(t=>({...t,[e]:!0})),t({tabKey:e})};return(0,n.jsx)("div",{className:"h-full bg-zinc-50 dark:bg-black p-4 sm:p-6 box-border overflow-hidden flex flex-col",children:(0,n.jsxs)("div",{className:"flex-1 w-full bg-white dark:bg-zinc-900 rounded-lg shadow-md p-6 box-border flex flex-col overflow-hidden",children:[(0,n.jsxs)("div",{className:"flex border-b border-zinc-200 dark:border-zinc-700 mb-6",children:[(0,n.jsx)("button",{className:`px-4 py-2 text-xs font-medium transition-colors ${"mock"===i?"border-b-2 border-blue-500 text-blue-600 dark:text-blue-400":"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200"}`,onClick:()=>a("mock"),children:"Mocker 数据配置"}),(0,n.jsx)("button",{className:`px-4 py-2 text-xs font-medium transition-colors ${"proxy"===i?"border-b-2 border-blue-500 text-blue-600 dark:text-blue-400":"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200"}`,onClick:()=>a("proxy"),children:"代理配置"})]}),(0,n.jsxs)("div",{className:"flex-1 relative overflow-hidden",children:[r.mock&&(0,n.jsx)("div",{className:`absolute inset-0 flex flex-col box-border overflow-hidden transition-all duration-300 ease-in-out ${"mock"===i?"opacity-100 translate-x-0":"opacity-0 translate-x-4 pointer-events-none"}`,children:(0,n.jsx)(y,{})}),r.proxy&&(0,n.jsx)("div",{className:`absolute inset-0 flex flex-col box-border overflow-hidden transition-all duration-300 ease-in-out ${"proxy"===i?"opacity-100 translate-x-0":"opacity-0 translate-x-4 pointer-events-none"}`,children:(0,n.jsx)(k,{})})]})]})})},{}),(0,n.jsx)(()=>{let{state:e}=m(),t=e.messageList;return Array.isArray(t)&&t.length?(0,n.jsx)("div",{className:"fixed inset-0 flex flex-col items-center z-90 gap-2 py-2 box-border pointer-events-none",children:t.map(e=>{let t=j[e.type],r=v[e.type];return(0,n.jsxs)("div",{className:"shadow-md py-2 px-4 box-border rounded-lg bg-white text-xs flex items-center gap-2 flex-wrap",children:[t?(0,n.jsx)(t,{className:r}):(0,n.jsx)(n.Fragment,{}),(0,n.jsx)("div",{children:e.message})]},e.id)})}):(0,n.jsx)(n.Fragment,{})},{})]}))}},o={};function i(e){var t=o[e];if(void 0!==t)return t.exports;var r=o[e]={exports:{}};return s[e].call(r.exports,r,r.exports,i),r.exports}i.m=s,i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},e=[],i.O=(t,r,n,s)=>{if(r){s=s||0;for(var o=e.length;o>0&&e[o-1][2]>s;o--)e[o]=e[o-1];e[o]=[r,n,s];return}for(var a=1/0,o=0;o<e.length;o++){for(var[r,n,s]=e[o],l=!0,c=0;c<r.length;c++)(!1&s||a>=s)&&Object.keys(i.O).every(e=>i.O[e](r[c]))?r.splice(c--,1):(l=!1,s<a&&(a=s));if(l){e.splice(o--,1);var d=n();void 0!==d&&(t=d)}}return t},t={410:0},i.O.j=e=>0===t[e],r=(e,r)=>{var n,s,[o,a,l]=r,c=0;if(o.some(e=>0!==t[e])){for(n in a)i.o(a,n)&&(i.m[n]=a[n]);if(l)var d=l(i)}for(e&&e(r);c<o.length;c++)s=o[c],i.o(t,s)&&t[s]&&t[s][0](),t[s]=0;return i.O(d)},(n=self.webpackChunk_fairys_mocker_ui=self.webpackChunk_fairys_mocker_ui||[]).forEach(r.bind(null,0)),n.push=r.bind(null,n.push.bind(n));var a=i.O(void 0,["783","514"],()=>i(711));a=i.O(a)})();