@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.
- package/LICENSE +15 -0
- package/README.md +313 -0
- package/dist/cache.d.ts +30 -0
- package/dist/cache.js +139 -0
- package/dist/cli/commands/auth.d.ts +5 -0
- package/dist/cli/commands/auth.js +411 -0
- package/dist/cli/commands/doctor.d.ts +37 -0
- package/dist/cli/commands/doctor.js +371 -0
- package/dist/cli/commands/fetch.d.ts +6 -0
- package/dist/cli/commands/fetch.js +1345 -0
- package/dist/cli/commands/guide.d.ts +2 -0
- package/dist/cli/commands/guide.js +183 -0
- package/dist/cli/commands/interact.d.ts +5 -0
- package/dist/cli/commands/interact.js +840 -0
- package/dist/cli/commands/jobs.d.ts +5 -0
- package/dist/cli/commands/jobs.js +997 -0
- package/dist/cli/commands/monitor.d.ts +12 -0
- package/dist/cli/commands/monitor.js +197 -0
- package/dist/cli/commands/observe.d.ts +12 -0
- package/dist/cli/commands/observe.js +158 -0
- package/dist/cli/commands/screenshot.d.ts +5 -0
- package/dist/cli/commands/screenshot.js +282 -0
- package/dist/cli/commands/search.d.ts +5 -0
- package/dist/cli/commands/search.js +1021 -0
- package/dist/cli/commands/setup.d.ts +13 -0
- package/dist/cli/commands/setup.js +244 -0
- package/dist/cli/commands/skill.d.ts +15 -0
- package/dist/cli/commands/skill.js +195 -0
- package/dist/cli/utils.d.ts +84 -0
- package/dist/cli/utils.js +806 -0
- package/dist/cli-auth.d.ts +75 -0
- package/dist/cli-auth.js +369 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +99 -0
- package/dist/core/actions.d.ts +69 -0
- package/dist/core/actions.js +495 -0
- package/dist/core/agent.d.ts +98 -0
- package/dist/core/agent.js +558 -0
- package/dist/core/answer.d.ts +42 -0
- package/dist/core/answer.js +395 -0
- package/dist/core/application-tracker.d.ts +84 -0
- package/dist/core/application-tracker.js +184 -0
- package/dist/core/apply.d.ts +162 -0
- package/dist/core/apply.js +816 -0
- package/dist/core/auth-detection.d.ts +35 -0
- package/dist/core/auth-detection.js +358 -0
- package/dist/core/auto-extract.d.ts +82 -0
- package/dist/core/auto-extract.js +604 -0
- package/dist/core/auto-interact.d.ts +23 -0
- package/dist/core/auto-interact.js +246 -0
- package/dist/core/bm25-filter.d.ts +66 -0
- package/dist/core/bm25-filter.js +288 -0
- package/dist/core/branding.d.ts +54 -0
- package/dist/core/branding.js +234 -0
- package/dist/core/browser-fetch.d.ts +323 -0
- package/dist/core/browser-fetch.js +1600 -0
- package/dist/core/browser-pool.d.ts +91 -0
- package/dist/core/browser-pool.js +550 -0
- package/dist/core/budget.d.ts +42 -0
- package/dist/core/budget.js +324 -0
- package/dist/core/business-intel.d.ts +47 -0
- package/dist/core/business-intel.js +279 -0
- package/dist/core/cache.d.ts +13 -0
- package/dist/core/cache.js +121 -0
- package/dist/core/cf-worker-proxy.d.ts +32 -0
- package/dist/core/cf-worker-proxy.js +87 -0
- package/dist/core/challenge-detection.d.ts +26 -0
- package/dist/core/challenge-detection.js +468 -0
- package/dist/core/change-tracking.d.ts +75 -0
- package/dist/core/change-tracking.js +276 -0
- package/dist/core/chunker.d.ts +46 -0
- package/dist/core/chunker.js +249 -0
- package/dist/core/chunking.d.ts +42 -0
- package/dist/core/chunking.js +181 -0
- package/dist/core/circuit-breaker.d.ts +44 -0
- package/dist/core/circuit-breaker.js +85 -0
- package/dist/core/content-pruner.d.ts +47 -0
- package/dist/core/content-pruner.js +425 -0
- package/dist/core/cookie-cache.d.ts +60 -0
- package/dist/core/cookie-cache.js +163 -0
- package/dist/core/crawl-checkpoint.d.ts +54 -0
- package/dist/core/crawl-checkpoint.js +104 -0
- package/dist/core/crawler.d.ts +84 -0
- package/dist/core/crawler.js +349 -0
- package/dist/core/cross-verify.d.ts +27 -0
- package/dist/core/cross-verify.js +93 -0
- package/dist/core/deep-fetch.d.ts +74 -0
- package/dist/core/deep-fetch.js +405 -0
- package/dist/core/deep-research.d.ts +141 -0
- package/dist/core/deep-research.js +972 -0
- package/dist/core/design-analysis.d.ts +70 -0
- package/dist/core/design-analysis.js +490 -0
- package/dist/core/design-compare.d.ts +38 -0
- package/dist/core/design-compare.js +264 -0
- package/dist/core/diff.d.ts +61 -0
- package/dist/core/diff.js +289 -0
- package/dist/core/dns-cache.d.ts +20 -0
- package/dist/core/dns-cache.js +198 -0
- package/dist/core/documents.d.ts +23 -0
- package/dist/core/documents.js +123 -0
- package/dist/core/domain-memory.d.ts +66 -0
- package/dist/core/domain-memory.js +163 -0
- package/dist/core/domain-verify.d.ts +40 -0
- package/dist/core/domain-verify.js +379 -0
- package/dist/core/engine-ranker.d.ts +112 -0
- package/dist/core/engine-ranker.js +395 -0
- package/dist/core/extract-inline.d.ts +38 -0
- package/dist/core/extract-inline.js +215 -0
- package/dist/core/extract-listings.d.ts +38 -0
- package/dist/core/extract-listings.js +461 -0
- package/dist/core/extract.d.ts +9 -0
- package/dist/core/extract.js +139 -0
- package/dist/core/fetch-cache.d.ts +57 -0
- package/dist/core/fetch-cache.js +95 -0
- package/dist/core/fetcher.d.ts +13 -0
- package/dist/core/fetcher.js +12 -0
- package/dist/core/google-cache.d.ts +29 -0
- package/dist/core/google-cache.js +180 -0
- package/dist/core/google-serp-parser.d.ts +82 -0
- package/dist/core/google-serp-parser.js +287 -0
- package/dist/core/hotel-search.d.ts +122 -0
- package/dist/core/hotel-search.js +382 -0
- package/dist/core/http-fetch.d.ts +72 -0
- package/dist/core/http-fetch.js +820 -0
- package/dist/core/human.d.ts +175 -0
- package/dist/core/human.js +680 -0
- package/dist/core/image-caption.d.ts +44 -0
- package/dist/core/image-caption.js +271 -0
- package/dist/core/jobs.d.ts +75 -0
- package/dist/core/jobs.js +634 -0
- package/dist/core/json-ld.d.ts +15 -0
- package/dist/core/json-ld.js +617 -0
- package/dist/core/language-detect.d.ts +18 -0
- package/dist/core/language-detect.js +135 -0
- package/dist/core/links.d.ts +10 -0
- package/dist/core/links.js +44 -0
- package/dist/core/llm-extract.d.ts +71 -0
- package/dist/core/llm-extract.js +507 -0
- package/dist/core/llm-provider.d.ts +100 -0
- package/dist/core/llm-provider.js +702 -0
- package/dist/core/local-search.d.ts +60 -0
- package/dist/core/local-search.js +308 -0
- package/dist/core/logger.d.ts +28 -0
- package/dist/core/logger.js +104 -0
- package/dist/core/map.d.ts +33 -0
- package/dist/core/map.js +127 -0
- package/dist/core/markdown.d.ts +92 -0
- package/dist/core/markdown.js +809 -0
- package/dist/core/metadata.d.ts +34 -0
- package/dist/core/metadata.js +422 -0
- package/dist/core/observe.d.ts +113 -0
- package/dist/core/observe.js +395 -0
- package/dist/core/ocr.d.ts +12 -0
- package/dist/core/ocr.js +33 -0
- package/dist/core/paginate.d.ts +31 -0
- package/dist/core/paginate.js +106 -0
- package/dist/core/pdf.d.ts +8 -0
- package/dist/core/pdf.js +25 -0
- package/dist/core/peel-tls.d.ts +25 -0
- package/dist/core/peel-tls.js +220 -0
- package/dist/core/pipeline.d.ts +132 -0
- package/dist/core/pipeline.js +1666 -0
- package/dist/core/profiles.d.ts +61 -0
- package/dist/core/profiles.js +350 -0
- package/dist/core/prompt-guard.d.ts +30 -0
- package/dist/core/prompt-guard.js +119 -0
- package/dist/core/proxy-config.d.ts +90 -0
- package/dist/core/proxy-config.js +172 -0
- package/dist/core/quick-answer.d.ts +53 -0
- package/dist/core/quick-answer.js +833 -0
- package/dist/core/rate-governor.d.ts +80 -0
- package/dist/core/rate-governor.js +238 -0
- package/dist/core/readability.d.ts +57 -0
- package/dist/core/readability.js +533 -0
- package/dist/core/research.d.ts +66 -0
- package/dist/core/research.js +270 -0
- package/dist/core/retry.d.ts +60 -0
- package/dist/core/retry.js +119 -0
- package/dist/core/safe-browsing.d.ts +30 -0
- package/dist/core/safe-browsing.js +206 -0
- package/dist/core/schema-extraction.d.ts +66 -0
- package/dist/core/schema-extraction.js +352 -0
- package/dist/core/schema-postprocess.d.ts +32 -0
- package/dist/core/schema-postprocess.js +469 -0
- package/dist/core/schema-templates.d.ts +19 -0
- package/dist/core/schema-templates.js +143 -0
- package/dist/core/screenshot.d.ts +224 -0
- package/dist/core/screenshot.js +207 -0
- package/dist/core/search-engines.d.ts +25 -0
- package/dist/core/search-engines.js +182 -0
- package/dist/core/search-provider.d.ts +243 -0
- package/dist/core/search-provider.js +1629 -0
- package/dist/core/searxng-provider.d.ts +35 -0
- package/dist/core/searxng-provider.js +105 -0
- package/dist/core/selective-evidence.d.ts +151 -0
- package/dist/core/selective-evidence.js +389 -0
- package/dist/core/site-search.d.ts +44 -0
- package/dist/core/site-search.js +252 -0
- package/dist/core/sitemap.d.ts +23 -0
- package/dist/core/sitemap.js +105 -0
- package/dist/core/source-credibility.d.ts +29 -0
- package/dist/core/source-credibility.js +584 -0
- package/dist/core/source-scoring.d.ts +166 -0
- package/dist/core/source-scoring.js +396 -0
- package/dist/core/stemmer.d.ts +38 -0
- package/dist/core/stemmer.js +509 -0
- package/dist/core/strategies.d.ts +104 -0
- package/dist/core/strategies.js +1044 -0
- package/dist/core/strategy-hooks.d.ts +145 -0
- package/dist/core/strategy-hooks.js +74 -0
- package/dist/core/structured-extract.d.ts +43 -0
- package/dist/core/structured-extract.js +550 -0
- package/dist/core/summarize.d.ts +17 -0
- package/dist/core/summarize.js +78 -0
- package/dist/core/synonyms.d.ts +42 -0
- package/dist/core/synonyms.js +184 -0
- package/dist/core/system-monitor.d.ts +61 -0
- package/dist/core/system-monitor.js +133 -0
- package/dist/core/table-format.d.ts +30 -0
- package/dist/core/table-format.js +146 -0
- package/dist/core/threat-feeds.d.ts +23 -0
- package/dist/core/threat-feeds.js +104 -0
- package/dist/core/timing.d.ts +21 -0
- package/dist/core/timing.js +33 -0
- package/dist/core/transcript-export.d.ts +47 -0
- package/dist/core/transcript-export.js +107 -0
- package/dist/core/user-agents.d.ts +82 -0
- package/dist/core/user-agents.js +239 -0
- package/dist/core/vertical-search.d.ts +54 -0
- package/dist/core/vertical-search.js +158 -0
- package/dist/core/watch-manager.d.ts +175 -0
- package/dist/core/watch-manager.js +416 -0
- package/dist/core/watch.d.ts +101 -0
- package/dist/core/watch.js +389 -0
- package/dist/core/youtube.d.ts +130 -0
- package/dist/core/youtube.js +1175 -0
- package/dist/ee/challenge-re-export.d.ts +1 -0
- package/dist/ee/challenge-re-export.js +1 -0
- package/dist/ee/challenge-solver.d.ts +72 -0
- package/dist/ee/challenge-solver.js +720 -0
- package/dist/ee/domain-extractors.d.ts +8 -0
- package/dist/ee/domain-extractors.js +8 -0
- package/dist/ee/domain-intel.d.ts +16 -0
- package/dist/ee/domain-intel.js +133 -0
- package/dist/ee/extractors/allrecipes.d.ts +2 -0
- package/dist/ee/extractors/allrecipes.js +120 -0
- package/dist/ee/extractors/amazon.d.ts +2 -0
- package/dist/ee/extractors/amazon.js +78 -0
- package/dist/ee/extractors/arxiv.d.ts +2 -0
- package/dist/ee/extractors/arxiv.js +137 -0
- package/dist/ee/extractors/bestbuy.d.ts +2 -0
- package/dist/ee/extractors/bestbuy.js +78 -0
- package/dist/ee/extractors/carscom.d.ts +2 -0
- package/dist/ee/extractors/carscom.js +121 -0
- package/dist/ee/extractors/coingecko.d.ts +2 -0
- package/dist/ee/extractors/coingecko.js +134 -0
- package/dist/ee/extractors/craigslist.d.ts +2 -0
- package/dist/ee/extractors/craigslist.js +92 -0
- package/dist/ee/extractors/devto.d.ts +2 -0
- package/dist/ee/extractors/devto.js +135 -0
- package/dist/ee/extractors/ebay.d.ts +2 -0
- package/dist/ee/extractors/ebay.js +90 -0
- package/dist/ee/extractors/espn.d.ts +2 -0
- package/dist/ee/extractors/espn.js +260 -0
- package/dist/ee/extractors/etsy.d.ts +2 -0
- package/dist/ee/extractors/etsy.js +52 -0
- package/dist/ee/extractors/facebook.d.ts +2 -0
- package/dist/ee/extractors/facebook.js +46 -0
- package/dist/ee/extractors/github.d.ts +2 -0
- package/dist/ee/extractors/github.js +196 -0
- package/dist/ee/extractors/google-flights.d.ts +2 -0
- package/dist/ee/extractors/google-flights.js +176 -0
- package/dist/ee/extractors/hackernews.d.ts +2 -0
- package/dist/ee/extractors/hackernews.js +147 -0
- package/dist/ee/extractors/imdb.d.ts +2 -0
- package/dist/ee/extractors/imdb.js +172 -0
- package/dist/ee/extractors/index.d.ts +26 -0
- package/dist/ee/extractors/index.js +247 -0
- package/dist/ee/extractors/instagram.d.ts +2 -0
- package/dist/ee/extractors/instagram.js +102 -0
- package/dist/ee/extractors/kalshi.d.ts +2 -0
- package/dist/ee/extractors/kalshi.js +121 -0
- package/dist/ee/extractors/kayak-cars.d.ts +2 -0
- package/dist/ee/extractors/kayak-cars.js +270 -0
- package/dist/ee/extractors/linkedin.d.ts +2 -0
- package/dist/ee/extractors/linkedin.js +113 -0
- package/dist/ee/extractors/medium.d.ts +2 -0
- package/dist/ee/extractors/medium.js +130 -0
- package/dist/ee/extractors/news.d.ts +4 -0
- package/dist/ee/extractors/news.js +173 -0
- package/dist/ee/extractors/npm.d.ts +2 -0
- package/dist/ee/extractors/npm.js +86 -0
- package/dist/ee/extractors/pdf.d.ts +2 -0
- package/dist/ee/extractors/pdf.js +108 -0
- package/dist/ee/extractors/pinterest.d.ts +2 -0
- package/dist/ee/extractors/pinterest.js +34 -0
- package/dist/ee/extractors/polymarket.d.ts +2 -0
- package/dist/ee/extractors/polymarket.js +358 -0
- package/dist/ee/extractors/producthunt.d.ts +2 -0
- package/dist/ee/extractors/producthunt.js +88 -0
- package/dist/ee/extractors/pubmed.d.ts +2 -0
- package/dist/ee/extractors/pubmed.js +162 -0
- package/dist/ee/extractors/pypi.d.ts +2 -0
- package/dist/ee/extractors/pypi.js +80 -0
- package/dist/ee/extractors/reddit.d.ts +2 -0
- package/dist/ee/extractors/reddit.js +438 -0
- package/dist/ee/extractors/redfin.d.ts +2 -0
- package/dist/ee/extractors/redfin.js +156 -0
- package/dist/ee/extractors/semanticscholar.d.ts +2 -0
- package/dist/ee/extractors/semanticscholar.js +131 -0
- package/dist/ee/extractors/shared.d.ts +12 -0
- package/dist/ee/extractors/shared.js +76 -0
- package/dist/ee/extractors/soundcloud.d.ts +2 -0
- package/dist/ee/extractors/soundcloud.js +34 -0
- package/dist/ee/extractors/sportsbetting.d.ts +2 -0
- package/dist/ee/extractors/sportsbetting.js +37 -0
- package/dist/ee/extractors/spotify.d.ts +2 -0
- package/dist/ee/extractors/spotify.js +34 -0
- package/dist/ee/extractors/stackoverflow.d.ts +2 -0
- package/dist/ee/extractors/stackoverflow.js +61 -0
- package/dist/ee/extractors/substack.d.ts +2 -0
- package/dist/ee/extractors/substack.js +115 -0
- package/dist/ee/extractors/substackroot.d.ts +2 -0
- package/dist/ee/extractors/substackroot.js +46 -0
- package/dist/ee/extractors/tiktok.d.ts +2 -0
- package/dist/ee/extractors/tiktok.js +29 -0
- package/dist/ee/extractors/tradingview.d.ts +2 -0
- package/dist/ee/extractors/tradingview.js +182 -0
- package/dist/ee/extractors/twitch.d.ts +2 -0
- package/dist/ee/extractors/twitch.js +36 -0
- package/dist/ee/extractors/twitter.d.ts +2 -0
- package/dist/ee/extractors/twitter.js +327 -0
- package/dist/ee/extractors/types.d.ts +14 -0
- package/dist/ee/extractors/types.js +1 -0
- package/dist/ee/extractors/walmart.d.ts +2 -0
- package/dist/ee/extractors/walmart.js +50 -0
- package/dist/ee/extractors/weather.d.ts +2 -0
- package/dist/ee/extractors/weather.js +133 -0
- package/dist/ee/extractors/wikipedia.d.ts +4 -0
- package/dist/ee/extractors/wikipedia.js +235 -0
- package/dist/ee/extractors/yelp.d.ts +2 -0
- package/dist/ee/extractors/yelp.js +216 -0
- package/dist/ee/extractors/youtube.d.ts +2 -0
- package/dist/ee/extractors/youtube.js +189 -0
- package/dist/ee/extractors/zillow.d.ts +54 -0
- package/dist/ee/extractors/zillow.js +247 -0
- package/dist/ee/extractors-re-export.d.ts +1 -0
- package/dist/ee/extractors-re-export.js +1 -0
- package/dist/ee/premium-hooks.d.ts +20 -0
- package/dist/ee/premium-hooks.js +50 -0
- package/dist/ee/spa-detection.d.ts +2 -0
- package/dist/ee/spa-detection.js +2 -0
- package/dist/ee/stability.d.ts +4 -0
- package/dist/ee/stability.js +29 -0
- package/dist/ee/swr-cache.d.ts +14 -0
- package/dist/ee/swr-cache.js +34 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.js +291 -0
- package/dist/integrations/index.d.ts +2 -0
- package/dist/integrations/index.js +2 -0
- package/dist/integrations/langchain.d.ts +64 -0
- package/dist/integrations/langchain.js +115 -0
- package/dist/integrations/llamaindex.d.ts +50 -0
- package/dist/integrations/llamaindex.js +91 -0
- package/dist/mcp/handlers/act.d.ts +5 -0
- package/dist/mcp/handlers/act.js +34 -0
- package/dist/mcp/handlers/definitions.d.ts +6 -0
- package/dist/mcp/handlers/definitions.js +395 -0
- package/dist/mcp/handlers/extract.d.ts +7 -0
- package/dist/mcp/handlers/extract.js +135 -0
- package/dist/mcp/handlers/fetch.d.ts +6 -0
- package/dist/mcp/handlers/fetch.js +98 -0
- package/dist/mcp/handlers/find.d.ts +5 -0
- package/dist/mcp/handlers/find.js +137 -0
- package/dist/mcp/handlers/index.d.ts +13 -0
- package/dist/mcp/handlers/index.js +63 -0
- package/dist/mcp/handlers/legacy.d.ts +25 -0
- package/dist/mcp/handlers/legacy.js +450 -0
- package/dist/mcp/handlers/meta.d.ts +6 -0
- package/dist/mcp/handlers/meta.js +40 -0
- package/dist/mcp/handlers/monitor.d.ts +5 -0
- package/dist/mcp/handlers/monitor.js +41 -0
- package/dist/mcp/handlers/observe.d.ts +8 -0
- package/dist/mcp/handlers/observe.js +37 -0
- package/dist/mcp/handlers/read.d.ts +6 -0
- package/dist/mcp/handlers/read.js +78 -0
- package/dist/mcp/handlers/see.d.ts +5 -0
- package/dist/mcp/handlers/see.js +75 -0
- package/dist/mcp/handlers/types.d.ts +29 -0
- package/dist/mcp/handlers/types.js +28 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.js +108 -0
- package/dist/mcp/smart-router.d.ts +23 -0
- package/dist/mcp/smart-router.js +178 -0
- package/dist/server/app.d.ts +14 -0
- package/dist/server/app.js +632 -0
- package/dist/server/auth-store.d.ts +28 -0
- package/dist/server/auth-store.js +88 -0
- package/dist/server/bull-queues.d.ts +60 -0
- package/dist/server/bull-queues.js +90 -0
- package/dist/server/email-service.d.ts +55 -0
- package/dist/server/email-service.js +291 -0
- package/dist/server/job-queue.d.ts +100 -0
- package/dist/server/job-queue.js +145 -0
- package/dist/server/logger.d.ts +10 -0
- package/dist/server/logger.js +37 -0
- package/dist/server/middleware/audit-log.d.ts +14 -0
- package/dist/server/middleware/audit-log.js +73 -0
- package/dist/server/middleware/auth.d.ts +35 -0
- package/dist/server/middleware/auth.js +225 -0
- package/dist/server/middleware/rate-limit.d.ts +50 -0
- package/dist/server/middleware/rate-limit.js +270 -0
- package/dist/server/middleware/scope-guard.d.ts +25 -0
- package/dist/server/middleware/scope-guard.js +45 -0
- package/dist/server/middleware/url-validator.d.ts +15 -0
- package/dist/server/middleware/url-validator.js +201 -0
- package/dist/server/openapi.yaml +6418 -0
- package/dist/server/pg-auth-store.d.ts +146 -0
- package/dist/server/pg-auth-store.js +576 -0
- package/dist/server/pg-job-queue.d.ts +59 -0
- package/dist/server/pg-job-queue.js +375 -0
- package/dist/server/routes/activity.d.ts +6 -0
- package/dist/server/routes/activity.js +79 -0
- package/dist/server/routes/admin-active.d.ts +7 -0
- package/dist/server/routes/admin-active.js +120 -0
- package/dist/server/routes/admin-stats.d.ts +7 -0
- package/dist/server/routes/admin-stats.js +176 -0
- package/dist/server/routes/agent.d.ts +24 -0
- package/dist/server/routes/agent.js +480 -0
- package/dist/server/routes/answer.d.ts +5 -0
- package/dist/server/routes/answer.js +125 -0
- package/dist/server/routes/ask.d.ts +28 -0
- package/dist/server/routes/ask.js +295 -0
- package/dist/server/routes/batch.d.ts +6 -0
- package/dist/server/routes/batch.js +493 -0
- package/dist/server/routes/cache-warm.d.ts +25 -0
- package/dist/server/routes/cache-warm.js +212 -0
- package/dist/server/routes/cli-usage.d.ts +6 -0
- package/dist/server/routes/cli-usage.js +127 -0
- package/dist/server/routes/compat.d.ts +23 -0
- package/dist/server/routes/compat.js +652 -0
- package/dist/server/routes/crawl.d.ts +13 -0
- package/dist/server/routes/crawl.js +287 -0
- package/dist/server/routes/deep-fetch.d.ts +8 -0
- package/dist/server/routes/deep-fetch.js +57 -0
- package/dist/server/routes/deep-research.d.ts +11 -0
- package/dist/server/routes/deep-research.js +232 -0
- package/dist/server/routes/demo.d.ts +24 -0
- package/dist/server/routes/demo.js +517 -0
- package/dist/server/routes/do.d.ts +8 -0
- package/dist/server/routes/do.js +72 -0
- package/dist/server/routes/extract.d.ts +14 -0
- package/dist/server/routes/extract.js +325 -0
- package/dist/server/routes/feed.d.ts +15 -0
- package/dist/server/routes/feed.js +311 -0
- package/dist/server/routes/fetch-queue.d.ts +13 -0
- package/dist/server/routes/fetch-queue.js +357 -0
- package/dist/server/routes/fetch.d.ts +7 -0
- package/dist/server/routes/fetch.js +1274 -0
- package/dist/server/routes/go.d.ts +14 -0
- package/dist/server/routes/go.js +81 -0
- package/dist/server/routes/health.d.ts +11 -0
- package/dist/server/routes/health.js +141 -0
- package/dist/server/routes/jobs.d.ts +7 -0
- package/dist/server/routes/jobs.js +574 -0
- package/dist/server/routes/map.d.ts +11 -0
- package/dist/server/routes/map.js +116 -0
- package/dist/server/routes/mcp.d.ts +14 -0
- package/dist/server/routes/mcp.js +197 -0
- package/dist/server/routes/metrics.d.ts +37 -0
- package/dist/server/routes/metrics.js +149 -0
- package/dist/server/routes/oauth.d.ts +9 -0
- package/dist/server/routes/oauth.js +396 -0
- package/dist/server/routes/playground.d.ts +17 -0
- package/dist/server/routes/playground.js +283 -0
- package/dist/server/routes/reader.d.ts +18 -0
- package/dist/server/routes/reader.js +192 -0
- package/dist/server/routes/research.d.ts +14 -0
- package/dist/server/routes/research.js +482 -0
- package/dist/server/routes/screenshot.d.ts +22 -0
- package/dist/server/routes/screenshot.js +820 -0
- package/dist/server/routes/search.d.ts +6 -0
- package/dist/server/routes/search.js +874 -0
- package/dist/server/routes/session.d.ts +17 -0
- package/dist/server/routes/session.js +548 -0
- package/dist/server/routes/share.d.ts +18 -0
- package/dist/server/routes/share.js +462 -0
- package/dist/server/routes/smart-search/handlers/cars.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/cars.js +102 -0
- package/dist/server/routes/smart-search/handlers/flights.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/flights.js +72 -0
- package/dist/server/routes/smart-search/handlers/general.d.ts +13 -0
- package/dist/server/routes/smart-search/handlers/general.js +717 -0
- package/dist/server/routes/smart-search/handlers/hotels.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/hotels.js +88 -0
- package/dist/server/routes/smart-search/handlers/products.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/products.js +1309 -0
- package/dist/server/routes/smart-search/handlers/rental.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/rental.js +154 -0
- package/dist/server/routes/smart-search/handlers/restaurants.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/restaurants.js +225 -0
- package/dist/server/routes/smart-search/handlers/transit-verdict.d.ts +41 -0
- package/dist/server/routes/smart-search/handlers/transit-verdict.js +224 -0
- package/dist/server/routes/smart-search/index.d.ts +19 -0
- package/dist/server/routes/smart-search/index.js +546 -0
- package/dist/server/routes/smart-search/intent.d.ts +3 -0
- package/dist/server/routes/smart-search/intent.js +264 -0
- package/dist/server/routes/smart-search/llm.d.ts +16 -0
- package/dist/server/routes/smart-search/llm.js +70 -0
- package/dist/server/routes/smart-search/sources/reddit.d.ts +18 -0
- package/dist/server/routes/smart-search/sources/reddit.js +34 -0
- package/dist/server/routes/smart-search/sources/yelp.d.ts +25 -0
- package/dist/server/routes/smart-search/sources/yelp.js +171 -0
- package/dist/server/routes/smart-search/sources/youtube.d.ts +8 -0
- package/dist/server/routes/smart-search/sources/youtube.js +9 -0
- package/dist/server/routes/smart-search/types.d.ts +81 -0
- package/dist/server/routes/smart-search/types.js +1 -0
- package/dist/server/routes/smart-search/utils.d.ts +20 -0
- package/dist/server/routes/smart-search/utils.js +146 -0
- package/dist/server/routes/stats.d.ts +6 -0
- package/dist/server/routes/stats.js +71 -0
- package/dist/server/routes/stripe.d.ts +15 -0
- package/dist/server/routes/stripe.js +296 -0
- package/dist/server/routes/transcript-export.d.ts +10 -0
- package/dist/server/routes/transcript-export.js +178 -0
- package/dist/server/routes/usage.d.ts +9 -0
- package/dist/server/routes/usage.js +279 -0
- package/dist/server/routes/users.d.ts +8 -0
- package/dist/server/routes/users.js +1867 -0
- package/dist/server/routes/watch.d.ts +15 -0
- package/dist/server/routes/watch.js +309 -0
- package/dist/server/routes/webhooks.d.ts +26 -0
- package/dist/server/routes/webhooks.js +170 -0
- package/dist/server/routes/youtube.d.ts +6 -0
- package/dist/server/routes/youtube.js +130 -0
- package/dist/server/sentry.d.ts +14 -0
- package/dist/server/sentry.js +104 -0
- package/dist/server/types.d.ts +15 -0
- package/dist/server/types.js +7 -0
- package/dist/server/utils/response.d.ts +44 -0
- package/dist/server/utils/response.js +69 -0
- package/dist/server/utils/sse.d.ts +22 -0
- package/dist/server/utils/sse.js +38 -0
- package/dist/types.d.ts +552 -0
- package/dist/types.js +39 -0
- package/llms.txt +105 -0
- package/package.json +189 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL-backed job queue for production deployments
|
|
3
|
+
* Uses same Pool pattern as pg-auth-store.ts
|
|
4
|
+
*/
|
|
5
|
+
import pg from 'pg';
|
|
6
|
+
import { randomUUID } from 'crypto';
|
|
7
|
+
const { Pool } = pg;
|
|
8
|
+
export class PostgresJobQueue {
|
|
9
|
+
pool;
|
|
10
|
+
cleanupInterval;
|
|
11
|
+
constructor(connectionString) {
|
|
12
|
+
const dbUrl = connectionString || process.env.DATABASE_URL;
|
|
13
|
+
if (!dbUrl) {
|
|
14
|
+
throw new Error('DATABASE_URL environment variable is required for PostgresJobQueue');
|
|
15
|
+
}
|
|
16
|
+
this.pool = new Pool({
|
|
17
|
+
connectionString: dbUrl,
|
|
18
|
+
// TLS: enabled when DATABASE_URL contains sslmode=require.
|
|
19
|
+
// Secure by default (rejectUnauthorized: true); set PG_REJECT_UNAUTHORIZED=false
|
|
20
|
+
// only for managed DBs (Render/Neon/Supabase) that use self-signed certs.
|
|
21
|
+
ssl: process.env.DATABASE_URL?.includes('sslmode=require')
|
|
22
|
+
? { rejectUnauthorized: process.env.PG_REJECT_UNAUTHORIZED !== 'false' }
|
|
23
|
+
: undefined,
|
|
24
|
+
max: 20,
|
|
25
|
+
idleTimeoutMillis: 30000,
|
|
26
|
+
connectionTimeoutMillis: 10000,
|
|
27
|
+
});
|
|
28
|
+
// Initialize table
|
|
29
|
+
this.initTable().catch(err => {
|
|
30
|
+
console.error('Failed to initialize jobs table:', err);
|
|
31
|
+
});
|
|
32
|
+
// Clean up old completed/failed jobs every hour
|
|
33
|
+
this.cleanupInterval = setInterval(() => {
|
|
34
|
+
this.cleanupOldJobs().catch(err => {
|
|
35
|
+
console.error('Failed to cleanup old jobs:', err);
|
|
36
|
+
});
|
|
37
|
+
}, 60 * 60 * 1000);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create jobs table if it doesn't exist
|
|
41
|
+
*/
|
|
42
|
+
async initTable() {
|
|
43
|
+
try {
|
|
44
|
+
await this.pool.query(`
|
|
45
|
+
CREATE TABLE IF NOT EXISTS jobs (
|
|
46
|
+
id TEXT PRIMARY KEY,
|
|
47
|
+
type TEXT NOT NULL,
|
|
48
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
49
|
+
progress INTEGER DEFAULT 0,
|
|
50
|
+
data JSONB,
|
|
51
|
+
error TEXT,
|
|
52
|
+
total INTEGER DEFAULT 0,
|
|
53
|
+
completed INTEGER DEFAULT 0,
|
|
54
|
+
credits_used INTEGER DEFAULT 0,
|
|
55
|
+
owner_id TEXT,
|
|
56
|
+
webhook_url TEXT,
|
|
57
|
+
webhook_events JSONB,
|
|
58
|
+
webhook_metadata JSONB,
|
|
59
|
+
webhook_secret TEXT,
|
|
60
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
61
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
62
|
+
expires_at TIMESTAMPTZ
|
|
63
|
+
)
|
|
64
|
+
`);
|
|
65
|
+
// Add owner_id column if it doesn't exist (migration for existing tables)
|
|
66
|
+
await this.pool.query(`
|
|
67
|
+
DO $$ BEGIN
|
|
68
|
+
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS owner_id TEXT;
|
|
69
|
+
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS webhook_delivery JSONB;
|
|
70
|
+
EXCEPTION WHEN others THEN NULL;
|
|
71
|
+
END $$;
|
|
72
|
+
`);
|
|
73
|
+
// Add index on status and created_at for faster queries
|
|
74
|
+
await this.pool.query(`
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_jobs_status_created
|
|
76
|
+
ON jobs(status, created_at DESC)
|
|
77
|
+
`);
|
|
78
|
+
// Add index on type for filtering
|
|
79
|
+
await this.pool.query(`
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_jobs_type
|
|
81
|
+
ON jobs(type)
|
|
82
|
+
`);
|
|
83
|
+
// Add index on expires_at for cleanup
|
|
84
|
+
await this.pool.query(`
|
|
85
|
+
CREATE INDEX IF NOT EXISTS idx_jobs_expires
|
|
86
|
+
ON jobs(expires_at)
|
|
87
|
+
`);
|
|
88
|
+
// Add index on owner_id for per-user job filtering
|
|
89
|
+
await this.pool.query(`
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_jobs_owner
|
|
91
|
+
ON jobs(owner_id)
|
|
92
|
+
`);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error('Failed to create jobs table:', error);
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Create a new job
|
|
101
|
+
*/
|
|
102
|
+
async createJob(type, webhook, ownerId) {
|
|
103
|
+
const id = randomUUID();
|
|
104
|
+
const now = new Date();
|
|
105
|
+
const expiresAt = new Date(now.getTime() + 25 * 60 * 60 * 1000); // 25h from now
|
|
106
|
+
try {
|
|
107
|
+
await this.pool.query(`INSERT INTO jobs (
|
|
108
|
+
id, type, status, progress, data, total, completed, credits_used,
|
|
109
|
+
owner_id, webhook_url, webhook_events, webhook_metadata, webhook_secret,
|
|
110
|
+
created_at, updated_at, expires_at
|
|
111
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)`, [
|
|
112
|
+
id,
|
|
113
|
+
type,
|
|
114
|
+
'queued',
|
|
115
|
+
0,
|
|
116
|
+
JSON.stringify([]),
|
|
117
|
+
0,
|
|
118
|
+
0,
|
|
119
|
+
0,
|
|
120
|
+
ownerId || null,
|
|
121
|
+
webhook?.url || null,
|
|
122
|
+
webhook?.events ? JSON.stringify(webhook.events) : null,
|
|
123
|
+
webhook?.metadata ? JSON.stringify(webhook.metadata) : null,
|
|
124
|
+
webhook?.secret || null,
|
|
125
|
+
now,
|
|
126
|
+
now,
|
|
127
|
+
expiresAt,
|
|
128
|
+
]);
|
|
129
|
+
return {
|
|
130
|
+
id,
|
|
131
|
+
type,
|
|
132
|
+
status: 'queued',
|
|
133
|
+
progress: 0,
|
|
134
|
+
total: 0,
|
|
135
|
+
completed: 0,
|
|
136
|
+
creditsUsed: 0,
|
|
137
|
+
data: [],
|
|
138
|
+
webhook,
|
|
139
|
+
ownerId,
|
|
140
|
+
createdAt: now.toISOString(),
|
|
141
|
+
updatedAt: now.toISOString(),
|
|
142
|
+
expiresAt: expiresAt.toISOString(),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.error('Failed to create job:', error);
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get a job by ID
|
|
152
|
+
*/
|
|
153
|
+
async getJob(id) {
|
|
154
|
+
try {
|
|
155
|
+
const result = await this.pool.query(`SELECT * FROM jobs WHERE id = $1`, [id]);
|
|
156
|
+
if (result.rows.length === 0) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
return this.mapRowToJob(result.rows[0]);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error('Failed to get job:', error);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Update a job
|
|
168
|
+
*/
|
|
169
|
+
async updateJob(id, update) {
|
|
170
|
+
try {
|
|
171
|
+
const job = await this.getJob(id);
|
|
172
|
+
if (!job)
|
|
173
|
+
return;
|
|
174
|
+
const updates = [];
|
|
175
|
+
const values = [];
|
|
176
|
+
let paramIndex = 1;
|
|
177
|
+
// Map Job fields to database columns
|
|
178
|
+
if (update.status !== undefined) {
|
|
179
|
+
updates.push(`status = $${paramIndex++}`);
|
|
180
|
+
values.push(update.status);
|
|
181
|
+
}
|
|
182
|
+
if (update.progress !== undefined) {
|
|
183
|
+
updates.push(`progress = $${paramIndex++}`);
|
|
184
|
+
values.push(update.progress);
|
|
185
|
+
}
|
|
186
|
+
if (update.total !== undefined) {
|
|
187
|
+
updates.push(`total = $${paramIndex++}`);
|
|
188
|
+
values.push(update.total);
|
|
189
|
+
}
|
|
190
|
+
if (update.completed !== undefined) {
|
|
191
|
+
updates.push(`completed = $${paramIndex++}`);
|
|
192
|
+
values.push(update.completed);
|
|
193
|
+
}
|
|
194
|
+
if (update.creditsUsed !== undefined) {
|
|
195
|
+
updates.push(`credits_used = $${paramIndex++}`);
|
|
196
|
+
values.push(update.creditsUsed);
|
|
197
|
+
}
|
|
198
|
+
if (update.data !== undefined) {
|
|
199
|
+
updates.push(`data = $${paramIndex++}`);
|
|
200
|
+
values.push(JSON.stringify(update.data));
|
|
201
|
+
}
|
|
202
|
+
if (update.error !== undefined) {
|
|
203
|
+
updates.push(`error = $${paramIndex++}`);
|
|
204
|
+
values.push(update.error);
|
|
205
|
+
}
|
|
206
|
+
if (update.webhookDelivery !== undefined) {
|
|
207
|
+
updates.push(`webhook_delivery = $${paramIndex++}`);
|
|
208
|
+
values.push(JSON.stringify(update.webhookDelivery));
|
|
209
|
+
}
|
|
210
|
+
// Always update updated_at
|
|
211
|
+
updates.push(`updated_at = $${paramIndex++}`);
|
|
212
|
+
values.push(new Date());
|
|
213
|
+
// When job completes/fails, set expiration to 24h from now
|
|
214
|
+
if (update.status === 'completed' || update.status === 'failed' || update.status === 'cancelled') {
|
|
215
|
+
const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000);
|
|
216
|
+
updates.push(`expires_at = $${paramIndex++}`);
|
|
217
|
+
values.push(expiresAt);
|
|
218
|
+
}
|
|
219
|
+
// Calculate progress percentage if total and completed are provided
|
|
220
|
+
const newTotal = update.total ?? job.total;
|
|
221
|
+
const newCompleted = update.completed ?? job.completed;
|
|
222
|
+
if (newTotal > 0) {
|
|
223
|
+
const progress = Math.round((newCompleted / newTotal) * 100);
|
|
224
|
+
if (!updates.some(u => u.startsWith('progress'))) {
|
|
225
|
+
updates.push(`progress = $${paramIndex++}`);
|
|
226
|
+
values.push(progress);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (updates.length === 0)
|
|
230
|
+
return;
|
|
231
|
+
// Add job ID as the last parameter
|
|
232
|
+
values.push(id);
|
|
233
|
+
const sql = `UPDATE jobs SET ${updates.join(', ')} WHERE id = $${paramIndex}`;
|
|
234
|
+
await this.pool.query(sql, values);
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
console.error('Failed to update job:', error);
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Cancel a job
|
|
243
|
+
*/
|
|
244
|
+
async cancelJob(id) {
|
|
245
|
+
try {
|
|
246
|
+
const job = await this.getJob(id);
|
|
247
|
+
if (!job)
|
|
248
|
+
return false;
|
|
249
|
+
// Can only cancel queued or processing jobs
|
|
250
|
+
if (job.status !== 'queued' && job.status !== 'processing') {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
await this.updateJob(id, {
|
|
254
|
+
status: 'cancelled',
|
|
255
|
+
});
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
console.error('Failed to cancel job:', error);
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* List jobs with optional filters
|
|
265
|
+
*/
|
|
266
|
+
async listJobs(options) {
|
|
267
|
+
try {
|
|
268
|
+
const conditions = [];
|
|
269
|
+
const values = [];
|
|
270
|
+
let paramIndex = 1;
|
|
271
|
+
if (options?.ownerId) {
|
|
272
|
+
conditions.push(`owner_id = $${paramIndex++}`);
|
|
273
|
+
values.push(options.ownerId);
|
|
274
|
+
}
|
|
275
|
+
if (options?.type) {
|
|
276
|
+
conditions.push(`type = $${paramIndex++}`);
|
|
277
|
+
values.push(options.type);
|
|
278
|
+
}
|
|
279
|
+
if (options?.status) {
|
|
280
|
+
conditions.push(`status = $${paramIndex++}`);
|
|
281
|
+
values.push(options.status);
|
|
282
|
+
}
|
|
283
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
284
|
+
const limit = options?.limit || 50;
|
|
285
|
+
const sql = `
|
|
286
|
+
SELECT * FROM jobs
|
|
287
|
+
${whereClause}
|
|
288
|
+
ORDER BY created_at DESC
|
|
289
|
+
LIMIT $${paramIndex}
|
|
290
|
+
`;
|
|
291
|
+
values.push(limit);
|
|
292
|
+
const result = await this.pool.query(sql, values);
|
|
293
|
+
return result.rows.map(row => this.mapRowToJob(row));
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
console.error('Failed to list jobs:', error);
|
|
297
|
+
return [];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Remove expired jobs (called periodically)
|
|
302
|
+
*/
|
|
303
|
+
async cleanExpired() {
|
|
304
|
+
try {
|
|
305
|
+
await this.pool.query(`DELETE FROM jobs WHERE expires_at < NOW()`);
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
console.error('Failed to clean expired jobs:', error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Remove old completed/failed jobs (>7 days)
|
|
313
|
+
*/
|
|
314
|
+
async cleanupOldJobs() {
|
|
315
|
+
try {
|
|
316
|
+
// Remove expired jobs
|
|
317
|
+
await this.cleanExpired();
|
|
318
|
+
// Remove completed/failed jobs older than 7 days
|
|
319
|
+
await this.pool.query(`DELETE FROM jobs
|
|
320
|
+
WHERE (status = 'completed' OR status = 'failed' OR status = 'cancelled')
|
|
321
|
+
AND updated_at < NOW() - INTERVAL '7 days'`);
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
console.error('Failed to cleanup old jobs:', error);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Map database row to Job object
|
|
329
|
+
*/
|
|
330
|
+
mapRowToJob(row) {
|
|
331
|
+
const webhook = row.webhook_url
|
|
332
|
+
? {
|
|
333
|
+
url: row.webhook_url,
|
|
334
|
+
events: row.webhook_events || [],
|
|
335
|
+
metadata: row.webhook_metadata || undefined,
|
|
336
|
+
secret: row.webhook_secret || undefined,
|
|
337
|
+
}
|
|
338
|
+
: undefined;
|
|
339
|
+
const webhookDelivery = row.webhook_delivery
|
|
340
|
+
? (typeof row.webhook_delivery === 'string'
|
|
341
|
+
? JSON.parse(row.webhook_delivery)
|
|
342
|
+
: row.webhook_delivery)
|
|
343
|
+
: undefined;
|
|
344
|
+
return {
|
|
345
|
+
id: row.id,
|
|
346
|
+
type: row.type,
|
|
347
|
+
status: row.status,
|
|
348
|
+
progress: row.progress || 0,
|
|
349
|
+
total: row.total || 0,
|
|
350
|
+
completed: row.completed || 0,
|
|
351
|
+
creditsUsed: row.credits_used || 0,
|
|
352
|
+
data: row.data || [],
|
|
353
|
+
error: row.error || undefined,
|
|
354
|
+
webhook,
|
|
355
|
+
webhookDelivery,
|
|
356
|
+
ownerId: row.owner_id || undefined,
|
|
357
|
+
createdAt: row.created_at.toISOString(),
|
|
358
|
+
updatedAt: row.updated_at.toISOString(),
|
|
359
|
+
expiresAt: row.expires_at.toISOString(),
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Clean up interval on shutdown
|
|
364
|
+
*/
|
|
365
|
+
destroy() {
|
|
366
|
+
clearInterval(this.cleanupInterval);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Close the database pool
|
|
370
|
+
*/
|
|
371
|
+
async close() {
|
|
372
|
+
this.destroy();
|
|
373
|
+
await this.pool.end();
|
|
374
|
+
}
|
|
375
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity endpoint - provides recent API request history
|
|
3
|
+
*/
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
import { PostgresAuthStore } from '../pg-auth-store.js';
|
|
6
|
+
export function createActivityRouter(authStore) {
|
|
7
|
+
const router = Router();
|
|
8
|
+
router.get('/v1/activity', async (req, res) => {
|
|
9
|
+
try {
|
|
10
|
+
// Require authentication (API key or JWT session token)
|
|
11
|
+
const userId = req.auth?.keyInfo?.accountId || req.user?.userId;
|
|
12
|
+
if (!userId) {
|
|
13
|
+
res.status(401).json({ success: false, error: { type: 'unauthorized', message: 'Authentication required', hint: 'Get a free API key at https://app.webpeel.dev/keys', docs: 'https://webpeel.dev/docs/errors#unauthorized' }, requestId: req.requestId });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
// Only works with PostgreSQL backend
|
|
17
|
+
if (!(authStore instanceof PostgresAuthStore)) {
|
|
18
|
+
res.status(501).json({
|
|
19
|
+
success: false,
|
|
20
|
+
error: {
|
|
21
|
+
type: 'not_implemented',
|
|
22
|
+
message: 'Activity endpoint requires PostgreSQL backend',
|
|
23
|
+
docs: 'https://webpeel.dev/docs/errors#not_implemented',
|
|
24
|
+
},
|
|
25
|
+
requestId: req.requestId,
|
|
26
|
+
});
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Access pool via any cast (pool is private but we need direct DB access)
|
|
30
|
+
const pgStore = authStore;
|
|
31
|
+
const limit = Math.min(parseInt(req.query.limit) || 50, 100);
|
|
32
|
+
// Get recent requests from usage_logs
|
|
33
|
+
const activityQuery = `
|
|
34
|
+
SELECT
|
|
35
|
+
id,
|
|
36
|
+
url,
|
|
37
|
+
endpoint,
|
|
38
|
+
method,
|
|
39
|
+
status_code,
|
|
40
|
+
processing_time_ms,
|
|
41
|
+
tokens_used,
|
|
42
|
+
ip_address,
|
|
43
|
+
created_at
|
|
44
|
+
FROM usage_logs
|
|
45
|
+
WHERE user_id = $1
|
|
46
|
+
ORDER BY created_at DESC
|
|
47
|
+
LIMIT $2
|
|
48
|
+
`;
|
|
49
|
+
const result = await pgStore.pool.query(activityQuery, [userId, limit]);
|
|
50
|
+
// Transform to frontend format
|
|
51
|
+
const requests = result.rows.map((row) => ({
|
|
52
|
+
id: row.id,
|
|
53
|
+
url: row.url || 'N/A',
|
|
54
|
+
endpoint: row.endpoint || null,
|
|
55
|
+
status: (row.status_code >= 200 && row.status_code < 300) ? 'success' : 'error',
|
|
56
|
+
responseTime: row.processing_time_ms || 0,
|
|
57
|
+
mode: row.method || 'basic',
|
|
58
|
+
timestamp: row.created_at,
|
|
59
|
+
tokensUsed: row.tokens_used || null,
|
|
60
|
+
ipAddress: row.ip_address || null,
|
|
61
|
+
statusCode: row.status_code || null,
|
|
62
|
+
}));
|
|
63
|
+
res.json({ requests });
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('Activity error:', error);
|
|
67
|
+
res.status(500).json({
|
|
68
|
+
success: false,
|
|
69
|
+
error: {
|
|
70
|
+
type: 'internal_error',
|
|
71
|
+
message: 'Failed to retrieve activity',
|
|
72
|
+
docs: 'https://webpeel.dev/docs/errors#internal_error',
|
|
73
|
+
},
|
|
74
|
+
requestId: req.requestId,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return router;
|
|
79
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin active-users endpoint — admin tier only
|
|
3
|
+
*
|
|
4
|
+
* GET /v1/admin/active — currently active API users (24h + 7d windows)
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
import pg from 'pg';
|
|
8
|
+
const { Pool } = pg;
|
|
9
|
+
function noDB(req, res) {
|
|
10
|
+
res.status(501).json({
|
|
11
|
+
success: false,
|
|
12
|
+
error: {
|
|
13
|
+
type: 'not_configured',
|
|
14
|
+
message: 'Admin endpoints require PostgreSQL backend',
|
|
15
|
+
docs: 'https://webpeel.dev/docs/errors#not_configured',
|
|
16
|
+
},
|
|
17
|
+
requestId: req.requestId,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function adminOnly(req, res) {
|
|
21
|
+
if (req.auth?.tier !== 'admin') {
|
|
22
|
+
res.status(403).json({
|
|
23
|
+
success: false,
|
|
24
|
+
error: { type: 'forbidden', message: 'Admin access required', docs: 'https://webpeel.dev/docs/authentication' },
|
|
25
|
+
requestId: req.requestId,
|
|
26
|
+
});
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
export function createAdminActiveRouter() {
|
|
32
|
+
const router = Router();
|
|
33
|
+
const dbUrl = process.env.DATABASE_URL;
|
|
34
|
+
if (!dbUrl) {
|
|
35
|
+
router.get('/v1/admin/active', noDB);
|
|
36
|
+
return router;
|
|
37
|
+
}
|
|
38
|
+
const pool = new Pool({
|
|
39
|
+
connectionString: dbUrl,
|
|
40
|
+
ssl: dbUrl.includes('sslmode=require')
|
|
41
|
+
? { rejectUnauthorized: process.env.PG_REJECT_UNAUTHORIZED !== 'false' }
|
|
42
|
+
: undefined,
|
|
43
|
+
max: 5,
|
|
44
|
+
});
|
|
45
|
+
router.get('/v1/admin/active', async (req, res) => {
|
|
46
|
+
if (!adminOnly(req, res))
|
|
47
|
+
return;
|
|
48
|
+
try {
|
|
49
|
+
// Total registered users
|
|
50
|
+
const totalResult = await pool.query('SELECT COUNT(*) AS count FROM users');
|
|
51
|
+
const totalRegistered = parseInt(totalResult.rows[0].count) || 0;
|
|
52
|
+
// Active 24h — users whose API key was used in the last 24h
|
|
53
|
+
// Join with usage_logs to get today's request count per user
|
|
54
|
+
const active24hResult = await pool.query(`
|
|
55
|
+
SELECT
|
|
56
|
+
u.id AS user_id,
|
|
57
|
+
u.email,
|
|
58
|
+
u.tier,
|
|
59
|
+
MAX(ak.last_used_at) AS last_seen,
|
|
60
|
+
COUNT(ul.id) AS requests_today
|
|
61
|
+
FROM users u
|
|
62
|
+
JOIN api_keys ak ON ak.user_id = u.id AND ak.is_active = true
|
|
63
|
+
LEFT JOIN usage_logs ul
|
|
64
|
+
ON ul.user_id::text = u.id::text
|
|
65
|
+
AND ul.created_at >= NOW() - INTERVAL '24 hours'
|
|
66
|
+
WHERE ak.last_used_at > NOW() - INTERVAL '24 hours'
|
|
67
|
+
GROUP BY u.id, u.email, u.tier
|
|
68
|
+
ORDER BY last_seen DESC
|
|
69
|
+
`);
|
|
70
|
+
const active24h = active24hResult.rows.map((r) => ({
|
|
71
|
+
userId: r.user_id,
|
|
72
|
+
email: r.email,
|
|
73
|
+
tier: r.tier,
|
|
74
|
+
lastSeen: r.last_seen instanceof Date ? r.last_seen.toISOString() : String(r.last_seen),
|
|
75
|
+
requestsToday: parseInt(r.requests_today) || 0,
|
|
76
|
+
}));
|
|
77
|
+
// Active 7d — users whose API key was used in the last 7 days
|
|
78
|
+
const active7dResult = await pool.query(`
|
|
79
|
+
SELECT
|
|
80
|
+
u.id AS user_id,
|
|
81
|
+
u.email,
|
|
82
|
+
u.tier,
|
|
83
|
+
MAX(ak.last_used_at) AS last_seen,
|
|
84
|
+
COUNT(ul.id) AS requests_7d
|
|
85
|
+
FROM users u
|
|
86
|
+
JOIN api_keys ak ON ak.user_id = u.id AND ak.is_active = true
|
|
87
|
+
LEFT JOIN usage_logs ul
|
|
88
|
+
ON ul.user_id::text = u.id::text
|
|
89
|
+
AND ul.created_at >= NOW() - INTERVAL '7 days'
|
|
90
|
+
WHERE ak.last_used_at > NOW() - INTERVAL '7 days'
|
|
91
|
+
GROUP BY u.id, u.email, u.tier
|
|
92
|
+
ORDER BY last_seen DESC
|
|
93
|
+
`);
|
|
94
|
+
const active7d = active7dResult.rows.map((r) => ({
|
|
95
|
+
userId: r.user_id,
|
|
96
|
+
email: r.email,
|
|
97
|
+
tier: r.tier,
|
|
98
|
+
lastSeen: r.last_seen instanceof Date ? r.last_seen.toISOString() : String(r.last_seen),
|
|
99
|
+
requestsLast7d: parseInt(r.requests_7d) || 0,
|
|
100
|
+
}));
|
|
101
|
+
res.json({
|
|
102
|
+
success: true,
|
|
103
|
+
data: {
|
|
104
|
+
active24h,
|
|
105
|
+
active7d,
|
|
106
|
+
totalRegistered,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.error('[admin-active] error:', err);
|
|
112
|
+
res.status(500).json({
|
|
113
|
+
success: false,
|
|
114
|
+
error: { type: 'internal_error', message: 'Failed to retrieve active users', docs: 'https://webpeel.dev/docs/errors#internal_error' },
|
|
115
|
+
requestId: req.requestId,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return router;
|
|
120
|
+
}
|