json-api-mocker 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.ch.md +216 -0
- package/README.md +216 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +43 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.js +155 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.js +2 -0
- package/package.json +57 -0
package/README.ch.md
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
# JSON Mock Server
|
2
|
+
|
3
|
+
一个轻量级且灵活的 Mock 服务器,通过 JSON 配置快速创建 RESTful API。
|
4
|
+
|
5
|
+
<p align="center">
|
6
|
+
<img src="https://img.shields.io/npm/v/json-mock-server" alt="npm 版本" />
|
7
|
+
<img src="https://img.shields.io/npm/l/json-mock-server" alt="许可证" />
|
8
|
+
<img src="https://img.shields.io/npm/dt/json-mock-server" alt="下载量" />
|
9
|
+
</p>
|
10
|
+
|
11
|
+
## ✨ 特性
|
12
|
+
|
13
|
+
- 🚀 通过 JSON 配置快速搭建
|
14
|
+
- 🔄 支持 GET、POST、PUT、DELETE 方法
|
15
|
+
- 📝 自动数据持久化
|
16
|
+
- 🔍 内置分页支持
|
17
|
+
- 🛠 可自定义响应结构
|
18
|
+
- 💡 TypeScript 支持
|
19
|
+
|
20
|
+
## 📦 安装
|
21
|
+
|
22
|
+
```bash
|
23
|
+
# 使用 npm
|
24
|
+
npm install json-mock-server
|
25
|
+
|
26
|
+
# 使用 yarn
|
27
|
+
yarn add json-mock-server
|
28
|
+
|
29
|
+
# 使用 pnpm
|
30
|
+
pnpm add json-mock-server
|
31
|
+
```
|
32
|
+
|
33
|
+
## 🚀 快速开始
|
34
|
+
|
35
|
+
### 1. 创建配置文件
|
36
|
+
|
37
|
+
在项目根目录创建 `data.json` 文件:
|
38
|
+
|
39
|
+
```json
|
40
|
+
{
|
41
|
+
"server": {
|
42
|
+
"port": 8080,
|
43
|
+
"baseProxy": "/api"
|
44
|
+
},
|
45
|
+
"routes": [
|
46
|
+
{
|
47
|
+
"path": "/users",
|
48
|
+
"methods": {
|
49
|
+
"get": {
|
50
|
+
"type": "array",
|
51
|
+
"pagination": {
|
52
|
+
"enabled": true,
|
53
|
+
"pageSize": 10,
|
54
|
+
"totalCount": 100
|
55
|
+
},
|
56
|
+
"response": [
|
57
|
+
{
|
58
|
+
"id": 1,
|
59
|
+
"name": "张三",
|
60
|
+
"age": 30,
|
61
|
+
"city": "北京"
|
62
|
+
}
|
63
|
+
]
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
]
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
### 2. 启动服务器
|
72
|
+
|
73
|
+
```bash
|
74
|
+
npx json-mock-server
|
75
|
+
```
|
76
|
+
|
77
|
+
现在你的 Mock 服务器已经在 `http://localhost:8080` 运行了!
|
78
|
+
|
79
|
+
## 📖 配置指南
|
80
|
+
|
81
|
+
### 服务器配置
|
82
|
+
|
83
|
+
`server` 部分配置基本的服务器设置:
|
84
|
+
|
85
|
+
```json
|
86
|
+
{
|
87
|
+
"server": {
|
88
|
+
"port": 8080, // 服务器端口号
|
89
|
+
"baseProxy": "/api" // 所有路由的基础路径
|
90
|
+
}
|
91
|
+
}
|
92
|
+
```
|
93
|
+
|
94
|
+
### 路由配置
|
95
|
+
|
96
|
+
每个路由可以支持多个 HTTP 方法:
|
97
|
+
|
98
|
+
```json
|
99
|
+
{
|
100
|
+
"path": "/users", // 路由路径
|
101
|
+
"methods": {
|
102
|
+
"get": {
|
103
|
+
"type": "array", // 响应类型:array 或 object
|
104
|
+
"pagination": { // 可选的分页设置
|
105
|
+
"enabled": true,
|
106
|
+
"pageSize": 10,
|
107
|
+
"totalCount": 100
|
108
|
+
},
|
109
|
+
"response": [] // 响应数据
|
110
|
+
},
|
111
|
+
"post": {
|
112
|
+
"requestSchema": { // 请求体验证模式
|
113
|
+
"name": "string",
|
114
|
+
"age": "number"
|
115
|
+
},
|
116
|
+
"response": {
|
117
|
+
"success": true
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
```
|
123
|
+
|
124
|
+
## 🎯 API 示例
|
125
|
+
|
126
|
+
### 基本的 CRUD 操作
|
127
|
+
|
128
|
+
#### 获取用户列表
|
129
|
+
```bash
|
130
|
+
curl http://localhost:8080/api/users
|
131
|
+
```
|
132
|
+
|
133
|
+
#### 获取单个用户
|
134
|
+
```bash
|
135
|
+
curl http://localhost:8080/api/users/1
|
136
|
+
```
|
137
|
+
|
138
|
+
#### 创建用户
|
139
|
+
```bash
|
140
|
+
curl -X POST http://localhost:8080/api/users \
|
141
|
+
-H "Content-Type: application/json" \
|
142
|
+
-d '{"name":"李四","age":25,"city":"上海"}'
|
143
|
+
```
|
144
|
+
|
145
|
+
#### 更新用户
|
146
|
+
```bash
|
147
|
+
curl -X PUT http://localhost:8080/api/users/1 \
|
148
|
+
-H "Content-Type: application/json" \
|
149
|
+
-d '{"name":"李四","age":26,"city":"上海"}'
|
150
|
+
```
|
151
|
+
|
152
|
+
#### 删除用户
|
153
|
+
```bash
|
154
|
+
curl -X DELETE http://localhost:8080/api/users/1
|
155
|
+
```
|
156
|
+
|
157
|
+
### 高级用法
|
158
|
+
|
159
|
+
#### 分页
|
160
|
+
```bash
|
161
|
+
# 获取第2页,每页10条数据
|
162
|
+
curl http://localhost:8080/api/users?page=2&pageSize=10
|
163
|
+
```
|
164
|
+
|
165
|
+
#### 自定义响应头
|
166
|
+
服务器自动添加以下响应头:
|
167
|
+
- `X-Total-Count`:数据总条数(用于分页响应)
|
168
|
+
|
169
|
+
## 🔧 高级配置
|
170
|
+
|
171
|
+
### 动态路由
|
172
|
+
|
173
|
+
你可以在路由中使用 URL 参数:
|
174
|
+
|
175
|
+
```json
|
176
|
+
{
|
177
|
+
"path": "/users/:id/posts",
|
178
|
+
"methods": {
|
179
|
+
"get": {
|
180
|
+
"type": "array",
|
181
|
+
"response": []
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
```
|
186
|
+
|
187
|
+
### 请求验证
|
188
|
+
|
189
|
+
为 POST/PUT 请求添加模式验证:
|
190
|
+
|
191
|
+
```json
|
192
|
+
{
|
193
|
+
"requestSchema": {
|
194
|
+
"name": "string",
|
195
|
+
"age": "number",
|
196
|
+
"email": "string"
|
197
|
+
}
|
198
|
+
}
|
199
|
+
```
|
200
|
+
|
201
|
+
## 🤝 贡献指南
|
202
|
+
|
203
|
+
1. Fork 本仓库
|
204
|
+
2. 创建你的特性分支 (`git checkout -b feature/amazing-feature`)
|
205
|
+
3. 提交你的改动 (`git commit -m '添加一些很棒的特性'`)
|
206
|
+
4. 推送到分支 (`git push origin feature/amazing-feature`)
|
207
|
+
5. 开启一个 Pull Request
|
208
|
+
|
209
|
+
## 📄 许可证
|
210
|
+
|
211
|
+
MIT © [熊海印]
|
212
|
+
|
213
|
+
## 🙏 致谢
|
214
|
+
|
215
|
+
- 感谢 Express.js 提供出色的 Web 框架
|
216
|
+
- 感谢所有贡献者和用户
|
package/README.md
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
# JSON Mock Server
|
2
|
+
|
3
|
+
A lightweight and flexible mock server that uses JSON configuration to quickly create RESTful APIs.
|
4
|
+
|
5
|
+
<p align="center">
|
6
|
+
<img src="https://img.shields.io/npm/v/json-mock-server" alt="npm version" />
|
7
|
+
<img src="https://img.shields.io/npm/l/json-mock-server" alt="license" />
|
8
|
+
<img src="https://img.shields.io/npm/dt/json-mock-server" alt="downloads" />
|
9
|
+
</p>
|
10
|
+
|
11
|
+
## ✨ Features
|
12
|
+
|
13
|
+
- 🚀 Quick setup with JSON configuration
|
14
|
+
- 🔄 Support for GET, POST, PUT, DELETE methods
|
15
|
+
- 📝 Automatic data persistence
|
16
|
+
- 🔍 Built-in pagination support
|
17
|
+
- 🛠 Customizable response schemas
|
18
|
+
- 💡 TypeScript support
|
19
|
+
|
20
|
+
## 📦 Installation
|
21
|
+
|
22
|
+
```bash
|
23
|
+
# 使用 npm
|
24
|
+
npm install json-mock-server
|
25
|
+
|
26
|
+
# 使用 yarn
|
27
|
+
yarn add json-mock-server
|
28
|
+
|
29
|
+
# 使用 pnpm
|
30
|
+
pnpm add json-mock-server
|
31
|
+
```
|
32
|
+
|
33
|
+
## 🚀 Quick Start
|
34
|
+
|
35
|
+
### 1. Create Configuration File
|
36
|
+
|
37
|
+
Create a `data.json` file in your project root:
|
38
|
+
|
39
|
+
```json
|
40
|
+
{
|
41
|
+
"server": {
|
42
|
+
"port": 8080,
|
43
|
+
"baseProxy": "/api"
|
44
|
+
},
|
45
|
+
"routes": [
|
46
|
+
{
|
47
|
+
"path": "/users",
|
48
|
+
"methods": {
|
49
|
+
"get": {
|
50
|
+
"type": "array",
|
51
|
+
"pagination": {
|
52
|
+
"enabled": true,
|
53
|
+
"pageSize": 10,
|
54
|
+
"totalCount": 100
|
55
|
+
},
|
56
|
+
"response": [
|
57
|
+
{
|
58
|
+
"id": 1,
|
59
|
+
"name": "John",
|
60
|
+
"age": 30,
|
61
|
+
"city": "New York"
|
62
|
+
}
|
63
|
+
]
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
]
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
### 2. Start the Server
|
72
|
+
|
73
|
+
```bash
|
74
|
+
npx json-mock-server
|
75
|
+
```
|
76
|
+
|
77
|
+
Now your mock server is running at `http://localhost:8080`!
|
78
|
+
|
79
|
+
## 📖 Configuration Guide
|
80
|
+
|
81
|
+
### Server Configuration
|
82
|
+
|
83
|
+
The `server` section configures basic server settings:
|
84
|
+
|
85
|
+
```json
|
86
|
+
{
|
87
|
+
"server": {
|
88
|
+
"port": 8080, // Server port number
|
89
|
+
"baseProxy": "/api" // Base path for all routes
|
90
|
+
}
|
91
|
+
}
|
92
|
+
```
|
93
|
+
|
94
|
+
### Route Configuration
|
95
|
+
|
96
|
+
Each route can support multiple HTTP methods:
|
97
|
+
|
98
|
+
```json
|
99
|
+
{
|
100
|
+
"path": "/users", // Route path
|
101
|
+
"methods": {
|
102
|
+
"get": {
|
103
|
+
"type": "array", // Response type: "array" or "object"
|
104
|
+
"pagination": { // Optional pagination settings
|
105
|
+
"enabled": true,
|
106
|
+
"pageSize": 10,
|
107
|
+
"totalCount": 100
|
108
|
+
},
|
109
|
+
"response": [] // Response data
|
110
|
+
},
|
111
|
+
"post": {
|
112
|
+
"requestSchema": { // Request body validation schema
|
113
|
+
"name": "string",
|
114
|
+
"age": "number"
|
115
|
+
},
|
116
|
+
"response": {
|
117
|
+
"success": true
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
```
|
123
|
+
|
124
|
+
## 🎯 API Examples
|
125
|
+
|
126
|
+
### Basic CRUD Operations
|
127
|
+
|
128
|
+
#### Get Users List
|
129
|
+
```bash
|
130
|
+
curl http://localhost:8080/api/users
|
131
|
+
```
|
132
|
+
|
133
|
+
#### Get Single User
|
134
|
+
```bash
|
135
|
+
curl http://localhost:8080/api/users/1
|
136
|
+
```
|
137
|
+
|
138
|
+
#### Create User
|
139
|
+
```bash
|
140
|
+
curl -X POST http://localhost:8080/api/users \
|
141
|
+
-H "Content-Type: application/json" \
|
142
|
+
-d '{"name":"Alice","age":25,"city":"Boston"}'
|
143
|
+
```
|
144
|
+
|
145
|
+
#### Update User
|
146
|
+
```bash
|
147
|
+
curl -X PUT http://localhost:8080/api/users/1 \
|
148
|
+
-H "Content-Type: application/json" \
|
149
|
+
-d '{"name":"Alice","age":26,"city":"Boston"}'
|
150
|
+
```
|
151
|
+
|
152
|
+
#### Delete User
|
153
|
+
```bash
|
154
|
+
curl -X DELETE http://localhost:8080/api/users/1
|
155
|
+
```
|
156
|
+
|
157
|
+
### Advanced Usage
|
158
|
+
|
159
|
+
#### Pagination
|
160
|
+
```bash
|
161
|
+
# Get page 2 with 10 items per page
|
162
|
+
curl http://localhost:8080/api/users?page=2&pageSize=10
|
163
|
+
```
|
164
|
+
|
165
|
+
#### Custom Response Headers
|
166
|
+
The server automatically adds these headers:
|
167
|
+
- `X-Total-Count`: Total number of items (for paginated responses)
|
168
|
+
|
169
|
+
## 🔧 Advanced Configuration
|
170
|
+
|
171
|
+
### Dynamic Routes
|
172
|
+
|
173
|
+
You can use URL parameters in routes:
|
174
|
+
|
175
|
+
```json
|
176
|
+
{
|
177
|
+
"path": "/users/:id/posts",
|
178
|
+
"methods": {
|
179
|
+
"get": {
|
180
|
+
"type": "array",
|
181
|
+
"response": []
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
```
|
186
|
+
|
187
|
+
### Request Validation
|
188
|
+
|
189
|
+
Add schema validation for POST/PUT requests:
|
190
|
+
|
191
|
+
```json
|
192
|
+
{
|
193
|
+
"requestSchema": {
|
194
|
+
"name": "string",
|
195
|
+
"age": "number",
|
196
|
+
"email": "string"
|
197
|
+
}
|
198
|
+
}
|
199
|
+
```
|
200
|
+
|
201
|
+
## 🤝 Contributing
|
202
|
+
|
203
|
+
1. Fork the repository
|
204
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
205
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
206
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
207
|
+
5. Open a Pull Request
|
208
|
+
|
209
|
+
## 📄 License
|
210
|
+
|
211
|
+
MIT © [Xiong Haiyin]
|
212
|
+
|
213
|
+
## 🙏 Acknowledgments
|
214
|
+
|
215
|
+
- Express.js for the excellent web framework
|
216
|
+
- All our contributors and users
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
18
|
+
};
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
20
|
+
exports.MockServer = void 0;
|
21
|
+
exports.startServer = startServer;
|
22
|
+
const fs_1 = __importDefault(require("fs"));
|
23
|
+
const path_1 = __importDefault(require("path"));
|
24
|
+
const server_1 = require("./server");
|
25
|
+
function startServer(configPath = 'data.json') {
|
26
|
+
const fullPath = path_1.default.resolve(process.cwd(), configPath);
|
27
|
+
try {
|
28
|
+
const configContent = fs_1.default.readFileSync(fullPath, 'utf-8');
|
29
|
+
const config = JSON.parse(configContent);
|
30
|
+
const server = new server_1.MockServer(config, configPath);
|
31
|
+
server.start();
|
32
|
+
}
|
33
|
+
catch (error) {
|
34
|
+
console.error('Failed to start server:', error);
|
35
|
+
process.exit(1);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
if (require.main === module) {
|
39
|
+
startServer();
|
40
|
+
}
|
41
|
+
var server_2 = require("./server");
|
42
|
+
Object.defineProperty(exports, "MockServer", { enumerable: true, get: function () { return server_2.MockServer; } });
|
43
|
+
__exportStar(require("./types"), exports);
|
package/dist/server.d.ts
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
import { Config } from './types';
|
2
|
+
export declare class MockServer {
|
3
|
+
private app;
|
4
|
+
private config;
|
5
|
+
private configPath;
|
6
|
+
constructor(config: Config, configPath?: string);
|
7
|
+
private setupMiddleware;
|
8
|
+
private setupRoutes;
|
9
|
+
private saveConfig;
|
10
|
+
private findUserById;
|
11
|
+
private getNextUserId;
|
12
|
+
private createRoute;
|
13
|
+
private handleRequest;
|
14
|
+
private handlePostRequest;
|
15
|
+
private handlePutRequest;
|
16
|
+
private handleDeleteRequest;
|
17
|
+
start(): void;
|
18
|
+
}
|
package/dist/server.js
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.MockServer = void 0;
|
7
|
+
const express_1 = __importDefault(require("express"));
|
8
|
+
const cors_1 = __importDefault(require("cors"));
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
10
|
+
const path_1 = __importDefault(require("path"));
|
11
|
+
class MockServer {
|
12
|
+
constructor(config, configPath = 'data.json') {
|
13
|
+
this.app = (0, express_1.default)();
|
14
|
+
this.config = config;
|
15
|
+
this.configPath = path_1.default.resolve(process.cwd(), configPath);
|
16
|
+
this.setupMiddleware();
|
17
|
+
this.setupRoutes();
|
18
|
+
}
|
19
|
+
setupMiddleware() {
|
20
|
+
this.app.use((0, cors_1.default)());
|
21
|
+
this.app.use(express_1.default.json());
|
22
|
+
}
|
23
|
+
setupRoutes() {
|
24
|
+
this.config.routes.forEach((route) => {
|
25
|
+
Object.entries(route.methods).forEach(([method, methodConfig]) => {
|
26
|
+
this.createRoute(route.path, method, methodConfig);
|
27
|
+
});
|
28
|
+
});
|
29
|
+
}
|
30
|
+
saveConfig() {
|
31
|
+
fs_1.default.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), 'utf-8');
|
32
|
+
}
|
33
|
+
findUserById(id) {
|
34
|
+
const usersRoute = this.config.routes.find(route => route.path === '/users');
|
35
|
+
if (!usersRoute)
|
36
|
+
return null;
|
37
|
+
const getMethod = usersRoute.methods.get;
|
38
|
+
if (!getMethod || !Array.isArray(getMethod.response))
|
39
|
+
return null;
|
40
|
+
return getMethod.response.find(user => user.id === id);
|
41
|
+
}
|
42
|
+
getNextUserId() {
|
43
|
+
const usersRoute = this.config.routes.find(route => route.path === '/users');
|
44
|
+
if (!usersRoute)
|
45
|
+
return 1;
|
46
|
+
const getMethod = usersRoute.methods.get;
|
47
|
+
if (!getMethod || !Array.isArray(getMethod.response))
|
48
|
+
return 1;
|
49
|
+
const maxId = Math.max(...getMethod.response.map(user => user.id));
|
50
|
+
return maxId + 1;
|
51
|
+
}
|
52
|
+
createRoute(path, method, config) {
|
53
|
+
const fullPath = `${this.config.server.baseProxy}${path}`;
|
54
|
+
console.log(`创建路由: ${method.toUpperCase()} ${fullPath}`);
|
55
|
+
switch (method.toLowerCase()) {
|
56
|
+
case 'get':
|
57
|
+
this.app.get(fullPath, this.handleRequest(config));
|
58
|
+
break;
|
59
|
+
case 'post':
|
60
|
+
this.app.post(fullPath, this.handlePostRequest(config));
|
61
|
+
break;
|
62
|
+
case 'put':
|
63
|
+
this.app.put(`${fullPath}/:id`, this.handlePutRequest(config));
|
64
|
+
break;
|
65
|
+
case 'delete':
|
66
|
+
this.app.delete(`${fullPath}/:id`, this.handleDeleteRequest(config));
|
67
|
+
break;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
handleRequest(config) {
|
71
|
+
return (req, res) => {
|
72
|
+
console.log(`收到请求: ${req.method} ${req.url}`);
|
73
|
+
if (config.pagination?.enabled && config.type === 'array') {
|
74
|
+
const page = parseInt(req.query.page) || 1;
|
75
|
+
const pageSize = parseInt(req.query.pageSize) || config.pagination.pageSize;
|
76
|
+
const startIndex = (page - 1) * pageSize;
|
77
|
+
const endIndex = startIndex + pageSize;
|
78
|
+
const data = config.response.slice(startIndex, endIndex);
|
79
|
+
res.header('X-Total-Count', config.pagination.totalCount.toString());
|
80
|
+
res.json(data);
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
res.json(config.response);
|
84
|
+
}
|
85
|
+
};
|
86
|
+
}
|
87
|
+
handlePostRequest(config) {
|
88
|
+
return (req, res) => {
|
89
|
+
console.log(`收到创建请求: ${req.url}`, req.body);
|
90
|
+
const usersRoute = this.config.routes.find(route => route.path === '/users');
|
91
|
+
if (!usersRoute) {
|
92
|
+
return res.status(404).json({ error: '路由未找到' });
|
93
|
+
}
|
94
|
+
const getMethod = usersRoute.methods.get;
|
95
|
+
if (!getMethod || !Array.isArray(getMethod.response)) {
|
96
|
+
return res.status(500).json({ error: '数据格式错误' });
|
97
|
+
}
|
98
|
+
const newUser = {
|
99
|
+
id: this.getNextUserId(),
|
100
|
+
...req.body
|
101
|
+
};
|
102
|
+
getMethod.response.push(newUser);
|
103
|
+
this.saveConfig();
|
104
|
+
res.status(201).json(newUser);
|
105
|
+
};
|
106
|
+
}
|
107
|
+
handlePutRequest(config) {
|
108
|
+
return (req, res) => {
|
109
|
+
const userId = parseInt(req.params.id);
|
110
|
+
console.log(`收到更新请求: ${req.url}`, req.body);
|
111
|
+
const user = this.findUserById(userId);
|
112
|
+
if (!user) {
|
113
|
+
return res.status(404).json({ error: '用户未找到' });
|
114
|
+
}
|
115
|
+
Object.assign(user, req.body);
|
116
|
+
this.saveConfig();
|
117
|
+
res.json(user);
|
118
|
+
};
|
119
|
+
}
|
120
|
+
handleDeleteRequest(config) {
|
121
|
+
return (req, res) => {
|
122
|
+
const userId = parseInt(req.params.id);
|
123
|
+
console.log(`收到删除请求: ${req.url}`);
|
124
|
+
const usersRoute = this.config.routes.find(route => route.path === '/users');
|
125
|
+
if (!usersRoute) {
|
126
|
+
return res.status(404).json({ error: '路由未找到' });
|
127
|
+
}
|
128
|
+
const getMethod = usersRoute.methods.get;
|
129
|
+
if (!getMethod || !Array.isArray(getMethod.response)) {
|
130
|
+
return res.status(500).json({ error: '数据格式错误' });
|
131
|
+
}
|
132
|
+
const userIndex = getMethod.response.findIndex(user => user.id === userId);
|
133
|
+
if (userIndex === -1) {
|
134
|
+
return res.status(404).json({ error: '用户未找到' });
|
135
|
+
}
|
136
|
+
getMethod.response.splice(userIndex, 1);
|
137
|
+
this.saveConfig();
|
138
|
+
res.json({ success: true, message: '删除成功' });
|
139
|
+
};
|
140
|
+
}
|
141
|
+
start() {
|
142
|
+
this.app.listen(this.config.server.port, () => {
|
143
|
+
console.log(`Mock 服务器已启动:`);
|
144
|
+
console.log(`- 地址: http://localhost:${this.config.server.port}`);
|
145
|
+
console.log(`- 基础路径: ${this.config.server.baseProxy}`);
|
146
|
+
console.log('可用的接口:');
|
147
|
+
this.config.routes.forEach(route => {
|
148
|
+
Object.keys(route.methods).forEach(method => {
|
149
|
+
console.log(` ${method.toUpperCase()} http://localhost:${this.config.server.port}${this.config.server.baseProxy}${route.path}`);
|
150
|
+
});
|
151
|
+
});
|
152
|
+
});
|
153
|
+
}
|
154
|
+
}
|
155
|
+
exports.MockServer = MockServer;
|
package/dist/types.d.ts
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
export interface ServerConfig {
|
2
|
+
port: number;
|
3
|
+
baseProxy: string;
|
4
|
+
}
|
5
|
+
export interface PaginationConfig {
|
6
|
+
enabled: boolean;
|
7
|
+
pageSize: number;
|
8
|
+
totalCount: number;
|
9
|
+
}
|
10
|
+
export interface MethodConfig {
|
11
|
+
type?: 'array' | 'object';
|
12
|
+
pagination?: PaginationConfig;
|
13
|
+
response: any;
|
14
|
+
requestSchema?: Record<string, string>;
|
15
|
+
params?: string[];
|
16
|
+
}
|
17
|
+
export interface RouteConfig {
|
18
|
+
path: string;
|
19
|
+
methods: {
|
20
|
+
[key: string]: MethodConfig;
|
21
|
+
};
|
22
|
+
}
|
23
|
+
export interface Config {
|
24
|
+
server: ServerConfig;
|
25
|
+
routes: RouteConfig[];
|
26
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
{
|
2
|
+
"name": "json-api-mocker",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "一个基于 JSON 配置的 Mock 服务器",
|
5
|
+
"main": "dist/index.js",
|
6
|
+
"types": "dist/index.d.ts",
|
7
|
+
"bin": {
|
8
|
+
"json-mock-server": "dist/cli.js"
|
9
|
+
},
|
10
|
+
"files": [
|
11
|
+
"dist",
|
12
|
+
"README.md",
|
13
|
+
"README.ch.md"
|
14
|
+
],
|
15
|
+
"scripts": {
|
16
|
+
"dev": "nodemon",
|
17
|
+
"build": "tsc",
|
18
|
+
"start": "node dist/index.js",
|
19
|
+
"test": "jest",
|
20
|
+
"prepublishOnly": "npm run build"
|
21
|
+
},
|
22
|
+
"keywords": [
|
23
|
+
"mock",
|
24
|
+
"server",
|
25
|
+
"json",
|
26
|
+
"api",
|
27
|
+
"typescript",
|
28
|
+
"rest",
|
29
|
+
"api-mock",
|
30
|
+
"mock-server"
|
31
|
+
],
|
32
|
+
"author": "Xiong Haiyin",
|
33
|
+
"license": "MIT",
|
34
|
+
"repository": {
|
35
|
+
"type": "git",
|
36
|
+
"url": "git+https://github.com/你的用户名/json-mock-server.git"
|
37
|
+
},
|
38
|
+
"bugs": {
|
39
|
+
"url": "https://github.com/你的用户名/json-mock-server/issues"
|
40
|
+
},
|
41
|
+
"homepage": "https://github.com/你的用户名/json-mock-server#readme",
|
42
|
+
"dependencies": {
|
43
|
+
"cors": "^2.8.5",
|
44
|
+
"express": "^4.17.1"
|
45
|
+
},
|
46
|
+
"devDependencies": {
|
47
|
+
"@types/cors": "^2.8.13",
|
48
|
+
"@types/express": "^4.17.13",
|
49
|
+
"@types/jest": "^27.5.2",
|
50
|
+
"@types/node": "^16.18.0",
|
51
|
+
"jest": "^27.5.1",
|
52
|
+
"nodemon": "^2.0.22",
|
53
|
+
"ts-jest": "^27.1.5",
|
54
|
+
"ts-node": "^10.9.1",
|
55
|
+
"typescript": "^4.9.5"
|
56
|
+
}
|
57
|
+
}
|