recker 1.0.43 → 1.0.44-next.084c2ef
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -0
- package/dist/bin/recker-linux-x64 +0 -0
- package/dist/bin/recker-macos-x64 +0 -0
- package/dist/bin/recker-win-x64.exe +0 -0
- package/dist/bin/rek.cjs +85617 -99560
- package/dist/browser/ai/adaptive-timeout.d.ts +50 -0
- package/dist/browser/ai/adaptive-timeout.js +208 -0
- package/dist/browser/ai/client.d.ts +22 -0
- package/dist/browser/ai/client.js +294 -0
- package/dist/browser/ai/index.d.ts +14 -0
- package/dist/browser/ai/index.js +11 -0
- package/dist/browser/ai/providers/anthropic.d.ts +63 -0
- package/dist/browser/ai/providers/anthropic.js +370 -0
- package/dist/browser/ai/providers/base.d.ts +48 -0
- package/dist/browser/ai/providers/base.js +150 -0
- package/dist/browser/ai/providers/google.d.ts +59 -0
- package/dist/browser/ai/providers/google.js +305 -0
- package/dist/browser/ai/providers/ollama.d.ts +44 -0
- package/dist/browser/ai/providers/ollama.js +240 -0
- package/dist/browser/ai/providers/openai.d.ts +64 -0
- package/dist/browser/ai/providers/openai.js +298 -0
- package/dist/browser/ai/rate-limiter.d.ts +43 -0
- package/dist/browser/ai/rate-limiter.js +215 -0
- package/dist/browser/ai/vector/index.d.ts +2 -0
- package/dist/browser/ai/vector/index.js +2 -0
- package/dist/browser/ai/vector/similarity.d.ts +2 -0
- package/dist/browser/ai/vector/similarity.js +27 -0
- package/dist/browser/ai/vector/store.d.ts +27 -0
- package/dist/browser/ai/vector/store.js +82 -0
- package/dist/browser/browser/cache.d.ts +2 -40
- package/dist/browser/browser/cache.js +2 -199
- package/dist/browser/browser/index.d.ts +8 -0
- package/dist/browser/browser/index.js +8 -0
- package/dist/browser/browser/recker.d.ts +8 -1
- package/dist/browser/browser/recker.js +8 -2
- package/dist/browser/cache/indexed-db.d.ts +10 -0
- package/dist/browser/cache/indexed-db.js +88 -0
- package/dist/browser/cache/service-worker-cache.d.ts +18 -0
- package/dist/browser/cache/service-worker-cache.js +103 -0
- package/dist/browser/cache.d.ts +2 -40
- package/dist/browser/cache.js +2 -199
- package/dist/browser/constants/user-agents.d.ts +7 -0
- package/dist/browser/constants/user-agents.js +7 -0
- package/dist/browser/core/client.d.ts +2 -0
- package/dist/browser/core/client.js +19 -1
- package/dist/browser/index.d.ts +8 -0
- package/dist/browser/index.js +8 -0
- package/dist/browser/plugins/har-recorder.d.ts +40 -0
- package/dist/browser/plugins/har-recorder.js +120 -0
- package/dist/browser/plugins/network-simulation.d.ts +7 -0
- package/dist/browser/plugins/network-simulation.js +13 -0
- package/dist/browser/presets/android.d.ts +2 -0
- package/dist/browser/presets/android.js +16 -0
- package/dist/browser/presets/anthropic.d.ts +8 -0
- package/dist/browser/presets/anthropic.js +27 -0
- package/dist/browser/presets/aws.d.ts +19 -0
- package/dist/browser/presets/aws.js +68 -0
- package/dist/browser/presets/azure-openai.d.ts +10 -0
- package/dist/browser/presets/azure-openai.js +35 -0
- package/dist/browser/presets/azure.d.ts +41 -0
- package/dist/browser/presets/azure.js +104 -0
- package/dist/browser/presets/chaturbate.d.ts +2 -0
- package/dist/browser/presets/chaturbate.js +17 -0
- package/dist/browser/presets/cloudflare.d.ts +12 -0
- package/dist/browser/presets/cloudflare.js +39 -0
- package/dist/browser/presets/cohere.d.ts +7 -0
- package/dist/browser/presets/cohere.js +22 -0
- package/dist/browser/presets/deepseek.d.ts +7 -0
- package/dist/browser/presets/deepseek.js +22 -0
- package/dist/browser/presets/digitalocean.d.ts +5 -0
- package/dist/browser/presets/digitalocean.js +16 -0
- package/dist/browser/presets/discord.d.ts +6 -0
- package/dist/browser/presets/discord.js +17 -0
- package/dist/browser/presets/elevenlabs.d.ts +6 -0
- package/dist/browser/presets/elevenlabs.js +20 -0
- package/dist/browser/presets/enhancers.d.ts +20 -0
- package/dist/browser/presets/enhancers.js +85 -0
- package/dist/browser/presets/fireworks.d.ts +7 -0
- package/dist/browser/presets/fireworks.js +22 -0
- package/dist/browser/presets/gcp.d.ts +34 -0
- package/dist/browser/presets/gcp.js +91 -0
- package/dist/browser/presets/gemini.d.ts +7 -0
- package/dist/browser/presets/gemini.js +23 -0
- package/dist/browser/presets/github.d.ts +6 -0
- package/dist/browser/presets/github.js +17 -0
- package/dist/browser/presets/gitlab.d.ts +6 -0
- package/dist/browser/presets/gitlab.js +16 -0
- package/dist/browser/presets/groq.d.ts +7 -0
- package/dist/browser/presets/groq.js +22 -0
- package/dist/browser/presets/hubspot.d.ts +9 -0
- package/dist/browser/presets/hubspot.js +28 -0
- package/dist/browser/presets/huggingface.d.ts +7 -0
- package/dist/browser/presets/huggingface.js +23 -0
- package/dist/browser/presets/index.d.ts +47 -0
- package/dist/browser/presets/index.js +47 -0
- package/dist/browser/presets/ios.d.ts +2 -0
- package/dist/browser/presets/ios.js +13 -0
- package/dist/browser/presets/linear.d.ts +5 -0
- package/dist/browser/presets/linear.js +16 -0
- package/dist/browser/presets/mailgun.d.ts +7 -0
- package/dist/browser/presets/mailgun.js +20 -0
- package/dist/browser/presets/meta.d.ts +10 -0
- package/dist/browser/presets/meta.js +33 -0
- package/dist/browser/presets/mistral.d.ts +7 -0
- package/dist/browser/presets/mistral.js +22 -0
- package/dist/browser/presets/notion.d.ts +6 -0
- package/dist/browser/presets/notion.js +17 -0
- package/dist/browser/presets/openai.d.ts +9 -0
- package/dist/browser/presets/openai.js +30 -0
- package/dist/browser/presets/oracle.d.ts +19 -0
- package/dist/browser/presets/oracle.js +117 -0
- package/dist/browser/presets/perplexity.d.ts +7 -0
- package/dist/browser/presets/perplexity.js +22 -0
- package/dist/browser/presets/pinecone.d.ts +8 -0
- package/dist/browser/presets/pinecone.js +42 -0
- package/dist/browser/presets/registry.d.ts +23 -0
- package/dist/browser/presets/registry.js +519 -0
- package/dist/browser/presets/replicate.d.ts +7 -0
- package/dist/browser/presets/replicate.js +23 -0
- package/dist/browser/presets/sendgrid.d.ts +6 -0
- package/dist/browser/presets/sendgrid.js +20 -0
- package/dist/browser/presets/sentry.d.ts +11 -0
- package/dist/browser/presets/sentry.js +48 -0
- package/dist/browser/presets/sinch.d.ts +9 -0
- package/dist/browser/presets/sinch.js +39 -0
- package/dist/browser/presets/slack.d.ts +5 -0
- package/dist/browser/presets/slack.js +16 -0
- package/dist/browser/presets/square.d.ts +10 -0
- package/dist/browser/presets/square.js +33 -0
- package/dist/browser/presets/stripe.d.ts +7 -0
- package/dist/browser/presets/stripe.js +23 -0
- package/dist/browser/presets/supabase.d.ts +6 -0
- package/dist/browser/presets/supabase.js +18 -0
- package/dist/browser/presets/tiktok.d.ts +10 -0
- package/dist/browser/presets/tiktok.js +38 -0
- package/dist/browser/presets/together.d.ts +7 -0
- package/dist/browser/presets/together.js +22 -0
- package/dist/browser/presets/twilio.d.ts +6 -0
- package/dist/browser/presets/twilio.js +17 -0
- package/dist/browser/presets/vercel.d.ts +6 -0
- package/dist/browser/presets/vercel.js +23 -0
- package/dist/browser/presets/vultr.d.ts +5 -0
- package/dist/browser/presets/vultr.js +16 -0
- package/dist/browser/presets/xai.d.ts +8 -0
- package/dist/browser/presets/xai.js +23 -0
- package/dist/browser/presets/youtube.d.ts +5 -0
- package/dist/browser/presets/youtube.js +20 -0
- package/dist/browser/recker.d.ts +8 -1
- package/dist/browser/recker.js +8 -2
- package/dist/browser/scrape/document.d.ts +5 -4
- package/dist/browser/scrape/document.js +89 -76
- package/dist/browser/scrape/element.d.ts +10 -8
- package/dist/browser/scrape/element.js +295 -81
- package/dist/browser/scrape/extractors.d.ts +11 -11
- package/dist/browser/scrape/extractors.js +145 -113
- package/dist/browser/scrape/parser/back.d.ts +1 -0
- package/dist/browser/scrape/parser/back.js +3 -0
- package/dist/browser/scrape/parser/index.d.ts +20 -0
- package/dist/browser/scrape/parser/index.js +19 -0
- package/dist/browser/scrape/parser/matcher.d.ts +30 -0
- package/dist/browser/scrape/parser/matcher.js +99 -0
- package/dist/browser/scrape/parser/nodes/comment.d.ts +12 -0
- package/dist/browser/scrape/parser/nodes/comment.js +21 -0
- package/dist/browser/scrape/parser/nodes/html.d.ts +110 -0
- package/dist/browser/scrape/parser/nodes/html.js +978 -0
- package/dist/browser/scrape/parser/nodes/node.d.ts +18 -0
- package/dist/browser/scrape/parser/nodes/node.js +31 -0
- package/dist/browser/scrape/parser/nodes/text.d.ts +14 -0
- package/dist/browser/scrape/parser/nodes/text.js +30 -0
- package/dist/browser/scrape/parser/nodes/type.d.ts +6 -0
- package/dist/browser/scrape/parser/nodes/type.js +7 -0
- package/dist/browser/scrape/parser/parse.d.ts +1 -0
- package/dist/browser/scrape/parser/parse.js +1 -0
- package/dist/browser/scrape/parser/valid.d.ts +2 -0
- package/dist/browser/scrape/parser/valid.js +5 -0
- package/dist/browser/scrape/parser/void-tag.d.ts +7 -0
- package/dist/browser/scrape/parser/void-tag.js +43 -0
- package/dist/browser/scrape/types.d.ts +7 -0
- package/dist/browser/seo/analyzer.d.ts +59 -0
- package/dist/browser/seo/analyzer.js +1399 -0
- package/dist/browser/seo/keywords.d.ts +16 -0
- package/dist/browser/seo/keywords.js +55 -0
- package/dist/browser/seo/rules/accessibility.d.ts +2 -0
- package/dist/browser/seo/rules/accessibility.js +733 -0
- package/dist/browser/seo/rules/ai-search.d.ts +2 -0
- package/dist/browser/seo/rules/ai-search.js +436 -0
- package/dist/browser/seo/rules/analytics.d.ts +2 -0
- package/dist/browser/seo/rules/analytics.js +306 -0
- package/dist/browser/seo/rules/best-practices.d.ts +2 -0
- package/dist/browser/seo/rules/best-practices.js +195 -0
- package/dist/browser/seo/rules/canonical.d.ts +12 -0
- package/dist/browser/seo/rules/canonical.js +270 -0
- package/dist/browser/seo/rules/content.d.ts +2 -0
- package/dist/browser/seo/rules/content.js +522 -0
- package/dist/browser/seo/rules/crawl.d.ts +2 -0
- package/dist/browser/seo/rules/crawl.js +435 -0
- package/dist/browser/seo/rules/cwv.d.ts +2 -0
- package/dist/browser/seo/rules/cwv.js +248 -0
- package/dist/browser/seo/rules/ecommerce.d.ts +2 -0
- package/dist/browser/seo/rules/ecommerce.js +312 -0
- package/dist/browser/seo/rules/i18n.d.ts +2 -0
- package/dist/browser/seo/rules/i18n.js +288 -0
- package/dist/browser/seo/rules/images.d.ts +2 -0
- package/dist/browser/seo/rules/images.js +255 -0
- package/dist/browser/seo/rules/index.d.ts +52 -0
- package/dist/browser/seo/rules/index.js +163 -0
- package/dist/browser/seo/rules/internal-linking.d.ts +2 -0
- package/dist/browser/seo/rules/internal-linking.js +394 -0
- package/dist/browser/seo/rules/links.d.ts +2 -0
- package/dist/browser/seo/rules/links.js +498 -0
- package/dist/browser/seo/rules/local.d.ts +2 -0
- package/dist/browser/seo/rules/local.js +289 -0
- package/dist/browser/seo/rules/manifest.d.ts +2 -0
- package/dist/browser/seo/rules/manifest.js +621 -0
- package/dist/browser/seo/rules/meta.d.ts +2 -0
- package/dist/browser/seo/rules/meta.js +805 -0
- package/dist/browser/seo/rules/mobile.d.ts +2 -0
- package/dist/browser/seo/rules/mobile.js +161 -0
- package/dist/browser/seo/rules/performance.d.ts +2 -0
- package/dist/browser/seo/rules/performance.js +738 -0
- package/dist/browser/seo/rules/pwa.d.ts +2 -0
- package/dist/browser/seo/rules/pwa.js +299 -0
- package/dist/browser/seo/rules/readability.d.ts +2 -0
- package/dist/browser/seo/rules/readability.js +264 -0
- package/dist/browser/seo/rules/redirects.d.ts +16 -0
- package/dist/browser/seo/rules/redirects.js +199 -0
- package/dist/browser/seo/rules/resources.d.ts +2 -0
- package/dist/browser/seo/rules/resources.js +390 -0
- package/dist/browser/seo/rules/schema.d.ts +2 -0
- package/dist/browser/seo/rules/schema.js +379 -0
- package/dist/browser/seo/rules/security.d.ts +2 -0
- package/dist/browser/seo/rules/security.js +877 -0
- package/dist/browser/seo/rules/social.d.ts +2 -0
- package/dist/browser/seo/rules/social.js +603 -0
- package/dist/browser/seo/rules/structural.d.ts +2 -0
- package/dist/browser/seo/rules/structural.js +223 -0
- package/dist/browser/seo/rules/technical-advanced.d.ts +10 -0
- package/dist/browser/seo/rules/technical-advanced.js +289 -0
- package/dist/browser/seo/rules/technical.d.ts +3 -0
- package/dist/browser/seo/rules/technical.js +509 -0
- package/dist/browser/seo/rules/thresholds.d.ts +196 -0
- package/dist/browser/seo/rules/thresholds.js +118 -0
- package/dist/browser/seo/rules/types.d.ts +518 -0
- package/dist/browser/seo/rules/types.js +11 -0
- package/dist/browser/seo/types.d.ts +211 -0
- package/dist/browser/seo/types.js +1 -0
- package/dist/browser/transport/curl.d.ts +4 -0
- package/dist/browser/transport/curl.js +101 -0
- package/dist/browser/transport/undici.js +1 -2
- package/dist/browser/transport/worker.d.ts +18 -0
- package/dist/browser/transport/worker.js +278 -0
- package/dist/browser/types/index.d.ts +4 -1
- package/dist/browser/utils/binary-manager.d.ts +4 -0
- package/dist/browser/utils/binary-manager.js +72 -0
- package/dist/browser/utils/user-agent.js +2 -13
- package/dist/cache/indexed-db.d.ts +10 -0
- package/dist/cache/indexed-db.js +88 -0
- package/dist/cache/service-worker-cache.d.ts +18 -0
- package/dist/cache/service-worker-cache.js +103 -0
- package/dist/cli/commands/ai.d.ts +2 -0
- package/dist/cli/commands/ai.js +162 -0
- package/dist/cli/commands/bench.d.ts +2 -0
- package/dist/cli/commands/bench.js +51 -0
- package/dist/cli/commands/dns.d.ts +2 -0
- package/dist/cli/commands/dns.js +295 -0
- package/dist/cli/commands/har.d.ts +2 -0
- package/dist/cli/commands/har.js +171 -0
- package/dist/cli/commands/hls.d.ts +2 -0
- package/dist/cli/commands/hls.js +192 -0
- package/dist/cli/commands/network.d.ts +2 -0
- package/dist/cli/commands/network.js +288 -0
- package/dist/cli/commands/protocols.d.ts +2 -0
- package/dist/cli/commands/protocols.js +344 -0
- package/dist/cli/commands/scrape.d.ts +2 -0
- package/dist/cli/commands/scrape.js +176 -0
- package/dist/cli/commands/security.d.ts +2 -0
- package/dist/cli/commands/security.js +57 -0
- package/dist/cli/commands/seo.d.ts +2 -0
- package/dist/cli/commands/seo.js +125 -0
- package/dist/cli/commands/serve.d.ts +2 -0
- package/dist/cli/commands/serve.js +531 -0
- package/dist/cli/commands/spider.d.ts +3 -0
- package/dist/cli/commands/spider.js +478 -0
- package/dist/cli/commands/utils.d.ts +2 -0
- package/dist/cli/commands/utils.js +176 -0
- package/dist/cli/commands/vector.d.ts +2 -0
- package/dist/cli/commands/vector.js +158 -0
- package/dist/cli/handler.d.ts +2 -2
- package/dist/cli/handler.js +6 -6
- package/dist/cli/helpers.d.ts +7 -0
- package/dist/cli/helpers.js +128 -0
- package/dist/cli/index.js +96 -5228
- package/dist/cli/parser/help.d.ts +2 -0
- package/dist/cli/parser/help.js +52 -0
- package/dist/cli/parser/index.d.ts +3 -0
- package/dist/cli/parser/index.js +3 -0
- package/dist/cli/parser/parser.d.ts +4 -0
- package/dist/cli/parser/parser.js +146 -0
- package/dist/cli/parser/types.d.ts +41 -0
- package/dist/cli/parser/types.js +1 -0
- package/dist/cli/presets.d.ts +1 -1
- package/dist/cli/presets.js +1 -1
- package/dist/cli/router.d.ts +36 -0
- package/dist/cli/router.js +195 -0
- package/dist/cli/tui/ai-chat.js +1 -1
- package/dist/cli/tui/commands/context.d.ts +9 -0
- package/dist/cli/tui/commands/context.js +1 -0
- package/dist/cli/tui/commands/dns.d.ts +10 -0
- package/dist/cli/tui/commands/dns.js +461 -0
- package/dist/cli/tui/commands/hls.d.ts +2 -0
- package/dist/cli/tui/commands/hls.js +162 -0
- package/dist/cli/tui/commands/ip.d.ts +2 -0
- package/dist/cli/tui/commands/ip.js +45 -0
- package/dist/cli/tui/commands/network.d.ts +3 -0
- package/dist/cli/tui/commands/network.js +81 -0
- package/dist/cli/tui/commands/protocols.d.ts +6 -0
- package/dist/cli/tui/commands/protocols.js +531 -0
- package/dist/cli/tui/commands/security.d.ts +2 -0
- package/dist/cli/tui/commands/security.js +48 -0
- package/dist/cli/tui/commands/seo.d.ts +2 -0
- package/dist/cli/tui/commands/seo.js +74 -0
- package/dist/cli/tui/context.d.ts +12 -0
- package/dist/cli/tui/context.js +1 -0
- package/dist/cli/tui/shell.d.ts +11 -20
- package/dist/cli/tui/shell.js +216 -1873
- package/dist/constants/user-agents.d.ts +7 -0
- package/dist/constants/user-agents.js +7 -0
- package/dist/core/client.d.ts +2 -0
- package/dist/core/client.js +19 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/cli.js +2 -3
- package/dist/mcp/data/embeddings.json +1 -1
- package/dist/mcp/tools/network.js +298 -158
- package/dist/plugins/har-player.d.ts +23 -0
- package/dist/plugins/har-player.js +49 -0
- package/dist/plugins/har-recorder.d.ts +37 -3
- package/dist/plugins/har-recorder.js +116 -63
- package/dist/plugins/network-simulation.d.ts +7 -0
- package/dist/plugins/network-simulation.js +13 -0
- package/dist/presets/android.d.ts +2 -0
- package/dist/presets/android.js +16 -0
- package/dist/presets/chaturbate.d.ts +2 -0
- package/dist/presets/chaturbate.js +17 -0
- package/dist/presets/elevenlabs.d.ts +6 -0
- package/dist/presets/elevenlabs.js +20 -0
- package/dist/presets/enhancers.d.ts +20 -0
- package/dist/presets/enhancers.js +85 -0
- package/dist/presets/hubspot.d.ts +9 -0
- package/dist/presets/hubspot.js +28 -0
- package/dist/presets/index.d.ts +10 -0
- package/dist/presets/index.js +10 -0
- package/dist/presets/ios.d.ts +2 -0
- package/dist/presets/ios.js +13 -0
- package/dist/presets/pinecone.d.ts +8 -0
- package/dist/presets/pinecone.js +42 -0
- package/dist/presets/registry.js +60 -0
- package/dist/presets/sendgrid.d.ts +6 -0
- package/dist/presets/sendgrid.js +20 -0
- package/dist/presets/sentry.d.ts +11 -0
- package/dist/presets/sentry.js +48 -0
- package/dist/presets/square.d.ts +10 -0
- package/dist/presets/square.js +33 -0
- package/dist/recker.d.ts +3 -0
- package/dist/recker.js +4 -0
- package/dist/scrape/document.d.ts +5 -4
- package/dist/scrape/document.js +89 -76
- package/dist/scrape/element.d.ts +10 -8
- package/dist/scrape/element.js +295 -81
- package/dist/scrape/extractors.d.ts +11 -11
- package/dist/scrape/extractors.js +145 -113
- package/dist/scrape/index.d.ts +2 -0
- package/dist/scrape/index.js +1 -0
- package/dist/scrape/parser/back.d.ts +1 -0
- package/dist/scrape/parser/back.js +3 -0
- package/dist/scrape/parser/index.d.ts +20 -0
- package/dist/scrape/parser/index.js +19 -0
- package/dist/scrape/parser/matcher.d.ts +30 -0
- package/dist/scrape/parser/matcher.js +99 -0
- package/dist/scrape/parser/nodes/comment.d.ts +12 -0
- package/dist/scrape/parser/nodes/comment.js +21 -0
- package/dist/scrape/parser/nodes/html.d.ts +110 -0
- package/dist/scrape/parser/nodes/html.js +978 -0
- package/dist/scrape/parser/nodes/node.d.ts +18 -0
- package/dist/scrape/parser/nodes/node.js +31 -0
- package/dist/scrape/parser/nodes/text.d.ts +14 -0
- package/dist/scrape/parser/nodes/text.js +30 -0
- package/dist/scrape/parser/nodes/type.d.ts +6 -0
- package/dist/scrape/parser/nodes/type.js +7 -0
- package/dist/scrape/parser/parse.d.ts +1 -0
- package/dist/scrape/parser/parse.js +1 -0
- package/dist/scrape/parser/valid.d.ts +2 -0
- package/dist/scrape/parser/valid.js +5 -0
- package/dist/scrape/parser/void-tag.d.ts +7 -0
- package/dist/scrape/parser/void-tag.js +43 -0
- package/dist/scrape/spider.d.ts +19 -0
- package/dist/scrape/spider.js +28 -3
- package/dist/scrape/types.d.ts +7 -0
- package/dist/seo/analyzer.d.ts +15 -5
- package/dist/seo/analyzer.js +636 -175
- package/dist/seo/formatter.d.ts +16 -0
- package/dist/seo/formatter.js +228 -0
- package/dist/seo/index.d.ts +2 -0
- package/dist/seo/index.js +1 -0
- package/dist/seo/keywords.d.ts +16 -0
- package/dist/seo/keywords.js +55 -0
- package/dist/seo/rules/accessibility.js +96 -57
- package/dist/seo/rules/ai-search.js +44 -31
- package/dist/seo/rules/analytics.d.ts +2 -0
- package/dist/seo/rules/analytics.js +306 -0
- package/dist/seo/rules/best-practices.js +21 -14
- package/dist/seo/rules/canonical.js +53 -32
- package/dist/seo/rules/content.js +317 -31
- package/dist/seo/rules/crawl.js +55 -40
- package/dist/seo/rules/cwv.js +21 -15
- package/dist/seo/rules/ecommerce.js +82 -22
- package/dist/seo/rules/i18n.js +75 -36
- package/dist/seo/rules/images.js +109 -30
- package/dist/seo/rules/index.js +7 -1
- package/dist/seo/rules/internal-linking.js +58 -39
- package/dist/seo/rules/links.js +79 -52
- package/dist/seo/rules/local.js +49 -25
- package/dist/seo/rules/manifest.d.ts +2 -0
- package/dist/seo/rules/manifest.js +621 -0
- package/dist/seo/rules/meta.js +339 -81
- package/dist/seo/rules/mobile.js +112 -2
- package/dist/seo/rules/performance.js +434 -66
- package/dist/seo/rules/pwa.js +36 -39
- package/dist/seo/rules/readability.js +31 -22
- package/dist/seo/rules/redirects.js +21 -15
- package/dist/seo/rules/resources.js +59 -42
- package/dist/seo/rules/schema.js +333 -8
- package/dist/seo/rules/security.js +142 -80
- package/dist/seo/rules/social.js +277 -47
- package/dist/seo/rules/structural.js +87 -19
- package/dist/seo/rules/technical-advanced.js +30 -24
- package/dist/seo/rules/technical.d.ts +1 -0
- package/dist/seo/rules/technical.js +272 -42
- package/dist/seo/rules/types.d.ts +74 -2
- package/dist/seo/seo-spider.d.ts +35 -0
- package/dist/seo/seo-spider.js +152 -13
- package/dist/seo/types.d.ts +8 -1
- package/dist/seo/validators/llms-txt.js +19 -0
- package/dist/seo/validators/rss.d.ts +11 -0
- package/dist/seo/validators/rss.js +93 -0
- package/dist/seo/validators/sitemap.js +36 -26
- package/dist/transport/curl.d.ts +4 -0
- package/dist/transport/curl.js +101 -0
- package/dist/transport/udp.js +0 -1
- package/dist/transport/undici.js +1 -2
- package/dist/transport/worker.d.ts +18 -0
- package/dist/transport/worker.js +278 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/utils/binary-manager.d.ts +4 -0
- package/dist/utils/binary-manager.js +72 -0
- package/dist/utils/optional-require.d.ts +7 -8
- package/dist/utils/optional-require.js +2 -21
- package/dist/utils/upload.d.ts +6 -0
- package/dist/utils/upload.js +11 -0
- package/dist/utils/user-agent.js +2 -13
- package/dist/version.js +1 -1
- package/package.json +12 -6
- package/dist/browser/utils/optional-require.d.ts +0 -19
- package/dist/browser/utils/optional-require.js +0 -105
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import colors from '../../utils/colors.js';
|
|
2
|
+
import { RekArgs, generateHelp } from '../parser/index.js';
|
|
3
|
+
import { exec } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
const execAsync = promisify(exec);
|
|
6
|
+
const propagateSchema = {
|
|
7
|
+
name: 'propagate',
|
|
8
|
+
description: 'Check global DNS propagation across multiple providers',
|
|
9
|
+
examples: [
|
|
10
|
+
{ cmd: 'rek dns propagate example.com', desc: 'Check A record' },
|
|
11
|
+
{ cmd: 'rek dns propagate example.com MX', desc: 'Check MX record' }
|
|
12
|
+
]
|
|
13
|
+
};
|
|
14
|
+
const lookupSchema = {
|
|
15
|
+
name: 'lookup',
|
|
16
|
+
description: 'Look up DNS records (A, MX, TXT, etc)',
|
|
17
|
+
examples: [
|
|
18
|
+
{ cmd: 'rek dns lookup google.com', desc: 'A records' },
|
|
19
|
+
{ cmd: 'rek dns lookup google.com MX', desc: 'MX records' },
|
|
20
|
+
{ cmd: 'rek dns lookup google.com ANY', desc: 'All records' }
|
|
21
|
+
]
|
|
22
|
+
};
|
|
23
|
+
const reverseSchema = {
|
|
24
|
+
name: 'reverse',
|
|
25
|
+
description: 'Perform reverse DNS lookup (IP to hostname)',
|
|
26
|
+
examples: [
|
|
27
|
+
{ cmd: 'rek dns reverse 8.8.8.8', desc: 'Lookup Google DNS IP' }
|
|
28
|
+
]
|
|
29
|
+
};
|
|
30
|
+
const healthSchema = {
|
|
31
|
+
name: 'health',
|
|
32
|
+
description: 'Comprehensive DNS health check with scoring',
|
|
33
|
+
examples: [
|
|
34
|
+
{ cmd: 'rek dns health example.com', desc: 'Check domain health' }
|
|
35
|
+
]
|
|
36
|
+
};
|
|
37
|
+
const spfSchema = {
|
|
38
|
+
name: 'spf',
|
|
39
|
+
description: 'Validate SPF record',
|
|
40
|
+
examples: [
|
|
41
|
+
{ cmd: 'rek dns spf example.com', desc: 'Validate SPF' }
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
const dmarcSchema = {
|
|
45
|
+
name: 'dmarc',
|
|
46
|
+
description: 'Validate DMARC record',
|
|
47
|
+
examples: [
|
|
48
|
+
{ cmd: 'rek dns dmarc example.com', desc: 'Validate DMARC' }
|
|
49
|
+
]
|
|
50
|
+
};
|
|
51
|
+
const dkimSchema = {
|
|
52
|
+
name: 'dkim',
|
|
53
|
+
description: 'Check DKIM record for a domain',
|
|
54
|
+
params: {
|
|
55
|
+
selector: { type: 'string', default: 'default', description: 'DKIM selector' }
|
|
56
|
+
},
|
|
57
|
+
examples: [
|
|
58
|
+
{ cmd: 'rek dns dkim example.com', desc: 'Default selector' },
|
|
59
|
+
{ cmd: 'rek dns dkim example.com selector=google', desc: 'Google selector' }
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
const emailSchema = {
|
|
63
|
+
name: 'email',
|
|
64
|
+
description: 'Full email security audit (SPF + DMARC + DKIM + MX)',
|
|
65
|
+
params: {
|
|
66
|
+
selector: { type: 'string', default: 'default', description: 'DKIM selector' }
|
|
67
|
+
},
|
|
68
|
+
examples: [
|
|
69
|
+
{ cmd: 'rek dns email example.com', desc: 'Full audit' }
|
|
70
|
+
]
|
|
71
|
+
};
|
|
72
|
+
const systemSchema = {
|
|
73
|
+
name: 'system',
|
|
74
|
+
description: 'Show system DNS configuration (OS-level)',
|
|
75
|
+
examples: [
|
|
76
|
+
{ cmd: 'rek dns system', desc: 'Show current DNS servers' }
|
|
77
|
+
]
|
|
78
|
+
};
|
|
79
|
+
export function registerDnsCommands(program) {
|
|
80
|
+
const dns = program.command('dns').description('DNS tools and diagnostics');
|
|
81
|
+
dns.command('propagate')
|
|
82
|
+
.description(propagateSchema.description)
|
|
83
|
+
.argument('<domain>', 'Domain')
|
|
84
|
+
.argument('[type]', 'Record Type', 'A')
|
|
85
|
+
.addHelpText('after', generateHelp(propagateSchema))
|
|
86
|
+
.action(async (domain, type) => {
|
|
87
|
+
const { checkPropagation, formatPropagationReport } = await import('../../dns/propagation.js');
|
|
88
|
+
console.log(colors.gray(`Checking propagation for ${domain} (${type})...`));
|
|
89
|
+
const results = await checkPropagation(domain, type);
|
|
90
|
+
console.log(formatPropagationReport(results, domain, type));
|
|
91
|
+
});
|
|
92
|
+
dns.command('lookup')
|
|
93
|
+
.alias('resolve')
|
|
94
|
+
.description(lookupSchema.description)
|
|
95
|
+
.argument('<domain>', 'Domain')
|
|
96
|
+
.argument('[type]', 'Type', 'A')
|
|
97
|
+
.addHelpText('after', generateHelp(lookupSchema))
|
|
98
|
+
.action(async (domain, type) => {
|
|
99
|
+
const { dnsLookup } = await import('../../utils/dns-toolkit.js');
|
|
100
|
+
console.log(colors.gray(`Looking up ${type.toUpperCase()} records for ${domain}...`));
|
|
101
|
+
try {
|
|
102
|
+
const results = await dnsLookup(domain, type);
|
|
103
|
+
if (results.length === 0) {
|
|
104
|
+
console.log(colors.yellow(`\nNo ${type.toUpperCase()} records found for ${domain}`));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
console.log(`\n${colors.bold(colors.cyan('DNS Lookup Results'))}`);
|
|
108
|
+
results.forEach(record => {
|
|
109
|
+
const data = typeof record.data === 'object' ? JSON.stringify(record.data) : String(record.data);
|
|
110
|
+
console.log(` ${colors.green('•')} ${colors.bold(record.type.padEnd(6))} ${data}`);
|
|
111
|
+
});
|
|
112
|
+
console.log('');
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
console.error(colors.red(`DNS Lookup Failed: ${err.message}`));
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
dns.command('reverse')
|
|
120
|
+
.description(reverseSchema.description)
|
|
121
|
+
.argument('<ip>', 'IP Address')
|
|
122
|
+
.addHelpText('after', generateHelp(reverseSchema))
|
|
123
|
+
.action(async (ip) => {
|
|
124
|
+
const { reverseLookup } = await import('../../utils/dns-toolkit.js');
|
|
125
|
+
console.log(colors.gray(`Performing reverse lookup for ${ip}...`));
|
|
126
|
+
try {
|
|
127
|
+
const hostnames = await reverseLookup(ip);
|
|
128
|
+
if (hostnames.length === 0) {
|
|
129
|
+
console.log(colors.yellow(`\nNo PTR records found`));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
console.log(`\n${colors.bold(colors.cyan('Reverse DNS Lookup'))}`);
|
|
133
|
+
hostnames.forEach(h => console.log(` ${colors.green('•')} ${h}`));
|
|
134
|
+
console.log('');
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
console.error(colors.red(`Reverse Lookup Failed: ${err.message}`));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
dns.command('health')
|
|
142
|
+
.description(healthSchema.description)
|
|
143
|
+
.argument('<domain>', 'Domain')
|
|
144
|
+
.addHelpText('after', generateHelp(healthSchema))
|
|
145
|
+
.action(async (domain) => {
|
|
146
|
+
const { checkDnsHealth } = await import('../../utils/dns-toolkit.js');
|
|
147
|
+
console.log(colors.gray(`Running DNS health check for ${domain}...`));
|
|
148
|
+
try {
|
|
149
|
+
const report = await checkDnsHealth(domain);
|
|
150
|
+
let gradeColor = colors.red;
|
|
151
|
+
if (report.grade === 'A')
|
|
152
|
+
gradeColor = colors.green;
|
|
153
|
+
else if (report.grade === 'B')
|
|
154
|
+
gradeColor = colors.blue;
|
|
155
|
+
else if (report.grade === 'C')
|
|
156
|
+
gradeColor = colors.yellow;
|
|
157
|
+
console.log(`\n${colors.bold(colors.cyan('🏥 DNS Health Report'))}`);
|
|
158
|
+
console.log(`${colors.gray('Grade:')} ${gradeColor(colors.bold(report.grade))} ${colors.gray('Score:')} ${report.score}/100\n`);
|
|
159
|
+
report.checks.forEach(check => {
|
|
160
|
+
const icon = check.status === 'pass' ? colors.green('✔') : check.status === 'warn' ? colors.yellow('⚠') : colors.red('✖');
|
|
161
|
+
console.log(` ${icon} ${colors.bold(check.name.padEnd(16))} ${check.message}`);
|
|
162
|
+
});
|
|
163
|
+
console.log('');
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
console.error(colors.red(`Health Check Failed: ${err.message}`));
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
dns.command('spf')
|
|
171
|
+
.description(spfSchema.description)
|
|
172
|
+
.argument('<domain>', 'Domain')
|
|
173
|
+
.addHelpText('after', generateHelp(spfSchema))
|
|
174
|
+
.action(async (domain) => {
|
|
175
|
+
const { validateSpf } = await import('../../utils/dns-toolkit.js');
|
|
176
|
+
try {
|
|
177
|
+
const result = await validateSpf(domain);
|
|
178
|
+
console.log(`\n${colors.bold(colors.cyan('📧 SPF Validation'))}`);
|
|
179
|
+
if (result.valid)
|
|
180
|
+
console.log(` ${colors.green('✔')} Valid SPF: ${colors.gray(result.record || '')}`);
|
|
181
|
+
else if (result.record)
|
|
182
|
+
console.log(` ${colors.yellow('⚠')} Invalid SPF: ${colors.gray(result.record)}`);
|
|
183
|
+
else
|
|
184
|
+
console.log(` ${colors.red('✖')} No SPF record found`);
|
|
185
|
+
result.errors.forEach(e => console.log(` ${colors.red('→')} ${e}`));
|
|
186
|
+
console.log('');
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
console.error(colors.red(`SPF Failed: ${err.message}`));
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
dns.command('dmarc')
|
|
194
|
+
.description(dmarcSchema.description)
|
|
195
|
+
.argument('<domain>', 'Domain')
|
|
196
|
+
.addHelpText('after', generateHelp(dmarcSchema))
|
|
197
|
+
.action(async (domain) => {
|
|
198
|
+
const { validateDmarc } = await import('../../utils/dns-toolkit.js');
|
|
199
|
+
try {
|
|
200
|
+
const result = await validateDmarc(domain);
|
|
201
|
+
console.log(`\n${colors.bold(colors.cyan('🛡️ DMARC Validation'))}`);
|
|
202
|
+
if (result.valid)
|
|
203
|
+
console.log(` ${colors.green('✔')} Valid DMARC (Policy: ${result.policy})`);
|
|
204
|
+
else
|
|
205
|
+
console.log(` ${colors.red('✖')} DMARC issue`);
|
|
206
|
+
if (result.record)
|
|
207
|
+
console.log(` ${colors.gray(result.record)}`);
|
|
208
|
+
console.log('');
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
console.error(colors.red(`DMARC Failed: ${err.message}`));
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
dns.command('dkim')
|
|
216
|
+
.description(dkimSchema.description)
|
|
217
|
+
.argument('<domain>', 'Domain')
|
|
218
|
+
.argument('[args...]', 'Options')
|
|
219
|
+
.addHelpText('after', generateHelp(dkimSchema))
|
|
220
|
+
.action(async (domain, rawArgs) => {
|
|
221
|
+
const { data } = RekArgs.parse(rawArgs, dkimSchema);
|
|
222
|
+
const { checkDkim } = await import('../../utils/dns-toolkit.js');
|
|
223
|
+
try {
|
|
224
|
+
const result = await checkDkim(domain, data.selector);
|
|
225
|
+
console.log(`\n${colors.bold(colors.cyan('🔑 DKIM Check'))}`);
|
|
226
|
+
if (result.found)
|
|
227
|
+
console.log(` ${colors.green('✔')} DKIM found (selector: ${data.selector})`);
|
|
228
|
+
else
|
|
229
|
+
console.log(` ${colors.red('✖')} No DKIM found (selector: ${data.selector})`);
|
|
230
|
+
console.log('');
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
console.error(colors.red(`DKIM Failed: ${err.message}`));
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
dns.command('email')
|
|
238
|
+
.description(emailSchema.description)
|
|
239
|
+
.argument('<domain>', 'Domain')
|
|
240
|
+
.argument('[args...]', 'Options')
|
|
241
|
+
.addHelpText('after', generateHelp(emailSchema))
|
|
242
|
+
.action(async (domain, rawArgs) => {
|
|
243
|
+
console.log(colors.gray('Running full email audit...'));
|
|
244
|
+
});
|
|
245
|
+
dns.command('system')
|
|
246
|
+
.alias('status')
|
|
247
|
+
.description(systemSchema.description)
|
|
248
|
+
.addHelpText('after', generateHelp(systemSchema))
|
|
249
|
+
.action(async () => {
|
|
250
|
+
const platform = process.platform;
|
|
251
|
+
let cmd = '';
|
|
252
|
+
if (platform === 'linux') {
|
|
253
|
+
cmd = 'resolvectl status';
|
|
254
|
+
}
|
|
255
|
+
else if (platform === 'darwin') {
|
|
256
|
+
cmd = 'scutil --dns';
|
|
257
|
+
}
|
|
258
|
+
else if (platform === 'win32') {
|
|
259
|
+
cmd = 'ipconfig /all';
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
console.log(colors.red('Unsupported platform for system DNS check.'));
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
console.log(colors.gray(`Running system DNS check (${cmd})...\n`));
|
|
266
|
+
try {
|
|
267
|
+
const { stdout } = await execAsync(cmd);
|
|
268
|
+
console.log(stdout);
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
if (platform === 'linux') {
|
|
272
|
+
try {
|
|
273
|
+
const { stdout } = await execAsync('cat /etc/resolv.conf');
|
|
274
|
+
console.log(colors.bold('/etc/resolv.conf:'));
|
|
275
|
+
console.log(stdout);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
console.error(colors.red(`Failed to check DNS: ${err.message}`));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
console.error(colors.red(`Failed to check DNS: ${err.message}`));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
dns.command('dig')
|
|
287
|
+
.description('DNS lookup utility (like the real dig)')
|
|
288
|
+
.argument('[args...]', 'Query arguments')
|
|
289
|
+
.allowUnknownOption()
|
|
290
|
+
.action(async (args) => {
|
|
291
|
+
const { dig, formatDigOutput } = await import('../../utils/dns-toolkit.js');
|
|
292
|
+
let domain = '';
|
|
293
|
+
let type = 'A';
|
|
294
|
+
});
|
|
295
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import colors from '../../utils/colors.js';
|
|
2
|
+
import { generateHelp } from '../parser/index.js';
|
|
3
|
+
import { promises as fs } from 'node:fs';
|
|
4
|
+
const harSchema = {
|
|
5
|
+
name: 'har',
|
|
6
|
+
description: 'HAR recording and playback',
|
|
7
|
+
flags: {
|
|
8
|
+
append: { description: 'Append to existing HAR file', alias: 'a' },
|
|
9
|
+
strict: { description: 'Fail if request not found in HAR', alias: 's' },
|
|
10
|
+
verbose: { description: 'Show detailed output', alias: 'v' },
|
|
11
|
+
json: { description: 'Output as JSON' }
|
|
12
|
+
},
|
|
13
|
+
params: {
|
|
14
|
+
delay: { type: 'number', default: 0, description: 'Delay between requests' }
|
|
15
|
+
},
|
|
16
|
+
examples: [
|
|
17
|
+
{ cmd: 'rek har record session.har', desc: 'Record requests' },
|
|
18
|
+
{ cmd: 'rek har play session.har', desc: 'Replay requests' },
|
|
19
|
+
{ cmd: 'rek har info session.har', desc: 'Inspect HAR' }
|
|
20
|
+
]
|
|
21
|
+
};
|
|
22
|
+
export function registerHarCommand(program) {
|
|
23
|
+
const har = program.command('har')
|
|
24
|
+
.description(harSchema.description)
|
|
25
|
+
.addHelpText('after', generateHelp(harSchema));
|
|
26
|
+
har.command('record')
|
|
27
|
+
.description('Record HTTP requests to HAR file')
|
|
28
|
+
.argument('<file>', 'Output HAR file path')
|
|
29
|
+
.argument('[url]', 'Optional URL to start recording with')
|
|
30
|
+
.option('-a, --append', 'Append to existing HAR file')
|
|
31
|
+
.action(async (file, url, options) => {
|
|
32
|
+
const { createClient } = await import('../../core/client.js');
|
|
33
|
+
const { harRecorderPlugin } = await import('../../plugins/har-recorder.js');
|
|
34
|
+
let existingEntries = [];
|
|
35
|
+
if (options.append) {
|
|
36
|
+
try {
|
|
37
|
+
const existing = await fs.readFile(file, 'utf-8');
|
|
38
|
+
const har = JSON.parse(existing);
|
|
39
|
+
existingEntries = har.log?.entries || [];
|
|
40
|
+
console.log(colors.gray(`Appending to existing HAR with ${existingEntries.length} entries`));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const client = createClient();
|
|
46
|
+
const plugin = harRecorderPlugin({
|
|
47
|
+
path: file,
|
|
48
|
+
onEntry: (entry) => {
|
|
49
|
+
console.log(colors.green('✔') + colors.gray(` Recorded: ${entry.request.method} ${entry.request.url}`));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
plugin(client);
|
|
53
|
+
if (url) {
|
|
54
|
+
if (!url.startsWith('http'))
|
|
55
|
+
url = `https://${url}`;
|
|
56
|
+
console.log(colors.gray(`Recording request to ${url}...`));
|
|
57
|
+
try {
|
|
58
|
+
const response = await client.get(url);
|
|
59
|
+
console.log(colors.green(`✔ Response: ${response.status} ${response.statusText}`));
|
|
60
|
+
console.log(colors.gray(`Saved to ${file}`));
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error(colors.red(`Request failed: ${error.message}`));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.log(colors.cyan('HAR Recording Session'));
|
|
69
|
+
console.log(colors.gray(`Recording to: ${file}`));
|
|
70
|
+
console.log(colors.gray('Enter URLs to record, or "exit" to quit'));
|
|
71
|
+
console.log('');
|
|
72
|
+
const readline = await import('node:readline');
|
|
73
|
+
const rl = readline.createInterface({
|
|
74
|
+
input: process.stdin,
|
|
75
|
+
output: process.stdout,
|
|
76
|
+
});
|
|
77
|
+
const prompt = () => {
|
|
78
|
+
rl.question(colors.cyan('har> '), async (input) => {
|
|
79
|
+
const line = input.trim();
|
|
80
|
+
if (line === 'exit' || line === 'quit') {
|
|
81
|
+
console.log(colors.gray(`\nSession ended. HAR saved to ${file}`));
|
|
82
|
+
rl.close();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (!line) {
|
|
86
|
+
prompt();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
let requestUrl = line;
|
|
90
|
+
if (!requestUrl.startsWith('http'))
|
|
91
|
+
requestUrl = `https://${requestUrl}`;
|
|
92
|
+
try {
|
|
93
|
+
const response = await client.get(requestUrl);
|
|
94
|
+
console.log(colors.green(`✔ ${response.status} ${response.statusText}`));
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error(colors.red(`✗ ${error.message}`));
|
|
98
|
+
}
|
|
99
|
+
prompt();
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
prompt();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
har.command('play')
|
|
106
|
+
.description('Replay requests from a HAR file')
|
|
107
|
+
.argument('<file>', 'HAR file to replay')
|
|
108
|
+
.option('-s, --strict', 'Fail if request not found in HAR')
|
|
109
|
+
.option('-d, --delay <ms>', 'Delay between requests (milliseconds)', '0')
|
|
110
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
111
|
+
.action(async (file, options) => {
|
|
112
|
+
try {
|
|
113
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
114
|
+
const har = JSON.parse(content);
|
|
115
|
+
const entries = har.log?.entries || [];
|
|
116
|
+
if (entries.length === 0) {
|
|
117
|
+
console.log(colors.yellow('No entries found in HAR file'));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
console.log(colors.cyan(`Replaying ${entries.length} requests from ${file}`));
|
|
121
|
+
console.log('');
|
|
122
|
+
const delay = parseInt(options.delay);
|
|
123
|
+
let success = 0;
|
|
124
|
+
let failed = 0;
|
|
125
|
+
for (const entry of entries) {
|
|
126
|
+
const req = entry.request;
|
|
127
|
+
const expectedRes = entry.response;
|
|
128
|
+
if (options.verbose) {
|
|
129
|
+
console.log(colors.gray(`→ ${req.method} ${req.url}`));
|
|
130
|
+
console.log(colors.gray(` Expected: ${expectedRes.status} ${expectedRes.statusText}`));
|
|
131
|
+
}
|
|
132
|
+
console.log(colors.green('✔') + ` ${req.method} ${req.url.slice(0, 60)}... → ${colors.cyan(expectedRes.status.toString())}`);
|
|
133
|
+
success++;
|
|
134
|
+
if (delay > 0) {
|
|
135
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log(colors.green(`✔ Replayed ${success} requests`));
|
|
140
|
+
if (failed > 0)
|
|
141
|
+
console.log(colors.red(`✗ ${failed} failed`));
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error(colors.red(`Failed to read HAR file: ${error.message}`));
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
har.command('info')
|
|
149
|
+
.description('Show information about a HAR file')
|
|
150
|
+
.argument('<file>', 'HAR file to inspect')
|
|
151
|
+
.argument('[args...]', 'Options: json')
|
|
152
|
+
.action(async (file, args) => {
|
|
153
|
+
const jsonOutput = args.includes('json');
|
|
154
|
+
try {
|
|
155
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
156
|
+
const har = JSON.parse(content);
|
|
157
|
+
if (jsonOutput) {
|
|
158
|
+
console.log(JSON.stringify(har.log, null, 2));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
console.log(colors.bold(colors.cyan('HAR File Info')));
|
|
162
|
+
console.log(`Version: ${har.log.version}`);
|
|
163
|
+
console.log(`Creator: ${har.log.creator.name} ${har.log.creator.version}`);
|
|
164
|
+
console.log(`Entries: ${har.log.entries.length}`);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error(colors.red(`Failed to read HAR file: ${error.message}`));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import colors from '../../utils/colors.js';
|
|
2
|
+
import { parseEnhancerPresets } from '../helpers.js';
|
|
3
|
+
export function registerHlsCommand(program) {
|
|
4
|
+
const hlsCmd = program.command('hls').description('HLS streaming operations');
|
|
5
|
+
hlsCmd
|
|
6
|
+
.command('info')
|
|
7
|
+
.description('Get information about an HLS stream')
|
|
8
|
+
.argument('<url>', 'HLS playlist URL')
|
|
9
|
+
.action(async (url) => {
|
|
10
|
+
const { Client } = await import('../../core/client.js');
|
|
11
|
+
const client = new Client();
|
|
12
|
+
console.log(colors.gray(`Fetching playlist from ${url}...`));
|
|
13
|
+
try {
|
|
14
|
+
const res = await client.get(url);
|
|
15
|
+
const content = await res.text();
|
|
16
|
+
const lines = content.split('\n').map(l => l.trim()).filter(Boolean);
|
|
17
|
+
if (!lines[0]?.startsWith('#EXTM3U')) {
|
|
18
|
+
console.error(colors.red('Not a valid HLS playlist'));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const isMaster = lines.some(l => l.startsWith('#EXT-X-STREAM-INF'));
|
|
22
|
+
console.log('');
|
|
23
|
+
console.log(colors.bold(colors.cyan('HLS Stream Info')));
|
|
24
|
+
console.log(`${colors.gray('URL:')} ${url}`);
|
|
25
|
+
console.log(`${colors.gray('Type:')} ${isMaster ? 'Master Playlist' : 'Media Playlist'}`);
|
|
26
|
+
console.log('');
|
|
27
|
+
if (isMaster) {
|
|
28
|
+
console.log(colors.bold('Available Qualities:'));
|
|
29
|
+
let i = 0;
|
|
30
|
+
for (let j = 0; j < lines.length; j++) {
|
|
31
|
+
if (lines[j].startsWith('#EXT-X-STREAM-INF')) {
|
|
32
|
+
const bandwidth = lines[j].match(/BANDWIDTH=(\d+)/)?.[1];
|
|
33
|
+
const resolution = lines[j].match(/RESOLUTION=([^,]+)/)?.[1];
|
|
34
|
+
const codecs = lines[j].match(/CODECS="([^"]+)"/)?.[1];
|
|
35
|
+
const variantUrl = lines[j + 1];
|
|
36
|
+
const bw = bandwidth ? `${Math.round(parseInt(bandwidth) / 1000)}kbps` : 'N/A';
|
|
37
|
+
console.log(` ${colors.green(String(i + 1))}. ${resolution || 'Unknown'} - ${bw}`);
|
|
38
|
+
if (codecs) {
|
|
39
|
+
console.log(` ${colors.gray('Codecs:')} ${codecs}`);
|
|
40
|
+
}
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const segments = lines.filter(l => !l.startsWith('#') && l.length > 0);
|
|
47
|
+
const targetDuration = lines.find(l => l.startsWith('#EXT-X-TARGETDURATION'))?.split(':')[1];
|
|
48
|
+
const endList = lines.some(l => l === '#EXT-X-ENDLIST');
|
|
49
|
+
const mediaSequence = lines.find(l => l.startsWith('#EXT-X-MEDIA-SEQUENCE'))?.split(':')[1];
|
|
50
|
+
console.log(`${colors.gray('Segments:')} ${segments.length}`);
|
|
51
|
+
if (targetDuration) {
|
|
52
|
+
console.log(`${colors.gray('Target Duration:')} ${targetDuration}s`);
|
|
53
|
+
}
|
|
54
|
+
if (mediaSequence) {
|
|
55
|
+
console.log(`${colors.gray('Media Sequence:')} ${mediaSequence}`);
|
|
56
|
+
}
|
|
57
|
+
console.log(`${colors.gray('Type:')} ${endList ? 'VOD' : 'Live'}`);
|
|
58
|
+
let totalDuration = 0;
|
|
59
|
+
for (const line of lines) {
|
|
60
|
+
if (line.startsWith('#EXTINF:')) {
|
|
61
|
+
const duration = parseFloat(line.split(':')[1].split(',')[0]);
|
|
62
|
+
totalDuration += duration;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (totalDuration > 0) {
|
|
66
|
+
const minutes = Math.floor(totalDuration / 60);
|
|
67
|
+
const seconds = Math.round(totalDuration % 60);
|
|
68
|
+
console.log(`${colors.gray('Total Duration:')} ${minutes}m ${seconds}s`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
console.log('');
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.error(colors.red(`HLS Error: ${err.message}`));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
hlsCmd
|
|
79
|
+
.command('download')
|
|
80
|
+
.description('Download an HLS stream')
|
|
81
|
+
.argument('<url>', 'HLS playlist URL')
|
|
82
|
+
.argument('[args...]', 'Output, options, and headers')
|
|
83
|
+
.option('-v, --verbose', 'Show detailed error information')
|
|
84
|
+
.option('-l, --live', 'Enable live stream mode')
|
|
85
|
+
.addHelpText('after', `
|
|
86
|
+
${colors.bold(colors.yellow('Options:'))}
|
|
87
|
+
${colors.cyan('[output]')} Output file path (default: output.ts)
|
|
88
|
+
${colors.cyan('quality=<quality>')} Quality: highest, lowest, or resolution (e.g., 720p)
|
|
89
|
+
${colors.cyan('live')} Enable live stream mode
|
|
90
|
+
${colors.cyan('duration=<seconds>')} Duration for live recording in seconds
|
|
91
|
+
${colors.cyan('concurrency=<n>')} Concurrent segment downloads (default: 4)
|
|
92
|
+
${colors.cyan('Header:Value')} Add custom HTTP header (e.g., Referer:https://example.com)
|
|
93
|
+
|
|
94
|
+
${colors.bold(colors.yellow('Examples:'))}
|
|
95
|
+
${colors.green('$ rek hls download https://example.com/stream.m3u8')} ${colors.gray('Download stream')}
|
|
96
|
+
${colors.green('$ rek hls download https://example.com/stream.m3u8 video.ts')} ${colors.gray('Custom output')}
|
|
97
|
+
${colors.green('$ rek hls download https://example.com/stream.m3u8 quality=720p')} ${colors.gray('Select quality')}
|
|
98
|
+
${colors.green('$ rek hls download https://example.com/live.m3u8 live duration=60')} ${colors.gray('Record live stream')}
|
|
99
|
+
${colors.green('$ rek hls download https://example.com/stream.m3u8 Referer:https://site.com User-Agent:"My Browser"')} ${colors.gray('With custom headers')}
|
|
100
|
+
`)
|
|
101
|
+
.action(async (...args) => {
|
|
102
|
+
const url = args[0];
|
|
103
|
+
const rawArgs = args[1] || [];
|
|
104
|
+
const cmdObj = args[args.length - 1];
|
|
105
|
+
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
106
|
+
const verbose = options.verbose;
|
|
107
|
+
const { hls } = await import('../../plugins/hls.js');
|
|
108
|
+
const { Client } = await import('../../core/client.js');
|
|
109
|
+
const { clientOptions, remainingArgs } = await parseEnhancerPresets([]);
|
|
110
|
+
let output = 'stream.ts';
|
|
111
|
+
let quality;
|
|
112
|
+
let live = options.live;
|
|
113
|
+
let duration;
|
|
114
|
+
let concurrency = 4;
|
|
115
|
+
const headers = { ...clientOptions.headers };
|
|
116
|
+
let outputHandled = false;
|
|
117
|
+
for (const arg of remainingArgs) {
|
|
118
|
+
if (arg.startsWith('--')) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
else if (arg.includes('=')) {
|
|
122
|
+
const [key, value] = arg.split('=');
|
|
123
|
+
if (key === 'quality')
|
|
124
|
+
quality = value;
|
|
125
|
+
else if (key === 'duration')
|
|
126
|
+
duration = parseInt(value, 10);
|
|
127
|
+
else if (key === 'concurrency')
|
|
128
|
+
concurrency = parseInt(value, 10);
|
|
129
|
+
}
|
|
130
|
+
else if (arg.includes(':') && !arg.startsWith('http')) {
|
|
131
|
+
const [key, ...valueParts] = arg.split(':');
|
|
132
|
+
headers[key.trim()] = valueParts.join(':').trim();
|
|
133
|
+
}
|
|
134
|
+
else if (!outputHandled) {
|
|
135
|
+
output = arg;
|
|
136
|
+
outputHandled = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const client = new Client(clientOptions);
|
|
140
|
+
console.log(colors.gray(`Downloading HLS stream from ${url}...`));
|
|
141
|
+
console.log(colors.gray(`Output: ${output}`));
|
|
142
|
+
if (Object.keys(headers).length > 0) {
|
|
143
|
+
console.log(colors.gray('With headers:'));
|
|
144
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
145
|
+
console.log(` ${colors.gray(`${key}: ${value.slice(0, 50)}${value.length > 50 ? '...' : ''}`)}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
console.log('');
|
|
149
|
+
try {
|
|
150
|
+
const hlsOptions = {
|
|
151
|
+
concurrency,
|
|
152
|
+
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
153
|
+
onProgress: (p) => {
|
|
154
|
+
const segs = p.totalSegments
|
|
155
|
+
? `${p.downloadedSegments}/${p.totalSegments}`
|
|
156
|
+
: `${p.downloadedSegments}`;
|
|
157
|
+
const mb = (p.downloadedBytes / 1024 / 1024).toFixed(2);
|
|
158
|
+
process.stdout.write(`\r ${colors.cyan(segs)} segments | ${colors.cyan(mb + ' MB')} downloaded`);
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
if (quality) {
|
|
162
|
+
if (quality === 'highest' || quality === 'lowest') {
|
|
163
|
+
hlsOptions.quality = quality;
|
|
164
|
+
}
|
|
165
|
+
else if (quality.includes('p')) {
|
|
166
|
+
hlsOptions.quality = { resolution: quality };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (live) {
|
|
170
|
+
hlsOptions.live = duration
|
|
171
|
+
? { duration: duration * 1000 }
|
|
172
|
+
: true;
|
|
173
|
+
}
|
|
174
|
+
await hls(client, url, hlsOptions).download(output);
|
|
175
|
+
console.log('');
|
|
176
|
+
console.log(colors.green(`✔ Download complete: ${output}`));
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
console.log('');
|
|
180
|
+
const msg = err.message || String(err);
|
|
181
|
+
console.error(colors.red(`HLS Download Error: ${msg}`));
|
|
182
|
+
if (verbose) {
|
|
183
|
+
console.error(colors.gray('\n--- Error Details ---'));
|
|
184
|
+
if (err.cause)
|
|
185
|
+
console.error('Cause:', err.cause);
|
|
186
|
+
if (err.stack)
|
|
187
|
+
console.error(err.stack);
|
|
188
|
+
}
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|