@iflow-mcp/jakeliume-webpeel 0.22.0

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 (547) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +313 -0
  3. package/dist/cache.d.ts +30 -0
  4. package/dist/cache.js +139 -0
  5. package/dist/cli/commands/auth.d.ts +5 -0
  6. package/dist/cli/commands/auth.js +411 -0
  7. package/dist/cli/commands/doctor.d.ts +37 -0
  8. package/dist/cli/commands/doctor.js +371 -0
  9. package/dist/cli/commands/fetch.d.ts +6 -0
  10. package/dist/cli/commands/fetch.js +1345 -0
  11. package/dist/cli/commands/guide.d.ts +2 -0
  12. package/dist/cli/commands/guide.js +183 -0
  13. package/dist/cli/commands/interact.d.ts +5 -0
  14. package/dist/cli/commands/interact.js +840 -0
  15. package/dist/cli/commands/jobs.d.ts +5 -0
  16. package/dist/cli/commands/jobs.js +997 -0
  17. package/dist/cli/commands/monitor.d.ts +12 -0
  18. package/dist/cli/commands/monitor.js +197 -0
  19. package/dist/cli/commands/observe.d.ts +12 -0
  20. package/dist/cli/commands/observe.js +158 -0
  21. package/dist/cli/commands/screenshot.d.ts +5 -0
  22. package/dist/cli/commands/screenshot.js +282 -0
  23. package/dist/cli/commands/search.d.ts +5 -0
  24. package/dist/cli/commands/search.js +1021 -0
  25. package/dist/cli/commands/setup.d.ts +13 -0
  26. package/dist/cli/commands/setup.js +244 -0
  27. package/dist/cli/commands/skill.d.ts +15 -0
  28. package/dist/cli/commands/skill.js +195 -0
  29. package/dist/cli/utils.d.ts +84 -0
  30. package/dist/cli/utils.js +806 -0
  31. package/dist/cli-auth.d.ts +75 -0
  32. package/dist/cli-auth.js +369 -0
  33. package/dist/cli.d.ts +17 -0
  34. package/dist/cli.js +99 -0
  35. package/dist/core/actions.d.ts +69 -0
  36. package/dist/core/actions.js +495 -0
  37. package/dist/core/agent.d.ts +98 -0
  38. package/dist/core/agent.js +558 -0
  39. package/dist/core/answer.d.ts +42 -0
  40. package/dist/core/answer.js +395 -0
  41. package/dist/core/application-tracker.d.ts +84 -0
  42. package/dist/core/application-tracker.js +184 -0
  43. package/dist/core/apply.d.ts +162 -0
  44. package/dist/core/apply.js +816 -0
  45. package/dist/core/auth-detection.d.ts +35 -0
  46. package/dist/core/auth-detection.js +358 -0
  47. package/dist/core/auto-extract.d.ts +82 -0
  48. package/dist/core/auto-extract.js +604 -0
  49. package/dist/core/auto-interact.d.ts +23 -0
  50. package/dist/core/auto-interact.js +246 -0
  51. package/dist/core/bm25-filter.d.ts +66 -0
  52. package/dist/core/bm25-filter.js +288 -0
  53. package/dist/core/branding.d.ts +54 -0
  54. package/dist/core/branding.js +234 -0
  55. package/dist/core/browser-fetch.d.ts +323 -0
  56. package/dist/core/browser-fetch.js +1600 -0
  57. package/dist/core/browser-pool.d.ts +91 -0
  58. package/dist/core/browser-pool.js +550 -0
  59. package/dist/core/budget.d.ts +42 -0
  60. package/dist/core/budget.js +324 -0
  61. package/dist/core/business-intel.d.ts +47 -0
  62. package/dist/core/business-intel.js +279 -0
  63. package/dist/core/cache.d.ts +13 -0
  64. package/dist/core/cache.js +121 -0
  65. package/dist/core/cf-worker-proxy.d.ts +32 -0
  66. package/dist/core/cf-worker-proxy.js +87 -0
  67. package/dist/core/challenge-detection.d.ts +26 -0
  68. package/dist/core/challenge-detection.js +468 -0
  69. package/dist/core/change-tracking.d.ts +75 -0
  70. package/dist/core/change-tracking.js +276 -0
  71. package/dist/core/chunker.d.ts +46 -0
  72. package/dist/core/chunker.js +249 -0
  73. package/dist/core/chunking.d.ts +42 -0
  74. package/dist/core/chunking.js +181 -0
  75. package/dist/core/circuit-breaker.d.ts +44 -0
  76. package/dist/core/circuit-breaker.js +85 -0
  77. package/dist/core/content-pruner.d.ts +47 -0
  78. package/dist/core/content-pruner.js +425 -0
  79. package/dist/core/cookie-cache.d.ts +60 -0
  80. package/dist/core/cookie-cache.js +163 -0
  81. package/dist/core/crawl-checkpoint.d.ts +54 -0
  82. package/dist/core/crawl-checkpoint.js +104 -0
  83. package/dist/core/crawler.d.ts +84 -0
  84. package/dist/core/crawler.js +349 -0
  85. package/dist/core/cross-verify.d.ts +27 -0
  86. package/dist/core/cross-verify.js +93 -0
  87. package/dist/core/deep-fetch.d.ts +74 -0
  88. package/dist/core/deep-fetch.js +405 -0
  89. package/dist/core/deep-research.d.ts +141 -0
  90. package/dist/core/deep-research.js +972 -0
  91. package/dist/core/design-analysis.d.ts +70 -0
  92. package/dist/core/design-analysis.js +490 -0
  93. package/dist/core/design-compare.d.ts +38 -0
  94. package/dist/core/design-compare.js +264 -0
  95. package/dist/core/diff.d.ts +61 -0
  96. package/dist/core/diff.js +289 -0
  97. package/dist/core/dns-cache.d.ts +20 -0
  98. package/dist/core/dns-cache.js +198 -0
  99. package/dist/core/documents.d.ts +23 -0
  100. package/dist/core/documents.js +123 -0
  101. package/dist/core/domain-memory.d.ts +66 -0
  102. package/dist/core/domain-memory.js +163 -0
  103. package/dist/core/domain-verify.d.ts +40 -0
  104. package/dist/core/domain-verify.js +379 -0
  105. package/dist/core/engine-ranker.d.ts +112 -0
  106. package/dist/core/engine-ranker.js +395 -0
  107. package/dist/core/extract-inline.d.ts +38 -0
  108. package/dist/core/extract-inline.js +215 -0
  109. package/dist/core/extract-listings.d.ts +38 -0
  110. package/dist/core/extract-listings.js +461 -0
  111. package/dist/core/extract.d.ts +9 -0
  112. package/dist/core/extract.js +139 -0
  113. package/dist/core/fetch-cache.d.ts +57 -0
  114. package/dist/core/fetch-cache.js +95 -0
  115. package/dist/core/fetcher.d.ts +13 -0
  116. package/dist/core/fetcher.js +12 -0
  117. package/dist/core/google-cache.d.ts +29 -0
  118. package/dist/core/google-cache.js +180 -0
  119. package/dist/core/google-serp-parser.d.ts +82 -0
  120. package/dist/core/google-serp-parser.js +287 -0
  121. package/dist/core/hotel-search.d.ts +122 -0
  122. package/dist/core/hotel-search.js +382 -0
  123. package/dist/core/http-fetch.d.ts +72 -0
  124. package/dist/core/http-fetch.js +820 -0
  125. package/dist/core/human.d.ts +175 -0
  126. package/dist/core/human.js +680 -0
  127. package/dist/core/image-caption.d.ts +44 -0
  128. package/dist/core/image-caption.js +271 -0
  129. package/dist/core/jobs.d.ts +75 -0
  130. package/dist/core/jobs.js +634 -0
  131. package/dist/core/json-ld.d.ts +15 -0
  132. package/dist/core/json-ld.js +617 -0
  133. package/dist/core/language-detect.d.ts +18 -0
  134. package/dist/core/language-detect.js +135 -0
  135. package/dist/core/links.d.ts +10 -0
  136. package/dist/core/links.js +44 -0
  137. package/dist/core/llm-extract.d.ts +71 -0
  138. package/dist/core/llm-extract.js +507 -0
  139. package/dist/core/llm-provider.d.ts +100 -0
  140. package/dist/core/llm-provider.js +702 -0
  141. package/dist/core/local-search.d.ts +60 -0
  142. package/dist/core/local-search.js +308 -0
  143. package/dist/core/logger.d.ts +28 -0
  144. package/dist/core/logger.js +104 -0
  145. package/dist/core/map.d.ts +33 -0
  146. package/dist/core/map.js +127 -0
  147. package/dist/core/markdown.d.ts +92 -0
  148. package/dist/core/markdown.js +809 -0
  149. package/dist/core/metadata.d.ts +34 -0
  150. package/dist/core/metadata.js +422 -0
  151. package/dist/core/observe.d.ts +113 -0
  152. package/dist/core/observe.js +395 -0
  153. package/dist/core/ocr.d.ts +12 -0
  154. package/dist/core/ocr.js +33 -0
  155. package/dist/core/paginate.d.ts +31 -0
  156. package/dist/core/paginate.js +106 -0
  157. package/dist/core/pdf.d.ts +8 -0
  158. package/dist/core/pdf.js +25 -0
  159. package/dist/core/peel-tls.d.ts +25 -0
  160. package/dist/core/peel-tls.js +220 -0
  161. package/dist/core/pipeline.d.ts +132 -0
  162. package/dist/core/pipeline.js +1666 -0
  163. package/dist/core/profiles.d.ts +61 -0
  164. package/dist/core/profiles.js +350 -0
  165. package/dist/core/prompt-guard.d.ts +30 -0
  166. package/dist/core/prompt-guard.js +119 -0
  167. package/dist/core/proxy-config.d.ts +90 -0
  168. package/dist/core/proxy-config.js +172 -0
  169. package/dist/core/quick-answer.d.ts +53 -0
  170. package/dist/core/quick-answer.js +833 -0
  171. package/dist/core/rate-governor.d.ts +80 -0
  172. package/dist/core/rate-governor.js +238 -0
  173. package/dist/core/readability.d.ts +57 -0
  174. package/dist/core/readability.js +533 -0
  175. package/dist/core/research.d.ts +66 -0
  176. package/dist/core/research.js +270 -0
  177. package/dist/core/retry.d.ts +60 -0
  178. package/dist/core/retry.js +119 -0
  179. package/dist/core/safe-browsing.d.ts +30 -0
  180. package/dist/core/safe-browsing.js +206 -0
  181. package/dist/core/schema-extraction.d.ts +66 -0
  182. package/dist/core/schema-extraction.js +352 -0
  183. package/dist/core/schema-postprocess.d.ts +32 -0
  184. package/dist/core/schema-postprocess.js +469 -0
  185. package/dist/core/schema-templates.d.ts +19 -0
  186. package/dist/core/schema-templates.js +143 -0
  187. package/dist/core/screenshot.d.ts +224 -0
  188. package/dist/core/screenshot.js +207 -0
  189. package/dist/core/search-engines.d.ts +25 -0
  190. package/dist/core/search-engines.js +182 -0
  191. package/dist/core/search-provider.d.ts +243 -0
  192. package/dist/core/search-provider.js +1629 -0
  193. package/dist/core/searxng-provider.d.ts +35 -0
  194. package/dist/core/searxng-provider.js +105 -0
  195. package/dist/core/selective-evidence.d.ts +151 -0
  196. package/dist/core/selective-evidence.js +389 -0
  197. package/dist/core/site-search.d.ts +44 -0
  198. package/dist/core/site-search.js +252 -0
  199. package/dist/core/sitemap.d.ts +23 -0
  200. package/dist/core/sitemap.js +105 -0
  201. package/dist/core/source-credibility.d.ts +29 -0
  202. package/dist/core/source-credibility.js +584 -0
  203. package/dist/core/source-scoring.d.ts +166 -0
  204. package/dist/core/source-scoring.js +396 -0
  205. package/dist/core/stemmer.d.ts +38 -0
  206. package/dist/core/stemmer.js +509 -0
  207. package/dist/core/strategies.d.ts +104 -0
  208. package/dist/core/strategies.js +1044 -0
  209. package/dist/core/strategy-hooks.d.ts +145 -0
  210. package/dist/core/strategy-hooks.js +74 -0
  211. package/dist/core/structured-extract.d.ts +43 -0
  212. package/dist/core/structured-extract.js +550 -0
  213. package/dist/core/summarize.d.ts +17 -0
  214. package/dist/core/summarize.js +78 -0
  215. package/dist/core/synonyms.d.ts +42 -0
  216. package/dist/core/synonyms.js +184 -0
  217. package/dist/core/system-monitor.d.ts +61 -0
  218. package/dist/core/system-monitor.js +133 -0
  219. package/dist/core/table-format.d.ts +30 -0
  220. package/dist/core/table-format.js +146 -0
  221. package/dist/core/threat-feeds.d.ts +23 -0
  222. package/dist/core/threat-feeds.js +104 -0
  223. package/dist/core/timing.d.ts +21 -0
  224. package/dist/core/timing.js +33 -0
  225. package/dist/core/transcript-export.d.ts +47 -0
  226. package/dist/core/transcript-export.js +107 -0
  227. package/dist/core/user-agents.d.ts +82 -0
  228. package/dist/core/user-agents.js +239 -0
  229. package/dist/core/vertical-search.d.ts +54 -0
  230. package/dist/core/vertical-search.js +158 -0
  231. package/dist/core/watch-manager.d.ts +175 -0
  232. package/dist/core/watch-manager.js +416 -0
  233. package/dist/core/watch.d.ts +101 -0
  234. package/dist/core/watch.js +389 -0
  235. package/dist/core/youtube.d.ts +130 -0
  236. package/dist/core/youtube.js +1175 -0
  237. package/dist/ee/challenge-re-export.d.ts +1 -0
  238. package/dist/ee/challenge-re-export.js +1 -0
  239. package/dist/ee/challenge-solver.d.ts +72 -0
  240. package/dist/ee/challenge-solver.js +720 -0
  241. package/dist/ee/domain-extractors.d.ts +8 -0
  242. package/dist/ee/domain-extractors.js +8 -0
  243. package/dist/ee/domain-intel.d.ts +16 -0
  244. package/dist/ee/domain-intel.js +133 -0
  245. package/dist/ee/extractors/allrecipes.d.ts +2 -0
  246. package/dist/ee/extractors/allrecipes.js +120 -0
  247. package/dist/ee/extractors/amazon.d.ts +2 -0
  248. package/dist/ee/extractors/amazon.js +78 -0
  249. package/dist/ee/extractors/arxiv.d.ts +2 -0
  250. package/dist/ee/extractors/arxiv.js +137 -0
  251. package/dist/ee/extractors/bestbuy.d.ts +2 -0
  252. package/dist/ee/extractors/bestbuy.js +78 -0
  253. package/dist/ee/extractors/carscom.d.ts +2 -0
  254. package/dist/ee/extractors/carscom.js +121 -0
  255. package/dist/ee/extractors/coingecko.d.ts +2 -0
  256. package/dist/ee/extractors/coingecko.js +134 -0
  257. package/dist/ee/extractors/craigslist.d.ts +2 -0
  258. package/dist/ee/extractors/craigslist.js +92 -0
  259. package/dist/ee/extractors/devto.d.ts +2 -0
  260. package/dist/ee/extractors/devto.js +135 -0
  261. package/dist/ee/extractors/ebay.d.ts +2 -0
  262. package/dist/ee/extractors/ebay.js +90 -0
  263. package/dist/ee/extractors/espn.d.ts +2 -0
  264. package/dist/ee/extractors/espn.js +260 -0
  265. package/dist/ee/extractors/etsy.d.ts +2 -0
  266. package/dist/ee/extractors/etsy.js +52 -0
  267. package/dist/ee/extractors/facebook.d.ts +2 -0
  268. package/dist/ee/extractors/facebook.js +46 -0
  269. package/dist/ee/extractors/github.d.ts +2 -0
  270. package/dist/ee/extractors/github.js +196 -0
  271. package/dist/ee/extractors/google-flights.d.ts +2 -0
  272. package/dist/ee/extractors/google-flights.js +176 -0
  273. package/dist/ee/extractors/hackernews.d.ts +2 -0
  274. package/dist/ee/extractors/hackernews.js +147 -0
  275. package/dist/ee/extractors/imdb.d.ts +2 -0
  276. package/dist/ee/extractors/imdb.js +172 -0
  277. package/dist/ee/extractors/index.d.ts +26 -0
  278. package/dist/ee/extractors/index.js +247 -0
  279. package/dist/ee/extractors/instagram.d.ts +2 -0
  280. package/dist/ee/extractors/instagram.js +102 -0
  281. package/dist/ee/extractors/kalshi.d.ts +2 -0
  282. package/dist/ee/extractors/kalshi.js +121 -0
  283. package/dist/ee/extractors/kayak-cars.d.ts +2 -0
  284. package/dist/ee/extractors/kayak-cars.js +270 -0
  285. package/dist/ee/extractors/linkedin.d.ts +2 -0
  286. package/dist/ee/extractors/linkedin.js +113 -0
  287. package/dist/ee/extractors/medium.d.ts +2 -0
  288. package/dist/ee/extractors/medium.js +130 -0
  289. package/dist/ee/extractors/news.d.ts +4 -0
  290. package/dist/ee/extractors/news.js +173 -0
  291. package/dist/ee/extractors/npm.d.ts +2 -0
  292. package/dist/ee/extractors/npm.js +86 -0
  293. package/dist/ee/extractors/pdf.d.ts +2 -0
  294. package/dist/ee/extractors/pdf.js +108 -0
  295. package/dist/ee/extractors/pinterest.d.ts +2 -0
  296. package/dist/ee/extractors/pinterest.js +34 -0
  297. package/dist/ee/extractors/polymarket.d.ts +2 -0
  298. package/dist/ee/extractors/polymarket.js +358 -0
  299. package/dist/ee/extractors/producthunt.d.ts +2 -0
  300. package/dist/ee/extractors/producthunt.js +88 -0
  301. package/dist/ee/extractors/pubmed.d.ts +2 -0
  302. package/dist/ee/extractors/pubmed.js +162 -0
  303. package/dist/ee/extractors/pypi.d.ts +2 -0
  304. package/dist/ee/extractors/pypi.js +80 -0
  305. package/dist/ee/extractors/reddit.d.ts +2 -0
  306. package/dist/ee/extractors/reddit.js +438 -0
  307. package/dist/ee/extractors/redfin.d.ts +2 -0
  308. package/dist/ee/extractors/redfin.js +156 -0
  309. package/dist/ee/extractors/semanticscholar.d.ts +2 -0
  310. package/dist/ee/extractors/semanticscholar.js +131 -0
  311. package/dist/ee/extractors/shared.d.ts +12 -0
  312. package/dist/ee/extractors/shared.js +76 -0
  313. package/dist/ee/extractors/soundcloud.d.ts +2 -0
  314. package/dist/ee/extractors/soundcloud.js +34 -0
  315. package/dist/ee/extractors/sportsbetting.d.ts +2 -0
  316. package/dist/ee/extractors/sportsbetting.js +37 -0
  317. package/dist/ee/extractors/spotify.d.ts +2 -0
  318. package/dist/ee/extractors/spotify.js +34 -0
  319. package/dist/ee/extractors/stackoverflow.d.ts +2 -0
  320. package/dist/ee/extractors/stackoverflow.js +61 -0
  321. package/dist/ee/extractors/substack.d.ts +2 -0
  322. package/dist/ee/extractors/substack.js +115 -0
  323. package/dist/ee/extractors/substackroot.d.ts +2 -0
  324. package/dist/ee/extractors/substackroot.js +46 -0
  325. package/dist/ee/extractors/tiktok.d.ts +2 -0
  326. package/dist/ee/extractors/tiktok.js +29 -0
  327. package/dist/ee/extractors/tradingview.d.ts +2 -0
  328. package/dist/ee/extractors/tradingview.js +182 -0
  329. package/dist/ee/extractors/twitch.d.ts +2 -0
  330. package/dist/ee/extractors/twitch.js +36 -0
  331. package/dist/ee/extractors/twitter.d.ts +2 -0
  332. package/dist/ee/extractors/twitter.js +327 -0
  333. package/dist/ee/extractors/types.d.ts +14 -0
  334. package/dist/ee/extractors/types.js +1 -0
  335. package/dist/ee/extractors/walmart.d.ts +2 -0
  336. package/dist/ee/extractors/walmart.js +50 -0
  337. package/dist/ee/extractors/weather.d.ts +2 -0
  338. package/dist/ee/extractors/weather.js +133 -0
  339. package/dist/ee/extractors/wikipedia.d.ts +4 -0
  340. package/dist/ee/extractors/wikipedia.js +235 -0
  341. package/dist/ee/extractors/yelp.d.ts +2 -0
  342. package/dist/ee/extractors/yelp.js +216 -0
  343. package/dist/ee/extractors/youtube.d.ts +2 -0
  344. package/dist/ee/extractors/youtube.js +189 -0
  345. package/dist/ee/extractors/zillow.d.ts +54 -0
  346. package/dist/ee/extractors/zillow.js +247 -0
  347. package/dist/ee/extractors-re-export.d.ts +1 -0
  348. package/dist/ee/extractors-re-export.js +1 -0
  349. package/dist/ee/premium-hooks.d.ts +20 -0
  350. package/dist/ee/premium-hooks.js +50 -0
  351. package/dist/ee/spa-detection.d.ts +2 -0
  352. package/dist/ee/spa-detection.js +2 -0
  353. package/dist/ee/stability.d.ts +4 -0
  354. package/dist/ee/stability.js +29 -0
  355. package/dist/ee/swr-cache.d.ts +14 -0
  356. package/dist/ee/swr-cache.js +34 -0
  357. package/dist/index.d.ts +143 -0
  358. package/dist/index.js +291 -0
  359. package/dist/integrations/index.d.ts +2 -0
  360. package/dist/integrations/index.js +2 -0
  361. package/dist/integrations/langchain.d.ts +64 -0
  362. package/dist/integrations/langchain.js +115 -0
  363. package/dist/integrations/llamaindex.d.ts +50 -0
  364. package/dist/integrations/llamaindex.js +91 -0
  365. package/dist/mcp/handlers/act.d.ts +5 -0
  366. package/dist/mcp/handlers/act.js +34 -0
  367. package/dist/mcp/handlers/definitions.d.ts +6 -0
  368. package/dist/mcp/handlers/definitions.js +395 -0
  369. package/dist/mcp/handlers/extract.d.ts +7 -0
  370. package/dist/mcp/handlers/extract.js +135 -0
  371. package/dist/mcp/handlers/fetch.d.ts +6 -0
  372. package/dist/mcp/handlers/fetch.js +98 -0
  373. package/dist/mcp/handlers/find.d.ts +5 -0
  374. package/dist/mcp/handlers/find.js +137 -0
  375. package/dist/mcp/handlers/index.d.ts +13 -0
  376. package/dist/mcp/handlers/index.js +63 -0
  377. package/dist/mcp/handlers/legacy.d.ts +25 -0
  378. package/dist/mcp/handlers/legacy.js +450 -0
  379. package/dist/mcp/handlers/meta.d.ts +6 -0
  380. package/dist/mcp/handlers/meta.js +40 -0
  381. package/dist/mcp/handlers/monitor.d.ts +5 -0
  382. package/dist/mcp/handlers/monitor.js +41 -0
  383. package/dist/mcp/handlers/observe.d.ts +8 -0
  384. package/dist/mcp/handlers/observe.js +37 -0
  385. package/dist/mcp/handlers/read.d.ts +6 -0
  386. package/dist/mcp/handlers/read.js +78 -0
  387. package/dist/mcp/handlers/see.d.ts +5 -0
  388. package/dist/mcp/handlers/see.js +75 -0
  389. package/dist/mcp/handlers/types.d.ts +29 -0
  390. package/dist/mcp/handlers/types.js +28 -0
  391. package/dist/mcp/server.d.ts +7 -0
  392. package/dist/mcp/server.js +108 -0
  393. package/dist/mcp/smart-router.d.ts +23 -0
  394. package/dist/mcp/smart-router.js +178 -0
  395. package/dist/server/app.d.ts +14 -0
  396. package/dist/server/app.js +632 -0
  397. package/dist/server/auth-store.d.ts +28 -0
  398. package/dist/server/auth-store.js +88 -0
  399. package/dist/server/bull-queues.d.ts +60 -0
  400. package/dist/server/bull-queues.js +90 -0
  401. package/dist/server/email-service.d.ts +55 -0
  402. package/dist/server/email-service.js +291 -0
  403. package/dist/server/job-queue.d.ts +100 -0
  404. package/dist/server/job-queue.js +145 -0
  405. package/dist/server/logger.d.ts +10 -0
  406. package/dist/server/logger.js +37 -0
  407. package/dist/server/middleware/audit-log.d.ts +14 -0
  408. package/dist/server/middleware/audit-log.js +73 -0
  409. package/dist/server/middleware/auth.d.ts +35 -0
  410. package/dist/server/middleware/auth.js +225 -0
  411. package/dist/server/middleware/rate-limit.d.ts +50 -0
  412. package/dist/server/middleware/rate-limit.js +270 -0
  413. package/dist/server/middleware/scope-guard.d.ts +25 -0
  414. package/dist/server/middleware/scope-guard.js +45 -0
  415. package/dist/server/middleware/url-validator.d.ts +15 -0
  416. package/dist/server/middleware/url-validator.js +201 -0
  417. package/dist/server/openapi.yaml +6418 -0
  418. package/dist/server/pg-auth-store.d.ts +146 -0
  419. package/dist/server/pg-auth-store.js +576 -0
  420. package/dist/server/pg-job-queue.d.ts +59 -0
  421. package/dist/server/pg-job-queue.js +375 -0
  422. package/dist/server/routes/activity.d.ts +6 -0
  423. package/dist/server/routes/activity.js +79 -0
  424. package/dist/server/routes/admin-active.d.ts +7 -0
  425. package/dist/server/routes/admin-active.js +120 -0
  426. package/dist/server/routes/admin-stats.d.ts +7 -0
  427. package/dist/server/routes/admin-stats.js +176 -0
  428. package/dist/server/routes/agent.d.ts +24 -0
  429. package/dist/server/routes/agent.js +480 -0
  430. package/dist/server/routes/answer.d.ts +5 -0
  431. package/dist/server/routes/answer.js +125 -0
  432. package/dist/server/routes/ask.d.ts +28 -0
  433. package/dist/server/routes/ask.js +295 -0
  434. package/dist/server/routes/batch.d.ts +6 -0
  435. package/dist/server/routes/batch.js +493 -0
  436. package/dist/server/routes/cache-warm.d.ts +25 -0
  437. package/dist/server/routes/cache-warm.js +212 -0
  438. package/dist/server/routes/cli-usage.d.ts +6 -0
  439. package/dist/server/routes/cli-usage.js +127 -0
  440. package/dist/server/routes/compat.d.ts +23 -0
  441. package/dist/server/routes/compat.js +652 -0
  442. package/dist/server/routes/crawl.d.ts +13 -0
  443. package/dist/server/routes/crawl.js +287 -0
  444. package/dist/server/routes/deep-fetch.d.ts +8 -0
  445. package/dist/server/routes/deep-fetch.js +57 -0
  446. package/dist/server/routes/deep-research.d.ts +11 -0
  447. package/dist/server/routes/deep-research.js +232 -0
  448. package/dist/server/routes/demo.d.ts +24 -0
  449. package/dist/server/routes/demo.js +517 -0
  450. package/dist/server/routes/do.d.ts +8 -0
  451. package/dist/server/routes/do.js +72 -0
  452. package/dist/server/routes/extract.d.ts +14 -0
  453. package/dist/server/routes/extract.js +325 -0
  454. package/dist/server/routes/feed.d.ts +15 -0
  455. package/dist/server/routes/feed.js +311 -0
  456. package/dist/server/routes/fetch-queue.d.ts +13 -0
  457. package/dist/server/routes/fetch-queue.js +357 -0
  458. package/dist/server/routes/fetch.d.ts +7 -0
  459. package/dist/server/routes/fetch.js +1274 -0
  460. package/dist/server/routes/go.d.ts +14 -0
  461. package/dist/server/routes/go.js +81 -0
  462. package/dist/server/routes/health.d.ts +11 -0
  463. package/dist/server/routes/health.js +141 -0
  464. package/dist/server/routes/jobs.d.ts +7 -0
  465. package/dist/server/routes/jobs.js +574 -0
  466. package/dist/server/routes/map.d.ts +11 -0
  467. package/dist/server/routes/map.js +116 -0
  468. package/dist/server/routes/mcp.d.ts +14 -0
  469. package/dist/server/routes/mcp.js +197 -0
  470. package/dist/server/routes/metrics.d.ts +37 -0
  471. package/dist/server/routes/metrics.js +149 -0
  472. package/dist/server/routes/oauth.d.ts +9 -0
  473. package/dist/server/routes/oauth.js +396 -0
  474. package/dist/server/routes/playground.d.ts +17 -0
  475. package/dist/server/routes/playground.js +283 -0
  476. package/dist/server/routes/reader.d.ts +18 -0
  477. package/dist/server/routes/reader.js +192 -0
  478. package/dist/server/routes/research.d.ts +14 -0
  479. package/dist/server/routes/research.js +482 -0
  480. package/dist/server/routes/screenshot.d.ts +22 -0
  481. package/dist/server/routes/screenshot.js +820 -0
  482. package/dist/server/routes/search.d.ts +6 -0
  483. package/dist/server/routes/search.js +874 -0
  484. package/dist/server/routes/session.d.ts +17 -0
  485. package/dist/server/routes/session.js +548 -0
  486. package/dist/server/routes/share.d.ts +18 -0
  487. package/dist/server/routes/share.js +462 -0
  488. package/dist/server/routes/smart-search/handlers/cars.d.ts +2 -0
  489. package/dist/server/routes/smart-search/handlers/cars.js +102 -0
  490. package/dist/server/routes/smart-search/handlers/flights.d.ts +2 -0
  491. package/dist/server/routes/smart-search/handlers/flights.js +72 -0
  492. package/dist/server/routes/smart-search/handlers/general.d.ts +13 -0
  493. package/dist/server/routes/smart-search/handlers/general.js +717 -0
  494. package/dist/server/routes/smart-search/handlers/hotels.d.ts +2 -0
  495. package/dist/server/routes/smart-search/handlers/hotels.js +88 -0
  496. package/dist/server/routes/smart-search/handlers/products.d.ts +2 -0
  497. package/dist/server/routes/smart-search/handlers/products.js +1309 -0
  498. package/dist/server/routes/smart-search/handlers/rental.d.ts +2 -0
  499. package/dist/server/routes/smart-search/handlers/rental.js +154 -0
  500. package/dist/server/routes/smart-search/handlers/restaurants.d.ts +2 -0
  501. package/dist/server/routes/smart-search/handlers/restaurants.js +225 -0
  502. package/dist/server/routes/smart-search/handlers/transit-verdict.d.ts +41 -0
  503. package/dist/server/routes/smart-search/handlers/transit-verdict.js +224 -0
  504. package/dist/server/routes/smart-search/index.d.ts +19 -0
  505. package/dist/server/routes/smart-search/index.js +546 -0
  506. package/dist/server/routes/smart-search/intent.d.ts +3 -0
  507. package/dist/server/routes/smart-search/intent.js +264 -0
  508. package/dist/server/routes/smart-search/llm.d.ts +16 -0
  509. package/dist/server/routes/smart-search/llm.js +70 -0
  510. package/dist/server/routes/smart-search/sources/reddit.d.ts +18 -0
  511. package/dist/server/routes/smart-search/sources/reddit.js +34 -0
  512. package/dist/server/routes/smart-search/sources/yelp.d.ts +25 -0
  513. package/dist/server/routes/smart-search/sources/yelp.js +171 -0
  514. package/dist/server/routes/smart-search/sources/youtube.d.ts +8 -0
  515. package/dist/server/routes/smart-search/sources/youtube.js +9 -0
  516. package/dist/server/routes/smart-search/types.d.ts +81 -0
  517. package/dist/server/routes/smart-search/types.js +1 -0
  518. package/dist/server/routes/smart-search/utils.d.ts +20 -0
  519. package/dist/server/routes/smart-search/utils.js +146 -0
  520. package/dist/server/routes/stats.d.ts +6 -0
  521. package/dist/server/routes/stats.js +71 -0
  522. package/dist/server/routes/stripe.d.ts +15 -0
  523. package/dist/server/routes/stripe.js +296 -0
  524. package/dist/server/routes/transcript-export.d.ts +10 -0
  525. package/dist/server/routes/transcript-export.js +178 -0
  526. package/dist/server/routes/usage.d.ts +9 -0
  527. package/dist/server/routes/usage.js +279 -0
  528. package/dist/server/routes/users.d.ts +8 -0
  529. package/dist/server/routes/users.js +1867 -0
  530. package/dist/server/routes/watch.d.ts +15 -0
  531. package/dist/server/routes/watch.js +309 -0
  532. package/dist/server/routes/webhooks.d.ts +26 -0
  533. package/dist/server/routes/webhooks.js +170 -0
  534. package/dist/server/routes/youtube.d.ts +6 -0
  535. package/dist/server/routes/youtube.js +130 -0
  536. package/dist/server/sentry.d.ts +14 -0
  537. package/dist/server/sentry.js +104 -0
  538. package/dist/server/types.d.ts +15 -0
  539. package/dist/server/types.js +7 -0
  540. package/dist/server/utils/response.d.ts +44 -0
  541. package/dist/server/utils/response.js +69 -0
  542. package/dist/server/utils/sse.d.ts +22 -0
  543. package/dist/server/utils/sse.js +38 -0
  544. package/dist/types.d.ts +552 -0
  545. package/dist/types.js +39 -0
  546. package/llms.txt +105 -0
  547. package/package.json +189 -0
