jacky-proxy 1.0.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.md ADDED
@@ -0,0 +1,410 @@
1
+ # jacky-proxy
2
+
3
+ [![npm version](https://img.shields.io/npm/v/jacky-proxy.svg)](https://www.npmjs.com/package/jacky-proxy)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ 通用 Mock 服务器 - 适用于任意网站的 HTTP 请求拦截和 Mock 响应系统。
7
+
8
+ ## ✨ 特性
9
+
10
+ - 🚀 **零配置启动**:支持直接启动 Raw 文件夹,自动转换后启动
11
+ - 🎯 **智能匹配**:根据请求参数智能匹配对应的 Mock 响应
12
+ - 🔧 **配置驱动**:完全配置化,适用于任意网站
13
+ - 📦 **接口识别**:支持多种接口识别策略(URL、请求头、请求体等)
14
+ - 🎨 **Web 管理界面**:提供可视化的接口管理界面
15
+ - 🔄 **动态场景切换**:支持接口级别的场景切换
16
+ - 📝 **TypeScript 支持**:原生支持 TypeScript Mock 文件
17
+
18
+ ## 📦 安装
19
+
20
+ ```bash
21
+ npm install -g jacky-proxy
22
+ ```
23
+
24
+ 或作为项目依赖安装:
25
+
26
+ ```bash
27
+ npm install jacky-proxy
28
+ ```
29
+
30
+ ## 🚀 快速开始
31
+
32
+ ### 方式一:直接启动 Raw 文件夹(推荐)
33
+
34
+ 如果你有 Proxyman 导出的 Raw 文件夹(以 `.folder` 结尾),可以直接启动:
35
+
36
+ ```bash
37
+ # 直接启动 Raw 文件夹,自动转换后启动
38
+ jacky-proxy start Raw_01-06-2026-00-38-22.folder
39
+
40
+ # 指定场景名称和目标文件夹
41
+ jacky-proxy start Raw_01-06-2026-00-38-22.folder -s "场景1" -t "mocks/test-folder"
42
+
43
+ # 忽略某些接口
44
+ jacky-proxy start Raw_01-06-2026-00-38-22.folder --ignore "saveLogInfo,commonQueryCommentSummary"
45
+ ```
46
+
47
+ ### 方式二:先转换再启动
48
+
49
+ ```bash
50
+ # 1. 从 Raw 文件夹生成 Mock 数据(交互式模式)
51
+ jacky-proxy migrate
52
+
53
+ # 或使用命令行模式
54
+ jacky-proxy migrate -s "场景1" -t "mocks/test-folder" -r "Raw_01-06-2026-00-38-22.folder"
55
+
56
+ # 2. 启动服务器(使用自动生成的场景 ID)
57
+ jacky-proxy start 1
58
+ ```
59
+
60
+ ### 方式三:使用已有的 base-data + mocks 结构
61
+
62
+ ```bash
63
+ # 直接启动,使用场景 ID
64
+ jacky-proxy start 1
65
+
66
+ # 指定端口
67
+ jacky-proxy start 1 -p 5000
68
+ ```
69
+
70
+ ## 📖 使用指南
71
+
72
+ ### 项目结构
73
+
74
+ ```
75
+ jacky-proxy/ # 项目根目录(npm 包)
76
+ ├── server.js # 主服务器文件
77
+ ├── bin/ # CLI 命令入口
78
+ ├── src/ # 命令实现
79
+ ├── utils/ # 工具函数
80
+ └── ...
81
+
82
+ 工作目录(用户项目) # 用户运行命令的目录
83
+ ├── proxy.config.json # 接口集配置(自动生成)
84
+ ├── config/
85
+ │ └── match-rules.json # 匹配规则配置(自动生成)
86
+ ├── base-data/ # Mock 数据存储目录
87
+ │ └── {interfaceName}/
88
+ │ ├── 场景1-1.json
89
+ │ └── 场景1-1-request.json
90
+ └── mocks/ # Mock 文件目录
91
+ └── {folder}/
92
+ └── {interfaceName}.mock.ts
93
+ ```
94
+
95
+ ### 配置文件
96
+
97
+ #### proxy.config.json
98
+
99
+ 接口集配置文件,用于存储所有包含 Mock 文件的文件夹配置:
100
+
101
+ ```json
102
+ {
103
+ "libraryId": 2773,
104
+ "folders": {
105
+ "list": [
106
+ {
107
+ "id": 1,
108
+ "path": "mocks/test-folder",
109
+ "name": "场景1"
110
+ }
111
+ ]
112
+ }
113
+ }
114
+ ```
115
+
116
+ **生成配置**:
117
+
118
+ ```bash
119
+ # 自动扫描并生成配置
120
+ jacky-proxy config generate
121
+
122
+ # 验证配置
123
+ jacky-proxy config validate
124
+
125
+ # 合并新发现的文件夹到现有配置
126
+ jacky-proxy config merge
127
+ ```
128
+
129
+ #### config/match-rules.json
130
+
131
+ 匹配规则配置文件,用于过滤请求中的随机参数。**此文件在工作目录自动生成**,无需手动创建:
132
+
133
+ ```json
134
+ {
135
+ "global": {
136
+ "ignoreProps": [
137
+ "timestamp",
138
+ "traceId",
139
+ "clientInfo"
140
+ ]
141
+ },
142
+ "interfaces": [
143
+ {
144
+ "interfaceName": "productSearch",
145
+ "ignoreProps": ["location", "client_locatedDistrictId"],
146
+ "deepIgnore": true
147
+ }
148
+ ]
149
+ }
150
+ ```
151
+
152
+ **管理匹配规则**:
153
+
154
+ ```bash
155
+ # 列出所有规则
156
+ jacky-proxy rules list
157
+
158
+ # 添加规则
159
+ jacky-proxy rules add -i productSearch --ignore "location,clientInfo"
160
+
161
+ # 删除规则
162
+ jacky-proxy rules remove -i productSearch
163
+
164
+ # 测试规则
165
+ jacky-proxy rules test -i productSearch -r request.json
166
+ ```
167
+
168
+ ### 创建 Mock 文件
169
+
170
+ 在 `mocks/` 目录下创建 `.mock.ts` 文件,例如 `productSearch.mock.ts`:
171
+
172
+ ```typescript
173
+ // 从 base-data 导入请求和响应数据
174
+ import response1 from '../base-data/productSearch/场景1.json';
175
+ import request1 from '../base-data/productSearch/场景1-request.json';
176
+
177
+ const requestList = [request1];
178
+ const responseList = [response1];
179
+
180
+ import { matchResponse } from '../utils/common/match-response';
181
+
182
+ // 直接导出异步函数
183
+ export default async (request) => {
184
+ const response = matchResponse(request, requestList, responseList, {
185
+ interfaceName: 'productSearch', // 从文件名提取
186
+ deepIgnore: true
187
+ });
188
+
189
+ return {
190
+ status: 200,
191
+ headers: { 'Content-Type': 'application/json' },
192
+ body: response,
193
+ };
194
+ };
195
+ ```
196
+
197
+ **重要**:文件名 `productSearch.mock.ts` 会自动提取为接口标识符 `productSearch`。
198
+
199
+ ### 配置 Proxyman
200
+
201
+ 在 Proxyman 的脚本配置中使用以下代码:
202
+
203
+ ```javascript
204
+ async function onRequest(context, url, request) {
205
+ // 转发到本地服务器
206
+ request.scheme = 'http';
207
+ request.host = 'localhost';
208
+ request.port = 5000; // 默认端口 5000
209
+
210
+ return request;
211
+ }
212
+ ```
213
+
214
+ ## 📚 CLI 命令
215
+
216
+ ### migrate
217
+
218
+ 从 Raw 文件夹生成 Mock 数据文件:
219
+
220
+ ```bash
221
+ # 交互式模式(推荐)
222
+ jacky-proxy migrate
223
+
224
+ # 命令行模式
225
+ jacky-proxy migrate -s "场景1" -t "mocks/test-folder" -r "Raw_01-06-2026-00-38-22.folder"
226
+
227
+ # 忽略某些接口
228
+ jacky-proxy migrate --ignore "saveLogInfo,commonQueryCommentSummary"
229
+ ```
230
+
231
+ **选项**:
232
+ - `-s, --scenario <name>`: 场景名称(默认:场景1)
233
+ - `-t, --target <path>`: 目标文件夹路径(默认:mocks/test-folder)
234
+ - `-r, --raw <path>`: Raw 文件夹路径(可选,会自动检测)
235
+ - `--ignore <interfaces>`: 要忽略的接口(逗号分隔)
236
+ - `-i, --interactive`: 交互式模式(默认开启)
237
+ - `--no-interactive`: 禁用交互式模式
238
+
239
+ ### start
240
+
241
+ 启动 Mock 服务器:
242
+
243
+ ```bash
244
+ # 启动已有的场景(通过 ID)
245
+ jacky-proxy start 1
246
+
247
+ # 直接启动 Raw 文件夹(自动转换后启动)
248
+ jacky-proxy start Raw_01-06-2026-00-38-22.folder
249
+
250
+ # 指定端口
251
+ jacky-proxy start 1 -p 5000
252
+
253
+ # 启动 Raw 文件夹并指定场景名称
254
+ jacky-proxy start Raw_01-06-2026-00-38-22.folder -s "场景1" -t "mocks/test-folder"
255
+
256
+ # 开启 Debug 模式
257
+ jacky-proxy start 1 --debug
258
+ ```
259
+
260
+ **选项**:
261
+ - `-p, --port <port>`: 监听端口(默认:5001)
262
+ - `-m, --mock-id <id>`: 接口集 ID(如果未在命令中指定)
263
+ - `-c, --config <path>`: 配置文件路径(默认:proxy.config.json)
264
+ - `-s, --scenario <name>`: 场景名称(当启动 Raw 文件夹时使用)
265
+ - `-t, --target <path>`: 目标文件夹路径(当启动 Raw 文件夹时使用)
266
+ - `--ignore <interfaces>`: 要忽略的接口(逗号分隔)
267
+ - `--no-migrate`: 不自动迁移,直接启动
268
+ - `--debug`: 开启 Debug 模式,输出详细的请求日志
269
+
270
+ ### config
271
+
272
+ 管理接口集配置:
273
+
274
+ ```bash
275
+ # 生成配置
276
+ jacky-proxy config generate
277
+
278
+ # 验证配置
279
+ jacky-proxy config validate
280
+
281
+ # 合并配置
282
+ jacky-proxy config merge
283
+ ```
284
+
285
+ ### rules
286
+
287
+ 管理匹配规则配置:
288
+
289
+ ```bash
290
+ # 列出所有规则
291
+ jacky-proxy rules list
292
+
293
+ # 添加规则
294
+ jacky-proxy rules add -i productSearch --ignore "location,clientInfo"
295
+
296
+ # 删除规则
297
+ jacky-proxy rules remove -i productSearch
298
+
299
+ # 测试规则
300
+ jacky-proxy rules test -i productSearch -r request.json
301
+ ```
302
+
303
+ ## 🎯 核心概念
304
+
305
+ ### 接口标识符
306
+
307
+ 接口标识符用于识别和匹配 Mock 文件。系统支持多种识别策略:
308
+
309
+ - **URL 路径模式**:从 URL 中提取(最常用)
310
+ - **请求头**:从请求头中提取
311
+ - **请求体**:从请求体中提取
312
+ - **查询参数**:从查询参数中提取
313
+ - **自定义函数**:使用自定义逻辑提取
314
+
315
+ 默认策略:
316
+ 1. 从 URL 最后一段提取(如 `/api/productSearch` -> `productSearch`)
317
+ 2. 从请求头 `X-Interface-Name` 提取
318
+
319
+ ### 匹配规则
320
+
321
+ 匹配规则用于过滤请求中的随机参数,确保匹配的准确性:
322
+
323
+ - **全局规则**:所有接口都会应用的规则
324
+ - **接口规则**:针对特定接口的规则
325
+ - **深度忽略**:递归删除嵌套属性
326
+
327
+ ### 接口集
328
+
329
+ 一个接口集(folder)包含多个 Mock 文件,通过 `proxy.config.json` 配置。启动时通过 `jacky-proxy start <mockId>` 指定要使用的接口集。
330
+
331
+ ## 🌐 Web 管理界面
332
+
333
+ 启动服务器后,访问 `http://localhost:5001/mock-admin` 可以:
334
+
335
+ - 查看所有可用的接口集
336
+ - 切换接口集(mockId)
337
+ - 查看和管理接口场景
338
+ - 启用/禁用接口
339
+ - 动态切换接口场景
340
+
341
+ ## 🔧 高级配置
342
+
343
+ ### 自定义接口识别策略
344
+
345
+ 在 `server.js` 中修改 `interfaceIdentifierConfig`:
346
+
347
+ ```javascript
348
+ const interfaceIdentifierConfig = {
349
+ strategies: [
350
+ {
351
+ type: 'urlPattern',
352
+ pattern: '/api/v1/([^/]+)',
353
+ group: 1,
354
+ description: '从 /api/v1/ 路径提取接口名'
355
+ },
356
+ {
357
+ type: 'header',
358
+ key: 'X-API-Name',
359
+ description: '从请求头提取'
360
+ }
361
+ ]
362
+ };
363
+ ```
364
+
365
+ ### 匹配规则选项
366
+
367
+ ```json
368
+ {
369
+ "interfaces": [
370
+ {
371
+ "interfaceName": "productSearch",
372
+ "ignoreProps": ["location"],
373
+ "essentialProps": ["destination", "keyword"],
374
+ "deepIgnore": true,
375
+ "sortProps": [
376
+ {
377
+ "prop": "districtInfo",
378
+ "compareKey": "key"
379
+ }
380
+ ]
381
+ }
382
+ ]
383
+ }
384
+ ```
385
+
386
+ **选项说明**:
387
+ - `ignoreProps`: 要忽略的属性列表(会被过滤掉)
388
+ - `essentialProps`: 必需属性(即使在其他忽略列表中也会保留)
389
+ - `deepIgnore`: 是否深度忽略(递归删除嵌套属性)
390
+ - `sortProps`: 数组排序配置
391
+
392
+ ## 📝 注意事项
393
+
394
+ 1. Mock 文件名会自动提取为接口标识符(去掉 `.mock.ts` 后缀)
395
+ 2. 确保 `base-data` 目录中的请求和响应数据格式正确
396
+ 3. 匹配规则配置需要与接口名称对应
397
+ 4. 接口识别策略需要根据实际接口格式配置
398
+
399
+ ## 🤝 贡献
400
+
401
+ 欢迎提交 Issue 和 Pull Request!
402
+
403
+ ## 📄 License
404
+
405
+ MIT
406
+
407
+ ## 🔗 相关链接
408
+
409
+ - [GitHub Repository](https://github.com/wangjs-jacky/jacky-proxy)
410
+ - [npm Package](https://www.npmjs.com/package/jacky-proxy)
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Jacky Proxy CLI 工具入口文件
5
+ * 使用 commander.js 构建命令行界面
6
+ */
7
+
8
+ const { Command } = require('commander');
9
+ const path = require('path');
10
+
11
+ const program = new Command();
12
+
13
+ // 设置程序信息
14
+ program
15
+ .name('jacky-proxy')
16
+ .description('通用 Mock 服务器 CLI 工具 - 用于管理 Mock 数据和启动服务器')
17
+ .version(require('../package.json').version);
18
+
19
+ // migrate 命令
20
+ program
21
+ .command('migrate')
22
+ .description('从 Raw 文件夹生成 Mock 数据文件')
23
+ .option('-s, --scenario <name>', '场景名称')
24
+ .option('-t, --target <path>', '目标文件夹路径')
25
+ .option('-r, --raw <path>', 'Raw 文件夹路径(可选,会自动检测)')
26
+ .option('--ignore <interfaces>', '要忽略的接口(逗号分隔)', '')
27
+ .option('-i, --interactive', '交互式模式(默认)', true)
28
+ .option('--no-interactive', '禁用交互式模式')
29
+ .action(async (options) => {
30
+ const migrateCommand = require('../src/commands/migrate');
31
+ await migrateCommand(options);
32
+ });
33
+
34
+ // start 命令
35
+ program
36
+ .command('start [mock-id-or-path]')
37
+ .description('启动 Mock 服务器(支持直接启动 Raw 文件夹或 mock-id)')
38
+ .option('-p, --port <port>', '监听端口', '5000')
39
+ .option('-m, --mock-id <id>', '接口集 ID(如果未在命令中指定)')
40
+ .option('-c, --config <path>', '配置文件路径', 'proxy.config.json')
41
+ .option('-s, --scenario <name>', '场景名称(当启动 Raw 文件夹时使用)', '场景1')
42
+ .option('-t, --target <path>', '目标文件夹路径(当启动 Raw 文件夹时使用)', 'mocks/test-folder')
43
+ .option('--ignore <interfaces>', '要忽略的接口(逗号分隔,当启动 Raw 文件夹时使用)', '')
44
+ .option('--no-migrate', '不自动迁移,直接启动(如果指定的是 Raw 文件夹)')
45
+ .option('--debug', '开启 Debug 模式,输出详细的请求日志')
46
+ .action(async (mockIdOrPath, options) => {
47
+ const startCommand = require('../src/commands/start');
48
+ await startCommand(mockIdOrPath || options.mockId || '1', options);
49
+ });
50
+
51
+ // config 命令组
52
+ const configCommand = program
53
+ .command('config')
54
+ .description('管理接口集配置');
55
+
56
+ configCommand
57
+ .command('generate')
58
+ .description('生成配置文件')
59
+ .option('-r, --root <dir>', '根目录', process.cwd())
60
+ .option('-o, --output <path>', '输出文件路径', 'proxy.config.json')
61
+ .option('-l, --library-id <id>', '库 ID', '2773')
62
+ .option('-s, --start-id <id>', '起始 ID', '1')
63
+ .action(async (options) => {
64
+ const configGenerateCommand = require('../src/commands/config-generate');
65
+ await configGenerateCommand(options);
66
+ });
67
+
68
+ configCommand
69
+ .command('validate')
70
+ .description('验证配置文件')
71
+ .option('-c, --config <path>', '配置文件路径', 'proxy.config.json')
72
+ .action(async (options) => {
73
+ const configValidateCommand = require('../src/commands/config-validate');
74
+ await configValidateCommand(options);
75
+ });
76
+
77
+ configCommand
78
+ .command('merge')
79
+ .description('合并配置')
80
+ .option('-r, --root <dir>', '根目录', process.cwd())
81
+ .option('-c, --config <path>', '配置文件路径', 'proxy.config.json')
82
+ .action(async (options) => {
83
+ const configMergeCommand = require('../src/commands/config-merge');
84
+ await configMergeCommand(options);
85
+ });
86
+
87
+ // rules 命令组(新功能)
88
+ const rulesCommand = program
89
+ .command('rules')
90
+ .description('管理匹配规则配置');
91
+
92
+ rulesCommand
93
+ .command('list')
94
+ .description('列出所有匹配规则')
95
+ .option('-c, --config <path>', '配置文件路径', 'config/match-rules.json')
96
+ .action(async (options) => {
97
+ const rulesListCommand = require('../src/commands/rules-list');
98
+ await rulesListCommand(options);
99
+ });
100
+
101
+ rulesCommand
102
+ .command('add')
103
+ .description('添加匹配规则')
104
+ .requiredOption('-i, --interface <name>', '接口名称')
105
+ .option('-c, --config <path>', '配置文件路径', 'config/match-rules.json')
106
+ .option('--ignore <props>', '要忽略的属性(逗号分隔)')
107
+ .option('--essential <props>', '必需属性(逗号分隔)')
108
+ .option('--deep-ignore', '启用深度忽略')
109
+ .action(async (options) => {
110
+ const rulesAddCommand = require('../src/commands/rules-add');
111
+ await rulesAddCommand(options);
112
+ });
113
+
114
+ rulesCommand
115
+ .command('remove')
116
+ .description('删除匹配规则')
117
+ .requiredOption('-i, --interface <name>', '接口名称')
118
+ .option('-c, --config <path>', '配置文件路径', 'config/match-rules.json')
119
+ .action(async (options) => {
120
+ const rulesRemoveCommand = require('../src/commands/rules-remove');
121
+ await rulesRemoveCommand(options);
122
+ });
123
+
124
+ rulesCommand
125
+ .command('test')
126
+ .description('测试匹配规则')
127
+ .requiredOption('-i, --interface <name>', '接口名称')
128
+ .requiredOption('-r, --request <path>', '请求文件路径')
129
+ .option('-c, --config <path>', '配置文件路径', 'config/match-rules.json')
130
+ .action(async (options) => {
131
+ const rulesTestCommand = require('../src/commands/rules-test');
132
+ await rulesTestCommand(options);
133
+ });
134
+
135
+ // 解析命令行参数
136
+ program.parse();
137
+
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "jacky-proxy",
3
+ "version": "1.0.0",
4
+ "description": "通用 Mock 服务器 - 适用于任意网站的 HTTP 请求拦截和 Mock 响应系统",
5
+ "main": "server.js",
6
+ "bin": {
7
+ "jacky-proxy": "bin/jacky-proxy.js"
8
+ },
9
+ "scripts": {
10
+ "start": "npm run config:generate && node server.js",
11
+ "dev": "nodemon server.js",
12
+ "config:generate": "node scripts/generate-config.js generate",
13
+ "config:validate": "node scripts/generate-config.js validate",
14
+ "config:merge": "node scripts/generate-config.js merge",
15
+ "migrate": "jacky-proxy migrate",
16
+ "cli": "node bin/jacky-proxy.js"
17
+ },
18
+ "keywords": [
19
+ "mock",
20
+ "proxy",
21
+ "express",
22
+ "api-mock",
23
+ "http-proxy",
24
+ "mock-server",
25
+ "api-testing",
26
+ "proxyman"
27
+ ],
28
+ "author": "",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/wangjs-jacky/jacky-proxy.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/wangjs-jacky/jacky-proxy/issues"
36
+ },
37
+ "homepage": "https://github.com/wangjs-jacky/jacky-proxy#readme",
38
+ "engines": {
39
+ "node": ">=14.0.0"
40
+ },
41
+ "files": [
42
+ "bin/",
43
+ "src/",
44
+ "server.js",
45
+ "scripts/",
46
+ "utils/",
47
+ "templates/",
48
+ "tsconfig.json",
49
+ "README.md"
50
+ ],
51
+ "dependencies": {
52
+ "commander": "^14.0.2",
53
+ "express": "^4.18.2",
54
+ "lodash": "^4.17.21"
55
+ },
56
+ "devDependencies": {
57
+ "@types/express": "^4.17.21",
58
+ "@types/lodash": "^4.14.202",
59
+ "@types/node": "^20.10.0",
60
+ "nodemon": "^3.0.1",
61
+ "ts-node": "^10.9.2",
62
+ "typescript": "^5.3.3"
63
+ }
64
+ }