json-api-mocker 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.ch.md CHANGED
@@ -3,11 +3,12 @@
3
3
  一个轻量级且灵活的 Mock 服务器,通过 JSON 配置快速创建 RESTful API。
4
4
 
5
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="下载量" />
6
+ <img src="https://img.shields.io/npm/v/json-api-mocker" alt="npm version" />
7
+ <img src="https://img.shields.io/npm/l/json-api-mocker" alt="license" />
8
+ <img src="https://img.shields.io/npm/dt/json-api-mocker" alt="downloads" />
9
9
  </p>
10
10
 
11
+
11
12
  ## ✨ 特性
12
13
 
13
14
  - 🚀 通过 JSON 配置快速搭建
@@ -15,6 +16,7 @@
15
16
  - 📝 自动数据持久化
16
17
  - 🔍 内置分页支持
17
18
  - 🛠 可自定义响应结构
19
+ - 💡 集成 Mock.js 实现强大的数据模拟
18
20
  - 💡 TypeScript 支持
19
21
 
20
22
  ## 📦 安装
@@ -152,6 +154,105 @@ Mock 服务器已启动:
152
154
  }
153
155
  ```
154
156
 
157
+ ### Mock.js 集成
158
+
159
+ 你可以使用 Mock.js 模板来生成动态数据:
160
+
161
+ ```json
162
+ {
163
+ "path": "/users",
164
+ "methods": {
165
+ "get": {
166
+ "type": "array",
167
+ "mock": {
168
+ "enabled": true,
169
+ "total": 200,
170
+ "template": {
171
+ "id|+1": 1,
172
+ "name": "@cname",
173
+ "email": "@email",
174
+ "age|18-60": 1,
175
+ "address": "@city(true)",
176
+ "avatar": "@image('200x200')",
177
+ "createTime": "@datetime"
178
+ }
179
+ },
180
+ "pagination": {
181
+ "enabled": true,
182
+ "pageSize": 10
183
+ }
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ #### 可用的 Mock.js 模板
190
+
191
+ - `@cname` - 生成中文姓名
192
+ - `@name` - 生成英文姓名
193
+ - `@email` - 生成邮箱地址
194
+ - `@datetime` - 生成日期时间
195
+ - `@image` - 生成图片链接
196
+ - `@city` - 生成城市名
197
+ - `@id` - 生成随机 ID
198
+ - `@guid` - 生成 GUID
199
+ - `@title` - 生成标题
200
+ - `@paragraph` - 生成段落
201
+ - `|+1` - 自增数字
202
+
203
+ 更多 Mock.js 模板请访问 [Mock.js 文档](http://mockjs.com/examples.html)
204
+
205
+ #### Mock.js 使用示例
206
+
207
+ 1. 生成用户列表:
208
+ ```json
209
+ {
210
+ "mock": {
211
+ "enabled": true,
212
+ "total": 100,
213
+ "template": {
214
+ "id|+1": 1,
215
+ "name": "@cname",
216
+ "email": "@email"
217
+ }
218
+ }
219
+ }
220
+ ```
221
+
222
+ 2. 生成文章列表:
223
+ ```json
224
+ {
225
+ "mock": {
226
+ "enabled": true,
227
+ "total": 50,
228
+ "template": {
229
+ "id|+1": 1,
230
+ "title": "@ctitle",
231
+ "content": "@cparagraph",
232
+ "author": "@cname",
233
+ "publishDate": "@datetime"
234
+ }
235
+ }
236
+ }
237
+ ```
238
+
239
+ 3. 生成商品列表:
240
+ ```json
241
+ {
242
+ "mock": {
243
+ "enabled": true,
244
+ "total": 30,
245
+ "template": {
246
+ "id|+1": 1,
247
+ "name": "@ctitle(3, 5)",
248
+ "price|100-1000.2": 1,
249
+ "category": "@pick(['电子产品', '图书', '服装'])",
250
+ "image": "@image('200x200', '#50B347', '#FFF', 'Mock.js')"
251
+ }
252
+ }
253
+ }
254
+ ```
255
+
155
256
  ## 🎯 API 示例
156
257
 
157
258
  ### 基本的 CRUD 操作
package/README.md CHANGED
@@ -15,6 +15,7 @@ A lightweight and flexible mock server that uses JSON configuration to quickly c
15
15
  - 📝 Automatic data persistence
16
16
  - 🔍 Built-in pagination support
17
17
  - 🛠 Customizable response schemas
18
+ - 💡 Integration with Mock.js for powerful data mocking
18
19
  - 💡 TypeScript support
19
20
 
20
21
  ## 📦 Installation
@@ -152,6 +153,104 @@ Each route can support multiple HTTP methods:
152
153
  }
153
154
  ```
154
155
 
156
+ ### Mock.js Integration
157
+
158
+ You can use Mock.js templates to generate dynamic data:
159
+
160
+ ```json
161
+ {
162
+ "path": "/users",
163
+ "methods": {
164
+ "get": {
165
+ "type": "array",
166
+ "mock": {
167
+ "enabled": true,
168
+ "total": 200,
169
+ "template": {
170
+ "id|+1": 1,
171
+ "name": "@name",
172
+ "email": "@email",
173
+ "age|18-60": 1,
174
+ "address": "@city(true)",
175
+ "avatar": "@image('200x200')",
176
+ "createTime": "@datetime"
177
+ }
178
+ },
179
+ "pagination": {
180
+ "enabled": true,
181
+ "pageSize": 10
182
+ }
183
+ }
184
+ }
185
+ }
186
+ ```
187
+
188
+ #### Available Mock.js Templates
189
+
190
+ - `@name` - Generate random name
191
+ - `@email` - Generate random email
192
+ - `@datetime` - Generate random datetime
193
+ - `@image` - Generate random image URL
194
+ - `@city` - Generate random city name
195
+ - `@id` - Generate random ID
196
+ - `@guid` - Generate GUID
197
+ - `@title` - Generate random title
198
+ - `@paragraph` - Generate random paragraph
199
+ - `|+1` - Auto increment number
200
+
201
+ For more Mock.js templates, visit [Mock.js Documentation](http://mockjs.com/examples.html)
202
+
203
+ #### Examples with Mock.js
204
+
205
+ 1. Generate user list with random data:
206
+ ```json
207
+ {
208
+ "mock": {
209
+ "enabled": true,
210
+ "total": 100,
211
+ "template": {
212
+ "id|+1": 1,
213
+ "name": "@name",
214
+ "email": "@email"
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ 2. Generate article list with random content:
221
+ ```json
222
+ {
223
+ "mock": {
224
+ "enabled": true,
225
+ "total": 50,
226
+ "template": {
227
+ "id|+1": 1,
228
+ "title": "@title",
229
+ "content": "@paragraph",
230
+ "author": "@name",
231
+ "publishDate": "@datetime"
232
+ }
233
+ }
234
+ }
235
+ ```
236
+
237
+ 3. Generate product list with random prices:
238
+ ```json
239
+ {
240
+ "mock": {
241
+ "enabled": true,
242
+ "total": 30,
243
+ "template": {
244
+ "id|+1": 1,
245
+ "name": "@title(3, 5)",
246
+ "price|100-1000.2": 1,
247
+ "category": "@pick(['Electronics', 'Books', 'Clothing'])",
248
+ "image": "@image('200x200', '#50B347', '#FFF', 'Mock.js')"
249
+ }
250
+ }
251
+ }
252
+ ```
253
+
155
254
  ## 🎯 API Examples
156
255
 
157
256
  ### Basic CRUD Operations
package/dist/server.d.ts CHANGED
@@ -5,14 +5,9 @@ export declare class MockServer {
5
5
  private configPath;
6
6
  constructor(config: Config, configPath?: string);
7
7
  private setupMiddleware;
8
+ private generateMockData;
9
+ private handleRequest;
8
10
  private setupRoutes;
9
- private saveConfig;
10
- private findUserById;
11
- private getNextUserId;
12
11
  private createRoute;
13
- private handleRequest;
14
- private handlePostRequest;
15
- private handlePutRequest;
16
- private handleDeleteRequest;
17
12
  start(): void;
18
13
  }
package/dist/server.js CHANGED
@@ -4,15 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.MockServer = void 0;
7
+ const mockjs_1 = __importDefault(require("mockjs"));
7
8
  const express_1 = __importDefault(require("express"));
8
9
  const cors_1 = __importDefault(require("cors"));
9
- const fs_1 = __importDefault(require("fs"));
10
- const path_1 = __importDefault(require("path"));
11
10
  class MockServer {
12
11
  constructor(config, configPath = 'data.json') {
13
12
  this.app = (0, express_1.default)();
14
13
  this.config = config;
15
- this.configPath = path_1.default.resolve(process.cwd(), configPath);
14
+ this.configPath = configPath;
16
15
  this.setupMiddleware();
17
16
  this.setupRoutes();
18
17
  }
@@ -20,6 +19,43 @@ class MockServer {
20
19
  this.app.use((0, cors_1.default)());
21
20
  this.app.use(express_1.default.json());
22
21
  }
22
+ generateMockData(config) {
23
+ try {
24
+ if (config.mock?.enabled && config.mock.template) {
25
+ const { total, template } = config.mock;
26
+ return mockjs_1.default.mock({
27
+ [`data|${total}`]: [template]
28
+ }).data;
29
+ }
30
+ return config.response || [];
31
+ }
32
+ catch (error) {
33
+ console.error('生成 Mock 数据时出错:', error);
34
+ return config.response || [];
35
+ }
36
+ }
37
+ handleRequest(config) {
38
+ return (req, res) => {
39
+ try {
40
+ console.log(`收到请求: ${req.method} ${req.url}`);
41
+ let responseData = this.generateMockData(config);
42
+ if (config.pagination?.enabled && Array.isArray(responseData)) {
43
+ const page = parseInt(req.query.page) || 1;
44
+ const pageSize = parseInt(req.query.pageSize) || config.pagination.pageSize;
45
+ const startIndex = (page - 1) * pageSize;
46
+ const endIndex = startIndex + pageSize;
47
+ const paginatedData = responseData.slice(startIndex, endIndex);
48
+ res.header('X-Total-Count', responseData.length.toString());
49
+ responseData = paginatedData;
50
+ }
51
+ res.json(responseData);
52
+ }
53
+ catch (error) {
54
+ console.error('处理请求时出错:', error);
55
+ res.status(500).json({ error: '服务器内部错误' });
56
+ }
57
+ };
58
+ }
23
59
  setupRoutes() {
24
60
  this.config.routes.forEach((route) => {
25
61
  Object.entries(route.methods).forEach(([method, methodConfig]) => {
@@ -27,28 +63,6 @@ class MockServer {
27
63
  });
28
64
  });
29
65
  }
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
66
  createRoute(path, method, config) {
53
67
  const fullPath = `${this.config.server.baseProxy}${path}`;
54
68
  console.log(`创建路由: ${method.toUpperCase()} ${fullPath}`);
@@ -57,87 +71,16 @@ class MockServer {
57
71
  this.app.get(fullPath, this.handleRequest(config));
58
72
  break;
59
73
  case 'post':
60
- this.app.post(fullPath, this.handlePostRequest(config));
74
+ this.app.post(fullPath, this.handleRequest(config));
61
75
  break;
62
76
  case 'put':
63
- this.app.put(`${fullPath}/:id`, this.handlePutRequest(config));
77
+ this.app.put(`${fullPath}/:id`, this.handleRequest(config));
64
78
  break;
65
79
  case 'delete':
66
- this.app.delete(`${fullPath}/:id`, this.handleDeleteRequest(config));
80
+ this.app.delete(`${fullPath}/:id`, this.handleRequest(config));
67
81
  break;
68
82
  }
69
83
  }
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
84
  start() {
142
85
  this.app.listen(this.config.server.port, () => {
143
86
  console.log(`Mock 服务器已启动:`);
package/dist/types.d.ts CHANGED
@@ -7,10 +7,16 @@ export interface PaginationConfig {
7
7
  pageSize: number;
8
8
  totalCount: number;
9
9
  }
10
+ export interface MockConfig {
11
+ enabled: boolean;
12
+ total: number;
13
+ template: Record<string, any>;
14
+ }
10
15
  export interface MethodConfig {
11
16
  type?: 'array' | 'object';
12
17
  pagination?: PaginationConfig;
13
- response: any;
18
+ mock?: MockConfig;
19
+ response?: any;
14
20
  requestSchema?: Record<string, string>;
15
21
  params?: string[];
16
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-api-mocker",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "一个基于 JSON 配置的 Mock 服务器",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -41,12 +41,14 @@
41
41
  "homepage": "https://github.com/Selteve/json-api-mocker#readme",
42
42
  "dependencies": {
43
43
  "cors": "^2.8.5",
44
- "express": "^4.17.1"
44
+ "express": "^4.17.1",
45
+ "mockjs": "^1.1.0"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@types/cors": "^2.8.13",
48
49
  "@types/express": "^4.17.13",
49
50
  "@types/jest": "^27.5.2",
51
+ "@types/mockjs": "^1.0.10",
50
52
  "@types/node": "^16.18.0",
51
53
  "jest": "^27.5.1",
52
54
  "nodemon": "^2.0.22",