@@ -0,0 +1,382 @@
1
+ /**
2
+ * Hotel search module — searches multiple travel sites and returns sorted hotel listings.
3
+ *
4
+ * Sources: Kayak, Booking.com, Google Travel
5
+ * All sources are fetched in parallel; failures are captured per-source without
6
+ * crashing the overall search.
7
+ */
8
+ import { peel } from '../index.js';
9
+ import { extractListings } from './extract-listings.js';
10
+ import { findSchemaForUrl, extractWithSchema } from './schema-extraction.js';
11
+ // ── Date Parsing ──────────────────────────────────────────────────────────────
12
+ /**
13
+ * Parse a date string (ISO or relative) into an ISO date string (YYYY-MM-DD).
14
+ *
15
+ * Supported relative formats:
16
+ * - "tomorrow" → today + 1 day
17
+ * - "next <weekday>" → next occurrence of that weekday
18
+ * - ISO date "2026-02-20" → returned as-is
19
+ */
20
+ export function parseDate(input, baseDate) {
21
+ const base = baseDate ?? new Date();
22
+ // Normalise
23
+ const normalised = input.trim().toLowerCase();
24
+ if (normalised === 'today') {
25
+ return toIsoDate(base);
26
+ }
27
+ if (normalised === 'tomorrow') {
28
+ const d = new Date(base);
29
+ d.setDate(d.getDate() + 1);
30
+ return toIsoDate(d);
31
+ }
32
+ // "next <weekday>"
33
+ const nextMatch = normalised.match(/^next\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/);
34
+ if (nextMatch) {
35
+ const weekdays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
36
+ const targetDay = weekdays.indexOf(nextMatch[1]);
37
+ const d = new Date(base);
38
+ const currentDay = d.getDay();
39
+ let daysUntil = targetDay - currentDay;
40
+ if (daysUntil <= 0)
41
+ daysUntil += 7;
42
+ d.setDate(d.getDate() + daysUntil);
43
+ return toIsoDate(d);
44
+ }
45
+ // Try ISO date (YYYY-MM-DD)
46
+ if (/^\d{4}-\d{2}-\d{2}$/.test(input.trim())) {
47
+ return input.trim();
48
+ }
49
+ // Fallback: try to parse as a generic date string
50
+ const parsed = new Date(input);
51
+ if (!isNaN(parsed.getTime())) {
52
+ return toIsoDate(parsed);
53
+ }
54
+ throw new Error(`Unrecognized date format: "${input}"`);
55
+ }
56
+ function toIsoDate(d) {
57
+ const yyyy = d.getFullYear();
58
+ const mm = String(d.getMonth() + 1).padStart(2, '0');
59
+ const dd = String(d.getDate()).padStart(2, '0');
60
+ return `${yyyy}-${mm}-${dd}`;
61
+ }
62
+ /** Add N days to an ISO date string and return the new ISO date string. */
63
+ export function addDays(isoDate, days) {
64
+ const d = new Date(isoDate + 'T12:00:00Z');
65
+ d.setUTCDate(d.getUTCDate() + days);
66
+ const yyyy = d.getUTCFullYear();
67
+ const mm = String(d.getUTCMonth() + 1).padStart(2, '0');
68
+ const dd = String(d.getUTCDate()).padStart(2, '0');
69
+ return `${yyyy}-${mm}-${dd}`;
70
+ }
71
+ // ── URL Builders ──────────────────────────────────────────────────────────────
72
+ /**
73
+ * Convert a destination name to a Kayak-friendly slug.
74
+ * e.g. "Manhattan, New York" → "Manhattan,New-York"
75
+ * e.g. "Long Island City" → "Long-Island-City"
76
+ */
77
+ export function toKayakSlug(destination) {
78
+ return destination
79
+ .split(',')
80
+ .map(part => part.trim().replace(/\s+/g, '-'))
81
+ .join(',');
82
+ }
83
+ /**
84
+ * Build the search URL for each source.
85
+ */
86
+ export function buildSourceUrls(destination, checkin, checkout) {
87
+ const kayakSlug = toKayakSlug(destination);
88
+ const bookingDest = encodeURIComponent(destination);
89
+ const googleDest = destination.replace(/\s+/g, '+');
90
+ const expediaDest = encodeURIComponent(destination);
91
+ return [
92
+ {
93
+ name: 'kayak',
94
+ url: `https://www.kayak.com/hotels/${kayakSlug}/${checkin}/${checkout}?sort=price_a`,
95
+ },
96
+ {
97
+ name: 'booking',
98
+ url: `https://www.booking.com/searchresults.html?ss=${bookingDest}&checkin=${checkin}&checkout=${checkout}&order=price`,
99
+ },
100
+ {
101
+ name: 'google',
102
+ url: `https://www.google.com/travel/hotels/${googleDest}`,
103
+ },
104
+ {
105
+ name: 'expedia',
106
+ url: `https://www.expedia.com/Hotel-Search?destination=${expediaDest}&startDate=${checkin}&endDate=${checkout}&sort=PRICE_LOW_TO_HIGH`,
107
+ },
108
+ ];
109
+ }
110
+ // ── Price & Rating Parsers ────────────────────────────────────────────────────
111
+ /**
112
+ * Parse a price display string into a numeric USD value.
113
+ * Returns null if unparseable.
114
+ *
115
+ * Examples:
116
+ * "$119" → 119
117
+ * "$1,299" → 1299
118
+ * "£85" → 85 (GBP treated as USD approximation)
119
+ * "€95" → 95
120
+ * "US$200" → 200
121
+ */
122
+ export function parsePrice(raw) {
123
+ if (!raw)
124
+ return null;
125
+ // Remove currency symbols and "US$" prefix, commas, whitespace
126
+ const cleaned = raw.replace(/US\$|[$£€¥₹]/g, '').replace(/,/g, '').trim();
127
+ // Extract first number
128
+ const match = cleaned.match(/(\d+(?:\.\d+)?)/);
129
+ if (!match)
130
+ return null;
131
+ const n = parseFloat(match[1]);
132
+ return isNaN(n) ? null : n;
133
+ }
134
+ /**
135
+ * Parse a rating string into a numeric value.
136
+ * Returns null if unparseable.
137
+ *
138
+ * Examples:
139
+ * "Scored 8.4" → 8.4
140
+ * "4.2/5" → 4.2
141
+ * "4.2/5 (1.4K)" → 4.2
142
+ * "8.3" → 8.3
143
+ * "Very Good 8.6" → 8.6
144
+ */
145
+ export function parseRating(raw) {
146
+ if (!raw)
147
+ return null;
148
+ // "Scored N.N" or "Very Good N.N" etc.
149
+ const scoredMatch = raw.match(/(\d+(?:\.\d+)?)\s*\/\s*\d/);
150
+ if (scoredMatch) {
151
+ const n = parseFloat(scoredMatch[1]);
152
+ return isNaN(n) ? null : n;
153
+ }
154
+ // Extract last number (handles "Scored 8.4", "Very Good 8.6", standalone "8.3")
155
+ const numMatch = raw.match(/(\d+(?:\.\d+)?)/g);
156
+ if (!numMatch)
157
+ return null;
158
+ // Take the last number that looks like a rating (0–10 scale or 0–5 scale)
159
+ for (let i = numMatch.length - 1; i >= 0; i--) {
160
+ const n = parseFloat(numMatch[i]);
161
+ if (!isNaN(n) && n >= 0 && n <= 10)
162
+ return n;
163
+ }
164
+ return null;
165
+ }
166
+ // ── Result Normalisation ──────────────────────────────────────────────────────
167
+ /**
168
+ * Map an extracted listing item to a HotelResult, tagged with the source name.
169
+ */
170
+ function normaliseToHotelResult(item, sourceName) {
171
+ const name = item.title?.trim();
172
+ if (!name)
173
+ return null;
174
+ const priceDisplay = item.price ?? '';
175
+ const ratingDisplay = item.rating ?? '';
176
+ return {
177
+ name,
178
+ price: parsePrice(priceDisplay),
179
+ priceDisplay,
180
+ rating: parseRating(ratingDisplay),
181
+ ratingDisplay,
182
+ source: sourceName,
183
+ link: item.link ?? '',
184
+ location: item.description?.trim() || undefined,
185
+ image: item.image || undefined,
186
+ };
187
+ }
188
+ // ── Deduplication ─────────────────────────────────────────────────────────────
189
+ /**
190
+ * Deduplicate hotel results by name (case-insensitive).
191
+ * When duplicates exist, keep the one with the most data (price + rating),
192
+ * with lowest price as a tiebreaker.
193
+ */
194
+ export function deduplicateHotels(hotels) {
195
+ const byName = new Map();
196
+ for (const hotel of hotels) {
197
+ const key = hotel.name.toLowerCase().replace(/\s+/g, ' ').trim();
198
+ const existing = byName.get(key);
199
+ if (!existing) {
200
+ byName.set(key, hotel);
201
+ continue;
202
+ }
203
+ // Score = number of non-null data fields
204
+ const scoreNew = (hotel.price !== null ? 1 : 0) + (hotel.rating !== null ? 1 : 0);
205
+ const scoreOld = (existing.price !== null ? 1 : 0) + (existing.rating !== null ? 1 : 0);
206
+ if (scoreNew > scoreOld) {
207
+ byName.set(key, hotel);
208
+ }
209
+ else if (scoreNew === scoreOld) {
210
+ // Tiebreak: prefer the one with lower price (or keep existing if equal)
211
+ if (hotel.price !== null && (existing.price === null || hotel.price < existing.price)) {
212
+ byName.set(key, hotel);
213
+ }
214
+ }
215
+ }
216
+ return Array.from(byName.values());
217
+ }
218
+ // ── Sorting ───────────────────────────────────────────────────────────────────
219
+ /**
220
+ * Sort hotel results.
221
+ * - price: ascending, nulls last
222
+ * - rating: descending, nulls last
223
+ * - value: rating/price ratio, descending, nulls last
224
+ */
225
+ export function sortHotels(hotels, sort) {
226
+ const sorted = [...hotels];
227
+ switch (sort) {
228
+ case 'price':
229
+ sorted.sort((a, b) => {
230
+ if (a.price === null && b.price === null)
231
+ return 0;
232
+ if (a.price === null)
233
+ return 1;
234
+ if (b.price === null)
235
+ return -1;
236
+ return a.price - b.price;
237
+ });
238
+ break;
239
+ case 'rating':
240
+ sorted.sort((a, b) => {
241
+ if (a.rating === null && b.rating === null)
242
+ return 0;
243
+ if (a.rating === null)
244
+ return 1;
245
+ if (b.rating === null)
246
+ return -1;
247
+ return b.rating - a.rating;
248
+ });
249
+ break;
250
+ case 'value': {
251
+ const valueOf = (h) => {
252
+ if (h.price === null || h.price === 0 || h.rating === null)
253
+ return null;
254
+ return h.rating / h.price;
255
+ };
256
+ sorted.sort((a, b) => {
257
+ const va = valueOf(a);
258
+ const vb = valueOf(b);
259
+ if (va === null && vb === null)
260
+ return 0;
261
+ if (va === null)
262
+ return 1;
263
+ if (vb === null)
264
+ return -1;
265
+ return vb - va;
266
+ });
267
+ break;
268
+ }
269
+ }
270
+ return sorted;
271
+ }
272
+ // ── Main Function ─────────────────────────────────────────────────────────────
273
+ const DEFAULT_SOURCES = ['kayak', 'booking', 'google', 'expedia'];
274
+ const SIMPLE_TIMEOUT = 15_000;
275
+ const BROWSER_TIMEOUT = 30_000;
276
+ const EXPEDIA_TIMEOUT = 60_000;
277
+ /**
278
+ * Search multiple travel sites for hotels and return sorted, deduplicated results.
279
+ */
280
+ export async function searchHotels(options) {
281
+ const startTime = Date.now();
282
+ // ── Parse dates ────────────────────────────────────────────────────────────
283
+ const checkin = parseDate(options.checkin);
284
+ const rawCheckout = options.checkout;
285
+ const checkout = rawCheckout ? parseDate(rawCheckout) : addDays(checkin, 1);
286
+ const destination = options.destination;
287
+ const sort = options.sort ?? 'price';
288
+ const limit = options.limit ?? 20;
289
+ const allowedSources = new Set((options.sources ?? DEFAULT_SOURCES).map(s => s.toLowerCase()));
290
+ const useGlobalStealth = options.stealth ?? false;
291
+ const proxyUrl = options.proxy;
292
+ // ── Build source URLs ──────────────────────────────────────────────────────
293
+ const allSourceUrls = buildSourceUrls(destination, checkin, checkout).filter(s => allowedSources.has(s.name));
294
+ // ── Fetch all sources in parallel ──────────────────────────────────────────
295
+ const settled = await Promise.allSettled(allSourceUrls.map(async (src) => {
296
+ const isKayak = src.name === 'kayak';
297
+ const isBooking = src.name === 'booking';
298
+ const isExpedia = src.name === 'expedia';
299
+ const useStealth = useGlobalStealth || isKayak || isExpedia;
300
+ const useRender = useStealth || isBooking;
301
+ const timeout = isExpedia ? EXPEDIA_TIMEOUT : (useRender ? BROWSER_TIMEOUT : SIMPLE_TIMEOUT);
302
+ // Expedia is a SPA — wait for property listings to appear before extracting
303
+ const actions = isExpedia
304
+ ? [{ type: 'waitForSelector', selector: "[data-stid='property-listing'], li.uitk-spacing" }]
305
+ : undefined;
306
+ const result = await peel(src.url, {
307
+ format: 'html',
308
+ render: useRender,
309
+ stealth: useStealth,
310
+ timeout,
311
+ ...(actions ? { actions } : {}),
312
+ ...(proxyUrl ? { proxy: proxyUrl } : {}),
313
+ });
314
+ // Prefer CSS schema extraction when a schema is available for this source
315
+ const schema = findSchemaForUrl(src.url);
316
+ const hotels = [];
317
+ if (schema) {
318
+ const schemaItems = extractWithSchema(result.content, schema, src.url);
319
+ for (const item of schemaItems) {
320
+ const mapped = {
321
+ title: typeof item.title === 'string' ? item.title : undefined,
322
+ price: typeof item.price === 'string' ? item.price : undefined,
323
+ rating: typeof item.rating === 'string' ? item.rating : undefined,
324
+ link: typeof item.link === 'string' ? item.link : undefined,
325
+ image: typeof item.image === 'string' ? item.image : undefined,
326
+ description: typeof item.location === 'string' ? item.location : undefined,
327
+ };
328
+ const hotel = normaliseToHotelResult(mapped, src.name);
329
+ if (hotel)
330
+ hotels.push(hotel);
331
+ }
332
+ }
333
+ // Fall back to generic extraction if schema yielded nothing
334
+ if (hotels.length === 0) {
335
+ const listings = extractListings(result.content, src.url);
336
+ for (const item of listings) {
337
+ const hotel = normaliseToHotelResult(item, src.name);
338
+ if (hotel)
339
+ hotels.push(hotel);
340
+ }
341
+ }
342
+ return { name: src.name, hotels };
343
+ }));
344
+ // ── Collect per-source status and results ──────────────────────────────────
345
+ const sourceStats = [];
346
+ const allHotels = [];
347
+ for (let i = 0; i < allSourceUrls.length; i++) {
348
+ const src = allSourceUrls[i];
349
+ const outcome = settled[i];
350
+ if (outcome.status === 'fulfilled') {
351
+ const { hotels } = outcome.value;
352
+ sourceStats.push({ name: src.name, count: hotels.length, status: 'ok' });
353
+ allHotels.push(...hotels);
354
+ }
355
+ else {
356
+ const errMsg = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
357
+ const isBlocked = errMsg.toLowerCase().includes('blocked') ||
358
+ errMsg.toLowerCase().includes('403') ||
359
+ errMsg.toLowerCase().includes('cloudflare');
360
+ sourceStats.push({
361
+ name: src.name,
362
+ count: 0,
363
+ status: isBlocked ? 'blocked' : 'error',
364
+ error: errMsg,
365
+ });
366
+ }
367
+ }
368
+ // ── Deduplicate, sort, limit ───────────────────────────────────────────────
369
+ const unique = deduplicateHotels(allHotels);
370
+ const sorted = sortHotels(unique, sort);
371
+ const results = sorted.slice(0, limit);
372
+ const elapsed = Date.now() - startTime;
373
+ return {
374
+ destination,
375
+ checkin,
376
+ checkout,
377
+ totalResults: results.length,
378
+ results,
379
+ sources: sourceStats,
380
+ elapsed,
381
+ };
382
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Pure HTTP fetching — no browser dependencies.
3
+ * Handles connection pooling, conditional caching, SSRF validation, and simpleFetch.
4
+ */
5
+ export declare function closePool(): Promise<void>;
6
+ export declare function createAbortError(): Error;
7
+ /**
8
+ * Domains known to aggressively block datacenter IPs.
9
+ * Requests to these domains automatically route through the Webshare residential
10
+ * proxy when proxy credentials are configured (WEBSHARE_PROXY_* env vars).
11
+ */
12
+ export declare const PROXY_PREFERRED_DOMAINS: readonly string[];
13
+ /**
14
+ * Returns true if the URL's domain is on the proxy-preferred blocklist.
15
+ * Matches exact hostname (sans www.) and all subdomains.
16
+ *
17
+ * @example
18
+ * shouldUseProxy('https://www.reddit.com/r/news') // true
19
+ * shouldUseProxy('https://example.com') // false
20
+ */
21
+ export declare function shouldUseProxy(url: string): boolean;
22
+ /**
23
+ * Generate browser-like request headers tailored to the User-Agent type.
24
+ *
25
+ * - Chrome/Edge: full Sec-CH-UA + Sec-Fetch-* header set
26
+ * - Firefox: adjusted Accept, TE header, partial Sec-Fetch-* (no Sec-CH-UA)
27
+ * - Safari: minimal headers, no Sec-Fetch-* or Sec-CH-UA
28
+ * - Other: basic headers only
29
+ *
30
+ * Automatically adds a Google referer for domains where it helps bypass blocks.
31
+ *
32
+ * @param url - Target URL (used for domain-specific header additions)
33
+ * @param userAgent - User-Agent string (determines which header set is applied)
34
+ */
35
+ export declare function getStealthHeaders(url: string, userAgent: string): Record<string, string>;
36
+ /**
37
+ * SECURITY: Validate URL to prevent SSRF attacks
38
+ * Blocks localhost, private IPs, link-local, and various bypass techniques
39
+ */
40
+ export declare function validateUrl(urlString: string): void;
41
+ /**
42
+ * Validate and sanitize user agent string
43
+ */
44
+ export declare function validateUserAgent(userAgent: string): string;
45
+ export interface FetchResult {
46
+ /** Text content (HTML/JSON/XML/plain text). For binary documents, this may be an empty string. */
47
+ html: string;
48
+ /** Raw response body (used for binary documents like PDFs/DOCX). */
49
+ buffer?: Buffer;
50
+ url: string;
51
+ statusCode?: number;
52
+ screenshot?: Buffer;
53
+ /** Raw Content-Type header from the response (may include charset). */
54
+ contentType?: string;
55
+ /** Selected response headers for freshness metadata (last-modified, etag, cache-control). */
56
+ responseHeaders?: Record<string, string>;
57
+ /** Playwright page object (only available in browser/stealth mode, must be closed by caller) */
58
+ page?: import('playwright').Page;
59
+ /** Playwright browser object (only available in browser/stealth mode, must be closed by caller) */
60
+ browser?: import('playwright').Browser;
61
+ /** Auto-interact result: what cookie banners / overlays were dismissed before extraction */
62
+ autoInteract?: import('./auto-interact.js').AutoInteractResult;
63
+ }
64
+ /**
65
+ * Simple HTTP fetch using native fetch + Cheerio
66
+ * Fast and lightweight, but can be blocked by Cloudflare/bot detection
67
+ * SECURITY: Manual redirect handling with SSRF re-validation
68
+ */
69
+ export declare function simpleFetch(url: string, userAgent?: string, timeoutMs?: number, customHeaders?: Record<string, string>, abortSignal?: AbortSignal, proxy?: string, proxyContext?: {
70
+ userId?: string;
71
+ tier?: string;
72
+ }): Promise<FetchResult>;