1 | ## 描述
|
2 |
|
3 | mock 用于本地开发使用模拟数据。
|
4 | 与其他线上 mock 平台不同,本地 mock 能够更好地把握和及时修改数据,拥有更好的体验和更高的效率。
|
5 |
|
6 | #### 特点
|
7 |
|
8 | - 长链接
|
9 |
|
10 | - socket
|
11 |
|
12 | - 自定义错误状态
|
13 |
|
14 | - 接口之间的隔离
|
15 |
|
16 | - 接口之间可以联动处理(数据传递)
|
17 |
|
18 | - 简单易用,容易扩展
|
19 |
|
20 | #### 相对于 oock 的改动
|
21 |
|
22 | - 文件路径即是路由和方法,更好的体验
|
23 |
|
24 | - 强制定义一个接口一个文件,防止出现不必要的麻烦
|
25 |
|
26 | - 添加 socket 服务,支持连接、断开、服务端主动发送消息等
|
27 |
|
28 | - 添加自定义数据结构,简单生成大量数据
|
29 |
|
30 | - 添加数据传递处理
|
31 |
|
32 |
|
33 | ## 如何使用
|
34 |
|
35 | #### 示例目录结构如下
|
36 |
|
37 | <img src="https://git.forchange.cn/newbility/fe-doc/uploads/2218992756047b6b05228f9e3005e8f1/image.png" width="400px" height="300px"/>
|
38 |
|
39 | </br>
|
40 |
|
41 | - data: 数据文件
|
42 | - config.js: [config 配置](#配置) 入口
|
43 | - rule.js [自定义规则](#rule) 文件
|
44 |
|
45 | #### 安装
|
46 |
|
47 | `npm install @forchange/mock`
|
48 |
|
49 | or
|
50 |
|
51 | `yarn add @forchange/mock`
|
52 |
|
53 |
|
54 | #### 添加服务配置
|
55 |
|
56 | 在 `package.json` -> `scripts` 添加
|
57 |
|
58 | `"mock": "node index.js -c config地址"`
|
59 |
|
60 | e.g: `"mock": "node index.js -c ./mock/config.js"`
|
61 |
|
62 | #### 添加 config 配置
|
63 |
|
64 | 添加 `mock` 文件夹,文件夹下添加 `config.js` 文件
|
65 |
|
66 | 按照 [配置](#配置) 进行配置
|
67 |
|
68 | #### 添加 data 数据
|
69 |
|
70 | 👉 [mock](#mock)
|
71 |
|
72 | #### 添加 rule 规则
|
73 |
|
74 | mock 文件夹下添加 `rule.js` 文件
|
75 |
|
76 | 按照 [rule 规则](#rule) 添加自定义规则
|
77 |
|
78 | #### 起服务
|
79 |
|
80 | `yarn mock`
|
81 |
|
82 |
|
83 | ## 配置
|
84 |
|
85 | #### 在 `mock` 文件夹下添加 'config.js' 文件
|
86 |
|
87 | #### 文档说明,参考 👉
|
88 |
|
89 | | 参数 | 解释 | 是否必填 | 数据类型 | 默认 |
|
90 | | :--------: | :----------: | :------: | :------: | :-------: |
|
91 | | host | | 是 | string | '0.0.0.0' |
|
92 | | port | 端口 | 是 | number | 3000 |
|
93 | | directory | data 文件夹 | 是 | string | |
|
94 | | socket | socket 配置 | 否 | object | {} |
|
95 | | middleware | 自定义中间件 | 否 | array | |
|
96 | | rule | 自定义规则文件 | 否 | string | './rule.js' |
|
97 | | watch | 监听 | 否 | boolean | |
|
98 | | httpsPort | https端口 | 否 | String | 443 |
|
99 | | tls | | 否 | boolean | false |
|
100 | | key | 私钥文件 | 否 | string | |
|
101 |
|
102 | ## mock
|
103 |
|
104 | 在 oock 的基础上我们改变了文件分层以及路由处理方式
|
105 |
|
106 | **我们强制定义了以下几条规则:**
|
107 |
|
108 | - 一个接口一个文件
|
109 | - 文件路径即路由和方法
|
110 |
|
111 | **添加文件方式**
|
112 |
|
113 | 我们通过文件的层级划分来定义路由和方法
|
114 |
|
115 | 例如:如果你的路由为 `/v2/address/email` 请求方法为 `GET`
|
116 | 那么你的文件层级应该如下:
|
117 |
|
118 | <img src="https://git.forchange.cn/newbility/fe-doc/uploads/8e91d5eb1a4cacd87ec3c1e0be55d4ca/image.png" />
|
119 |
|
120 | </br >
|
121 |
|
122 | > 接口的最后一级路径加上请求方法即是文件名
|
123 | > 没有请求方法将不会解析成功
|
124 |
|
125 |
|
126 | **我们有两种数据定义方式: data 数据、 function 中间件**
|
127 |
|
128 | 在 [koa-router](https://www.npmjs.com/package/koa-router#module_koa-router--Router+param) 处理路由时,参数为 middleware ,所以传入 data 数据我们将会在内部处理为 midddleware 中间件 -->
|
129 |
|
130 | - data 数据
|
131 |
|
132 | 直接定义 data 数据。我们将会获取到数据中的 data 字段,并且返回。
|
133 |
|
134 | ```
|
135 | module.exports = {
|
136 | flow: [{
|
137 | method: 'get',
|
138 | route: '/ambassador/courses',
|
139 | data : {
|
140 | a:'abc',
|
141 | email: 'abc@forchange.tech',
|
142 | b:123
|
143 | }
|
144 | }],
|
145 | data: {
|
146 | a: '@number',
|
147 | b: '2',
|
148 | c: [1, 2, 3],
|
149 | d: '@string',
|
150 | type: {
|
151 | // 枚举
|
152 | __rule__: "@enum",
|
153 | payload: ['数组', 'b', 'c']
|
154 | },
|
155 | },
|
156 | }
|
157 | ```
|
158 |
|
159 | 在上面的例子中我们使用了自定义的 rule 规则进行数据构造,请参考 👉:[rule 规则](#rule)
|
160 |
|
161 | > 如果你不需要使用 rule 规则进行定义,按照常规定义数据即可
|
162 |
|
163 | 如果你希望进行数据联动,在访问一个接口的前提下访问当前接口获取特定数据,请参考 [flow](#flow)
|
164 |
|
165 | - function 中间件
|
166 |
|
167 | ```
|
168 | module.exports = async (ctx, next) => {
|
169 | ctx.status = 200
|
170 | ctx.body = {
|
171 | aaa: 123,
|
172 | bbb: 234
|
173 | }
|
174 | await next()
|
175 | }
|
176 | ```
|
177 |
|
178 | ## socket
|
179 |
|
180 | #### 如果你想开启 socket 服务,你可以在 [config 配置](#配置) 中添加 `socket` 字段开启 socket 服务
|
181 |
|
182 | ```
|
183 | socket: {
|
184 | port: 端口号
|
185 | }
|
186 | ```
|
187 |
|
188 | 🚗🚗🚗☁️☁️☁️未完待续...
|
189 |
|
190 | ## rule
|
191 |
|
192 | #### 你可以在定义 `data` 数据时添加自定义的 `rule` 文件进行规则定义。
|
193 |
|
194 | :::tip
|
195 | 此时你需要在 [配置](#配置) 中添加 `rule` 配置,不然将不会生效
|
196 | 如果自定义字段没有找到规则我们将不会解析
|
197 | 如果自定义方法和内置方法相同我们将会进行强制覆盖
|
198 | :::
|
199 |
|
200 | e.g:
|
201 |
|
202 | ```
|
203 | module.exports = {
|
204 | houses: function(req) {
|
205 | return {
|
206 | 3:3,
|
207 | 4:4
|
208 | };
|
209 | }
|
210 | };
|
211 | ```
|
212 |
|
213 | #### 在定义 data 数据是便可使用 rule 规则进行数据构造
|
214 |
|
215 | ```
|
216 | module.exports = {
|
217 | flow: [{
|
218 | method: 'get',
|
219 | route: '/ambassador/courses',
|
220 | data : {
|
221 | a:'abc',
|
222 | email: 'abc@forchange.tech',
|
223 | b:123
|
224 | }
|
225 | }],
|
226 | data: {
|
227 | a: '@number',
|
228 | b: '2',
|
229 | c: [1, 2, 3],
|
230 | d: '@string',
|
231 | type: {
|
232 | // 枚举
|
233 | __rule__: "@enum",
|
234 | payload: ['数组', 'b', 'c']
|
235 | },
|
236 | orders: {
|
237 | name: "cheaa",
|
238 | ids: {
|
239 | // 原子数组
|
240 | __rule__: "@list",
|
241 | number: 10,
|
242 | payload: {
|
243 | id: '@number',
|
244 | name: '@string',
|
245 | rooms: [1, 3],
|
246 | books: {
|
247 | __rule__: "@list",
|
248 | number: 4,
|
249 | payload: {
|
250 | tags: {
|
251 | __rule__: "@enum",
|
252 | payload: [1,2,3]
|
253 | }
|
254 | }
|
255 | }
|
256 | }
|
257 | }
|
258 | },
|
259 | },
|
260 | }
|
261 | ```
|
262 |
|
263 | ### 对于复杂类型,我们需要进行特殊的规则处理
|
264 |
|
265 | #### 内部方法表:
|
266 | | 参数 | 解释 | 数据类型 |
|
267 | | :--------: | :----------: | :------: |
|
268 | | @string | 字符串 | string |
|
269 | | @address | 地址 | string |
|
270 | | @name | 姓名 | string |
|
271 | | @month | 月份 | string |
|
272 | | @number | 数字 | number |
|
273 | | @enum | 枚举 | array |
|
274 | | @list | 数组/数组对象 | array |
|
275 |
|
276 | ## flow
|
277 |
|
278 | #### 你可以在定义 `data` 数据时添加 `flow` 字段来处理接口之间的联动
|
279 |
|
280 | 我们规定,当你当前请求的上一次请求和 `flow` 中定义的 `method`、`route` 相匹配,将会将 `data` 中的数据作为该次请求的返回。
|
281 |
|
282 | 如果当前 `flow` 字段中没有 `data` 我们将会强制返回本次请求的 `data` 数据,并抛出警告。
|
283 |
|
284 | > flow 字段类型为 array
|
285 |
|
286 | | 参数 | 解释 | 是否必填 | 数据类型 |
|
287 | | :--------: | :----------: | :------: | :------: |
|
288 | | method | 方法 | 是 | string |
|
289 | | route | 路由 | 是 | string |
|
290 | | data | 强制返回的数据 | 是 | object |
|
291 |
|
292 | ```
|
293 | flow: [{
|
294 | method: 'get',
|
295 | route: '/ambassador/courses',
|
296 | data : {
|
297 | a:faker.name.findName(),
|
298 | email: faker.internet.email(),
|
299 | randomCard: faker.database.type(),
|
300 | b:faker.date.month()
|
301 | }
|
302 | }, {
|
303 | method: 'get',
|
304 | route: '/ambassador/settlements',
|
305 | data: {
|
306 | a: '/ambassador/settlements',
|
307 | b: 234
|
308 | }
|
309 | }],
|
310 | ```
|
311 |
|
312 | ## middleware 中间件
|
313 |
|
314 | #### 如果你需要自定义中间件,你需要在 [配置](#配置) 中添加 `middleware` 字段
|
315 |
|
316 | > middleware 字段类型为 array
|
317 |
|
318 | 我们将会在 koa 服务中解析中间件,所以 array 数组的每一项均是一个 middleware
|
319 |
|
320 | ## example
|