@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,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct file operations for when proxy is not running
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const path = require('path')
|
|
7
|
+
const { meddleDir } = require('./proxy-detect')
|
|
8
|
+
|
|
9
|
+
const routeRulesDir = path.join(meddleDir, 'route-rules')
|
|
10
|
+
const settingsPath = path.join(meddleDir, 'settings.json')
|
|
11
|
+
const defaultMocksPath = path.join(meddleDir, 'mocks.json')
|
|
12
|
+
|
|
13
|
+
// ========== Settings ==========
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Load settings.json
|
|
17
|
+
*/
|
|
18
|
+
function loadSettings() {
|
|
19
|
+
try {
|
|
20
|
+
if (fs.existsSync(settingsPath)) {
|
|
21
|
+
return JSON.parse(fs.readFileSync(settingsPath, 'utf8'))
|
|
22
|
+
}
|
|
23
|
+
} catch (_) {}
|
|
24
|
+
return {}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Save settings.json
|
|
29
|
+
*/
|
|
30
|
+
function saveSettings(settings) {
|
|
31
|
+
const dir = path.dirname(settingsPath)
|
|
32
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
|
|
33
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get active rule file names
|
|
38
|
+
*/
|
|
39
|
+
function getActiveRuleFileNames() {
|
|
40
|
+
const settings = loadSettings()
|
|
41
|
+
const arr = settings.activeRuleFiles
|
|
42
|
+
return Array.isArray(arr) ? arr : []
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Set active rule file names
|
|
47
|
+
*/
|
|
48
|
+
function setActiveRuleFileNames(names) {
|
|
49
|
+
const settings = loadSettings()
|
|
50
|
+
settings.activeRuleFiles = names
|
|
51
|
+
saveSettings(settings)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ========== Mocks ==========
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get mocks file path (supports custom path in settings)
|
|
58
|
+
*/
|
|
59
|
+
function getMocksPath() {
|
|
60
|
+
const settings = loadSettings()
|
|
61
|
+
return settings.mocksFilePath || defaultMocksPath
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Load mock rules from file
|
|
66
|
+
*/
|
|
67
|
+
function loadMockRules() {
|
|
68
|
+
const mocksPath = getMocksPath()
|
|
69
|
+
try {
|
|
70
|
+
if (fs.existsSync(mocksPath)) {
|
|
71
|
+
const data = JSON.parse(fs.readFileSync(mocksPath, 'utf8'))
|
|
72
|
+
return data.rules || []
|
|
73
|
+
}
|
|
74
|
+
} catch (_) {}
|
|
75
|
+
return []
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Save mock rules to file
|
|
80
|
+
*/
|
|
81
|
+
function saveMockRules(rules) {
|
|
82
|
+
const mocksPath = getMocksPath()
|
|
83
|
+
const dir = path.dirname(mocksPath)
|
|
84
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
|
|
85
|
+
|
|
86
|
+
// Find max id for sequence
|
|
87
|
+
let maxId = 0
|
|
88
|
+
rules.forEach(r => {
|
|
89
|
+
if (r.id > maxId) maxId = r.id
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
const data = {
|
|
93
|
+
rules,
|
|
94
|
+
lastId: maxId
|
|
95
|
+
}
|
|
96
|
+
fs.writeFileSync(mocksPath, JSON.stringify(data, null, 2), 'utf8')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Add mock rule
|
|
101
|
+
*/
|
|
102
|
+
function addMockRule(rule) {
|
|
103
|
+
const rules = loadMockRules()
|
|
104
|
+
const mocksPath = getMocksPath()
|
|
105
|
+
|
|
106
|
+
// Get next id
|
|
107
|
+
let nextId = 1
|
|
108
|
+
try {
|
|
109
|
+
if (fs.existsSync(mocksPath)) {
|
|
110
|
+
const data = JSON.parse(fs.readFileSync(mocksPath, 'utf8'))
|
|
111
|
+
nextId = (data.lastId || 0) + 1
|
|
112
|
+
}
|
|
113
|
+
} catch (_) {}
|
|
114
|
+
if (rules.length > 0) {
|
|
115
|
+
const maxId = Math.max(...rules.map(r => r.id))
|
|
116
|
+
if (maxId >= nextId) nextId = maxId + 1
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
rule.id = nextId
|
|
120
|
+
rules.push(rule)
|
|
121
|
+
saveMockRules(rules)
|
|
122
|
+
return rule
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Update mock rule by id
|
|
127
|
+
*/
|
|
128
|
+
function updateMockRule(id, updates) {
|
|
129
|
+
const rules = loadMockRules()
|
|
130
|
+
const idx = rules.findIndex(r => r.id === id)
|
|
131
|
+
if (idx === -1) return null
|
|
132
|
+
rules[idx] = { ...rules[idx], ...updates, id }
|
|
133
|
+
saveMockRules(rules)
|
|
134
|
+
return rules[idx]
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Delete mock rule by id
|
|
139
|
+
*/
|
|
140
|
+
function deleteMockRule(id) {
|
|
141
|
+
const rules = loadMockRules()
|
|
142
|
+
const idx = rules.findIndex(r => r.id === id)
|
|
143
|
+
if (idx === -1) return false
|
|
144
|
+
rules.splice(idx, 1)
|
|
145
|
+
saveMockRules(rules)
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ========== Route Rules ==========
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Ensure route-rules directory exists
|
|
153
|
+
*/
|
|
154
|
+
function ensureRouteRulesDir() {
|
|
155
|
+
if (!fs.existsSync(routeRulesDir)) {
|
|
156
|
+
fs.mkdirSync(routeRulesDir, { recursive: true })
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get rule file path
|
|
162
|
+
*/
|
|
163
|
+
function getRuleFilePath(name) {
|
|
164
|
+
return path.join(routeRulesDir, `${name}.txt`)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* List all rule files
|
|
169
|
+
*/
|
|
170
|
+
function listRuleFiles() {
|
|
171
|
+
ensureRouteRulesDir()
|
|
172
|
+
const activeNames = getActiveRuleFileNames()
|
|
173
|
+
|
|
174
|
+
const files = fs.readdirSync(routeRulesDir)
|
|
175
|
+
.filter(f => f.endsWith('.txt'))
|
|
176
|
+
.map(f => f.replace(/\.txt$/, ''))
|
|
177
|
+
|
|
178
|
+
return files.map(name => {
|
|
179
|
+
const filePath = getRuleFilePath(name)
|
|
180
|
+
let ruleCount = 0
|
|
181
|
+
let excludeCount = 0
|
|
182
|
+
try {
|
|
183
|
+
const content = fs.readFileSync(filePath, 'utf8')
|
|
184
|
+
const { ruleMap, excludeMap } = parseEprcWithExclusions(content)
|
|
185
|
+
ruleCount = Object.keys(ruleMap).length
|
|
186
|
+
// Count total exclusions across all rules
|
|
187
|
+
for (const exclusions of Object.values(excludeMap)) {
|
|
188
|
+
excludeCount += exclusions.length
|
|
189
|
+
}
|
|
190
|
+
} catch (_) {}
|
|
191
|
+
return {
|
|
192
|
+
name,
|
|
193
|
+
enabled: activeNames.includes(name),
|
|
194
|
+
ruleCount,
|
|
195
|
+
excludeCount
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Get rule file content
|
|
202
|
+
*/
|
|
203
|
+
function getRuleFileContent(name) {
|
|
204
|
+
const filePath = getRuleFilePath(name)
|
|
205
|
+
try {
|
|
206
|
+
if (fs.existsSync(filePath)) {
|
|
207
|
+
return fs.readFileSync(filePath, 'utf8')
|
|
208
|
+
}
|
|
209
|
+
} catch (_) {}
|
|
210
|
+
return null
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Save rule file content
|
|
215
|
+
*/
|
|
216
|
+
function saveRuleFileContent(name, content) {
|
|
217
|
+
ensureRouteRulesDir()
|
|
218
|
+
const filePath = getRuleFilePath(name)
|
|
219
|
+
fs.writeFileSync(filePath, content, 'utf8')
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Create rule file
|
|
224
|
+
*/
|
|
225
|
+
function createRuleFile(name, content = '', enabled = true) {
|
|
226
|
+
ensureRouteRulesDir()
|
|
227
|
+
const safeName = name.trim().replace(/[/\\:*?"<>|]/g, '_')
|
|
228
|
+
const filePath = getRuleFilePath(safeName)
|
|
229
|
+
|
|
230
|
+
if (fs.existsSync(filePath)) {
|
|
231
|
+
throw new Error(`规则文件 "${safeName}" 已存在`)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
fs.writeFileSync(filePath, content, 'utf8')
|
|
235
|
+
|
|
236
|
+
if (enabled) {
|
|
237
|
+
const activeNames = getActiveRuleFileNames()
|
|
238
|
+
if (!activeNames.includes(safeName)) {
|
|
239
|
+
activeNames.push(safeName)
|
|
240
|
+
setActiveRuleFileNames(activeNames)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const ruleCount = content.trim() ? Object.keys(parseEprc(content)).length : 0
|
|
245
|
+
return { name: safeName, enabled, ruleCount }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Delete rule file
|
|
250
|
+
*/
|
|
251
|
+
function deleteRuleFile(name) {
|
|
252
|
+
const filePath = getRuleFilePath(name)
|
|
253
|
+
if (!fs.existsSync(filePath)) {
|
|
254
|
+
throw new Error('规则文件不存在')
|
|
255
|
+
}
|
|
256
|
+
fs.unlinkSync(filePath)
|
|
257
|
+
|
|
258
|
+
const activeNames = getActiveRuleFileNames()
|
|
259
|
+
const idx = activeNames.indexOf(name)
|
|
260
|
+
if (idx !== -1) {
|
|
261
|
+
activeNames.splice(idx, 1)
|
|
262
|
+
setActiveRuleFileNames(activeNames)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Enable/disable rule file
|
|
268
|
+
*/
|
|
269
|
+
function setRuleFileEnabled(name, enabled) {
|
|
270
|
+
const filePath = getRuleFilePath(name)
|
|
271
|
+
if (!fs.existsSync(filePath)) {
|
|
272
|
+
throw new Error('规则文件不存在')
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const activeNames = getActiveRuleFileNames()
|
|
276
|
+
const idx = activeNames.indexOf(name)
|
|
277
|
+
|
|
278
|
+
if (enabled && idx === -1) {
|
|
279
|
+
activeNames.push(name)
|
|
280
|
+
} else if (!enabled && idx !== -1) {
|
|
281
|
+
activeNames.splice(idx, 1)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
setActiveRuleFileNames(activeNames)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get content of all active rule files merged
|
|
289
|
+
*/
|
|
290
|
+
function getActiveRuleFilesContent() {
|
|
291
|
+
const activeNames = getActiveRuleFileNames()
|
|
292
|
+
const contents = []
|
|
293
|
+
for (const name of activeNames) {
|
|
294
|
+
const content = getRuleFileContent(name)
|
|
295
|
+
if (content) {
|
|
296
|
+
contents.push(content)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return contents.join('\n')
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ========== Parser (imported) ==========
|
|
303
|
+
|
|
304
|
+
const { parseEprc, parseEprcWithExclusions, ruleMapToEprcText } = require('./parsers')
|
|
305
|
+
|
|
306
|
+
module.exports = {
|
|
307
|
+
// Settings
|
|
308
|
+
loadSettings,
|
|
309
|
+
saveSettings,
|
|
310
|
+
getActiveRuleFileNames,
|
|
311
|
+
setActiveRuleFileNames,
|
|
312
|
+
|
|
313
|
+
// Mocks
|
|
314
|
+
getMocksPath,
|
|
315
|
+
loadMockRules,
|
|
316
|
+
saveMockRules,
|
|
317
|
+
addMockRule,
|
|
318
|
+
updateMockRule,
|
|
319
|
+
deleteMockRule,
|
|
320
|
+
|
|
321
|
+
// Route Rules
|
|
322
|
+
routeRulesDir,
|
|
323
|
+
ensureRouteRulesDir,
|
|
324
|
+
getRuleFilePath,
|
|
325
|
+
listRuleFiles,
|
|
326
|
+
getRuleFileContent,
|
|
327
|
+
getActiveRuleFilesContent,
|
|
328
|
+
saveRuleFileContent,
|
|
329
|
+
createRuleFile,
|
|
330
|
+
deleteRuleFile,
|
|
331
|
+
setRuleFileEnabled,
|
|
332
|
+
|
|
333
|
+
// Parser (re-exported)
|
|
334
|
+
parseEprc,
|
|
335
|
+
parseEprcWithExclusions,
|
|
336
|
+
ruleMapToEprcText
|
|
337
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MEDDLE_HOME resolver — single source of truth for meddle data directory.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order:
|
|
5
|
+
* 1. MEDDLE_HOME env var (if set and non-empty)
|
|
6
|
+
* 2. ~/.meddle (default, backward compatible)
|
|
7
|
+
*
|
|
8
|
+
* Pure JS so the CLI can require it without a build step.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const os = require('os')
|
|
12
|
+
const path = require('path')
|
|
13
|
+
|
|
14
|
+
function resolveMeddleHome() {
|
|
15
|
+
const fromEnv = (process.env.MEDDLE_HOME || '').trim()
|
|
16
|
+
if (fromEnv) return path.resolve(fromEnv)
|
|
17
|
+
return path.resolve(os.homedir(), '.meddle')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = { resolveMeddleHome }
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatter for CLI commands
|
|
3
|
+
* Supports both human-readable and JSON output
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const chalk = require('chalk')
|
|
7
|
+
|
|
8
|
+
let jsonMode = false
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Set JSON output mode
|
|
12
|
+
*/
|
|
13
|
+
function setJsonMode(mode) {
|
|
14
|
+
jsonMode = mode
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if JSON mode is enabled
|
|
19
|
+
*/
|
|
20
|
+
function isJsonMode() {
|
|
21
|
+
return jsonMode
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Print header with title
|
|
26
|
+
*/
|
|
27
|
+
function header(title) {
|
|
28
|
+
if (jsonMode) return
|
|
29
|
+
console.log('')
|
|
30
|
+
console.log(chalk.bold.cyan('════════════════════════════════════════'))
|
|
31
|
+
console.log(chalk.bold.cyan(` ${title}`))
|
|
32
|
+
console.log(chalk.bold.cyan('════════════════════════════════════════'))
|
|
33
|
+
console.log('')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Print section header
|
|
38
|
+
*/
|
|
39
|
+
function section(title) {
|
|
40
|
+
if (jsonMode) return
|
|
41
|
+
console.log(chalk.bold.yellow(`\n▶ ${title}`))
|
|
42
|
+
console.log(chalk.gray('─'.repeat(40)))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Print success message
|
|
47
|
+
*/
|
|
48
|
+
function success(message) {
|
|
49
|
+
if (jsonMode) return
|
|
50
|
+
console.log(chalk.green(' ✓'), message)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Print error message
|
|
55
|
+
*/
|
|
56
|
+
function error(message) {
|
|
57
|
+
if (jsonMode) return
|
|
58
|
+
console.log(chalk.red(' ✗'), message)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Print warning message
|
|
63
|
+
*/
|
|
64
|
+
function warning(message) {
|
|
65
|
+
if (jsonMode) return
|
|
66
|
+
console.log(chalk.yellow(' ⚠'), message)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Print info message
|
|
71
|
+
*/
|
|
72
|
+
function info(message) {
|
|
73
|
+
if (jsonMode) return
|
|
74
|
+
console.log(chalk.gray(' →'), message)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Print JSON output (only in JSON mode)
|
|
79
|
+
*/
|
|
80
|
+
function json(data) {
|
|
81
|
+
if (!jsonMode) return
|
|
82
|
+
console.log(JSON.stringify(data, null, 2))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Print raw JSON (without formatting, for --json output)
|
|
87
|
+
*/
|
|
88
|
+
function jsonRaw(data) {
|
|
89
|
+
console.log(JSON.stringify(data))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Print plain text message
|
|
94
|
+
*/
|
|
95
|
+
function plain(message) {
|
|
96
|
+
if (jsonMode) return
|
|
97
|
+
console.log(message)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Print key-value pair
|
|
102
|
+
*/
|
|
103
|
+
function kv(key, value, indent = 2) {
|
|
104
|
+
if (jsonMode) return
|
|
105
|
+
const spaces = ' '.repeat(indent)
|
|
106
|
+
console.log(spaces + chalk.gray(key + ':'), value)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Print bullet item
|
|
111
|
+
*/
|
|
112
|
+
function bullet(message, active = false, indent = 2) {
|
|
113
|
+
if (jsonMode) return
|
|
114
|
+
const spaces = ' '.repeat(indent)
|
|
115
|
+
const marker = active ? chalk.green('●') : chalk.gray('○')
|
|
116
|
+
console.log(spaces + marker, message)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Print table row
|
|
121
|
+
*/
|
|
122
|
+
function tableRow(columns, widths) {
|
|
123
|
+
if (jsonMode) return
|
|
124
|
+
const row = columns.map((col, i) => {
|
|
125
|
+
const width = widths[i] || 10
|
|
126
|
+
return String(col).padEnd(width)
|
|
127
|
+
}).join(' ')
|
|
128
|
+
console.log(' ' + row)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
setJsonMode,
|
|
133
|
+
isJsonMode,
|
|
134
|
+
header,
|
|
135
|
+
section,
|
|
136
|
+
success,
|
|
137
|
+
error,
|
|
138
|
+
warning,
|
|
139
|
+
info,
|
|
140
|
+
json,
|
|
141
|
+
jsonRaw,
|
|
142
|
+
plain,
|
|
143
|
+
kv,
|
|
144
|
+
bullet,
|
|
145
|
+
tableRow
|
|
146
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EPRC file parsers
|
|
3
|
+
* Ported from helpers.ts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const path = require('path')
|
|
7
|
+
|
|
8
|
+
const FILE_PATTERN = /^file:\/\//
|
|
9
|
+
const LOCAL_FILE_PATTERN = /^[A-Za-z]:\\|^\/|^\\/
|
|
10
|
+
|
|
11
|
+
function routeRulesToLegacyMaps(rules) {
|
|
12
|
+
const ruleMap = Object.create(null)
|
|
13
|
+
const excludeMap = Object.create(null)
|
|
14
|
+
for (const entry of rules) {
|
|
15
|
+
ruleMap[entry.pattern] = entry.target
|
|
16
|
+
excludeMap[entry.pattern] = entry.exclusions.slice()
|
|
17
|
+
}
|
|
18
|
+
return { ruleMap, excludeMap }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Parse EPRC content into ordered rules + legacy ruleMap/excludeMap
|
|
23
|
+
*/
|
|
24
|
+
function parseEprcWithExclusions(content) {
|
|
25
|
+
const rules = []
|
|
26
|
+
|
|
27
|
+
content.split(/\r?\n/).forEach(line => {
|
|
28
|
+
const trimmed = line.trim()
|
|
29
|
+
if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('//')) return
|
|
30
|
+
|
|
31
|
+
const parts = trimmed.split(/\s+/).filter(Boolean)
|
|
32
|
+
if (parts.length < 2) return
|
|
33
|
+
|
|
34
|
+
const exclusions = []
|
|
35
|
+
const regularParts = parts.filter(p => {
|
|
36
|
+
if (p.startsWith('!')) {
|
|
37
|
+
exclusions.push(p.slice(1))
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
return true
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
if (regularParts.length < 2) return
|
|
44
|
+
|
|
45
|
+
let target = regularParts[regularParts.length - 1]
|
|
46
|
+
const patterns = regularParts.slice(0, -1)
|
|
47
|
+
|
|
48
|
+
if (LOCAL_FILE_PATTERN.test(target) && !FILE_PATTERN.test(target)) {
|
|
49
|
+
target = 'file://' + target.replace(/\\/g, '/')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const lineExclusions = exclusions.slice()
|
|
53
|
+
|
|
54
|
+
patterns.forEach(rule => {
|
|
55
|
+
const bm = rule.match(/\[([^\]]+)\]/)
|
|
56
|
+
let patternKey
|
|
57
|
+
let storedTarget = target
|
|
58
|
+
if (bm) {
|
|
59
|
+
patternKey = rule.replace(bm[0], bm[1])
|
|
60
|
+
storedTarget = target + bm[0]
|
|
61
|
+
} else {
|
|
62
|
+
patternKey = rule
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
rules.push({
|
|
66
|
+
pattern: patternKey,
|
|
67
|
+
target: storedTarget,
|
|
68
|
+
exclusions: lineExclusions,
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const { ruleMap, excludeMap } = routeRulesToLegacyMaps(rules)
|
|
74
|
+
return { rules, ruleMap, excludeMap }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Parse EPRC content into ruleMap (without exclusions)
|
|
79
|
+
*/
|
|
80
|
+
function parseEprc(content) {
|
|
81
|
+
return parseEprcWithExclusions(content).ruleMap
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Convert ruleMap back to EPRC text format
|
|
86
|
+
*/
|
|
87
|
+
function ruleMapToEprcText(ruleMap, excludeMap) {
|
|
88
|
+
const entries = Object.entries(ruleMap)
|
|
89
|
+
if (entries.length === 0) return ''
|
|
90
|
+
|
|
91
|
+
const byTargetAndExclusions = {}
|
|
92
|
+
|
|
93
|
+
entries.forEach(([rule, target]) => {
|
|
94
|
+
const bm = target.match(/\[([^\]]+)\]/)
|
|
95
|
+
const groupKey = bm ? target.replace(bm[0], '') : target
|
|
96
|
+
const displayRule = bm ? rule.replace(bm[1], bm[0]) : rule
|
|
97
|
+
const exclusions = excludeMap?.[rule] || []
|
|
98
|
+
const exclusionsKey = exclusions.join(',')
|
|
99
|
+
|
|
100
|
+
const compoundKey = `${groupKey}|||${exclusionsKey}`
|
|
101
|
+
|
|
102
|
+
if (!byTargetAndExclusions[compoundKey]) {
|
|
103
|
+
byTargetAndExclusions[compoundKey] = { target: groupKey, rules: [], exclusions }
|
|
104
|
+
}
|
|
105
|
+
byTargetAndExclusions[compoundKey].rules.push(displayRule)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
return Object.values(byTargetAndExclusions)
|
|
109
|
+
.map(({ target, rules, exclusions }) => {
|
|
110
|
+
let displayTarget = target
|
|
111
|
+
if (FILE_PATTERN.test(target)) {
|
|
112
|
+
displayTarget = target.replace(/^file:\/\//, '').replace(/\//g, path.sep)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const exclusionStr = exclusions.map(e => `!${e}`).join(' ')
|
|
116
|
+
const rulesStr = rules.join(' ')
|
|
117
|
+
return exclusionStr ? `${rulesStr} ${exclusionStr} ${displayTarget}` : `${rulesStr} ${displayTarget}`
|
|
118
|
+
})
|
|
119
|
+
.join('\n')
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
module.exports = {
|
|
123
|
+
parseEprcWithExclusions,
|
|
124
|
+
parseEprc,
|
|
125
|
+
ruleMapToEprcText,
|
|
126
|
+
routeRulesToLegacyMaps,
|
|
127
|
+
}
|