mocksw 1.0.0 → 1.1.1
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.md +76 -26
- package/dist/index.js +2 -7
- package/package.json +2 -2
- package/public/swMockWorker.js +7 -5
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# mocksw
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/mocksw)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
3
6
|
一个基于 Service Worker 的轻量级、零侵入 API 模拟工具。通过在 Service Worker 层拦截 fetch 请求,实现在本地开发环境中快速模拟 API 响应。
|
|
4
7
|
|
|
5
8
|
## ✨ 特性
|
|
@@ -14,28 +17,31 @@
|
|
|
14
17
|
|
|
15
18
|
```sh
|
|
16
19
|
npm install mocksw -D
|
|
20
|
+
# or
|
|
21
|
+
npm install mocksw -D
|
|
17
22
|
```
|
|
18
23
|
|
|
19
24
|
## 🚀 快速开始
|
|
20
25
|
|
|
21
|
-
### 1. 初始化
|
|
26
|
+
### 1. 初始化 Worker 环境
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
在你的项目根目录下运行初始化命令:
|
|
24
29
|
|
|
25
30
|
```sh
|
|
26
31
|
npx mocksw init public
|
|
32
|
+
# or
|
|
33
|
+
pnpm exec mocksw init public
|
|
27
34
|
```
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
这将在指定的目录 `public` 下生成 `swMockWorker.js` worker环境。
|
|
30
37
|
|
|
31
|
-
### 2.
|
|
38
|
+
### 2. 定义 Mock 接口
|
|
32
39
|
|
|
33
40
|
在你的应用入口文件(如 `main.ts` 或 `index.ts`)中进行配置:
|
|
34
41
|
|
|
35
42
|
```js
|
|
36
43
|
import { httpRequest } from 'mocksw';
|
|
37
|
-
|
|
38
|
-
// 定义 Mock 接口
|
|
44
|
+
// 定义简单的 Mock 接口
|
|
39
45
|
httpRequest.post('/api/user/login', async ({ body }, res) => {
|
|
40
46
|
const { username, password } = body;
|
|
41
47
|
// 模拟延迟 1000ms
|
|
@@ -51,22 +57,25 @@ httpRequest.post('/api/user/login', async ({ body }, res) => {
|
|
|
51
57
|
msg: 'success',
|
|
52
58
|
});
|
|
53
59
|
});
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```js
|
|
61
|
-
// 初始化 Mock 环境 指定域名进行拦截 推荐在 Vue 实例挂载后初始化
|
|
62
|
-
httpRequest.init('www.vadmin.test.com').then(() => {
|
|
63
|
-
console.log('🚀 完美 Mock 环境已就绪');
|
|
64
|
-
// 挂载 Vue 实例 推荐在 init 后挂载
|
|
65
|
-
app.mount('#app');
|
|
60
|
+
// 初始化并指定拦截域名
|
|
61
|
+
httpRequest.init('www.api-server.com').then(() => {
|
|
62
|
+
console.log('🚀 Mock 环境已就绪');
|
|
63
|
+
app.mount('#app'); // 建议在 init 成功后挂载应用
|
|
64
|
+
// 现在这个接口调用会被拦截 并返回模拟响应
|
|
65
|
+
login();
|
|
66
66
|
});
|
|
67
|
-
```
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
function login() {
|
|
69
|
+
axios
|
|
70
|
+
.post('http://www.vadmin.test.com/user/login', {
|
|
71
|
+
username: 'admin',
|
|
72
|
+
password: '123456',
|
|
73
|
+
})
|
|
74
|
+
.then(res => {
|
|
75
|
+
console.log(res.data);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
```
|
|
70
79
|
|
|
71
80
|
## 📖 API 说明
|
|
72
81
|
|
|
@@ -87,6 +96,7 @@ httpRequest.init('www.vadmin.test.com').then(() => {
|
|
|
87
96
|
- `query`:URL 查询参数对象
|
|
88
97
|
- `headers`:原生请求头
|
|
89
98
|
- `method`:请求方法(如 GET、POST 等)
|
|
99
|
+
- `headers`:原生请求头
|
|
90
100
|
|
|
91
101
|
`MockResponse` (回调第二个参数)
|
|
92
102
|
|
|
@@ -95,15 +105,55 @@ httpRequest.init('www.vadmin.test.com').then(() => {
|
|
|
95
105
|
- `delay(ms)`:延迟响应指定毫秒数 支持链式调用
|
|
96
106
|
- `status(code)`:设置 HTTP 状态码(默认 200)支持链式调用
|
|
97
107
|
|
|
98
|
-
## 🛠️
|
|
108
|
+
## 🛠️ 结合web数据库模拟真实后端
|
|
99
109
|
|
|
100
110
|
由于拦截器运行在主线程环境,你可以轻松结合 IndexedDB 进行增删改查:
|
|
101
111
|
|
|
102
112
|
```ts
|
|
103
|
-
|
|
104
|
-
httpRequest.
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
113
|
+
// 登录接口
|
|
114
|
+
httpRequest.post('/user/login', async (req, res) => {
|
|
115
|
+
// 获取请求体中的用户名和密码
|
|
116
|
+
const { username, password } = req.body;
|
|
117
|
+
// 从数据库中查询用户
|
|
118
|
+
const user = await db.users.where({ name: username, password: password }).first();
|
|
119
|
+
// 如果用户不存在 则返回错误响应
|
|
120
|
+
if (!user) return res.json({ code: 500, message: '账号或密码不匹配' });
|
|
121
|
+
// 生成 token 并存储到数据库
|
|
122
|
+
const createToken = 'tk_' + Date.now();
|
|
123
|
+
if (user) {
|
|
124
|
+
user.token = createToken;
|
|
125
|
+
await db.users.update(user.id, user);
|
|
126
|
+
await db.tokens.add({ token: createToken });
|
|
127
|
+
// 登录成功后返回 token
|
|
128
|
+
return res.json({ code: 200, data: { token: createToken } });
|
|
129
|
+
}
|
|
108
130
|
});
|
|
131
|
+
// 获取用户信息接口
|
|
132
|
+
httpRequest.get('/user/getInfo', async (req, res) => {
|
|
133
|
+
const token = getHeadersToken(req);
|
|
134
|
+
if (!token) return res.json({ code: 500, message: '未登录' });
|
|
135
|
+
const tokenInfo = await db.tokens.where({ token: token }).first();
|
|
136
|
+
if (!tokenInfo) return res.json({ code: 500, message: 'token 无效' });
|
|
137
|
+
const user = await db.users.where({ token: token }).first();
|
|
138
|
+
if (!user) return res.json({ code: 500, message: '用户不存在' });
|
|
139
|
+
// 模拟延迟 500ms
|
|
140
|
+
return res.delay(500).json({ code: 200, data: Object.assign({}, user, { token: undefined }) });
|
|
141
|
+
});
|
|
142
|
+
// 登出接口
|
|
143
|
+
httpRequest.post('/user/logout', async (req, res) => {
|
|
144
|
+
const token = getHeadersToken(req);
|
|
145
|
+
if (token) {
|
|
146
|
+
await db.tokens.where({ token }).delete();
|
|
147
|
+
const user = await db.users.where({ token }).first();
|
|
148
|
+
if (!user) return res.json({ code: 500, message: '用户不存在' });
|
|
149
|
+
user.token = '';
|
|
150
|
+
await db.users.update(user.id, user);
|
|
151
|
+
}
|
|
152
|
+
return res.json({ code: 200, message: '登出成功' });
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
function getHeadersToken(req) {
|
|
156
|
+
const authHeader = req.headers['authorization'] || req.headers['Authorization'];
|
|
157
|
+
return authHeader?.replace('Bearer ', '');
|
|
158
|
+
}
|
|
109
159
|
```
|
package/dist/index.js
CHANGED
|
@@ -92,19 +92,14 @@ var MockClient = class {
|
|
|
92
92
|
});
|
|
93
93
|
navigator.serviceWorker.addEventListener("message", async (event) => {
|
|
94
94
|
if (event.data.type === "MSW_SIMULATE_REQUEST") {
|
|
95
|
-
const { method, url
|
|
95
|
+
const { method, url } = event.data.data;
|
|
96
96
|
const port = event.ports[0];
|
|
97
97
|
const handlerKey = `${method}:${url}`;
|
|
98
98
|
const handler = this.handlers.get(handlerKey);
|
|
99
99
|
if (!port) return;
|
|
100
100
|
if (handler) {
|
|
101
101
|
const res = new ResponseActions(port);
|
|
102
|
-
await handler({
|
|
103
|
-
url,
|
|
104
|
-
method,
|
|
105
|
-
body,
|
|
106
|
-
query
|
|
107
|
-
}, res);
|
|
102
|
+
await handler(Object.assign({}, event.data.data), res);
|
|
108
103
|
} else port.postMessage({
|
|
109
104
|
body: { error: "Not Found" },
|
|
110
105
|
status: 404
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mocksw",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "@zstings",
|
|
7
7
|
"description": "一个基于 Service Worker 的轻量级、零侵入 API 模拟工具",
|
|
8
8
|
"bin": {
|
|
9
|
-
"mocksw": "
|
|
9
|
+
"mocksw": "dist/cli.mjs"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
package/public/swMockWorker.js
CHANGED
|
@@ -25,7 +25,6 @@ self.addEventListener('fetch', event => {
|
|
|
25
25
|
status: status || 200,
|
|
26
26
|
headers: {
|
|
27
27
|
'Content-Type': 'application/json',
|
|
28
|
-
'Content-Length': 100000, // 显式设置大小
|
|
29
28
|
...headers,
|
|
30
29
|
},
|
|
31
30
|
}),
|
|
@@ -37,10 +36,13 @@ self.addEventListener('fetch', event => {
|
|
|
37
36
|
allClients[0].postMessage(
|
|
38
37
|
{
|
|
39
38
|
type: 'MSW_SIMULATE_REQUEST',
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
data: {
|
|
40
|
+
url: url.pathname,
|
|
41
|
+
method: event.request.method,
|
|
42
|
+
body: requestBody,
|
|
43
|
+
query: Object.fromEntries(url.searchParams.entries()),
|
|
44
|
+
headers: Object.fromEntries(event.request.headers.entries()),
|
|
45
|
+
},
|
|
44
46
|
},
|
|
45
47
|
[channel.port2],
|
|
46
48
|
);
|