json-api-mocker 1.0.0
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.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
|
+
}
|