json-api-mocker 1.0.2 → 1.1.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 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
  ## 📦 安装
@@ -70,12 +72,43 @@ pnpm add json-api-mocker
70
72
 
71
73
  ### 2. 启动服务器
72
74
 
75
+ 有多种方式可以启动 Mock 服务器:
76
+
73
77
  ```bash
78
+ # 方式一:使用 npx(推荐)
74
79
  npx json-api-mocker
80
+
81
+ # 方式二:使用 npx 并指定配置文件
82
+ npx json-api-mocker ./custom-config.json
83
+
84
+ # 方式三:如果全局安装了包
85
+ json-api-mocker
86
+
87
+ # 方式四:如果作为项目依赖安装
88
+ # 在 package.json 的 scripts 中添加:
89
+ {
90
+ "scripts": {
91
+ "mock": "json-api-mocker"
92
+ }
93
+ }
94
+ # 然后运行:
95
+ npm run mock
75
96
  ```
76
97
 
77
98
  现在你的 Mock 服务器已经在 `http://localhost:8080` 运行了!
78
99
 
100
+ 你会看到类似这样的输出:
101
+ ```bash
102
+ Mock 服务器已启动:
103
+ - 地址:http://localhost:8080
104
+ - 基础路径:/api
105
+ 可用的接口:
106
+ GET http://localhost:8080/api/users
107
+ POST http://localhost:8080/api/users
108
+ PUT http://localhost:8080/api/users/:id
109
+ DELETE http://localhost:8080/api/users/:id
110
+ ```
111
+
79
112
  ## 📖 配置指南
80
113
 
81
114
  ### 服务器配置
@@ -121,6 +154,105 @@ npx json-api-mocker
121
154
  }
122
155
  ```
123
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
+
124
256
  ## 🎯 API 示例
125
257
 
126
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
@@ -70,12 +71,43 @@ Create a `data.json` file in your project root:
70
71
 
71
72
  ### 2. Start the Server
72
73
 
74
+ There are several ways to start the mock server:
75
+
73
76
  ```bash
77
+ # Method 1: Using npx (Recommended)
74
78
  npx json-api-mocker
79
+
80
+ # Method 2: Using npx with a custom config file
81
+ npx json-api-mocker ./custom-config.json
82
+
83
+ # Method 3: If installed globally
84
+ json-api-mocker
85
+
86
+ # Method 4: If installed as a project dependency
87
+ # Add this to your package.json scripts:
88
+ {
89
+ "scripts": {
90
+ "mock": "json-api-mocker"
91
+ }
92
+ }
93
+ # Then run:
94
+ npm run mock
75
95
  ```
76
96
 
77
97
  Now your mock server is running at `http://localhost:8080`!
78
98
 
99
+ You'll see output like this:
100
+ ```bash
101
+ Mock Server is running:
102
+ - Address: http://localhost:8080
103
+ - Base Path: /api
104
+ Available APIs:
105
+ GET http://localhost:8080/api/users
106
+ POST http://localhost:8080/api/users
107
+ PUT http://localhost:8080/api/users/:id
108
+ DELETE http://localhost:8080/api/users/:id
109
+ ```
110
+
79
111
  ## 📖 Configuration Guide
80
112
 
81
113
  ### Server Configuration
@@ -121,6 +153,104 @@ Each route can support multiple HTTP methods:
121
153
  }
122
154
  ```
123
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
+
124
254
  ## 🎯 API Examples
125
255
 
126
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.2",
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",