recker 1.0.43 → 1.0.44

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 (459) hide show
  1. package/README.md +47 -0
  2. package/dist/bin/recker-linux-x64 +0 -0
  3. package/dist/bin/recker-macos-x64 +0 -0
  4. package/dist/bin/recker-win-x64.exe +0 -0
  5. package/dist/bin/rek.cjs +85152 -100207
  6. package/dist/browser/ai/adaptive-timeout.d.ts +50 -0
  7. package/dist/browser/ai/adaptive-timeout.js +208 -0
  8. package/dist/browser/ai/client.d.ts +22 -0
  9. package/dist/browser/ai/client.js +294 -0
  10. package/dist/browser/ai/index.d.ts +14 -0
  11. package/dist/browser/ai/index.js +11 -0
  12. package/dist/browser/ai/providers/anthropic.d.ts +63 -0
  13. package/dist/browser/ai/providers/anthropic.js +370 -0
  14. package/dist/browser/ai/providers/base.d.ts +48 -0
  15. package/dist/browser/ai/providers/base.js +150 -0
  16. package/dist/browser/ai/providers/google.d.ts +59 -0
  17. package/dist/browser/ai/providers/google.js +305 -0
  18. package/dist/browser/ai/providers/ollama.d.ts +44 -0
  19. package/dist/browser/ai/providers/ollama.js +240 -0
  20. package/dist/browser/ai/providers/openai.d.ts +64 -0
  21. package/dist/browser/ai/providers/openai.js +298 -0
  22. package/dist/browser/ai/rate-limiter.d.ts +43 -0
  23. package/dist/browser/ai/rate-limiter.js +215 -0
  24. package/dist/browser/ai/vector/index.d.ts +2 -0
  25. package/dist/browser/ai/vector/index.js +2 -0
  26. package/dist/browser/ai/vector/similarity.d.ts +2 -0
  27. package/dist/browser/ai/vector/similarity.js +27 -0
  28. package/dist/browser/ai/vector/store.d.ts +27 -0
  29. package/dist/browser/ai/vector/store.js +82 -0
  30. package/dist/browser/browser/cache.d.ts +2 -40
  31. package/dist/browser/browser/cache.js +2 -199
  32. package/dist/browser/browser/index.d.ts +8 -0
  33. package/dist/browser/browser/index.js +8 -0
  34. package/dist/browser/browser/recker.d.ts +8 -1
  35. package/dist/browser/browser/recker.js +8 -2
  36. package/dist/browser/cache/indexed-db.d.ts +10 -0
  37. package/dist/browser/cache/indexed-db.js +88 -0
  38. package/dist/browser/cache/service-worker-cache.d.ts +18 -0
  39. package/dist/browser/cache/service-worker-cache.js +103 -0
  40. package/dist/browser/cache.d.ts +2 -40
  41. package/dist/browser/cache.js +2 -199
  42. package/dist/browser/constants/user-agents.d.ts +7 -0
  43. package/dist/browser/constants/user-agents.js +7 -0
  44. package/dist/browser/core/client.d.ts +2 -0
  45. package/dist/browser/core/client.js +19 -1
  46. package/dist/browser/index.d.ts +8 -0
  47. package/dist/browser/index.js +8 -0
  48. package/dist/browser/plugins/har-recorder.d.ts +40 -0
  49. package/dist/browser/plugins/har-recorder.js +120 -0
  50. package/dist/browser/plugins/network-simulation.d.ts +7 -0
  51. package/dist/browser/plugins/network-simulation.js +13 -0
  52. package/dist/browser/presets/android.d.ts +2 -0
  53. package/dist/browser/presets/android.js +16 -0
  54. package/dist/browser/presets/anthropic.d.ts +8 -0
  55. package/dist/browser/presets/anthropic.js +27 -0
  56. package/dist/browser/presets/aws.d.ts +19 -0
  57. package/dist/browser/presets/aws.js +68 -0
  58. package/dist/browser/presets/azure-openai.d.ts +10 -0
  59. package/dist/browser/presets/azure-openai.js +35 -0
  60. package/dist/browser/presets/azure.d.ts +41 -0
  61. package/dist/browser/presets/azure.js +104 -0
  62. package/dist/browser/presets/chaturbate.d.ts +2 -0
  63. package/dist/browser/presets/chaturbate.js +17 -0
  64. package/dist/browser/presets/cloudflare.d.ts +12 -0
  65. package/dist/browser/presets/cloudflare.js +39 -0
  66. package/dist/browser/presets/cohere.d.ts +7 -0
  67. package/dist/browser/presets/cohere.js +22 -0
  68. package/dist/browser/presets/deepseek.d.ts +7 -0
  69. package/dist/browser/presets/deepseek.js +22 -0
  70. package/dist/browser/presets/digitalocean.d.ts +5 -0
  71. package/dist/browser/presets/digitalocean.js +16 -0
  72. package/dist/browser/presets/discord.d.ts +6 -0
  73. package/dist/browser/presets/discord.js +17 -0
  74. package/dist/browser/presets/elevenlabs.d.ts +6 -0
  75. package/dist/browser/presets/elevenlabs.js +20 -0
  76. package/dist/browser/presets/enhancers.d.ts +20 -0
  77. package/dist/browser/presets/enhancers.js +85 -0
  78. package/dist/browser/presets/fireworks.d.ts +7 -0
  79. package/dist/browser/presets/fireworks.js +22 -0
  80. package/dist/browser/presets/gcp.d.ts +34 -0
  81. package/dist/browser/presets/gcp.js +91 -0
  82. package/dist/browser/presets/gemini.d.ts +7 -0
  83. package/dist/browser/presets/gemini.js +23 -0
  84. package/dist/browser/presets/github.d.ts +6 -0
  85. package/dist/browser/presets/github.js +17 -0
  86. package/dist/browser/presets/gitlab.d.ts +6 -0
  87. package/dist/browser/presets/gitlab.js +16 -0
  88. package/dist/browser/presets/groq.d.ts +7 -0
  89. package/dist/browser/presets/groq.js +22 -0
  90. package/dist/browser/presets/hubspot.d.ts +9 -0
  91. package/dist/browser/presets/hubspot.js +28 -0
  92. package/dist/browser/presets/huggingface.d.ts +7 -0
  93. package/dist/browser/presets/huggingface.js +23 -0
  94. package/dist/browser/presets/index.d.ts +47 -0
  95. package/dist/browser/presets/index.js +47 -0
  96. package/dist/browser/presets/ios.d.ts +2 -0
  97. package/dist/browser/presets/ios.js +13 -0
  98. package/dist/browser/presets/linear.d.ts +5 -0
  99. package/dist/browser/presets/linear.js +16 -0
  100. package/dist/browser/presets/mailgun.d.ts +7 -0
  101. package/dist/browser/presets/mailgun.js +20 -0
  102. package/dist/browser/presets/meta.d.ts +10 -0
  103. package/dist/browser/presets/meta.js +33 -0
  104. package/dist/browser/presets/mistral.d.ts +7 -0
  105. package/dist/browser/presets/mistral.js +22 -0
  106. package/dist/browser/presets/notion.d.ts +6 -0
  107. package/dist/browser/presets/notion.js +17 -0
  108. package/dist/browser/presets/openai.d.ts +9 -0
  109. package/dist/browser/presets/openai.js +30 -0
  110. package/dist/browser/presets/oracle.d.ts +19 -0
  111. package/dist/browser/presets/oracle.js +117 -0
  112. package/dist/browser/presets/perplexity.d.ts +7 -0
  113. package/dist/browser/presets/perplexity.js +22 -0
  114. package/dist/browser/presets/pinecone.d.ts +8 -0
  115. package/dist/browser/presets/pinecone.js +42 -0
  116. package/dist/browser/presets/registry.d.ts +23 -0
  117. package/dist/browser/presets/registry.js +519 -0
  118. package/dist/browser/presets/replicate.d.ts +7 -0
  119. package/dist/browser/presets/replicate.js +23 -0
  120. package/dist/browser/presets/sendgrid.d.ts +6 -0
  121. package/dist/browser/presets/sendgrid.js +20 -0
  122. package/dist/browser/presets/sentry.d.ts +11 -0
  123. package/dist/browser/presets/sentry.js +48 -0
  124. package/dist/browser/presets/sinch.d.ts +9 -0
  125. package/dist/browser/presets/sinch.js +39 -0
  126. package/dist/browser/presets/slack.d.ts +5 -0
  127. package/dist/browser/presets/slack.js +16 -0
  128. package/dist/browser/presets/square.d.ts +10 -0
  129. package/dist/browser/presets/square.js +33 -0
  130. package/dist/browser/presets/stripe.d.ts +7 -0
  131. package/dist/browser/presets/stripe.js +23 -0
  132. package/dist/browser/presets/supabase.d.ts +6 -0
  133. package/dist/browser/presets/supabase.js +18 -0
  134. package/dist/browser/presets/tiktok.d.ts +10 -0
  135. package/dist/browser/presets/tiktok.js +38 -0
  136. package/dist/browser/presets/together.d.ts +7 -0
  137. package/dist/browser/presets/together.js +22 -0
  138. package/dist/browser/presets/twilio.d.ts +6 -0
  139. package/dist/browser/presets/twilio.js +17 -0
  140. package/dist/browser/presets/vercel.d.ts +6 -0
  141. package/dist/browser/presets/vercel.js +23 -0
  142. package/dist/browser/presets/vultr.d.ts +5 -0
  143. package/dist/browser/presets/vultr.js +16 -0
  144. package/dist/browser/presets/xai.d.ts +8 -0
  145. package/dist/browser/presets/xai.js +23 -0
  146. package/dist/browser/presets/youtube.d.ts +5 -0
  147. package/dist/browser/presets/youtube.js +20 -0
  148. package/dist/browser/recker.d.ts +8 -1
  149. package/dist/browser/recker.js +8 -2
  150. package/dist/browser/scrape/document.d.ts +5 -4
  151. package/dist/browser/scrape/document.js +89 -76
  152. package/dist/browser/scrape/element.d.ts +10 -8
  153. package/dist/browser/scrape/element.js +295 -81
  154. package/dist/browser/scrape/extractors.d.ts +11 -11
  155. package/dist/browser/scrape/extractors.js +145 -113
  156. package/dist/browser/scrape/parser/back.d.ts +1 -0
  157. package/dist/browser/scrape/parser/back.js +3 -0
  158. package/dist/browser/scrape/parser/index.d.ts +20 -0
  159. package/dist/browser/scrape/parser/index.js +19 -0
  160. package/dist/browser/scrape/parser/matcher.d.ts +30 -0
  161. package/dist/browser/scrape/parser/matcher.js +99 -0
  162. package/dist/browser/scrape/parser/nodes/comment.d.ts +12 -0
  163. package/dist/browser/scrape/parser/nodes/comment.js +21 -0
  164. package/dist/browser/scrape/parser/nodes/html.d.ts +110 -0
  165. package/dist/browser/scrape/parser/nodes/html.js +978 -0
  166. package/dist/browser/scrape/parser/nodes/node.d.ts +18 -0
  167. package/dist/browser/scrape/parser/nodes/node.js +31 -0
  168. package/dist/browser/scrape/parser/nodes/text.d.ts +14 -0
  169. package/dist/browser/scrape/parser/nodes/text.js +30 -0
  170. package/dist/browser/scrape/parser/nodes/type.d.ts +6 -0
  171. package/dist/browser/scrape/parser/nodes/type.js +7 -0
  172. package/dist/browser/scrape/parser/parse.d.ts +1 -0
  173. package/dist/browser/scrape/parser/parse.js +1 -0
  174. package/dist/browser/scrape/parser/valid.d.ts +2 -0
  175. package/dist/browser/scrape/parser/valid.js +5 -0
  176. package/dist/browser/scrape/parser/void-tag.d.ts +7 -0
  177. package/dist/browser/scrape/parser/void-tag.js +43 -0
  178. package/dist/browser/scrape/types.d.ts +7 -0
  179. package/dist/browser/seo/analyzer.d.ts +59 -0
  180. package/dist/browser/seo/analyzer.js +1399 -0
  181. package/dist/browser/seo/keywords.d.ts +16 -0
  182. package/dist/browser/seo/keywords.js +55 -0
  183. package/dist/browser/seo/rules/accessibility.d.ts +2 -0
  184. package/dist/browser/seo/rules/accessibility.js +733 -0
  185. package/dist/browser/seo/rules/ai-search.d.ts +2 -0
  186. package/dist/browser/seo/rules/ai-search.js +436 -0
  187. package/dist/browser/seo/rules/analytics.d.ts +2 -0
  188. package/dist/browser/seo/rules/analytics.js +306 -0
  189. package/dist/browser/seo/rules/best-practices.d.ts +2 -0
  190. package/dist/browser/seo/rules/best-practices.js +195 -0
  191. package/dist/browser/seo/rules/canonical.d.ts +12 -0
  192. package/dist/browser/seo/rules/canonical.js +270 -0
  193. package/dist/browser/seo/rules/content.d.ts +2 -0
  194. package/dist/browser/seo/rules/content.js +522 -0
  195. package/dist/browser/seo/rules/crawl.d.ts +2 -0
  196. package/dist/browser/seo/rules/crawl.js +435 -0
  197. package/dist/browser/seo/rules/cwv.d.ts +2 -0
  198. package/dist/browser/seo/rules/cwv.js +248 -0
  199. package/dist/browser/seo/rules/ecommerce.d.ts +2 -0
  200. package/dist/browser/seo/rules/ecommerce.js +312 -0
  201. package/dist/browser/seo/rules/i18n.d.ts +2 -0
  202. package/dist/browser/seo/rules/i18n.js +288 -0
  203. package/dist/browser/seo/rules/images.d.ts +2 -0
  204. package/dist/browser/seo/rules/images.js +255 -0
  205. package/dist/browser/seo/rules/index.d.ts +52 -0
  206. package/dist/browser/seo/rules/index.js +159 -0
  207. package/dist/browser/seo/rules/internal-linking.d.ts +2 -0
  208. package/dist/browser/seo/rules/internal-linking.js +394 -0
  209. package/dist/browser/seo/rules/links.d.ts +2 -0
  210. package/dist/browser/seo/rules/links.js +498 -0
  211. package/dist/browser/seo/rules/local.d.ts +2 -0
  212. package/dist/browser/seo/rules/local.js +289 -0
  213. package/dist/browser/seo/rules/meta.d.ts +2 -0
  214. package/dist/browser/seo/rules/meta.js +805 -0
  215. package/dist/browser/seo/rules/mobile.d.ts +2 -0
  216. package/dist/browser/seo/rules/mobile.js +161 -0
  217. package/dist/browser/seo/rules/performance.d.ts +2 -0
  218. package/dist/browser/seo/rules/performance.js +738 -0
  219. package/dist/browser/seo/rules/pwa.d.ts +2 -0
  220. package/dist/browser/seo/rules/pwa.js +299 -0
  221. package/dist/browser/seo/rules/readability.d.ts +2 -0
  222. package/dist/browser/seo/rules/readability.js +264 -0
  223. package/dist/browser/seo/rules/redirects.d.ts +16 -0
  224. package/dist/browser/seo/rules/redirects.js +199 -0
  225. package/dist/browser/seo/rules/resources.d.ts +2 -0
  226. package/dist/browser/seo/rules/resources.js +390 -0
  227. package/dist/browser/seo/rules/schema.d.ts +2 -0
  228. package/dist/browser/seo/rules/schema.js +379 -0
  229. package/dist/browser/seo/rules/security.d.ts +2 -0
  230. package/dist/browser/seo/rules/security.js +877 -0
  231. package/dist/browser/seo/rules/social.d.ts +2 -0
  232. package/dist/browser/seo/rules/social.js +603 -0
  233. package/dist/browser/seo/rules/structural.d.ts +2 -0
  234. package/dist/browser/seo/rules/structural.js +223 -0
  235. package/dist/browser/seo/rules/technical-advanced.d.ts +10 -0
  236. package/dist/browser/seo/rules/technical-advanced.js +289 -0
  237. package/dist/browser/seo/rules/technical.d.ts +2 -0
  238. package/dist/browser/seo/rules/technical.js +480 -0
  239. package/dist/browser/seo/rules/thresholds.d.ts +196 -0
  240. package/dist/browser/seo/rules/thresholds.js +118 -0
  241. package/dist/browser/seo/rules/types.d.ts +498 -0
  242. package/dist/browser/seo/rules/types.js +11 -0
  243. package/dist/browser/seo/types.d.ts +211 -0
  244. package/dist/browser/seo/types.js +1 -0
  245. package/dist/browser/transport/curl.d.ts +4 -0
  246. package/dist/browser/transport/curl.js +101 -0
  247. package/dist/browser/transport/undici.js +1 -2
  248. package/dist/browser/transport/worker.d.ts +18 -0
  249. package/dist/browser/transport/worker.js +278 -0
  250. package/dist/browser/types/index.d.ts +4 -1
  251. package/dist/browser/utils/binary-manager.d.ts +4 -0
  252. package/dist/browser/utils/binary-manager.js +72 -0
  253. package/dist/browser/utils/user-agent.js +2 -13
  254. package/dist/cache/indexed-db.d.ts +10 -0
  255. package/dist/cache/indexed-db.js +88 -0
  256. package/dist/cache/service-worker-cache.d.ts +18 -0
  257. package/dist/cache/service-worker-cache.js +103 -0
  258. package/dist/cli/commands/ai.d.ts +2 -0
  259. package/dist/cli/commands/ai.js +162 -0
  260. package/dist/cli/commands/bench.d.ts +2 -0
  261. package/dist/cli/commands/bench.js +51 -0
  262. package/dist/cli/commands/dns.d.ts +2 -0
  263. package/dist/cli/commands/dns.js +295 -0
  264. package/dist/cli/commands/har.d.ts +2 -0
  265. package/dist/cli/commands/har.js +171 -0
  266. package/dist/cli/commands/hls.d.ts +2 -0
  267. package/dist/cli/commands/hls.js +192 -0
  268. package/dist/cli/commands/network.d.ts +2 -0
  269. package/dist/cli/commands/network.js +288 -0
  270. package/dist/cli/commands/protocols.d.ts +2 -0
  271. package/dist/cli/commands/protocols.js +344 -0
  272. package/dist/cli/commands/scrape.d.ts +2 -0
  273. package/dist/cli/commands/scrape.js +176 -0
  274. package/dist/cli/commands/security.d.ts +2 -0
  275. package/dist/cli/commands/security.js +57 -0
  276. package/dist/cli/commands/seo.d.ts +2 -0
  277. package/dist/cli/commands/seo.js +125 -0
  278. package/dist/cli/commands/serve.d.ts +2 -0
  279. package/dist/cli/commands/serve.js +531 -0
  280. package/dist/cli/commands/spider.d.ts +3 -0
  281. package/dist/cli/commands/spider.js +456 -0
  282. package/dist/cli/commands/utils.d.ts +2 -0
  283. package/dist/cli/commands/utils.js +176 -0
  284. package/dist/cli/commands/vector.d.ts +2 -0
  285. package/dist/cli/commands/vector.js +158 -0
  286. package/dist/cli/handler.d.ts +2 -2
  287. package/dist/cli/handler.js +6 -6
  288. package/dist/cli/helpers.d.ts +7 -0
  289. package/dist/cli/helpers.js +128 -0
  290. package/dist/cli/index.js +96 -5228
  291. package/dist/cli/parser/help.d.ts +2 -0
  292. package/dist/cli/parser/help.js +52 -0
  293. package/dist/cli/parser/index.d.ts +3 -0
  294. package/dist/cli/parser/index.js +3 -0
  295. package/dist/cli/parser/parser.d.ts +4 -0
  296. package/dist/cli/parser/parser.js +146 -0
  297. package/dist/cli/parser/types.d.ts +41 -0
  298. package/dist/cli/parser/types.js +1 -0
  299. package/dist/cli/presets.d.ts +1 -1
  300. package/dist/cli/presets.js +1 -1
  301. package/dist/cli/router.d.ts +36 -0
  302. package/dist/cli/router.js +195 -0
  303. package/dist/cli/tui/ai-chat.js +1 -1
  304. package/dist/cli/tui/commands/context.d.ts +9 -0
  305. package/dist/cli/tui/commands/context.js +1 -0
  306. package/dist/cli/tui/commands/dns.d.ts +10 -0
  307. package/dist/cli/tui/commands/dns.js +461 -0
  308. package/dist/cli/tui/commands/hls.d.ts +2 -0
  309. package/dist/cli/tui/commands/hls.js +162 -0
  310. package/dist/cli/tui/commands/ip.d.ts +2 -0
  311. package/dist/cli/tui/commands/ip.js +45 -0
  312. package/dist/cli/tui/commands/network.d.ts +3 -0
  313. package/dist/cli/tui/commands/network.js +81 -0
  314. package/dist/cli/tui/commands/protocols.d.ts +6 -0
  315. package/dist/cli/tui/commands/protocols.js +531 -0
  316. package/dist/cli/tui/commands/security.d.ts +2 -0
  317. package/dist/cli/tui/commands/security.js +48 -0
  318. package/dist/cli/tui/commands/seo.d.ts +2 -0
  319. package/dist/cli/tui/commands/seo.js +74 -0
  320. package/dist/cli/tui/context.d.ts +12 -0
  321. package/dist/cli/tui/context.js +1 -0
  322. package/dist/cli/tui/shell.d.ts +11 -20
  323. package/dist/cli/tui/shell.js +216 -1873
  324. package/dist/constants/user-agents.d.ts +7 -0
  325. package/dist/constants/user-agents.js +7 -0
  326. package/dist/core/client.d.ts +2 -0
  327. package/dist/core/client.js +19 -1
  328. package/dist/index.d.ts +1 -0
  329. package/dist/index.js +1 -0
  330. package/dist/mcp/cli.js +2 -3
  331. package/dist/mcp/data/embeddings.json +1 -1
  332. package/dist/mcp/tools/network.js +298 -158
  333. package/dist/plugins/har-player.d.ts +23 -0
  334. package/dist/plugins/har-player.js +49 -0
  335. package/dist/plugins/har-recorder.d.ts +37 -3
  336. package/dist/plugins/har-recorder.js +116 -63
  337. package/dist/plugins/network-simulation.d.ts +7 -0
  338. package/dist/plugins/network-simulation.js +13 -0
  339. package/dist/presets/android.d.ts +2 -0
  340. package/dist/presets/android.js +16 -0
  341. package/dist/presets/chaturbate.d.ts +2 -0
  342. package/dist/presets/chaturbate.js +17 -0
  343. package/dist/presets/elevenlabs.d.ts +6 -0
  344. package/dist/presets/elevenlabs.js +20 -0
  345. package/dist/presets/enhancers.d.ts +20 -0
  346. package/dist/presets/enhancers.js +85 -0
  347. package/dist/presets/hubspot.d.ts +9 -0
  348. package/dist/presets/hubspot.js +28 -0
  349. package/dist/presets/index.d.ts +10 -0
  350. package/dist/presets/index.js +10 -0
  351. package/dist/presets/ios.d.ts +2 -0
  352. package/dist/presets/ios.js +13 -0
  353. package/dist/presets/pinecone.d.ts +8 -0
  354. package/dist/presets/pinecone.js +42 -0
  355. package/dist/presets/registry.js +60 -0
  356. package/dist/presets/sendgrid.d.ts +6 -0
  357. package/dist/presets/sendgrid.js +20 -0
  358. package/dist/presets/sentry.d.ts +11 -0
  359. package/dist/presets/sentry.js +48 -0
  360. package/dist/presets/square.d.ts +10 -0
  361. package/dist/presets/square.js +33 -0
  362. package/dist/recker.d.ts +3 -0
  363. package/dist/recker.js +4 -0
  364. package/dist/scrape/document.d.ts +5 -4
  365. package/dist/scrape/document.js +89 -76
  366. package/dist/scrape/element.d.ts +10 -8
  367. package/dist/scrape/element.js +295 -81
  368. package/dist/scrape/extractors.d.ts +11 -11
  369. package/dist/scrape/extractors.js +145 -113
  370. package/dist/scrape/index.d.ts +2 -0
  371. package/dist/scrape/index.js +1 -0
  372. package/dist/scrape/parser/back.d.ts +1 -0
  373. package/dist/scrape/parser/back.js +3 -0
  374. package/dist/scrape/parser/index.d.ts +20 -0
  375. package/dist/scrape/parser/index.js +19 -0
  376. package/dist/scrape/parser/matcher.d.ts +30 -0
  377. package/dist/scrape/parser/matcher.js +99 -0
  378. package/dist/scrape/parser/nodes/comment.d.ts +12 -0
  379. package/dist/scrape/parser/nodes/comment.js +21 -0
  380. package/dist/scrape/parser/nodes/html.d.ts +110 -0
  381. package/dist/scrape/parser/nodes/html.js +978 -0
  382. package/dist/scrape/parser/nodes/node.d.ts +18 -0
  383. package/dist/scrape/parser/nodes/node.js +31 -0
  384. package/dist/scrape/parser/nodes/text.d.ts +14 -0
  385. package/dist/scrape/parser/nodes/text.js +30 -0
  386. package/dist/scrape/parser/nodes/type.d.ts +6 -0
  387. package/dist/scrape/parser/nodes/type.js +7 -0
  388. package/dist/scrape/parser/parse.d.ts +1 -0
  389. package/dist/scrape/parser/parse.js +1 -0
  390. package/dist/scrape/parser/valid.d.ts +2 -0
  391. package/dist/scrape/parser/valid.js +5 -0
  392. package/dist/scrape/parser/void-tag.d.ts +7 -0
  393. package/dist/scrape/parser/void-tag.js +43 -0
  394. package/dist/scrape/spider.d.ts +19 -0
  395. package/dist/scrape/spider.js +28 -3
  396. package/dist/scrape/types.d.ts +7 -0
  397. package/dist/seo/analyzer.d.ts +15 -5
  398. package/dist/seo/analyzer.js +636 -175
  399. package/dist/seo/formatter.d.ts +16 -0
  400. package/dist/seo/formatter.js +228 -0
  401. package/dist/seo/index.d.ts +2 -0
  402. package/dist/seo/index.js +1 -0
  403. package/dist/seo/keywords.d.ts +16 -0
  404. package/dist/seo/keywords.js +55 -0
  405. package/dist/seo/rules/accessibility.js +96 -57
  406. package/dist/seo/rules/ai-search.js +44 -31
  407. package/dist/seo/rules/analytics.d.ts +2 -0
  408. package/dist/seo/rules/analytics.js +306 -0
  409. package/dist/seo/rules/best-practices.js +21 -14
  410. package/dist/seo/rules/canonical.js +53 -32
  411. package/dist/seo/rules/content.js +317 -31
  412. package/dist/seo/rules/crawl.js +55 -40
  413. package/dist/seo/rules/cwv.js +21 -15
  414. package/dist/seo/rules/ecommerce.js +82 -22
  415. package/dist/seo/rules/i18n.js +75 -36
  416. package/dist/seo/rules/images.js +109 -30
  417. package/dist/seo/rules/index.js +2 -0
  418. package/dist/seo/rules/internal-linking.js +58 -39
  419. package/dist/seo/rules/links.js +79 -52
  420. package/dist/seo/rules/local.js +49 -25
  421. package/dist/seo/rules/meta.js +339 -81
  422. package/dist/seo/rules/mobile.js +112 -2
  423. package/dist/seo/rules/performance.js +434 -66
  424. package/dist/seo/rules/pwa.js +36 -39
  425. package/dist/seo/rules/readability.js +31 -22
  426. package/dist/seo/rules/redirects.js +21 -15
  427. package/dist/seo/rules/resources.js +59 -42
  428. package/dist/seo/rules/schema.js +333 -8
  429. package/dist/seo/rules/security.js +142 -80
  430. package/dist/seo/rules/social.js +277 -47
  431. package/dist/seo/rules/structural.js +87 -19
  432. package/dist/seo/rules/technical-advanced.js +30 -24
  433. package/dist/seo/rules/technical.js +243 -42
  434. package/dist/seo/rules/types.d.ts +53 -1
  435. package/dist/seo/seo-spider.d.ts +22 -0
  436. package/dist/seo/seo-spider.js +77 -13
  437. package/dist/seo/types.d.ts +8 -1
  438. package/dist/seo/validators/llms-txt.js +19 -0
  439. package/dist/seo/validators/rss.d.ts +11 -0
  440. package/dist/seo/validators/rss.js +93 -0
  441. package/dist/seo/validators/sitemap.js +36 -26
  442. package/dist/transport/curl.d.ts +4 -0
  443. package/dist/transport/curl.js +101 -0
  444. package/dist/transport/udp.js +0 -1
  445. package/dist/transport/undici.js +1 -2
  446. package/dist/transport/worker.d.ts +18 -0
  447. package/dist/transport/worker.js +278 -0
  448. package/dist/types/index.d.ts +4 -1
  449. package/dist/utils/binary-manager.d.ts +4 -0
  450. package/dist/utils/binary-manager.js +72 -0
  451. package/dist/utils/optional-require.d.ts +7 -8
  452. package/dist/utils/optional-require.js +2 -21
  453. package/dist/utils/upload.d.ts +6 -0
  454. package/dist/utils/upload.js +11 -0
  455. package/dist/utils/user-agent.js +2 -13
  456. package/dist/version.js +1 -1
  457. package/package.json +12 -6
  458. package/dist/browser/utils/optional-require.d.ts +0 -19
  459. package/dist/browser/utils/optional-require.js +0 -105
