vite-plugin-mock-dev-server 0.3.0 → 0.3.3

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.
@@ -0,0 +1,405 @@
1
+ # vite-plugin-mock-dev-server
2
+
3
+ <br>
4
+ <br>
5
+ <p align="center">vite mock开发服务(mock-dev-server)插件。</p>
6
+
7
+ <p align="center">在 vite 开发环境中,注入一个 mock-dev-server。</p>
8
+
9
+ <br>
10
+ <p align="center">
11
+ <a href="https://www.npmjs.com/package/vite-plugin-mock-dev-server"><img alt="npm" src="https://img.shields.io/npm/v/vite-plugin-mock-dev-server?style=flat-square"></a>
12
+ <img alt="node-current" src="https://img.shields.io/node/v/vite-plugin-mock-dev-server?style=flat-square">
13
+ <img alt="GitHub package.json dependency version (prod)" src="https://img.shields.io/github/package-json/dependency-version/pengzhanbo/vite-plugin-mock-dev-server/vite?style=flat-square">
14
+ <img alt="NPM" src="https://img.shields.io/npm/l/vite-plugin-mock-dev-server?style=flat-square">
15
+ </p>
16
+ <br>
17
+ <p align="center">
18
+ <a href="/README.md">English</a> | <span>简体中文</span>
19
+ </p>
20
+ <br>
21
+ <br>
22
+
23
+ ## 特性
24
+
25
+ - ⚡️ 轻量,灵活,快速
26
+ - 🧲 非注入式,对客户端代码无侵入
27
+ - 💡 ESModule/commonjs
28
+ - 🦾 Typescript
29
+ - 🏷 支持 json / json5 编写 mock 数据
30
+ - 📦 自动加载 mock 文件
31
+ - 🎨 可选择你喜欢的任意用于生成mock数据库,如 `mockjs`,或者不是用其他库
32
+ - 📥 路径规则匹配,请求参数匹配
33
+ - ⚙️ 随意开启或关闭对某个接口的 mock配置
34
+ - 🔥 热更新
35
+ - ⚖️ 使用 `server.proxy` 配置
36
+ - 🍕 支持在 mock文件中使用 `viteConfig.define`配置字段
37
+
38
+
39
+ ## 使用
40
+
41
+ ### 安装
42
+
43
+ ```sh
44
+ # npm
45
+ npm i -D vite-plugin-mock-dev-server
46
+ # yarn
47
+ yarn add vite-plugin-mock-dev-server
48
+ # pnpm
49
+ pnpm add -D vite-plugin-mock-dev-server
50
+ ```
51
+
52
+ ### 配置
53
+
54
+ `vite.config.ts`
55
+ ```ts
56
+ import { defineConfig } from 'vite'
57
+ import mockDevServerPlugin from 'vite-plugin-mock-dev-server'
58
+
59
+ export default defineConfig({
60
+ plugins: [
61
+ mockDevServerPlugin(),
62
+ ],
63
+ // 这里定义的字段,在mock中也能使用
64
+ define: {},
65
+ server: {
66
+ proxy: {
67
+ '^/api': {
68
+ target: 'http://example.com'
69
+ }
70
+ }
71
+ }
72
+ })
73
+ ```
74
+ 插件会读取 `server.proxy` 的配置, 仅对设置了代理的 url 匹配,启用mock 匹配。
75
+
76
+ 插件也会读取 `define` 配置, 支持在 mock 文件中直接使用。
77
+
78
+ > 因为一般场景下,我们只需要对有代理的url进行mock,这样才能通过 vite 提供的 http 服务进行 代理和 mock
79
+
80
+ ### 编写mock文件
81
+
82
+ 默认配置,在你的项目根目录的 `mock` 目录中编写mock数据:
83
+
84
+ `mock/api.mock.ts` :
85
+ ```ts
86
+ import { defineMock } from 'vite-plugin-mock-dev-server'
87
+
88
+ export default defineMock({
89
+ url: '/api/test',
90
+ body: {
91
+ a: 1,
92
+ b: 2,
93
+ }
94
+ })
95
+ ```
96
+
97
+ ## 方法
98
+
99
+ ### mockDevServerPlugin(options)
100
+
101
+ vite plugin
102
+
103
+
104
+ `vite.config.ts`
105
+ ```ts
106
+ import { defineConfig } from 'vite'
107
+ import mockDevServerPlugin from 'vite-plugin-mock-dev-server'
108
+
109
+ export default defineConfig({
110
+ plugins: [
111
+ mockDevServerPlugin(),
112
+ ]
113
+ })
114
+ ```
115
+
116
+ #### options
117
+
118
+ - `option.include`
119
+
120
+ 配置读取 mock文件,可以是一个 目录,glob,或者一个数组
121
+
122
+ 默认值: `['mock/**/*.mock.{js,ts,cjs,mjs,json,json5}']` (相对于根目录)
123
+
124
+ - `options.exclude`
125
+
126
+ 配置读取 mock文件时,需要排除的文件, 可以是一个 目录、glob、或者一个数组
127
+
128
+ 默认值:`['**/node_modules/**','**/test/**','**/cypress/**','src/**','**/.vscode/**','**/.git/**','**/dist/**',]`
129
+
130
+
131
+ ### defineMock(config)
132
+
133
+ mock 配置帮助函数,提供类型检查帮助
134
+
135
+ ```ts
136
+ import { defineMock } from 'vite-plugin-mock-dev-server'
137
+
138
+ export default defineMock({
139
+ url: '/api/test',
140
+ body: {}
141
+ })
142
+ ```
143
+
144
+ ## Mock 配置
145
+
146
+ ```ts
147
+ export default defineMock({
148
+ /**
149
+ * 请求地址,支持 `/api/user/:id` 格式
150
+ */
151
+ url: '/api/test',
152
+ /**
153
+ * 接口支持的请求方法
154
+ *
155
+ * @type string | string[]
156
+ * @default ['POST','GET']
157
+ *
158
+ */
159
+ method: ['GET', 'POST'],
160
+ /**
161
+ * 是否启用当前 mock请求
162
+ *
163
+ * 在实际场景中,我们一般只需要某几个mock接口生效,
164
+ * 而不是所以mock接口都启用。
165
+ * 对当前不需要mock的接口,可设置为 false
166
+ *
167
+ * @default true
168
+ */
169
+ enable: true,
170
+ /**
171
+ * 设置接口响应延迟, 单位:ms
172
+ *
173
+ * @default 0
174
+ */
175
+ delay: 1000,
176
+ /**
177
+ * 响应状态码
178
+ *
179
+ * @default 200
180
+ */
181
+ status: 200,
182
+ /**
183
+ * 响应状态文本
184
+ */
185
+ statusText: 'OK',
186
+ /**
187
+ * 请求验证器,通过验证器则返回 mock数据,否则不是用当前mock。
188
+ * 这对于一些场景中,某个接口需要通过不同的入参来返回不同的数据,
189
+ * 验证器可以很好的解决这一类问题,将同个 url 分为多个 mock配置,
190
+ * 根据 验证器来判断哪个mock配置生效。
191
+ *
192
+ * @type { header?: object; body?: object; query?: object; params?: object }
193
+ *
194
+ * 如果 validator 传入的是一个对象,那么验证方式是严格比较 请求的接口
195
+ * 中,headers/body/query/params 的各个`key`的`value`是否全等,
196
+ * 全等则校验通过
197
+ *
198
+ * @type ({ header: object; body: object; query: object; params: object }) => boolean
199
+ * 如果 validator 传入的是一个函数,那么会讲 请求的接口相关数据作为入参,提供给使用者进行自定义校验,并返回一个 boolean
200
+ *
201
+ */
202
+ validator: {
203
+ headers: {},
204
+ body: {},
205
+ query: {},
206
+ params: {},
207
+ },
208
+ /**
209
+ *
210
+ * 响应状态 headers
211
+ *
212
+ * @type Record<string, any>
213
+ *
214
+ * @type (({ query, body, params, headers }) => Record<string, any>)
215
+ * 入参部分为 请求相关信息
216
+ */
217
+ headers: {
218
+ 'Content-Type': 'application/json'
219
+ },
220
+
221
+ /**
222
+ * 响应体数据
223
+ * 定义返回的响应体数据内容。
224
+ * 在这里,你可以直接返回JavaScript支持的数据类型如 `string/number/array/object` 等
225
+ * 同时,你也可以使用如 `mockjs` 等库来生成数据内容
226
+ *
227
+ * @type string | number | array | object
228
+ * 直接返回定义的数据
229
+ *
230
+ * @type (request: { header, query, body, params }) => any | Promise<any>
231
+ * 如果传入一个函数,那么可以更加灵活的定义返回响应体数据
232
+ */
233
+ body: {},
234
+
235
+ /**
236
+ * 如果通过 body 配置不能解决mock需求,
237
+ * 那么可以通过 配置 response,暴露http server 的接口,
238
+ * 实现完全可控的自定义配置
239
+ *
240
+ * 在 req参数中,已内置了 query、body、params 的解析,
241
+ * 你可以直接使用它们
242
+ *
243
+ * 别忘了,需要通过 `res.end()` 返回响应体数据,
244
+ * 或者需要跳过mock,那么别忘了调用 `next()`
245
+ */
246
+ response(req, res, next) {
247
+ res.end()
248
+ }
249
+ })
250
+
251
+ ```
252
+
253
+ > 注意:
254
+ >
255
+ > 如果使用 json/json5 编写 mock文件,则不支持使用 `response` 方法,以及不支持使用其他字段的函数形式。
256
+
257
+ `mock/**/*.mock.{ts,js,mjs,cjs,json,json5}`
258
+
259
+ 查看更多示例: [example](/example/)
260
+
261
+ #### 示例1:
262
+ 命中 `/api/test` 请求,并返回一个 数据为空的响应体内容
263
+ ```ts
264
+ export default defineMock({
265
+ url: '/api/test',
266
+ })
267
+ ```
268
+
269
+ #### 示例2:
270
+ 命中 `/api/test` 请求,并返回一个固定内容数据
271
+ ```ts
272
+ export default defineMock({
273
+ url: '/api/test',
274
+ body: {
275
+ a: 1
276
+ }
277
+ })
278
+ ```
279
+
280
+ #### 示例3:
281
+ 限定只允许 `GET` 请求
282
+ ```ts
283
+ export default defineMock({
284
+ url: '/api/test',
285
+ method: 'GET'
286
+ })
287
+ ```
288
+
289
+ #### 示例4:
290
+ 在返回的响应头中,添加自定义header
291
+ ```ts
292
+ export default defineMock({
293
+ url: '/api/test',
294
+ headers: {
295
+ 'X-Custom': '12345678'
296
+ }
297
+ })
298
+ ```
299
+ ```ts
300
+ export default defineMock({
301
+ url: '/api/test',
302
+ headers({ query, body, params, headers }) {
303
+ return {
304
+ 'X-Custom': query.custom
305
+ }
306
+ }
307
+ })
308
+ ```
309
+
310
+ #### 示例5:
311
+ 定义多个相同url请求mock,并使用验证器匹配生效规则
312
+ ```ts
313
+ export default defineMock([
314
+ // 命中 /api/test?a=1
315
+ {
316
+ url: '/api/test',
317
+ validator: {
318
+ query: {
319
+ a: 1
320
+ }
321
+ },
322
+ body: {
323
+ message: 'query.a === 1'
324
+ }
325
+ },
326
+ // 命中 /api/test?a=2
327
+ {
328
+ url: '/api/test',
329
+ validator: {
330
+ query: {
331
+ a: 2
332
+ }
333
+ },
334
+ body: {
335
+ message: 'query.a === 2'
336
+ }
337
+ }
338
+ ])
339
+ ```
340
+
341
+ #### 示例6:
342
+ 延迟接口响应:
343
+ ```ts
344
+ export default defineMock({
345
+ url: '/api/test',
346
+ delay: 6000, // 延迟 6秒
347
+ })
348
+ ```
349
+
350
+ #### 示例7:
351
+ 使接口请求失败
352
+ ```ts
353
+ export default defineMock({
354
+ url: '/api/test',
355
+ status: 504,
356
+ statusText: 'Bad Gateway'
357
+ })
358
+ ```
359
+
360
+ #### 示例8:
361
+ 使用 `mockjs` 生成响应数据:
362
+ ```ts
363
+ import Mock from 'mockjs'
364
+ export default defineMock({
365
+ url: '/api/test',
366
+ body: Mock.mock({
367
+ 'list|1-10': [{
368
+ 'id|+1': 1
369
+ }]
370
+ })
371
+ })
372
+ ```
373
+ 请先安装 `mockjs`
374
+
375
+ ### 示例9:
376
+ 使用 `response` 自定义响应
377
+ ```ts
378
+ export default defineMock({
379
+ url: '/api/test',
380
+ response(req, res, next) {
381
+ const { query, body, params, headers } = req
382
+ console.log(query, body, params, headers)
383
+
384
+ res.status = 200
385
+ res.setHeader('Content-Type', 'application/json')
386
+ res.end(JSON.stringify({
387
+ query,
388
+ body,
389
+ params,
390
+ }))
391
+ }
392
+ })
393
+ ```
394
+
395
+ ### 示例10:
396
+ 使用 json / json5
397
+ ```json
398
+ {
399
+ // 支持 comment
400
+ "url": "/api/test",
401
+ "body": {
402
+ "a": 1
403
+ }
404
+ }
405
+ ```
package/dist/index.cjs CHANGED
@@ -146,26 +146,24 @@ var _MockLoader = class extends import_node_events.default {
146
146
  }
