recker 1.0.20-next.9796be9 → 1.0.20-next.a5aea1e

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 (368) hide show
  1. package/dist/ai/adaptive-timeout.d.ts +0 -1
  2. package/dist/ai/client.d.ts +0 -1
  3. package/dist/ai/index.d.ts +0 -1
  4. package/dist/ai/providers/anthropic.d.ts +0 -1
  5. package/dist/ai/providers/base.d.ts +0 -1
  6. package/dist/ai/providers/index.d.ts +0 -1
  7. package/dist/ai/providers/openai.d.ts +0 -1
  8. package/dist/ai/rate-limiter.d.ts +0 -1
  9. package/dist/bench/generator.d.ts +0 -1
  10. package/dist/bench/stats.d.ts +0 -1
  11. package/dist/cache/file-storage.d.ts +0 -1
  12. package/dist/cache/memory-limits.d.ts +0 -1
  13. package/dist/cache/memory-storage.d.ts +0 -1
  14. package/dist/cache/redis-storage.d.ts +0 -1
  15. package/dist/cli/handler.d.ts +2 -1
  16. package/dist/cli/handler.js +36 -5
  17. package/dist/cli/index.d.ts +0 -1
  18. package/dist/cli/index.js +504 -4
  19. package/dist/cli/presets.d.ts +0 -1
  20. package/dist/cli/tui/ai-chat.d.ts +0 -1
  21. package/dist/cli/tui/load-dashboard.d.ts +0 -1
  22. package/dist/cli/tui/scroll-buffer.d.ts +0 -1
  23. package/dist/cli/tui/search-panel.d.ts +0 -1
  24. package/dist/cli/tui/shell-search.d.ts +0 -1
  25. package/dist/cli/tui/shell.d.ts +0 -1
  26. package/dist/cli/tui/shell.js +1 -1
  27. package/dist/cli/tui/websocket.d.ts +0 -1
  28. package/dist/constants/http-status.d.ts +0 -1
  29. package/dist/constants.d.ts +0 -1
  30. package/dist/contract/index.d.ts +0 -1
  31. package/dist/cookies/memory-cookie-jar.d.ts +0 -1
  32. package/dist/core/client.d.ts +0 -1
  33. package/dist/core/errors.d.ts +0 -1
  34. package/dist/core/index.d.ts +0 -1
  35. package/dist/core/request-promise.d.ts +0 -1
  36. package/dist/core/request.d.ts +0 -1
  37. package/dist/core/response.d.ts +0 -1
  38. package/dist/dns/index.d.ts +0 -1
  39. package/dist/dns/propagation.d.ts +0 -1
  40. package/dist/events/request-events.d.ts +0 -1
  41. package/dist/index.d.ts +0 -1
  42. package/dist/mcp/client.d.ts +0 -1
  43. package/dist/mcp/contract.d.ts +0 -1
  44. package/dist/mcp/embeddings-loader.d.ts +0 -1
  45. package/dist/mcp/geoip-loader.d.ts +0 -1
  46. package/dist/mcp/index.d.ts +0 -1
  47. package/dist/mcp/ip-intel.d.ts +0 -1
  48. package/dist/mcp/search/hybrid-search.d.ts +0 -1
  49. package/dist/mcp/search/index.d.ts +0 -1
  50. package/dist/mcp/search/math.d.ts +0 -1
  51. package/dist/mcp/search/types.d.ts +0 -1
  52. package/dist/mcp/server.d.ts +0 -1
  53. package/dist/mcp/types.d.ts +0 -1
  54. package/dist/plugins/auth.d.ts +0 -1
  55. package/dist/plugins/cache.d.ts +0 -1
  56. package/dist/plugins/cache.js +1 -1
  57. package/dist/plugins/circuit-breaker.d.ts +0 -1
  58. package/dist/plugins/compression.d.ts +0 -1
  59. package/dist/plugins/cookie-jar.d.ts +0 -1
  60. package/dist/plugins/dedup.d.ts +0 -1
  61. package/dist/plugins/graphql.d.ts +0 -1
  62. package/dist/plugins/grpc-web.d.ts +0 -1
  63. package/dist/plugins/har-player.d.ts +0 -1
  64. package/dist/plugins/har-recorder.d.ts +0 -1
  65. package/dist/plugins/hls.d.ts +0 -1
  66. package/dist/plugins/http2-push.d.ts +0 -1
  67. package/dist/plugins/http3.d.ts +0 -1
  68. package/dist/plugins/interface-rotator.d.ts +0 -1
  69. package/dist/plugins/jsonrpc.d.ts +0 -1
  70. package/dist/plugins/logger.d.ts +0 -1
  71. package/dist/plugins/odata.d.ts +0 -1
  72. package/dist/plugins/pagination.d.ts +0 -1
  73. package/dist/plugins/proxy-rotator.d.ts +0 -1
  74. package/dist/plugins/retry.d.ts +0 -1
  75. package/dist/plugins/retry.js +2 -2
  76. package/dist/plugins/scrape.d.ts +0 -1
  77. package/dist/plugins/server-timing.d.ts +0 -1
  78. package/dist/plugins/soap.d.ts +0 -1
  79. package/dist/plugins/user-agent.d.ts +0 -1
  80. package/dist/plugins/xml.d.ts +0 -1
  81. package/dist/plugins/xsrf.d.ts +0 -1
  82. package/dist/presets/anthropic.d.ts +0 -1
  83. package/dist/presets/aws.d.ts +0 -1
  84. package/dist/presets/azure-openai.d.ts +0 -1
  85. package/dist/presets/azure.d.ts +0 -1
  86. package/dist/presets/cloudflare.d.ts +0 -1
  87. package/dist/presets/cohere.d.ts +0 -1
  88. package/dist/presets/deepseek.d.ts +0 -1
  89. package/dist/presets/digitalocean.d.ts +0 -1
  90. package/dist/presets/discord.d.ts +0 -1
  91. package/dist/presets/fireworks.d.ts +0 -1
  92. package/dist/presets/gcp.d.ts +0 -1
  93. package/dist/presets/gemini.d.ts +0 -1
  94. package/dist/presets/github.d.ts +0 -1
  95. package/dist/presets/gitlab.d.ts +0 -1
  96. package/dist/presets/groq.d.ts +0 -1
  97. package/dist/presets/huggingface.d.ts +0 -1
  98. package/dist/presets/index.d.ts +0 -1
  99. package/dist/presets/linear.d.ts +0 -1
  100. package/dist/presets/mailgun.d.ts +0 -1
  101. package/dist/presets/meta.d.ts +0 -1
  102. package/dist/presets/mistral.d.ts +0 -1
  103. package/dist/presets/notion.d.ts +0 -1
  104. package/dist/presets/openai.d.ts +0 -1
  105. package/dist/presets/oracle.d.ts +0 -1
  106. package/dist/presets/perplexity.d.ts +0 -1
  107. package/dist/presets/registry.d.ts +0 -1
  108. package/dist/presets/replicate.d.ts +0 -1
  109. package/dist/presets/sinch.d.ts +0 -1
  110. package/dist/presets/slack.d.ts +0 -1
  111. package/dist/presets/stripe.d.ts +0 -1
  112. package/dist/presets/supabase.d.ts +0 -1
  113. package/dist/presets/tiktok.d.ts +0 -1
  114. package/dist/presets/together.d.ts +0 -1
  115. package/dist/presets/twilio.d.ts +0 -1
  116. package/dist/presets/vercel.d.ts +0 -1
  117. package/dist/presets/vultr.d.ts +0 -1
  118. package/dist/presets/xai.d.ts +0 -1
  119. package/dist/presets/youtube.d.ts +0 -1
  120. package/dist/protocols/ftp.d.ts +0 -1
  121. package/dist/protocols/index.d.ts +0 -1
  122. package/dist/protocols/sftp.d.ts +0 -1
  123. package/dist/protocols/telnet.d.ts +0 -1
  124. package/dist/recker.d.ts +0 -1
  125. package/dist/runner/request-runner.d.ts +0 -1
  126. package/dist/scrape/document.d.ts +0 -1
  127. package/dist/scrape/element.d.ts +0 -1
  128. package/dist/scrape/extractors.d.ts +0 -1
  129. package/dist/scrape/index.d.ts +0 -1
  130. package/dist/scrape/types.d.ts +0 -1
  131. package/dist/testing/index.d.ts +8 -1
  132. package/dist/testing/index.js +4 -0
  133. package/dist/testing/mock-dns-server.d.ts +69 -0
  134. package/dist/testing/mock-dns-server.js +269 -0
  135. package/dist/testing/mock-ftp-server.d.ts +89 -0
  136. package/dist/testing/mock-ftp-server.js +562 -0
  137. package/dist/testing/mock-hls-server.d.ts +0 -1
  138. package/dist/testing/mock-http-server.d.ts +0 -1
  139. package/dist/testing/mock-sse-server.d.ts +0 -1
  140. package/dist/testing/mock-telnet-server.d.ts +59 -0
  141. package/dist/testing/mock-telnet-server.js +273 -0
  142. package/dist/testing/mock-udp-server.d.ts +0 -1
  143. package/dist/testing/mock-websocket-server.d.ts +0 -1
  144. package/dist/testing/mock-whois-server.d.ts +56 -0
  145. package/dist/testing/mock-whois-server.js +234 -0
  146. package/dist/testing/mock.d.ts +0 -1
  147. package/dist/transport/base-udp.d.ts +0 -1
  148. package/dist/transport/fetch.d.ts +0 -1
  149. package/dist/transport/udp-response.d.ts +0 -1
  150. package/dist/transport/udp.d.ts +0 -1
  151. package/dist/transport/undici.d.ts +0 -1
  152. package/dist/transport/undici.js +1 -1
  153. package/dist/types/ai.d.ts +0 -1
  154. package/dist/types/index.d.ts +0 -1
  155. package/dist/types/logger.d.ts +0 -1
  156. package/dist/types/udp.d.ts +0 -1
  157. package/dist/udp/index.d.ts +0 -1
  158. package/dist/utils/agent-manager.d.ts +0 -1
  159. package/dist/utils/body.d.ts +0 -1
  160. package/dist/utils/cert.d.ts +0 -1
  161. package/dist/utils/charset.d.ts +0 -1
  162. package/dist/utils/chart.d.ts +0 -1
  163. package/dist/utils/client-pool.d.ts +0 -1
  164. package/dist/utils/colors.d.ts +0 -1
  165. package/dist/utils/concurrency.d.ts +0 -1
  166. package/dist/utils/dns-toolkit.d.ts +0 -1
  167. package/dist/utils/dns-toolkit.js +1 -1
  168. package/dist/utils/dns.d.ts +0 -1
  169. package/dist/utils/dns.js +2 -2
  170. package/dist/utils/doh.d.ts +0 -1
  171. package/dist/utils/download.d.ts +0 -1
  172. package/dist/utils/env-proxy.d.ts +0 -1
  173. package/dist/utils/header-parser.d.ts +0 -1
  174. package/dist/utils/html-cleaner.d.ts +0 -1
  175. package/dist/utils/link-header.d.ts +0 -1
  176. package/dist/utils/optional-require.d.ts +0 -1
  177. package/dist/utils/optional-require.js +1 -1
  178. package/dist/utils/progress.d.ts +0 -1
  179. package/dist/utils/rdap.d.ts +0 -1
  180. package/dist/utils/request-pool.d.ts +0 -1
  181. package/dist/utils/security-grader.d.ts +0 -1
  182. package/dist/utils/sparkline.d.ts +0 -1
  183. package/dist/utils/sse.d.ts +0 -1
  184. package/dist/utils/streaming.d.ts +0 -1
  185. package/dist/utils/system-metrics.d.ts +0 -1
  186. package/dist/utils/tls-inspector.d.ts +0 -1
  187. package/dist/utils/try-fn.d.ts +0 -1
  188. package/dist/utils/upload.d.ts +0 -1
  189. package/dist/utils/user-agent.d.ts +0 -1
  190. package/dist/utils/whois.d.ts +0 -1
  191. package/dist/webrtc/index.d.ts +0 -1
  192. package/dist/webrtc/index.js +1 -1
  193. package/dist/websocket/client.d.ts +0 -1
  194. package/package.json +1 -1
  195. package/dist/ai/adaptive-timeout.d.ts.map +0 -1
  196. package/dist/ai/client.d.ts.map +0 -1
  197. package/dist/ai/index.d.ts.map +0 -1
  198. package/dist/ai/providers/anthropic.d.ts.map +0 -1
  199. package/dist/ai/providers/base.d.ts.map +0 -1
  200. package/dist/ai/providers/index.d.ts.map +0 -1
  201. package/dist/ai/providers/openai.d.ts.map +0 -1
  202. package/dist/ai/rate-limiter.d.ts.map +0 -1
  203. package/dist/bench/generator.d.ts.map +0 -1
  204. package/dist/bench/stats.d.ts.map +0 -1
  205. package/dist/cache/file-storage.d.ts.map +0 -1
  206. package/dist/cache/memory-limits.d.ts.map +0 -1
  207. package/dist/cache/memory-storage.d.ts.map +0 -1
  208. package/dist/cache/redis-storage.d.ts.map +0 -1
  209. package/dist/cli/handler.d.ts.map +0 -1
  210. package/dist/cli/index.d.ts.map +0 -1
  211. package/dist/cli/presets.d.ts.map +0 -1
  212. package/dist/cli/tui/ai-chat.d.ts.map +0 -1
  213. package/dist/cli/tui/load-dashboard.d.ts.map +0 -1
  214. package/dist/cli/tui/scroll-buffer.d.ts.map +0 -1
  215. package/dist/cli/tui/search-panel.d.ts.map +0 -1
  216. package/dist/cli/tui/shell-search.d.ts.map +0 -1
  217. package/dist/cli/tui/shell.d.ts.map +0 -1
  218. package/dist/cli/tui/websocket.d.ts.map +0 -1
  219. package/dist/constants/http-status.d.ts.map +0 -1
  220. package/dist/constants.d.ts.map +0 -1
  221. package/dist/contract/index.d.ts.map +0 -1
  222. package/dist/cookies/memory-cookie-jar.d.ts.map +0 -1
  223. package/dist/core/client.d.ts.map +0 -1
  224. package/dist/core/errors.d.ts.map +0 -1
  225. package/dist/core/index.d.ts.map +0 -1
  226. package/dist/core/request-promise.d.ts.map +0 -1
  227. package/dist/core/request.d.ts.map +0 -1
  228. package/dist/core/response.d.ts.map +0 -1
  229. package/dist/dns/index.d.ts.map +0 -1
  230. package/dist/dns/propagation.d.ts.map +0 -1
  231. package/dist/events/request-events.d.ts.map +0 -1
  232. package/dist/index.d.ts.map +0 -1
  233. package/dist/mcp/client.d.ts.map +0 -1
  234. package/dist/mcp/contract.d.ts.map +0 -1
  235. package/dist/mcp/embeddings-loader.d.ts.map +0 -1
  236. package/dist/mcp/geoip-loader.d.ts.map +0 -1
  237. package/dist/mcp/index.d.ts.map +0 -1
  238. package/dist/mcp/ip-intel.d.ts.map +0 -1
  239. package/dist/mcp/search/hybrid-search.d.ts.map +0 -1
  240. package/dist/mcp/search/index.d.ts.map +0 -1
  241. package/dist/mcp/search/math.d.ts.map +0 -1
  242. package/dist/mcp/search/types.d.ts.map +0 -1
  243. package/dist/mcp/server.d.ts.map +0 -1
  244. package/dist/mcp/types.d.ts.map +0 -1
  245. package/dist/plugins/auth.d.ts.map +0 -1
  246. package/dist/plugins/cache.d.ts.map +0 -1
  247. package/dist/plugins/circuit-breaker.d.ts.map +0 -1
  248. package/dist/plugins/compression.d.ts.map +0 -1
  249. package/dist/plugins/cookie-jar.d.ts.map +0 -1
  250. package/dist/plugins/dedup.d.ts.map +0 -1
  251. package/dist/plugins/graphql.d.ts.map +0 -1
  252. package/dist/plugins/grpc-web.d.ts.map +0 -1
  253. package/dist/plugins/har-player.d.ts.map +0 -1
  254. package/dist/plugins/har-recorder.d.ts.map +0 -1
  255. package/dist/plugins/hls.d.ts.map +0 -1
  256. package/dist/plugins/http2-push.d.ts.map +0 -1
  257. package/dist/plugins/http3.d.ts.map +0 -1
  258. package/dist/plugins/interface-rotator.d.ts.map +0 -1
  259. package/dist/plugins/jsonrpc.d.ts.map +0 -1
  260. package/dist/plugins/logger.d.ts.map +0 -1
  261. package/dist/plugins/odata.d.ts.map +0 -1
  262. package/dist/plugins/pagination.d.ts.map +0 -1
  263. package/dist/plugins/proxy-rotator.d.ts.map +0 -1
  264. package/dist/plugins/retry.d.ts.map +0 -1
  265. package/dist/plugins/scrape.d.ts.map +0 -1
  266. package/dist/plugins/server-timing.d.ts.map +0 -1
  267. package/dist/plugins/soap.d.ts.map +0 -1
  268. package/dist/plugins/user-agent.d.ts.map +0 -1
  269. package/dist/plugins/xml.d.ts.map +0 -1
  270. package/dist/plugins/xsrf.d.ts.map +0 -1
  271. package/dist/presets/anthropic.d.ts.map +0 -1
  272. package/dist/presets/aws.d.ts.map +0 -1
  273. package/dist/presets/azure-openai.d.ts.map +0 -1
  274. package/dist/presets/azure.d.ts.map +0 -1
  275. package/dist/presets/cloudflare.d.ts.map +0 -1
  276. package/dist/presets/cohere.d.ts.map +0 -1
  277. package/dist/presets/deepseek.d.ts.map +0 -1
  278. package/dist/presets/digitalocean.d.ts.map +0 -1
  279. package/dist/presets/discord.d.ts.map +0 -1
  280. package/dist/presets/fireworks.d.ts.map +0 -1
  281. package/dist/presets/gcp.d.ts.map +0 -1
  282. package/dist/presets/gemini.d.ts.map +0 -1
  283. package/dist/presets/github.d.ts.map +0 -1
  284. package/dist/presets/gitlab.d.ts.map +0 -1
  285. package/dist/presets/groq.d.ts.map +0 -1
  286. package/dist/presets/huggingface.d.ts.map +0 -1
  287. package/dist/presets/index.d.ts.map +0 -1
  288. package/dist/presets/linear.d.ts.map +0 -1
  289. package/dist/presets/mailgun.d.ts.map +0 -1
  290. package/dist/presets/meta.d.ts.map +0 -1
  291. package/dist/presets/mistral.d.ts.map +0 -1
  292. package/dist/presets/notion.d.ts.map +0 -1
  293. package/dist/presets/openai.d.ts.map +0 -1
  294. package/dist/presets/oracle.d.ts.map +0 -1
  295. package/dist/presets/perplexity.d.ts.map +0 -1
  296. package/dist/presets/registry.d.ts.map +0 -1
  297. package/dist/presets/replicate.d.ts.map +0 -1
  298. package/dist/presets/sinch.d.ts.map +0 -1
  299. package/dist/presets/slack.d.ts.map +0 -1
  300. package/dist/presets/stripe.d.ts.map +0 -1
  301. package/dist/presets/supabase.d.ts.map +0 -1
  302. package/dist/presets/tiktok.d.ts.map +0 -1
  303. package/dist/presets/together.d.ts.map +0 -1
  304. package/dist/presets/twilio.d.ts.map +0 -1
  305. package/dist/presets/vercel.d.ts.map +0 -1
  306. package/dist/presets/vultr.d.ts.map +0 -1
  307. package/dist/presets/xai.d.ts.map +0 -1
  308. package/dist/presets/youtube.d.ts.map +0 -1
  309. package/dist/protocols/ftp.d.ts.map +0 -1
  310. package/dist/protocols/index.d.ts.map +0 -1
  311. package/dist/protocols/sftp.d.ts.map +0 -1
  312. package/dist/protocols/telnet.d.ts.map +0 -1
  313. package/dist/recker.d.ts.map +0 -1
  314. package/dist/runner/request-runner.d.ts.map +0 -1
  315. package/dist/scrape/document.d.ts.map +0 -1
  316. package/dist/scrape/element.d.ts.map +0 -1
  317. package/dist/scrape/extractors.d.ts.map +0 -1
  318. package/dist/scrape/index.d.ts.map +0 -1
  319. package/dist/scrape/types.d.ts.map +0 -1
  320. package/dist/testing/index.d.ts.map +0 -1
  321. package/dist/testing/mock-hls-server.d.ts.map +0 -1
  322. package/dist/testing/mock-http-server.d.ts.map +0 -1
  323. package/dist/testing/mock-sse-server.d.ts.map +0 -1
  324. package/dist/testing/mock-udp-server.d.ts.map +0 -1
  325. package/dist/testing/mock-websocket-server.d.ts.map +0 -1
  326. package/dist/testing/mock.d.ts.map +0 -1
  327. package/dist/transport/base-udp.d.ts.map +0 -1
  328. package/dist/transport/fetch.d.ts.map +0 -1
  329. package/dist/transport/udp-response.d.ts.map +0 -1
  330. package/dist/transport/udp.d.ts.map +0 -1
  331. package/dist/transport/undici.d.ts.map +0 -1
  332. package/dist/types/ai.d.ts.map +0 -1
  333. package/dist/types/index.d.ts.map +0 -1
  334. package/dist/types/logger.d.ts.map +0 -1
  335. package/dist/types/udp.d.ts.map +0 -1
  336. package/dist/udp/index.d.ts.map +0 -1
  337. package/dist/utils/agent-manager.d.ts.map +0 -1
  338. package/dist/utils/body.d.ts.map +0 -1
  339. package/dist/utils/cert.d.ts.map +0 -1
  340. package/dist/utils/charset.d.ts.map +0 -1
  341. package/dist/utils/chart.d.ts.map +0 -1
  342. package/dist/utils/client-pool.d.ts.map +0 -1
  343. package/dist/utils/colors.d.ts.map +0 -1
  344. package/dist/utils/concurrency.d.ts.map +0 -1
  345. package/dist/utils/dns-toolkit.d.ts.map +0 -1
  346. package/dist/utils/dns.d.ts.map +0 -1
  347. package/dist/utils/doh.d.ts.map +0 -1
  348. package/dist/utils/download.d.ts.map +0 -1
  349. package/dist/utils/env-proxy.d.ts.map +0 -1
  350. package/dist/utils/header-parser.d.ts.map +0 -1
  351. package/dist/utils/html-cleaner.d.ts.map +0 -1
  352. package/dist/utils/link-header.d.ts.map +0 -1
  353. package/dist/utils/optional-require.d.ts.map +0 -1
  354. package/dist/utils/progress.d.ts.map +0 -1
  355. package/dist/utils/rdap.d.ts.map +0 -1
  356. package/dist/utils/request-pool.d.ts.map +0 -1
  357. package/dist/utils/security-grader.d.ts.map +0 -1
  358. package/dist/utils/sparkline.d.ts.map +0 -1
  359. package/dist/utils/sse.d.ts.map +0 -1
  360. package/dist/utils/streaming.d.ts.map +0 -1
  361. package/dist/utils/system-metrics.d.ts.map +0 -1
  362. package/dist/utils/tls-inspector.d.ts.map +0 -1
  363. package/dist/utils/try-fn.d.ts.map +0 -1
  364. package/dist/utils/upload.d.ts.map +0 -1
  365. package/dist/utils/user-agent.d.ts.map +0 -1
  366. package/dist/utils/whois.d.ts.map +0 -1
  367. package/dist/webrtc/index.d.ts.map +0 -1
  368. package/dist/websocket/client.d.ts.map +0 -1
