Skip to content

Commit d761803

Browse files
authored
Merge pull request #3 from richLpf/feature/dev
Feature/dev
2 parents 3b39f75 + e35afd8 commit d761803

File tree

16 files changed

+487
-2582
lines changed

16 files changed

+487
-2582
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mock

.github/workflows/build.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Build and Push Multi-Arch Docker Images
2+
3+
on:
4+
push:
5+
branches:
6+
- feature/dev
7+
- main # 当代码推送到 main 分支时触发
8+
- dev # 或者 dev 分支
9+
10+
jobs:
11+
build:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
# 检出代码
16+
- name: Checkout code
17+
uses: actions/checkout@v3
18+
19+
# 设置 Docker Buildx
20+
- name: Set up Docker Buildx
21+
uses: docker/setup-buildx-action@v2
22+
23+
# 登录 Docker Hub
24+
- name: Log in to Docker Hub
25+
uses: docker/login-action@v2
26+
with:
27+
username: ${{ secrets.DOCKER_USERNAME }}
28+
password: ${{ secrets.DOCKER_PASSWORD }}
29+
30+
# 设置多平台环境
31+
- name: Set up QEMU for multi-platform builds
32+
uses: docker/setup-qemu-action@v2
33+
with:
34+
platforms: all
35+
36+
# 构建多平台镜像
37+
- name: Build and push Docker image
38+
uses: docker/build-push-action@v5
39+
with:
40+
context: .
41+
platforms: linux/amd64,linux/arm64
42+
push: true
43+
tags: |
44+
${{ secrets.DOCKER_USERNAME }}/dev-mock-cli:latest
45+
46+

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
node_modules
2-
mock
3-
mock.config.json
2+
mock

Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# 使用官方的 Node.js 18 镜像作为基础镜像
2+
FROM node:18-alpine
3+
4+
# 设置工作目录
5+
WORKDIR /app
6+
7+
# 将项目文件复制到工作目录中
8+
COPY . .
9+
10+
# 安装项目依赖
11+
RUN yarn install
12+
13+
# 暴露端口
14+
EXPOSE 9000
15+
16+
# 启动应用
17+
CMD ["yarn", "start"]

README.md

Lines changed: 37 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,52 @@
1-
## dev-mock-cli
2-
支持能力/价值:
3-
- Mock API
4-
- 读取Swagger API,并生成接口
5-
- 无需担心跨域问题
6-
- 安装和启动方便
1+
说明:前端的工作中,mock api是比较麻烦的事情,特别是API交付节点太晚导致前端项目延期背锅。所以构建了当前项目,用来配合前端项目快速生成mock API。
72

8-
待办:
9-
- [已完成]支持版本:node>=18
10-
- [已完成]发布启动的配置信息汇总,提示产品使用文档:CLI使用说明,配置说明mock.config.json,提示当前运行的action风格还是restful风格
11-
- [已完成]读取配置文件,全局使用处理,并确认默认文件的优先级:命令行 > 配置文件 > 默认配置
12-
- [已完成]如何remote api,网络不通,进行告警,并不再转发
13-
- TODO: restful: 读取swagger,生成json,处理中,晚上CLI的文档,用来测试
14-
- ACL文档的返回值
15-
- 上传npm的时候,指定文件
16-
- 生成单元测试
17-
- CLI使用文档
18-
- 录制演示视频
19-
- 优化打印日志,全部英文显示
20-
- 配置npm可以发布的文件
21-
- 支持自动生成mock.config.json
22-
- 同时只能支持一个风格,当风格切换时,检测到有mock文件夹,则提示清空
23-
- 当用户之前用restful风格,后面切换成了action后,在代码里面兼容,如果读取格式不对,就报错
24-
- TODO: .js默认加载
25-
- TODO: mock能力细节处理,支持不走本地的local json
3+
## 支持能力/价值:
264

27-
### 二、启动一个Mock-API服务
5+
1. Mock API
6+
1. 读取Swagger文档,并生成API接口
7+
1. 无需担心跨域问题
8+
1. 安装方便:node环境一行指令安装/Docker启动
9+
1. API生成读取顺序:本地mock -> swagger -> remote api
2810

29-
#### action 风格的api
11+
## 快速开始
3012

