@fairys/mocker-cli 0.0.1
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 +36 -0
- package/bin/fairys-mocker +22 -0
- package/esm/base.d.ts +28 -0
- package/esm/base.js +80 -0
- package/esm/ci.d.ts +2 -0
- package/esm/ci.js +49 -0
- package/esm/connect.d.ts +15 -0
- package/esm/connect.js +38 -0
- package/esm/controller/base.d.ts +2 -0
- package/esm/controller/base.js +3 -0
- package/esm/controller/index.d.ts +3 -0
- package/esm/controller/index.js +3 -0
- package/esm/controller/mock.router.d.ts +21 -0
- package/esm/controller/mock.router.js +497 -0
- package/esm/controller/proxy.router.d.ts +18 -0
- package/esm/controller/proxy.router.js +503 -0
- package/esm/index.d.ts +5 -0
- package/esm/index.js +5 -0
- package/esm/main.d.ts +15 -0
- package/esm/main.js +38 -0
- package/esm/plugins/rsbuild.d.ts +2 -0
- package/esm/plugins/rsbuild.js +12 -0
- package/esm/router/base.d.ts +12 -0
- package/esm/router/base.js +23 -0
- package/esm/router/index.d.ts +3 -0
- package/esm/router/index.js +3 -0
- package/esm/router/mock.d.ts +7 -0
- package/esm/router/mock.js +32 -0
- package/esm/router/proxy.d.ts +14 -0
- package/esm/router/proxy.js +67 -0
- package/esm/utils/decorator.d.ts +18 -0
- package/esm/utils/decorator.js +55 -0
- package/esm/utils/index.d.ts +2 -0
- package/esm/utils/index.js +2 -0
- package/esm/utils/mcok.proxy.d.ts +36 -0
- package/esm/utils/mcok.proxy.js +141 -0
- package/esm/utils/utils.d.ts +20 -0
- package/esm/utils/utils.js +31 -0
- package/package.json +52 -0
- package/public/_fairys_mocker/favicon.png +0 -0
- package/public/_fairys_mocker/index.html +1 -0
- package/public/_fairys_mocker/static/css/index.2ba69ff5.css +1 -0
- package/public/_fairys_mocker/static/js/514.950758f1.js +2 -0
- package/public/_fairys_mocker/static/js/514.950758f1.js.LICENSE.txt +5 -0
- package/public/_fairys_mocker/static/js/index.f70ed1dc.js +1 -0
- package/public/_fairys_mocker/static/js/lib-react.2748fa4b.js +2 -0
- package/public/_fairys_mocker/static/js/lib-react.2748fa4b.js.LICENSE.txt +49 -0
- package/src/base.ts +125 -0
- package/src/ci.ts +61 -0
- package/src/connect.ts +62 -0
- package/src/controller/base.ts +4 -0
- package/src/controller/index.ts +3 -0
- package/src/controller/mock.router.ts +175 -0
- package/src/controller/proxy.router.ts +182 -0
- package/src/index.ts +5 -0
- package/src/main.ts +59 -0
- package/src/plugins/rsbuild.ts +14 -0
- package/src/router/base.ts +36 -0
- package/src/router/index.ts +3 -0
- package/src/router/mock.ts +38 -0
- package/src/router/proxy.ts +89 -0
- package/src/utils/decorator.ts +90 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/mcok.proxy.ts +162 -0
- package/src/utils/utils.ts +46 -0
package/src/base.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import connect from 'connect';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import cors from "cors"
|
|
6
|
+
import nodePath from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { MockRouterController } from "./controller/mock.router.js"
|
|
9
|
+
import { ClassStruct, registerRoutes } from "./utils/decorator.js"
|
|
10
|
+
import { ProxyRouterController } from "./controller/proxy.router.js"
|
|
11
|
+
import chalk from "chalk"
|
|
12
|
+
import http from "node:http";
|
|
13
|
+
|
|
14
|
+
// 转换成 __filename 和 __dirname
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = nodePath.dirname(__filename);
|
|
17
|
+
|
|
18
|
+
export class FairysMockerBase {
|
|
19
|
+
/**服务*/
|
|
20
|
+
server: http.Server | undefined = undefined
|
|
21
|
+
/**主路由*/
|
|
22
|
+
router: express.Router | undefined = undefined;
|
|
23
|
+
/**内置路由*/
|
|
24
|
+
fairysMockerRouter: express.Router | undefined = undefined;
|
|
25
|
+
/**子应用*/
|
|
26
|
+
app: express.Express | undefined = undefined;
|
|
27
|
+
/**主应用*/
|
|
28
|
+
mainApp: express.Express | connect.Server | undefined = undefined;
|
|
29
|
+
/**类*/
|
|
30
|
+
controller: ClassStruct[] = [MockRouterController, ProxyRouterController];
|
|
31
|
+
|
|
32
|
+
/**静态文件服务列表*/
|
|
33
|
+
staticServerList: string[] = [];
|
|
34
|
+
|
|
35
|
+
/**静态文件服务*/
|
|
36
|
+
staticServer = (dir: string, prefix: string = '/', isRegister: boolean = true) => {
|
|
37
|
+
if (!this.app) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (fs.existsSync(dir)) {
|
|
41
|
+
const _prefix = /^\/$/.test(prefix) ? prefix : `/${prefix}`;
|
|
42
|
+
this.app.use(_prefix, express.static(dir));
|
|
43
|
+
// console.log(chalk.green(`静态文件服务:${dir}`))
|
|
44
|
+
if (isRegister) {
|
|
45
|
+
this.staticServerList.push(_prefix)
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
console.log(chalk.red(`${dir} 目录不存在`))
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**初始化 app 服务*/
|
|
53
|
+
initApp = (app: express.Express | connect.Server, cb?: () => void): express.Express | connect.Server => {
|
|
54
|
+
if (!this.app) {
|
|
55
|
+
console.log('')
|
|
56
|
+
console.log(chalk.hex('#54FF9F')('===fairys-mocker================='))
|
|
57
|
+
console.log('')
|
|
58
|
+
|
|
59
|
+
this.mainApp = app
|
|
60
|
+
this.app = express();
|
|
61
|
+
// 挂子应用
|
|
62
|
+
this.mainApp.use(this.app)
|
|
63
|
+
|
|
64
|
+
this.app.use(express.json());
|
|
65
|
+
this.app.use(cors());
|
|
66
|
+
/**注册主路由*/
|
|
67
|
+
this.router = express.Router();
|
|
68
|
+
/**注册内置路由*/
|
|
69
|
+
this.fairysMockerRouter = express.Router();
|
|
70
|
+
this.router.use(this.fairysMockerRouter);
|
|
71
|
+
|
|
72
|
+
// 静态文件服务
|
|
73
|
+
const staticDir = nodePath.join(__dirname, '../public/_fairys_mocker');
|
|
74
|
+
this.staticServer(staticDir, '/_fairys_mocker', false);
|
|
75
|
+
|
|
76
|
+
for (let index = 0; index < this.controller.length; index++) {
|
|
77
|
+
const Controller = this.controller[index];
|
|
78
|
+
const newController = new Controller();
|
|
79
|
+
registerRoutes(newController)
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
const start = newController?.start;
|
|
82
|
+
if (typeof start === 'function') {
|
|
83
|
+
start()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
this.app.use('/', this.router);
|
|
87
|
+
|
|
88
|
+
cb?.()
|
|
89
|
+
|
|
90
|
+
console.log('')
|
|
91
|
+
|
|
92
|
+
} else {
|
|
93
|
+
console.log('挂载 主应用 服务')
|
|
94
|
+
this.mainApp = app
|
|
95
|
+
this.mainApp.use(this.app)
|
|
96
|
+
}
|
|
97
|
+
return app;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**启动日志打印服务器地址*/
|
|
101
|
+
logServer = async (port: number) => {
|
|
102
|
+
if (!this.app) {
|
|
103
|
+
console.log(chalk.red('请先初始化 app'));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
console.log("")
|
|
107
|
+
console.log(chalk.green(`\tfairys-mocker API地址: http://localhost:${port}`));
|
|
108
|
+
console.log(chalk.green(`\tfairys-mocker UI地址: http://localhost:${port}/_fairys_mocker`));
|
|
109
|
+
console.log("")
|
|
110
|
+
for (let index = 0; index < this.staticServerList.length; index++) {
|
|
111
|
+
const element = this.staticServerList[index];
|
|
112
|
+
console.log(chalk.green(`\tfairys-mocker 静态服务 ${chalk.yellow(element)} 地址: http://localhost:${port}${element}`));
|
|
113
|
+
}
|
|
114
|
+
console.log("")
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
close = () => {
|
|
118
|
+
if (this.server) {
|
|
119
|
+
this.server.close();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const fairysMockerBase = new FairysMockerBase();
|
|
125
|
+
|
package/src/ci.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import parser, { Arguments } from 'yargs-parser'
|
|
2
|
+
import { fairysMockerExpress } from "./main.js"
|
|
3
|
+
import { fairysMockerConnect } from "./connect.js"
|
|
4
|
+
import { utils } from "./utils/utils.js"
|
|
5
|
+
|
|
6
|
+
function help() {
|
|
7
|
+
console.log('\n Usage: \x1b[34;1fairys-mocker\x1b[0m [--help|h|--root|--dir|--file|--file2|--static|--static-prefix]');
|
|
8
|
+
console.log('\n Displays help information.');
|
|
9
|
+
console.log('\n Options:\n');
|
|
10
|
+
console.log(' --root ', '设置根目录路径(默认取环境变量中的`FAIRYS_MOCKER_ROOT_DIR`).');
|
|
11
|
+
console.log(' --dir ', '设置目录名(默认取环境变量中的`FAIRYS_MOCKER_DIR`).');
|
|
12
|
+
console.log(' --file ', '设置文件名(默认取环境变量中的`FAIRYS_MOCKER_FILE`).');
|
|
13
|
+
console.log(' --file2 ', '设置文件名2(默认取环境变量中的`FAIRYS_MOCKER_PROXY_FILE`).');
|
|
14
|
+
console.log(' --static ', '设置静态文件服务目录.');
|
|
15
|
+
console.log(' --static-prefix ', '设置静态文件服务目录访问前缀.');
|
|
16
|
+
|
|
17
|
+
console.log('\n Example:\n');
|
|
18
|
+
console.log(' $ \x1b[35mfairys-mocker\x1b[0m --dir mock2');
|
|
19
|
+
console.log(' $ \x1b[35mfairys-mocker\x1b[0m --file index.mock');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const argv: Partial<Arguments> = parser(process.argv.slice(2), {
|
|
23
|
+
string: ["root", 'dir', 'file', 'file2', 'static', 'static-prefix'],
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export const runExpressCli = () => {
|
|
27
|
+
if (argv.help | argv.h) {
|
|
28
|
+
help();
|
|
29
|
+
return;
|
|
30
|
+
} else {
|
|
31
|
+
utils.setRootDir(argv.root);
|
|
32
|
+
utils.setDir(argv.dir);
|
|
33
|
+
utils.setFile(argv.file);
|
|
34
|
+
utils.setProxyFile(argv.file2);
|
|
35
|
+
// 1. 直接当 mock 服务,
|
|
36
|
+
// 2. 生成 mock 数据
|
|
37
|
+
// 3. mock 服务 + 数据
|
|
38
|
+
fairysMockerExpress.start(() => {
|
|
39
|
+
if (argv.static) {
|
|
40
|
+
fairysMockerExpress.staticServer(argv.static, argv['static-prefix']);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const runConnectCli = () => {
|
|
47
|
+
if (argv.help) {
|
|
48
|
+
help();
|
|
49
|
+
return;
|
|
50
|
+
} else {
|
|
51
|
+
utils.setRootDir(argv.root);
|
|
52
|
+
utils.setDir(argv.dir);
|
|
53
|
+
utils.setFile(argv.file);
|
|
54
|
+
utils.setProxyFile(argv.file2);
|
|
55
|
+
fairysMockerConnect.start(() => {
|
|
56
|
+
if (argv.static) {
|
|
57
|
+
fairysMockerConnect.staticServer(argv.static, argv['static-prefix']);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
package/src/connect.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
import connect from 'connect';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { fairysMockerBase } from './base.js';
|
|
5
|
+
import { detect } from 'detect-port';
|
|
6
|
+
|
|
7
|
+
export class FairysMockerConnect {
|
|
8
|
+
base = fairysMockerBase;
|
|
9
|
+
/**创建 app*/
|
|
10
|
+
createApp = (cb?: () => void) => {
|
|
11
|
+
return fairysMockerBase.initApp(connect(), cb)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 使用 connect
|
|
15
|
+
/**检测端口,返回实际端口*/
|
|
16
|
+
detectPort = (port?: number) => {
|
|
17
|
+
/**启动服务器*/
|
|
18
|
+
const PORT = port || process.env.PORT || 6901;
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
detect(PORT)
|
|
21
|
+
.then(realPort => {
|
|
22
|
+
resolve(realPort);
|
|
23
|
+
})
|
|
24
|
+
.catch(err => {
|
|
25
|
+
reject(err);
|
|
26
|
+
});
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**启动服务器*/
|
|
31
|
+
listen = async (port?: number, callback?: (error?: Error) => void) => {
|
|
32
|
+
if (!fairysMockerBase.mainApp) {
|
|
33
|
+
console.log(chalk.red('请先初始化 app'));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const app = fairysMockerBase.mainApp
|
|
37
|
+
const realPort = await this.detectPort(port);
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
fairysMockerBase.server = app.listen(realPort, (...rest: any) => {
|
|
40
|
+
fairysMockerBase.logServer(realPort as number);
|
|
41
|
+
callback?.(...rest);
|
|
42
|
+
});
|
|
43
|
+
return fairysMockerBase.server
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
staticServer = fairysMockerBase.staticServer;
|
|
47
|
+
|
|
48
|
+
/**启动 app*/
|
|
49
|
+
start = (cb?: () => void) => {
|
|
50
|
+
this.createApp(cb);
|
|
51
|
+
this.listen();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
close = () => {
|
|
55
|
+
if (fairysMockerBase.server) {
|
|
56
|
+
fairysMockerBase.server.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const fairysMockerConnect = new FairysMockerConnect();
|
|
62
|
+
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { Get, Post, Controller } from "../utils/decorator.js"
|
|
4
|
+
import { utils } from "../utils/index.js"
|
|
5
|
+
import { MockRouter } from "../router/mock.js"
|
|
6
|
+
import { BaseController } from "./base.js"
|
|
7
|
+
import { getMcokFile, createMockFile } from '../utils/mcok.proxy.js';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
|
|
10
|
+
/**路由*/
|
|
11
|
+
@Controller('/_fairys')
|
|
12
|
+
export class MockRouterController extends BaseController {
|
|
13
|
+
/**mock 路由器实例*/
|
|
14
|
+
router: MockRouter | null = null;
|
|
15
|
+
constructor() {
|
|
16
|
+
super();
|
|
17
|
+
this.router = new MockRouter();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**保存 Mock 配置*/
|
|
21
|
+
@Post('/_mock')
|
|
22
|
+
post_mock(req: express.Request, res: express.Response) {
|
|
23
|
+
// 定义接口
|
|
24
|
+
try {
|
|
25
|
+
const { mockList, dir, fileName = 'index.mock', rootDir } = req.body;
|
|
26
|
+
let _rootDir = rootDir || utils.rootDir;
|
|
27
|
+
if (rootDir && !fs.existsSync(rootDir)) {
|
|
28
|
+
_rootDir = utils.rootDir;
|
|
29
|
+
}
|
|
30
|
+
const mockData = createMockFile(mockList, _rootDir, dir, fileName)
|
|
31
|
+
if (mockData?.mockConfig) {
|
|
32
|
+
if (this.router?.isEnabled) {
|
|
33
|
+
this.router?.load(mockData.mockConfig);
|
|
34
|
+
}
|
|
35
|
+
res.json({
|
|
36
|
+
code: 200,
|
|
37
|
+
message: 'Mock 配置保存成功',
|
|
38
|
+
data: mockData.mockConfig,
|
|
39
|
+
mockList: mockList,
|
|
40
|
+
rootDir: mockData.rootDir,
|
|
41
|
+
dir: mockData.dir,
|
|
42
|
+
cache: mockData.cache,
|
|
43
|
+
fileName: mockData.fileName,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
} catch (error: any) {
|
|
48
|
+
res.status(500).json({
|
|
49
|
+
code: 500,
|
|
50
|
+
message: '保存 Mock 配置失败',
|
|
51
|
+
error: error.message
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**读取 Mock 配置*/
|
|
57
|
+
@Get('/_mock')
|
|
58
|
+
get_mock(req: express.Request, res: express.Response) {
|
|
59
|
+
try {
|
|
60
|
+
const savePath = (req.query?.dir as string)?.trim()
|
|
61
|
+
const saveFileName = (req.query?.fileName as string)?.trim()
|
|
62
|
+
const rootDir = (req.query?.rootDir as string)?.trim()
|
|
63
|
+
const mockData = getMcokFile(rootDir, savePath, saveFileName);
|
|
64
|
+
if (mockData?.mockList) {
|
|
65
|
+
res.json({
|
|
66
|
+
code: 200,
|
|
67
|
+
message: '读取 Mock 配置成功',
|
|
68
|
+
data: mockData.mockList,
|
|
69
|
+
rootDir: mockData.rootDir,
|
|
70
|
+
dir: mockData.dir,
|
|
71
|
+
cache: mockData.cache,
|
|
72
|
+
fileName: mockData.fileName,
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
res.json({
|
|
76
|
+
code: 404,
|
|
77
|
+
message: 'Mock 配置文件不存在',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
} catch (error: any) {
|
|
81
|
+
res.status(500).json({
|
|
82
|
+
code: 500,
|
|
83
|
+
message: '读取 Mock 配置失败',
|
|
84
|
+
error: error.message
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**检查 Mock 配置服务是否启用*/
|
|
90
|
+
@Get('/_mock/_is_enabled')
|
|
91
|
+
get_mock_enabled(req: express.Request, res: express.Response) {
|
|
92
|
+
res.json({
|
|
93
|
+
code: 200,
|
|
94
|
+
message: 'Mock 配置服务是否启用',
|
|
95
|
+
data: this.router?.isEnabled,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**启动 Mock 配置服务*/
|
|
100
|
+
@Get('/_mock/_start')
|
|
101
|
+
get_mock_start(req: express.Request, res: express.Response) {
|
|
102
|
+
try {
|
|
103
|
+
const mockData = getMcokFile(req.query.rootDir as string, req.query.dir as string, req.query.fileName as string);
|
|
104
|
+
if (mockData?.mockList) {
|
|
105
|
+
this.router?.load(mockData.mockList);
|
|
106
|
+
res.json({
|
|
107
|
+
code: 200,
|
|
108
|
+
message: '启动 Mock 配置服务成功',
|
|
109
|
+
data: mockData.mockList,
|
|
110
|
+
rootDir: mockData.rootDir,
|
|
111
|
+
dir: mockData.dir,
|
|
112
|
+
cache: mockData.cache,
|
|
113
|
+
fileName: mockData.fileName,
|
|
114
|
+
isEnabled: true,
|
|
115
|
+
});
|
|
116
|
+
} else {
|
|
117
|
+
res.json({
|
|
118
|
+
code: 404,
|
|
119
|
+
message: 'Mock 配置文件不存在',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
} catch (error: any) {
|
|
123
|
+
res.status(500).json({
|
|
124
|
+
code: 500,
|
|
125
|
+
message: '启动 Mock 配置失败',
|
|
126
|
+
error: error.message
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**销毁 Mock 配置服务*/
|
|
132
|
+
@Get('/_mock/_destroy')
|
|
133
|
+
get_mock_destroy(req: express.Request, res: express.Response) {
|
|
134
|
+
try {
|
|
135
|
+
if (this.router?.router) {
|
|
136
|
+
this.router?.destroy("销毁mock路由器实例");
|
|
137
|
+
} else {
|
|
138
|
+
res.json({
|
|
139
|
+
code: 404,
|
|
140
|
+
message: 'Mock 配置服务不存在',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
res.json({
|
|
144
|
+
code: 200,
|
|
145
|
+
message: '销毁 Mock 配置服务成功',
|
|
146
|
+
});
|
|
147
|
+
} catch (error: any) {
|
|
148
|
+
res.status(500).json({
|
|
149
|
+
code: 500,
|
|
150
|
+
message: '销毁 Mock 配置服务',
|
|
151
|
+
error: error.message
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**启动 Mock 配置服务*/
|
|
157
|
+
start = (rootDir?: string, dir?: string, fileName?: string) => {
|
|
158
|
+
try {
|
|
159
|
+
const mockData = getMcokFile(rootDir, dir, fileName);
|
|
160
|
+
if (mockData?.mockList) {
|
|
161
|
+
try {
|
|
162
|
+
this.router?.load(mockData.mockList);
|
|
163
|
+
console.log(chalk.green(` 启动 Mock 配置服务成功,配置文件:${mockData.rootDir}/${mockData.dir}/${mockData.fileName}.ts`))
|
|
164
|
+
console.log('')
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.log(chalk.red(` 启动 Mock 配置服务失败,配置文件:${mockData.rootDir}/${mockData.dir}/${mockData.fileName}.ts`))
|
|
167
|
+
console.log('')
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.log(chalk.red(` 启动 Mock 配置服务失败`))
|
|
172
|
+
console.log('')
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import nodePath from "node:path"
|
|
4
|
+
import { createProxyData } from '@fairys/create-mock-data';
|
|
5
|
+
import { Get, Post, Controller } from "../utils/decorator.js"
|
|
6
|
+
import { utils } from "../utils/index.js"
|
|
7
|
+
import { ProxyRouter } from '../router/proxy.js';
|
|
8
|
+
import { BaseController } from './base.js';
|
|
9
|
+
import { getProxyFile, createProxyFile } from '../utils/mcok.proxy.js';
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
|
|
12
|
+
/**路由*/
|
|
13
|
+
@Controller('/_fairys')
|
|
14
|
+
export class ProxyRouterController extends BaseController {
|
|
15
|
+
/**代理 路由器实例*/
|
|
16
|
+
router: ProxyRouter | null = null;
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
this.router = new ProxyRouter();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Post('/_proxy')
|
|
24
|
+
post_proxy(req: express.Request, res: express.Response) {
|
|
25
|
+
try {
|
|
26
|
+
const { proxyList, dir, fileName = 'proxy', rootDir } = req.body;
|
|
27
|
+
let _rootDir = rootDir || utils.rootDir;
|
|
28
|
+
if (rootDir && !fs.existsSync(rootDir)) {
|
|
29
|
+
_rootDir = utils.rootDir;
|
|
30
|
+
}
|
|
31
|
+
const proxyData = createProxyFile(proxyList, _rootDir, dir, fileName)
|
|
32
|
+
if (proxyData?.proxyConfig) {
|
|
33
|
+
if (this.router?.isEnabled) {
|
|
34
|
+
this.router?.load(proxyList);
|
|
35
|
+
}
|
|
36
|
+
res.json({
|
|
37
|
+
code: 200,
|
|
38
|
+
message: '代理配置保存成功',
|
|
39
|
+
data: proxyData.proxyConfig,
|
|
40
|
+
proxyList: proxyList,
|
|
41
|
+
rootDir: proxyData.rootDir,
|
|
42
|
+
dir: proxyData.dir,
|
|
43
|
+
cache: proxyData.cache,
|
|
44
|
+
fileName: proxyData.fileName,
|
|
45
|
+
});
|
|
46
|
+
} else {
|
|
47
|
+
res.json({
|
|
48
|
+
code: 404,
|
|
49
|
+
message: '生成配置文件错误',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
} catch (error: any) {
|
|
53
|
+
res.status(500).json({
|
|
54
|
+
code: 500,
|
|
55
|
+
message: '保存代理配置失败',
|
|
56
|
+
error: error.message
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Get('/_proxy')
|
|
62
|
+
get_proxy(req: express.Request, res: express.Response) {
|
|
63
|
+
try {
|
|
64
|
+
const savePath = (req.query.dir as string)?.trim()
|
|
65
|
+
const saveFileName = (req.query.fileName as string)?.trim()
|
|
66
|
+
const rootDir = (req.query.rootDir as string)?.trim()
|
|
67
|
+
const proxyData = getProxyFile(rootDir, savePath, saveFileName);
|
|
68
|
+
if (proxyData?.proxyList) {
|
|
69
|
+
res.json({
|
|
70
|
+
code: 200,
|
|
71
|
+
message: '读取代理配置成功',
|
|
72
|
+
data: proxyData.proxyList,
|
|
73
|
+
rootDir: proxyData.rootDir,
|
|
74
|
+
dir: proxyData.dir,
|
|
75
|
+
cache: proxyData.cache,
|
|
76
|
+
fileName: proxyData.fileName,
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
res.json({
|
|
80
|
+
code: 404,
|
|
81
|
+
message: '代理配置文件不存在',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
} catch (error: any) {
|
|
85
|
+
res.status(500).json({
|
|
86
|
+
code: 500,
|
|
87
|
+
message: '读取代理配置失败',
|
|
88
|
+
error: error.message
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**检查代理服务是否启用*/
|
|
94
|
+
@Get('/_proxy/_is_enabled')
|
|
95
|
+
get_proxy_enabled(req: express.Request, res: express.Response) {
|
|
96
|
+
res.json({
|
|
97
|
+
code: 200,
|
|
98
|
+
message: '代理服务是否启用',
|
|
99
|
+
data: this.router?.isEnabled,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**启动代理服务*/
|
|
104
|
+
@Get('/_proxy/_start')
|
|
105
|
+
get_proxy_start(req: express.Request, res: express.Response) {
|
|
106
|
+
try {
|
|
107
|
+
const savePath = (req.query.dir as string)?.trim()
|
|
108
|
+
const saveFileName = (req.query.fileName as string)?.trim();
|
|
109
|
+
const rootDir = (req.query.rootDir as string)?.trim()
|
|
110
|
+
const proxyData = getProxyFile(rootDir, savePath, saveFileName);
|
|
111
|
+
if (proxyData?.proxyList) {
|
|
112
|
+
this.router?.load(proxyData.proxyList);
|
|
113
|
+
res.json({
|
|
114
|
+
code: 200,
|
|
115
|
+
message: '启动代理服务成功',
|
|
116
|
+
data: proxyData.proxyList,
|
|
117
|
+
rootDir: rootDir,
|
|
118
|
+
dir: proxyData.dir,
|
|
119
|
+
cache: proxyData.cache,
|
|
120
|
+
fileName: proxyData.fileName,
|
|
121
|
+
isEnabled: true,
|
|
122
|
+
});
|
|
123
|
+
} else {
|
|
124
|
+
res.json({
|
|
125
|
+
code: 404,
|
|
126
|
+
message: '代理配置文件不存在',
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
} catch (error: any) {
|
|
130
|
+
res.status(500).json({
|
|
131
|
+
code: 500,
|
|
132
|
+
message: '启动代理配置失败',
|
|
133
|
+
error: error.message
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**销毁代理服务*/
|
|
139
|
+
@Get('/_proxy/_destroy')
|
|
140
|
+
get_proxy_destroy(req: express.Request, res: express.Response) {
|
|
141
|
+
try {
|
|
142
|
+
if (this.router?.router) {
|
|
143
|
+
this.router?.destroy("销毁proxy路由器实例");
|
|
144
|
+
} else {
|
|
145
|
+
res.json({
|
|
146
|
+
code: 404,
|
|
147
|
+
message: '代理服务不存在',
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
res.json({
|
|
151
|
+
code: 200,
|
|
152
|
+
message: '销毁代理服务成功',
|
|
153
|
+
});
|
|
154
|
+
} catch (error: any) {
|
|
155
|
+
res.status(500).json({
|
|
156
|
+
code: 500,
|
|
157
|
+
message: '销毁代理服务失败',
|
|
158
|
+
error: error.message
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
start = (rootDir?: string, dir?: string, fileName?: string) => {
|
|
164
|
+
try {
|
|
165
|
+
const proxyData = getProxyFile(rootDir, dir, fileName);
|
|
166
|
+
if (proxyData?.proxyList) {
|
|
167
|
+
try {
|
|
168
|
+
this.router?.load(proxyData.proxyList);
|
|
169
|
+
console.log(chalk.green(` 启动代理服务成功,配置文件:${proxyData.rootDir}/${proxyData.dir}/${proxyData.fileName}.ts`))
|
|
170
|
+
console.log('')
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.log(chalk.red(` 启动代理服务失败,配置文件:${proxyData.rootDir}/${proxyData.dir}/${proxyData.fileName}.ts`))
|
|
173
|
+
console.log('')
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.log(chalk.red(` 启动代理服务失败`))
|
|
178
|
+
console.log('')
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
}
|
package/src/index.ts
ADDED
package/src/main.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { fairysMockerBase } from './base.js';
|
|
5
|
+
import { detect } from 'detect-port';
|
|
6
|
+
|
|
7
|
+
export class FairysMockerExpress {
|
|
8
|
+
base = fairysMockerBase;
|
|
9
|
+
/**创建 app*/
|
|
10
|
+
createApp = (cb?: () => void) => {
|
|
11
|
+
return fairysMockerBase.initApp(express(), cb)
|
|
12
|
+
}
|
|
13
|
+
// 使用express
|
|
14
|
+
/**检测端口,返回实际端口*/
|
|
15
|
+
detectPort = (port?: number) => {
|
|
16
|
+
/**启动服务器*/
|
|
17
|
+
const PORT = port || process.env.PORT || 6901;
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
detect(PORT)
|
|
20
|
+
.then(realPort => {
|
|
21
|
+
resolve(realPort);
|
|
22
|
+
})
|
|
23
|
+
.catch(err => {
|
|
24
|
+
reject(err);
|
|
25
|
+
});
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**启动服务器*/
|
|
30
|
+
listen = async (port?: number, callback?: (error?: Error) => void) => {
|
|
31
|
+
if (!fairysMockerBase.app) {
|
|
32
|
+
console.log(chalk.red('请先初始化 app'));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const app = fairysMockerBase.mainApp
|
|
36
|
+
const realPort = await this.detectPort(port);
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
fairysMockerBase.server = app.listen(realPort, (...rest) => {
|
|
39
|
+
fairysMockerBase.logServer(realPort as number);
|
|
40
|
+
callback?.(...rest);
|
|
41
|
+
});
|
|
42
|
+
return fairysMockerBase.server
|
|
43
|
+
}
|
|
44
|
+
staticServer = fairysMockerBase.staticServer;
|
|
45
|
+
/**启动 app*/
|
|
46
|
+
start = (cb?: () => void) => {
|
|
47
|
+
this.createApp(cb);
|
|
48
|
+
this.listen();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
close = () => {
|
|
52
|
+
if (fairysMockerBase.server) {
|
|
53
|
+
fairysMockerBase.server.close();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const fairysMockerExpress = new FairysMockerExpress();
|
|
59
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RsbuildPlugin } from '@rsbuild/core';
|
|
2
|
+
import { fairysMockerBase } from '../base.js';
|
|
3
|
+
|
|
4
|
+
export const fairysMockerRsbuildPlugin = () => ({
|
|
5
|
+
setup(api) {
|
|
6
|
+
api.onBeforeStartDevServer(({ server }) => {
|
|
7
|
+
fairysMockerBase.initApp(server.middlewares, () => {
|
|
8
|
+
fairysMockerBase.logServer(server.port);
|
|
9
|
+
});
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
fairysMockerBase.server = server.httpServer
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
} as RsbuildPlugin);
|