147
147
  watchDeps() {
148
148
  const oldDeps = [];
149
+ this.depsWatcher = import_chokidar.default.watch([], {
150
+ ignoreInitial: true,
151
+ cwd: this.cwd
152
+ });
153
+ this.depsWatcher.on("change", (filepath) => {
154
+ const mockFiles = this.moduleDeps.get(filepath);
155
+ mockFiles && mockFiles.forEach((file) => {
156
+ this.emit("mock:update", file);
157
+ });
158
+ });
159
+ this.depsWatcher.on("unlink", (filepath) => {
160
+ this.moduleDeps.delete(filepath);
161
+ });
149
162
  this.on("update:deps", () => {
150
163
  const deps = [];
151
164
  for (const [dep] of this.moduleDeps.entries()) {
152
165
  deps.push(dep);
153
166
  }
154
- if (!this.depsWatcher && deps.length > 0) {
155
- this.depsWatcher = import_chokidar.default.watch(deps, {
156
- ignoreInitial: true,
157
- cwd: this.cwd
158
- });
159
- this.depsWatcher.on("change", (filepath) => {
160
- const mockFiles = this.moduleDeps.get(filepath);
161
- mockFiles && mockFiles.forEach((file) => {
162
- this.emit("mock:update", file);
163
- });
164
- });
165
- this.depsWatcher.on("unlink", (filepath) => {
166
- this.moduleDeps.delete(filepath);
167
- });
168
- }
169
167
  const exactDeps = deps.filter((dep) => !oldDeps.includes(dep));
170
168
  exactDeps.length > 0 && this.depsWatcher.add(exactDeps);
171
169
  });
@@ -476,7 +474,9 @@ function mockDevServerPlugin({
476
474
  }
477
475
 
478
476
  // src/define.ts
479
- var defineMock = (config) => config;
477
+ function defineMock(config) {
478
+ return config;
479
+ }
480
480
 
481
481
  // src/index.ts
482
482
  var src_default = mockDevServerPlugin;
package/dist/index.d.ts CHANGED
@@ -112,16 +112,21 @@ declare type MockOptions = MockOptionsItem[];
112
112
  declare function mockDevServerPlugin({ include, exclude, }?: MockServerPluginOptions): Plugin;
113
113
 
114
114
  /**
115
+ * mock config helper
116
+ *
115
117
  * mock配置帮助函数
118
+ *
116
119
  * @param config
117
120
  * @example
118
121
  * ```ts
119
122
  * export default defineMock({
120
123
  * url: '/api/example',
124
+ * method: ['GET', 'POST'],
121
125
  * body: { a: 1 },
122
126
  * })
123
127
  * ```
124
128
  */
125
- declare const defineMock: (config: MockOptionsItem | MockOptions) => MockOptionsItem | MockOptions;
129
+ declare function defineMock(config: MockOptionsItem): MockOptionsItem;
130
+ declare function defineMock(config: MockOptions): MockOptions;
126
131
 
127
132
  export { MockOptions, MockOptionsItem, MockServerPluginOptions, mockDevServerPlugin as default, defineMock, mockDevServerPlugin };
package/dist/index.js CHANGED
@@ -111,26 +111,24 @@ var _MockLoader = class extends EventEmitter {
111
111
  }
112
112
  watchDeps() {
113
113
  const oldDeps = [];
114
+ this.depsWatcher = chokidar.watch([], {
115
+ ignoreInitial: true,
116
+ cwd: this.cwd
117
+ });
118
+ this.depsWatcher.on("change", (filepath) => {
119
+ const mockFiles = this.moduleDeps.get(filepath);
120
+ mockFiles && mockFiles.forEach((file) => {
121
+ this.emit("mock:update", file);
122
+ });
123
+ });
124
+ this.depsWatcher.on("unlink", (filepath) => {
125
+ this.moduleDeps.delete(filepath);
126
+ });
114
127
  this.on("update:deps", () => {
115
128
  const deps = [];
116
129
  for (const [dep] of this.moduleDeps.entries()) {
117
130
  deps.push(dep);
118
131
  }
119
- if (!this.depsWatcher && deps.length > 0) {
120
- this.depsWatcher = chokidar.watch(deps, {
121
- ignoreInitial: true,
122
- cwd: this.cwd
123
- });
124
- this.depsWatcher.on("change", (filepath) => {
125
- const mockFiles = this.moduleDeps.get(filepath);
126
- mockFiles && mockFiles.forEach((file) => {
127
- this.emit("mock:update", file);
128
- });
129
- });
130
- this.depsWatcher.on("unlink", (filepath) => {
131
- this.moduleDeps.delete(filepath);
132
- });
133
- }
134
132
  const exactDeps = deps.filter((dep) => !oldDeps.includes(dep));
135
133
  exactDeps.length > 0 && this.depsWatcher.add(exactDeps);
136
134
  });
@@ -441,7 +439,9 @@ function mockDevServerPlugin({
441
439
  }
442
440
 
443
441
  // src/define.ts
444
- var defineMock = (config) => config;
442
+ function defineMock(config) {
443
+ return config;
444
+ }
445
445
 
446
446
  // src/index.ts
447
447
  var src_default = mockDevServerPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-mock-dev-server",
3
- "version": "0.3.0",
3
+ "version": "0.3.3",
4
4
  "keywords": [
5
5
  "vite",
6
6
  "plugin",
@@ -66,6 +66,9 @@
66
66
  "typescript": "^4.8.4",
67
67
  "vite-plugin-mock-dev-server": "file:"
68
68
  },
69
+ "peerDependencies": {
70
+ "vite": ">=3.0.0"
71
+ },
69
72
  "packageManager": "pnpm@7.14.0",
70
73
  "engines": {
71
74
  "node": ">=16"