package/dist/cli/index.js CHANGED
@@ -126,6 +126,8 @@ async function main() {
126
126
  .version(version)
127
127
  .argument('[args...]', 'URL, Method, Headers (Key:Value), Data (key=value)')
128
128
  .option('-v, --verbose', 'Show full request/response details')
129
+ .option('-q, --quiet', 'Output only response body (no colors, perfect for piping)')
130
+ .option('-o, --output <file>', 'Write response body to file')
129
131
  .option('-j, --json', 'Force JSON content-type')
130
132
  .option('-e, --env [path]', 'Load .env file from current directory or specified path')
131
133
  .addHelpText('after', `
@@ -200,14 +202,18 @@ ${colors.bold(colors.yellow('Available Presets:'))}
200
202
  headers,
201
203
  body,
202
204
  verbose: options.verbose,
205
+ quiet: options.quiet,
206
+ output: options.output,
203
207
  presetConfig
204
208
  });
205
209
  }
206
210
  catch (error) {
207
- console.error(colors.red(`
211
+ if (!options.quiet) {
212
+ console.error(colors.red(`
208
213
  Error: ${error.message}`));
209
- if (options.verbose && error.cause) {
210
- console.error(error.cause);
214
+ if (options.verbose && error.cause) {
215
+ console.error(error.cause);
216
+ }
211
217
  }
212
218
  process.exit(1);
213
219
  }
@@ -724,7 +730,7 @@ ${colors.gray('Status:')} ${statusIcon}
724
730
  .command('generate-dmarc')
725
731
  .description('Generate a DMARC record interactively')
726
732
  .option('-p, --policy <policy>', 'Policy: none, quarantine, reject', 'none')
727
- .option('-sp, --subdomain-policy <policy>', 'Subdomain policy')
733
+ .option('--subdomain-policy <policy>', 'Subdomain policy')
728
734
  .option('--pct <percent>', 'Percentage of emails to apply policy', '100')
729
735
  .option('--rua <emails>', 'Aggregate report email(s), comma-separated')
730
736
  .option('--ruf <emails>', 'Forensic report email(s), comma-separated')
@@ -879,6 +885,500 @@ ${colors.bold(colors.yellow('Examples:'))}
879
885
  const { startLoadDashboard } = await import('./tui/load-dashboard.js');
880
886
  await startLoadDashboard({ url, users, duration, mode, http2, rampUp });
881
887
  });
