@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.
Files changed (361) hide show
  1. package/CONFIG_STRUCTURE.md +315 -0
  2. package/LICENSE +21 -0
  3. package/README.md +298 -0
  4. package/bin/commands/mock/add.js +92 -0
  5. package/bin/commands/mock/delete.js +58 -0
  6. package/bin/commands/mock/index.js +50 -0
  7. package/bin/commands/mock/list.js +68 -0
  8. package/bin/commands/mock/toggle.js +64 -0
  9. package/bin/commands/mock/update.js +94 -0
  10. package/bin/commands/route/active.js +141 -0
  11. package/bin/commands/route/add.js +127 -0
  12. package/bin/commands/route/create.js +77 -0
  13. package/bin/commands/route/delete.js +120 -0
  14. package/bin/commands/route/index.js +59 -0
  15. package/bin/commands/route/list.js +67 -0
  16. package/bin/commands/route/preview.js +159 -0
  17. package/bin/commands/route/show.js +111 -0
  18. package/bin/commands/route/update.js +126 -0
  19. package/bin/commands/session/create.js +166 -0
  20. package/bin/commands/session/delete.js +69 -0
  21. package/bin/commands/session/index.js +61 -0
  22. package/bin/commands/session/list.js +42 -0
  23. package/bin/commands/session/prune.js +31 -0
  24. package/bin/commands/start.js +43 -0
  25. package/bin/commands/status.js +115 -0
  26. package/bin/commands/supervise.js +106 -0
  27. package/bin/commands/url.js +30 -0
  28. package/bin/doctor.js +356 -0
  29. package/bin/index +130 -0
  30. package/bin/lib/api-client.js +72 -0
  31. package/bin/lib/file-access.js +337 -0
  32. package/bin/lib/meddle-home.js +20 -0
  33. package/bin/lib/output.js +146 -0
  34. package/bin/lib/parsers.js +127 -0
  35. package/bin/lib/proxy-detect.js +105 -0
  36. package/bin/lib/route-preview.js +180 -0
  37. package/bin/lib/session-args.js +54 -0
  38. package/bin/lib/sessions.js +213 -0
  39. package/dist/cert.d.ts +10 -0
  40. package/dist/cert.d.ts.map +1 -0
  41. package/dist/cert.js +184 -0
  42. package/dist/cert.js.map +1 -0
  43. package/dist/core/application-identity.d.ts +55 -0
  44. package/dist/core/application-identity.d.ts.map +1 -0
  45. package/dist/core/application-identity.js +321 -0
  46. package/dist/core/application-identity.js.map +1 -0
  47. package/dist/core/body-utils.d.ts +2 -0
  48. package/dist/core/body-utils.d.ts.map +1 -0
  49. package/dist/core/body-utils.js +21 -0
  50. package/dist/core/body-utils.js.map +1 -0
  51. package/dist/core/browser.d.ts +2 -0
  52. package/dist/core/browser.d.ts.map +1 -0
  53. package/dist/core/browser.js +92 -0
  54. package/dist/core/browser.js.map +1 -0
  55. package/dist/core/client-identity.d.ts +27 -0
  56. package/dist/core/client-identity.d.ts.map +1 -0
  57. package/dist/core/client-identity.js +136 -0
  58. package/dist/core/client-identity.js.map +1 -0
  59. package/dist/core/config-diagnostics.d.ts +14 -0
  60. package/dist/core/config-diagnostics.d.ts.map +1 -0
  61. package/dist/core/config-diagnostics.js +137 -0
  62. package/dist/core/config-diagnostics.js.map +1 -0
  63. package/dist/core/connect-tunnel.d.ts +5 -0
  64. package/dist/core/connect-tunnel.d.ts.map +1 -0
  65. package/dist/core/connect-tunnel.js +45 -0
  66. package/dist/core/connect-tunnel.js.map +1 -0
  67. package/dist/core/content-encoding.d.ts +2 -0
  68. package/dist/core/content-encoding.d.ts.map +1 -0
  69. package/dist/core/content-encoding.js +77 -0
  70. package/dist/core/content-encoding.js.map +1 -0
  71. package/dist/core/custom-plugin-loader.d.ts +18 -0
  72. package/dist/core/custom-plugin-loader.d.ts.map +1 -0
  73. package/dist/core/custom-plugin-loader.js +178 -0
  74. package/dist/core/custom-plugin-loader.js.map +1 -0
  75. package/dist/core/h2-pool.d.ts +4 -0
  76. package/dist/core/h2-pool.d.ts.map +1 -0
  77. package/dist/core/h2-pool.js +180 -0
  78. package/dist/core/h2-pool.js.map +1 -0
  79. package/dist/core/inspection-dispatch.d.ts +5 -0
  80. package/dist/core/inspection-dispatch.d.ts.map +1 -0
  81. package/dist/core/inspection-dispatch.js +146 -0
  82. package/dist/core/inspection-dispatch.js.map +1 -0
  83. package/dist/core/log-rate-limit.d.ts +34 -0
  84. package/dist/core/log-rate-limit.d.ts.map +1 -0
  85. package/dist/core/log-rate-limit.js +52 -0
  86. package/dist/core/log-rate-limit.js.map +1 -0
  87. package/dist/core/map-local.d.ts +4 -0
  88. package/dist/core/map-local.d.ts.map +1 -0
  89. package/dist/core/map-local.js +195 -0
  90. package/dist/core/map-local.js.map +1 -0
  91. package/dist/core/meddle-home.d.ts +13 -0
  92. package/dist/core/meddle-home.d.ts.map +1 -0
  93. package/dist/core/meddle-home.js +56 -0
  94. package/dist/core/meddle-home.js.map +1 -0
  95. package/dist/core/mock-gate.d.ts +3 -0
  96. package/dist/core/mock-gate.d.ts.map +1 -0
  97. package/dist/core/mock-gate.js +20 -0
  98. package/dist/core/mock-gate.js.map +1 -0
  99. package/dist/core/mock-handler.d.ts +5 -0
  100. package/dist/core/mock-handler.d.ts.map +1 -0
  101. package/dist/core/mock-handler.js +339 -0
  102. package/dist/core/mock-handler.js.map +1 -0
  103. package/dist/core/on-mode-gate.d.ts +4 -0
  104. package/dist/core/on-mode-gate.d.ts.map +1 -0
  105. package/dist/core/on-mode-gate.js +64 -0
  106. package/dist/core/on-mode-gate.js.map +1 -0
  107. package/dist/core/pipeline-gate.d.ts +3 -0
  108. package/dist/core/pipeline-gate.d.ts.map +1 -0
  109. package/dist/core/pipeline-gate.js +34 -0
  110. package/dist/core/pipeline-gate.js.map +1 -0
  111. package/dist/core/pipeline.d.ts +6 -0
  112. package/dist/core/pipeline.d.ts.map +1 -0
  113. package/dist/core/pipeline.js +228 -0
  114. package/dist/core/pipeline.js.map +1 -0
  115. package/dist/core/plugin-bootstrap-runner.d.ts +6 -0
  116. package/dist/core/plugin-bootstrap-runner.d.ts.map +1 -0
  117. package/dist/core/plugin-bootstrap-runner.js +148 -0
  118. package/dist/core/plugin-bootstrap-runner.js.map +1 -0
  119. package/dist/core/plugin-bootstrap.d.ts +3 -0
  120. package/dist/core/plugin-bootstrap.d.ts.map +1 -0
  121. package/dist/core/plugin-bootstrap.js +15 -0
  122. package/dist/core/plugin-bootstrap.js.map +1 -0
  123. package/dist/core/plugin-compiler.d.ts +37 -0
  124. package/dist/core/plugin-compiler.d.ts.map +1 -0
  125. package/dist/core/plugin-compiler.js +172 -0
  126. package/dist/core/plugin-compiler.js.map +1 -0
  127. package/dist/core/plugin-context-factory.d.ts +29 -0
  128. package/dist/core/plugin-context-factory.d.ts.map +1 -0
  129. package/dist/core/plugin-context-factory.js +206 -0
  130. package/dist/core/plugin-context-factory.js.map +1 -0
  131. package/dist/core/plugin-generator.d.ts +47 -0
  132. package/dist/core/plugin-generator.d.ts.map +1 -0
  133. package/dist/core/plugin-generator.js +697 -0
  134. package/dist/core/plugin-generator.js.map +1 -0
  135. package/dist/core/plugin-health.d.ts +3 -0
  136. package/dist/core/plugin-health.d.ts.map +1 -0
  137. package/dist/core/plugin-health.js +54 -0
  138. package/dist/core/plugin-health.js.map +1 -0
  139. package/dist/core/plugin-intercept.d.ts +17 -0
  140. package/dist/core/plugin-intercept.d.ts.map +1 -0
  141. package/dist/core/plugin-intercept.js +133 -0
  142. package/dist/core/plugin-intercept.js.map +1 -0
  143. package/dist/core/plugin-runtime.d.ts +33 -0
  144. package/dist/core/plugin-runtime.d.ts.map +1 -0
  145. package/dist/core/plugin-runtime.js +254 -0
  146. package/dist/core/plugin-runtime.js.map +1 -0
  147. package/dist/core/proxy-context.d.ts +3 -0
  148. package/dist/core/proxy-context.d.ts.map +1 -0
  149. package/dist/core/proxy-context.js +129 -0
  150. package/dist/core/proxy-context.js.map +1 -0
  151. package/dist/core/proxy-record.d.ts +3 -0
  152. package/dist/core/proxy-record.d.ts.map +1 -0
  153. package/dist/core/proxy-record.js +32 -0
  154. package/dist/core/proxy-record.js.map +1 -0
  155. package/dist/core/refactor-config.d.ts +6 -0
  156. package/dist/core/refactor-config.d.ts.map +1 -0
  157. package/dist/core/refactor-config.js +45 -0
  158. package/dist/core/refactor-config.js.map +1 -0
  159. package/dist/core/refactor-status.d.ts +3 -0
  160. package/dist/core/refactor-status.d.ts.map +1 -0
  161. package/dist/core/refactor-status.js +19 -0
  162. package/dist/core/refactor-status.js.map +1 -0
  163. package/dist/core/remote-access.d.ts +40 -0
  164. package/dist/core/remote-access.d.ts.map +1 -0
  165. package/dist/core/remote-access.js +281 -0
  166. package/dist/core/remote-access.js.map +1 -0
  167. package/dist/core/route-decision.d.ts +3 -0
  168. package/dist/core/route-decision.d.ts.map +1 -0
  169. package/dist/core/route-decision.js +20 -0
  170. package/dist/core/route-decision.js.map +1 -0
  171. package/dist/core/route-loader.d.ts +14 -0
  172. package/dist/core/route-loader.d.ts.map +1 -0
  173. package/dist/core/route-loader.js +94 -0
  174. package/dist/core/route-loader.js.map +1 -0
  175. package/dist/core/route-preview.d.ts +15 -0
  176. package/dist/core/route-preview.d.ts.map +1 -0
  177. package/dist/core/route-preview.js +91 -0
  178. package/dist/core/route-preview.js.map +1 -0
  179. package/dist/core/runtime-health.d.ts +92 -0
  180. package/dist/core/runtime-health.d.ts.map +1 -0
  181. package/dist/core/runtime-health.js +205 -0
  182. package/dist/core/runtime-health.js.map +1 -0
  183. package/dist/core/sessions.d.ts +19 -0
  184. package/dist/core/sessions.d.ts.map +1 -0
  185. package/dist/core/sessions.js +93 -0
  186. package/dist/core/sessions.js.map +1 -0
  187. package/dist/core/shadow-compare.d.ts +8 -0
  188. package/dist/core/shadow-compare.d.ts.map +1 -0
  189. package/dist/core/shadow-compare.js +83 -0
  190. package/dist/core/shadow-compare.js.map +1 -0
  191. package/dist/core/shadow-readiness.d.ts +4 -0
  192. package/dist/core/shadow-readiness.d.ts.map +1 -0
  193. package/dist/core/shadow-readiness.js +118 -0
  194. package/dist/core/shadow-readiness.js.map +1 -0
  195. package/dist/core/short-response.d.ts +5 -0
  196. package/dist/core/short-response.d.ts.map +1 -0
  197. package/dist/core/short-response.js +18 -0
  198. package/dist/core/short-response.js.map +1 -0
  199. package/dist/core/static-server.d.ts +9 -0
  200. package/dist/core/static-server.d.ts.map +1 -0
  201. package/dist/core/static-server.js +136 -0
  202. package/dist/core/static-server.js.map +1 -0
  203. package/dist/core/types.d.ts +590 -0
  204. package/dist/core/types.d.ts.map +1 -0
  205. package/dist/core/types.js +4 -0
  206. package/dist/core/types.js.map +1 -0
  207. package/dist/helpers.d.ts +36 -0
  208. package/dist/helpers.d.ts.map +1 -0
  209. package/dist/helpers.js +290 -0
  210. package/dist/helpers.js.map +1 -0
  211. package/dist/plugins/builtin/index.d.ts +3 -0
  212. package/dist/plugins/builtin/index.d.ts.map +1 -0
  213. package/dist/plugins/builtin/index.js +23 -0
  214. package/dist/plugins/builtin/index.js.map +1 -0
  215. package/dist/plugins/builtin/logger-plugin.d.ts +8 -0
  216. package/dist/plugins/builtin/logger-plugin.d.ts.map +1 -0
  217. package/dist/plugins/builtin/logger-plugin.js +121 -0
  218. package/dist/plugins/builtin/logger-plugin.js.map +1 -0
  219. package/dist/plugins/builtin/mock-plugin.d.ts +3 -0
  220. package/dist/plugins/builtin/mock-plugin.d.ts.map +1 -0
  221. package/dist/plugins/builtin/mock-plugin.js +99 -0
  222. package/dist/plugins/builtin/mock-plugin.js.map +1 -0
  223. package/dist/plugins/builtin/router-plugin.d.ts +3 -0
  224. package/dist/plugins/builtin/router-plugin.d.ts.map +1 -0
  225. package/dist/plugins/builtin/router-plugin.js +36 -0
  226. package/dist/plugins/builtin/router-plugin.js.map +1 -0
  227. package/dist/server/agent/model.d.ts +30 -0
  228. package/dist/server/agent/model.d.ts.map +1 -0
  229. package/dist/server/agent/model.js +143 -0
  230. package/dist/server/agent/model.js.map +1 -0
  231. package/dist/server/agent/routes.d.ts +4 -0
  232. package/dist/server/agent/routes.d.ts.map +1 -0
  233. package/dist/server/agent/routes.js +188 -0
  234. package/dist/server/agent/routes.js.map +1 -0
  235. package/dist/server/agent/runtime.d.ts +12 -0
  236. package/dist/server/agent/runtime.d.ts.map +1 -0
  237. package/dist/server/agent/runtime.js +208 -0
  238. package/dist/server/agent/runtime.js.map +1 -0
  239. package/dist/server/agent/tools.d.ts +13 -0
  240. package/dist/server/agent/tools.d.ts.map +1 -0
  241. package/dist/server/agent/tools.js +1201 -0
  242. package/dist/server/agent/tools.js.map +1 -0
  243. package/dist/server/agent/types.d.ts +56 -0
  244. package/dist/server/agent/types.d.ts.map +1 -0
  245. package/dist/server/agent/types.js +3 -0
  246. package/dist/server/agent/types.js.map +1 -0
  247. package/dist/server/config.d.ts +9 -0
  248. package/dist/server/config.d.ts.map +1 -0
  249. package/dist/server/config.js +124 -0
  250. package/dist/server/config.js.map +1 -0
  251. package/dist/server/health.d.ts +4 -0
  252. package/dist/server/health.d.ts.map +1 -0
  253. package/dist/server/health.js +22 -0
  254. package/dist/server/health.js.map +1 -0
  255. package/dist/server/index.d.ts +239 -0
  256. package/dist/server/index.d.ts.map +1 -0
  257. package/dist/server/index.js +44 -0
  258. package/dist/server/index.js.map +1 -0
  259. package/dist/server/logs.d.ts +4 -0
  260. package/dist/server/logs.d.ts.map +1 -0
  261. package/dist/server/logs.js +40 -0
  262. package/dist/server/logs.js.map +1 -0
  263. package/dist/server/mocks.d.ts +9 -0
  264. package/dist/server/mocks.d.ts.map +1 -0
  265. package/dist/server/mocks.js +103 -0
  266. package/dist/server/mocks.js.map +1 -0
  267. package/dist/server/pipeline.d.ts +16 -0
  268. package/dist/server/pipeline.d.ts.map +1 -0
  269. package/dist/server/pipeline.js +159 -0
  270. package/dist/server/pipeline.js.map +1 -0
  271. package/dist/server/plugins.d.ts +32 -0
  272. package/dist/server/plugins.d.ts.map +1 -0
  273. package/dist/server/plugins.js +795 -0
  274. package/dist/server/plugins.js.map +1 -0
  275. package/dist/server/refactor.d.ts +4 -0
  276. package/dist/server/refactor.d.ts.map +1 -0
  277. package/dist/server/refactor.js +86 -0
  278. package/dist/server/refactor.js.map +1 -0
  279. package/dist/server/rule-files.d.ts +34 -0
  280. package/dist/server/rule-files.d.ts.map +1 -0
  281. package/dist/server/rule-files.js +389 -0
  282. package/dist/server/rule-files.js.map +1 -0
  283. package/dist/server/rules.d.ts +4 -0
  284. package/dist/server/rules.d.ts.map +1 -0
  285. package/dist/server/rules.js +40 -0
  286. package/dist/server/rules.js.map +1 -0
  287. package/dist/server/sessions.d.ts +4 -0
  288. package/dist/server/sessions.d.ts.map +1 -0
  289. package/dist/server/sessions.js +20 -0
  290. package/dist/server/sessions.js.map +1 -0
  291. package/index.js +950 -0
  292. package/mcp-server.js +794 -0
  293. package/package.json +92 -0
  294. package/plugins/builtin/index.ts +25 -0
  295. package/plugins/builtin/logger-plugin.ts +126 -0
  296. package/plugins/builtin/mock-plugin.ts +112 -0
  297. package/plugins/builtin/router-plugin.ts +35 -0
  298. package/web/README.md +111 -0
  299. package/web/dist/assets/ai-config-store-DQXVJVn_.js +1 -0
  300. package/web/dist/assets/alert-COF-DIAE.js +1 -0
  301. package/web/dist/assets/arrow-right-B4Mrlj2-.js +1 -0
  302. package/web/dist/assets/babel-DsprIpXZ.js +15 -0
  303. package/web/dist/assets/body-diff-view-D7dCWajG.js +6 -0
  304. package/web/dist/assets/button-BTToMaBW.js +1 -0
  305. package/web/dist/assets/checkbox-DIBarrJx.js +1 -0
  306. package/web/dist/assets/chevron-down-CPngAx4M.js +1 -0
  307. package/web/dist/assets/chevron-right-V1DGIDbL.js +1 -0
  308. package/web/dist/assets/circle-alert-Q8cZk9Rv.js +1 -0
  309. package/web/dist/assets/circle-x-C9USji_R.js +1 -0
  310. package/web/dist/assets/code-5_eJ_XpJ.js +1 -0
  311. package/web/dist/assets/code-fixer-fQtWZ5He.js +20 -0
  312. package/web/dist/assets/copy-BYjq1hdN.js +1 -0
  313. package/web/dist/assets/detail-panel-BX_hxeI0.js +3 -0
  314. package/web/dist/assets/dist-B8XUKgXe.js +1 -0
  315. package/web/dist/assets/dist-Bb9TeEub.js +1 -0
  316. package/web/dist/assets/dist-C5nMErq8.js +1 -0
  317. package/web/dist/assets/dist-C6eaYCUo.js +1 -0
  318. package/web/dist/assets/dist-Cn0y0IRn.js +1 -0
  319. package/web/dist/assets/dist-CxdY_A67.js +5 -0
  320. package/web/dist/assets/dist-D5Dj17P8.js +1 -0
  321. package/web/dist/assets/dist-DZJ9SMlJ.js +1 -0
  322. package/web/dist/assets/es2015-CfXu88Y7.js +41 -0
  323. package/web/dist/assets/estree-BP7k0NIt.js +44 -0
  324. package/web/dist/assets/file-system-access-CtcvBfj4.js +1 -0
  325. package/web/dist/assets/global-panel-shell-ChdO0dWd.js +6 -0
  326. package/web/dist/assets/health-panel-CQeCQ7gr.js +1 -0
  327. package/web/dist/assets/html-6FIWbqxX.js +25 -0
  328. package/web/dist/assets/index-CjqaTnE_.css +2 -0
  329. package/web/dist/assets/index-L7uWxTnp.js +18 -0
  330. package/web/dist/assets/mobile-proxy-panel-Dj1iLami.js +8 -0
  331. package/web/dist/assets/mock-config-BTTCw7RK.js +1 -0
  332. package/web/dist/assets/mock-editor-panel-C-aVfFme.js +1 -0
  333. package/web/dist/assets/monaco-editor-B3brLg8j.js +11 -0
  334. package/web/dist/assets/pencil-line-Cqe41E4h.js +1 -0
  335. package/web/dist/assets/plugin-code-editor-CPjCbJ9g.js +2 -0
  336. package/web/dist/assets/plugin-config-BzmCkvz3.js +1 -0
  337. package/web/dist/assets/plugin-generator-BnEafDF9.js +2 -0
  338. package/web/dist/assets/plugin-test-dialog-BWoWsWV4.js +7 -0
  339. package/web/dist/assets/plus-tVxSydJ8.js +1 -0
  340. package/web/dist/assets/postcss-Dnf30fQU.js +61 -0
  341. package/web/dist/assets/refresh-cw-CG3HaiQT.js +1 -0
  342. package/web/dist/assets/rotate-ccw-CAYM6Vv0.js +1 -0
  343. package/web/dist/assets/route-preview-BX7sfY0O.js +1 -0
  344. package/web/dist/assets/rule-ai-assistant-panel-WBiOOUw5.js +47 -0
  345. package/web/dist/assets/rule-config-CHpVij2M.css +1 -0
  346. package/web/dist/assets/rule-config-fTIZVwg1.js +15 -0
  347. package/web/dist/assets/select-CkFOB61l.js +1 -0
  348. package/web/dist/assets/server-Cpj4KNwN.js +1 -0
  349. package/web/dist/assets/settings-panel-COCYiIUg.js +1 -0
  350. package/web/dist/assets/shield-check-OqUmVLQt.js +1 -0
  351. package/web/dist/assets/smartphone-DKeDuJTU.js +1 -0
  352. package/web/dist/assets/standalone-CjxtLKw-.js +29 -0
  353. package/web/dist/assets/switch-C-Xk56TK.js +1 -0
  354. package/web/dist/assets/syntax-highlight-DVhPdkuV.js +5 -0
  355. package/web/dist/assets/table-CT97lAYq.js +1 -0
  356. package/web/dist/assets/textarea-C6NooVK1.js +1 -0
  357. package/web/dist/assets/wand-sparkles-wkul5vje.js +1 -0
  358. package/web/dist/assets/wifi-D9M35Ajj.js +1 -0
  359. package/web/dist/assets/zap-Djo4cgux.js +1 -0
  360. package/web/dist/index.html +24 -0
  361. package/web/dist/vite.svg +1 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * meddle route create - Create a route file
