@jonathanleelx/meddle 0.0.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/CONFIG_STRUCTURE.md +315 -0
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/bin/commands/mock/add.js +92 -0
- package/bin/commands/mock/delete.js +58 -0
- package/bin/commands/mock/index.js +50 -0
- package/bin/commands/mock/list.js +68 -0
- package/bin/commands/mock/toggle.js +64 -0
- package/bin/commands/mock/update.js +94 -0
- package/bin/commands/route/active.js +141 -0
- package/bin/commands/route/add.js +127 -0
- package/bin/commands/route/create.js +77 -0
- package/bin/commands/route/delete.js +120 -0
- package/bin/commands/route/index.js +59 -0
- package/bin/commands/route/list.js +67 -0
- package/bin/commands/route/preview.js +159 -0
- package/bin/commands/route/show.js +111 -0
- package/bin/commands/route/update.js +126 -0
- package/bin/commands/session/create.js +166 -0
- package/bin/commands/session/delete.js +69 -0
- package/bin/commands/session/index.js +61 -0
- package/bin/commands/session/list.js +42 -0
- package/bin/commands/session/prune.js +31 -0
- package/bin/commands/start.js +43 -0
- package/bin/commands/status.js +115 -0
- package/bin/commands/supervise.js +106 -0
- package/bin/commands/url.js +30 -0
- package/bin/doctor.js +356 -0
- package/bin/index +130 -0
- package/bin/lib/api-client.js +72 -0
- package/bin/lib/file-access.js +337 -0
- package/bin/lib/meddle-home.js +20 -0
- package/bin/lib/output.js +146 -0
- package/bin/lib/parsers.js +127 -0
- package/bin/lib/proxy-detect.js +105 -0
- package/bin/lib/route-preview.js +180 -0
- package/bin/lib/session-args.js +54 -0
- package/bin/lib/sessions.js +213 -0
- package/dist/cert.d.ts +10 -0
- package/dist/cert.d.ts.map +1 -0
- package/dist/cert.js +184 -0
- package/dist/cert.js.map +1 -0
- package/dist/core/application-identity.d.ts +55 -0
- package/dist/core/application-identity.d.ts.map +1 -0
- package/dist/core/application-identity.js +321 -0
- package/dist/core/application-identity.js.map +1 -0
- package/dist/core/body-utils.d.ts +2 -0
- package/dist/core/body-utils.d.ts.map +1 -0
- package/dist/core/body-utils.js +21 -0
- package/dist/core/body-utils.js.map +1 -0
- package/dist/core/browser.d.ts +2 -0
- package/dist/core/browser.d.ts.map +1 -0
- package/dist/core/browser.js +92 -0
- package/dist/core/browser.js.map +1 -0
- package/dist/core/client-identity.d.ts +27 -0
- package/dist/core/client-identity.d.ts.map +1 -0
- package/dist/core/client-identity.js +136 -0
- package/dist/core/client-identity.js.map +1 -0
- package/dist/core/config-diagnostics.d.ts +14 -0
- package/dist/core/config-diagnostics.d.ts.map +1 -0
- package/dist/core/config-diagnostics.js +137 -0
- package/dist/core/config-diagnostics.js.map +1 -0
- package/dist/core/connect-tunnel.d.ts +5 -0
- package/dist/core/connect-tunnel.d.ts.map +1 -0
- package/dist/core/connect-tunnel.js +45 -0
- package/dist/core/connect-tunnel.js.map +1 -0
- package/dist/core/content-encoding.d.ts +2 -0
- package/dist/core/content-encoding.d.ts.map +1 -0
- package/dist/core/content-encoding.js +77 -0
- package/dist/core/content-encoding.js.map +1 -0
- package/dist/core/custom-plugin-loader.d.ts +18 -0
- package/dist/core/custom-plugin-loader.d.ts.map +1 -0
- package/dist/core/custom-plugin-loader.js +178 -0
- package/dist/core/custom-plugin-loader.js.map +1 -0
- package/dist/core/h2-pool.d.ts +4 -0
- package/dist/core/h2-pool.d.ts.map +1 -0
- package/dist/core/h2-pool.js +180 -0
- package/dist/core/h2-pool.js.map +1 -0
- package/dist/core/inspection-dispatch.d.ts +5 -0
- package/dist/core/inspection-dispatch.d.ts.map +1 -0
- package/dist/core/inspection-dispatch.js +146 -0
- package/dist/core/inspection-dispatch.js.map +1 -0
- package/dist/core/log-rate-limit.d.ts +34 -0
- package/dist/core/log-rate-limit.d.ts.map +1 -0
- package/dist/core/log-rate-limit.js +52 -0
- package/dist/core/log-rate-limit.js.map +1 -0
- package/dist/core/map-local.d.ts +4 -0
- package/dist/core/map-local.d.ts.map +1 -0
- package/dist/core/map-local.js +195 -0
- package/dist/core/map-local.js.map +1 -0
- package/dist/core/meddle-home.d.ts +13 -0
- package/dist/core/meddle-home.d.ts.map +1 -0
- package/dist/core/meddle-home.js +56 -0
- package/dist/core/meddle-home.js.map +1 -0
- package/dist/core/mock-gate.d.ts +3 -0
- package/dist/core/mock-gate.d.ts.map +1 -0
- package/dist/core/mock-gate.js +20 -0
- package/dist/core/mock-gate.js.map +1 -0
- package/dist/core/mock-handler.d.ts +5 -0
- package/dist/core/mock-handler.d.ts.map +1 -0
- package/dist/core/mock-handler.js +339 -0
- package/dist/core/mock-handler.js.map +1 -0
- package/dist/core/on-mode-gate.d.ts +4 -0
- package/dist/core/on-mode-gate.d.ts.map +1 -0
- package/dist/core/on-mode-gate.js +64 -0
- package/dist/core/on-mode-gate.js.map +1 -0
- package/dist/core/pipeline-gate.d.ts +3 -0
- package/dist/core/pipeline-gate.d.ts.map +1 -0
- package/dist/core/pipeline-gate.js +34 -0
- package/dist/core/pipeline-gate.js.map +1 -0
- package/dist/core/pipeline.d.ts +6 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +228 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/plugin-bootstrap-runner.d.ts +6 -0
- package/dist/core/plugin-bootstrap-runner.d.ts.map +1 -0
- package/dist/core/plugin-bootstrap-runner.js +148 -0
- package/dist/core/plugin-bootstrap-runner.js.map +1 -0
- package/dist/core/plugin-bootstrap.d.ts +3 -0
- package/dist/core/plugin-bootstrap.d.ts.map +1 -0
- package/dist/core/plugin-bootstrap.js +15 -0
- package/dist/core/plugin-bootstrap.js.map +1 -0
- package/dist/core/plugin-compiler.d.ts +37 -0
- package/dist/core/plugin-compiler.d.ts.map +1 -0
- package/dist/core/plugin-compiler.js +172 -0
- package/dist/core/plugin-compiler.js.map +1 -0
- package/dist/core/plugin-context-factory.d.ts +29 -0
- package/dist/core/plugin-context-factory.d.ts.map +1 -0
- package/dist/core/plugin-context-factory.js +206 -0
- package/dist/core/plugin-context-factory.js.map +1 -0
- package/dist/core/plugin-generator.d.ts +47 -0
- package/dist/core/plugin-generator.d.ts.map +1 -0
- package/dist/core/plugin-generator.js +697 -0
- package/dist/core/plugin-generator.js.map +1 -0
- package/dist/core/plugin-health.d.ts +3 -0
- package/dist/core/plugin-health.d.ts.map +1 -0
- package/dist/core/plugin-health.js +54 -0
- package/dist/core/plugin-health.js.map +1 -0
- package/dist/core/plugin-intercept.d.ts +17 -0
- package/dist/core/plugin-intercept.d.ts.map +1 -0
- package/dist/core/plugin-intercept.js +133 -0
- package/dist/core/plugin-intercept.js.map +1 -0
- package/dist/core/plugin-runtime.d.ts +33 -0
- package/dist/core/plugin-runtime.d.ts.map +1 -0
- package/dist/core/plugin-runtime.js +254 -0
- package/dist/core/plugin-runtime.js.map +1 -0
- package/dist/core/proxy-context.d.ts +3 -0
- package/dist/core/proxy-context.d.ts.map +1 -0
- package/dist/core/proxy-context.js +129 -0
- package/dist/core/proxy-context.js.map +1 -0
- package/dist/core/proxy-record.d.ts +3 -0
- package/dist/core/proxy-record.d.ts.map +1 -0
- package/dist/core/proxy-record.js +32 -0
- package/dist/core/proxy-record.js.map +1 -0
- package/dist/core/refactor-config.d.ts +6 -0
- package/dist/core/refactor-config.d.ts.map +1 -0
- package/dist/core/refactor-config.js +45 -0
- package/dist/core/refactor-config.js.map +1 -0
- package/dist/core/refactor-status.d.ts +3 -0
- package/dist/core/refactor-status.d.ts.map +1 -0
- package/dist/core/refactor-status.js +19 -0
- package/dist/core/refactor-status.js.map +1 -0
- package/dist/core/remote-access.d.ts +40 -0
- package/dist/core/remote-access.d.ts.map +1 -0
- package/dist/core/remote-access.js +281 -0
- package/dist/core/remote-access.js.map +1 -0
- package/dist/core/route-decision.d.ts +3 -0
- package/dist/core/route-decision.d.ts.map +1 -0
- package/dist/core/route-decision.js +20 -0
- package/dist/core/route-decision.js.map +1 -0
- package/dist/core/route-loader.d.ts +14 -0
- package/dist/core/route-loader.d.ts.map +1 -0
- package/dist/core/route-loader.js +94 -0
- package/dist/core/route-loader.js.map +1 -0
- package/dist/core/route-preview.d.ts +15 -0
- package/dist/core/route-preview.d.ts.map +1 -0
- package/dist/core/route-preview.js +91 -0
- package/dist/core/route-preview.js.map +1 -0
- package/dist/core/runtime-health.d.ts +92 -0
- package/dist/core/runtime-health.d.ts.map +1 -0
- package/dist/core/runtime-health.js +205 -0
- package/dist/core/runtime-health.js.map +1 -0
- package/dist/core/sessions.d.ts +19 -0
- package/dist/core/sessions.d.ts.map +1 -0
- package/dist/core/sessions.js +93 -0
- package/dist/core/sessions.js.map +1 -0
- package/dist/core/shadow-compare.d.ts +8 -0
- package/dist/core/shadow-compare.d.ts.map +1 -0
- package/dist/core/shadow-compare.js +83 -0
- package/dist/core/shadow-compare.js.map +1 -0
- package/dist/core/shadow-readiness.d.ts +4 -0
- package/dist/core/shadow-readiness.d.ts.map +1 -0
- package/dist/core/shadow-readiness.js +118 -0
- package/dist/core/shadow-readiness.js.map +1 -0
- package/dist/core/short-response.d.ts +5 -0
- package/dist/core/short-response.d.ts.map +1 -0
- package/dist/core/short-response.js +18 -0
- package/dist/core/short-response.js.map +1 -0
- package/dist/core/static-server.d.ts +9 -0
- package/dist/core/static-server.d.ts.map +1 -0
- package/dist/core/static-server.js +136 -0
- package/dist/core/static-server.js.map +1 -0
- package/dist/core/types.d.ts +590 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +4 -0
- package/dist/core/types.js.map +1 -0
- package/dist/helpers.d.ts +36 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +290 -0
- package/dist/helpers.js.map +1 -0
- package/dist/plugins/builtin/index.d.ts +3 -0
- package/dist/plugins/builtin/index.d.ts.map +1 -0
- package/dist/plugins/builtin/index.js +23 -0
- package/dist/plugins/builtin/index.js.map +1 -0
- package/dist/plugins/builtin/logger-plugin.d.ts +8 -0
- package/dist/plugins/builtin/logger-plugin.d.ts.map +1 -0
- package/dist/plugins/builtin/logger-plugin.js +121 -0
- package/dist/plugins/builtin/logger-plugin.js.map +1 -0
- package/dist/plugins/builtin/mock-plugin.d.ts +3 -0
- package/dist/plugins/builtin/mock-plugin.d.ts.map +1 -0
- package/dist/plugins/builtin/mock-plugin.js +99 -0
- package/dist/plugins/builtin/mock-plugin.js.map +1 -0
- package/dist/plugins/builtin/router-plugin.d.ts +3 -0
- package/dist/plugins/builtin/router-plugin.d.ts.map +1 -0
- package/dist/plugins/builtin/router-plugin.js +36 -0
- package/dist/plugins/builtin/router-plugin.js.map +1 -0
- package/dist/server/agent/model.d.ts +30 -0
- package/dist/server/agent/model.d.ts.map +1 -0
- package/dist/server/agent/model.js +143 -0
- package/dist/server/agent/model.js.map +1 -0
- package/dist/server/agent/routes.d.ts +4 -0
- package/dist/server/agent/routes.d.ts.map +1 -0
- package/dist/server/agent/routes.js +188 -0
- package/dist/server/agent/routes.js.map +1 -0
- package/dist/server/agent/runtime.d.ts +12 -0
- package/dist/server/agent/runtime.d.ts.map +1 -0
- package/dist/server/agent/runtime.js +208 -0
- package/dist/server/agent/runtime.js.map +1 -0
- package/dist/server/agent/tools.d.ts +13 -0
- package/dist/server/agent/tools.d.ts.map +1 -0
- package/dist/server/agent/tools.js +1201 -0
- package/dist/server/agent/tools.js.map +1 -0
- package/dist/server/agent/types.d.ts +56 -0
- package/dist/server/agent/types.d.ts.map +1 -0
- package/dist/server/agent/types.js +3 -0
- package/dist/server/agent/types.js.map +1 -0
- package/dist/server/config.d.ts +9 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +124 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/health.d.ts +4 -0
- package/dist/server/health.d.ts.map +1 -0
- package/dist/server/health.js +22 -0
- package/dist/server/health.js.map +1 -0
- package/dist/server/index.d.ts +239 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +44 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/logs.d.ts +4 -0
- package/dist/server/logs.d.ts.map +1 -0
- package/dist/server/logs.js +40 -0
- package/dist/server/logs.js.map +1 -0
- package/dist/server/mocks.d.ts +9 -0
- package/dist/server/mocks.d.ts.map +1 -0
- package/dist/server/mocks.js +103 -0
- package/dist/server/mocks.js.map +1 -0
- package/dist/server/pipeline.d.ts +16 -0
- package/dist/server/pipeline.d.ts.map +1 -0
- package/dist/server/pipeline.js +159 -0
- package/dist/server/pipeline.js.map +1 -0
- package/dist/server/plugins.d.ts +32 -0
- package/dist/server/plugins.d.ts.map +1 -0
- package/dist/server/plugins.js +795 -0
- package/dist/server/plugins.js.map +1 -0
- package/dist/server/refactor.d.ts +4 -0
- package/dist/server/refactor.d.ts.map +1 -0
- package/dist/server/refactor.js +86 -0
- package/dist/server/refactor.js.map +1 -0
- package/dist/server/rule-files.d.ts +34 -0
- package/dist/server/rule-files.d.ts.map +1 -0
- package/dist/server/rule-files.js +389 -0
- package/dist/server/rule-files.js.map +1 -0
- package/dist/server/rules.d.ts +4 -0
- package/dist/server/rules.d.ts.map +1 -0
- package/dist/server/rules.js +40 -0
- package/dist/server/rules.js.map +1 -0
- package/dist/server/sessions.d.ts +4 -0
- package/dist/server/sessions.d.ts.map +1 -0
- package/dist/server/sessions.js +20 -0
- package/dist/server/sessions.js.map +1 -0
- package/index.js +950 -0
- package/mcp-server.js +794 -0
- package/package.json +92 -0
- package/plugins/builtin/index.ts +25 -0
- package/plugins/builtin/logger-plugin.ts +126 -0
- package/plugins/builtin/mock-plugin.ts +112 -0
- package/plugins/builtin/router-plugin.ts +35 -0
- package/web/README.md +111 -0
- package/web/dist/assets/ai-config-store-DQXVJVn_.js +1 -0
- package/web/dist/assets/alert-COF-DIAE.js +1 -0
- package/web/dist/assets/arrow-right-B4Mrlj2-.js +1 -0
- package/web/dist/assets/babel-DsprIpXZ.js +15 -0
- package/web/dist/assets/body-diff-view-D7dCWajG.js +6 -0
- package/web/dist/assets/button-BTToMaBW.js +1 -0
- package/web/dist/assets/checkbox-DIBarrJx.js +1 -0
- package/web/dist/assets/chevron-down-CPngAx4M.js +1 -0
- package/web/dist/assets/chevron-right-V1DGIDbL.js +1 -0
- package/web/dist/assets/circle-alert-Q8cZk9Rv.js +1 -0
- package/web/dist/assets/circle-x-C9USji_R.js +1 -0
- package/web/dist/assets/code-5_eJ_XpJ.js +1 -0
- package/web/dist/assets/code-fixer-fQtWZ5He.js +20 -0
- package/web/dist/assets/copy-BYjq1hdN.js +1 -0
- package/web/dist/assets/detail-panel-BX_hxeI0.js +3 -0
- package/web/dist/assets/dist-B8XUKgXe.js +1 -0
- package/web/dist/assets/dist-Bb9TeEub.js +1 -0
- package/web/dist/assets/dist-C5nMErq8.js +1 -0
- package/web/dist/assets/dist-C6eaYCUo.js +1 -0
- package/web/dist/assets/dist-Cn0y0IRn.js +1 -0
- package/web/dist/assets/dist-CxdY_A67.js +5 -0
- package/web/dist/assets/dist-D5Dj17P8.js +1 -0
- package/web/dist/assets/dist-DZJ9SMlJ.js +1 -0
- package/web/dist/assets/es2015-CfXu88Y7.js +41 -0
- package/web/dist/assets/estree-BP7k0NIt.js +44 -0
- package/web/dist/assets/file-system-access-CtcvBfj4.js +1 -0
- package/web/dist/assets/global-panel-shell-ChdO0dWd.js +6 -0
- package/web/dist/assets/health-panel-CQeCQ7gr.js +1 -0
- package/web/dist/assets/html-6FIWbqxX.js +25 -0
- package/web/dist/assets/index-CjqaTnE_.css +2 -0
- package/web/dist/assets/index-L7uWxTnp.js +18 -0
- package/web/dist/assets/mobile-proxy-panel-Dj1iLami.js +8 -0
- package/web/dist/assets/mock-config-BTTCw7RK.js +1 -0
- package/web/dist/assets/mock-editor-panel-C-aVfFme.js +1 -0
- package/web/dist/assets/monaco-editor-B3brLg8j.js +11 -0
- package/web/dist/assets/pencil-line-Cqe41E4h.js +1 -0
- package/web/dist/assets/plugin-code-editor-CPjCbJ9g.js +2 -0
- package/web/dist/assets/plugin-config-BzmCkvz3.js +1 -0
- package/web/dist/assets/plugin-generator-BnEafDF9.js +2 -0
- package/web/dist/assets/plugin-test-dialog-BWoWsWV4.js +7 -0
- package/web/dist/assets/plus-tVxSydJ8.js +1 -0
- package/web/dist/assets/postcss-Dnf30fQU.js +61 -0
- package/web/dist/assets/refresh-cw-CG3HaiQT.js +1 -0
- package/web/dist/assets/rotate-ccw-CAYM6Vv0.js +1 -0
- package/web/dist/assets/route-preview-BX7sfY0O.js +1 -0
- package/web/dist/assets/rule-ai-assistant-panel-WBiOOUw5.js +47 -0
- package/web/dist/assets/rule-config-CHpVij2M.css +1 -0
- package/web/dist/assets/rule-config-fTIZVwg1.js +15 -0
- package/web/dist/assets/select-CkFOB61l.js +1 -0
- package/web/dist/assets/server-Cpj4KNwN.js +1 -0
- package/web/dist/assets/settings-panel-COCYiIUg.js +1 -0
- package/web/dist/assets/shield-check-OqUmVLQt.js +1 -0
- package/web/dist/assets/smartphone-DKeDuJTU.js +1 -0
- package/web/dist/assets/standalone-CjxtLKw-.js +29 -0
- package/web/dist/assets/switch-C-Xk56TK.js +1 -0
- package/web/dist/assets/syntax-highlight-DVhPdkuV.js +5 -0
- package/web/dist/assets/table-CT97lAYq.js +1 -0
- package/web/dist/assets/textarea-C6NooVK1.js +1 -0
- package/web/dist/assets/wand-sparkles-wkul5vje.js +1 -0
- package/web/dist/assets/wifi-D9M35Ajj.js +1 -0
- package/web/dist/assets/zap-Djo4cgux.js +1 -0
- package/web/dist/index.html +24 -0
- package/web/dist/vite.svg +1 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle mock add - Add a mock rule
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const output = require('../../lib/output')
|
|
6
|
+
const { isProxyRunning } = require('../../lib/proxy-detect')
|
|
7
|
+
const { apiPost } = require('../../lib/api-client')
|
|
8
|
+
const { addMockRule } = require('../../lib/file-access')
|
|
9
|
+
|
|
10
|
+
// Parse arguments
|
|
11
|
+
const args = process.argv.slice(3)
|
|
12
|
+
const jsonFlag = args.includes('--json')
|
|
13
|
+
output.setJsonMode(jsonFlag)
|
|
14
|
+
|
|
15
|
+
function parseArgs(args) {
|
|
16
|
+
const options = {}
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
if (args[i] === '--name') options.name = args[++i]
|
|
19
|
+
else if (args[i] === '--pattern') options.urlPattern = args[++i]
|
|
20
|
+
else if (args[i] === '--method') options.method = args[++i]
|
|
21
|
+
else if (args[i] === '--status') options.statusCode = parseInt(args[++i], 10)
|
|
22
|
+
else if (args[i] === '--body') options.body = args[++i]
|
|
23
|
+
else if (args[i] === '--delay') options.delay = parseInt(args[++i], 10)
|
|
24
|
+
else if (args[i] === '--headers') {
|
|
25
|
+
try {
|
|
26
|
+
options.headers = JSON.parse(args[++i])
|
|
27
|
+
} catch (_) {
|
|
28
|
+
options.headers = {}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return options
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function run() {
|
|
36
|
+
const options = parseArgs(args)
|
|
37
|
+
|
|
38
|
+
// Validate required fields
|
|
39
|
+
if (!options.name) {
|
|
40
|
+
output.error('Missing required option: --name')
|
|
41
|
+
process.exit(1)
|
|
42
|
+
}
|
|
43
|
+
if (!options.urlPattern) {
|
|
44
|
+
output.error('Missing required option: --pattern')
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Set defaults
|
|
49
|
+
const rule = {
|
|
50
|
+
name: options.name,
|
|
51
|
+
urlPattern: options.urlPattern,
|
|
52
|
+
method: options.method || '*',
|
|
53
|
+
statusCode: options.statusCode || 200,
|
|
54
|
+
delay: options.delay || 0,
|
|
55
|
+
bodyType: 'inline',
|
|
56
|
+
headers: options.headers || {},
|
|
57
|
+
body: options.body || '',
|
|
58
|
+
enabled: true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const running = await isProxyRunning()
|
|
62
|
+
|
|
63
|
+
let result
|
|
64
|
+
if (running) {
|
|
65
|
+
try {
|
|
66
|
+
result = await apiPost('/api/mocks', rule)
|
|
67
|
+
result = result.rule || result
|
|
68
|
+
} catch (e) {
|
|
69
|
+
// Fallback to file mode
|
|
70
|
+
result = addMockRule(rule)
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
result = addMockRule(rule)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (jsonFlag) {
|
|
77
|
+
output.jsonRaw(result)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
output.header('Mock Rule Added')
|
|
82
|
+
output.success(`#${result.id}: ${result.name}`)
|
|
83
|
+
output.kv('Pattern', result.urlPattern)
|
|
84
|
+
output.kv('Method', result.method)
|
|
85
|
+
output.kv('Status', result.statusCode)
|
|
86
|
+
output.kv('Delay', `${result.delay}ms`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
run().catch(e => {
|
|
90
|
+
output.error(e.message)
|
|
91
|
+
process.exit(1)
|
|
92
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle mock delete - Delete a mock rule
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const output = require('../../lib/output')
|
|
6
|
+
const { isProxyRunning } = require('../../lib/proxy-detect')
|
|
7
|
+
const { apiDelete } = require('../../lib/api-client')
|
|
8
|
+
const { deleteMockRule } = require('../../lib/file-access')
|
|
9
|
+
|
|
10
|
+
// Parse arguments (skip 'mock' and 'delete' from argv)
|
|
11
|
+
const args = process.argv.slice(4)
|
|
12
|
+
const jsonFlag = args.includes('--json')
|
|
13
|
+
output.setJsonMode(jsonFlag)
|
|
14
|
+
|
|
15
|
+
// Get id from positional argument
|
|
16
|
+
const idArg = args.find(a => !a.startsWith('--'))
|
|
17
|
+
const id = idArg ? parseInt(idArg, 10) : null
|
|
18
|
+
|
|
19
|
+
async function run() {
|
|
20
|
+
if (id === null) {
|
|
21
|
+
output.error('Missing required argument: <id>')
|
|
22
|
+
process.exit(1)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const running = await isProxyRunning()
|
|
26
|
+
|
|
27
|
+
if (running) {
|
|
28
|
+
try {
|
|
29
|
+
await apiDelete(`/api/mocks/${id}`)
|
|
30
|
+
} catch (e) {
|
|
31
|
+
// Fallback to file mode
|
|
32
|
+
const deleted = deleteMockRule(id)
|
|
33
|
+
if (!deleted) {
|
|
34
|
+
output.error(`Mock rule not found: id=${id}`)
|
|
35
|
+
process.exit(1)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
const deleted = deleteMockRule(id)
|
|
40
|
+
if (!deleted) {
|
|
41
|
+
output.error(`Mock rule not found: id=${id}`)
|
|
42
|
+
process.exit(1)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (jsonFlag) {
|
|
47
|
+
output.jsonRaw({ success: true, id })
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
output.header('Mock Rule Deleted')
|
|
52
|
+
output.success(`id=${id}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
run().catch(e => {
|
|
56
|
+
output.error(e.message)
|
|
57
|
+
process.exit(1)
|
|
58
|
+
})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle mock - Mock rule subcommand router
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const args = process.argv.slice(3)
|
|
6
|
+
const subcommand = args[0]
|
|
7
|
+
|
|
8
|
+
switch (subcommand) {
|
|
9
|
+
case 'list':
|
|
10
|
+
require('./list.js')
|
|
11
|
+
break
|
|
12
|
+
case 'add':
|
|
13
|
+
require('./add.js')
|
|
14
|
+
break
|
|
15
|
+
case 'update':
|
|
16
|
+
require('./update.js')
|
|
17
|
+
break
|
|
18
|
+
case 'delete':
|
|
19
|
+
require('./delete.js')
|
|
20
|
+
break
|
|
21
|
+
case 'enable':
|
|
22
|
+
case 'disable':
|
|
23
|
+
require('./toggle.js')
|
|
24
|
+
break
|
|
25
|
+
default:
|
|
26
|
+
console.log(`
|
|
27
|
+
Mock Commands:
|
|
28
|
+
meddle mock list [--json] List all mock rules
|
|
29
|
+
meddle mock add [options] Add a mock rule
|
|
30
|
+
meddle mock update <id> [options] Update a mock rule
|
|
31
|
+
meddle mock delete <id> Delete a mock rule
|
|
32
|
+
meddle mock enable <id> Enable a mock rule
|
|
33
|
+
meddle mock disable <id> Disable a mock rule
|
|
34
|
+
|
|
35
|
+
Add Options:
|
|
36
|
+
--name <n> Rule name
|
|
37
|
+
--pattern <p> URL pattern (regex or string)
|
|
38
|
+
--method <m> HTTP method (GET, POST, *, default: *)
|
|
39
|
+
--status <s> Response status code (default: 200)
|
|
40
|
+
--body <b> Response body content
|
|
41
|
+
--delay <d> Response delay in ms (default: 0)
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
meddle mock list
|
|
45
|
+
meddle mock add --name "API Mock" --pattern "example.com/api" --status 200
|
|
46
|
+
meddle mock update 1 --status 404
|
|
47
|
+
meddle mock delete 1
|
|
48
|
+
`)
|
|
49
|
+
process.exit(1)
|
|
50
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle mock list - List all mock rules
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const output = require('../../lib/output')
|
|
6
|
+
const { isProxyRunning } = require('../../lib/proxy-detect')
|
|
7
|
+
const { apiGet } = require('../../lib/api-client')
|
|
8
|
+
const { loadMockRules } = require('../../lib/file-access')
|
|
9
|
+
|
|
10
|
+
// Check for --json flag
|
|
11
|
+
const args = process.argv.slice(3)
|
|
12
|
+
const jsonFlag = args.includes('--json')
|
|
13
|
+
output.setJsonMode(jsonFlag)
|
|
14
|
+
|
|
15
|
+
async function run() {
|
|
16
|
+
const running = await isProxyRunning()
|
|
17
|
+
|
|
18
|
+
let rules = []
|
|
19
|
+
|
|
20
|
+
if (running) {
|
|
21
|
+
try {
|
|
22
|
+
rules = await apiGet('/api/mocks')
|
|
23
|
+
} catch (e) {
|
|
24
|
+
// Fallback to file mode
|
|
25
|
+
rules = loadMockRules()
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
rules = loadMockRules()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (jsonFlag) {
|
|
32
|
+
output.jsonRaw(rules)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
output.header(`Mock Rules (${rules.length} total)`)
|
|
37
|
+
|
|
38
|
+
if (rules.length === 0) {
|
|
39
|
+
output.info('No mock rules found')
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Separate active and inactive
|
|
44
|
+
const active = rules.filter(r => r.enabled)
|
|
45
|
+
const inactive = rules.filter(r => !r.enabled)
|
|
46
|
+
|
|
47
|
+
if (active.length > 0) {
|
|
48
|
+
output.section('Active Rules')
|
|
49
|
+
active.forEach(rule => {
|
|
50
|
+
output.success(`#${rule.id}: ${rule.name} (${rule.urlPattern})`)
|
|
51
|
+
output.kv('Status', rule.statusCode, 4)
|
|
52
|
+
output.kv('Method', rule.method || '*', 4)
|
|
53
|
+
output.kv('Delay', `${rule.delay || 0}ms`, 4)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (inactive.length > 0) {
|
|
58
|
+
output.section('Inactive Rules')
|
|
59
|
+
inactive.forEach(rule => {
|
|
60
|
+
output.bullet(`#${rule.id}: ${rule.name} (${rule.urlPattern})`, false)
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
run().catch(e => {
|
|
66
|
+
output.error(e.message)
|
|
67
|
+
process.exit(1)
|
|
68
|
+
})
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle mock enable/disable - Toggle mock rule enabled status
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const output = require('../../lib/output')
|
|
6
|
+
const { isProxyRunning } = require('../../lib/proxy-detect')
|
|
7
|
+
const { apiPut } = require('../../lib/api-client')
|
|
8
|
+
const { updateMockRule } = require('../../lib/file-access')
|
|
9
|
+
|
|
10
|
+
// Parse arguments
|
|
11
|
+
const args = process.argv.slice(2) // Full args: ['mock', 'enable'/'disable', '<id>']
|
|
12
|
+
const subcommand = args[1] // 'enable' or 'disable' (at index 1)
|
|
13
|
+
const jsonFlag = args.includes('--json')
|
|
14
|
+
output.setJsonMode(jsonFlag)
|
|
15
|
+
|
|
16
|
+
// Get id from positional argument
|
|
17
|
+
const idArg = args.find(a => !a.startsWith('--') && a !== 'mock' && a !== 'enable' && a !== 'disable')
|
|
18
|
+
const id = idArg ? parseInt(idArg, 10) : null
|
|
19
|
+
|
|
20
|
+
async function run() {
|
|
21
|
+
if (id === null) {
|
|
22
|
+
output.error('Missing required argument: <id>')
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const enabled = subcommand === 'enable'
|
|
27
|
+
|
|
28
|
+
const running = await isProxyRunning()
|
|
29
|
+
|
|
30
|
+
let result
|
|
31
|
+
if (running) {
|
|
32
|
+
try {
|
|
33
|
+
result = await apiPut(`/api/mocks/${id}`, { enabled })
|
|
34
|
+
result = result.rule || result
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Fallback to file mode
|
|
37
|
+
result = updateMockRule(id, { enabled })
|
|
38
|
+
if (!result) {
|
|
39
|
+
output.error(`Mock rule not found: id=${id}`)
|
|
40
|
+
process.exit(1)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
result = updateMockRule(id, { enabled })
|
|
45
|
+
if (!result) {
|
|
46
|
+
output.error(`Mock rule not found: id=${id}`)
|
|
47
|
+
process.exit(1)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (jsonFlag) {
|
|
52
|
+
output.jsonRaw(result)
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
output.header('Mock Rule Updated')
|
|
57
|
+
output.success(`#${result.id}: ${result.name}`)
|
|
58
|
+
output.kv('Enabled', enabled ? 'Yes' : 'No')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
run().catch(e => {
|
|
62
|
+
output.error(e.message)
|
|
63
|
+
process.exit(1)
|
|
64
|
+
})
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle mock update - Update a mock rule
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const output = require('../../lib/output')
|
|
6
|
+
const { isProxyRunning } = require('../../lib/proxy-detect')
|
|
7
|
+
const { apiPut } = require('../../lib/api-client')
|
|
8
|
+
const { updateMockRule, loadMockRules, saveMockRules } = require('../../lib/file-access')
|
|
9
|
+
|
|
10
|
+
// Parse arguments (skip 'mock' and 'update' from argv)
|
|
11
|
+
const args = process.argv.slice(4)
|
|
12
|
+
const jsonFlag = args.includes('--json')
|
|
13
|
+
output.setJsonMode(jsonFlag)
|
|
14
|
+
|
|
15
|
+
function parseArgs(args) {
|
|
16
|
+
// First positional arg is id
|
|
17
|
+
let id = null
|
|
18
|
+
const options = {}
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < args.length; i++) {
|
|
21
|
+
if (args[i] === '--name') options.name = args[++i]
|
|
22
|
+
else if (args[i] === '--pattern') options.urlPattern = args[++i]
|
|
23
|
+
else if (args[i] === '--method') options.method = args[++i]
|
|
24
|
+
else if (args[i] === '--status') options.statusCode = parseInt(args[++i], 10)
|
|
25
|
+
else if (args[i] === '--body') options.body = args[++i]
|
|
26
|
+
else if (args[i] === '--delay') options.delay = parseInt(args[++i], 10)
|
|
27
|
+
else if (args[i] === '--headers') {
|
|
28
|
+
try {
|
|
29
|
+
options.headers = JSON.parse(args[++i])
|
|
30
|
+
} catch (_) {
|
|
31
|
+
options.headers = {}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else if (!args[i].startsWith('--') && id === null) {
|
|
35
|
+
id = parseInt(args[i], 10)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return { id, options }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function run() {
|
|
43
|
+
const { id, options } = parseArgs(args)
|
|
44
|
+
|
|
45
|
+
if (id === null) {
|
|
46
|
+
output.error('Missing required argument: <id>')
|
|
47
|
+
process.exit(1)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (Object.keys(options).length === 0) {
|
|
51
|
+
output.error('No update options provided')
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const running = await isProxyRunning()
|
|
56
|
+
|
|
57
|
+
let result
|
|
58
|
+
if (running) {
|
|
59
|
+
try {
|
|
60
|
+
result = await apiPut(`/api/mocks/${id}`, options)
|
|
61
|
+
result = result.rule || result
|
|
62
|
+
} catch (e) {
|
|
63
|
+
// Fallback to file mode
|
|
64
|
+
result = updateMockRule(id, options)
|
|
65
|
+
if (!result) {
|
|
66
|
+
output.error(`Mock rule not found: id=${id}`)
|
|
67
|
+
process.exit(1)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
result = updateMockRule(id, options)
|
|
72
|
+
if (!result) {
|
|
73
|
+
output.error(`Mock rule not found: id=${id}`)
|
|
74
|
+
process.exit(1)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (jsonFlag) {
|
|
79
|
+
output.jsonRaw(result)
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
output.header('Mock Rule Updated')
|
|
84
|
+
output.success(`#${result.id}: ${result.name}`)
|
|
85
|
+
if (options.urlPattern) output.kv('Pattern', result.urlPattern)
|
|
86
|
+
if (options.method) output.kv('Method', result.method)
|
|
87
|
+
if (options.statusCode) output.kv('Status', result.statusCode)
|
|
88
|
+
if (options.delay) output.kv('Delay', `${result.delay}ms`)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
run().catch(e => {
|
|
92
|
+
output.error(e.message)
|
|
93
|
+
process.exit(1)
|
|
94
|
+
})
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle route active - Show or set active route files
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const output = require('../../lib/output')
|
|
6
|
+
const { isProxyRunning } = require('../../lib/proxy-detect')
|
|
7
|
+
const { apiGet, apiPut } = require('../../lib/api-client')
|
|
8
|
+
const { listRuleFiles, getActiveRuleFileNames, setActiveRuleFileNames, setRuleFileEnabled } = require('../../lib/file-access')
|
|
9
|
+
|
|
10
|
+
// Parse arguments (skip 'route' and 'active' from argv)
|
|
11
|
+
const args = process.argv.slice(4)
|
|
12
|
+
const jsonFlag = args.includes('--json')
|
|
13
|
+
output.setJsonMode(jsonFlag)
|
|
14
|
+
|
|
15
|
+
// Check for 'set' subcommand - now 'set' would be at args[0] if present
|
|
16
|
+
const isSet = args[0] === 'set'
|
|
17
|
+
const targetFile = isSet ? args[1] : null
|
|
18
|
+
|
|
19
|
+
async function run() {
|
|
20
|
+
const running = await isProxyRunning()
|
|
21
|
+
|
|
22
|
+
if (isSet) {
|
|
23
|
+
if (!targetFile) {
|
|
24
|
+
output.error('Missing required argument: <file>')
|
|
25
|
+
process.exit(1)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Set active route file (disable others, enable this one)
|
|
29
|
+
if (running) {
|
|
30
|
+
try {
|
|
31
|
+
const files = await apiGet('/api/rule-files')
|
|
32
|
+
if (!Array.isArray(files)) {
|
|
33
|
+
throw new Error('规则文件列表返回格式错误')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const target = files.find(f => f && f.name === targetFile)
|
|
37
|
+
if (!target) {
|
|
38
|
+
output.error(`Route file not found: ${targetFile}`)
|
|
39
|
+
process.exit(1)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const f of files) {
|
|
43
|
+
const nextEnabled = f.name === targetFile
|
|
44
|
+
if (!!f.enabled === nextEnabled) continue
|
|
45
|
+
await apiPut(`/api/rule-files/${encodeURIComponent(f.name)}`, { enabled: nextEnabled })
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (jsonFlag) {
|
|
49
|
+
output.jsonRaw({ success: true, activeFile: targetFile })
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
output.header('Active Route File Set')
|
|
54
|
+
output.success(targetFile)
|
|
55
|
+
} catch (e) {
|
|
56
|
+
// Fallback to file mode
|
|
57
|
+
const files = listRuleFiles()
|
|
58
|
+
const target = files.find(f => f.name === targetFile)
|
|
59
|
+
if (!target) {
|
|
60
|
+
output.error(`Route file not found: ${targetFile}`)
|
|
61
|
+
process.exit(1)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Disable all, then enable target
|
|
65
|
+
files.forEach(f => setRuleFileEnabled(f.name, f.name === targetFile))
|
|
66
|
+
|
|
67
|
+
if (jsonFlag) {
|
|
68
|
+
output.jsonRaw({ success: true, activeFile: targetFile })
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
output.header('Active Route File Set')
|
|
73
|
+
output.success(targetFile)
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
// File mode
|
|
77
|
+
const files = listRuleFiles()
|
|
78
|
+
const target = files.find(f => f.name === targetFile)
|
|
79
|
+
if (!target) {
|
|
80
|
+
output.error(`Route file not found: ${targetFile}`)
|
|
81
|
+
process.exit(1)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
files.forEach(f => setRuleFileEnabled(f.name, f.name === targetFile))
|
|
85
|
+
|
|
86
|
+
if (jsonFlag) {
|
|
87
|
+
output.jsonRaw({ success: true, activeFile: targetFile })
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
output.header('Active Route File Set')
|
|
92
|
+
output.success(targetFile)
|
|
93
|
+
}
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Show active route files
|
|
98
|
+
let files = []
|
|
99
|
+
let activeFiles = []
|
|
100
|
+
|
|
101
|
+
if (running) {
|
|
102
|
+
try {
|
|
103
|
+
files = await apiGet('/api/rule-files')
|
|
104
|
+
activeFiles = Array.isArray(files) ? files.filter(f => f && f.enabled).map(f => f.name) : []
|
|
105
|
+
} catch (e) {
|
|
106
|
+
activeFiles = getActiveRuleFileNames()
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
activeFiles = getActiveRuleFileNames()
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const currentRuleFile = activeFiles.length === 1 ? activeFiles[0] : null
|
|
113
|
+
|
|
114
|
+
if (jsonFlag) {
|
|
115
|
+
output.jsonRaw({
|
|
116
|
+
currentRuleFile,
|
|
117
|
+
activeRuleFiles: activeFiles,
|
|
118
|
+
count: activeFiles.length
|
|
119
|
+
})
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
output.header('Active Route Files')
|
|
124
|
+
|
|
125
|
+
if (activeFiles.length === 0) {
|
|
126
|
+
output.info('No active route files')
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (currentRuleFile) {
|
|
131
|
+
output.kv('Current', currentRuleFile)
|
|
132
|
+
} else {
|
|
133
|
+
output.kv('Active Files', activeFiles.length)
|
|
134
|
+
activeFiles.forEach(f => output.bullet(f, true))
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
run().catch(e => {
|
|
139
|
+
output.error(e.message)
|
|
140
|
+
process.exit(1)
|
|
141
|
+
})
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* meddle route add - Add a rule to a route file
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const output = require('../../lib/output')
|
|
6
|
+
const { isProxyRunning } = require('../../lib/proxy-detect')
|
|
7
|
+
const { apiGet, apiPut } = require('../../lib/api-client')
|
|
8
|
+
const { getRuleFileContent, saveRuleFileContent, parseEprc, ruleMapToEprcText } = require('../../lib/file-access')
|
|
9
|
+
|
|
10
|
+
// Parse arguments (skip 'route' and 'add' from argv)
|
|
11
|
+
const args = process.argv.slice(4)
|
|
12
|
+
const jsonFlag = args.includes('--json')
|
|
13
|
+
output.setJsonMode(jsonFlag)
|
|
14
|
+
|
|
15
|
+
// Get positional arguments: file, pattern, target
|
|
16
|
+
const positionalArgs = args.filter(a => !a.startsWith('--'))
|
|
17
|
+
const fileName = positionalArgs[0]
|
|
18
|
+
const pattern = positionalArgs[1]
|
|
19
|
+
const target = positionalArgs[2]
|
|
20
|
+
|
|
21
|
+
async function run() {
|
|
22
|
+
if (!fileName) {
|
|
23
|
+
output.error('Missing required argument: <file>')
|
|
24
|
+
process.exit(1)
|
|
25
|
+
}
|
|
26
|
+
if (!pattern) {
|
|
27
|
+
output.error('Missing required argument: <pattern>')
|
|
28
|
+
process.exit(1)
|
|
29
|
+
}
|
|
30
|
+
if (!target) {
|
|
31
|
+
output.error('Missing required argument: <target>')
|
|
32
|
+
process.exit(1)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const running = await isProxyRunning()
|
|
36
|
+
|
|
37
|
+
const pat = pattern.trim()
|
|
38
|
+
const tgt = target.trim()
|
|
39
|
+
|
|
40
|
+
if (running) {
|
|
41
|
+
try {
|
|
42
|
+
// Get current content
|
|
43
|
+
let content = await apiGet(`/api/rule-files/${encodeURIComponent(fileName)}/content`)
|
|
44
|
+
const text = typeof content === 'string' ? content : String(content)
|
|
45
|
+
const ruleMap = parseEprc(text)
|
|
46
|
+
|
|
47
|
+
// Handle [marker] syntax
|
|
48
|
+
const bm = pat.match(/\[([^\]]+)\]/)
|
|
49
|
+
if (bm) {
|
|
50
|
+
ruleMap[pat.replace(bm[0], bm[1])] = tgt + bm[0]
|
|
51
|
+
} else {
|
|
52
|
+
ruleMap[pat] = tgt
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const newContent = ruleMapToEprcText(ruleMap)
|
|
56
|
+
await apiPut(`/api/rule-files/${encodeURIComponent(fileName)}/content`, { content: newContent })
|
|
57
|
+
|
|
58
|
+
if (jsonFlag) {
|
|
59
|
+
output.jsonRaw({ success: true, file: fileName, pattern: pat, target: tgt })
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
output.header('Route Rule Added')
|
|
64
|
+
output.success(`${pat} -> ${tgt}`)
|
|
65
|
+
output.kv('File', fileName)
|
|
66
|
+
} catch (e) {
|
|
67
|
+
// Fallback to file mode
|
|
68
|
+
const content = getRuleFileContent(fileName)
|
|
69
|
+
if (!content) {
|
|
70
|
+
output.error(`Route file not found: ${fileName}`)
|
|
71
|
+
process.exit(1)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const ruleMap = parseEprc(content)
|
|
75
|
+
const bm = pat.match(/\[([^\]]+)\]/)
|
|
76
|
+
if (bm) {
|
|
77
|
+
ruleMap[pat.replace(bm[0], bm[1])] = tgt + bm[0]
|
|
78
|
+
} else {
|
|
79
|
+
ruleMap[pat] = tgt
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const newContent = ruleMapToEprcText(ruleMap)
|
|
83
|
+
saveRuleFileContent(fileName, newContent)
|
|
84
|
+
|
|
85
|
+
if (jsonFlag) {
|
|
86
|
+
output.jsonRaw({ success: true, file: fileName, pattern: pat, target: tgt })
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
output.header('Route Rule Added')
|
|
91
|
+
output.success(`${pat} -> ${tgt}`)
|
|
92
|
+
output.kv('File', fileName)
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
// File mode
|
|
96
|
+
const content = getRuleFileContent(fileName)
|
|
97
|
+
if (!content) {
|
|
98
|
+
output.error(`Route file not found: ${fileName}`)
|
|
99
|
+
process.exit(1)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const ruleMap = parseEprc(content)
|
|
103
|
+
const bm = pat.match(/\[([^\]]+)\]/)
|
|
104
|
+
if (bm) {
|
|
105
|
+
ruleMap[pat.replace(bm[0], bm[1])] = tgt + bm[0]
|
|
106
|
+
} else {
|
|
107
|
+
ruleMap[pat] = tgt
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const newContent = ruleMapToEprcText(ruleMap)
|
|
111
|
+
saveRuleFileContent(fileName, newContent)
|
|
112
|
+
|
|
113
|
+
if (jsonFlag) {
|
|
114
|
+
output.jsonRaw({ success: true, file: fileName, pattern: pat, target: tgt })
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
output.header('Route Rule Added')
|
|
119
|
+
output.success(`${pat} -> ${tgt}`)
|
|
120
|
+
output.kv('File', fileName)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
run().catch(e => {
|
|
125
|
+
output.error(e.message)
|
|
126
|
+
process.exit(1)
|
|
127
|
+
})
|