888
+ const serve = program.command('serve').description('Start mock servers for testing protocols');
889
+ serve
890
+ .command('http')
891
+ .description('Start a mock HTTP server')
892
+ .option('-p, --port <number>', 'Port to listen on', '3000')
893
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
894
+ .option('--echo', 'Echo request body back in response')
895
+ .option('--delay <ms>', 'Add delay to responses (milliseconds)', '0')
896
+ .option('--cors', 'Enable CORS', true)
897
+ .addHelpText('after', `
898
+ ${colors.bold(colors.yellow('Examples:'))}
899
+ ${colors.green('$ rek serve http')} ${colors.gray('Start on port 3000')}
900
+ ${colors.green('$ rek serve http -p 8080')} ${colors.gray('Start on port 8080')}
901
+ ${colors.green('$ rek serve http --echo')} ${colors.gray('Echo mode')}
902
+ ${colors.green('$ rek serve http --delay 500')} ${colors.gray('Add 500ms delay')}
903
+ `)
904
+ .action(async (options) => {
905
+ const { MockHttpServer } = await import('../testing/mock-http-server.js');
906
+ const server = await MockHttpServer.create({
907
+ port: parseInt(options.port),
908
+ host: options.host,
909
+ delay: parseInt(options.delay),
910
+ cors: options.cors,
911
+ });
912
+ if (options.echo) {
913
+ server.any('/*', (req) => ({
914
+ status: 200,
915
+ body: {
916
+ method: req.method,
917
+ path: req.path,
918
+ query: req.query,
919
+ headers: req.headers,
920
+ body: req.body,
921
+ },
922
+ }));
923
+ }
924
+ console.log(colors.green(`
925
+ ┌─────────────────────────────────────────────┐
926
+ │ ${colors.bold('Recker Mock HTTP Server')} │
927
+ ├─────────────────────────────────────────────┤
928
+ │ URL: ${colors.cyan(server.url.padEnd(37))}│
929
+ │ Mode: ${colors.yellow((options.echo ? 'Echo' : 'Default').padEnd(36))}│
930
+ │ Delay: ${colors.gray((options.delay + 'ms').padEnd(35))}│
931
+ ├─────────────────────────────────────────────┤
932
+ │ Press ${colors.bold('Ctrl+C')} to stop │
933
+ └─────────────────────────────────────────────┘
934
+ `));
935
+ server.on('request', (req) => {
936
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(req.method.padEnd(7)) + req.path);
937
+ });
938
+ process.on('SIGINT', async () => {
939
+ console.log(colors.yellow('\nShutting down...'));
940
+ await server.stop();
941
+ process.exit(0);
942
+ });
943
+ });
944
+ serve
945
+ .command('websocket')
946
+ .alias('ws')
947
+ .description('Start a mock WebSocket server')
948
+ .option('-p, --port <number>', 'Port to listen on', '8080')
949
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
950
+ .option('--echo', 'Echo messages back (default: true)', true)
951
+ .option('--no-echo', 'Disable echo mode')
952
+ .option('--delay <ms>', 'Add delay to responses (milliseconds)', '0')
953
+ .addHelpText('after', `
954
+ ${colors.bold(colors.yellow('Examples:'))}
955
+ ${colors.green('$ rek serve websocket')} ${colors.gray('Start on port 8080')}
956
+ ${colors.green('$ rek serve ws -p 9000')} ${colors.gray('Start on port 9000')}
957
+ ${colors.green('$ rek serve ws --no-echo')} ${colors.gray('Disable echo')}
958
+ `)
959
+ .action(async (options) => {
960
+ const { MockWebSocketServer } = await import('../testing/mock-websocket-server.js');
961
+ const server = await MockWebSocketServer.create({
962
+ port: parseInt(options.port),
963
+ host: options.host,
964
+ echo: options.echo,
965
+ delay: parseInt(options.delay),
966
+ });
967
+ console.log(colors.green(`
968
+ ┌─────────────────────────────────────────────┐
969
+ │ ${colors.bold('Recker Mock WebSocket Server')} │
970
+ ├─────────────────────────────────────────────┤
971
+ │ URL: ${colors.cyan(server.url.padEnd(37))}│
972
+ │ Echo: ${colors.yellow((options.echo ? 'Enabled' : 'Disabled').padEnd(36))}│
973
+ │ Delay: ${colors.gray((options.delay + 'ms').padEnd(35))}│
974
+ ├─────────────────────────────────────────────┤
975
+ │ Press ${colors.bold('Ctrl+C')} to stop │
976
+ └─────────────────────────────────────────────┘
977
+ `));
978
+ server.on('connection', (client) => {
979
+ console.log(colors.green(`+ Connected: ${client.id}`));
980
+ });
981
+ server.on('message', (msg, client) => {
982
+ const data = msg.data.toString().slice(0, 50);
983
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(client.id) + ` ${data}${msg.data.toString().length > 50 ? '...' : ''}`);
984
+ });
985
+ server.on('disconnect', (client) => {
986
+ console.log(colors.red(`- Disconnected: ${client.id}`));
987
+ });
988
+ process.on('SIGINT', async () => {
989
+ console.log(colors.yellow('\nShutting down...'));
990
+ await server.stop();
991
+ process.exit(0);
992
+ });
993
+ });
994
+ serve
995
+ .command('sse')
996
+ .description('Start a mock SSE (Server-Sent Events) server')
997
+ .option('-p, --port <number>', 'Port to listen on', '8081')
998
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
999
+ .option('--path <string>', 'SSE endpoint path', '/events')
1000
+ .option('--heartbeat <ms>', 'Send heartbeat every N ms (0 = disabled)', '0')
1001
+ .addHelpText('after', `
1002
+ ${colors.bold(colors.yellow('Examples:'))}
1003
+ ${colors.green('$ rek serve sse')} ${colors.gray('Start on port 8081')}
1004
+ ${colors.green('$ rek serve sse -p 9000')} ${colors.gray('Start on port 9000')}
1005
+ ${colors.green('$ rek serve sse --heartbeat 5000')} ${colors.gray('Send heartbeat every 5s')}
1006
+
1007
+ ${colors.bold(colors.yellow('Interactive Commands:'))}
1008
+ Type a message and press Enter to broadcast it to all clients.
1009
+ `)
1010
+ .action(async (options) => {
1011
+ const { MockSSEServer } = await import('../testing/mock-sse-server.js');
1012
+ const readline = await import('node:readline');
1013
+ const server = await MockSSEServer.create({
1014
+ port: parseInt(options.port),
1015
+ host: options.host,
1016
+ path: options.path,
1017
+ });
1018
+ if (parseInt(options.heartbeat) > 0) {
1019
+ server.startPeriodicEvents('heartbeat', parseInt(options.heartbeat));
1020
+ }
1021
+ console.log(colors.green(`
1022
+ ┌─────────────────────────────────────────────┐
1023
+ │ ${colors.bold('Recker Mock SSE Server')} │
1024
+ ├─────────────────────────────────────────────┤
1025
+ │ URL: ${colors.cyan(server.url.padEnd(37))}│
1026
+ │ Heartbeat: ${colors.yellow((options.heartbeat === '0' ? 'Disabled' : options.heartbeat + 'ms').padEnd(31))}│
1027
+ ├─────────────────────────────────────────────┤
1028
+ │ Type message + Enter to broadcast │
1029
+ │ Press ${colors.bold('Ctrl+C')} to stop │
1030
+ └─────────────────────────────────────────────┘
1031
+ `));
1032
+ server.on('connection', (client) => {
1033
+ console.log(colors.green(`+ Connected: ${client.id}`));
1034
+ });
1035
+ server.on('disconnect', (client) => {
1036
+ console.log(colors.red(`- Disconnected: ${client.id}`));
1037
+ });
1038
+ const rl = readline.createInterface({
1039
+ input: process.stdin,
1040
+ output: process.stdout,
1041
+ });
1042
+ rl.on('line', (line) => {
1043
+ if (line.trim()) {
1044
+ const sent = server.sendData(line.trim());
1045
+ console.log(colors.gray(`Broadcast to ${sent} client(s): ${line.trim()}`));
1046
+ }
1047
+ });
1048
+ process.on('SIGINT', async () => {
1049
+ console.log(colors.yellow('\nShutting down...'));
1050
+ rl.close();
1051
+ await server.stop();
1052
+ process.exit(0);
1053
+ });
1054
+ });
1055
+ serve
1056
+ .command('hls')
1057
+ .description('Start a mock HLS streaming server')
1058
+ .option('-p, --port <number>', 'Port to listen on', '8082')
1059
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
1060
+ .option('--mode <type>', 'Stream mode: vod, live, event', 'vod')
1061
+ .option('--segments <number>', 'Number of segments (VOD mode)', '10')
1062
+ .option('--duration <seconds>', 'Segment duration in seconds', '6')
1063
+ .option('--qualities <list>', 'Comma-separated quality variants', '720p,480p,360p')
1064
+ .addHelpText('after', `
1065
+ ${colors.bold(colors.yellow('Examples:'))}
1066
+ ${colors.green('$ rek serve hls')} ${colors.gray('Start VOD server')}
1067
+ ${colors.green('$ rek serve hls --mode live')} ${colors.gray('Start live stream')}
1068
+ ${colors.green('$ rek serve hls --segments 20')} ${colors.gray('VOD with 20 segments')}
1069
+ ${colors.green('$ rek serve hls --qualities 1080p,720p,480p')}
1070
+
1071
+ ${colors.bold(colors.yellow('Endpoints:'))}
1072
+ ${colors.cyan('/master.m3u8')} Master playlist (multi-quality)
1073
+ ${colors.cyan('/playlist.m3u8')} Single quality playlist
1074
+ ${colors.cyan('/<quality>/playlist.m3u8')} Quality-specific playlist
1075
+ `)
1076
+ .action(async (options) => {
1077
+ const { MockHlsServer } = await import('../testing/mock-hls-server.js');
1078
+ const http = await import('node:http');
1079
+ const port = parseInt(options.port);
1080
+ const host = options.host;
1081
+ const qualities = options.qualities.split(',').map(q => q.trim());
1082
+ const resolutions = ['1920x1080', '1280x720', '854x480', '640x360', '426x240'];
1083
+ const bandwidths = [5000000, 2500000, 1400000, 800000, 500000];
1084
+ const variants = qualities.map((name, i) => ({
1085
+ name,
1086
+ bandwidth: bandwidths[i] || 500000,
1087
+ resolution: resolutions[i] || '640x360',
1088
+ }));
1089
+ const baseUrl = `http://${host}:${port}`;
1090
+ const hlsServer = await MockHlsServer.create({
1091
+ baseUrl,
1092
+ mode: options.mode,
1093
+ segmentCount: parseInt(options.segments),
1094
+ segmentDuration: parseInt(options.duration),
1095
+ multiQuality: variants.length > 1,
1096
+ variants: variants.length > 1 ? variants : undefined,
1097
+ });
1098
+ const httpServer = http.createServer(async (req, res) => {
1099
+ const url = `${baseUrl}${req.url}`;
1100
+ try {
1101
+ const response = await hlsServer.transport.dispatch({ url, method: req.method || 'GET' });
1102
+ res.statusCode = response.status;
1103
+ response.headers.forEach((value, key) => {
1104
+ res.setHeader(key, value);
1105
+ });
1106
+ const body = await response.arrayBuffer();
1107
+ res.end(Buffer.from(body));
1108
+ }
1109
+ catch {
1110
+ res.statusCode = 404;
1111
+ res.end('Not Found');
1112
+ }
1113
+ });
1114
+ httpServer.listen(port, host, () => {
1115
+ console.log(colors.green(`
1116
+ ┌─────────────────────────────────────────────┐
1117
+ │ ${colors.bold('Recker Mock HLS Server')} │
1118
+ ├─────────────────────────────────────────────┤
1119
+ │ Master: ${colors.cyan((hlsServer.manifestUrl).padEnd(34))}│
1120
+ │ Mode: ${colors.yellow(options.mode.padEnd(36))}│
1121
+ │ Segments: ${colors.gray(options.segments.padEnd(32))}│
1122
+ │ Duration: ${colors.gray((options.duration + 's').padEnd(32))}│
1123
+ │ Qualities: ${colors.cyan(qualities.join(', ').padEnd(31))}│
1124
+ ├─────────────────────────────────────────────┤
1125
+ │ Press ${colors.bold('Ctrl+C')} to stop │
1126
+ └─────────────────────────────────────────────┘
1127
+ `));
1128
+ });
1129
+ process.on('SIGINT', async () => {
1130
+ console.log(colors.yellow('\nShutting down...'));
1131
+ httpServer.close();
1132
+ await hlsServer.stop();
1133
+ process.exit(0);
1134
+ });
1135
+ });
1136
+ serve
1137
+ .command('udp')
1138
+ .description('Start a mock UDP server')
1139
+ .option('-p, --port <number>', 'Port to listen on', '9000')
1140
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
1141
+ .option('--echo', 'Echo messages back (default: true)', true)
1142
+ .option('--no-echo', 'Disable echo mode')
1143
+ .addHelpText('after', `
1144
+ ${colors.bold(colors.yellow('Examples:'))}
1145
+ ${colors.green('$ rek serve udp')} ${colors.gray('Start on port 9000')}
1146
+ ${colors.green('$ rek serve udp -p 5353')} ${colors.gray('Start on port 5353')}
1147
+ ${colors.green('$ rek serve udp --no-echo')} ${colors.gray('Disable echo')}
1148
+ `)
1149
+ .action(async (options) => {
1150
+ const { MockUDPServer } = await import('../testing/mock-udp-server.js');
1151
+ const server = new MockUDPServer({
1152
+ port: parseInt(options.port),
1153
+ host: options.host,
1154
+ echo: options.echo,
1155
+ });
1156
+ await server.start();
1157
+ console.log(colors.green(`
1158
+ ┌─────────────────────────────────────────────┐
1159
+ │ ${colors.bold('Recker Mock UDP Server')} │
1160
+ ├─────────────────────────────────────────────┤
1161
+ │ Address: ${colors.cyan(`${options.host}:${options.port}`.padEnd(33))}│
1162
+ │ Echo: ${colors.yellow((options.echo ? 'Enabled' : 'Disabled').padEnd(36))}│
1163
+ ├─────────────────────────────────────────────┤
1164
+ │ Press ${colors.bold('Ctrl+C')} to stop │
1165
+ └─────────────────────────────────────────────┘
1166
+ `));
1167
+ server.on('message', (msg) => {
1168
+ const data = msg.data.toString().slice(0, 50);
1169
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(`${msg.rinfo.address}:${msg.rinfo.port}`) + ` ${data}${msg.data.toString().length > 50 ? '...' : ''}`);
1170
+ });
1171
+ process.on('SIGINT', async () => {
1172
+ console.log(colors.yellow('\nShutting down...'));
1173
+ await server.stop();
1174
+ process.exit(0);
1175
+ });
1176
+ });
1177
+ serve
1178
+ .command('dns')
1179
+ .description('Start a mock DNS server')
1180
+ .option('-p, --port <number>', 'Port to listen on', '5353')
1181
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
1182
+ .option('--delay <ms>', 'Add delay to responses (milliseconds)', '0')
1183
+ .addHelpText('after', `
1184
+ ${colors.bold(colors.yellow('Examples:'))}
1185
+ ${colors.green('$ rek serve dns')} ${colors.gray('Start on port 5353')}
1186
+ ${colors.green('$ rek serve dns -p 53')} ${colors.gray('Start on standard port (requires root)')}
1187
+ ${colors.green('$ dig @127.0.0.1 -p 5353 example.com')} ${colors.gray('Test with dig')}
1188
+
1189
+ ${colors.bold(colors.yellow('Default Records:'))}
1190
+ ${colors.cyan('localhost')} A: 127.0.0.1, AAAA: ::1
1191
+ ${colors.cyan('example.com')} A, AAAA, NS, MX, TXT records
1192
+ ${colors.cyan('test.local')} A: 192.168.1.100
1193
+ `)
1194
+ .action(async (options) => {
1195
+ const { MockDnsServer } = await import('../testing/mock-dns-server.js');
1196
+ const server = await MockDnsServer.create({
1197
+ port: parseInt(options.port),
1198
+ host: options.host,
1199
+ delay: parseInt(options.delay),
1200
+ });
1201
+ console.log(colors.green(`
1202
+ ┌─────────────────────────────────────────────┐
1203
+ │ ${colors.bold('Recker Mock DNS Server')} │
1204
+ ├─────────────────────────────────────────────┤
1205
+ │ Address: ${colors.cyan(`${options.host}:${options.port}`.padEnd(33))}│
1206
+ │ Protocol: ${colors.yellow('UDP'.padEnd(32))}│
1207
+ ├─────────────────────────────────────────────┤
1208
+ │ Test: dig @${options.host} -p ${options.port} example.com │
1209
+ │ Press ${colors.bold('Ctrl+C')} to stop │
1210
+ └─────────────────────────────────────────────┘
1211
+ `));
1212
+ server.on('query', (query) => {
1213
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(query.type.padEnd(6)) + ` ${query.domain}`);
1214
+ });
1215
+ process.on('SIGINT', async () => {
1216
+ console.log(colors.yellow('\nShutting down...'));
1217
+ await server.stop();
1218
+ process.exit(0);
1219
+ });
1220
+ });
1221
+ serve
1222
+ .command('whois')
1223
+ .description('Start a mock WHOIS server')
1224
+ .option('-p, --port <number>', 'Port to listen on', '4343')
1225
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
1226
+ .option('--delay <ms>', 'Add delay to responses (milliseconds)', '0')
1227
+ .addHelpText('after', `
1228
+ ${colors.bold(colors.yellow('Examples:'))}
1229
+ ${colors.green('$ rek serve whois')} ${colors.gray('Start on port 4343')}
1230
+ ${colors.green('$ whois -h 127.0.0.1 -p 4343 example.com')} ${colors.gray('Test with whois')}
1231
+
1232
+ ${colors.bold(colors.yellow('Default Domains:'))}
1233
+ ${colors.cyan('example.com')} IANA reserved domain
1234
+ ${colors.cyan('google.com')} MarkMonitor registrar
1235
+ ${colors.cyan('test.local')} Test domain
1236
+ `)
1237
+ .action(async (options) => {
1238
+ const { MockWhoisServer } = await import('../testing/mock-whois-server.js');
1239
+ const server = await MockWhoisServer.create({
1240
+ port: parseInt(options.port),
1241
+ host: options.host,
1242
+ delay: parseInt(options.delay),
1243
+ });
1244
+ console.log(colors.green(`
1245
+ ┌─────────────────────────────────────────────┐
1246
+ │ ${colors.bold('Recker Mock WHOIS Server')} │
1247
+ ├─────────────────────────────────────────────┤
1248
+ │ Address: ${colors.cyan(`${options.host}:${options.port}`.padEnd(33))}│
1249
+ │ Protocol: ${colors.yellow('TCP'.padEnd(32))}│
1250
+ ├─────────────────────────────────────────────┤
1251
+ │ Test: whois -h ${options.host} -p ${options.port} example.com │
1252
+ │ Press ${colors.bold('Ctrl+C')} to stop │
1253
+ └─────────────────────────────────────────────┘
1254
+ `));
1255
+ server.on('query', (query) => {
1256
+ console.log(colors.gray(`${new Date().toISOString()} `) + `Query: ${colors.cyan(query)}`);
1257
+ });
1258
+ process.on('SIGINT', async () => {
1259
+ console.log(colors.yellow('\nShutting down...'));
1260
+ await server.stop();
1261
+ process.exit(0);
1262
+ });
1263
+ });
1264
+ serve
1265
+ .command('telnet')
1266
+ .description('Start a mock Telnet server')
1267
+ .option('-p, --port <number>', 'Port to listen on', '2323')
1268
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
1269
+ .option('--echo', 'Echo input back (default: true)', true)
1270
+ .option('--no-echo', 'Disable echo mode')
1271
+ .option('--delay <ms>', 'Add delay to responses (milliseconds)', '0')
1272
+ .addHelpText('after', `
1273
+ ${colors.bold(colors.yellow('Examples:'))}
1274
+ ${colors.green('$ rek serve telnet')} ${colors.gray('Start on port 2323')}
1275
+ ${colors.green('$ telnet localhost 2323')} ${colors.gray('Connect to server')}
1276
+
1277
+ ${colors.bold(colors.yellow('Built-in Commands:'))}
1278
+ ${colors.cyan('help')} Show available commands
1279
+ ${colors.cyan('echo <msg>')} Echo message back
1280
+ ${colors.cyan('date')} Show current date
1281
+ ${colors.cyan('time')} Show current time
1282
+ ${colors.cyan('ping')} Returns "pong"
1283
+ ${colors.cyan('quit')} Disconnect
1284
+ `)
1285
+ .action(async (options) => {
1286
+ const { MockTelnetServer } = await import('../testing/mock-telnet-server.js');
1287
+ const server = await MockTelnetServer.create({
1288
+ port: parseInt(options.port),
1289
+ host: options.host,
1290
+ echo: options.echo,
1291
+ delay: parseInt(options.delay),
1292
+ });
1293
+ console.log(colors.green(`
1294
+ ┌─────────────────────────────────────────────┐
1295
+ │ ${colors.bold('Recker Mock Telnet Server')} │
1296
+ ├─────────────────────────────────────────────┤
1297
+ │ Address: ${colors.cyan(`${options.host}:${options.port}`.padEnd(33))}│
1298
+ │ Echo: ${colors.yellow((options.echo ? 'Enabled' : 'Disabled').padEnd(36))}│
1299
+ ├─────────────────────────────────────────────┤
1300
+ │ Connect: telnet ${options.host} ${options.port} │
1301
+ │ Press ${colors.bold('Ctrl+C')} to stop │
1302
+ └─────────────────────────────────────────────┘
1303
+ `));
1304
+ server.on('connect', (session) => {
1305
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.green('+ Connected: ') + colors.cyan(session.id));
1306
+ });
1307
+ server.on('disconnect', (session) => {
1308
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.red('- Disconnected: ') + colors.cyan(session.id));
1309
+ });
1310
+ server.on('command', (cmd, session) => {
1311
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(session.id) + ` $ ${cmd}`);
1312
+ });
1313
+ process.on('SIGINT', async () => {
1314
+ console.log(colors.yellow('\nShutting down...'));
1315
+ await server.stop();
1316
+ process.exit(0);
1317
+ });
1318
+ });
1319
+ serve
1320
+ .command('ftp')
1321
+ .description('Start a mock FTP server')
1322
+ .option('-p, --port <number>', 'Port to listen on', '2121')
1323
+ .option('-h, --host <string>', 'Host to bind to', '127.0.0.1')
1324
+ .option('-u, --username <user>', 'Username for auth', 'user')
1325
+ .option('--password <pass>', 'Password for auth', 'pass')
1326
+ .option('--anonymous', 'Allow anonymous login (default: true)', true)
1327
+ .option('--no-anonymous', 'Disable anonymous login')
1328
+ .option('--delay <ms>', 'Add delay to responses (milliseconds)', '0')
1329
+ .addHelpText('after', `
1330
+ ${colors.bold(colors.yellow('Examples:'))}
1331
+ ${colors.green('$ rek serve ftp')} ${colors.gray('Start on port 2121')}
1332
+ ${colors.green('$ ftp localhost 2121')} ${colors.gray('Connect to server')}
1333
+ ${colors.green('$ rek serve ftp --no-anonymous')} ${colors.gray('Require authentication')}
1334
+
1335
+ ${colors.bold(colors.yellow('Default Files:'))}
1336
+ ${colors.cyan('/welcome.txt')} Welcome message
1337
+ ${colors.cyan('/readme.md')} README file
1338
+ ${colors.cyan('/data/sample.json')} Sample JSON data
1339
+ ${colors.cyan('/public/index.html')} HTML file
1340
+
1341
+ ${colors.bold(colors.yellow('Credentials:'))}
1342
+ Username: ${colors.cyan('user')} Password: ${colors.cyan('pass')}
1343
+ Or use anonymous login with user: ${colors.cyan('anonymous')}
1344
+ `)
1345
+ .action(async (options) => {
1346
+ const { MockFtpServer } = await import('../testing/mock-ftp-server.js');
1347
+ const server = await MockFtpServer.create({
1348
+ port: parseInt(options.port),
1349
+ host: options.host,
1350
+ username: options.username,
1351
+ password: options.password,
1352
+ anonymous: options.anonymous,
1353
+ delay: parseInt(options.delay),
1354
+ });
1355
+ console.log(colors.green(`
1356
+ ┌─────────────────────────────────────────────┐
1357
+ │ ${colors.bold('Recker Mock FTP Server')} │
1358
+ ├─────────────────────────────────────────────┤
1359
+ │ Address: ${colors.cyan(`${options.host}:${options.port}`.padEnd(33))}│
1360
+ │ Anonymous: ${colors.yellow((options.anonymous ? 'Allowed' : 'Disabled').padEnd(31))}│
1361
+ │ User: ${colors.cyan(options.username.padEnd(36))}│
1362
+ ├─────────────────────────────────────────────┤
1363
+ │ Connect: ftp ${options.host} ${options.port} │
1364
+ │ Press ${colors.bold('Ctrl+C')} to stop │
1365
+ └─────────────────────────────────────────────┘
1366
+ `));
1367
+ server.on('connect', (session) => {
1368
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.green('+ Connected: ') + colors.cyan(session.id));
1369
+ });
1370
+ server.on('disconnect', (session) => {
1371
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.red('- Disconnected: ') + colors.cyan(session.id));
1372
+ });
1373
+ server.on('command', (cmd, _args, session) => {
1374
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(session.id) + ` ${cmd}`);
1375
+ });
1376
+ process.on('SIGINT', async () => {
1377
+ console.log(colors.yellow('\nShutting down...'));
1378
+ await server.stop();
1379
+ process.exit(0);
1380
+ });
1381
+ });
882
1382
  program