3
+ */
4
+
5
+ const output = require('../../lib/output')
6
+ const { isProxyRunning } = require('../../lib/proxy-detect')
7
+ const { apiPost } = require('../../lib/api-client')
8
+ const { createRuleFile } = require('../../lib/file-access')
9
+
10
+ // Parse arguments (skip 'route' and 'create' from argv)
11
+ const args = process.argv.slice(4)
12
+ const jsonFlag = args.includes('--json')
13
+ output.setJsonMode(jsonFlag)
14
+
15
+ // Get file name from positional argument
16
+ const positionalArgs = args.filter(a => !a.startsWith('--'))
17
+ const fileName = positionalArgs[0]
18
+
19
+ // Get content from --content option
20
+ let content = ''
21
+ for (let i = 0; i < args.length; i++) {
22
+ if (args[i] === '--content') {
23
+ content = args[++i] || ''
24
+ break
25
+ }
26
+ }
27
+
28
+ async function run() {
29
+ if (!fileName) {
30
+ output.error('Missing required argument: <name>')
31
+ process.exit(1)
32
+ }
33
+
34
+ const running = await isProxyRunning()
35
+
36
+ let result
37
+ if (running) {
38
+ try {
39
+ result = await apiPost('/api/rule-files', {
40
+ name: fileName.trim(),
41
+ content: content.trim(),
42
+ enabled: true
43
+ })
44
+ result = result.ruleFile || result
45
+ } catch (e) {
46
+ // Fallback to file mode
47
+ try {
48
+ result = createRuleFile(fileName, content, true)
49
+ } catch (err) {
50
+ output.error(err.message)
51
+ process.exit(1)
52
+ }
53
+ }
54
+ } else {
55
+ try {
56
+ result = createRuleFile(fileName, content, true)
57
+ } catch (err) {
58
+ output.error(err.message)
59
+ process.exit(1)
60
+ }
61
+ }
62
+
63
+ if (jsonFlag) {
64
+ output.jsonRaw(result)
65
+ return
66
+ }
67
+
68
+ output.header('Route File Created')
69
+ output.success(result.name)
70
+ output.kv('Enabled', result.enabled ? 'Yes' : 'No')
71
+ output.kv('Rules', result.ruleCount)
72
+ }
73
+
74
+ run().catch(e => {
75
+ output.error(e.message)
76
+ process.exit(1)
77
+ })
@@ -0,0 +1,120 @@
1
+ /**
2
+ * meddle route delete - Delete a rule from 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 'delete' 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
16
+ const positionalArgs = args.filter(a => !a.startsWith('--'))
17
+ const fileName = positionalArgs[0]
18
+ const pattern = positionalArgs[1]
19
+
20
+ async function run() {
21
+ if (!fileName) {
22
+ output.error('Missing required argument: <file>')
23
+ process.exit(1)
24
+ }
25
+ if (!pattern) {
26
+ output.error('Missing required argument: <pattern>')
27
+ process.exit(1)
28
+ }
29
+
30
+ const running = await isProxyRunning()
31
+
32
+ const pat = pattern.trim()
33
+
34
+ // Handle [marker] syntax for lookup
35
+ const bm = pat.match(/\[([^\]]+)\]/)
36
+ const internalKey = bm ? pat.replace(bm[0], bm[1]) : pat
37
+
38
+ if (running) {
39
+ try {
40
+ let content = await apiGet(`/api/rule-files/${encodeURIComponent(fileName)}/content`)
41
+ const text = typeof content === 'string' ? content : String(content)
42
+ const ruleMap = parseEprc(text)
43
+
44
+ if (!Object.prototype.hasOwnProperty.call(ruleMap, internalKey)) {
45
+ output.error(`Pattern not found: ${pat}`)
46
+ process.exit(1)
47
+ }
48
+
49
+ delete ruleMap[internalKey]
50
+ const newContent = ruleMapToEprcText(ruleMap)
51
+ await apiPut(`/api/rule-files/${encodeURIComponent(fileName)}/content`, { content: newContent })
52
+
53
+ if (jsonFlag) {
54
+ output.jsonRaw({ success: true, file: fileName, pattern: pat })
55
+ return
56
+ }
57
+
58
+ output.header('Route Rule Deleted')
59
+ output.success(pat)
60
+ output.kv('File', fileName)
61
+ } catch (e) {
62
+ // Fallback to file mode
63
+ const content = getRuleFileContent(fileName)
64
+ if (!content) {
65
+ output.error(`Route file not found: ${fileName}`)
66
+ process.exit(1)
67
+ }
68
+
69
+ const ruleMap = parseEprc(content)
70
+ if (!Object.prototype.hasOwnProperty.call(ruleMap, internalKey)) {
71
+ output.error(`Pattern not found: ${pat}`)
72
+ process.exit(1)
73
+ }
74
+
75
+ delete ruleMap[internalKey]
76
+ const newContent = ruleMapToEprcText(ruleMap)
77
+ saveRuleFileContent(fileName, newContent)
78
+
79
+ if (jsonFlag) {
80
+ output.jsonRaw({ success: true, file: fileName, pattern: pat })
81
+ return
82
+ }
83
+
84
+ output.header('Route Rule Deleted')
85
+ output.success(pat)
86
+ output.kv('File', fileName)
87
+ }
88
+ } else {
89
+ // File mode
90
+ const content = getRuleFileContent(fileName)
91
+ if (!content) {
92
+ output.error(`Route file not found: ${fileName}`)
93
+ process.exit(1)
94
+ }
95
+
96
+ const ruleMap = parseEprc(content)
97
+ if (!Object.prototype.hasOwnProperty.call(ruleMap, internalKey)) {
98
+ output.error(`Pattern not found: ${pat}`)
99
+ process.exit(1)
100
+ }
101
+
102
+ delete ruleMap[internalKey]
103
+ const newContent = ruleMapToEprcText(ruleMap)
104
+ saveRuleFileContent(fileName, newContent)
105
+
106
+ if (jsonFlag) {
107
+ output.jsonRaw({ success: true, file: fileName, pattern: pat })
108
+ return
109
+ }
110
+
111
+ output.header('Route Rule Deleted')
112
+ output.success(pat)
113
+ output.kv('File', fileName)
114
+ }
115
+ }
116
+
117
+ run().catch(e => {
118
+ output.error(e.message)
119
+ process.exit(1)
120
+ })
@@ -0,0 +1,59 @@
1
+ /**
2
+ * meddle route - Route 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 'show':
13
+ require('./show.js')
14
+ break
15
+ case 'preview':
16
+ require('./preview.js')
17
+ break
18
+ case 'active':
19
+ require('./active.js')
20
+ break
21
+ case 'create':
22
+ require('./create.js')
23
+ break
24
+ case 'add':
25
+ require('./add.js')
26
+ break
27
+ case 'update':
28
+ require('./update.js')
29
+ break
30
+ case 'delete':
31
+ require('./delete.js')
32
+ break
33
+ default:
34
+ console.log(`
35
+ Route Commands:
36
+ meddle route list [--json] List all route files
37
+ meddle route show <file> [--json] Show rules in a file
38
+ meddle route preview <url> [--file <name>] [--json] Preview route target for a URL
39
+ meddle route active Show active route files
40
+ meddle route active set <file> Set active route file
41
+ meddle route create <name> [--content <text>] Create a route file
42
+ meddle route add <file> <pattern> <target> Add a rule to file
43
+ meddle route update <file> <pattern> <target> Update a rule in file
44
+ meddle route delete <file> <pattern> Delete a rule from file
45
+
46
+ Examples:
47
+ meddle route list
48
+ meddle route show dev-rules
49
+ meddle route preview "https://api.example.com/v1/users"
50
+ meddle route preview "https://cdn.com/assets/js/app.js" --file dev-rules
51
+ meddle route preview "https://api.test.com/data" --json
52
+ meddle route active set beta-rules
53
+ meddle route create staging --content "example.com localhost:3000"
54
+ meddle route add dev-rules "api.test.com" "localhost:8080"
55
+ meddle route update dev-rules "api.test.com" "localhost:9000"
56
+ meddle route delete dev-rules "api.test.com"
57
+ `)
58
+ process.exit(1)
59
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * meddle route list - List all route files
3
+ */
4
+
5
+ const output = require('../../lib/output')
6
+ const { isProxyRunning } = require('../../lib/proxy-detect')
7
+ const { apiGet } = require('../../lib/api-client')
8
+ const { listRuleFiles } = 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 files = []
19
+
20
+ if (running) {
21
+ try {
22
+ files = await apiGet('/api/rule-files')
23
+ } catch (e) {
24
+ // Fallback to file mode
25
+ files = listRuleFiles()
26
+ }
27
+ } else {
28
+ files = listRuleFiles()
29
+ }
30
+
31
+ if (jsonFlag) {
32
+ output.jsonRaw(files)
33
+ return
34
+ }
35
+
36
+ output.header(`Route Files (${files.length} total)`)
37
+
38
+ if (files.length === 0) {
39
+ output.info('No route files found')
40
+ return
41
+ }
42
+
43
+ // Separate active and inactive
44
+ const active = files.filter(f => f.enabled)
45
+ const inactive = files.filter(f => !f.enabled)
46
+
47
+ if (active.length > 0) {
48
+ output.section('Active Files')
49
+ active.forEach(f => {
50
+ const excludeInfo = f.excludeCount > 0 ? `, ${f.excludeCount} exclusions` : ''
51
+ output.success(`${f.name} (${f.ruleCount} rules${excludeInfo})`)
52
+ })
53
+ }
54
+
55
+ if (inactive.length > 0) {
56
+ output.section('Inactive Files')
57
+ inactive.forEach(f => {
58
+ const excludeInfo = f.excludeCount > 0 ? `, ${f.excludeCount} exclusions` : ''
59
+ output.bullet(`${f.name} (${f.ruleCount} rules${excludeInfo})`, false)
60
+ })
61
+ }
62
+ }
63
+
64
+ run().catch(e => {
65
+ output.error(e.message)
66
+ process.exit(1)
67
+ })
@@ -0,0 +1,159 @@
1
+ /**
2
+ * meddle route preview - Preview route target for a given URL
3
+ */
4
+
5
+ const output = require('../../lib/output')
6
+ const { isProxyRunning, getProxyUrl } = require('../../lib/proxy-detect')
7
+ const { apiPost } = require('../../lib/api-client')
8
+ const { getActiveRuleFileNames, getRuleFileContent, parseEprcWithExclusions } = require('../../lib/file-access')
9
+
10
+ // Parse arguments (skip 'route' and 'preview' from argv)
11
+ const args = process.argv.slice(4)
12
+ const jsonFlag = args.includes('--json')
13
+ output.setJsonMode(jsonFlag)
14
+
15
+ // Parse --file argument
16
+ let ruleFileArg = null
17
+ const fileEqIndex = args.findIndex(a => a.startsWith('--file='))
18
+ if (fileEqIndex !== -1) {
19
+ ruleFileArg = args[fileEqIndex].split('=')[1]
20
+ } else {
21
+ const fileIndex = args.indexOf('--file')
22
+ if (fileIndex !== -1 && fileIndex + 1 < args.length) {
23
+ ruleFileArg = args[fileIndex + 1]
24
+ }
25
+ }
26
+
27
+ // Get URL from positional argument (not --file value, not --json, not --file)
28
+ const urlArg = args.find(a => !a.startsWith('--') && a !== ruleFileArg)
29
+
30
+ async function run() {
31
+ if (!urlArg) {
32
+ output.error('Missing required argument: <url>')
33
+ output.info('Usage: meddle route preview <url> [--file <rule-file>] [--json]')
34
+ process.exit(1)
35
+ }
36
+
37
+ // Validate URL format
38
+ try {
39
+ new URL(urlArg)
40
+ } catch {
41
+ output.error('Invalid URL format')
42
+ process.exit(1)
43
+ }
44
+
45
+ const running = await isProxyRunning()
46
+ let result
47
+
48
+ if (running) {
49
+ // Use API when proxy is running
50
+ try {
51
+ const baseUrl = getProxyUrl()
52
+
53
+ // Get rules text from specified file or all active files
54
+ let rulesText = ''
55
+ if (ruleFileArg) {
56
+ // Use specified rule file
57
+ const content = await fetch(`${baseUrl}/api/rule-files/${encodeURIComponent(ruleFileArg)}/content`)
58
+ .then(r => r.ok ? r.text() : null)
59
+ .catch(() => null)
60
+ if (!content) {
61
+ output.error(`Rule file not found: ${ruleFileArg}`)
62
+ process.exit(1)
63
+ }
64
+ rulesText = content
65
+ } else {
66
+ // Use all active rule files
67
+ const filesRes = await fetch(`${baseUrl}/api/rule-files`).then(r => r.json())
68
+ const activeFiles = filesRes.filter(f => f.enabled)
69
+
70
+ for (const file of activeFiles) {
71
+ const content = await fetch(`${baseUrl}/api/rule-files/${encodeURIComponent(file.name)}/content`)
72
+ .then(r => r.text())
73
+ .catch(() => '')
74
+ if (content) {
75
+ rulesText += content + '\n'
76
+ }
77
+ }
78
+ }
79
+
80
+ // Call preview API
81
+ result = await apiPost('/api/rules/preview', { url: urlArg, rulesText })
82
+ } catch (e) {
83
+ output.error(e.message)
84
+ process.exit(1)
85
+ }
86
+ } else {
87
+ // Use local file access when proxy is not running
88
+ try {
89
+ let rulesText = ''
90
+
91
+ if (ruleFileArg) {
92
+ // Use specified rule file
93
+ const content = getRuleFileContent(ruleFileArg)
94
+ if (!content) {
95
+ output.error(`Rule file not found: ${ruleFileArg}`)
96
+ process.exit(1)
97
+ }
98
+ rulesText = content
99
+ } else {
100
+ // Use all active rule files
101
+ const activeNames = getActiveRuleFileNames()
102
+
103
+ for (const name of activeNames) {
104
+ const content = getRuleFileContent(name)
105
+ if (content) {
106
+ rulesText += content + '\n'
107
+ }
108
+ }
109
+ }
110
+
111
+ if (!rulesText.trim()) {
112
+ output.error('No active rule files found')
113
+ output.info('Use --file <name> to specify a rule file, or activate one with: meddle route active set <file>')
114
+ process.exit(1)
115
+ }
116
+
117
+ // Use local preview logic (same as core/route-preview.ts)
118
+ const { previewRouteTargetLocal } = require('../../lib/route-preview')
119
+ result = previewRouteTargetLocal(urlArg, rulesText)
120
+ } catch (e) {
121
+ output.error(e.message)
122
+ process.exit(1)
123
+ }
124
+ }
125
+
126
+ // Output result
127
+ if (jsonFlag) {
128
+ output.jsonRaw(result)
129
+ return
130
+ }
131
+
132
+ output.header('Route Preview')
133
+ output.kv('Input URL', result.inputUrl)
134
+
135
+ if (result.matched) {
136
+ output.success('Matched rule found')
137
+ output.section('Match Details')
138
+ output.kv('Pattern', result.matchedRule.pattern)
139
+ output.kv('Target', result.matchedRule.target)
140
+ output.kv('Kind', result.matchedRule.kind)
141
+ output.kv('Resolved URL', result.resolvedUrl)
142
+
143
+ if (result.notes.length > 0) {
144
+ output.section('Notes')
145
+ for (const note of result.notes) {
146
+ output.info(note)
147
+ }
148
+ }
149
+ } else {
150
+ output.warning('No matching rule found')
151
+ output.kv('Resolved URL', result.resolvedUrl)
152
+ output.info('Request will pass through unchanged')
153
+ }
154
+ }
155
+
156
+ run().catch(e => {
157
+ output.error(e.message)
158
+ process.exit(1)
159
+ })
@@ -0,0 +1,111 @@
1
+ /**
2
+ * meddle route show - Show rules in a file
3
+ */
4
+
5
+ const output = require('../../lib/output')
6
+ const { isProxyRunning } = require('../../lib/proxy-detect')
7
+ const { apiGet } = require('../../lib/api-client')
8
+ const { getRuleFileContent, parseEprcWithExclusions } = require('../../lib/file-access')
9
+
10
+ // Parse arguments (skip 'route' and 'show' from argv)
11
+ const args = process.argv.slice(4)
12
+ const jsonFlag = args.includes('--json')
13
+ output.setJsonMode(jsonFlag)
14
+
15
+ // Get file name from positional argument
16
+ const fileName = args.find(a => !a.startsWith('--'))
17
+
18
+ async function run() {
19
+ if (!fileName) {
20
+ output.error('Missing required argument: <file>')
21
+ process.exit(1)
22
+ }
23
+
24
+ const running = await isProxyRunning()
25
+
26
+ let content = null
27
+ let ruleMap = {}
28
+ let excludeMap = {}
29
+
30
+ if (running) {
31
+ try {
32
+ content = await apiGet(`/api/rule-files/${encodeURIComponent(fileName)}/content`)
33
+ const parsed = parseEprcWithExclusions(typeof content === 'string' ? content : String(content))
34
+ ruleMap = parsed.ruleMap
35
+ excludeMap = parsed.excludeMap
36
+ } catch (e) {
37
+ // Fallback to file mode
38
+ content = getRuleFileContent(fileName)
39
+ if (!content) {
40
+ output.error(`Route file not found: ${fileName}`)
41
+ process.exit(1)
42
+ }
43
+ const parsed = parseEprcWithExclusions(content)
44
+ ruleMap = parsed.ruleMap
45
+ excludeMap = parsed.excludeMap
46
+ }
47
+ } else {
48
+ content = getRuleFileContent(fileName)
49
+ if (!content) {
50
+ output.error(`Route file not found: ${fileName}`)
51
+ process.exit(1)
52
+ }
53
+ const parsed = parseEprcWithExclusions(content)
54
+ ruleMap = parsed.ruleMap
55
+ excludeMap = parsed.excludeMap
56
+ }
57
+
58
+ // Build display rules (handle [marker] syntax)
59
+ const displayRules = {}
60
+ for (const [pat, tgt] of Object.entries(ruleMap)) {
61
+ const bm = tgt.match(/\[([^\]]+)\]/)
62
+ const displayPat = bm ? pat.replace(bm[1], bm[0]) : pat
63
+ const displayTgt = bm ? tgt.replace(bm[0], '') : tgt
64
+ const exclusions = excludeMap[pat] || []
65
+ displayRules[displayPat] = exclusions.length > 0
66
+ ? { target: displayTgt, exclusions }
67
+ : displayTgt
68
+ }
69
+
70
+ // Calculate total exclusions
71
+ let totalExclusions = 0
72
+ for (const exclusions of Object.values(excludeMap)) {
73
+ totalExclusions += exclusions.length
74
+ }
75
+
76
+ if (jsonFlag) {
77
+ output.jsonRaw({
78
+ file: fileName,
79
+ rules: displayRules,
80
+ ruleCount: Object.keys(displayRules).length,
81
+ exclusionCount: totalExclusions
82
+ })
83
+ return
84
+ }
85
+
86
+ output.header(`Route File: ${fileName}`)
87
+ output.kv('Rules', Object.keys(displayRules).length)
88
+ if (totalExclusions > 0) {
89
+ output.kv('Exclusions', totalExclusions)
90
+ }
91
+
92
+ if (Object.keys(displayRules).length === 0) {
93
+ output.info('No rules in this file')
94
+ return
95
+ }
96
+
97
+ output.section('Rules')
98
+ for (const [pattern, rule] of Object.entries(displayRules)) {
99
+ if (typeof rule === 'string') {
100
+ output.kv(pattern, rule)
101
+ } else {
102
+ const exclStr = rule.exclusions.map(e => `!${e}`).join(' ')
103
+ output.kv(pattern, `${rule.target} ${exclStr}`)
104
+ }
105
+ }
106
+ }
107
+
108
+ run().catch(e => {
109
+ output.error(e.message)
110
+ process.exit(1)
111
+ })