@@ -0,0 +1,125 @@
1
+ import colors from '../../utils/colors.js';
2
+ import { RekArgs, generateHelp } from '../parser/index.js';
3
+ import { formatSeoReport, formatSeoReportJson } from '../../seo/formatter.js';
4
+ const seoSchema = {
5
+ name: 'seo',
6
+ description: 'Analyze SEO for a webpage.\nRuns a comprehensive SEO audit including technical, content, and performance checks.',
7
+ flags: {
8
+ json: { description: 'Output report as JSON' },
9
+ all: { description: 'Show all checks including passed', alias: 'a' },
10
+ evidence: { description: 'Show detailed evidence for issues', alias: 'e' },
11
+ compact: { description: 'Compact output mode', alias: 'c' },
12
+ content: { description: 'Analyze content depth/quality', default: true },
13
+ 'no-content': { description: 'Skip content analysis' },
14
+ links: { description: 'Check broken links (slower)', default: false }
15
+ },
16
+ params: {
17
+ category: {
18
+ type: 'string',
19
+ description: 'Filter by category (e.g., performance, security, content, links, images, meta, technical, accessibility, og, twitter)',
20
+ },
21
+ },
22
+ keywords: {
23
+ all: { description: 'Show all checks including passed', mapTo: 'all' },
24
+ json: { description: 'Output report as JSON', mapTo: 'json' },
25
+ evidence: { description: 'Show detailed evidence', mapTo: 'evidence' },
26
+ compact: { description: 'Compact output', mapTo: 'compact' },
27
+ },
28
+ examples: [
29
+ { cmd: 'rek seo example.com', desc: 'Run SEO audit' },
30
+ { cmd: 'rek seo example.com --json', desc: 'Get JSON report' },
31
+ { cmd: 'rek seo example.com -a', desc: 'Show all checks' },
32
+ { cmd: 'rek seo example.com -e', desc: 'Show evidence for issues' },
33
+ { cmd: 'rek seo example.com category=performance', desc: 'Only performance checks' },
34
+ { cmd: 'rek seo example.com category=security', desc: 'Only security checks' }
35
+ ]
36
+ };
37
+ export function registerSeoCommand(program) {
38
+ program
39
+ .command('seo')
40
+ .description(seoSchema.description)
41
+ .argument('<url>', 'URL to analyze')
42
+ .argument('[args...]', 'Options')
43
+ .addHelpText('after', generateHelp(seoSchema))
44
+ .action(async (url, rawArgs) => {
45
+ const { options, data } = RekArgs.parse(rawArgs, seoSchema);
46
+ const jsonOutput = !!options.json || !!data.json;
47
+ const analyzeContent = options['no-content'] ? false : (options.content !== false);
48
+ const checkBrokenLinks = !!options.links;
49
+ const formatOptions = {
50
+ showAll: !!options.all || !!data.all,
51
+ showEvidence: !!options.evidence || !!data.evidence,
52
+ compact: !!options.compact || !!data.compact,
53
+ showKeywords: true,
54
+ showTiming: true,
55
+ };
56
+ if (!url.startsWith('http'))
57
+ url = `https://${url}`;
58
+ const { SeoAnalyzer } = await import('../../seo/analyzer.js');
59
+ const { createClient } = await import('../../core/client.js');
60
+ if (!jsonOutput) {
61
+ console.log(colors.gray(`Analyzing ${url}...`));
62
+ }
63
+ try {
64
+ const client = createClient();
65
+ const startTime = performance.now();
66
+ const response = await client.get(url);
67
+ const html = await response.text();
68
+ const duration = Math.round(performance.now() - startTime);
69
+ const responseHeaders = Object.fromEntries(response.headers.entries());
70
+ const analyzer = await SeoAnalyzer.fromHtml(html, {
71
+ baseUrl: url,
72
+ analyzeContent,
73
+ checkBrokenLinks,
74
+ responseHeaders
75
+ });
76
+ let report = analyzer.analyze();
77
+ const categoryFilter = data.category;
78
+ if (categoryFilter) {
79
+ const normalizedFilter = categoryFilter.toLowerCase();
80
+ const filteredChecks = report.checks.filter(check => check.category.toLowerCase() === normalizedFilter);
81
+ const passed = filteredChecks.filter(c => c.status === 'pass').length;
82
+ const warnings = filteredChecks.filter(c => c.status === 'warn').length;
83
+ const errors = filteredChecks.filter(c => c.status === 'fail').length;
84
+ const infos = filteredChecks.filter(c => c.status === 'info').length;
85
+ const totalChecks = filteredChecks.length;
86
+ report = {
87
+ ...report,
88
+ checks: filteredChecks,
89
+ summary: {
90
+ ...report.summary,
91
+ totalChecks,
92
+ passed,
93
+ warnings,
94
+ errors,
95
+ infos,
96
+ passRate: totalChecks > 0 ? Math.round((passed / totalChecks) * 100) : 0,
97
+ topIssues: report.summary.topIssues.filter(issue => issue.category.toLowerCase() === normalizedFilter),
98
+ },
99
+ };
100
+ if (!jsonOutput) {
101
+ console.log(colors.gray(`Filtered to category: ${categoryFilter} (${totalChecks} checks)`));
102
+ }
103
+ }
104
+ const t = response.timings;
105
+ report.timing = {
106
+ ttfb: t?.firstByte ? Math.round(t.firstByte) : undefined,
107
+ total: t?.total ? Math.round(t.total) : duration,
108
+ dns: t?.dns ? Math.round(t.dns) : undefined,
109
+ tcp: t?.tcp ? Math.round(t.tcp) : undefined,
110
+ tls: t?.tls ? Math.round(t.tls) : undefined,
111
+ download: t?.content ? Math.round(t.content) : undefined,
112
+ };
113
+ if (jsonOutput) {
114
+ const jsonResult = formatSeoReportJson(report, url);
115
+ console.log(JSON.stringify(jsonResult, null, 2));
116
+ return;
117
+ }
118
+ console.log(formatSeoReport(report, url, formatOptions));
119
+ }
120
+ catch (error) {
121
+ console.error(colors.red(`Analysis failed: ${error.message}`));
122
+ process.exit(1);
123
+ }
124
+ });
125
+ }
@@ -0,0 +1,2 @@
1
+ import { RekCommand as Command } from '../router.js';
2
+ export declare function registerServeCommand(program: Command): void;
@@ -0,0 +1,531 @@
1
+ import colors from '../../utils/colors.js';
2
+ import { RekArgs, generateHelp } from '../parser/index.js';
3
+ const httpSchema = {
4
+ name: 'http',
5
+ description: 'Start a mock HTTP server for testing',
6
+ params: {
7
+ port: { type: 'number', default: 3000, description: 'Port to listen on' },
8
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
9
+ delay: { type: 'number', default: 0, description: 'Add delay to responses in ms' },
10
+ },
11
+ flags: {
12
+ echo: { description: 'Echo request body back in response', default: false },
13
+ cors: { description: 'Enable CORS', default: true },
14
+ nocors: { description: 'Disable CORS' }
15
+ },
16
+ examples: [
17
+ { cmd: 'rek serve http', desc: 'Start on port 3000' },
18
+ { cmd: 'rek serve http port=8080', desc: 'Start on port 8080' },
19
+ { cmd: 'rek serve http echo', desc: 'Echo mode' }
20
+ ]
21
+ };
22
+ const webhookSchema = {
23
+ name: 'webhook',
24
+ description: 'Start a webhook receiver server',
25
+ params: {
26
+ port: { type: 'number', default: 3000, description: 'Port to listen on' },
27
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
28
+ status: { type: 'number', default: 204, description: 'Response status code (200 or 204)' },
29
+ },
30
+ flags: {
31
+ quiet: { description: 'Disable logging', default: false }
32
+ },
33
+ examples: [
34
+ { cmd: 'rek serve webhook', desc: 'Start on port 3000' },
35
+ { cmd: 'rek serve webhook status=200', desc: 'Return 200 OK' }
36
+ ]
37
+ };
38
+ const websocketSchema = {
39
+ name: 'websocket',
40
+ description: 'Start a mock WebSocket server',
41
+ params: {
42
+ port: { type: 'number', default: 8080, description: 'Port to listen on' },
43
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
44
+ delay: { type: 'number', default: 0, description: 'Add delay to responses in ms' },
45
+ },
46
+ flags: {
47
+ echo: { description: 'Echo messages back', default: true },
48
+ noecho: { description: 'Disable echo mode' }
49
+ },
50
+ examples: [
51
+ { cmd: 'rek serve websocket', desc: 'Start on port 8080' },
52
+ { cmd: 'rek serve ws noecho', desc: 'Disable echo' }
53
+ ]
54
+ };
55
+ const sseSchema = {
56
+ name: 'sse',
57
+ description: 'Start a mock SSE (Server-Sent Events) server',
58
+ params: {
59
+ port: { type: 'number', default: 8081, description: 'Port to listen on' },
60
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
61
+ path: { type: 'string', default: '/events', description: 'SSE endpoint path' },
62
+ heartbeat: { type: 'number', default: 0, description: 'Send heartbeat every N ms (0 = disabled)' },
63
+ },
64
+ examples: [
65
+ { cmd: 'rek serve sse', desc: 'Start on port 8081' },
66
+ { cmd: 'rek serve sse heartbeat=5000', desc: 'Heartbeat every 5s' }
67
+ ]
68
+ };
69
+ const hlsSchema = {
70
+ name: 'hls',
71
+ description: 'Start a mock HLS streaming server',
72
+ params: {
73
+ port: { type: 'number', default: 8082, description: 'Port to listen on' },
74
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
75
+ mode: { type: 'string', default: 'vod', choices: ['vod', 'live', 'event'], description: 'Stream mode' },
76
+ segments: { type: 'number', default: 10, description: 'Number of segments' },
77
+ duration: { type: 'number', default: 6, description: 'Segment duration in seconds' },
78
+ qualities: { type: 'string', default: '720p,480p,360p', description: 'Comma-separated quality variants' },
79
+ },
80
+ examples: [
81
+ { cmd: 'rek serve hls', desc: 'Start VOD server' },
82
+ { cmd: 'rek serve hls mode=live', desc: 'Start live stream' }
83
+ ]
84
+ };
85
+ const udpSchema = {
86
+ name: 'udp',
87
+ description: 'Start a mock UDP server',
88
+ params: {
89
+ port: { type: 'number', default: 9000, description: 'Port to listen on' },
90
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
91
+ },
92
+ flags: {
93
+ echo: { description: 'Echo messages back', default: true },
94
+ noecho: { description: 'Disable echo mode' }
95
+ },
96
+ examples: [
97
+ { cmd: 'rek serve udp', desc: 'Start on port 9000' }
98
+ ]
99
+ };
100
+ const dnsSchema = {
101
+ name: 'dns',
102
+ description: 'Start a mock DNS server',
103
+ params: {
104
+ port: { type: 'number', default: 5353, description: 'Port to listen on' },
105
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
106
+ delay: { type: 'number', default: 0, description: 'Add delay to responses in ms' },
107
+ },
108
+ examples: [
109
+ { cmd: 'rek serve dns', desc: 'Start on port 5353' }
110
+ ]
111
+ };
112
+ const whoisSchema = {
113
+ name: 'whois',
114
+ description: 'Start a mock WHOIS server',
115
+ params: {
116
+ port: { type: 'number', default: 4343, description: 'Port to listen on' },
117
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
118
+ delay: { type: 'number', default: 0, description: 'Add delay to responses in ms' },
119
+ },
120
+ examples: [
121
+ { cmd: 'rek serve whois', desc: 'Start on port 4343' }
122
+ ]
123
+ };
124
+ const telnetSchema = {
125
+ name: 'telnet',
126
+ description: 'Start a mock Telnet server',
127
+ params: {
128
+ port: { type: 'number', default: 2323, description: 'Port to listen on' },
129
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
130
+ delay: { type: 'number', default: 0, description: 'Add delay to responses in ms' },
131
+ },
132
+ flags: {
133
+ echo: { description: 'Echo input back', default: true },
134
+ noecho: { description: 'Disable echo mode' }
135
+ },
136
+ examples: [
137
+ { cmd: 'rek serve telnet', desc: 'Start on port 2323' }
138
+ ]
139
+ };
140
+ const ftpSchema = {
141
+ name: 'ftp',
142
+ description: 'Start a mock FTP server',
143
+ params: {
144
+ port: { type: 'number', default: 2121, description: 'Port to listen on' },
145
+ host: { type: 'string', default: '127.0.0.1', description: 'Host to bind to' },
146
+ username: { type: 'string', default: 'user', description: 'Username for auth' },
147
+ password: { type: 'string', default: 'pass', description: 'Password for auth' },
148
+ delay: { type: 'number', default: 0, description: 'Add delay to responses' },
149
+ },
150
+ flags: {
151
+ anonymous: { description: 'Allow anonymous login', default: true },
152
+ noanonymous: { description: 'Disable anonymous login' }
153
+ },
154
+ examples: [
155
+ { cmd: 'rek serve ftp', desc: 'Start on port 2121' }
156
+ ]
157
+ };
158
+ export function registerServeCommand(program) {
159
+ const serve = program.command('serve').description('Start mock servers for testing protocols');
160
+ serve.command('http')
161
+ .description(httpSchema.description)
162
+ .argument('[args...]', 'Options: port=3000 host=127.0.0.1 echo delay=0 cors')
163
+ .addHelpText('after', generateHelp(httpSchema))
164
+ .action(async (rawArgs) => {
165
+ const { data, options } = RekArgs.parse(rawArgs, httpSchema);
166
+ const { MockHttpServer } = await import('../../testing/mock-http-server.js');
167
+ const cors = options.nocors ? false : (options.cors || data.cors);
168
+ const useCors = options.nocors ? false : true;
169
+ const server = await MockHttpServer.create({
170
+ port: data.port,
171
+ host: data.host,
172
+ delay: data.delay,
173
+ cors: useCors,
174
+ });
175
+ if (options.echo) {
176
+ server.any('/*', (req) => ({
177
+ status: 200,
178
+ body: { method: req.method, path: req.path, query: req.query, headers: req.headers, body: req.body },
179
+ }));
180
+ }
181
+ console.log(colors.green(`
182
+ ┌─────────────────────────────────────────────┐
183
+ │ ${colors.bold('Recker Mock HTTP Server')} │
184
+ ├─────────────────────────────────────────────┤
185
+ │ URL: ${colors.cyan(server.url.padEnd(37))}│
186
+ │ Mode: ${colors.yellow((options.echo ? 'Echo' : 'Default').padEnd(36))}│
187
+ │ Delay: ${colors.gray((data.delay + 'ms').padEnd(35))}
188
+ ├─────────────────────────────────────────────┤
189
+ │ Press ${colors.bold('Ctrl+C')} to stop │
190
+ └─────────────────────────────────────────────┘`));
191
+ server.on('request', (req) => {
192
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(req.method.padEnd(7)) + req.path);
193
+ });
194
+ process.on('SIGINT', async () => {
195
+ console.log(colors.yellow('\nShutting down...'));
196
+ await server.stop();
197
+ process.exit(0);
198
+ });
199
+ });
200
+ serve.command('webhook').alias('wh')
201
+ .description(webhookSchema.description)
202
+ .argument('[args...]', 'Options: port=3000 host=127.0.0.1 status=204 quiet')
203
+ .addHelpText('after', generateHelp(webhookSchema))
204
+ .action(async (rawArgs) => {
205
+ const { data, options } = RekArgs.parse(rawArgs, webhookSchema);
206
+ const { createWebhookServer } = await import('../../testing/mock-http-server.js');
207
+ if (data.status !== 200 && data.status !== 204) {
208
+ console.error(colors.red('Status must be 200 or 204'));
209
+ process.exit(1);
210
+ }
211
+ const server = await createWebhookServer({
212
+ port: data.port,
213
+ host: data.host,
214
+ status: data.status,
215
+ log: !options.quiet,
216
+ });
217
+ console.log(colors.green(`
218
+ ┌─────────────────────────────────────────────┐
219
+ │ ${colors.bold('Recker Webhook Receiver')} │
220
+ ├─────────────────────────────────────────────┤
221
+ │ URL: ${colors.cyan(server.url.padEnd(37))}│
222
+ │ Status: ${colors.yellow(String(data.status).padEnd(34))}│
223
+ ├─────────────────────────────────────────────┤
224
+ │ ${colors.cyan('*')} ${colors.cyan('/')} ${colors.gray('Webhook without ID')} │
225
+ │ ${colors.cyan('*')} ${colors.cyan('/:id')} ${colors.gray('Webhook with custom ID')} │
226
+ ├─────────────────────────────────────────────┤
227
+ │ Press ${colors.bold('Ctrl+C')} to stop │
228
+ └─────────────────────────────────────────────┘`));
229
+ process.on('SIGINT', async () => {
230
+ console.log(colors.yellow('\nShutting down...'));
231
+ console.log(colors.gray(`Total webhooks received: ${server.webhooks.length}`));
232
+ await server.stop();
233
+ process.exit(0);
234
+ });
235
+ });
236
+ serve.command('websocket').alias('ws')
237
+ .description(websocketSchema.description)
238
+ .argument('[args...]', 'Options: port=8080 host=127.0.0.1 echo noecho delay=0')
239
+ .addHelpText('after', generateHelp(websocketSchema))
240
+ .action(async (rawArgs) => {
241
+ const { data, options } = RekArgs.parse(rawArgs, websocketSchema);
242
+ const { MockWebSocketServer } = await import('../../testing/mock-websocket-server.js');
243
+ const echo = options.noecho ? false : (options.echo !== undefined ? Boolean(options.echo) : true);
244
+ const server = await MockWebSocketServer.create({
245
+ port: data.port,
246
+ host: data.host,
247
+ echo,
248
+ delay: data.delay,
249
+ });
250
+ console.log(colors.green(`
251
+ ┌─────────────────────────────────────────────┐
252
+ │ ${colors.bold('Recker Mock WebSocket Server')} │
253
+ ├─────────────────────────────────────────────┤
254
+ │ URL: ${colors.cyan(server.url.padEnd(37))}│
255
+ │ Echo: ${colors.yellow((echo ? 'Enabled' : 'Disabled').padEnd(36))}│
256
+ │ Delay: ${colors.gray((data.delay + 'ms').padEnd(35))}
257
+ ├─────────────────────────────────────────────┤
258
+ │ Press ${colors.bold('Ctrl+C')} to stop │
259
+ └─────────────────────────────────────────────┘`));
260
+ server.on('connection', (client) => console.log(colors.green(`+ Connected: ${client.id}`)));
261
+ server.on('message', (msg, client) => {
262
+ const d = msg.data.toString();
263
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(client.id) + ` ${d.slice(0, 50)}${d.length > 50 ? '...' : ''}`);
264
+ });
265
+ server.on('disconnect', (client) => console.log(colors.red(`- Disconnected: ${client.id}`)));
266
+ process.on('SIGINT', async () => {
267
+ console.log(colors.yellow('\nShutting down...'));
268
+ await server.stop();
269
+ process.exit(0);
270
+ });
271
+ });
272
+ serve.command('sse')
273
+ .description(sseSchema.description)
274
+ .argument('[args...]', 'Options')
275
+ .addHelpText('after', generateHelp(sseSchema))
276
+ .action(async (rawArgs) => {
277
+ const { data } = RekArgs.parse(rawArgs, sseSchema);
278
+ const { MockSSEServer } = await import('../../testing/mock-sse-server.js');
279
+ const readline = await import('node:readline');
280
+ const server = await MockSSEServer.create({
281
+ port: data.port,
282
+ host: data.host,
283
+ path: data.path,
284
+ });
285
+ if (data.heartbeat > 0)
286
+ server.startPeriodicEvents('heartbeat', data.heartbeat);
287
+ console.log(colors.green(`
288
+ ┌─────────────────────────────────────────────┐
289
+ │ ${colors.bold('Recker Mock SSE Server')} │
290
+ ├─────────────────────────────────────────────┤
291
+ │ URL: ${colors.cyan(server.url.padEnd(37))}│
292
+ │ Heartbeat: ${colors.yellow((data.heartbeat === 0 ? 'Disabled' : data.heartbeat + 'ms').padEnd(31))}
293
+ ├─────────────────────────────────────────────┤
294
+ │ Type message + Enter to broadcast │
295
+ │ Press ${colors.bold('Ctrl+C')} to stop │
296
+ └─────────────────────────────────────────────┘`));
297
+ server.on('connection', (client) => console.log(colors.green(`+ Connected: ${client.id}`)));
298
+ server.on('disconnect', (client) => console.log(colors.red(`- Disconnected: ${client.id}`)));
299
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
300
+ rl.on('line', (line) => {
301
+ if (line.trim()) {
302
+ const sent = server.sendData(line.trim());
303
+ console.log(colors.gray(`Broadcast to ${sent} client(s): ${line.trim()}`));
304
+ }
305
+ });
306
+ process.on('SIGINT', async () => {
307
+ console.log(colors.yellow('\nShutting down...'));
308
+ rl.close();
309
+ await server.stop();
310
+ process.exit(0);
311
+ });
312
+ });
313
+ serve.command('hls')
314
+ .description(hlsSchema.description)
315
+ .argument('[args...]', 'Options')
316
+ .addHelpText('after', generateHelp(hlsSchema))
317
+ .action(async (rawArgs) => {
318
+ const { data } = RekArgs.parse(rawArgs, hlsSchema);
319
+ const { MockHlsServer } = await import('../../testing/mock-hls-server.js');
320
+ const http = await import('node:http');
321
+ const qualities = data.qualities.split(',').map(q => q.trim());
322
+ const variants = qualities.map((name, i) => ({
323
+ name,
324
+ bandwidth: [5000000, 2500000, 1400000][i] || 500000,
325
+ resolution: ['1920x1080', '1280x720', '854x480'][i] || '640x360',
326
+ }));
327
+ const baseUrl = `http://${data.host}:${data.port}`;
328
+ const hlsServer = await MockHlsServer.create({
329
+ baseUrl,
330
+ mode: data.mode,
331
+ segmentCount: data.segments,
332
+ segmentDuration: data.duration,
333
+ multiQuality: variants.length > 1,
334
+ variants: variants.length > 1 ? variants : undefined,
335
+ });
336
+ const httpServer = http.createServer(async (req, res) => {
337
+ const url = `${baseUrl}${req.url}`;
338
+ try {
339
+ const response = await hlsServer.transport.dispatch({ url, method: req.method || 'GET' });
340
+ res.statusCode = response.status;
341
+ response.headers.forEach((value, key) => res.setHeader(key, value));
342
+ const body = await response.arrayBuffer();
343
+ res.end(Buffer.from(body));
344
+ }
345
+ catch {
346
+ res.statusCode = 404;
347
+ res.end('Not Found');
348
+ }
349
+ });
350
+ httpServer.listen(data.port, data.host, () => {
351
+ console.log(colors.green(`
352
+ ┌─────────────────────────────────────────────┐
353
+ │ ${colors.bold('Recker Mock HLS Server')} │
354
+ ├─────────────────────────────────────────────┤
355
+ │ Master: ${colors.cyan((hlsServer.manifestUrl).padEnd(34))}│
356
+ │ Mode: ${colors.yellow(data.mode.padEnd(36))}│
357
+ │ Qualities: ${colors.cyan(qualities.join(', ').padEnd(31))}
358
+ ├─────────────────────────────────────────────┤
359
+ │ Press ${colors.bold('Ctrl+C')} to stop │
360
+ └─────────────────────────────────────────────┘`));
361
+ });
362
+ process.on('SIGINT', async () => {
363
+ console.log(colors.yellow('\nShutting down...'));
364
+ httpServer.close();
365
+ await hlsServer.stop();
366
+ process.exit(0);
367
+ });
368
+ });
369
+ serve.command('udp')
370
+ .description(udpSchema.description)
371
+ .argument('[args...]', 'Options')
372
+ .addHelpText('after', generateHelp(udpSchema))
373
+ .action(async (rawArgs) => {
374
+ const { data, options } = RekArgs.parse(rawArgs, udpSchema);
375
+ const { MockUDPServer } = await import('../../testing/mock-udp-server.js');
376
+ const echo = options.noecho ? false : (options.echo !== undefined ? Boolean(options.echo) : true);
377
+ const server = new MockUDPServer({
378
+ port: data.port,
379
+ host: data.host,
380
+ echo,
381
+ });
382
+ await server.start();
383
+ console.log(colors.green(`
384
+ ┌─────────────────────────────────────────────┐
385
+ │ ${colors.bold('Recker Mock UDP Server')} │
386
+ ├─────────────────────────────────────────────┤
387
+ │ Address: ${colors.cyan(`${data.host}:${data.port}`.padEnd(33))}
388
+ │ Echo: ${colors.yellow((echo ? 'Enabled' : 'Disabled').padEnd(36))}
389
+ ├─────────────────────────────────────────────┤
390
+ │ Press ${colors.bold('Ctrl+C')} to stop │
391
+ └─────────────────────────────────────────────┘`));
392
+ server.on('message', (msg) => {
393
+ const d = msg.data.toString();
394
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(`${msg.rinfo.address}:${msg.rinfo.port}`) + ` ${d.slice(0, 50)}${d.length > 50 ? '...' : ''}`);
395
+ });
396
+ process.on('SIGINT', async () => {
397
+ console.log(colors.yellow('\nShutting down...'));
398
+ await server.stop();
399
+ process.exit(0);
400
+ });
401
+ });
402
+ serve.command('dns')
403
+ .description(dnsSchema.description)
404
+ .argument('[args...]', 'Options')
405
+ .addHelpText('after', generateHelp(dnsSchema))
406
+ .action(async (rawArgs) => {
407
+ const { data } = RekArgs.parse(rawArgs, dnsSchema);
408
+ const { MockDnsServer } = await import('../../testing/mock-dns-server.js');
409
+ const server = await MockDnsServer.create({
410
+ port: data.port,
411
+ host: data.host,
412
+ delay: data.delay,
413
+ });
414
+ console.log(colors.green(`
415
+ ┌─────────────────────────────────────────────┐
416
+ │ ${colors.bold('Recker Mock DNS Server')} │
417
+ ├─────────────────────────────────────────────┤
418
+ │ Address: ${colors.cyan(`${data.host}:${data.port}`.padEnd(33))}
419
+ │ Protocol: ${colors.yellow('UDP'.padEnd(32))}
420
+ ├─────────────────────────────────────────────┤
421
+ │ Test: dig @${data.host} -p ${data.port} example.com │
422
+ │ Press ${colors.bold('Ctrl+C')} to stop │
423
+ └─────────────────────────────────────────────┘`));
424
+ server.on('query', (query) => {
425
+ console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(query.type.padEnd(6)) + ` ${query.domain}`);
426
+ });
427
+ process.on('SIGINT', async () => {
428
+ console.log(colors.yellow('\nShutting down...'));
429
+ await server.stop();
430
+ process.exit(0);
431
+ });
432
+ });
433
+ serve.command('whois')
434
+ .description(whoisSchema.description)
435
+ .argument('[args...]', 'Options')
436
+ .addHelpText('after', generateHelp(whoisSchema))
437
+ .action(async (rawArgs) => {
438
+ const { data } = RekArgs.parse(rawArgs, whoisSchema);
439
+ const { MockWhoisServer } = await import('../../testing/mock-whois-server.js');
440
+ const server = await MockWhoisServer.create({
441
+ port: data.port,
442
+ host: data.host,
443
+ delay: data.delay,
444
+ });
445
+ console.log(colors.green(`
446
+ ┌─────────────────────────────────────────────┐
447
+ │ ${colors.bold('Recker Mock WHOIS Server')} │
448
+ ├─────────────────────────────────────────────┤
449
+ │ Address: ${colors.cyan(`${data.host}:${data.port}`.padEnd(33))}
450
+ │ Protocol: ${colors.yellow('TCP'.padEnd(32))}
451
+ ├─────────────────────────────────────────────┤
452
+ │ Test: whois -h ${data.host} -p ${data.port} example.com │
453
+ │ Press ${colors.bold('Ctrl+C')} to stop │
454
+ └─────────────────────────────────────────────┘`));
455
+ server.on('query', (query) => console.log(colors.gray(`${new Date().toISOString()} `) + `Query: ${colors.cyan(query)}`));
456
+ process.on('SIGINT', async () => {
457
+ console.log(colors.yellow('\nShutting down...'));
458
+ await server.stop();
459
+ process.exit(0);
460
+ });
461
+ });
462
+ serve.command('telnet')
463
+ .description(telnetSchema.description)
464
+ .argument('[args...]', 'Options')
465
+ .addHelpText('after', generateHelp(telnetSchema))
466
+ .action(async (rawArgs) => {
467
+ const { data, options } = RekArgs.parse(rawArgs, telnetSchema);
468
+ const { MockTelnetServer } = await import('../../testing/mock-telnet-server.js');
469
+ const echo = options.noecho ? false : (options.echo !== undefined ? Boolean(options.echo) : true);
470
+ const server = await MockTelnetServer.create({
471
+ port: data.port,
472
+ host: data.host,
473
+ echo,
474
+ delay: data.delay,
475
+ });
476
+ console.log(colors.green(`
477
+ ┌─────────────────────────────────────────────┐
478
+ │ ${colors.bold('Recker Mock Telnet Server')} │
479
+ ├─────────────────────────────────────────────┤
480
+ │ Address: ${colors.cyan(`${data.host}:${data.port}`.padEnd(33))}
481
+ │ Echo: ${colors.yellow((echo ? 'Enabled' : 'Disabled').padEnd(36))}
482
+ ├─────────────────────────────────────────────┤
483
+ │ Connect: telnet ${data.host} ${data.port} │
484
+ │ Press ${colors.bold('Ctrl+C')} to stop │
485
+ └─────────────────────────────────────────────┘`));
486
+ server.on('connect', (s) => console.log(colors.gray(`${new Date().toISOString()} `) + colors.green('+ Connected: ') + colors.cyan(s.id)));
487
+ server.on('disconnect', (s) => console.log(colors.gray(`${new Date().toISOString()} `) + colors.red('- Disconnected: ') + colors.cyan(s.id)));
488
+ server.on('command', (cmd, s) => console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(s.id) + ` $ ${cmd}`));
489
+ process.on('SIGINT', async () => {
490
+ console.log(colors.yellow('\nShutting down...'));
491
+ await server.stop();
492
+ process.exit(0);
493
+ });
494
+ });
495
+ serve.command('ftp')
496
+ .description(ftpSchema.description)
497
+ .argument('[args...]', 'Options')
498
+ .addHelpText('after', generateHelp(ftpSchema))
499
+ .action(async (rawArgs) => {
500
+ const { data, options } = RekArgs.parse(rawArgs, ftpSchema);
501
+ const { MockFtpServer } = await import('../../testing/mock-ftp-server.js');
502
+ const anonymous = options.noanonymous ? false : (options.anonymous !== undefined ? Boolean(options.anonymous) : true);
503
+ const server = await MockFtpServer.create({
504
+ port: data.port,
505
+ host: data.host,
506
+ username: data.username,
507
+ password: data.password,
508
+ anonymous,
509
+ delay: data.delay,
510
+ });
511
+ console.log(colors.green(`
512
+ ┌─────────────────────────────────────────────┐
513
+ │ ${colors.bold('Recker Mock FTP Server')} │
514
+ ├─────────────────────────────────────────────┤
515
+ │ Address: ${colors.cyan(`${data.host}:${data.port}`.padEnd(33))}
516
+ │ Anonymous: ${colors.yellow((anonymous ? 'Allowed' : 'Disabled').padEnd(31))}
517
+ │ User: ${colors.cyan(data.username.padEnd(36))}
518
+ ├─────────────────────────────────────────────┤
519
+ │ Connect: ftp ${data.host} ${data.port} │
520
+ │ Press ${colors.bold('Ctrl+C')} to stop │
521
+ └─────────────────────────────────────────────┘`));
522
+ server.on('connect', (s) => console.log(colors.gray(`${new Date().toISOString()} `) + colors.green('+ Connected: ') + colors.cyan(s.id)));
523
+ server.on('disconnect', (s) => console.log(colors.gray(`${new Date().toISOString()} `) + colors.red('- Disconnected: ') + colors.cyan(s.id)));
524
+ server.on('command', (cmd, _a, s) => console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(s.id) + ` ${cmd}`));
525
+ process.on('SIGINT', async () => {
526
+ console.log(colors.yellow('\nShutting down...'));
527
+ await server.stop();
528
+ process.exit(0);
529
+ });
530
+ });
531
+ }
@@ -0,0 +1,3 @@
1
+ import { RekCommand as Command } from '../router.js';
2
+ export declare function runSpider(rawArgs: string[], defaultUrl?: string): Promise<void>;
3
+ export declare function registerSpiderCommand(program: Command): void;