883
1383
  .command('mcp')
884
1384
  .description('Start MCP server for AI agents to access Recker documentation')
@@ -1,2 +1 @@
1
1
  export declare function resolvePreset(name: string): any;
2
- //# sourceMappingURL=presets.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import readline from 'node:readline';
2
2
  export declare function startAIChat(rl: readline.Interface, provider?: string, apiKey?: string, model?: string): Promise<void>;
3
- //# sourceMappingURL=ai-chat.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import { LoadConfig } from '../../bench/generator.js';
2
2
  export declare function startLoadDashboard(config: LoadConfig): Promise<void>;
3
- //# sourceMappingURL=load-dashboard.d.ts.map
@@ -40,4 +40,3 @@ export declare function parseScrollKey(data: Buffer): 'pageUp' | 'pageDown' | 's
40
40
  export declare function parseMouseScroll(data: Buffer): 'scrollUp' | 'scrollDown' | null;
41
41
  export declare function enableMouseReporting(): void;
42
42
  export declare function disableMouseReporting(): void;
43
- //# sourceMappingURL=scroll-buffer.d.ts.map
@@ -38,4 +38,3 @@ export declare class SearchPanel {
38
38
  }
39
39
  export declare function openSearchPanel(query?: string): Promise<void>;
40
40
  export {};
