mcp-scraper 0.93.0 → 0.93.1
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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-core.js +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.js +1 -1
- package/dist/{chunk-PMOPJOSJ.js → chunk-5JKBFNYF.js} +1 -1
- package/dist/{chunk-35QGIWR6.js → chunk-5QYW4CSJ.js} +5 -5
- package/dist/{chunk-LBMRUR4E.js → chunk-AFFMCO7R.js} +2 -2
- package/dist/chunk-AYQSKD7D.js +1 -0
- package/dist/{chunk-H3SJLJYM.js → chunk-IJF4VXJ7.js} +1 -1
- package/dist/chunk-KPQM4UDJ.js +6 -0
- package/dist/{chunk-5KQO27NH.js → chunk-NLKA6SHC.js} +1 -1
- package/dist/{chunk-VRVO4OQ3.js → chunk-OD2WLHEN.js} +150 -150
- package/dist/chunk-UN6FVDJQ.js +1 -0
- package/dist/{chunk-4YLZR4OR.js → chunk-X6RD3Y4W.js} +1 -1
- package/dist/{extract-bundle-M2XM4BEW.js → extract-bundle-C3N6E6V7.js} +1 -1
- package/dist/{gmail-service-EGATZIBE.js → gmail-service-6V5MFBYH.js} +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/{server-JLR2YJ7V.js → server-KWGXYWYO.js} +5 -5
- package/dist/{site-extract-repository-3NFFFPXQ.js → site-extract-repository-2LFDP6FZ.js} +1 -1
- package/dist/{stripe-event-worker-PUYXT5DS.js → stripe-event-worker-IJXA6T37.js} +1 -1
- package/dist/{worker-UG4OXZWR.js → worker-ASXALAY7.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-DUJ56SHU.js +0 -1
- package/dist/chunk-RZEZJAID.js +0 -1
- package/dist/chunk-XASDACRP.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to MCP Scraper are documented here. The format is based on [
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.93.1] - 2026-09-24
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Keep explicitly requested two-page Google searches on the provider that supports them. Two-page full requests return organic listings with rich feature status marked unsupported and cost 40 Credits; if page 2 cannot be delivered, an available page 1 is returned as partial and billed for one page.
|
|
12
|
+
|
|
7
13
|
## [0.93.0] - 2026-09-24
|
|
8
14
|
|
|
9
15
|
### Added
|
package/README.md
CHANGED
|
@@ -175,7 +175,7 @@ Build the branded one-click bundle:
|
|
|
175
175
|
npm run build:mcpb
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
-
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.93.
|
|
178
|
+
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.93.1`, SHA-256 `4294210c53817e94aa5b2fd9f52c0293e3c6437ca4a3d1aff34df5ab1a27f675`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, API-key configuration field, and manually curated current-release message from the bundle manifest.
|
|
179
179
|
|
|
180
180
|
The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
|
|
181
181
|
|
package/dist/bin/api-server.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import{readFileSync as s}from"fs";function c(){try{for(let r of s(".env","utf8").split(`
|
|
3
|
-
`)){let o=r.indexOf("=");if(o<1||r.trimStart().startsWith("#"))continue;let e=r.slice(0,o).trim();process.env[e]||(process.env[e]=r.slice(o+1).trim())}}catch{}}c();async function a(){let[{serve:r},{app:o},{startWorker:e},{migrate:i}]=await Promise.all([import("@hono/node-server"),import("../server-
|
|
3
|
+
`)){let o=r.indexOf("=");if(o<1||r.trimStart().startsWith("#"))continue;let e=r.slice(0,o).trim();process.env[e]||(process.env[e]=r.slice(o+1).trim())}}catch{}}c();async function a(){let[{serve:r},{app:o},{startWorker:e},{migrate:i}]=await Promise.all([import("@hono/node-server"),import("../server-KWGXYWYO.js"),import("../worker-ASXALAY7.js"),import("../db-B5XJTOGN.js")]),n=parseInt(process.env.PORT??"3001");try{if(await i(),process.env.ANALYTICS_DATABASE_URL){let{migrateAnalytics:t}=await import("../analytics-repository-IHOFBSUV.js");await t()}e(),r({fetch:o.fetch,port:n},t=>{console.log(`[server] http://localhost:${t.port}`),console.log(`[server] admin auth: ${process.env.ADMIN_KEY?"configured":"not configured"}`)})}catch(t){console.error("[startup] server preflight failed",t instanceof Error?t.name:"unknown_error"),process.exit(1)}}a();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{b as E,c as N,d as M,e as L,f as T,j as U}from"../chunk-W2T4NTCE.js";import"../chunk-KJQXUZ4Y.js";import"../chunk-Y6MKMSOC.js";import{g as v,j as b,k as D,l as K,m as H}from"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import{a as P}from"../chunk-
|
|
2
|
+
import{b as E,c as N,d as M,e as L,f as T,j as U}from"../chunk-W2T4NTCE.js";import"../chunk-KJQXUZ4Y.js";import"../chunk-Y6MKMSOC.js";import{g as v,j as b,k as D,l as K,m as H}from"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import{a as P}from"../chunk-AYQSKD7D.js";import{Command as he}from"commander";import{spawn as ne}from"child_process";import{mkdir as ke,writeFile as Pe}from"fs/promises";import{basename as Ce,join as Z}from"path";function se(e){return e.apiKey?.trim()||"sk_live_your_key"}function ce(e){return e.packageSpec?.trim()||"mcp-scraper@latest"}function A(e={}){return["-y","--package",ce(e),"mcp-scraper"]}function pe(e){let n={MCP_SCRAPER_API_KEY:se(e)},c=e.browserProfileName?.trim();return c&&(n.BROWSER_AGENT_PROFILE_NAME=c),e.browserProfileSaveChanges===!0&&(n.BROWSER_AGENT_PROFILE_SAVE_CHANGES="true"),n}function q(){return["mcp","remove","mcp-scraper","-s","user"]}function J(){return["mcp","get","mcp-scraper"]}function B(e){let n=e.match(/^\s*Command:\s*(.+?)\s*$/m)?.[1];if(!n)return null;let c=e.match(/^\s*Args:\s*(.*?)\s*$/m)?.[1]??"",i=c.length?c.split(/\s+/):[],p={},u=e.split(/^\s*Environment:\s*$/m)[1];if(u)for(let a of u.split(`
|
|
3
3
|
`)){let l=a.match(/^\s{2,}([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);if(!l){if(a.trim().length&&!/^\s{2,}/.test(a))break;continue}p[l[1]]=l[2]}return{command:n,args:i,env:p}}function j(e){let n=["mcp","add","mcp-scraper","--scope","user"];for(let[c,i]of Object.entries(e.env))n.push("--env",`${c}=${i}`);return n.push("--",e.command,...e.args),n}function G(e={}){let n=["mcp","add","mcp-scraper","--scope","user"];for(let[c,i]of Object.entries(pe(e)))n.push("--env",`${c}=${i}`);return n.push("--","npx",...A(e)),n}function O(e){if(e==="claude-code")return"claude";if(e==="claude"||D.hosts.some(n=>n.id===e))return e;throw new Error('Unknown host "'+e+'". Use: codex, claude, claude-code, claude-desktop, cursor, windsurf, cline, or user-action-only')}function ue(e){return K(e==="claude"?"claude-code":e)}function W(e,n={}){let c=O(e),i=ue(c),p="Restart the MCP client so it starts a fresh npx process.",u='MCP_SCRAPER_API_KEY="$MCP_SCRAPER_API_KEY" npx -y -p mcp-scraper@latest mcp-scraper-cli agent install claude --apply',a=`X-Ray install protocol: ${v} (${b})`;return c==="codex"?["# Codex MCP config",a,i.exactConfig,"",`Continuation: ${i.continuation}`,`Rollback: ${i.rollback}`,"",p].join(`
|
|
4
4
|
`):c==="claude"?["# Claude Code command",a,i.exactConfig,"","# One-command Claude Code setup",u,"",`Continuation: ${i.continuation}`,`Rollback: ${i.rollback}`,"",p].join(`
|
|
5
5
|
`):c==="claude-desktop"?["# Claude Desktop config",a,i.exactConfig,"","Desktop Extension: https://mcpscraper.dev/downloads/mcp-scraper.mcpb",`Continuation: ${i.continuation}`,`Rollback: ${i.rollback}`,p].join(`
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as e}from"../chunk-
|
|
2
|
+
import{a as e}from"../chunk-X6RD3Y4W.js";import"../chunk-OD2WLHEN.js";import"../chunk-DT2FYN6N.js";import"../chunk-W2BVJ7S2.js";import"../chunk-RK2VCTZI.js";import"../chunk-ORB4RHCK.js";import"../chunk-TMB56NCA.js";import"../chunk-HUV2WTRW.js";import"../chunk-YGBTTW5D.js";import"../chunk-UN6FVDJQ.js";import"../chunk-SH5KB4P7.js";import"../chunk-2SP57VCG.js";import"../chunk-6DTXIZY2.js";import"../chunk-5QYW4CSJ.js";import"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import"../chunk-AYQSKD7D.js";import"../chunk-WJ4XFLS4.js";var _=["harvest_paa","search_serp","extract_url","diff_page","map_site_urls","map_wayback_snapshots","extract_site","analyze_site_similarity","audit_site","check_site_export","site_export_read","site_export_image","archive_read","youtube_harvest","youtube_transcribe","facebook_page_intel","facebook_ad_search","reddit_thread","reddit_trending","video_frame_analysis","video_frame_analysis_status","facebook_ad_transcribe","google_ads_search","google_ads_page_intel","google_ads_transcribe","facebook_video_transcribe","instagram_profile_content","instagram_media_download","maps_place_intel","maps_search","trustpilot_reviews","g2_reviews","capture_serp_snapshot","capture_serp_page_snapshots"];e({toolsets:new Set(["paa","serp"]),allowedToolNames:_});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as s}from"../chunk-
|
|
2
|
+
import{a as s}from"../chunk-5QYW4CSJ.js";import{a as e}from"../chunk-AYQSKD7D.js";var r=process.argv.includes("--no-color")||process.env.NO_COLOR!==void 0||process.env.FORCE_COLOR==="0"||!process.stdout.isTTY,n=process.argv.includes("--help")||process.argv.includes("-h");n&&(process.stdout.write(["Usage: mcp-scraper-install [--no-color]","","Prints the branded MCP Scraper terminal install card and copyable install commands.","mcp-scraper prints the same card in a human terminal and runs as the MCP stdio server in clients.",""].join(`
|
|
3
3
|
`)),process.exit(0));process.stdout.write(s({version:e,color:!r,apiKeyConfigured:!!process.env.MCP_SCRAPER_API_KEY?.trim()}));
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as r}from"../chunk-
|
|
2
|
+
import{a as r}from"../chunk-X6RD3Y4W.js";import"../chunk-OD2WLHEN.js";import"../chunk-DT2FYN6N.js";import"../chunk-W2BVJ7S2.js";import"../chunk-RK2VCTZI.js";import"../chunk-ORB4RHCK.js";import"../chunk-TMB56NCA.js";import"../chunk-HUV2WTRW.js";import"../chunk-YGBTTW5D.js";import"../chunk-UN6FVDJQ.js";import"../chunk-SH5KB4P7.js";import"../chunk-2SP57VCG.js";import"../chunk-6DTXIZY2.js";import"../chunk-5QYW4CSJ.js";import"../chunk-WO3N5FH2.js";import"../chunk-HE45FFBU.js";import"../chunk-AYQSKD7D.js";import"../chunk-WJ4XFLS4.js";r();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{ba as w}from"./chunk-
|
|
1
|
+
import{a as j,b as T,c as P,d as C,f as S}from"./chunk-TMB56NCA.js";import{ba as w}from"./chunk-UN6FVDJQ.js";import{Kb as N,Tb as D,d as m,e as I,i as u,t as s}from"./chunk-WJ4XFLS4.js";import{createHash as W}from"crypto";import{gunzipSync as $,gzipSync as q}from"zlib";var y="site-extracts/",L=10080*60*1e3,H=900*1e3;function U(){return process.env.SITE_EXTRACT_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.PRIVATE_ARTIFACT_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_BLOB_READ_WRITE_TOKEN?.trim()||null}function v(){return process.env.VERCEL==="1"||process.env.NODE_ENV==="production"}function p(){return{prefix:y,artifactTtlMs:L,downloadTtlMs:H,token:U()}}function h(t){return j(t,y)}async function V(t){let e=await P({policy:p(),ownerId:t.ownerId,artifactKey:`${t.jobId}.zip`,createdAt:t.createdAt,filename:`${t.jobId}-site-export.zip`,contentType:"application/zip",content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"bundle"}}async function G(t){let e=await T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"images"],artifactKey:`${t.imageId}.bin`,createdAt:new Date,filename:t.filename,contentType:t.contentType,content:t.content});return{key:e.artifactId,url:e.downloadUrl??"",bytes:e.bytes,contentType:e.contentType,filename:e.filename,sha256:e.sha256,expiresAt:e.expiresAt,downloadUrlExpiresAt:e.downloadUrlExpiresAt,kind:"image",imageId:t.imageId,sourceUrl:t.sourceUrl,sourcePage:t.sourcePage}}async function O(t){return T({policy:p(),ownerId:t.ownerId,scopeSegments:[t.jobId,"content"],artifactKey:`${t.chunkKey}.json.gz`,createdAt:t.createdAt,filename:`${t.chunkKey}.json.gz`,contentType:"application/gzip",content:t.content})}async function Q(t){return C({policy:p(),artifactId:t.artifactId,ownerId:t.ownerId})}async function J(t){return S({policy:p(),artifactId:t,maxBytes:50*1024*1024})}async function Z(t){return h(t.artifactId)!==t.ownerId?null:J(t.artifactId)}async function k(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:25*1024*1024})}async function tt(t){return h(t.artifactId)!==t.ownerId?null:S({policy:p(),artifactId:t.artifactId,maxBytes:10*1024*1024})}async function et(t={}){let e=t.now??new Date,n=U();if(!n)return{deleted:0,store:v()?"none":"local"};if(!t.force&&!(e.getUTCHours()===3&&e.getUTCMinutes()===21))return{deleted:0,store:"private-vercel-blob",skipped:!0};let r=e.getTime()-L,{list:i,del:a}=await import("@vercel/blob"),o,c=0;for(let d=0;d<20;d+=1){let l=await i({prefix:y,token:n,limit:1e3,cursor:o}),f=l.blobs.filter(A=>new Date(A.uploadedAt).getTime()<=r);if(f.length>0&&(await a(f.map(A=>A.pathname),{token:n}),c+=f.length),!l.hasMore||!l.cursor)break;o=l.cursor}return{deleted:c,store:"private-vercel-blob"}}var F=10,b=20*1024*1024;function E(t){return W("sha256").update(t).digest("hex")}function B(t){return!t.acquiredHtml||t.extractionStatus==="failed"?null:{pageId:t.pageId??E(t.archivedUrl??t.url),url:t.archivedUrl??t.url,html:t.acquiredHtml,mainHtml:t.mainHtml??"",markdown:t.bodyMarkdown,htmlSha256:t.htmlSha256??E(t.acquiredHtml),markdownSha256:t.markdownSha256??E(t.bodyMarkdown)}}function R(t){return Buffer.from(JSON.stringify({version:"site-extract-content.v1",pages:t}))}async function M(t){let e=t.pages.flatMap(o=>{let c=B(o);return c?[c]:[]}),n=new Map,r=[],i=0,a=async()=>{if(!r.length)return;let o=R(r);if(o.length>b)throw new Error(`site export content chunk exceeds ${b} bytes`);let c=E(r.map(l=>l.pageId).join("\0")).slice(0,16),d=await O({ownerId:t.ownerId,jobId:t.jobId,createdAt:t.createdAt,chunkKey:`content-${String(i).padStart(4,"0")}-${c}`,content:q(o,{level:6})});for(let l of r)n.set(l.url,{artifactId:d.artifactId,artifactSha256:d.sha256,pageId:l.pageId,uncompressedBytes:o.length});i++,r=[]};for(let o of e){let c=[...r,o];if(r.length>0&&(c.length>F||R(c).length>b)&&await a(),r.push(o),R(r).length>b)throw new Error(`page ${o.pageId} exceeds the durable content chunk limit`)}return await a(),n}function it(t){let e=new Map;return async n=>{let r=e.get(n.artifactId);if(!r){let a=await k({artifactId:n.artifactId,ownerId:t});if(!a)throw new Error("site export content chunk is missing or unauthorized");if(E(a)!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let o=$(a);if(o.length>b)throw new Error("site export content chunk exceeds its read limit");if(r=JSON.parse(o.toString("utf8")),r.version!=="site-extract-content.v1"||!Array.isArray(r.pages))throw new Error("site export content chunk has an unsupported contract");for(e.set(n.artifactId,r);e.size>2;)e.delete(e.keys().next().value)}let i=r.pages.find(a=>a.pageId===n.pageId);if(!i)throw new Error("site export page is missing from its content chunk");if(E(i.html)!==i.htmlSha256||E(i.markdown)!==i.markdownSha256)throw new Error("site export page checksum mismatch");return i}}var g="xray_entitlement";function pt(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function Et(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function _(t){let e=Number(t.total_urls??0),n=t.attempted_urls==null,r=Number(n?t.done_urls??0:t.attempted_urls),i=Number(n?t.done_urls??0:t.successful_urls??0),a=Number(t.failed_urls??Math.max(0,r-i));return{id:String(t.id),userId:t.user_id!=null?Number(t.user_id):null,idempotencyKey:t.idempotency_key!=null?String(t.idempotency_key):null,requestFingerprint:t.request_fingerprint!=null?String(t.request_fingerprint):null,status:t.status!=null?String(t.status):"pending",startUrl:String(t.start_url??""),options:t.options?JSON.parse(String(t.options)):{},totalUrls:e,doneUrls:r,attemptedUrls:r,successfulUrls:i,failedUrls:a,remainingUrls:Math.max(0,e-r),artifacts:t.artifacts?JSON.parse(String(t.artifacts)):null,error:t.error!=null?String(t.error):null,publicError:I(t.public_error_json),billedMc:t.billed_mc!=null?Number(t.billed_mc):null,createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??"")}}async function mt(t,e,n,r){await s().execute({sql:`INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)
|
|
2
2
|
VALUES (?, ?, 'pending', ?, ?, datetime('now'), datetime('now'))`,args:[t,e,n,JSON.stringify(r)]})}async function K(t,e){let r=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? AND idempotency_key = ? LIMIT 1",args:[t,e]});return r.rows[0]?_(r.rows[0]):null}async function gt(t){let n=await s().execute({sql:`INSERT OR IGNORE INTO site_extract_jobs
|
|
3
3
|
(id, user_id, status, start_url, options, idempotency_key, request_fingerprint, created_at, updated_at)
|
|
4
4
|
VALUES (?, ?, 'pending', ?, ?, ?, ?, datetime('now'), datetime('now'))`,args:[t.jobId,t.userId,t.startUrl,JSON.stringify(t.options),t.idempotencyKey,t.requestFingerprint]}),r=await K(t.userId,t.idempotencyKey);if(!r)throw new Error("idempotent extract job was not persisted");return{job:r,created:n.rowsAffected===1,conflict:r.requestFingerprint!==t.requestFingerprint}}async function x(t){let n=await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE id = ?",args:[t]});return n.rows[0]?_(n.rows[0]):null}async function _t(t){return(await s().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[t]})).rows.map(r=>_(r))}async function xt(t=25){return(await s().execute({sql:`SELECT * FROM site_extract_jobs
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var s={message:"search_serp light mode returns organic Google positions, URLs, titles, and descriptions. One-page full mode adds available same-page SERP features. Both default to one page; request pages:2 explicitly for two organic pages. If page 2 is unavailable, an available page 1 is returned as partial. Light costs 20 Credits per delivered page, or 35 Credits when the backup supplies one page. One-page full costs 35 Credits; two-page organic results cost 40 Credits when both pages arrive."};var i={reset:"\x1B[0m",cyan:"\x1B[36m",lime:"\x1B[32m",amber:"\x1B[33m",red:"\x1B[31m",muted:"\x1B[90m",bold:"\x1B[1m"};function r(t,e,a){return a?`${i[e]}${t}${i.reset}`:t}function o(t,e,a){let n=t.padEnd(9," ");return` ${r(n,"muted",a)} ${e.join(r(" . ","muted",a))}`}function m(t){let e=t.color??!0,a=t.apiKeyConfigured?"$MCP_SCRAPER_API_KEY":"sk_live_your_key",n=String.raw`
|
|
2
2
|
__ __ ____ ____
|
|
3
3
|
| \/ |/ ___| _ \
|
|
4
4
|
| |\/| | | | |_) |
|
|
@@ -10,7 +10,7 @@ var a={message:"search_serp light mode returns organic Google positions, URLs, t
|
|
|
10
10
|
\___ \| | | |_) | / _ \ | |_) | _| | |_) |
|
|
11
11
|
___) | |___| _ < / ___ \| __/| |___| _ <
|
|
12
12
|
|____/ \____|_| \_\/_/ \_\_| |_____|_| \_\
|
|
13
|
-
`,
|
|
14
|
-
`),c=["[mcp_servers.mcp-scraper]",'command = "npx"','args = ["-y", "-p", "mcp-scraper@latest", "mcp-scraper"]',`env = { MCP_SCRAPER_API_KEY = "${
|
|
15
|
-
`);return[r(`mcp-scraper v${t.version}`,"bold",e),r("> mcp-scraper-install","muted",e),r(
|
|
16
|
-
`)}export{
|
|
13
|
+
`,_=[`MCP_SCRAPER_API_KEY=${a} npx -y -p mcp-scraper@latest \\`," mcp-scraper-cli agent install claude --apply"].join(`
|
|
14
|
+
`),c=["[mcp_servers.mcp-scraper]",'command = "npx"','args = ["-y", "-p", "mcp-scraper@latest", "mcp-scraper"]',`env = { MCP_SCRAPER_API_KEY = "${a}" }`].join(`
|
|
15
|
+
`);return[r(`mcp-scraper v${t.version}`,"bold",e),r("> mcp-scraper-install","muted",e),r(n,"amber",e),`${r("MCP Scraper Agent","cyan",e)} . v${t.version} . mcpscraper.dev`,"1/1 install surfaces ready",r(`Newest in v${t.version}: ${s.message}`,"lime",e),"",`${r("Tools","cyan",e)} ${r("(362 MCP tools)","muted",e)}`,o("search",["harvest_paa","search_serp","maps_search","maps_place_intel"],e),o("extract",["extract_url","map_site_urls","extract_site","audit_site","directory_workflow"],e),o("build",["create_editorial_reading_room","rank_tracker_workflow","portable HTML"],e),o("media",["youtube_harvest","youtube_transcribe","facebook_reels_inventory","facebook_ad_search","facebook_page_intel","facebook_ad_transcribe","facebook_video_transcribe","tiktok_video_transcribe","instagram_profile_content","instagram_media_download","reddit_thread"],e),o("browser",["serp_identity_create","serp_identity_list","browser_open","browser_profile_connect","browser_profile_list","browser_close","browser_screenshot","browser_read","browser_locate","browser_replay_mark","browser_replay_annotate"],e),o("connect",["list_service_connections","describe_service_connection_tool","import_service_connection_to_memory","export_connected_service_data","renew_connected_data_download","read_service_connection","call_service_connection_action"],e),o("commons",["commons_search_entities","commons_get_entity_linkset","commons_prepare_entity","commons_submit_entity","commons_prepare_publication","commons_claim_publication","commons_publish_editorial","commons_get_publication"],e),o("account",["credits_info","reports","MCP resources"],e),o("memory",["memory-put","memory-get","memory-search","list-vaults","record-fact","list-scheduled-actions"],e),`${r("Workflows","cyan",e)} ${r("(MCP + CLI + API)","muted",e)}`,o("route",["workflow_list","workflow_suggest","workflow_run","workflow_step","workflow_status","workflow_artifact_read"],e),o("seo",["directory","agent-packet","competitive audit","map/serp comparison","PAA/AIO briefs","scheduled runs"],e),"",r("Usage tips:","amber",e),"Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.","Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.","Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install","Hosted browser sessions use direct/no-proxy egress by default.","Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.","Connected account ranges: call export_connected_service_data once. It handles Gmail, Calendar, Zoom, and Resend pagination; do not loop read_service_connection over individual records.","Connected account RAG: call import_service_connection_to_memory for one bounded approved read. It writes a redacted, untrusted snapshot to a stable Memory path and embeds it for search.","Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.","Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.","For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.","If you hit the concurrency limit, add 2 browsers for $5/month with mcp-scraper-cli billing concurrency checkout.","",`${r("Ready.","lime",e)} Install the combined MCP server with one command:`,"",r("Setup doctor","amber",e),"npx -y -p mcp-scraper@latest mcp-scraper-cli doctor","",r("Hosted profile setup","amber",e),'In your MCP client, call browser_profile_connect with email="seo@example.com" and domain="chatgpt.com".',"Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.","",r("Claude Code one-command setup","amber",e),_,"Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list","",r("Codex config","amber",e),c,"",r("Claude Desktop Extension","amber",e),"Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb","",r("Safety note:","muted",e),"mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.","Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.",""].join(`
|
|
16
|
+
`)}export{m as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as Zt,s as tn}from"./chunk-
|
|
1
|
+
import{a as Zt,s as tn}from"./chunk-IJF4VXJ7.js";import{T as cn,a as de,b as Ne,c as yt,d as an,e as on,q as f,r as v,sa as G,ta as Ce,v as U,w as J}from"./chunk-LI7WHOII.js";import{a as Fe,e as en}from"./chunk-QTDLZTQ7.js";import{d as nn,g as je,i as qe,k as _t,m as mt,o as rn,r as He,t as sn,u as pt}from"./chunk-YGBTTW5D.js";import{$ as ce,A as zt,E as dt,I as D,J as Yt,S as Xt,T as Gt,U as he,V as lt,W as Qt,X as ut,Z as X,ba as Ue,u as Me,v as Jt}from"./chunk-UN6FVDJQ.js";import{Ab as ot,Bb as Wt,Fb as oe,H as qt,Ib as Bt,Jb as ct,Ob as Vt,R as ke,Sb as Kt,T as Ht,t as ae,vb as T,wb as Pe,yb as st,zb as at}from"./chunk-WJ4XFLS4.js";import{createCipheriv as Di,createDecipheriv as Ti,randomBytes as xi,scryptSync as Li}from"crypto";import{setScheduleEntitlementTool as $i}from"mcpscraper-memory-tools/tools/schedule/set-schedule-entitlement";import{createHash as Si,randomUUID as hi}from"crypto";import{exportJWK as Ni,importPKCS8 as Ci,SignJWT as Ri}from"jose";function wi(e=process.env.OAUTH_ISSUER){let t=e?.trim()||"https://mcpscraper.dev",n=new URL(t);if(n.protocol!=="https:"||n.username||n.password||n.search||n.hash||n.pathname!=="/"&&n.pathname!=="")throw new Error("OAUTH_ISSUER must be an HTTPS origin without credentials, path, query, or fragment");return n.origin}var Oi=wi(),We=null;async function dn(){if(We)return We;let e=process.env.OAUTH_SIGNING_KEY;if(!e?.trim())throw new Error("OAUTH_SIGNING_KEY is not set");let t=e.includes("BEGIN")?e:Buffer.from(e,"base64").toString("utf8"),n=await Ci(t,"RS256",{extractable:!0}),i=await Ni(n),r={kty:i.kty,n:i.n,e:i.e},s=Si("sha256").update(JSON.stringify({e:r.e,kty:r.kty,n:r.n})).digest("base64url").slice(0,16);return r.kid=s,r.alg="RS256",r.use="sig",We={privateKey:n,publicJwk:r,kid:s},We}async function Ls(){return(await dn()).publicJwk}async function ln(e){let{privateKey:t,kid:n}=await dn();return new Ri({scope:e.scope,plan:e.plan}).setProtectedHeader({alg:"RS256",kid:n}).setIssuer(Oi).setSubject(e.identity).setAudience(e.audience).setIssuedAt().setJti(hi()).setExpirationTime(`${e.ttlSeconds}s`).sign(t)}var ki=()=>(process.env.MCP_MEMORY_BASE_URL??"https://memory.mcpscraper.dev").replace(/\/$/,""),Pi=()=>(process.env.MCP_MEMORY_RESOURCE_URL??"https://memory.mcpscraper.dev/mcp").replace(/\/$/,""),Mi=()=>process.env.MCP_MEMORY_ADMIN_KEY?.trim()??"",Ui=300;function Fi(e){let t=e.split(`
|
|
2
2
|
`).find(i=>i.startsWith("data:")),n=t?t.slice(5).trim():e;return JSON.parse(n)}function gt(e){return e?(process.env.MEMORY_OPERATOR_IDENTITIES??"").split(",").map(n=>n.trim().toLowerCase()).filter(Boolean).includes(e.trim().toLowerCase()):!1}function un(){return Li(Fe(),"mcp-memory-key-v1",32)}function qs(e){let t=xi(12),n=Di("aes-256-gcm",un(),t),i=Buffer.concat([n.update(e,"utf8"),n.final()]),r=n.getAuthTag();return`${t.toString("base64")}:${r.toString("base64")}:${i.toString("base64")}`}function Hs(e){try{let[t,n,i]=e.split(":"),r=Ti("aes-256-gcm",un(),Buffer.from(t,"base64"));return r.setAuthTag(Buffer.from(n,"base64")),Buffer.concat([r.update(Buffer.from(i,"base64")),r.final()]).toString("utf8")}catch{return null}}async function _n(e,t,n){try{let i=await fetch(`${ki()}/mcp`,{method:"POST",headers:{"content-type":"application/json",accept:"application/json, text/event-stream",authorization:`Bearer ${n}`},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"tools/call",params:{name:e,arguments:t}})}),r=await i.text();if(!i.ok)return{ok:!1,error:`memory ${e} failed (${i.status})`};let s=Fi(r);if(s.error)return{ok:!1,error:s.error.message??`memory ${e} failed`};if(s.result?.structuredContent)return s.result.structuredContent;let a=s.result?.content?.find(o=>o.type==="text")?.text;if(a)try{return JSON.parse(a)}catch{return{ok:!1,error:a}}return{ok:!1,error:`memory ${e} returned no result`}}catch(i){return{ok:!1,error:i?.message??"memory call failed"}}}function mn(e){return e.email}function ji(e){return mn(e)}function Ws(e){return gt(e.email)?"unlimited":e.memory_plan==="pro"||e.memory_plan==="team"?e.memory_plan:"free"}async function Bs(e){try{let{key:t}=await pn(e);if(!t)return;(await _n("listVaultsTool",{},t)).ok&&await Bt(e.id,!0)}catch{}}function qi(e){return e?!!Yt[e]?.includes_memory:!1}function F(e){return e.memory_plan==="team"?"team":qi(e.subscription_tier)||e.memory_plan==="pro"?"pro":"free"}async function pn(e,t){try{let n=gt(e.email),i=n?"unlimited":t??F(e),r=n?"memory.read memory.write memory.admin":"memory.read memory.write";return{key:await ln({identity:mn(e),scope:r,plan:i,audience:Pi(),ttlSeconds:Ui})}}catch(n){return{key:null,error:n instanceof Error?n.message:"memory service authorization unavailable"}}}async function z(e,t){let n=gt(e.email)?"unlimited":t,{key:i,error:r}=await pn(e,n);if(!i)return{ok:!1,error:r??"memory unavailable"};let s=await _n("listVaultsTool",{},i);return{ok:s.ok,error:s.error}}async function Be(e){let t=Mi();if(!t)return{ok:!1,error:"memory not configured (MCP_MEMORY_ADMIN_KEY missing)"};let n=ji(e),i=await $i.execute({apiKey:t,granteeIdentity:n,mcpScraperApiKey:e.api_key},{});return{ok:i.ok,error:i.error}}var yn=["active","trialing","past_due"];function Re(e){return yn.includes(e)}function gn(e,t){for(let n of yn){let i=e.find(r=>r.status===n&&t(r));if(i)return i}}var Hi="price_1TtYPAS8aAcsk3TGHOgrDZiQ";function Wi(e=new Date){return`${e.getUTCFullYear()}-${String(e.getUTCMonth()+1).padStart(2,"0")}`}var Bi=new Set(["connected","needs_reauth"]);function Vi(e){return Bi.has(String(e.lifecycleStatus??""))}async function Ki(e,t){let n=await ae().execute({sql:"SELECT connection_id FROM connected_account_charges WHERE user_id = ? AND period_start = ?",args:[Number(e),t]});return new Set(n.rows.map(i=>String(i.connection_id)))}async function Ji(e,t,n){await en();let i=Number(e),r=ae();return await r.batch([{sql:`
|
|
3
3
|
INSERT OR IGNORE INTO connected_account_charge_transfers (
|
|
4
4
|
user_id, period_start, from_connection_id, to_connection_id, provider_config_key
|
|
@@ -817,4 +817,4 @@ MCowBQYDK2VwAyEAi2HR1srL4o18O8BRa7gVJY7G7bupbN3H9AwJrHCDiOg=
|
|
|
817
817
|
)
|
|
818
818
|
ORDER BY edge.confidence DESC, edge.last_seen_at DESC
|
|
819
819
|
LIMIT 1
|
|
820
|
-
FOR SHARE OF p, ns, cs, receipt`,[t.siteId,Ce("customer_id",t.stableUserId)])).rows[0]??null}async function Ut(e,t){let n=process.env.MCP_SCRAPER_XRAY_SITE_ID?.trim();if(!n)return{status:"skipped",eventName:Le,reason:"site_not_configured"};if(!vs(n))return{status:"skipped",eventName:Le,reason:"site_id_invalid"};let i=String(e.userId).trim();if(!i||!e.invoiceId.trim()||!Number.isSafeInteger(e.amountPaidMinor)||e.amountPaidMinor<0||!/^[a-z]{3}$/i.test(e.currency)||!Number.isFinite(new Date(e.occurredAt).getTime()))throw new Error("analytics_first_party_outcome_invalid");let r=t??{db:v(),record:(a,o)=>oi({...a,transactionClient:o})},s=await r.db.connect();try{await s.query("BEGIN");let a=await Es(s,{siteId:n,stableUserId:i});if(!a)return await s.query("ROLLBACK"),{status:"skipped",eventName:Le,reason:"identity_or_consent_unavailable"};let o={schemaVersion:1,eventId:`mcp_invoice_${e.invoiceId}`.slice(0,200),sourceEventId:`stripe:invoice:${e.invoiceId}`.slice(0,300),source:"mcp_scraper",sourceAccountRef:"first_party_billing",eventKind:"transaction",eventName:Le,occurredAt:e.occurredAt,personRef:i,orderId:e.invoiceId,valueMinor:e.amountPaidMinor,currency:e.currency.toUpperCase(),consent:{analytics:"granted",adUserData:"granted",adPersonalization:a.advertising_measurement?"granted":"denied",globalPrivacyControl:!1,occurredAt:new Date(a.effective_at).toISOString(),receiptId:a.receipt_id,policyVersion:a.policy_version,purposes:{site_analytics:"granted",enhanced_matching:"granted",advertising_measurement:a.advertising_measurement?"granted":"denied"}},properties:{product:"mcp_scraper",billingKind:"base_plan_paid_invoice",revenueProvenance:"stripe_paid_invoice"}},c=await r.record({siteId:n,event:o},s);return await s.query("COMMIT"),{status:"recorded",eventName:Le,reason:"recorded",created:c.created,conversionIds:c.conversionIds}}catch(a){throw await s.query("ROLLBACK").catch(()=>{}),a}finally{s.release()}}function ci(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}function Ie(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function bs(e){let t=e.subscription;if(t)return Ie(t);let n=e.parent;return Ie(n?.subscription_details?.subscription)}async function As(e,t){let n=await T(e);return n||!t||(n=await ke(t),n&&await Pe(n.id,e)),n}async function Is(e,t,n){let i=t.memory_subscription_id;if(!(!i||i===n))try{let r=await e.subscriptions.retrieve(i);r.status!=="canceled"&&!r.cancel_at_period_end&&await e.subscriptions.update(i,{cancel_at_period_end:!0})}catch(r){console.error("[stripe] could not wind down standalone memory subscription",i,r instanceof Error?r.message:r)}}async function Ft(e,t,n){if(!t.id||t.status!=="paid")return{status:"not_applicable",invoiceId:t.id??null};let i=t.lines.data.some(y=>{let E=ci(y);return!!E&&E in D});if(!fn(i,t.total))return{status:"not_applicable",invoiceId:t.id};let r=bs(t),a=(r?le(await e.subscriptions.retrieve(r))?.price?.id:void 0)??t.lines.data.map(ci).find(y=>!!y&&y in D),o=a?D[a]:void 0;if(!o)return{status:"not_applicable",invoiceId:t.id};let c=Ie(t.customer);if(!c)throw new Error("Paid subscription invoice has no Stripe customer");let d=await As(c,t.customer_email);if(!d)throw new Error("Paid subscription invoice does not map to an MCP Scraper account");let _=await Wt({invoiceId:t.id,userId:d.id,subscriptionId:r??d.subscription_id,tier:o.tier,concurrency:o.concurrency,creditsMc:o.credits_mc,description:`${o.label} subscription credits`,neverExpires:!!o.credits_never_expire,includedMemoryPlan:o.includes_memory?"pro":null});o.includes_memory&&(await Is(e,d,r??d.subscription_id),await z(d,F({...d,memory_plan:"pro",subscription_tier:o.tier})));let u=await Be(d);u.ok||console.warn("[stripe] scheduled-action credential sync failed:",u.error??"unknown error");try{await Ut({userId:d.id,invoiceId:t.id,amountPaidMinor:t.amount_paid,currency:t.currency,occurredAt:new Date(((t.status_transitions?.paid_at??n)||Math.floor(Date.now()/1e3))*1e3).toISOString()})}catch(y){console.error("[stripe] X-Ray paid outcome failed",{invoiceId:t.id,error:y instanceof Error?y.message:String(y)})}return{status:_.granted?"fulfilled":"already_fulfilled",invoiceId:t.id,userId:d.id,tier:o.tier}}async function di(e,t,n){let i=await e.checkout.sessions.retrieve(t,{expand:["invoice"]});if(i.mode!=="subscription")throw new Error("Checkout session is not a subscription purchase");if(i.payment_status!=="paid"&&i.payment_status!=="no_payment_required")return{status:"not_applicable",invoiceId:Ie(i.invoice)??null};let r=Ie(i.customer);if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=typeof i.invoice=="object"&&i.invoice&&!("deleted"in i.invoice)?i.invoice:await e.invoices.retrieve(Ie(i.invoice)??"");if(!s?.id)throw new Error("Paid subscription checkout has no invoice");return Ft(e,s,i.created)}var li="scale_credit_pack";function rt(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function ui(e){let t=Number(e);if(!Number.isSafeInteger(t)||t<1||t>ut)throw new Error(`quantity must be a whole number from 1 to ${ut}`);return t}function Tc(e){return e.subscription_tier==="scale"}function xc(e,t){let n=ui(t);return{purchase_kind:li,account_user_id:String(e),eligible_tier:"scale",increment_quantity:String(n),increment_usd:String(he),credits_per_increment:String(lt)}}async function _i(e,t,n){let i=await e.checkout.sessions.retrieve(t);if(i.mode!=="payment"||i.metadata?.purchase_kind!==li)return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};if(i.payment_status!=="paid")return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};let r=rt(i.customer);if(!r)throw new Error("Paid Scale credit-pack checkout has no Stripe customer");if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=ui(i.metadata.increment_quantity),a=s*he*100;if(i.currency!=="usd"||i.amount_subtotal!==a)throw new Error("Scale credit-pack checkout amount does not match the product contract");let o=await e.checkout.sessions.listLineItems(i.id,{limit:2}),c=o.data[0];if(o.data.length!==1||c?.quantity!==s||c.price?.currency!=="usd"||c.price?.unit_amount!==he*100)throw new Error("Scale credit-pack checkout line item does not match the product contract");let d=await T(r);if(!d)throw new Error("Paid Scale credit-pack checkout does not map to an MCP Scraper account");if(i.metadata.account_user_id!==String(d.id)||i.metadata.eligible_tier!=="scale")throw new Error("Scale credit-pack checkout account metadata does not match the billing account");let _=rt(i.payment_intent);if(!_)throw new Error("Paid Scale credit-pack checkout has no payment intent");let u=s*lt;return{status:(await Vt(d.id,s*Qt,Ue.TOPUP,`$${s*he} Scale credit pack (${u.toLocaleString("en-US")} credits)`,`stripe-payment-intent:${_}`,{neverExpires:!1})).duplicate?"already_fulfilled":"fulfilled",paymentIntentId:_,userId:d.id,quantity:s,credits:u}}import Ss from"stripe";import{Hono as hs}from"hono";import{waitUntil as Ns}from"@vercel/functions";var x=new Ss(process.env.STRIPE_SECRET_KEY,{apiVersion:"2026-02-25.clover"});async function Cs(e,t){if(!(!e||e===t))try{let n=await x.subscriptions.retrieve(e),i=n.items.data[0]?.price?.id,r=n.status!=="canceled"&&!n.cancel_at_period_end;i&&i in ce&&r&&await x.subscriptions.update(e,{cancel_at_period_end:!0})}catch(n){console.error("[stripe] could not wind down standalone memory subscription",e,n instanceof Error?n.message:n)}}var Rs=new hs;Rs.post("/webhooks",async e=>{let t=e.req.header("stripe-signature"),n=await e.req.text(),i;try{i=x.webhooks.constructEvent(n,t,process.env.STRIPE_WEBHOOK_SECRET)}catch{return e.json({error:"Invalid signature"},400)}try{let r=await qt(i.id,i.type,i.created);return r==="queued"&&ws(),e.json({received:!0,disposition:r})}catch(r){let s=r instanceof Error?r.message:String(r);return console.error("[stripe] webhook enqueue failed",i.id,s),e.json({error:"Webhook enqueue failed"},500)}});function ws(){let e=import("./stripe-event-worker-PUYXT5DS.js").then(({drainStripeEventQueue:t})=>t({limit:10,leaseSeconds:300})).catch(t=>{console.error("[stripe] immediate queue drain failed; the scheduled drain will retry",t instanceof Error?t.message:String(t))});Ns(e)}async function Kc(e){if(e.type==="checkout.session.completed"||e.type==="checkout.session.async_payment_succeeded"){let t=e.data.object;t.mode==="payment"?await _i(x,t.id):await di(x,t.id);return}if(e.type==="invoice.created"){let t=e.data.object;mi(t)&&t.status==="draft"&&await x.invoices.update(t.id,{description:Xt,footer:Gt,custom_fields:[{name:"Pack benefit",value:"2 browsers per $5 monthly pack"},{name:"Billing cadence",value:"Monthly"}]});return}if(e.type==="invoice.paid"||e.type==="invoice.payment_succeeded"){let t=e.data.object;if(mi(t)){let i=t.customer_email?void 0:await yi(t.customer,void 0),r=t.customer_email??i?.email;if(!r)throw new Error("Paid concurrency invoice has no customer receipt email");await Os(t.id,r);return}if(t.lines.data.map(gi).find(i=>i&&i in ce))return;await Ft(x,t,e.created)}if(e.type==="customer.subscription.created"||e.type==="customer.subscription.updated"){let t=e.data.object,n=pi(t);if(n){let s=await T(t.customer);if(!s)return;let a=Re(t.status);await st(s.id,a?Ds(n):0),await at(s.id,a?t.id:null);return}let i=le(t)?.price?.id??t.items.data[0]?.price?.id;if(i&&i in ce){let s=ce[i],a=await yi(t.customer,t.customer_email);if(a){let o=Re(t.status),c=o?s.plan:"free";await oe(a.id,c,o?t.id:null),await z(a,F({...a,memory_plan:c}))}return}let r=await T(t.customer);if(!r)return;if(i&&i in D){let s=D[i],a=Re(t.status),o=a?s.tier:null;if(await ot(r.id,o,a?s.concurrency:0,a?t.id:null),s.includes_memory){let c=a?"pro":"free";a&&await Cs(r.memory_subscription_id,t.id),await oe(r.id,c,null),await z(r,F({...r,memory_plan:c}))}else r.memory_subscription_id===t.id&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"})));if(a){let c=await Be(r);c.ok||console.warn("[stripe] scheduled-action credential sync failed:",c.error??"unknown error")}}}if(e.type==="customer.subscription.deleted"){let t=e.data.object;if(pi(t)){let i=await T(t.customer);i&&(await st(i.id,0),await at(i.id,null));return}let n=le(t)?.price?.id??t.items.data[0]?.price?.id;if(n&&n in D){let i=D[n],r=await T(t.customer);r&&(await ot(r.id,null,0,null),(i.includes_memory||r.memory_subscription_id===t.id)&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"}))));return}if(n&&n in ce||await ct(t.id)){let i=await ct(t.id)??await T(t.customer);i&&(await oe(i.id,"free",null),await z(i,F({...i,memory_plan:"free"})));return}}}function mi(e){return e.lines.data.some(t=>gi(t)===dt)}async function Os(e,t){let i=(await x.invoicePayments.list({invoice:e,status:"paid",limit:10})).data.find(a=>a.status==="paid");if(!i)throw new Error("Paid concurrency invoice has no paid Stripe payment");let r;if(i.payment.type==="charge")r=i.payment.charge;else if(i.payment.type==="payment_intent"&&i.payment.payment_intent){let a=typeof i.payment.payment_intent=="string"?i.payment.payment_intent:i.payment.payment_intent.id;r=(await x.paymentIntents.retrieve(a,{expand:["latest_charge"]})).latest_charge}if(!r)throw new Error("Paid concurrency invoice has no receipt-capable charge");let s=typeof r=="string"?await x.charges.retrieve(r):r;s.receipt_email!==t&&await x.charges.update(s.id,{receipt_email:t})}function pi(e){return e.items.data.find(t=>t.price?.id===dt)}function Ds(e){let t=e.quantity??1;if(!Number.isSafeInteger(t)||t<1)throw new Error("Stripe concurrency pack quantity must be a positive safe integer");return t}function gi(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}async function yi(e,t){let n=await T(e);if(n)return n;if(t)return n=await ke(t),n&&await Pe(n.id,e),n}export{Oi as a,Ls as b,ln as c,gt as d,qs as e,Hs as f,_n as g,ji as h,Ws as i,Bs as j,qi as k,pn as l,Be as m,Et as n,j as o,le as p,Qs as q,Zs as r,ea as s,ze as t,Ye as u,Sn as v,dr as w,ur as x,At as y,ua as z,_a as A,ma as B,pa as C,Aa as D,wn as E,Ca as F,Ra as G,wa as H,Oa as I,Da as J,Ta as K,xa as L,La as M,$a as N,ka as O,Pa as P,Ma as Q,Ua as R,Dn as S,Fa as T,gr as U,ja as V,te as W,Ze as X,$ as Y,qa as Z,Er as _,Va as $,Ka as aa,Ja as ba,Un as ca,Fn as da,za as ea,so as fa,Bn as ga,Vn as ha,lo as ia,uo as ja,Kn as ka,po as la,Jn as ma,zn as na,Yn as oa,Xn as pa,Gn as qa,Qn as ra,it as sa,Co as ta,Ro as ua,wo as va,Oo as wa,Do as xa,To as ya,ei as za,ti as Aa,$t as Ba,ni as Ca,ii as Da,ss as Ea,Qo as Fa,Zo as Ga,ec as Ha,tc as Ia,nc as Ja,ic as Ka,rc as La,sc as Ma,ac as Na,oc as Oa,cc as Pa,dc as Qa,lc as Ra,uc as Sa,_c as Ta,mc as Ua,ri as Va,pc as Wa,yc as Xa,oi as Ya,gc as Za,fc as _a,Ft as $a,di as ab,ui as bb,Tc as cb,xc as db,_i as eb,x as fb,Rs as gb,Kc as hb};
|
|
820
|
+
FOR SHARE OF p, ns, cs, receipt`,[t.siteId,Ce("customer_id",t.stableUserId)])).rows[0]??null}async function Ut(e,t){let n=process.env.MCP_SCRAPER_XRAY_SITE_ID?.trim();if(!n)return{status:"skipped",eventName:Le,reason:"site_not_configured"};if(!vs(n))return{status:"skipped",eventName:Le,reason:"site_id_invalid"};let i=String(e.userId).trim();if(!i||!e.invoiceId.trim()||!Number.isSafeInteger(e.amountPaidMinor)||e.amountPaidMinor<0||!/^[a-z]{3}$/i.test(e.currency)||!Number.isFinite(new Date(e.occurredAt).getTime()))throw new Error("analytics_first_party_outcome_invalid");let r=t??{db:v(),record:(a,o)=>oi({...a,transactionClient:o})},s=await r.db.connect();try{await s.query("BEGIN");let a=await Es(s,{siteId:n,stableUserId:i});if(!a)return await s.query("ROLLBACK"),{status:"skipped",eventName:Le,reason:"identity_or_consent_unavailable"};let o={schemaVersion:1,eventId:`mcp_invoice_${e.invoiceId}`.slice(0,200),sourceEventId:`stripe:invoice:${e.invoiceId}`.slice(0,300),source:"mcp_scraper",sourceAccountRef:"first_party_billing",eventKind:"transaction",eventName:Le,occurredAt:e.occurredAt,personRef:i,orderId:e.invoiceId,valueMinor:e.amountPaidMinor,currency:e.currency.toUpperCase(),consent:{analytics:"granted",adUserData:"granted",adPersonalization:a.advertising_measurement?"granted":"denied",globalPrivacyControl:!1,occurredAt:new Date(a.effective_at).toISOString(),receiptId:a.receipt_id,policyVersion:a.policy_version,purposes:{site_analytics:"granted",enhanced_matching:"granted",advertising_measurement:a.advertising_measurement?"granted":"denied"}},properties:{product:"mcp_scraper",billingKind:"base_plan_paid_invoice",revenueProvenance:"stripe_paid_invoice"}},c=await r.record({siteId:n,event:o},s);return await s.query("COMMIT"),{status:"recorded",eventName:Le,reason:"recorded",created:c.created,conversionIds:c.conversionIds}}catch(a){throw await s.query("ROLLBACK").catch(()=>{}),a}finally{s.release()}}function ci(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}function Ie(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function bs(e){let t=e.subscription;if(t)return Ie(t);let n=e.parent;return Ie(n?.subscription_details?.subscription)}async function As(e,t){let n=await T(e);return n||!t||(n=await ke(t),n&&await Pe(n.id,e)),n}async function Is(e,t,n){let i=t.memory_subscription_id;if(!(!i||i===n))try{let r=await e.subscriptions.retrieve(i);r.status!=="canceled"&&!r.cancel_at_period_end&&await e.subscriptions.update(i,{cancel_at_period_end:!0})}catch(r){console.error("[stripe] could not wind down standalone memory subscription",i,r instanceof Error?r.message:r)}}async function Ft(e,t,n){if(!t.id||t.status!=="paid")return{status:"not_applicable",invoiceId:t.id??null};let i=t.lines.data.some(y=>{let E=ci(y);return!!E&&E in D});if(!fn(i,t.total))return{status:"not_applicable",invoiceId:t.id};let r=bs(t),a=(r?le(await e.subscriptions.retrieve(r))?.price?.id:void 0)??t.lines.data.map(ci).find(y=>!!y&&y in D),o=a?D[a]:void 0;if(!o)return{status:"not_applicable",invoiceId:t.id};let c=Ie(t.customer);if(!c)throw new Error("Paid subscription invoice has no Stripe customer");let d=await As(c,t.customer_email);if(!d)throw new Error("Paid subscription invoice does not map to an MCP Scraper account");let _=await Wt({invoiceId:t.id,userId:d.id,subscriptionId:r??d.subscription_id,tier:o.tier,concurrency:o.concurrency,creditsMc:o.credits_mc,description:`${o.label} subscription credits`,neverExpires:!!o.credits_never_expire,includedMemoryPlan:o.includes_memory?"pro":null});o.includes_memory&&(await Is(e,d,r??d.subscription_id),await z(d,F({...d,memory_plan:"pro",subscription_tier:o.tier})));let u=await Be(d);u.ok||console.warn("[stripe] scheduled-action credential sync failed:",u.error??"unknown error");try{await Ut({userId:d.id,invoiceId:t.id,amountPaidMinor:t.amount_paid,currency:t.currency,occurredAt:new Date(((t.status_transitions?.paid_at??n)||Math.floor(Date.now()/1e3))*1e3).toISOString()})}catch(y){console.error("[stripe] X-Ray paid outcome failed",{invoiceId:t.id,error:y instanceof Error?y.message:String(y)})}return{status:_.granted?"fulfilled":"already_fulfilled",invoiceId:t.id,userId:d.id,tier:o.tier}}async function di(e,t,n){let i=await e.checkout.sessions.retrieve(t,{expand:["invoice"]});if(i.mode!=="subscription")throw new Error("Checkout session is not a subscription purchase");if(i.payment_status!=="paid"&&i.payment_status!=="no_payment_required")return{status:"not_applicable",invoiceId:Ie(i.invoice)??null};let r=Ie(i.customer);if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=typeof i.invoice=="object"&&i.invoice&&!("deleted"in i.invoice)?i.invoice:await e.invoices.retrieve(Ie(i.invoice)??"");if(!s?.id)throw new Error("Paid subscription checkout has no invoice");return Ft(e,s,i.created)}var li="scale_credit_pack";function rt(e){if(typeof e=="string")return e;if(e&&typeof e=="object"&&"id"in e)return String(e.id)}function ui(e){let t=Number(e);if(!Number.isSafeInteger(t)||t<1||t>ut)throw new Error(`quantity must be a whole number from 1 to ${ut}`);return t}function Tc(e){return e.subscription_tier==="scale"}function xc(e,t){let n=ui(t);return{purchase_kind:li,account_user_id:String(e),eligible_tier:"scale",increment_quantity:String(n),increment_usd:String(he),credits_per_increment:String(lt)}}async function _i(e,t,n){let i=await e.checkout.sessions.retrieve(t);if(i.mode!=="payment"||i.metadata?.purchase_kind!==li)return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};if(i.payment_status!=="paid")return{status:"not_applicable",paymentIntentId:rt(i.payment_intent)??null};let r=rt(i.customer);if(!r)throw new Error("Paid Scale credit-pack checkout has no Stripe customer");if(n&&r!==n)throw new Error("Checkout session does not belong to this billing account");let s=ui(i.metadata.increment_quantity),a=s*he*100;if(i.currency!=="usd"||i.amount_subtotal!==a)throw new Error("Scale credit-pack checkout amount does not match the product contract");let o=await e.checkout.sessions.listLineItems(i.id,{limit:2}),c=o.data[0];if(o.data.length!==1||c?.quantity!==s||c.price?.currency!=="usd"||c.price?.unit_amount!==he*100)throw new Error("Scale credit-pack checkout line item does not match the product contract");let d=await T(r);if(!d)throw new Error("Paid Scale credit-pack checkout does not map to an MCP Scraper account");if(i.metadata.account_user_id!==String(d.id)||i.metadata.eligible_tier!=="scale")throw new Error("Scale credit-pack checkout account metadata does not match the billing account");let _=rt(i.payment_intent);if(!_)throw new Error("Paid Scale credit-pack checkout has no payment intent");let u=s*lt;return{status:(await Vt(d.id,s*Qt,Ue.TOPUP,`$${s*he} Scale credit pack (${u.toLocaleString("en-US")} credits)`,`stripe-payment-intent:${_}`,{neverExpires:!1})).duplicate?"already_fulfilled":"fulfilled",paymentIntentId:_,userId:d.id,quantity:s,credits:u}}import Ss from"stripe";import{Hono as hs}from"hono";import{waitUntil as Ns}from"@vercel/functions";var x=new Ss(process.env.STRIPE_SECRET_KEY,{apiVersion:"2026-02-25.clover"});async function Cs(e,t){if(!(!e||e===t))try{let n=await x.subscriptions.retrieve(e),i=n.items.data[0]?.price?.id,r=n.status!=="canceled"&&!n.cancel_at_period_end;i&&i in ce&&r&&await x.subscriptions.update(e,{cancel_at_period_end:!0})}catch(n){console.error("[stripe] could not wind down standalone memory subscription",e,n instanceof Error?n.message:n)}}var Rs=new hs;Rs.post("/webhooks",async e=>{let t=e.req.header("stripe-signature"),n=await e.req.text(),i;try{i=x.webhooks.constructEvent(n,t,process.env.STRIPE_WEBHOOK_SECRET)}catch{return e.json({error:"Invalid signature"},400)}try{let r=await qt(i.id,i.type,i.created);return r==="queued"&&ws(),e.json({received:!0,disposition:r})}catch(r){let s=r instanceof Error?r.message:String(r);return console.error("[stripe] webhook enqueue failed",i.id,s),e.json({error:"Webhook enqueue failed"},500)}});function ws(){let e=import("./stripe-event-worker-IJXA6T37.js").then(({drainStripeEventQueue:t})=>t({limit:10,leaseSeconds:300})).catch(t=>{console.error("[stripe] immediate queue drain failed; the scheduled drain will retry",t instanceof Error?t.message:String(t))});Ns(e)}async function Kc(e){if(e.type==="checkout.session.completed"||e.type==="checkout.session.async_payment_succeeded"){let t=e.data.object;t.mode==="payment"?await _i(x,t.id):await di(x,t.id);return}if(e.type==="invoice.created"){let t=e.data.object;mi(t)&&t.status==="draft"&&await x.invoices.update(t.id,{description:Xt,footer:Gt,custom_fields:[{name:"Pack benefit",value:"2 browsers per $5 monthly pack"},{name:"Billing cadence",value:"Monthly"}]});return}if(e.type==="invoice.paid"||e.type==="invoice.payment_succeeded"){let t=e.data.object;if(mi(t)){let i=t.customer_email?void 0:await yi(t.customer,void 0),r=t.customer_email??i?.email;if(!r)throw new Error("Paid concurrency invoice has no customer receipt email");await Os(t.id,r);return}if(t.lines.data.map(gi).find(i=>i&&i in ce))return;await Ft(x,t,e.created)}if(e.type==="customer.subscription.created"||e.type==="customer.subscription.updated"){let t=e.data.object,n=pi(t);if(n){let s=await T(t.customer);if(!s)return;let a=Re(t.status);await st(s.id,a?Ds(n):0),await at(s.id,a?t.id:null);return}let i=le(t)?.price?.id??t.items.data[0]?.price?.id;if(i&&i in ce){let s=ce[i],a=await yi(t.customer,t.customer_email);if(a){let o=Re(t.status),c=o?s.plan:"free";await oe(a.id,c,o?t.id:null),await z(a,F({...a,memory_plan:c}))}return}let r=await T(t.customer);if(!r)return;if(i&&i in D){let s=D[i],a=Re(t.status),o=a?s.tier:null;if(await ot(r.id,o,a?s.concurrency:0,a?t.id:null),s.includes_memory){let c=a?"pro":"free";a&&await Cs(r.memory_subscription_id,t.id),await oe(r.id,c,null),await z(r,F({...r,memory_plan:c}))}else r.memory_subscription_id===t.id&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"})));if(a){let c=await Be(r);c.ok||console.warn("[stripe] scheduled-action credential sync failed:",c.error??"unknown error")}}}if(e.type==="customer.subscription.deleted"){let t=e.data.object;if(pi(t)){let i=await T(t.customer);i&&(await st(i.id,0),await at(i.id,null));return}let n=le(t)?.price?.id??t.items.data[0]?.price?.id;if(n&&n in D){let i=D[n],r=await T(t.customer);r&&(await ot(r.id,null,0,null),(i.includes_memory||r.memory_subscription_id===t.id)&&(await oe(r.id,"free",null),await z(r,F({...r,memory_plan:"free"}))));return}if(n&&n in ce||await ct(t.id)){let i=await ct(t.id)??await T(t.customer);i&&(await oe(i.id,"free",null),await z(i,F({...i,memory_plan:"free"})));return}}}function mi(e){return e.lines.data.some(t=>gi(t)===dt)}async function Os(e,t){let i=(await x.invoicePayments.list({invoice:e,status:"paid",limit:10})).data.find(a=>a.status==="paid");if(!i)throw new Error("Paid concurrency invoice has no paid Stripe payment");let r;if(i.payment.type==="charge")r=i.payment.charge;else if(i.payment.type==="payment_intent"&&i.payment.payment_intent){let a=typeof i.payment.payment_intent=="string"?i.payment.payment_intent:i.payment.payment_intent.id;r=(await x.paymentIntents.retrieve(a,{expand:["latest_charge"]})).latest_charge}if(!r)throw new Error("Paid concurrency invoice has no receipt-capable charge");let s=typeof r=="string"?await x.charges.retrieve(r):r;s.receipt_email!==t&&await x.charges.update(s.id,{receipt_email:t})}function pi(e){return e.items.data.find(t=>t.price?.id===dt)}function Ds(e){let t=e.quantity??1;if(!Number.isSafeInteger(t)||t<1)throw new Error("Stripe concurrency pack quantity must be a positive safe integer");return t}function gi(e){let t=e;return t?.price?.id??t?.pricing?.price_details?.price??t?.plan?.id}async function yi(e,t){let n=await T(e);if(n)return n;if(t)return n=await ke(t),n&&await Pe(n.id,e),n}export{Oi as a,Ls as b,ln as c,gt as d,qs as e,Hs as f,_n as g,ji as h,Ws as i,Bs as j,qi as k,pn as l,Be as m,Et as n,j as o,le as p,Qs as q,Zs as r,ea as s,ze as t,Ye as u,Sn as v,dr as w,ur as x,At as y,ua as z,_a as A,ma as B,pa as C,Aa as D,wn as E,Ca as F,Ra as G,wa as H,Oa as I,Da as J,Ta as K,xa as L,La as M,$a as N,ka as O,Pa as P,Ma as Q,Ua as R,Dn as S,Fa as T,gr as U,ja as V,te as W,Ze as X,$ as Y,qa as Z,Er as _,Va as $,Ka as aa,Ja as ba,Un as ca,Fn as da,za as ea,so as fa,Bn as ga,Vn as ha,lo as ia,uo as ja,Kn as ka,po as la,Jn as ma,zn as na,Yn as oa,Xn as pa,Gn as qa,Qn as ra,it as sa,Co as ta,Ro as ua,wo as va,Oo as wa,Do as xa,To as ya,ei as za,ti as Aa,$t as Ba,ni as Ca,ii as Da,ss as Ea,Qo as Fa,Zo as Ga,ec as Ha,tc as Ia,nc as Ja,ic as Ka,rc as La,sc as Ma,ac as Na,oc as Oa,cc as Pa,dc as Qa,lc as Ra,uc as Sa,_c as Ta,mc as Ua,ri as Va,pc as Wa,yc as Xa,oi as Ya,gc as Za,fc as _a,Ft as $a,di as ab,ui as bb,Tc as cb,xc as db,_i as eb,x as fb,Rs as gb,Kc as hb};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var o="0.93.1";export{o as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{f as F,h as V,i as re,j as ae,l as $}from"./chunk-QTDLZTQ7.js";import{B as ie,ba as R,e as U,t as _,w as G,x as ne,y as oe,z as M}from"./chunk-
|
|
1
|
+
import{f as F,h as V,i as re,j as ae,l as $}from"./chunk-QTDLZTQ7.js";import{B as ie,ba as R,e as U,t as _,w as G,x as ne,y as oe,z as M}from"./chunk-UN6FVDJQ.js";import{h as L}from"./chunk-2SP57VCG.js";import{b as K}from"./chunk-6DTXIZY2.js";import{R as te,Sb as D,Xb as x,t as C}from"./chunk-WJ4XFLS4.js";import{createHash as Te,randomUUID as Ne}from"crypto";import{z as f}from"zod";async function at(e,t){!Number.isFinite(t)||t<=0||await K({op:R.CONNECTED_ACCOUNT_FEE,userId:Number(e)},()=>L({vendor:"nango_connection",units:t,unitType:"connection_month"}))}async function se(e,t){let n=[{vendor:"nango_function_run",units:t.functionRuns,unitType:"function_run"},{vendor:"nango_proxy_request",units:t.proxyRequests,unitType:"proxy_request"},{vendor:"nango_compute",units:t.computeMilliseconds/1e3,unitType:"compute_second"}];await K({op:R.CONNECTED_USAGE,userId:Number(e)},async()=>{for(let o of n)!Number.isFinite(o.units)||o.units<=0||await L(o)})}var E="connected_usage",Re="mastra_scheduler",Ie=f.object({toolName:f.string().trim().min(1).max(200).optional(),operationKind:f.enum(["read","action","sync","export","proxy","other"]).optional(),outcome:f.enum(["success","error","partial"]).optional(),requestId:f.string().trim().min(1).max(200).optional(),occurrenceId:f.string().trim().min(1).max(200).optional(),scheduleId:f.string().trim().min(1).max(200).optional(),nangoOperationId:f.string().trim().min(1).max(200).optional(),startedAt:f.string().datetime({offset:!0}).optional(),completedAt:f.string().datetime({offset:!0}).optional()}).strict(),Ae=f.object({identity:f.string().trim().min(1).max(320),idempotencyKey:f.string().trim().min(1).max(500),ratePolicyVersion:f.string().trim().min(1).max(100),connectionId:f.string().trim().min(1).max(500),providerConfigKey:f.string().trim().min(1).max(200),functionRuns:f.number().int().safe().nonnegative(),proxyRequests:f.number().int().safe().nonnegative(),computeMilliseconds:f.number().int().safe().nonnegative(),sourceSurface:f.enum(["main_mcp","mastra_scheduler","nango_reconciliation"]).default(Re),metadata:Ie.optional()}).strict(),Pe=f.object({identity:f.string().trim().min(1).max(320),ratePolicyVersion:f.string().trim().min(1).max(100)}).strict(),h=class extends Error{constructor(n,o,a,i={}){super(o);this.code=n;this.httpStatus=a;this.details=i;this.name="ConnectedUsageBillingError"}code;httpStatus;details};function z(e){return Te("sha256").update(e).digest("hex")}function xe(e){return`connected-usage:${z(e)}`}function Ue(e){return`connected-usage-debit:${z(e)}`}function Me(e){return e.trim().toLowerCase()}async function ce(e){let t=await te(Me(e));if(!t)throw new h("user_not_found","billing identity was not found",404);return t}function Oe(e){let t={toolName:e.metadata.toolName??null,operationKind:e.metadata.operationKind??null,outcome:e.metadata.outcome??null,requestId:e.metadata.requestId??null,occurrenceId:e.metadata.occurrenceId??null,scheduleId:e.metadata.scheduleId??null,nangoOperationId:e.metadata.nangoOperationId??null,startedAt:e.metadata.startedAt??null,completedAt:e.metadata.completedAt??null};return z(JSON.stringify({ratePolicyVersion:_,connectionId:e.connectionId,providerConfigKey:e.providerConfigKey,usage:e.usage,sourceSurface:e.sourceSurface,metadata:t}))}function A(e){let t=JSON.stringify(e);if(t.length>4e3)throw new h("invalid_request","connected usage metadata is too large",400);return t}function W(e){try{let t=JSON.parse(e.metadata??"");if(t.contract!=="connected_usage_receipt"||t.ratePolicyVersion!==_||typeof t.fingerprint!="string"||typeof t.connectionId!="string"||typeof t.providerConfigKey!="string"||!t.usage||!t.charge)throw new Error("invalid connected usage receipt metadata");return t}catch{throw new h("idempotency_key_conflict","the idempotency key is already bound to an incompatible billing receipt",409)}}async function H(e){let t=await C().execute({sql:"SELECT id, user_id, billing_class, source_surface, status, amount_mc, metadata FROM billing_events WHERE idempotency_key = ? LIMIT 1",args:[e]});return t.rows[0]?t.rows[0]:null}async function de(e,t){return(await C().execute({sql:`SELECT 1
|
|
2
2
|
FROM billing_events
|
|
3
3
|
WHERE user_id = ?
|
|
4
4
|
AND billing_class = ?
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{a as Tt}from"./chunk-XG6GCEUE.js";import{l as St,m as Rt,w as At}from"./chunk-M5VZVMPC.js";import{a as G,c as Oe,d as L,e as V,f as ie,j as Ie,k as Ct}from"./chunk-DT2FYN6N.js";import{b as Pt,c as Et,d as $,f as z,g as H,h as U,i as kt,k as B,n as Ot,q as It}from"./chunk-ORB4RHCK.js";import{a as Ce,b as Te,g as xe}from"./chunk-UN6FVDJQ.js";import{a as it,b as lt}from"./chunk-SH5KB4P7.js";import{a as _t,b as wt,d as vt}from"./chunk-2SP57VCG.js";import{b as yt,c as bt}from"./chunk-6DTXIZY2.js";import{c as at}from"./chunk-Y6MKMSOC.js";import{Nb as ae,Rb as Ee,Tb as ke,Va as Ae,b as Se,g as M,h as ut,hb as ht,ia as mt,j as ct,ja as gt,jb as Pe,la as ft,m as dt,o as pt,oa as Re}from"./chunk-WJ4XFLS4.js";import{request as _r}from"https";import{HttpsProxyAgent as wr}from"https-proxy-agent";var le={source:"https://\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061.com/users/zone/premium_domains",retrievedAt:"2026-09-23T20:14:30.483Z",includedStatuses:["premium","remove_candidate"],domains:["advanceautoparts.com","affitto.it","agoda.cn","albertsons.com","allpeople.com","autozone.com","bestbuy.com","bestwestern.com","billiger.de","bottlerover.com","carousell.com","carousell.com.hk","carousell.com.my","carousell.ph","carousell.sg","carsales.com.au","cdiscount.com","chewy.com","costco.com","cvs.com","despegar.com.mx","dickssportinggoods.com","dynos.es","emaxme.com","familytreenow.com","feuvert.fr","flooranddecor.com","foodlion.com","footlocker.co.uk","footlocker.com","giantfoodstores.com","gopuff.com","gplay.bg","hermes.com","hyatt.com","idealo.de","immobilienscout24.de","ingatlan.com","instacart.com","intersport.fr","joann.com","kroger.com","lazada.co.id","lazada.co.th","lazada.com.my","lazada.com.ph","lazada.sg","lazada.vn","lowes.ca","lowes.com","mcmaster.com","mediamarkt.de","mediamarkt.es","medline.com","mscdirect.com","napaonline.com","nofrills.ca","peoplefinders.com","platt.com","publicdatausa.com","realcanadiansuperstore.ca","realestate.com.au","restaurantguru.com","searchpeoplefree.com","shopee.cl","shopee.co.id","shopee.co.th","shopee.com.br","shopee.com.co","shopee.com.mx","shopee.com.my","shopee.ph","shopee.sg","shopee.tw","shopee.vn","similarweb.com","skyscanner.co.kr","skyscanner.net","stopandshop.com","target.com","temu.com","ticketmaster.com","totalwine.com","tractorsupply.com","walmart.com.mx","wayfair.com","weismarkets.com","wizzair.com","worten.pt"]};var Xr=le.source,xt=le.retrievedAt,yr=new Set(le.domains);function Z(e){let t=new URL(e).hostname.toLowerCase().replace(/\.$/,"");for(let n of yr)if(t===n||t.endsWith(`.${n}`))return"premium";return"standard"}function ue(e){for(let t of["providerProduct","billingTier","billableEvent","unitType","source","policyVersion","effectiveAt"])if(!e[t]?.trim())throw new Error(`Provider rate ${t} is required`);if(!Number.isSafeInteger(e.numeratorUsdNanos)||e.numeratorUsdNanos<0)throw new Error("Provider rate numerator must be a non-negative safe integer");if(!Number.isSafeInteger(e.denominatorUnits)||e.denominatorUnits<1)throw new Error("Provider rate denominator must be a positive safe integer");if(Number.isNaN(Date.parse(e.effectiveAt)))throw new Error("Provider rate effectiveAt must be a date");return e}function ce(e,t){if(ue(e),!Number.isSafeInteger(t)||t<0)throw new Error("Billable units must be a non-negative safe integer");let n=BigInt(e.numeratorUsdNanos)*BigInt(t),r=BigInt(e.denominatorUnits),o=(n*2n+r)/(r*2n);if(o>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Provider amount exceeds safe integer range");return Number(o)}function Mt(e=process.env){let t=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_CONTRACT_USD_PER_1000?.trim(),n=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_SOURCE?.trim(),r=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_POLICY_VERSION?.trim(),o=e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_RATE_EFFECTIVE_AT?.trim();if(!t&&!n&&!r&&!o)return null;if(!t||!n||!r||!o)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract rate requires amount, source, policy version, and effective date");let a=Number(t);if(!Number.isFinite(a)||a<0)throw new Error("Invalid \u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP contract amount");return ue({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",billingTier:"payg",billableEvent:"successful_delivery",unitType:"request",numeratorUsdNanos:Math.round(a*1e9),denominatorUnits:1e3,source:n,policyVersion:r,effectiveAt:o})}function br(e){return ue({providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api",billingTier:e,billableEvent:"transferred_byte",unitType:"byte",numeratorUsdNanos:(e==="premium"?11:8)*1e9,denominatorUnits:1e9,source:`owner_confirmed_payg_2026-09-23;\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_domain_snapshot_${xt}`,policyVersion:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061-browser-domain-tier-2026-09-23",effectiveAt:"2026-09-23T00:00:00Z"})}function to(e){return br(Z(e))}function Nt(){return ue({providerProduct:"apify_google_serp_scraperlink",billingTier:"store_pay_per_event",billableEvent:"serp_page",unitType:"page",numeratorUsdNanos:5e8,denominatorUnits:1e3,source:"https://apify.com/scraperlink/google-search-results-serp-scraper",policyVersion:"scraperlink-listing-2026-09-24",effectiveAt:"2026-09-24T00:00:00Z"})}var vr="https://api.\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061.com/request",Sr=8e3,Rr="brd.superproxy.io",Ar="44445",Pr=10*1024*1024;async function Er(e,t){let n=new URL(`http://${t.host}:${t.port}`);n.username=t.username,n.password=t.password;let r=new wr(n);try{return await new Promise((o,a)=>{let s=_r(e,{agent:r,headers:{"x-unblock-data-format":"parsed"},rejectUnauthorized:!1,signal:t.signal},i=>{let l=[],u=0;i.on("data",c=>{let p=Buffer.isBuffer(c)?c:Buffer.from(c);if(u+=p.length,u>Pr){s.destroy(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP response exceeded the maximum size"));return}l.push(p)}),i.on("end",()=>o({ok:(i.statusCode??500)>=200&&(i.statusCode??500)<300,status:i.statusCode??500,rawText:Buffer.concat(l).toString("utf8"),providerRequestId:typeof i.headers["x-response-id"]=="string"?i.headers["x-response-id"]:typeof i.headers["x-request-id"]=="string"?i.headers["x-request-id"]:null}))});s.on("error",()=>a(new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 native SERP request failed"))),s.end()})}finally{r.destroy()}}function zt(e=process.env){let t=!!(e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME?.trim()&&e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD?.trim()),n=!!((e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY||e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_API_KEY)?.trim()&&e.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE?.trim());return t||n}function m(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)?e:null}function N(e){return Array.isArray(e)?e:[]}function Ne(e){return typeof e=="string"&&e.trim()?e.trim():null}function A(e){return typeof e=="number"&&Number.isFinite(e)?e:typeof e=="string"&&e.trim()&&Number.isFinite(Number(e))?Number(e):null}function g(e,t){for(let n of t){let r=Ne(e[n]);if(r)return r}return null}function J(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return""}}function Kt(e){return{rawUrl:e,resolvedUrl:e,linkType:"plain",resolutionStatus:"not_needed"}}function kr(e){let t=e;if(typeof t=="string")try{t=JSON.parse(t)}catch{throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON")}let n=m(t);if(!n)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned an invalid payload");if(typeof n.body=="string")try{let o=JSON.parse(n.body);if(m(o))return m(o)}catch{}let r=m(n.body);return r?m(r.result)??m(r.data)??r:m(n.result)??m(n.data)??n}function j(e,t){for(let r of t){let o=N(e[r]);if(o.length)return o}let n=m(e.results);if(n)for(let r of t){let o=N(n[r]);if(o.length)return o}return[]}function K(e,t){let n=[e,m(e.results)].filter(r=>!!r);for(let r of n)for(let o of t)if(Object.prototype.hasOwnProperty.call(r,o))return{observed:!0,rawShapeValid:Array.isArray(r[o]),rawCount:N(r[o]).length};return{observed:!1,rawShapeValid:!1,rawCount:0}}function Me(e,t){let n=[e,m(e.results)].filter(r=>!!r);for(let r of n)for(let o of t){if(!Object.prototype.hasOwnProperty.call(r,o))continue;let a=m(r[o]);return{observed:!0,rawShapeValid:a!==null,rawCount:a&&Object.keys(a).length>0?1:0}}return{observed:!1,rawShapeValid:!1,rawCount:0}}function Dt(e){return j(e,["organic","organic_results","organicResults"]).flatMap((t,n)=>{let r=m(t);if(!r)return[];let o=g(r,["link","url","href"]),a=g(r,["title","name"]);if(!o||!a)return[];let s=m(r.rating)??m(r.inline_rating);return[{position:Math.max(1,Math.trunc(A(r.global_rank)??A(r.rank)??A(r.position)??n+1)),title:a,url:o,...Kt(o),domain:J(o),cite:g(r,["display_link","displayLink","cite"]),snippet:g(r,["description","snippet","text"]),isRedditStyle:J(o)==="reddit.com",inlineRating:s?{value:String(s.value??s.rating??""),count:String(s.count??s.reviews??"")}:null}]}).sort((t,n)=>t.position-n.position)}function qt(e){return j(e,["snack_pack","local","local_results","local_pack","localPack"]).flatMap((t,n)=>{let r=m(t);if(!r)return[];let o=g(r,["title","name"]);if(!o)return[];let a=N(r.extensions??r.metadata).map(Ne).filter(s=>!!s);return[{position:Math.max(1,Math.trunc(A(r.global_rank)??A(r.rank)??A(r.position)??n+1)),name:o,cid:g(r,["cid"]),rating:g(r,["rating"])??(A(r.rating)!=null?String(A(r.rating)):null),reviewCount:g(r,["reviews_cnt","reviews","review_count","reviewCount"])??(A(r.reviews_cnt)!=null?String(A(r.reviews_cnt)):A(r.reviews)!=null?String(A(r.reviews)):null),metadata:a,websiteUrl:g(r,["website","website_url","link"]),directionsUrl:g(r,["directions","directions_url"])}]})}function Jt(e){let t=m(e);return N(t?.citations??t?.sources??t?.references).flatMap(n=>{let r=m(n);if(!r)return[];let o=g(r,["link","url","href"]);return o?[{text:g(r,["title","text","name"])??J(o),href:o,...Kt(o)}]:[]})}function me(e,t=0){if(t>4)return[];if(Array.isArray(e))return e.flatMap(a=>me(a,t+1));let n=m(e);if(!n)return[];let r=g(n,["snippet","text","answer"]),o=me(n.texts??n.list??n.items,t+1);return[...r?[r]:[],...o]}function Ht(e,t){if(!t)return{detected:!1,text:null,citations:[]};let n=m(e.ai_overview)??m(e.aiOverview)??m(e.overview);if(!n)return{detected:!1,text:null,citations:[]};let r=g(n,["text","answer","description"])??(me(n.texts).join(`
|
|
2
|
+
|
|
3
|
+
`).slice(0,5e4)||null),o=Jt(n);return{detected:!!(r||o.length),text:r,citations:o}}function Ut(e,t){if(!t)return{detected:!1,text:null,citations:[]};let n=m(e.ai_mode)??m(e.aiMode);if(!n)return{detected:!1,text:null,citations:[]};let r=g(n,["text","answer","description"])??(me(n.texts).join(`
|
|
4
|
+
|
|
5
|
+
`).slice(0,5e4)||null),o=Jt(n);return{detected:!!(r||o.length),text:r,citations:o}}function Bt(e,t){return t?[...j(e,["videos","video_results"]),...j(e,["short_videos","shorts"])].flatMap(n=>{let r=m(n);if(!r)return[];let o=g(r,["link","url"]),a=g(r,["title","name"]);return!o||!a?[]:[{type:"video",title:a,channel:g(r,["channel","source"])??"",platform:J(o),duration:g(r,["duration"])??"",url:o}]}):[]}function Ft(e,t){if(!t)return[];let n=m(e.forums);return[...j(e,["discussions","forums","forum_results"]),...N(n?.items)].flatMap(r=>{let o=m(r);if(!o)return[];let a=g(o,["link","url"]),s=g(o,["title","name"]);return!a||!s?[]:[{title:s,source:g(o,["source"])??J(a),url:a}]})}function Gt(e,t){return t?j(e,["what_people_are_saying","whatPeopleSaying"]).flatMap(n=>{let r=m(n);if(!r)return[];let o=g(r,["link","url"]),a=g(r,["title","name"]);if(!o||!a)return[];let s=g(r,["platform","source"])??J(o),i=s.toLowerCase();return[{type:i.includes("reddit")?"reddit":i.includes("facebook")?"facebook":i.includes("instagram")?"instagram":i.includes("tiktok")?"tiktok":i.includes("youtube")?"youtube":i.includes("news")?"news":"unknown",title:a,url:o,source:s,platform:s,popularComment:g(r,["comment","popular_comment"]),engagement:g(r,["engagement"])??"",date:g(r,["date"])??"",duration:g(r,["duration"]),authorNote:g(r,["author_note"])}]}):[]}var Or={featuredSnippets:["featured_snippets","featured_snippet","featuredSnippet"],knowledgePanel:["knowledge","knowledge_graph","knowledgeGraph"],topStories:["top_stories","topStories"],news:["news","news_results"],images:["images","image_results"],shopping:["shopping","shopping_results"],relatedSearches:["related","related_searches","relatedSearches"],recipes:["recipes","recipe_results"],jobs:["jobs","job_results"],topAds:["top_ads"],bottomAds:["bottom_ads"],topProducts:["top_pla"],bottomProducts:["bottom_pla"],jackpotProducts:["jackpot_pla"],shortVideos:["short_videos","shorts"],localMap:["snack_pack_map"],flights:["flights"],hotels:["hotels_selection"],popularProducts:["popular_products"],weather:["weather"],currencyExchange:["currency_exchange"],latestPosts:["latest_posts"],perspectives:["perspectives"],navigation:["navigation"],chips:["chips"],spelling:["spelling"]};function de(e,t){for(let n of[e,m(e.results)])if(n){for(let r of t)if(Object.prototype.hasOwnProperty.call(n,r))return{observed:!0,value:n[r]}}return{observed:!1,value:null}}function pe(e,t,n){return e?t==null||Array.isArray(t)&&t.length===0?"observed_absent":Array.isArray(t)?n>0?"observed_present":"incomplete":m(t)?n>0?"observed_present":Object.keys(m(t)).length===0?"observed_absent":"incomplete":"incomplete":"unknown"}function Ir(e,t){let n={},r=[["localPack",["snack_pack","local","local_results","local_pack","localPack"],t.localPack],["forums",["discussions","forums","forum_results"],t.forums],["videos",["videos","video_results","short_videos","shorts"],t.videos],["aiOverview",["ai_overview","aiOverview","overview"],t.aiOverview],["whatPeopleSaying",["what_people_are_saying","whatPeopleSaying"],t.whatPeopleSaying],["entityIds",["knowledge","knowledge_graph","knowledgeGraph"],t.entityIds]];for(let[l,u,c]of r){let p=de(e,u);n[l]=pe(p.observed,p.value,c)}let o=de(e,["ai_mode","aiMode"]);n.aiMode=pe(o.observed,o.value,t.aiMode);let a=de(e,["people_also_ask","peopleAlsoAsk","related_questions","paa"]),s=N(a.value).slice(0,30).flatMap(l=>{let u=m(l);if(!u)return[];let c=g(u,["question","title"]);return c?[{question:c.slice(0,1e3),answer:g(u,["answer","snippet","text"])?.slice(0,1e4)??null,url:g(u,["link","url"])??null}]:[]});n.paaPreview=pe(a.observed,a.value,s.length);let i=[];for(let[l,u]of Object.entries(Or)){let c=de(e,u);if(!c.observed)continue;let p=m(c.value),w=(Array.isArray(c.value)?c.value:p&&(Array.isArray(p.items)||Array.isArray(p.posts))?[...N(p.items),...N(p.posts)]:[c.value]).slice(0,20).flatMap(S=>{let y=m(S);if(!y)return[];let C=g(y,["title","name","heading"]),k=g(y,["link","url","website"]),D=g(y,["description","snippet","text","summary","story"]);return!C&&!k&&!D?[]:[{title:C?.slice(0,1e3)??null,url:k,description:D?.slice(0,1e4)??null,position:A(y.global_rank)??A(y.rank)??A(y.position)??null}]});n[l]=pe(c.observed,c.value,w.length);let R=Object.fromEntries(Object.entries(p??{}).slice(0,30).flatMap(([S,y])=>/^[a-zA-Z0-9_]{1,80}$/.test(S)&&(y===null||["string","number","boolean"].includes(typeof y))?[[S,typeof y=="string"?y.slice(0,2e3):y]]:[]));i.push({name:l,attributes:R,items:w})}return{status:n,paaPreview:s,additional:i}}function Lt(e,t){let n=new Set,r=new Set(t.map(s=>s.cid).filter(s=>!!s)),o=new Set,a=(s,i=0)=>{if(i>6||s==null)return;if(Array.isArray(s)){for(let u of s)a(u,i+1);return}let l=m(s);if(l)for(let[u,c]of Object.entries(l)){let p=u.toLowerCase().replace(/[^a-z]/g,""),b=Ne(c);b&&(p==="kgid"||p==="kgmid"||p==="mid")?n.add(b):b&&p==="cid"?r.add(b):b&&p==="gcid"?o.add(b):typeof c=="object"&&a(c,i+1)}};return a(e),{entities:[],kgIds:[...n],cids:[...r],gcids:[...o]}}function Vt(e,t){let n=e instanceof Error?e.message:String(e);return t.aborted||/timeout|timed out/i.test(n)?"timeout":/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(n)?"captcha":/invalid (?:json|payload)/i.test(n)?"invalid_payload":"provider_error"}function $t(e){return e==="invalid_payload"?"invalid_payload":e==="captcha"?"serp_readiness":e==="timeout"||e==="provider_error"?"provider_transport":"pagination"}async function De(e,t=process.env,n=fetch,r=Er,o){if(e.pages!==1)throw new Error("\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP supports one page only; use Apify for two pages");let a=(t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_API_KEY||t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_API_KEY)?.trim(),s=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_ZONE?.trim(),i=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_USERNAME?.trim(),l=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PASSWORD?.trim(),u=!!(i&&l);if(!u&&(!a||!s))throw new Error("Direct SERP API is not configured");let c=Date.now(),p=bt(),b=null,w=e.location?Rt(e.location):null;if(e.location&&!w?.canonical)throw new G("query_integrity","location_unresolved",`SERP location could not be resolved without changing the query (candidates: ${w?.ambiguousCandidates??0})`);let R=w?.canonical?St(w.canonical):null,S=AbortSignal.timeout(e.includeAllSerpFeatures?33e3:Sr),y=e.signal?AbortSignal.any([e.signal,S]):S,C=1,k=[],D=[],ze=0,Ke=async d=>{let O=Date.now(),_=u?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest",I=null,q=null,Q=!1,W=!1,F=null,Y=null;if(p?.operationRunId&&(d===1||b))try{I=await $({runId:p.operationRunId,attemptNumber:o?o.attemptNumber+d-1:d,method:_,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",...d===2?{parentAttemptId:b,edgeKind:"next_phase"}:o?{parentAttemptId:o.parentAttemptId,edgeKind:"provider_fallback",retryKind:"provider_fallback"}:{},normalizedFlags:{page:d,device:e.device,hasLocation:!!e.location}}),d===1&&(b=I),q=(await H({attemptId:I,provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",providerProduct:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_api",accountScope:p.operationAccountScope??"production-default",method:_,providerStatus:"started"})).id}catch(h){throw console.warn(JSON.stringify({event:"direct_serp_telemetry_start_failed",page:d,message:h instanceof Error?h.message:String(h)})),h}let P=new URLSearchParams({q:e.query,gl:e.gl,hl:e.hl,pws:"0",num:"10",...d===2?{start:"10"}:{}}),se=at(e.recency);se&&P.set("tbs",se),e.device==="mobile"&&P.set("brd_mobile","1"),(e.includeAiOverview||e.includeAllSerpFeatures)&&P.set("brd_ai_overview","2"),R&&P.set("uule",R),u&&P.set("brd_json","1"),ze+=1;let x;try{if(u){let E=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_HOST?.trim()||Rr,X=t.\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041_SERP_PROXY_PORT?.trim()||Ar;x=await r(`https://www.google.com/search?${P}`,{username:i,password:l,host:E,port:X,signal:y})}else{let E=await n(vr,{method:"POST",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify({zone:s,url:`https://www.google.com/search?${P}`,format:"json",data_format:"parsed"}),signal:y});x={ok:E.ok,status:E.status,rawText:await E.text(),providerRequestId:E.headers.get("x-response-id")??E.headers.get("x-request-id")}}if(Y=`http_${x.status}`,q&&x.providerRequestId&&await U(q,x.providerRequestId),!x.ok)throw new Error(`\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API failed with HTTP ${x.status}`);Q=!0;let h;try{h=kr(JSON.parse(x.rawText))}catch(E){let X=E instanceof Error&&E.message!=="Unexpected end of JSON input"?E.message:"\u0042\u0072\u0069\u0067\u0068\u0074 \u0044\u0061\u0074\u0061 SERP API returned invalid JSON";throw new G("invalid_payload","invalid_provider_payload",X)}let f=Dt(h);return k.push({page:d,attempted:!0,captured:f.length>0,resultCount:f.length,requestOffset:d===2?10:0,providerRequestIdObserved:!!x.providerRequestId,...f.length===0?{failureCode:"empty_page"}:{}}),W=!0,h}catch(h){F=h;let f=Vt(h,y);if(k.some(X=>X.page===d)||k.push({page:d,attempted:!0,captured:!1,resultCount:0,requestOffset:d===2?10:0,providerRequestIdObserved:!1,failureCode:f}),d===2)throw h;let E=h instanceof G?h.stage:$t(f);throw h instanceof G?h:new G(E,f,h instanceof Error?h.message:String(h))}finally{let h=null;if(q&&Q)try{let f=Mt(t);f&&await B({receiptId:q,costState:"measured",units:1,unitType:"request",amountUsdNanos:ce(f,1),rateSource:f.source,providerProduct:f.providerProduct,billingTier:f.billingTier,billableEvent:f.billableEvent,measurementSource:"provider_http_delivery",rateNumerator:f.numeratorUsdNanos,rateDenominator:f.denominatorUnits,ratePolicyVersion:f.policyVersion,rateEffectiveAt:f.effectiveAt,providerStatus:Y??"delivered",providerDurationMs:Date.now()-O})}catch(f){console.warn(JSON.stringify({event:"direct_serp_receipt_finalize_failed",page:d,message:f instanceof Error?f.message:String(f)})),h=f}if(I&&await z({attemptId:I,status:W?"succeeded":y.aborted?"timed_out":"failed",errorCode:F?Vt(F,y):null,durationMs:Date.now()-O}).catch(f=>console.warn(JSON.stringify({event:"direct_serp_attempt_finish_failed",page:d,message:f instanceof Error?f.message:String(f)}))),h)throw h}};try{D.push({page:1,payload:await Ke(1)})}catch(d){throw d}let Je=null;if(C===2)try{D.push({page:2,payload:await Ke(2)})}catch(d){Je=d}let ir=Date.now()-c,lr=Date.now(),v=D[0].payload,ur=D.flatMap(({page:d,payload:O})=>Dt(O).map(_=>({..._,position:d===2&&_.position<=10?_.position+10:_.position,sourcePage:d}))).filter((d,O,_)=>_.findIndex(I=>Oe(I.url)===Oe(d.url))===O),je=e.includeLocalPack||e.includeAllSerpFeatures,ye=je?qt(v):[],be=K(v,["snack_pack","local","local_results","local_pack","localPack"]),cr=V({requested:je,moduleObserved:be.observed,rawCount:be.rawCount,mappedCount:ye.length,rawShapeValid:be.rawShapeValid}),Qe=e.includeAiOverview||e.includeAllSerpFeatures,We=Ht(v,Qe),Ye=e.includeForums||e.includeAllSerpFeatures,Xe=Ft(v,Ye),Ze=e.includeVideos||e.includeAllSerpFeatures,et=Bt(v,Ze),tt=e.includeWhatPeopleSaying||e.includeAllSerpFeatures,rt=Gt(v,tt),_e=m(v.forums),we=_e&&Array.isArray(_e.items)?{observed:!0,rawCount:_e.items.length,rawShapeValid:!0}:K(v,["discussions","forums","forum_results"]),ve=K(v,["videos","video_results","short_videos","shorts"]),ot={localPack:cr,forums:V({requested:Ye,moduleObserved:we.observed,rawCount:we.rawCount,mappedCount:Xe.length,rawShapeValid:we.rawShapeValid}),videos:V({requested:Ze,moduleObserved:ve.observed,rawCount:ve.rawCount,mappedCount:et.length,rawShapeValid:ve.rawShapeValid}),aiOverview:V({requested:Qe,moduleObserved:Me(v,["ai_overview","aiOverview","overview"]).observed,rawCount:Me(v,["ai_overview","aiOverview","overview"]).rawCount,mappedCount:We.detected?1:0,rawShapeValid:Me(v,["ai_overview","aiOverview","overview"]).rawShapeValid}),whatPeopleSaying:V({requested:tt,moduleObserved:K(v,["what_people_are_saying","whatPeopleSaying"]).observed,rawCount:K(v,["what_people_are_saying","whatPeopleSaying"]).rawCount,mappedCount:rt.length,rawShapeValid:K(v,["what_people_are_saying","whatPeopleSaying"]).rawShapeValid})},dr=L(1,k),pr=k.find(d=>d.page===1)?.resultCount??0,oe=k.find(d=>d.page===2)?.resultCount??0,mr=ie({query:e.query,finalQuery:e.query,canonicalLocation:w?.canonical??null,locationResolutionSource:w?.source??"not_requested",locationAmbiguousCandidates:w?.ambiguousCandidates??0,uule:R,outboundProviderMethod:u?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_native_proxy":"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_serp_rest"}),ne=Je?$t(k.find(d=>d.page===2)?.failureCode??"provider_error"):Object.values(ot).some(d=>d==="incomplete"||d==="unknown")?"optional_feature_parsing":null,gr={pagination:{...dr,providerRequestCount:ze},features:ot,queryIntegrity:mr,failureStage:ne},nt=e.includeAllSerpFeatures?(()=>{let d=D.map(({page:O,payload:_})=>{let I=qt(_),q=Ft(_,!0),Q=Bt(_,!0),W=Gt(_,!0),F=Ht(_,!0),Y=Ut(_,!0),P=Lt(_,I),se=Ir(_,{localPack:I.length,forums:q.length,videos:Q.length,aiOverview:F.detected?1:0,aiMode:Y.detected?1:0,whatPeopleSaying:W.length,entityIds:P.entities.length+P.kgIds.length+P.cids.length+P.gcids.length});return{page:O,...se,localPack:I,forums:q,videos:Q,whatPeopleSaying:W,aiOverview:F,aiMode:Y,entityIds:P}});return{status:d[0].status,paaPreview:d.flatMap(O=>O.paaPreview),additional:d.flatMap(O=>O.additional),pages:d}})():void 0,fr=new Date().toISOString(),st=Date.now()-c;return{seed:e.query,location:e.location??null,extractedAt:fr,diagnostics:{phaseTimings:{providerConnectMs:ir,serpParseMs:Date.now()-lr,totalServerMs:st},pagination:{requestedPages:C,capturedPages:C===2&&oe>0?2:1,page2Status:C===2?oe>0?"captured":"failed":"not_requested",page1OrganicCount:pr,page2OrganicCount:oe,...C===2&&oe===0?{failureCode:k.find(d=>d.page===2)?.failureCode==="captcha"?"captcha":k.find(d=>d.page===2)?.failureCode==="timeout"?"timeout":"empty_page"}:{}},completionStatus:"serp_only",problem:null,resultQuality:ne?"partial":"complete",degradedResult:!!ne,degradationReasons:[],retryRecommended:!!ne,serpCompleteness:gr},totalQuestions:0,surface:"web",aiOverview:We,aiMode:Ut(v,e.includeAllSerpFeatures),...nt?{fullSerpFeatures:nt}:{},whatPeopleSaying:rt,tree:[],flat:[],videos:et,forums:Xe,organicResults:ur,localPack:ye,entityIds:Lt(v,ye),stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:st,errorCount:0}}}var Cr="scraperlink~google-search-results-serp-scraper",ee="https://api.apify.com/v2";var T=class extends Error{constructor(n,r=null,o=!1,a=null){super(n);this.runId=r;this.retrySafe=o;this.terminalStatus=a;this.name="ApifyGoogleRunError"}runId;retrySafe;terminalStatus};function te(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:null}function re(e){return typeof e=="string"&&e.trim()?e.trim():null}function Tr(e){try{return["http:","https:"].includes(new URL(e).protocol)}catch{return!1}}function xr(e){if(typeof e!="string")return e;try{return JSON.parse(e)}catch{throw new Error("Apify searchResults is not valid JSON")}}function jt(e,t){if(!Array.isArray(e)||e.length===0)throw new Error("Apify dataset contains no search results");let n=[];for(let[a,s]of e.entries()){let i=te(s);if(!i)throw new Error("Apify dataset contains an invalid row");let l=xr(i.searchResults??i),u=te(l),c=Array.isArray(l)?l:Array.isArray(u?.results)?u.results:Array.isArray(u?.organicResults)?u.organicResults:Array.isArray(u?.organic)?u.organic:u&&(u.position!==void 0||u.title!==void 0)?[u]:null;if(!c)throw new Error("Apify dataset search result shape is unsupported");let p=Number(i.page_number??u?.page_number??a+1);if(!Number.isInteger(p)||p<1||p>t)throw new Error("Apify dataset has an unexpected page number");n.push(...c.map(b=>({row:b,page:p})))}let r=n.map(({row:a,page:s},i)=>{let l=te(a),u=l?.position,c=re(l?.title),p=re(l?.url??l?.link);if(!l||!c||!p||!Tr(p)||u!==void 0&&(!Number.isInteger(u)||u<1))throw new Error(`Apify search result ${i+1} is missing a valid position, URL, or title`);let b=re(l.description??l.snippet),w=typeof u=="number"?u:i%10+1;return{position:s>1&&w<=10?w+(s-1)*10:w,url:p,title:c,description:b}});if(r.length>t*10)throw new Error("Apify returned more results than requested");let o={page1:r.filter(a=>a.position<=10).length,page2:r.filter(a=>a.position>10).length};if(o.page1===0)throw new Error("Apify did not return the first result page");return{results:r,pageResultCounts:o}}async function ge(e,t,n,r){let o=await n(e,{headers:{Authorization:`Bearer ${t}`},signal:r});if(!o.ok)throw new Error(`Apify API returned HTTP ${o.status}`);return o.json()}function qe(e){let t=te(te(e)?.data),n=re(t?.id),r=re(t?.status);if(!n||!r)throw new Error("Apify returned an invalid run receipt");return{id:n,status:r}}async function Mr(e,t=fetch){let n=performance.now(),r=AbortSignal.timeout(9e4),o=e.signal?AbortSignal.any([e.signal,r]):r,a=e.runId,s=!1,i=null;try{if(!/^[A-Za-z0-9]+$/.test(a))throw new Error("Invalid Apify run ID");let l=qe(await ge(`${ee}/actor-runs/${a}?waitForFinish=30`,e.token,t,o));for(;["READY","RUNNING","TIMING-OUT","ABORTING"].includes(l.status);)l=qe(await ge(`${ee}/actor-runs/${a}?waitForFinish=30`,e.token,t,o));if(s=!0,i=l.status,l.status!=="SUCCEEDED")throw new Error(`Apify run ended with status ${l.status}`);let u=e.pages??1,c=await ge(`${ee}/actor-runs/${a}/dataset/items?format=json`,e.token,t,o);return{query:e.query,...jt(c,u),requestedPages:u,runId:a,elapsedMs:Math.round(performance.now()-n)}}catch(l){throw new T(l instanceof Error?l.message:String(l),a,s,i)}}async function Qt(e,t,n=fetch){let r=performance.now(),o=e.query.trim(),a=e.pages??1;if(!o||o.includes(`
|
|
6
|
+
`))throw new Error("Apify search requires one nonempty query");if(a!==1&&a!==2)throw new Error("Apify search supports one or two pages");let s=t.token.trim();if(!s)throw new Error("Apify API token is required");let i=t.maxChargeUsd??.01;if(!Number.isFinite(i)||i<=0)throw new Error("Invalid Apify charge cap");let l=AbortSignal.timeout(9e4),u=e.signal?AbortSignal.any([e.signal,l]):l,c=`${ee}/actors/${Cr}/runs?maxTotalChargeUsd=${i}&restartOnError=false&waitForFinish=30`,p=null,b=!1,w=null;try{let R=await n(c,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({keyword:o,limit:a===2?"20":"10",page:1,proxy_location:"us",include_merged:!1}),signal:u});if(!R.ok)throw new Error(`Apify run start returned HTTP ${R.status}`);let S=qe(await R.json());if(p=S.id,b=!["READY","RUNNING","TIMING-OUT","ABORTING"].includes(S.status),b&&(w=S.status),S.status!=="SUCCEEDED"&&S.status!=="READY"&&S.status!=="RUNNING")throw new Error(`Apify run ended with status ${S.status}`);if(S.status==="SUCCEEDED"){let C=await ge(`${ee}/actor-runs/${p}/dataset/items?format=json`,s,n,u);return{query:o,...jt(C,a),requestedPages:a,runId:p,elapsedMs:Math.round(performance.now()-r)}}return{...await Mr({runId:p,query:o,token:s,pages:a,signal:u},n),elapsedMs:Math.round(performance.now()-r)}}catch(R){throw R instanceof T?R:new T(R instanceof Error?R.message:String(R),p,b,w)}}var Wt="apify_google_serp",Yt="apify",Nr="apify_google_serp_scraperlink";async function Xt(e,t,n,r){let o=Nt();await B({receiptId:e,costState:"estimated",units:t,unitType:o.unitType,amountUsdNanos:ce(o,t),rateSource:o.source,providerProduct:o.providerProduct,billingTier:o.billingTier,billableEvent:o.billableEvent,measurementSource:"actor_run_succeeded",rateNumerator:o.numeratorUsdNanos,rateDenominator:o.denominatorUnits,ratePolicyVersion:o.policyVersion,rateEffectiveAt:o.effectiveAt,providerStatus:r,providerDurationMs:n})}async function Zt(e){let t=performance.now(),n=await $({runId:e.operationRunId,attemptNumber:e.attemptNumber,method:Wt,provider:Yt,parentAttemptId:e.parentAttemptId,edgeKind:e.edgeKind,retryKind:e.retryKind,normalizedFlags:{page:1,pages:e.options.pages??1,proxyLocation:"us"}}),r=await H({attemptId:n,provider:Yt,providerProduct:Nr,billingTier:"store_pay_per_event",accountScope:e.accountScope,method:Wt,providerStatus:"before_actor_start"}),o=null,a=null;try{return o=await Qt(e.options,{token:e.token},e.fetchImpl),await U(r.id,o.runId),await Xt(r.id,o.requestedPages,o.elapsedMs,"succeeded_estimated"),{...o,attemptId:n}}catch(s){throw a=s,o?Object.assign(new T("Apify cost tracking failed after run completion",o.runId),{attemptId:n}):(s instanceof T&&s.runId&&(await U(r.id,s.runId),s.terminalStatus==="SUCCEEDED"?await Xt(r.id,e.options.pages??1,Math.round(performance.now()-t),"succeeded_dataset_unavailable"):await kt({receiptId:r.id,units:e.options.pages??1,unitType:"page",providerStatus:"run_outcome_or_cost_pending"})),Object.assign(s instanceof Error?s:new Error(String(s)),{attemptId:n}))}finally{await z({attemptId:n,status:a?e.options.signal?.aborted?"timed_out":"failed":"succeeded",errorCode:a?"apify_search_failed":null,durationMs:Math.round(performance.now()-t)})}}function er(e,t=e.requestedPages){let n=e.results.map(s=>{let i=new URL(s.url).hostname.replace(/^www\./,"");return{position:s.position,title:s.title,url:s.url,rawUrl:s.url,resolvedUrl:s.url,linkType:"plain",resolutionStatus:"not_needed",domain:i,cite:null,snippet:s.description,isRedditStyle:i==="reddit.com",inlineRating:null}}),r=t===2&&e.pageResultCounts.page2>0?2:1,o=t===2&&r===1,a=L(t,[{page:1,attempted:!0,captured:!0,resultCount:e.pageResultCounts.page1,requestOffset:0,providerRequestIdObserved:!0},...t===2?[{page:2,attempted:!0,captured:!o,resultCount:e.pageResultCounts.page2,requestOffset:10,providerRequestIdObserved:!0,...o?{failureCode:"empty_page"}:{}}]:[]]);return{seed:e.query,location:null,extractedAt:new Date().toISOString(),diagnostics:{phaseTimings:{providerConnectMs:e.elapsedMs,totalServerMs:e.elapsedMs},pagination:{requestedPages:t,capturedPages:r,page2Status:t===2?o?"failed":"captured":"not_requested",page1OrganicCount:e.pageResultCounts.page1,page2OrganicCount:e.pageResultCounts.page2},completionStatus:"serp_only",problem:null,resultQuality:o?"partial":"complete",degradedResult:o,degradationReasons:o?["page_two_missing"]:[],retryRecommended:!1,serpCompleteness:{pagination:a,features:{localPack:"not_requested",forums:"not_requested",videos:"not_requested",aiOverview:"not_requested",whatPeopleSaying:"not_requested"},queryIntegrity:ie({query:e.query,finalQuery:e.query,locationResolutionSource:"not_requested",outboundProviderMethod:"default_search"}),failureStage:null}},totalQuestions:0,surface:"web",aiOverview:{detected:!1,text:null,citations:[],shareUrl:null},aiMode:{detected:!1,text:null,citations:[]},whatPeopleSaying:[],tree:[],flat:[],videos:[],forums:[],organicResults:n,localPack:[],entityIds:{entities:[],kgIds:[],cids:[],gcids:[]},stats:{seed:e.query,totalQuestions:0,maxDepthReached:0,durationMs:e.elapsedMs,errorCount:0}}}var Dr=12e3;async function He(e){if(e.mode==="full")return Hr(e);if(!e.token)throw new Error("Apify search is not configured");let t=performance.now(),n;for(let o=1;o<=2;o++){let a=AbortSignal.any([e.signal,AbortSignal.timeout(Dr)]),s=e.pages===2&&o===2?1:e.pages;try{let i=await Zt({options:{query:e.query,pages:s,signal:a},token:e.token,operationRunId:e.operationRunId,accountScope:e.accountScope,attemptNumber:o,...n?{parentAttemptId:n,edgeKind:"same_method_retry",retryKind:"same_method"}:{}});console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"apify",operationRunId:e.operationRunId,attemptNumber:o,durationMs:i.elapsedMs,resultCount:i.results.length,requestedPages:e.pages,providerRequestedPages:i.requestedPages,deliveredPages:i.pageResultCounts.page2>0?2:1,runId:i.runId}));let l=er(i,e.pages);return l.stats.durationMs=Math.round(performance.now()-t),l.diagnostics.phaseTimings&&(l.diagnostics.phaseTimings.totalServerMs=l.stats.durationMs),{result:l,mode:"light",deliveryProvider:"apify",deliveredPages:i.pageResultCounts.page2>0?2:1}}catch(i){n=i&&typeof i=="object"&&"attemptId"in i?String(i.attemptId):void 0;let l=i instanceof T?i:null;if(console.warn(JSON.stringify({event:"serp_provider_failed",provider:"apify",operationRunId:e.operationRunId,attemptNumber:o,runId:l?.runId??null,requestedPages:e.pages,attemptPages:s,retrySafe:l?.retrySafe===!0,error:i instanceof Error?i.message:String(i)})),e.signal.aborted||!n||l?.retrySafe!==!0)throw i}}if(!n)throw new Error("Search attempt receipt is missing");let r={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,includeAllSerpFeatures:!1,includeLocalPack:!1,includeForums:!1,includeVideos:!1,includeAiOverview:!1,includeWhatPeopleSaying:!1,signal:e.signal};console.info(JSON.stringify({event:"serp_provider_fallback",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,requestedPages:e.pages,providerRequestedPages:1}));try{let o=await De(r,process.env,fetch,void 0,{attemptNumber:3,parentAttemptId:n});if(o.organicResults.length===0)throw new Error("Search returned no organic results");return e.pages===2&&qr(o),o.stats.durationMs=Math.round(performance.now()-t),o.diagnostics.phaseTimings&&(o.diagnostics.phaseTimings.totalServerMs=o.stats.durationMs),console.info(JSON.stringify({event:"serp_provider_succeeded",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,durationMs:o.stats.durationMs,resultCount:o.organicResults.length,requestedPages:e.pages,providerRequestedPages:1,deliveredPages:1,resultQuality:o.diagnostics.resultQuality})),{result:o,mode:"light",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:1}}catch(o){throw console.warn(JSON.stringify({event:"serp_provider_failed",provider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",operationRunId:e.operationRunId,attemptNumber:3,error:o instanceof Error?o.message:String(o)})),o}}function qr(e){let t=e.organicResults.length,n=e.diagnostics.pagination;n&&(n.requestedPages=2,n.capturedPages=1,n.page2Status="failed",n.page2OrganicCount=0),e.diagnostics.resultQuality="partial",e.diagnostics.degradedResult=!0,e.diagnostics.degradationReasons=["page_two_missing"];let r=e.diagnostics;if(r.serpCompleteness){let o=r.serpCompleteness.pagination.evidence.find(a=>a.page===1);r.serpCompleteness.pagination={...L(2,[{page:1,attempted:!0,captured:!0,resultCount:t,requestOffset:0,providerRequestIdObserved:o?.providerRequestIdObserved??!1},{page:2,attempted:!0,captured:!1,resultCount:0,requestOffset:10,providerRequestIdObserved:!1,failureCode:"provider_error"}]),providerRequestCount:r.serpCompleteness.pagination.providerRequestCount}}}async function Hr(e){if(e.pages===2){let o=await He({...e,mode:"light",pages:2}),a=Object.fromEntries(["localPack","forums","videos","aiOverview","aiMode","whatPeopleSaying","entityIds","paaPreview","topStories"].map(i=>[i,"unsupported"]));o.result.fullSerpFeatures={status:a,paaPreview:[],additional:[],pages:[]};let s=o.result.diagnostics;return s.serpCompleteness&&(s.serpCompleteness.features={localPack:"unsupported",forums:"unsupported",videos:"unsupported",aiOverview:"unsupported",whatPeopleSaying:"unsupported"}),{...o,mode:"full"}}let t=performance.now(),n={query:e.query,gl:"us",hl:"en",device:"desktop",pages:1,includeAllSerpFeatures:!0,includeLocalPack:!0,includeForums:!0,includeVideos:!0,includeAiOverview:!0,includeWhatPeopleSaying:!0,signal:e.signal},r=await De(n);if(r.organicResults.length===0)throw new Error("Full Search returned no organic results");return r.stats.durationMs=Math.round(performance.now()-t),r.diagnostics.phaseTimings&&(r.diagnostics.phaseTimings.totalServerMs=r.stats.durationMs),{result:r,mode:"full",deliveryProvider:"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061",deliveredPages:r.diagnostics.pagination?.capturedPages===2?2:1}}async function Ue(e,t,n=3){for(let r=1;r<=n;r++){try{let o=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(1e4)});if(o.ok)return;console.warn(`[webhook] attempt ${r} \u2192 ${o.status} from ${e}`)}catch(o){console.warn(`[webhook] attempt ${r} failed:`,o instanceof Error?o.message:o)}r<n&&await new Promise(o=>setTimeout(o,1e3*r*2))}console.error(`[webhook] gave up after ${n} attempts for ${e}`)}function Ur(e){return e instanceof Error?e.message:String(e)}function Br(e,t){return e instanceof DOMException&&(e.name==="TimeoutError"||e.name==="AbortError")?!0:/timeout|timed out|Timeout \d+ms exceeded|deadline/i.test(t)}function Fr(e){return/captcha|recaptcha|unusual traffic|google\.com\/sorry|blocked/i.test(e)}function Gr(e){return/ERR_TUNNEL_CONNECTION_FAILED|ERR_PROXY_CONNECTION_FAILED|ERR_SOCKS_CONNECTION_FAILED|tunnel connection failed|proxy connection failed|transport error: proxy/i.test(e)}function Lr(e){return/proxy unavailable|proxy_unavailable|connection_test_failed|did not return a proxy id|configured fallback/i.test(e)}function Vr(e){return/(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\/\/\S*dashboard/i.test(e)}function $r(e){return/browser (?:has been )?closed|context (?:has been )?closed|target page, context or browser has been closed|session closed|page has been closed/i.test(e)}function Be(e){let t=Ur(e);return e instanceof dt?{error_code:"request_aborted",error_type:"request_aborted",message:M("request_aborted"),retryable:!0,httpStatus:408,terminalStatus:"cancelled"}:e instanceof ct||Fr(t)?{error_code:"captcha_exhausted",error_type:"captcha",message:M("captcha_exhausted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Tt(e,t)?{error_code:"vendor_unavailable",error_type:"service_unavailable",message:M("vendor_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:e instanceof pt?{error_code:"location_mismatch",error_type:"location_mismatch",message:M("location_mismatch"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Gr(t)?{error_code:"proxy_tunnel_failed",error_type:"connection",message:M("proxy_tunnel_failed"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Lr(t)?{error_code:"proxy_unavailable",error_type:"connection",message:M("proxy_unavailable"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:$r(t)?{error_code:"browser_session_interrupted",error_type:"extraction",message:M("browser_session_interrupted"),retryable:!0,httpStatus:503,terminalStatus:"failed"}:Br(e,t)?{error_code:"harvest_timeout",error_type:"timeout",message:M("harvest_timeout"),retryable:!0,httpStatus:504,terminalStatus:"failed"}:Vr(t)?{error_code:"service_unavailable",error_type:"service_unavailable",message:Se,retryable:!0,httpStatus:503,terminalStatus:"failed"}:{error_code:"extraction_failed",error_type:"extraction",message:Se,retryable:!1,httpStatus:500,terminalStatus:"failed"}}function Fe(e){return JSON.stringify({error_code:e.error_code,error_type:e.error_type,message:e.message,retryable:e.retryable})}function fe(e,t={}){let n=ut({errorCode:e.error_code,errorType:e.error_type,retryable:e.retryable,retryAfterSeconds:t.retryAfterSeconds,chargeStatus:t.chargeStatus,details:t.details});return{error:n.message,...n}}function Ge(e,t={}){let{error:n,...r}=fe(e,t);return r}function Io(e,t={}){let n=Be(e);return{body:fe(n,t),status:n.httpStatus}}import{createHash as zr}from"crypto";var Kr=1e9;function Jr(e){return zr("sha256").update(JSON.stringify(e)).digest("hex")}function he(e){return`harvest:${e}`}async function Do(e){let t=he(e.jobId);try{return(await Pt({id:t,userId:e.userId,ownerScope:`user:${e.userId}`,tool:e.tool,normalizedFlags:e.normalizedFlags,idempotencyKey:`job:${e.jobId}`,requestFingerprint:Jr(e.normalizedFlags),jobId:e.jobId,requestId:e.requestId??null,deploymentCommit:process.env.VERCEL_GIT_COMMIT_SHA?.trim()||process.env.GIT_COMMIT_SHA?.trim()||null})).id}catch(n){return console.warn(JSON.stringify({event:"operation_run_start_failed",job_id:e.jobId,tool:e.tool,message:n instanceof Error?n.message:String(n)})),null}}async function Ve(e,t,n){if(e)try{await Et({runId:e,status:t,failureClass:n})}catch(r){console.warn(JSON.stringify({event:"operation_run_finish_failed",operation_run_id:e,message:r instanceof Error?r.message:String(r)}))}}async function qo(e,t,n,r){if(!(!e||!t))try{await Ot({runId:e,billingTable:"billing_debits",billingKey:t,relation:n,amountMc:r})}catch(o){console.warn(JSON.stringify({event:"operation_billing_link_failed",operation_run_id:e,relation:n,message:o instanceof Error?o.message:String(o)}))}}function Le(e){return e==="timeout"?"timed_out":e==="request_aborted"?"cancelled":e==="browser_session_interrupted"?"interrupted":e==="captcha"||e==="proxy_tunnel_failed"||e==="proxy_unavailable"||e==="location_mismatch"||e==="error"?"failed":"succeeded"}function jr(e){return e==="\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061":"\u006b\u0065\u0072\u006e\u0065\u006c"}function tr(e,t,n=0){let r=new Map,o=null;return async a=>{if(e)try{if(a.type==="started"){let i=n+a.attemptNumber;if(i>1&&!o){let p=(await It(e))?.attempts.at(-1);o=p?.id==null?null:String(p.id)}let l=await $({runId:e,attemptNumber:i,method:a.method,provider:a.provider,parentAttemptId:i===1?null:o,edgeKind:i===1?null:n>0&&a.attemptNumber===1?"durable_resume":a.retryKind==="provider_fallback"?"provider_fallback":"same_method_retry",retryKind:i===1?null:n>0&&a.attemptNumber===1?"durable_resume":a.retryKind,retryReason:i===1?null:n>0&&a.attemptNumber===1?"durable_worker_resume":a.retryReason,retryOwner:i===1?null:n>0&&a.attemptNumber===1?"durable_reconciler":"harvest",normalizedFlags:{maxAttempts:a.maxAttempts,maxQuestions:a.maxQuestions,hasLocation:!!a.location,plannedProvider:a.provider,planReason:a.planReason??null,planTimeoutMs:a.planTimeoutMs??null},startedAt:a.startedAt}),u=await H({attemptId:l,provider:a.provider,providerProduct:a.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:a.provider==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Z("https://www.google.com/search"):null,accountScope:t,method:a.method,providerStatus:"started"});r.set(a.attemptNumber,{attemptId:l,receiptId:u.id,plannedProvider:a.provider,observedProvider:null,providerMismatch:!1,method:a.method,startedAtMs:Date.parse(a.startedAt),billingMode:null}),o=l;return}let s=r.get(a.attemptNumber);if(!s)throw new Error(`Missing operation attempt state for attempt ${a.attemptNumber}`);if(a.type==="provider_session_started"){let i=jr(a.provider);if(s.observedProvider=i,s.billingMode=a.billingMode??null,i!==s.plannedProvider){s.providerMismatch=!0,await B({receiptId:s.receiptId,costState:"unavailable",providerStatus:"provider_mismatch",errorCode:"provider_mismatch",errorMessage:`Planned ${s.plannedProvider}; observed ${i}`,finalizedAt:a.observedAt});let l=i==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",u=await H({attemptId:s.attemptId,provider:i,providerProduct:i==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?"\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061_browser_api":"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:i==="\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061"?Z("https://www.google.com/search"):null,accountScope:t,method:l,providerStatus:"observed_provider_mismatch"});s.receiptId=u.id,s.method=l}await U(s.receiptId,a.providerSessionId);return}if(await z({attemptId:s.attemptId,status:s.providerMismatch?"failed":Le(a.outcome),errorCode:s.providerMismatch?"provider_mismatch":Le(a.outcome)==="succeeded"?null:a.outcome,errorMessage:a.error,durationMs:a.durationMs,endedAt:a.completedAt}),(s.observedProvider??s.plannedProvider)==="\u006b\u0065\u0072\u006e\u0065\u006c"){let i=s.billingMode==="headful",l=s.billingMode==="headless"||s.billingMode==="headful"?vt(a.durationMs,i):null;await B({receiptId:s.receiptId,costState:"estimated",units:a.durationMs/1e3,unitType:"wall_open_second",amountUsdNanos:l==null?null:Math.round(l*Kr),providerProduct:"\u006b\u0065\u0072\u006e\u0065\u006c_browser",billingTier:s.billingMode,billableEvent:"provider_active_gb_second",measurementSource:"wall_open_time_proxy",rateSource:l!=null?`\u006b\u0065\u0072\u006e\u0065\u006c_${s.billingMode}_usd_per_second:${i?wt:_t}`:null,providerStatus:s.providerMismatch?"provider_mismatch":a.outcome,providerDurationMs:a.durationMs,errorCode:s.providerMismatch?"provider_mismatch":Le(a.outcome)==="succeeded"?null:a.outcome,errorMessage:a.error,finalizedAt:a.completedAt})}}catch(s){console.warn(JSON.stringify({event:"operation_attempt_telemetry_failed",operation_run_id:e,attempt_number:a.attemptNumber,message:s instanceof Error?s.message:String(s)}))}}}function rr(e,t,n=null,r="production-default",o=0){let a=tr(n,r,o);return async s=>{if(await a(s),s.type==="started"){await mt({jobId:e,userId:t,attemptNumber:s.attemptNumber,maxAttempts:s.maxAttempts,query:s.query,location:s.location,maxQuestions:s.maxQuestions,startedAt:s.startedAt});return}if(s.type==="provider_session_started"){await gt({jobId:e,attemptNumber:s.attemptNumber,browserProvider:s.provider,providerSessionId:s.providerSessionId,observedAt:s.observedAt});return}await ft({jobId:e,attemptNumber:s.attemptNumber,outcome:s.outcome,\u006b\u0065\u0072\u006e\u0065\u006cSessionId:s.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,questionCount:s.questionCount,durationMs:s.durationMs,error:s.error,willRetry:s.willRetry,\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted,\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded,\u006b\u0065\u0072\u006e\u0065\u006cDeleteError:s.cleanup.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,browserCloseSucceeded:s.cleanup.browserCloseSucceeded,browserCloseError:s.cleanup.browserCloseError,browserProvider:s.cleanup.provider??null,providerSessionId:s.cleanup.providerSessionId??null,providerLookupStatus:s.cleanup.providerSessionId?"pending":"not_applicable",providerErrorCode:s.cleanup.providerDisconnectObserved?"browser_session_interrupted":null,providerErrorMessage:s.cleanup.providerDisconnectMessage??null,providerReasonSource:s.cleanup.providerDisconnectObserved?"client_runtime":null,providerDisconnectObserved:s.cleanup.providerDisconnectObserved??!1,providerDisconnectMessage:s.cleanup.providerDisconnectMessage??null,debug:s.debug,completedAt:s.completedAt})}}var or=2,$e=0;function nr(e){if(!e||typeof e!="object")return 0;let t=e;return typeof t.totalQuestions=="number"?t.totalQuestions:Array.isArray(t.flat)?t.flat.length:0}function sr(e){return Ce.paa_base+Math.max(1,e)*Ce.paa}async function ar(e){$e++;try{let t=typeof e.options=="string"?JSON.parse(e.options):e.options,n={value:null},r=null,o=t.serpOnly&&!t.serpIdentity,a=he(e.id),s=process.env.APIFY_API_TOKEN?.trim();if(o&&(t.pages===2?!s:!zt()||t.mode!=="full"&&!s))throw new Error("Search providers are not configured");let i=await yt({op:t.serpOnly?"serp":"paa",userId:Number(e.user_id),headlessSentOut:n,operationRunId:a,operationAccountScope:"production-default"},()=>o?He({query:t.query??e.query,pages:t.pages===2?2:1,token:s,mode:t.mode,operationRunId:a,accountScope:"production-default",signal:AbortSignal.timeout(it(t.maxQuestions??30,!0,t.mode,t.pages).serverMs)}).then(u=>(r=u,u.result)):At({...t,\u006b\u0065\u0072\u006e\u0065\u006cApiKey:lt(),headless:!0,format:"json",outputDir:"/tmp/paa-output-api",onAttemptEvent:rr(e.id,e.user_id,a)}));if(o&&!r)throw new Error("Search provider billing receipt is missing");await ht(e.id,i),await Ve(a,"succeeded");let l=await Re(e.id,e.user_id);if(typeof t.billingHoldMc=="number"&&t.billingDebitKey){let u=t.serpOnly?o?xe(r.deliveredPages,r.deliveryProvider):Te(n.value):sr(nr(i));await ke(Number(e.user_id),t.billingDebitKey,u,t.serpOnly?"serp_refund":"paa_refund",t.serpOnly?"SERP search settlement":"PAA harvest settlement",t.serpOnly?"serp_search":"paa_harvest")}else if(!t.serpOnly&&typeof t.billingHoldMc=="number"){let u=sr(nr(i)),c=t.billingHoldMc-u;c>0?await ae(e.user_id,c,"paa_refund","overestimate refund"):c<0&&await Ee(e.user_id,-c,"paa",t.query??e.query)}else if(t.serpOnly&&typeof t.billingHoldMc=="number"){let u=o?xe(r.deliveredPages,r.deliveryProvider):Te(n.value),c=t.billingHoldMc-u;c>0?await ae(e.user_id,c,"serp_refund","headless-mode pricing settle"):c<0&&await Ee(e.user_id,-c,"serp",t.query??e.query)}e.callback_url&&await Ue(e.callback_url,{job_id:e.id,status:"done",result:Ct(i),attempts:Ie(l)})}catch(t){console.error("[harvest/worker] failed",{jobId:e.id,error:t instanceof Error?t.message:String(t)});let n=Be(t);await Ve(he(e.id),n.error_code==="harvest_timeout"?"timed_out":n.terminalStatus,n.error_code);let r=typeof e.options=="string"?JSON.parse(e.options):e.options,o=typeof r.billingHoldMc=="number"&&r.billingHoldMc>0;await Pe(e.id,Fe(n),Ge(n,{chargeStatus:o?"refund_pending":"not_charged"}));let a=await Re(e.id,e.user_id);try{o&&(r.billingDebitKey?await ke(Number(e.user_id),r.billingDebitKey,0,r.serpOnly?"serp_refund":"paa_refund","failed call",r.serpOnly?"serp_search":"paa_harvest"):await ae(e.user_id,r.billingHoldMc,"refund","failed call"),await Pe(e.id,Fe(n),Ge(n,{chargeStatus:"refunded"})))}catch{}e.callback_url&&await Ue(e.callback_url,{job_id:e.id,status:"failed",...fe(n),attempts:Ie(a)})}finally{$e--}}async function Qr(){let e=await Ae();if(!e)return{claimed:!1};let t=Date.now();return await ar(e),{claimed:!0,jobId:e.id,completed:!0,durationMs:Date.now()-t}}async function en(e){let t=[];for(let n=0;n<e.maxJobs&&!(Date.now()>=e.deadlineMs);n++){let r=await Qr();if(t.push(r),!r.claimed)break}return t}function tn(){setInterval(async()=>{if($e>=or)return;let e=await Ae();e&&ar(e)},2e3),console.log(`[worker] started \u2014 polling every 2s, max ${or} concurrent`)}export{Z as a,ce as b,br as c,to as d,zt as e,He as f,Be as g,Fe as h,fe as i,Ge as j,Io as k,he as l,Do as m,Ve as n,qo as o,rr as p,Ue as q,Qr as r,en as s,tn as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{k as K}from"./chunk-
|
|
1
|
+
import{k as K}from"./chunk-IJF4VXJ7.js";import{a as X}from"./chunk-QTDLZTQ7.js";import{c as J,d as H}from"./chunk-HUV2WTRW.js";import{t as f}from"./chunk-WJ4XFLS4.js";import{createHash as U,createHmac as re,timingSafeEqual as he}from"crypto";import{createHash as fe,randomUUID as Y}from"crypto";var ge=1440*60*1e3,F=5e3,h=class extends Error{constructor(n,i,o=400){super(i);this.code=n;this.status=o;this.name="GmailSelectionError"}code;status},k=null,P=null;function $(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map($).join(",")}]`:`{${Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>`${JSON.stringify(t)}:${$(n)}`).join(",")}}`}function b(e){return fe("sha256").update($(e)).digest("hex")}async function x(){let e=f();return k&&P===e||(P=e,k=(async()=>{await e.execute(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS gmail_selections (
|
|
3
3
|
selection_id TEXT PRIMARY KEY,
|
|
4
4
|
owner_identity TEXT NOT NULL,
|