UNPKG

14.8 kBMarkdownView Raw
1## Mock
2
3[![npm version](https://img.shields.io/npm/v/@forchange/mock.svg)](https://www.npmjs.com/package/@forchange/mock)
4
5mock 自定义规则、流程的数据模拟服务
6
7## 特点
8
9- mock 方式多样化,支持 json 和 function
10- 隔离接口,容易维护,适合开源协作
11- 接口联动处理,可根据业务流程自定义返回数据
12- 文件路径即是路由和方法,接口唯一,更好的开发体验
13- 支持 webSocket,连接、断开、主动推送消息 等操作可视化
14
15## 快速开始
16
17#### 安装
18
19**安装 node 环境**
20
21```
22$ brew install node
23```
24
25**安装 mock 服务**
26
27```
28$ npm install -g @forchange/mock
29```
30
31#### 开始
32
33**初始化:**
34
35```
36$ fmock init
37```
38
39```
40$ cd <输入的文件名>
41```
42
43**启动:**
44
45```
46$ fmock
47```
48
49现在,访问 http://0.0.0.0:3839/user/info 查看接口
50
51## 如何使用
52
53#### 配置 config
54
55config 文件是整个服务的配置文件 [详细说明](#config)
56
57#### 添加 data
58
59data 文件是接口对应的返回数据 [详细说明](#data)
60
61#### 添加 rule
62
63当我们构造 data 数据时,将会提供部分 [内部方法](#内部-rule)
64当你需要自定义 data 的返回数据时,可通过 rule 文件配置 [详细说明](#自定义-rule)
65
66#### 添加 label
67
68为了防止数据文件间的冲突,我们提供 label 标识 [详细说明](#label)
69
70#### 添加 flow
71
72当你需要进行接口间的数据联动时,可添加 flow 流程 [详细说明](#flow)
73
74#### 示例目录结构
75
76```tree
77mock
78├── config.js //config 配置入口
79├── data //data 数据
80│   └── ambassador
81│   ├── courses
82│   │   └── :id
83│   │   └── :pay#get.js
84│   ├── courses#get.js
85│   ├── settlements
86│   │   └── search.js
87│   └── settlements#get.js
88├── socket //socket 数据
89│ ├── aaa.js
90│ ├── access.js
91│ ├── cun.js
92│ ├── kkk
93│ │   └── bbb.js
94│ └── promise.js
95└── rule.js //自定义规则
96```
97
98</br>
99
100- data: 添加 [data](#data)
101- socket: 添加 [socket](#socket)
102- config.js: 配置 [config](#config)
103- rule.js: 配置 [自定义规则](#自定义-rule)
104
105## 命令
106
107#### 常用指令
108
109```
110选项:
111 create <path> [-l <label>] [-m <method>] [-s]
112 path 路径
113 -l, --label label 标签
114 -s 是否为 socket 数据
115 -m, --method method of mock http
116
117 init 快速开始
118
119 -c, --config config file of mock
120 -h, --host host of mock
121 -p, --port port of mock http
122 -d, --directory directory of mock http
123
124 -v, --version 显示版本号
125 --help 显示帮助信息
126
127示例:
128 fmock init
129 fmock
130```
131
132#### 启动 mock 服务
133
134```bash
135$ fmock -c ./mock/config
136```
137
138#### 新建文件
139
140默认创建 http 服务 data 文件
141当添加 `-s` 指令时创建 socket 服务 data 文件
142
143```bash
144$ fmock create ./aaa/bbb -m '方法名'
145```
146
147## config
148
149#### 新建
150
151添加 `config.js` 文件
152
153#### 参数
154
155<table>
156 <tr>
157 <td colspan="3">参数</td>
158 <td>解释</td>
159 <td>数据类型</td>
160 <td>示例</td>
161 </tr>
162 <tr>
163 <td colspan="3">host</td>
164 <td>string</td>
165 <td>ip</td>
166 <td>‘0.0.0.0’</td>
167 </tr>
168 <tr>
169 <td rowspan="7">http</td>
170 <td colspan="2">port</td>
171 <td>number</td>
172 <td>http 服务端口</td>
173 <td>3839</td>
174 </tr>
175 <tr>
176 <td colspan="2">directory</td>
177 <td>string</td>
178 <td>http 数据文件路径</td>
179 <td>‘./data’</td>
180 </tr>
181 <tr>
182 <td colspan="2">middleware</td>
183 <td>array</td>
184 <td>自定义中间件</td>
185 <td>[]</td>
186 </tr>
187 <tr>
188 <td colspan="2">rule</td>
189 <td>string</td>
190 <td>自定义规则</td>
191 <td>‘./rule.js’</td>
192 </tr>
193 <tr>
194 <td rowspan="3">tls</td>
195 <td>httpsPort</td>
196 <td>number</td>
197 <td>https 端口</td>
198 <td>443</td>
199 </tr>
200 <tr>
201 <td>key</td>
202 <td>string</td>
203 <td>密钥</td>
204 <td></td>
205 </tr>
206 <tr>
207 <td>cert</td>
208 <td>string</td>
209 <td>证书</td>
210 <td></td>
211 </tr>
212 <tr>
213 <td rowspan="2">socket</td>
214 <td colspan="2">port</td>
215 <td>number</td>
216 <td>socket 服务端口</td>
217 <td>3838</td>
218 </tr>
219 <tr>
220 <td colspan="2">directory</td>
221 <td>string</td>
222 <td>socket 自定义回复文件</td>
223 <td>‘./socket’</td>
224 </tr>
225 <tr>
226 <td colspan="3">label</td>
227 <td>string</td>
228 <td>自定义 label</td>
229 <td>‘xindongdong’</td>
230 </tr>
231</table>
232
233#### 示例
234
235```javascript
236module.exports = {
237 host: "0.0.0.0",
238 http: {
239 port: 8888,
240 directory: "./data",
241 middleware: ["a"],
242 rule: "./rule.js",
243 tls: {
244 httpsPort: 443,
245 key: "aaa",
246 cert: "111"
247 }
248 },
249 socket: {
250 port: 3838,
251 directory: "./socket"
252 },
253 label: "chenle"
254};
255```
256
257## data
258
259#### 新建
260
261添加 `data` 文件夹,按照以下规则新建文件
262
263#### 规则
264
265- 一个接口一个文件
266- 文件路径即路由和方法
267
268#### 示例
269
270`路由`:/ambassador/courses/:id/:pay
271`方法`:GET
272
273```tree
274mock
275├── data
276│   └── ambassador
277│   ├── courses
278│   │   └── :id
279│   │   └── :pay#get.js
280```
281
282#### 数据定义
283
284**JSON 数据**
285
286我们将会直接获取到定义 data 数据。
287
288**示例**
289
290```javascript
291exports.data = {
292 errcode: 0,
293 errmsg: "ok",
294 data: {
295 a: "@number",
296 b: "2",
297 c: [1, 2, 3],
298 d: "@string",
299 type: {
300 __rule__: "@enum", // 枚举
301 params: ["数组", "b", "c"]
302 }
303 }
304};
305```
306
307**function**
308
309在 function 中,你可以构造你想要的数据、状态等任何你需要的结构。
310
311**示例**
312
313```javascript
314exports.data = async (ctx, next) => {
315 ctx.status = 200;
316 ctx.body = {
317 aaa: 123,
318 bbb: 234
319 };
320 await next();
321};
322```
323
324## 内部 rule
325
326在构造数据时,我们提供部分内部方法供你快速定义数据
327
328#### 简单方法
329
330**内置列表**
331
332| 参数 | 解释 | 返回数据类型 | 示例 |
333| :----------: | :--------: | :----------: | :----------------------------------: |
334| @id | id(8 位) | string | 64669287 |
335| @name | 姓名 | string | 李健龙 |
336| @province | 省份 | string | 湖北省 |
337| @phoneNumber | 电话号码 | string | 13888888888 |
338| @number | 1-100 整数 | number | 2 |
339| @price | 价格 | number | 388.00 |
340| @weekday | 星期 | string | Monday |
341| @month | 月份 | string | January |
342| @recentDate | 最近时间 | date | 2019-08-06T06:46:32.360Z |
343| @futureDate | 未来时间 | date | |
344| @pastDate | 过去时间 | date | |
345| @avatar | 头像 | string | |
346| @animals | 动物图片 | string | |
347| @sentences | 段落 | string | |
348| @lines | 一行文本 | string | |
349| @boolean | 布尔值 | boolean | true |
350| @uuid | uuid | string | 5c9b344b-a589-4efd-9c95-17508c0c0087 |
351
352**示例**
353
354```javascript
355exports.rules = {
356 books: {
357 a: "@number",
358 b: "2",
359 c: [1, 2, 3],
360 d: "@string"
361 }
362};
363```
364
365#### 复杂方法
366
367复杂方法中,需要用参数进行配置,参数说明如下:
368
369| 参数 | 解释 | 是否必填 | 数据类型 | 示例 |
370| :----------: | :--: | :------: | :------: | :-----: |
371| \_\_rule\_\_ | 标识 | 是 | string | '@list' |
372| params | 参数 | 是 | object | |
373
374**内置列表**
375
376| 参数 | 解释 | 返回数据类型 | 示例 |
377| :---: | :-----------: | :-----------: | :--: |
378| @enum | 枚举 | string/number | |
379| @list | 数组/数组对象 | array | |
380
381**列表详情**
382
383`list`:列表方法,返回一定长度的列表,params 中定义以下参数
384
385| 参数 | 解释 | 是否必填 | 数据类型 | 示例 |
386| :-----: | :----: | :------: | :------: | :--: |
387| number | 数量 | 否 | number | 3 |
388| payload | 子数据 | 是 | 任意类型 | |
389
390示例
391
392```javascript
393exports.rules = {
394 classrooms: {
395 __rule__: "@list",
396 params: {
397 number: 3,
398 payload: {
399 name: "@name"
400 }
401 }
402 }
403};
404```
405
406`enum`:枚举方法,返回定义的枚举之一,params 定义如下
407
408| 参数 | 解释 | 是否必填 | 数据类型 | 示例 |
409| :----: | :--: | :------: | :------: | :--: |
410| params | 参数 | 是 | array | |
411
412示例
413
414```javascript
415exports.rules = {
416 types: {
417 __rule__: "@enum",
418 params: [1, "@string", 3]
419 }
420};
421```
422
423## 自定义 rule
424
425非必须项,不需要可跳过
426
427#### 新建
428
429添加 `rule.js` 文件
430
431#### 添加规则
432
433- 在 [config](#config) 中添加 `rule` 字段
434- 通过 key-value 的方式添加规则,其中 key 为规则名,value 为方法
435
436**简单规则**
437
438既可以直接返回 number、 string 等**基本类型**,也可以返回 function**高级类型**
439
440基本类型示例
441
442```javascript
443module.exports = {
444 houses: {
445 a: 123,
446 b: "@string"
447 }
448};
449```
450
451高级类型示例
452
453```javascript
454module.exports = {
455 houses: function() {
456 return {
457 3: 3,
458 4: 4
459 };
460 }
461};
462```
463
464**复杂规则**
465
466当我们需要在方法中传递参数时,我们就需要使用**复杂规则**
467
468**示例**
469
470```javascript
471module.exports = {
472 houses: function(params) {
473 let payload = params.payload;
474 let number = params.number || 1;
475 return {
476 payload,
477 number
478 };
479 }
480};
481```
482
483此时的参数 `params` 便是我们在定义 [data 数据](#数据定义) 时添加的参数
484
485**组合使用**
486
487内置规则和自定义规则可以组合使用,进行数据构造
488
489**示例**
490
491定义规则:
492
493```javascript
494module.exports = {
495 houses: function() {
496 return {
497 3: {
498 __rule__: "@list",
499 params: {
500 payload: {
501 a: "@avatar"
502 }
503 }
504 },
505 4: 4
506 };
507 }
508};
509```
510
511组合使用:
512
513```javascript
514exports.data = {
515 errcode: 0,
516 errmsg: "",
517 data: {
518 a: "@houses",
519 b: "2",
520 c: [1, 2, 3],
521 d: "@string",
522 type: {
523 __rule__: "@enum", // 枚举
524 payload: ["数组", "b", "c"]
525 },
526 orders: {
527 name: "cheaa",
528 ids: {
529 __rule__: "@list", // 原子数组
530 number: 10,
531 payload: {
532 id: "@number",
533 name: "@string",
534 rooms: [1, 3],
535 books: {
536 __rule__: "@list",
537 number: 4,
538 payload: {
539 tags: {
540 __rule__: "@enum",
541 payload: [1, 2, 3]
542 }
543 }
544 }
545 }
546 }
547 }
548 }
549};
550```
551
552**接口作用域规则**
553
554你可以在定义 [data 数据](#data) 时添加当前接口作用域下的自定义规则
555
556```javascript
557exports.rules = {
558 a: function() {
559 return 1;
560 }
561};
562
563exports.data = {
564 data: {
565 name: "forchange",
566 desc: "@a"
567 }
568};
569```
570
571## label
572
573通过添加 label 标识,处理数据间的冲突问题
574`label` 字段对 http 服务和 socket 服务均支持
575
576#### 新建
577
578在 [config](#config) 中添加 `label` 字段
579新建文档时添加 `-l` 指令指定 `label` 或者手动添加 `&<你的 label 名>`
580
581#### 示例
582
583新建
584
585```
586$ fmock create './aaa/bbb' -l 'xindongdong'
587```
588
589你将会生成
590
591```tree
592mock
593├── data
594│   └── aaa
595│   ├── bbb#get&xindongdong.js
596```
597
598## flow
599
600特殊情况下,可能需要在多个接口之间进行数据的联动处理,你可以在定义 `data` 数据时添加 `flow` 字段
601
602#### 规定
603
604- 当上一次请求和当前请求中 `flow` 定义的 `method``route` 匹配时,我们会返回 `flow` 中定义的 `data 数据`
605- 如果当前 `flow` 字段中没有 `data` 字段我们将会强制返回本次请求的 `data` 数据,并抛出警告。
606
607#### 结构
608
609[]{method, route, data}
610
611| 参数 | 解释 | 是否必填 | 数据类型 |
612| :----: | :------------: | :------: | :------: |
613| method | 方法 | 是 | string |
614| route | 路由 | 是 | string |
615| data | 强制返回的数据 | 是 | object |
616
617#### 示例
618
619```javascript
620exports.flow = [
621 {
622 method: "get",
623 route: "/ambassador/courses",
624 data: {
625 a: "/ambassador/courses",
626 b: 234
627 }
628 },
629 {
630 method: "get",
631 route: "/ambassador/settlements",
632 data: {
633 a: "/ambassador/settlements",
634 b: 234
635 }
636 }
637];
638```
639
640## middleware
641
642#### 新建
643
644如果你需要自定义 middleware,你需要在 [config](#config) 中添加 `middleware` 字段
645
646#### 示例
647
648```
649middleware: [
650 async (ctx, next) => {
651 console.log('中间件运行 🐸🐸')
652 await next()
653 },
654 async (ctx, next) => {
655 console.log('中间件运行 🐸🐸')
656 await next()
657 }
658]
659```
660
661## socket
662
663#### 启动 socket 服务
664
665你可以在 [config](#config) 中添加 `socket` 字段开启 socket 服务
666
667#### 示例
668
669```
670socket: {
671 port: 端口号
672}
673```
674
675#### 连接
676
677当 socket 服务启动后,我们可以通过 `ws://host: 端口号/任意路由` 进行连接
678
679#### 管理
680
681当我们开启 socket 服务后,我们能通过 `host: 端口号/` 查看到所有 socket 连接情况
682你可以在此页面上进行连接、断开、发送消息等一系列操作,如图
683
684<img src="https://git.forchange.cn/newbility/fe-doc/uploads/b3f833df1ff20477393eb211b7862fac/image.png" width="500px" height= "200px"/>
685
686#### 添加自定义回复
687
688你可以在 [config](#config) `socket` 字段中添加 `directory` 字段处理 socket 自定义回复文件
689
690添加 `socket` 文件夹
691
692**我们规定:**
693
694- 文件路径即是你的路由(连接),如 `/aaa` 连接下对应的文件名为 `aaa.js`
695- 一个文件对应一种回应方式
696
697**示例**
698
699```javascript
700module.exports = async message => {
701 return {
702 name: "forchange",
703 message: message
704 };
705};
706```
707
708#### 添加 label
709
710参考 [label](#label)