mcp-scraper 0.43.3 → 0.43.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bin/api-server.cjs +170 -76
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +1 -1
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +4 -4
- package/dist/bin/paa-harvest.cjs +42 -22
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +3 -3
- package/dist/{chunk-FCFQ634B.js → chunk-5X7CJEK3.js} +25 -8
- package/dist/chunk-5X7CJEK3.js.map +1 -0
- package/dist/chunk-H4RPUFRR.js +7 -0
- package/dist/chunk-H4RPUFRR.js.map +1 -0
- package/dist/{chunk-ZBQ6EXZW.js → chunk-OVD4E4AP.js} +2 -2
- package/dist/{chunk-H7LQ6PTI.js → chunk-RJMOOII7.js} +50 -24
- package/dist/chunk-RJMOOII7.js.map +1 -0
- package/dist/{chunk-CHC3RCFA.js → chunk-RSGUS5V6.js} +3 -3
- package/dist/{chunk-DAS7L4SF.js → chunk-T5AFM4G5.js} +4 -2
- package/dist/chunk-T5AFM4G5.js.map +1 -0
- package/dist/{chunk-QOWBJ4YY.js → chunk-WT2UHDSE.js} +2 -2
- package/dist/{chunk-GUI33Q27.js → chunk-WWIJ2NID.js} +2 -2
- package/dist/{db-C5ELI55I.js → db-4ABEYNDM.js} +4 -2
- package/dist/{extract-bundle-IOM45SFL.js → extract-bundle-ITPFWRNI.js} +3 -3
- package/dist/index.cjs +42 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/{location-data-repository-SHEOIBTL.js → location-data-repository-HDNCU4Z4.js} +3 -3
- package/dist/{server-7CLMCX42.js → server-BTDXZA5U.js} +101 -57
- package/dist/server-BTDXZA5U.js.map +1 -0
- package/dist/{site-extract-repository-XNI4ZK2M.js → site-extract-repository-CKCJDP7N.js} +3 -3
- package/dist/{worker-2LIOH744.js → worker-73AYU4IK.js} +5 -5
- package/package.json +3 -1
- package/dist/chunk-4LQVW2EK.js +0 -7
- package/dist/chunk-4LQVW2EK.js.map +0 -1
- package/dist/chunk-DAS7L4SF.js.map +0 -1
- package/dist/chunk-FCFQ634B.js.map +0 -1
- package/dist/chunk-H7LQ6PTI.js.map +0 -1
- package/dist/server-7CLMCX42.js.map +0 -1
- /package/dist/{chunk-ZBQ6EXZW.js.map → chunk-OVD4E4AP.js.map} +0 -0
- /package/dist/{chunk-CHC3RCFA.js.map → chunk-RSGUS5V6.js.map} +0 -0
- /package/dist/{chunk-QOWBJ4YY.js.map → chunk-WT2UHDSE.js.map} +0 -0
- /package/dist/{chunk-GUI33Q27.js.map → chunk-WWIJ2NID.js.map} +0 -0
- /package/dist/{db-C5ELI55I.js.map → db-4ABEYNDM.js.map} +0 -0
- /package/dist/{extract-bundle-IOM45SFL.js.map → extract-bundle-ITPFWRNI.js.map} +0 -0
- /package/dist/{location-data-repository-SHEOIBTL.js.map → location-data-repository-HDNCU4Z4.js.map} +0 -0
- /package/dist/{site-extract-repository-XNI4ZK2M.js.map → site-extract-repository-CKCJDP7N.js.map} +0 -0
- /package/dist/{worker-2LIOH744.js.map → worker-73AYU4IK.js.map} +0 -0
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
harvest
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RJMOOII7.js";
|
|
4
4
|
import {
|
|
5
5
|
recordVendorUsage
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-T5AFM4G5.js";
|
|
7
7
|
import "./chunk-3ZUBQQPQ.js";
|
|
8
8
|
import "./chunk-5UN33CGU.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-5X7CJEK3.js";
|
|
10
10
|
|
|
11
11
|
// src/video/VideoGenerator.ts
|
|
12
12
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
parseHostedCensusPlacesCsv,
|
|
14
14
|
parseHostedZipGroupsCsv,
|
|
15
15
|
queryHostedLocationMarkets
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-WT2UHDSE.js";
|
|
17
17
|
import "./chunk-G3P3ZDB4.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-5X7CJEK3.js";
|
|
19
19
|
export {
|
|
20
20
|
HOSTED_CENSUS_DATASET_PREFIX,
|
|
21
21
|
HOSTED_ZIP_DATASET_KIND,
|
|
@@ -32,4 +32,4 @@ export {
|
|
|
32
32
|
parseHostedZipGroupsCsv,
|
|
33
33
|
queryHostedLocationMarkets
|
|
34
34
|
};
|
|
35
|
-
//# sourceMappingURL=location-data-repository-
|
|
35
|
+
//# sourceMappingURL=location-data-repository-HDNCU4Z4.js.map
|
|
@@ -10,14 +10,14 @@ import {
|
|
|
10
10
|
importHostedCensusPlacesCsv,
|
|
11
11
|
importHostedZipGroupsCsv,
|
|
12
12
|
listActiveHostedLocationDatasets
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WT2UHDSE.js";
|
|
14
14
|
import {
|
|
15
15
|
classifyHarvestProblem,
|
|
16
16
|
createHarvestAttemptRecorder,
|
|
17
17
|
deliverWebhook,
|
|
18
18
|
harvestProblemResponse,
|
|
19
19
|
serializeHarvestProblem
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-OVD4E4AP.js";
|
|
21
21
|
import {
|
|
22
22
|
AIModeSelectors,
|
|
23
23
|
AIOverviewSelectors,
|
|
@@ -35,13 +35,16 @@ import {
|
|
|
35
35
|
cleanupBackupProxyId,
|
|
36
36
|
createBackupProxyIdSafe,
|
|
37
37
|
deleteKernelProxyId,
|
|
38
|
+
detectPageUserAgent,
|
|
39
|
+
detectRuntimeUserAgent,
|
|
38
40
|
encodeUule,
|
|
39
41
|
harvest,
|
|
40
42
|
normalizeLocation,
|
|
41
43
|
resolveBackupKernelProxyId,
|
|
42
44
|
resolveKernelProxyId,
|
|
43
|
-
serpArrivalUrl
|
|
44
|
-
|
|
45
|
+
serpArrivalUrl,
|
|
46
|
+
withRuntimeUserAgent
|
|
47
|
+
} from "./chunk-RJMOOII7.js";
|
|
45
48
|
import {
|
|
46
49
|
ApiErrorResponseSchema,
|
|
47
50
|
ArtifactTemplateConfigSchema,
|
|
@@ -83,7 +86,7 @@ import {
|
|
|
83
86
|
renewDirectoryArtifactDownload,
|
|
84
87
|
resolveDeploymentProfile,
|
|
85
88
|
transcribeMediaUrl
|
|
86
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-RSGUS5V6.js";
|
|
87
90
|
import {
|
|
88
91
|
auditImageUrls,
|
|
89
92
|
auditImages,
|
|
@@ -111,7 +114,7 @@ import {
|
|
|
111
114
|
recordKernelSession,
|
|
112
115
|
recordVendorUsage,
|
|
113
116
|
runWithCostContext
|
|
114
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-T5AFM4G5.js";
|
|
115
118
|
import {
|
|
116
119
|
listWorkflowDefinitions,
|
|
117
120
|
runWorkflow,
|
|
@@ -139,7 +142,7 @@ import {
|
|
|
139
142
|
} from "./chunk-3ZUBQQPQ.js";
|
|
140
143
|
import {
|
|
141
144
|
PACKAGE_VERSION
|
|
142
|
-
} from "./chunk-
|
|
145
|
+
} from "./chunk-H4RPUFRR.js";
|
|
143
146
|
import {
|
|
144
147
|
abandonExtractSettlement,
|
|
145
148
|
countSuccessfulPages,
|
|
@@ -162,7 +165,7 @@ import {
|
|
|
162
165
|
setExtractJobTotal,
|
|
163
166
|
settleExtractJob,
|
|
164
167
|
terminalExtractJobStatus
|
|
165
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-WWIJ2NID.js";
|
|
166
169
|
import {
|
|
167
170
|
BROWSER_OPEN_MIN_BALANCE_MC,
|
|
168
171
|
CONCURRENCY_PRICE_ID,
|
|
@@ -318,7 +321,7 @@ import {
|
|
|
318
321
|
startHarvestAttempt,
|
|
319
322
|
upsertPageSnapshot,
|
|
320
323
|
verifyPassword
|
|
321
|
-
} from "./chunk-
|
|
324
|
+
} from "./chunk-5X7CJEK3.js";
|
|
322
325
|
|
|
323
326
|
// src/blog/registry.ts
|
|
324
327
|
var posts = [
|
|
@@ -3749,10 +3752,10 @@ async function fetchWithKernel(url) {
|
|
|
3749
3752
|
const kb = await client2.browsers.create({ stealth: true, ...useHeadless ? { headless: true } : {}, timeout_seconds: 60 });
|
|
3750
3753
|
const browser = await chromium.connectOverCDP(kb.cdp_ws_url);
|
|
3751
3754
|
try {
|
|
3752
|
-
const
|
|
3753
|
-
|
|
3755
|
+
const runtimeUserAgent = await detectRuntimeUserAgent(browser);
|
|
3756
|
+
const context = await browser.newContext(withRuntimeUserAgent({
|
|
3754
3757
|
serviceWorkers: "block"
|
|
3755
|
-
});
|
|
3758
|
+
}, runtimeUserAgent));
|
|
3756
3759
|
const page = context.pages()[0] ?? await context.newPage();
|
|
3757
3760
|
const guard = await installBrowserRequestGuard(page, auditedUrl);
|
|
3758
3761
|
await page.goto(auditedUrl, { waitUntil: "domcontentloaded", timeout: 3e4 });
|
|
@@ -4296,8 +4299,6 @@ async function extractBrandingFromPage(page) {
|
|
|
4296
4299
|
// src/lib/screenshot.ts
|
|
4297
4300
|
var DESKTOP_VIEWPORT = { width: 1440, height: 900 };
|
|
4298
4301
|
var MOBILE_VIEWPORT = { width: 390, height: 844 };
|
|
4299
|
-
var DESKTOP_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
|
|
4300
|
-
var MOBILE_UA = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1";
|
|
4301
4302
|
var SCROLL_STEP = 900;
|
|
4302
4303
|
var SETTLE_MS = 400;
|
|
4303
4304
|
async function scrollAndStitch(page, device = "desktop") {
|
|
@@ -4348,14 +4349,13 @@ async function scrollAndStitch(page, device = "desktop") {
|
|
|
4348
4349
|
}
|
|
4349
4350
|
async function captureLocal(url, device, wantScreenshot, wantBranding) {
|
|
4350
4351
|
const vp = device === "mobile" ? MOBILE_VIEWPORT : DESKTOP_VIEWPORT;
|
|
4351
|
-
const ua = device === "mobile" ? MOBILE_UA : DESKTOP_UA;
|
|
4352
4352
|
const browser = await chromium2.launch({ headless: true });
|
|
4353
|
-
const
|
|
4353
|
+
const runtimeUserAgent = await detectRuntimeUserAgent(browser);
|
|
4354
|
+
const context = await browser.newContext(withRuntimeUserAgent({
|
|
4354
4355
|
viewport: vp,
|
|
4355
4356
|
locale: "en-US",
|
|
4356
|
-
userAgent: ua,
|
|
4357
4357
|
isMobile: device === "mobile"
|
|
4358
|
-
});
|
|
4358
|
+
}, runtimeUserAgent));
|
|
4359
4359
|
const page = await context.newPage();
|
|
4360
4360
|
try {
|
|
4361
4361
|
await page.goto(url, { waitUntil: "networkidle", timeout: 6e4 });
|
|
@@ -4374,12 +4374,11 @@ async function captureKernel(url, kernelApiKey, device, wantScreenshot, wantBran
|
|
|
4374
4374
|
const session = await kernel.browsers.create({ stealth: true, timeout_seconds: 240 });
|
|
4375
4375
|
const browser = await chromium2.connectOverCDP(session.cdp_ws_url);
|
|
4376
4376
|
const vp = device === "mobile" ? MOBILE_VIEWPORT : DESKTOP_VIEWPORT;
|
|
4377
|
-
const
|
|
4378
|
-
const context = browser.contexts()[0] ?? await browser.newContext({
|
|
4377
|
+
const runtimeUserAgent = await detectRuntimeUserAgent(browser);
|
|
4378
|
+
const context = browser.contexts()[0] ?? await browser.newContext(withRuntimeUserAgent({
|
|
4379
4379
|
viewport: vp,
|
|
4380
|
-
userAgent: ua,
|
|
4381
4380
|
isMobile: device === "mobile"
|
|
4382
|
-
});
|
|
4381
|
+
}, runtimeUserAgent));
|
|
4383
4382
|
const page = context.pages()[0] ?? await context.newPage();
|
|
4384
4383
|
try {
|
|
4385
4384
|
await page.goto(url, { waitUntil: "networkidle", timeout: 6e4 });
|
|
@@ -4885,6 +4884,7 @@ async function crawlWithRotation(urls, opts) {
|
|
|
4885
4884
|
const worker = async () => {
|
|
4886
4885
|
let kb = null;
|
|
4887
4886
|
let browser = null;
|
|
4887
|
+
let runtimeUserAgent = null;
|
|
4888
4888
|
let inBrowser = 0;
|
|
4889
4889
|
let kbOpenedAtMs = 0;
|
|
4890
4890
|
const retire = async () => {
|
|
@@ -4892,6 +4892,7 @@ async function crawlWithRotation(urls, opts) {
|
|
|
4892
4892
|
browser = null;
|
|
4893
4893
|
kb = null;
|
|
4894
4894
|
kbOpenedAtMs = 0;
|
|
4895
|
+
runtimeUserAgent = null;
|
|
4895
4896
|
if (b) await b.close().catch(() => {
|
|
4896
4897
|
});
|
|
4897
4898
|
if (k) {
|
|
@@ -4913,9 +4914,10 @@ async function crawlWithRotation(urls, opts) {
|
|
|
4913
4914
|
kb = await createBrowserWithRetry(client2, headless);
|
|
4914
4915
|
kbOpenedAtMs = Date.now();
|
|
4915
4916
|
browser = await withTimeout(chromium3.connectOverCDP(kb.cdp_ws_url), 3e4);
|
|
4917
|
+
runtimeUserAgent = await detectRuntimeUserAgent(browser);
|
|
4916
4918
|
inBrowser = 0;
|
|
4917
4919
|
}
|
|
4918
|
-
const context = await browser.newContext({ serviceWorkers: "block" });
|
|
4920
|
+
const context = await browser.newContext(withRuntimeUserAgent({ serviceWorkers: "block" }, runtimeUserAgent));
|
|
4919
4921
|
try {
|
|
4920
4922
|
r = await crawlPage(context, url);
|
|
4921
4923
|
} finally {
|
|
@@ -8664,7 +8666,7 @@ var siteExtractFn = inngest.createFunction(
|
|
|
8664
8666
|
});
|
|
8665
8667
|
}) : null;
|
|
8666
8668
|
const finalized = await step.run("finalize", async () => {
|
|
8667
|
-
const { assembleExtractArtifacts } = await import("./extract-bundle-
|
|
8669
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-ITPFWRNI.js");
|
|
8668
8670
|
const current = await getExtractJob(jobId2);
|
|
8669
8671
|
if (!current) throw new Error("extract job disappeared before finalization");
|
|
8670
8672
|
const stored = await assembleExtractArtifacts(current, { branding, imageAudit });
|
|
@@ -9606,7 +9608,7 @@ async function resolveUsZipsPath(requestedPath) {
|
|
|
9606
9608
|
async function loadZipGroups(stateAbbr, requestedPath, warnings, sourceMode) {
|
|
9607
9609
|
const mode = resolvedLocationDataMode({ zipSource: sourceMode });
|
|
9608
9610
|
if (mode === "hosted") {
|
|
9609
|
-
const { getHostedZipGroups } = await import("./location-data-repository-
|
|
9611
|
+
const { getHostedZipGroups } = await import("./location-data-repository-HDNCU4Z4.js");
|
|
9610
9612
|
const hosted = await getHostedZipGroups(stateAbbr);
|
|
9611
9613
|
if (!hosted.dataset) {
|
|
9612
9614
|
throw new DirectoryLocationError(
|
|
@@ -9669,7 +9671,7 @@ async function resolveDirectoryMarkets(options, config = {}) {
|
|
|
9669
9671
|
const sourceUrl = censusStateUrl(state.fips);
|
|
9670
9672
|
const warnings = [];
|
|
9671
9673
|
if (resolvedLocationDataMode(config) === "hosted") {
|
|
9672
|
-
const { queryHostedLocationMarkets } = await import("./location-data-repository-
|
|
9674
|
+
const { queryHostedLocationMarkets } = await import("./location-data-repository-HDNCU4Z4.js");
|
|
9673
9675
|
const hosted = await queryHostedLocationMarkets({
|
|
9674
9676
|
state: state.abbr,
|
|
9675
9677
|
minPopulation: options.minPopulation,
|
|
@@ -16681,7 +16683,6 @@ facebookAdApp.post("/media", createApiKeyAuth(), async (c) => {
|
|
|
16681
16683
|
try {
|
|
16682
16684
|
res = await fetch(parsedUrl.href, {
|
|
16683
16685
|
headers: {
|
|
16684
|
-
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
|
|
16685
16686
|
"Referer": "https://www.facebook.com/"
|
|
16686
16687
|
},
|
|
16687
16688
|
signal: AbortSignal.timeout(6e4)
|
|
@@ -17998,10 +17999,10 @@ function blobKeyPrefix(shortcode, sourceUrl) {
|
|
|
17998
17999
|
const slug = shortcode ? `instagram-${shortcode}` : safeFilePart(sourceUrl);
|
|
17999
18000
|
return `instagram/${stamp}-${slug}`;
|
|
18000
18001
|
}
|
|
18001
|
-
async function fetchMediaBytes(url, referer) {
|
|
18002
|
+
async function fetchMediaBytes(url, referer, runtimeUserAgent) {
|
|
18002
18003
|
const res = await fetch(url, {
|
|
18003
18004
|
headers: {
|
|
18004
|
-
"User-Agent":
|
|
18005
|
+
...runtimeUserAgent ? { "User-Agent": runtimeUserAgent } : {},
|
|
18005
18006
|
"Referer": referer
|
|
18006
18007
|
},
|
|
18007
18008
|
signal: AbortSignal.timeout(9e4)
|
|
@@ -18121,6 +18122,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
18121
18122
|
const launch = await resolveInstagramLaunch(body);
|
|
18122
18123
|
await driver.launch(launch.config);
|
|
18123
18124
|
const page = driver.getPage();
|
|
18125
|
+
const runtimeUserAgent = await detectPageUserAgent(page);
|
|
18124
18126
|
const capturedMediaUrls = [];
|
|
18125
18127
|
page.on("response", (response) => {
|
|
18126
18128
|
const url = normalizeInstagramMediaUrl(response.url());
|
|
@@ -18149,7 +18151,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
18149
18151
|
downloads.push({ kind: "text", url: null, savedPath: storedText.url, sizeBytes: storedText.bytes, mimeType: "text/plain", error: null });
|
|
18150
18152
|
if (mediaTypes.has("image") && extraction.imageUrl) {
|
|
18151
18153
|
try {
|
|
18152
|
-
const { bytes, mimeType } = await fetchMediaBytes(extraction.imageUrl, extraction.pageUrl);
|
|
18154
|
+
const { bytes, mimeType } = await fetchMediaBytes(extraction.imageUrl, extraction.pageUrl, runtimeUserAgent);
|
|
18153
18155
|
const ext = extFromMime(mimeType, "jpg");
|
|
18154
18156
|
const stored = await store.put(`${prefix}/image.${ext}`, bytes, mimeType ?? "application/octet-stream");
|
|
18155
18157
|
downloads.push({ kind: "image", url: extraction.imageUrl, savedPath: stored.url, sizeBytes: stored.bytes, mimeType, error: null });
|
|
@@ -18165,7 +18167,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
18165
18167
|
if (track.streamType === "audio" && !mediaTypes.has("audio")) continue;
|
|
18166
18168
|
const kind = track.streamType === "audio" ? "audio" : "video";
|
|
18167
18169
|
try {
|
|
18168
|
-
const { bytes, mimeType } = await fetchMediaBytes(track.url, extraction.pageUrl);
|
|
18170
|
+
const { bytes, mimeType } = await fetchMediaBytes(track.url, extraction.pageUrl, runtimeUserAgent);
|
|
18169
18171
|
const stored = await store.put(`${prefix}/${trackFilename(track, index, extraction.shortcode)}`, bytes, mimeType ?? "video/mp4");
|
|
18170
18172
|
downloads.push({ kind, url: track.url, savedPath: stored.url, sizeBytes: stored.bytes, mimeType, error: null });
|
|
18171
18173
|
const isMuxInput = muxEligible && (track.url === extraction.selectedVideoTrack.url || track.url === extraction.selectedAudioTrack.url);
|
|
@@ -24041,6 +24043,12 @@ async function runFanoutCapture(page, input) {
|
|
|
24041
24043
|
// src/services/browser-agent/browser-agent-service.ts
|
|
24042
24044
|
function keepHostedBrowserAlive(_browser) {
|
|
24043
24045
|
}
|
|
24046
|
+
async function currentOrRuntimeContext(browser) {
|
|
24047
|
+
const current = browser.contexts()[0];
|
|
24048
|
+
if (current) return current;
|
|
24049
|
+
const runtimeUserAgent = await detectRuntimeUserAgent(browser);
|
|
24050
|
+
return browser.newContext(withRuntimeUserAgent({}, runtimeUserAgent));
|
|
24051
|
+
}
|
|
24044
24052
|
var DEFAULT_TIMEOUT_SECONDS = 600;
|
|
24045
24053
|
function client() {
|
|
24046
24054
|
const apiKey = browserServiceApiKey();
|
|
@@ -24165,7 +24173,7 @@ async function pressKeys(runtimeSessionId, keys) {
|
|
|
24165
24173
|
async function goto(cdpWsUrl, url) {
|
|
24166
24174
|
const browser = await playwrightChromium.connectOverCDP(cdpWsUrl);
|
|
24167
24175
|
try {
|
|
24168
|
-
const context =
|
|
24176
|
+
const context = await currentOrRuntimeContext(browser);
|
|
24169
24177
|
const page = context.pages()[0] ?? await context.newPage();
|
|
24170
24178
|
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 45e3 });
|
|
24171
24179
|
return { url: page.url(), title: await page.title() };
|
|
@@ -24176,7 +24184,7 @@ async function goto(cdpWsUrl, url) {
|
|
|
24176
24184
|
async function captureFanout(cdpWsUrl, input) {
|
|
24177
24185
|
const browser = await playwrightChromium.connectOverCDP(cdpWsUrl);
|
|
24178
24186
|
try {
|
|
24179
|
-
const context =
|
|
24187
|
+
const context = await currentOrRuntimeContext(browser);
|
|
24180
24188
|
const page = context.pages()[0] ?? await context.newPage();
|
|
24181
24189
|
return await runFanoutCapture(page, input);
|
|
24182
24190
|
} finally {
|
|
@@ -24186,7 +24194,7 @@ async function captureFanout(cdpWsUrl, input) {
|
|
|
24186
24194
|
async function readPage(cdpWsUrl) {
|
|
24187
24195
|
const browser = await playwrightChromium.connectOverCDP(cdpWsUrl);
|
|
24188
24196
|
try {
|
|
24189
|
-
const context =
|
|
24197
|
+
const context = await currentOrRuntimeContext(browser);
|
|
24190
24198
|
const page = context.pages()[0] ?? await context.newPage();
|
|
24191
24199
|
const url = page.url();
|
|
24192
24200
|
const title = await page.title().catch(() => "");
|
|
@@ -24241,7 +24249,7 @@ async function readPage(cdpWsUrl) {
|
|
|
24241
24249
|
async function locatePageTargets(cdpWsUrl, targets) {
|
|
24242
24250
|
const browser = await playwrightChromium.connectOverCDP(cdpWsUrl);
|
|
24243
24251
|
try {
|
|
24244
|
-
const context =
|
|
24252
|
+
const context = await currentOrRuntimeContext(browser);
|
|
24245
24253
|
const page = context.pages()[0] ?? await context.newPage();
|
|
24246
24254
|
const url = page.url();
|
|
24247
24255
|
const title = await page.title().catch(() => "");
|
|
@@ -25541,6 +25549,31 @@ var ACCESS_TTL_SECONDS = 3600;
|
|
|
25541
25549
|
var REFRESH_TTL_SECONDS = 60 * 60 * 24 * 30;
|
|
25542
25550
|
var CODE_TTL_SECONDS = 60;
|
|
25543
25551
|
var ROTATION_GRACE_SECONDS = 120;
|
|
25552
|
+
var OAUTH_DATABASE_TIMEOUT_MS = 5e3;
|
|
25553
|
+
var OAuthDatabaseUnavailableError = class extends Error {
|
|
25554
|
+
stage;
|
|
25555
|
+
constructor(stage) {
|
|
25556
|
+
super("The authorization service database is temporarily unavailable.");
|
|
25557
|
+
this.name = "OAuthDatabaseUnavailableError";
|
|
25558
|
+
this.stage = stage;
|
|
25559
|
+
}
|
|
25560
|
+
};
|
|
25561
|
+
async function withOAuthDatabaseDeadline(stage, operation, timeoutMs = OAUTH_DATABASE_TIMEOUT_MS) {
|
|
25562
|
+
const startedAt = Date.now();
|
|
25563
|
+
let timeout;
|
|
25564
|
+
try {
|
|
25565
|
+
const value = await Promise.race([
|
|
25566
|
+
operation,
|
|
25567
|
+
new Promise((_, reject) => {
|
|
25568
|
+
timeout = setTimeout(() => reject(new OAuthDatabaseUnavailableError(stage)), timeoutMs);
|
|
25569
|
+
})
|
|
25570
|
+
]);
|
|
25571
|
+
console.log("[oauth-db] stage=%s status=ok duration_ms=%d", stage, Date.now() - startedAt);
|
|
25572
|
+
return value;
|
|
25573
|
+
} finally {
|
|
25574
|
+
if (timeout) clearTimeout(timeout);
|
|
25575
|
+
}
|
|
25576
|
+
}
|
|
25544
25577
|
var secureCookies = process.env.NODE_ENV === "production" || process.env.VERCEL === "1";
|
|
25545
25578
|
var sessionCookieOptions = {
|
|
25546
25579
|
httpOnly: true,
|
|
@@ -25603,7 +25636,7 @@ async function sessionUser(token4) {
|
|
|
25603
25636
|
if (!token4) return null;
|
|
25604
25637
|
const userId = verifySession(token4);
|
|
25605
25638
|
if (!userId) return null;
|
|
25606
|
-
const user = await getUserById(userId);
|
|
25639
|
+
const user = await withOAuthDatabaseDeadline("session-user", getUserById(userId));
|
|
25607
25640
|
return user ?? null;
|
|
25608
25641
|
}
|
|
25609
25642
|
function escapeHtml(value) {
|
|
@@ -25693,6 +25726,18 @@ function redirectWithError(redirectUri, state, error) {
|
|
|
25693
25726
|
return new Response(null, { status: 302, headers: { Location: u.toString() } });
|
|
25694
25727
|
}
|
|
25695
25728
|
var oauthApp = new Hono23();
|
|
25729
|
+
oauthApp.onError((error, c) => {
|
|
25730
|
+
if (error instanceof OAuthDatabaseUnavailableError) {
|
|
25731
|
+
console.error("[oauth-db] stage=%s status=timeout timeout_ms=%d", error.stage, OAUTH_DATABASE_TIMEOUT_MS);
|
|
25732
|
+
c.header("Retry-After", "5");
|
|
25733
|
+
return c.json({
|
|
25734
|
+
error: "temporarily_unavailable",
|
|
25735
|
+
error_description: "Authorization is temporarily unavailable. Please retry shortly."
|
|
25736
|
+
}, 503);
|
|
25737
|
+
}
|
|
25738
|
+
console.error("[oauth] unhandled error:", error);
|
|
25739
|
+
return c.json({ error: "server_error", error_description: "Authorization could not be completed." }, 500);
|
|
25740
|
+
});
|
|
25696
25741
|
oauthApp.use("*", async (c, next) => {
|
|
25697
25742
|
c.header("Access-Control-Allow-Origin", "*");
|
|
25698
25743
|
c.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
@@ -25775,7 +25820,7 @@ oauthApp.post("/oauth/register", async (c) => {
|
|
|
25775
25820
|
}
|
|
25776
25821
|
const clientName = typeof body.client_name === "string" ? body.client_name : null;
|
|
25777
25822
|
const clientId = `client_${randomBytes2(16).toString("hex")}`;
|
|
25778
|
-
await registerClient(clientId, redirectUris, clientName);
|
|
25823
|
+
await withOAuthDatabaseDeadline("register-client", registerClient(clientId, redirectUris, clientName));
|
|
25779
25824
|
console.log("[oauth-dcr] register OK client_id=%s redirect_uris=%s", clientId, JSON.stringify(redirectUris));
|
|
25780
25825
|
return c.json({
|
|
25781
25826
|
client_id: clientId,
|
|
@@ -25802,7 +25847,7 @@ function parseAuthParams(get) {
|
|
|
25802
25847
|
async function validateAuthRequest(p) {
|
|
25803
25848
|
if (p.response_type !== "code") return { ok: false, status: 400, message: "response_type must be code" };
|
|
25804
25849
|
if (!p.client_id) return { ok: false, status: 400, message: "client_id is required" };
|
|
25805
|
-
const client2 = await getClient(p.client_id);
|
|
25850
|
+
const client2 = await withOAuthDatabaseDeadline("get-client", getClient(p.client_id));
|
|
25806
25851
|
if (!client2) return { ok: false, status: 400, message: "unknown client_id" };
|
|
25807
25852
|
if (!p.redirect_uri || !client2.redirect_uris.includes(p.redirect_uri)) return { ok: false, status: 400, message: "redirect_uri does not match the registered set" };
|
|
25808
25853
|
if (!isAllowedRedirect(p.redirect_uri)) return { ok: false, status: 400, message: "redirect_uri host not allowed" };
|
|
@@ -25835,7 +25880,7 @@ oauthApp.post("/oauth/authorize", async (c) => {
|
|
|
25835
25880
|
if (action === "login") {
|
|
25836
25881
|
const email = (get("email") ?? "").trim().toLowerCase();
|
|
25837
25882
|
const password = get("password") ?? "";
|
|
25838
|
-
const user2 = email ? await getUserByEmail(email) : void 0;
|
|
25883
|
+
const user2 = email ? await withOAuthDatabaseDeadline("login-user", getUserByEmail(email)) : void 0;
|
|
25839
25884
|
const okPw = !!(user2 && user2.password_hash && verifyPassword(password, user2.password_hash));
|
|
25840
25885
|
console.log("[oauth-dcr] LOGIN email=%s found=%s hasHash=%s pwLen=%d ok=%s", email, !!user2, !!(user2 && user2.password_hash), password.length, okPw);
|
|
25841
25886
|
if (!okPw) {
|
|
@@ -25851,7 +25896,7 @@ oauthApp.post("/oauth/authorize", async (c) => {
|
|
|
25851
25896
|
const scope = negotiateScope(p.scope, user, p.resource);
|
|
25852
25897
|
const code = `code_${randomBytes2(32).toString("base64url")}`;
|
|
25853
25898
|
const expiresAt = new Date(Date.now() + CODE_TTL_SECONDS * 1e3).toISOString();
|
|
25854
|
-
await putCode({
|
|
25899
|
+
await withOAuthDatabaseDeadline("put-authorization-code", putCode({
|
|
25855
25900
|
code,
|
|
25856
25901
|
client_id: p.client_id,
|
|
25857
25902
|
redirect_uri: p.redirect_uri,
|
|
@@ -25860,7 +25905,7 @@ oauthApp.post("/oauth/authorize", async (c) => {
|
|
|
25860
25905
|
scope,
|
|
25861
25906
|
resource: p.resource || RESOURCE(),
|
|
25862
25907
|
expires_at: expiresAt
|
|
25863
|
-
});
|
|
25908
|
+
}));
|
|
25864
25909
|
const u = new URL(p.redirect_uri);
|
|
25865
25910
|
u.searchParams.set("code", code);
|
|
25866
25911
|
if (p.state) u.searchParams.set("state", p.state);
|
|
@@ -25890,18 +25935,18 @@ oauthApp.post("/oauth/token", async (c) => {
|
|
|
25890
25935
|
const clientId = get("client_id") ?? "";
|
|
25891
25936
|
const redirectUri = get("redirect_uri") ?? "";
|
|
25892
25937
|
const verifier = get("code_verifier") ?? "";
|
|
25893
|
-
const record = await consumeCode(code);
|
|
25938
|
+
const record = await withOAuthDatabaseDeadline("consume-authorization-code", consumeCode(code));
|
|
25894
25939
|
if (!record) return tokenErrorResponse(c, "invalid_grant", "Authorization code is invalid or already used", 400);
|
|
25895
25940
|
if (new Date(record.expires_at).getTime() < Date.now()) return tokenErrorResponse(c, "invalid_grant", "Authorization code has expired", 400);
|
|
25896
25941
|
if (record.client_id !== clientId) return tokenErrorResponse(c, "invalid_grant", "client_id mismatch", 400);
|
|
25897
25942
|
if (record.redirect_uri !== redirectUri) return tokenErrorResponse(c, "invalid_grant", "redirect_uri mismatch", 400);
|
|
25898
25943
|
if (!pkceMatches(verifier, record.code_challenge)) return tokenErrorResponse(c, "invalid_grant", "PKCE verification failed", 400);
|
|
25899
|
-
const user = await getUserByEmail(record.identity);
|
|
25944
|
+
const user = await withOAuthDatabaseDeadline("token-user", getUserByEmail(record.identity));
|
|
25900
25945
|
const plan = user ? resolvePlan(user) : "free";
|
|
25901
25946
|
const audience = record.resource ?? RESOURCE();
|
|
25902
25947
|
const accessToken = await mintAccessToken(record.identity, record.scope, plan, audience);
|
|
25903
25948
|
const refreshToken = `rt_${randomBytes2(40).toString("base64url")}`;
|
|
25904
|
-
await putRefresh({
|
|
25949
|
+
await withOAuthDatabaseDeadline("put-refresh-token", putRefresh({
|
|
25905
25950
|
refresh_token: refreshToken,
|
|
25906
25951
|
client_id: clientId,
|
|
25907
25952
|
identity: record.identity,
|
|
@@ -25909,15 +25954,15 @@ oauthApp.post("/oauth/token", async (c) => {
|
|
|
25909
25954
|
resource: audience,
|
|
25910
25955
|
expires_at: new Date(Date.now() + REFRESH_TTL_SECONDS * 1e3).toISOString(),
|
|
25911
25956
|
revoked: 0
|
|
25912
|
-
});
|
|
25957
|
+
}));
|
|
25913
25958
|
return c.json({ access_token: accessToken, token_type: "Bearer", expires_in: ACCESS_TTL_SECONDS, refresh_token: refreshToken, scope: record.scope });
|
|
25914
25959
|
}
|
|
25915
25960
|
if (grantType === "refresh_token") {
|
|
25916
25961
|
const refreshToken = get("refresh_token") ?? "";
|
|
25917
25962
|
const clientId = get("client_id") ?? "";
|
|
25918
|
-
const record = await getRefresh(refreshToken);
|
|
25963
|
+
const record = await withOAuthDatabaseDeadline("get-refresh-token", getRefresh(refreshToken));
|
|
25919
25964
|
if (record && record.revoked && record.replaced_by && record.rotated_at && Date.now() - new Date(record.rotated_at).getTime() < ROTATION_GRACE_SECONDS * 1e3 && (!clientId || record.client_id === clientId)) {
|
|
25920
|
-
const graceUser = await getUserByEmail(record.identity);
|
|
25965
|
+
const graceUser = await withOAuthDatabaseDeadline("refresh-grace-user", getUserByEmail(record.identity));
|
|
25921
25966
|
const gracePlan = graceUser ? resolvePlan(graceUser) : "free";
|
|
25922
25967
|
const graceAudience = record.resource ?? RESOURCE();
|
|
25923
25968
|
const graceAccess = await mintAccessToken(record.identity, record.scope, gracePlan, graceAudience);
|
|
@@ -25926,12 +25971,12 @@ oauthApp.post("/oauth/token", async (c) => {
|
|
|
25926
25971
|
if (!record || record.revoked) return tokenErrorResponse(c, "invalid_grant", "Refresh token is invalid or revoked", 400);
|
|
25927
25972
|
if (new Date(record.expires_at).getTime() < Date.now()) return tokenErrorResponse(c, "invalid_grant", "Refresh token has expired", 400);
|
|
25928
25973
|
if (clientId && record.client_id !== clientId) return tokenErrorResponse(c, "invalid_grant", "client_id mismatch", 400);
|
|
25929
|
-
const user = await getUserByEmail(record.identity);
|
|
25974
|
+
const user = await withOAuthDatabaseDeadline("refresh-user", getUserByEmail(record.identity));
|
|
25930
25975
|
const plan = user ? resolvePlan(user) : "free";
|
|
25931
25976
|
const audience = record.resource ?? RESOURCE();
|
|
25932
25977
|
const accessToken = await mintAccessToken(record.identity, record.scope, plan, audience);
|
|
25933
25978
|
const nextRefresh = `rt_${randomBytes2(40).toString("base64url")}`;
|
|
25934
|
-
await rotateRefresh(refreshToken, {
|
|
25979
|
+
await withOAuthDatabaseDeadline("rotate-refresh-token", rotateRefresh(refreshToken, {
|
|
25935
25980
|
refresh_token: nextRefresh,
|
|
25936
25981
|
client_id: record.client_id,
|
|
25937
25982
|
identity: record.identity,
|
|
@@ -25939,7 +25984,7 @@ oauthApp.post("/oauth/token", async (c) => {
|
|
|
25939
25984
|
resource: audience,
|
|
25940
25985
|
expires_at: new Date(Date.now() + REFRESH_TTL_SECONDS * 1e3).toISOString(),
|
|
25941
25986
|
revoked: 0
|
|
25942
|
-
});
|
|
25987
|
+
}));
|
|
25943
25988
|
return c.json({ access_token: accessToken, token_type: "Bearer", expires_in: ACCESS_TTL_SECONDS, refresh_token: nextRefresh, scope: record.scope });
|
|
25944
25989
|
}
|
|
25945
25990
|
return tokenErrorResponse(c, "unsupported_grant_type", "grant_type must be authorization_code or refresh_token", 400);
|
|
@@ -34346,8 +34391,7 @@ app.use("*", (c, next) => {
|
|
|
34346
34391
|
const op = opForCostPath(new URL(c.req.url).pathname);
|
|
34347
34392
|
if (!op) return next();
|
|
34348
34393
|
const probeRunId = c.req.header("x-cost-probe-id") ?? null;
|
|
34349
|
-
|
|
34350
|
-
return runWithCostContext({ op, probeRunId, forceHeadless }, () => next());
|
|
34394
|
+
return runWithCostContext({ op, probeRunId }, () => next());
|
|
34351
34395
|
});
|
|
34352
34396
|
app.post("/auth/register", requireAllowedOrigin, async (c) => {
|
|
34353
34397
|
const { email, password } = await c.req.json();
|
|
@@ -37165,7 +37209,7 @@ app.get("/cron/tick", async (c) => {
|
|
|
37165
37209
|
if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
|
|
37166
37210
|
return c.json({ error: "Unauthorized" }, 401);
|
|
37167
37211
|
}
|
|
37168
|
-
const { drainQueue } = await import("./worker-
|
|
37212
|
+
const { drainQueue } = await import("./worker-73AYU4IK.js");
|
|
37169
37213
|
const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
|
|
37170
37214
|
const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
|
|
37171
37215
|
const [results, sweepResult, reapResult, expiredResult, blobCleanup, connectedDataArtifactCleanup, connectedAccountBilling, directoryWorkflowDispatch, directoryWorkflowReconciliation, directoryArtifactCleanup, siteExtractArtifactCleanup, siteExtractRedispatch, siteExtractReconciliation, paaHarvestRedispatch, paaHarvestReconciliation] = await Promise.all([
|
|
@@ -37218,8 +37262,8 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
37218
37262
|
finishExtractJob: finishExtractJob2,
|
|
37219
37263
|
terminalExtractJobStatus: terminalExtractJobStatus2,
|
|
37220
37264
|
extractJobLimitInfo: extractJobLimitInfo2
|
|
37221
|
-
} = await import("./site-extract-repository-
|
|
37222
|
-
const { assembleExtractArtifacts } = await import("./extract-bundle-
|
|
37265
|
+
} = await import("./site-extract-repository-CKCJDP7N.js");
|
|
37266
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-ITPFWRNI.js");
|
|
37223
37267
|
const existing = await getExtractJob2(jobId2);
|
|
37224
37268
|
if (!existing) return c.json({ error: "job not found" }, 404);
|
|
37225
37269
|
if (existing.status !== "failed") {
|
|
@@ -37246,7 +37290,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
37246
37290
|
if (!updated) return c.json({ error: "job state changed during re-finalization" }, 409);
|
|
37247
37291
|
let settlement = "already_settled_or_refunded";
|
|
37248
37292
|
if (job.billedMc == null && job.userId != null) {
|
|
37249
|
-
const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-
|
|
37293
|
+
const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-CKCJDP7N.js");
|
|
37250
37294
|
const heldMc = Number(job.options.heldMc ?? 0);
|
|
37251
37295
|
const successful = await countSuccessfulPages2(jobId2);
|
|
37252
37296
|
const usedMc = Math.min(successful * MC_COSTS.page_scrape, heldMc);
|
|
@@ -37425,4 +37469,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
37425
37469
|
export {
|
|
37426
37470
|
app
|
|
37427
37471
|
};
|
|
37428
|
-
//# sourceMappingURL=server-
|
|
37472
|
+
//# sourceMappingURL=server-BTDXZA5U.js.map
|