41
- //# sourceMappingURL=search-panel.d.ts.map
@@ -43,4 +43,3 @@ export declare class ShellSearch {
43
43
  private parseTypeDefinitions;
44
44
  }
45
45
  export declare function getShellSearch(): ShellSearch;
46
- //# sourceMappingURL=shell-search.d.ts.map
@@ -73,4 +73,3 @@ export declare class RekShell {
73
73
  private printMarkdown;
74
74
  private printHelp;
75
75
  }
76
- //# sourceMappingURL=shell.d.ts.map
@@ -1716,7 +1716,7 @@ ${colors.bold('Network:')}
1716
1716
  console.log(colors.gray(` Names: ${mapData.names.length}`));
1717
1717
  console.log(colors.bold('\nOriginal sources:'));
1718
1718
  mapData.sources.forEach((source, i) => {
1719
- const hasContent = mapData.sourcesContent && mapData.sourcesContent[i];
1719
+ const hasContent = mapData.sourcesContent?.[i];
1720
1720
  const sizeInfo = hasContent
1721
1721
  ? colors.green(`[${(mapData.sourcesContent[i].length / 1024).toFixed(1)}kb]`)
1722
1722
  : colors.yellow('[no content]');
@@ -1,2 +1 @@
1
1
  export declare function startInteractiveWebSocket(url: string, headers: Record<string, string>): Promise<void>;
2
- //# sourceMappingURL=websocket.d.ts.map
@@ -71,4 +71,3 @@ export declare function isServerError(status: number): boolean;
71
71
  export declare function isError(status: number): boolean;
72
72
  export declare function isRetryable(status: number): boolean;
73
73
  export declare function getStatusText(status: number): string;
74
- //# sourceMappingURL=http-status.d.ts.map
@@ -16,4 +16,3 @@ export declare const DEFAULT_PAGE_PARAM = "page";
16
16
  export declare const DEFAULT_LIMIT_PARAM = "limit";
17
17
  export declare const DEFAULT_FAILURE_THRESHOLD = 5;
18
18
  export declare const DEFAULT_RESET_TIMEOUT_MS = 60000;
19
- //# sourceMappingURL=constants.d.ts.map
@@ -29,4 +29,3 @@ export declare class ContractError extends Error {
29
29
  }
30
30
  export declare function createContract<T extends ContractDefinition>(client: Client, contract: T): ContractClient<T>;
31
31
  export {};
32
- //# sourceMappingURL=index.d.ts.map
@@ -28,4 +28,3 @@ export declare class MemoryCookieJar implements CookieJar {
28
28
  private isExpired;
29
29
  }
30
30
  export {};
31
- //# sourceMappingURL=memory-cookie-jar.d.ts.map
@@ -116,4 +116,3 @@ export declare class Client {
116
116
  }
117
117
  export declare function createClient(options?: ExtendedClientOptions): Client;
118
118
  export {};
119
- //# sourceMappingURL=client.d.ts.map
@@ -140,4 +140,3 @@ export declare class DownloadError extends ReckerError {
140
140
  request?: ReckerRequest;
141
141
  });
142
142
  }
143
- //# sourceMappingURL=errors.d.ts.map
@@ -3,4 +3,3 @@ export * from './errors.js';
3
3
  export * from './request-promise.js';
4
4
  export * from './request.js';
5
5
  export * from './response.js';
6
- //# sourceMappingURL=index.d.ts.map
@@ -21,4 +21,3 @@ export declare class RequestPromise<T = unknown> implements Promise<ReckerRespon
21
21
  download(): AsyncGenerator<ProgressEvent>;
22
22
  [Symbol.asyncIterator](): AsyncGenerator<Uint8Array>;
23
23
  }
24
- //# sourceMappingURL=request-promise.d.ts.map
@@ -18,4 +18,3 @@ export declare class HttpRequest implements ReckerRequest {
18
18
  withHeader(name: string, value: string): ReckerRequest;
19
19
  withBody(body: BodyInit): ReckerRequest;
20
20
  }
21
- //# sourceMappingURL=request.d.ts.map