13+
要求node环境:node > 18,后续考虑降低成本
3114

32-
在mock文件新建`[Action].json`文件,Action为对应api的名字,如果请求地址路径有参数,可以创建多层
15+
1、安装dev-mock-cli
3316

34-
比如一个请求url: `http://localhost:9000/list`, Action: "List"的api,数据为
35-
36-
```json
37-
{
38-
"RetCode": 0,
39-
"Message": "",
40-
"Data": []
41-
}
42-
```
43-
44-
在mock下新建list文件夹,并写入`List.json`, 执行命令`u-admin-cli mock`, 然后就可以请求接口了
45-
46-
![mock](https://cdn.jsdelivr.net/gh/richLpf/pictures@main/gitbook/1650466393888data.png)
47-
48-
还可以改动文件,再次请求接口内容也会跟着变化
49-
50-
```bash
51-
u-admin-cli mock -n
52-
```
53-
54-
### 三、功能介绍
55-
56-
1、mock - 启动本地开发服务
57-
58-
| 参数 | 别名 | 类型 | 默认值 | 描述 |
59-
| ------ | ---- | ------ | -------------------- | ------------------------ |
60-
| create | c | true | 创建mock数据 |
61-
| PORT | P | number | 启动本地服务的端口号 |
62-
| type | t | string | action | api类型:action、restful |
63-
64-
2、dev - 启动本地开发服务
65-
66-
| 参数 | 别名 | 类型 | 默认值 | 描述 |
67-
| ------------------ | ---- | ------- | -------------------- | ------------------ |
68-
| projects | p | array | 启动的微应用名称 |
69-
| PORT | P | number | 启动本地服务的端口号 |
70-
| withoutOpenBrowser | wb | boolean | true | 取消自动打开浏览器 |
71-
| env | e | object | | 开发自定义环境变量 |
72-
73-
- 1、首先启动服务,获取启动项目的html代码
74-
- 2、挂载微服务的代码,子项目的port依次+1
75-
76-
### 四、发布版本
77-
78-
```bash
79-
# 登录 npm
80-
npm config set registry https://registry.npmjs.org/
81-
82-
npm login
8317
```
84-
85-
1、修改版本号,执行下面命令
86-
87-
```
88-
npm run publish:patch
18+
yarn add -D dev-mock-cli
8919
```
9020

91-
2、撤回 24 小时内发布的版本,撤回后 24 小时内不允许发布
92-
21+
2、在项目根目录下新建`mock.config.json`
9322
```
94-
npm unpublish dev-mock-cli@1.0.2
23+
{
24+
"port": "9000",
25+
"type": "action",
26+
"proxyApiUrl": "http://localhost:9000",
27+
"cors": {
28+
"allowedHeaders": ["Origin", "X-Requested-With", "Content-Type", "Accept", "X-Accesstoken"],
29+
"allowCredentials": true,
30+
"maxAge": 86400
31+
},
32+
"swaggerApi": [
33+
{
34+
"title": "swagger",
35+
"type": "action",
36+
"url": "http://subscri.xxx.com/swagger/doc.json"
37+
}
38+
],
39+
"mockFields": {
40+
"RetCode": {
41+
"fixedValue": 0
42+
}
43+
}
44+
}
9545
```
46+
配置说明:待补充
9647

97-
### 五、本地开发
48+
3、启动mock
9849

9950
```
100-
cd dev-mock-cli
101-
yarn install
102-
yarn start [command]
51+
yarn dev-mock-cli mock
10352
```

command/action.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import fs from 'fs';
22
import { createProxyMiddleware } from 'http-proxy-middleware';
33
import { ResponseExample } from './response.js';
44
import { getAllAction } from '../utils/index.js';
5-
import { generateApi, createAPIFile, fetchAndCreateRoutes } from './localAction.js';
6-
5+
import { generateApi, createAPIFile } from './localAction.js';
6+
import { fetchAndCreateRoutes } from './swaggerAction.js';
77

88
const action = async ({ app, filePath, config }) => {
99
// TODO: 配置信息需要统一处理,作为全局使用,type的每个优先级需要确认和逻辑开发
@@ -26,7 +26,7 @@ const action = async ({ app, filePath, config }) => {
2626

2727
// Step2: 获取swagger api json的数据,注册接口
2828
// 调用 fetchAndCreateRoutes 函数
29-
await fetchAndCreateRoutes({app, swaggerApi});
29+
await fetchAndCreateRoutes({app, swaggerApi, config});
3030

3131
// Step3: 获取代理配置并设置代理
3232
if (proxyApiUrl) {

command/localAction.js

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import path from 'path';
22
import fs from 'fs';
33
import Mock from 'mockjs';
4-
import axios from 'axios';
5-
import { createSwaggerMockData } from './swaggerAction.js'
4+
import { ResponseExample, NotFoundResponse } from './response.js';
5+
// import axios from 'axios';
6+
// import { createSwaggerMockData } from './swaggerAction.js'
67
export const createAPIFile = (dataJson, folderPath, fileName) => {
78
const apiFolderPath = path.resolve(folderPath); // 定义 API 目录的绝对路径
89
const filePath = path.resolve(apiFolderPath, fileName); // 定义 get.json 文件的绝对路径
@@ -41,55 +42,4 @@ export const generateApi = (app, filePath, actions) => {
4142
});
4243
});
4344
});
44-
}
45-
46-
// swagger生成路由
47-
export const createRoutes = ({ app, data }) => {
48-
const paths = data.paths || {}
49-
if(!paths){
50-
return
51-
}
52-
const keys = Object.keys(paths);
53-
const limit = Math.min(keys.length, 100); // 只生成前100个路由
54-
55-
for (let i = 0; i < limit; i++) {
56-
const pathKey = keys[i];
57-
const pathInfo = paths[pathKey];
58-
const lastSegment = `/${pathKey.split('/').pop()}`;
59-
60-
Object.keys(pathInfo).forEach(method => {
61-
app[method](lastSegment, async (req, res) => {
62-
const { Action } = req.body;
63-
if (Action) {
64-
// TODO: 这里指读取了$ref字段,如果没有关联需要处理下
65-
const responseSchema = pathInfo[method].responses['200'].schema['$ref'].split('/').pop();
66-
const response = data.definitions[responseSchema]
67-
const mockResponse = await createSwaggerMockData(data, response)
68-
return res.status(200).json(mockResponse);
69-
} else {
70-
return res.status(404).send(NotFoundResponse);
71-
}
72-
});
73-
});
74-
}
75-
};
76-
77-
// Step3: 获取swagger api json的数据,注册接口
78-
export const fetchAndCreateRoutes = async ({ app, swaggerApi }) => {
79-
const routePromises = swaggerApi.map(async (item) => {
80-
const { type, url } = item;
81-
if (type === 'action') {
82-
try {
83-
// TODO: 优化, 全局加载,方便后面读取直接使用
84-
const response = await axios.get(url);
85-
const data = response.data;
86-
createRoutes({ app, data });
87-
} catch (error) {
88-
console.error('Error fetching data from URL:', url, error);
89-
}
90-
}
91-
});
92-
93-
// 等待所有的请求完成
94-
await Promise.all(routePromises);
95-
};
45+
}

command/restful.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import { createProxyMiddleware } from 'http-proxy-middleware';
22
import { getAllAPIPath } from '../utils/index.js';
33
import { checkFileExist, checkFileExistsAndRespond } from './localRestful.js';
4+
import { fetchAndCreateRoutes } from './swaggerRestful.js';
5+
46

57
const restful = async ({ app, filePath, config }) => {
6-
const { proxyApiUrl } = config;
8+
const { proxyApiUrl, swaggerApi=[] } = config;
79
// 如果没有文件,新建example
810
checkFileExist(filePath, true)
9-
console.log(filePath)
1011
const apiList = getAllAPIPath(filePath);
1112
// 获取本地所有的path,生成本地代理
1213
app.all(apiList, async (req, res) => {
1314
const url = req.path;
1415
checkFileExistsAndRespond(url, filePath, req, res);
1516
});
17+
18+
await fetchAndCreateRoutes({app, swaggerApi});
19+
1620
// 没有本地mock,则读取远程接口
1721
if (proxyApiUrl) {
1822
const proxyMiddleware = createProxyMiddleware({

0 commit comments

Comments
 (0)