mcp-scraper 0.3.17 → 0.3.18
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 +26 -58
- package/dist/bin/api-server.cjs +286 -49
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- package/dist/bin/mcp-scraper-cli.cjs +4 -4
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +5 -5
- package/dist/bin/mcp-scraper-cli.js.map +1 -1
- package/dist/bin/mcp-scraper-install.cjs +12 -12
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +3 -3
- package/dist/bin/mcp-scraper-install.js.map +1 -1
- package/dist/bin/mcp-stdio-server.cjs +2441 -785
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +1377 -9
- package/dist/bin/mcp-stdio-server.js.map +1 -1
- package/dist/bin/paa-harvest.js +2 -3
- package/dist/bin/paa-harvest.js.map +1 -1
- package/dist/{chunk-N33YEY6W.js → chunk-2XCNU22L.js} +210 -10
- package/dist/{chunk-N33YEY6W.js.map → chunk-2XCNU22L.js.map} +1 -1
- package/dist/chunk-C7ZNIXOA.js +7 -0
- package/dist/chunk-C7ZNIXOA.js.map +1 -0
- package/dist/{chunk-ACIUCZ27.js → chunk-DE7WP4UU.js} +11 -11
- package/dist/chunk-DE7WP4UU.js.map +1 -0
- package/dist/{chunk-ZAUMSBV3.js → chunk-HDPWLYK7.js} +6 -6
- package/dist/{chunk-4OPKIDON.js → chunk-IGOEAKC7.js} +4 -6
- package/dist/{chunk-4OPKIDON.js.map → chunk-IGOEAKC7.js.map} +1 -1
- package/dist/{chunk-M2S27J6Z.js → chunk-ZAP7MYVO.js} +26 -1
- package/dist/chunk-ZAP7MYVO.js.map +1 -0
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/{server-TKWY47JA.js → server-3M3XCVOT.js} +323 -158
- package/dist/server-3M3XCVOT.js.map +1 -0
- package/dist/{worker-2WVKKCC7.js → worker-J6I5XP2F.js} +9 -10
- package/dist/{worker-2WVKKCC7.js.map → worker-J6I5XP2F.js.map} +1 -1
- package/docs/mcp-tool-manifest.generated.json +28 -27
- package/package.json +3 -3
- package/dist/bin/browser-agent-stdio-server.cjs +0 -1523
- package/dist/bin/browser-agent-stdio-server.cjs.map +0 -1
- package/dist/bin/browser-agent-stdio-server.d.cts +0 -1
- package/dist/bin/browser-agent-stdio-server.d.ts +0 -1
- package/dist/bin/browser-agent-stdio-server.js +0 -43
- package/dist/bin/browser-agent-stdio-server.js.map +0 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs +0 -5718
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +0 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.d.cts +0 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.d.ts +0 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.js +0 -70
- package/dist/bin/mcp-scraper-combined-stdio-server.js.map +0 -1
- package/dist/chunk-3YGKXXUG.js +0 -133
- package/dist/chunk-3YGKXXUG.js.map +0 -1
- package/dist/chunk-ACIUCZ27.js.map +0 -1
- package/dist/chunk-M2S27J6Z.js.map +0 -1
- package/dist/chunk-PVWWY5NV.js +0 -7
- package/dist/chunk-PVWWY5NV.js.map +0 -1
- package/dist/chunk-UFD7N36R.js +0 -1332
- package/dist/chunk-UFD7N36R.js.map +0 -1
- package/dist/chunk-WN7PBKMV.js +0 -28
- package/dist/chunk-WN7PBKMV.js.map +0 -1
- package/dist/server-TKWY47JA.js.map +0 -1
- /package/dist/{chunk-ZAUMSBV3.js.map → chunk-HDPWLYK7.js.map} +0 -0
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CaptureSerpPageSnapshotsInputSchema,
|
|
3
|
+
CaptureSerpPageSnapshotsOutputSchema,
|
|
4
|
+
CaptureSerpSnapshotInputSchema,
|
|
5
|
+
CaptureSerpSnapshotOutputSchema,
|
|
6
|
+
HttpMcpToolExecutor,
|
|
7
|
+
auditImages,
|
|
8
|
+
buildLinkGraph,
|
|
9
|
+
buildLinkReport,
|
|
10
|
+
buildPaaExtractorMcpServer,
|
|
11
|
+
computeIssues,
|
|
12
|
+
configureReportSaving,
|
|
13
|
+
exportFanout,
|
|
14
|
+
formatCaptureSerpPageSnapshots,
|
|
15
|
+
formatCaptureSerpSnapshot,
|
|
16
|
+
harvestTimeoutBudget,
|
|
17
|
+
liveWebToolAnnotations,
|
|
18
|
+
outputBaseDir,
|
|
19
|
+
renderImageSection,
|
|
20
|
+
renderIssueReport,
|
|
21
|
+
renderLinkReport,
|
|
22
|
+
sanitizeAttempts,
|
|
23
|
+
sanitizeHarvestResult
|
|
24
|
+
} from "./chunk-2XCNU22L.js";
|
|
25
|
+
import {
|
|
26
|
+
csvRecords,
|
|
27
|
+
listWorkflowDefinitions,
|
|
28
|
+
rowsToCsv,
|
|
29
|
+
runWorkflow,
|
|
30
|
+
runWorkflowStep,
|
|
31
|
+
workflowDefinition,
|
|
32
|
+
workflowOutputBaseDir,
|
|
33
|
+
workflowStepCount,
|
|
34
|
+
workflowSupportsSteps
|
|
35
|
+
} from "./chunk-H2R232HK.js";
|
|
36
|
+
import "./chunk-C7ZNIXOA.js";
|
|
1
37
|
import {
|
|
2
38
|
BALANCE_PACK_LABELS,
|
|
3
39
|
BALANCE_PRICE_IDS,
|
|
@@ -16,7 +52,34 @@ import {
|
|
|
16
52
|
harvestProblemResponse,
|
|
17
53
|
insufficientBalanceResponse,
|
|
18
54
|
serializeHarvestProblem
|
|
19
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-HDPWLYK7.js";
|
|
56
|
+
import {
|
|
57
|
+
BrowserDriver,
|
|
58
|
+
MapsSelectors,
|
|
59
|
+
buildYouTubeChannelVideosUrl,
|
|
60
|
+
deleteKernelProxyId,
|
|
61
|
+
harvest,
|
|
62
|
+
resolveKernelProxyId
|
|
63
|
+
} from "./chunk-IGOEAKC7.js";
|
|
64
|
+
import {
|
|
65
|
+
CaptchaError,
|
|
66
|
+
RECAPTCHA_INSTRUCTIONS,
|
|
67
|
+
browserServiceApiKey,
|
|
68
|
+
browserServiceProfileName,
|
|
69
|
+
browserServiceProfileSaveChanges,
|
|
70
|
+
browserServiceProxyId,
|
|
71
|
+
sanitizeVendorName
|
|
72
|
+
} from "./chunk-ZAP7MYVO.js";
|
|
73
|
+
import {
|
|
74
|
+
DEFAULT_MAPS_PROXY_MODE,
|
|
75
|
+
DEFAULT_PROXY_MODE,
|
|
76
|
+
MapsPlaceOptionsSchema,
|
|
77
|
+
MapsSearchOptionsSchema,
|
|
78
|
+
RawMapsAboutAttributeSchema,
|
|
79
|
+
RawMapsHoursRowSchema,
|
|
80
|
+
RawMapsOverviewSchema,
|
|
81
|
+
RawMapsReviewStatsSchema
|
|
82
|
+
} from "./chunk-LFATOGDF.js";
|
|
20
83
|
import {
|
|
21
84
|
SiteAuditJobRowSchema,
|
|
22
85
|
advanceWorkflowRunStep,
|
|
@@ -78,118 +141,6 @@ import {
|
|
|
78
141
|
setStripeCustomerId,
|
|
79
142
|
verifyPassword
|
|
80
143
|
} from "./chunk-5H22TOXQ.js";
|
|
81
|
-
import {
|
|
82
|
-
BrowserDriver,
|
|
83
|
-
MapsSelectors,
|
|
84
|
-
buildYouTubeChannelVideosUrl,
|
|
85
|
-
deleteKernelProxyId,
|
|
86
|
-
harvest,
|
|
87
|
-
resolveKernelProxyId
|
|
88
|
-
} from "./chunk-4OPKIDON.js";
|
|
89
|
-
import {
|
|
90
|
-
CaptureSerpPageSnapshotsInputSchema,
|
|
91
|
-
CaptureSerpPageSnapshotsOutputSchema,
|
|
92
|
-
CaptureSerpSnapshotInputSchema,
|
|
93
|
-
CaptureSerpSnapshotOutputSchema,
|
|
94
|
-
HttpMcpToolExecutor,
|
|
95
|
-
auditImages,
|
|
96
|
-
buildLinkGraph,
|
|
97
|
-
buildLinkReport,
|
|
98
|
-
buildPaaExtractorMcpServer,
|
|
99
|
-
computeIssues,
|
|
100
|
-
configureReportSaving,
|
|
101
|
-
formatCaptureSerpPageSnapshots,
|
|
102
|
-
formatCaptureSerpSnapshot,
|
|
103
|
-
harvestTimeoutBudget,
|
|
104
|
-
liveWebToolAnnotations,
|
|
105
|
-
outputBaseDir,
|
|
106
|
-
renderImageSection,
|
|
107
|
-
renderIssueReport,
|
|
108
|
-
renderLinkReport
|
|
109
|
-
} from "./chunk-N33YEY6W.js";
|
|
110
|
-
import {
|
|
111
|
-
CaptchaError,
|
|
112
|
-
RECAPTCHA_INSTRUCTIONS,
|
|
113
|
-
sanitizeVendorName
|
|
114
|
-
} from "./chunk-M2S27J6Z.js";
|
|
115
|
-
import {
|
|
116
|
-
exportFanout
|
|
117
|
-
} from "./chunk-3YGKXXUG.js";
|
|
118
|
-
import {
|
|
119
|
-
browserServiceApiKey,
|
|
120
|
-
browserServiceProfileName,
|
|
121
|
-
browserServiceProfileSaveChanges,
|
|
122
|
-
browserServiceProxyId
|
|
123
|
-
} from "./chunk-WN7PBKMV.js";
|
|
124
|
-
import {
|
|
125
|
-
csvRecords,
|
|
126
|
-
listWorkflowDefinitions,
|
|
127
|
-
rowsToCsv,
|
|
128
|
-
runWorkflow,
|
|
129
|
-
runWorkflowStep,
|
|
130
|
-
workflowDefinition,
|
|
131
|
-
workflowOutputBaseDir,
|
|
132
|
-
workflowStepCount,
|
|
133
|
-
workflowSupportsSteps
|
|
134
|
-
} from "./chunk-H2R232HK.js";
|
|
135
|
-
import {
|
|
136
|
-
DEFAULT_MAPS_PROXY_MODE,
|
|
137
|
-
DEFAULT_PROXY_MODE,
|
|
138
|
-
MapsPlaceOptionsSchema,
|
|
139
|
-
MapsSearchOptionsSchema,
|
|
140
|
-
RawMapsAboutAttributeSchema,
|
|
141
|
-
RawMapsHoursRowSchema,
|
|
142
|
-
RawMapsOverviewSchema,
|
|
143
|
-
RawMapsReviewStatsSchema
|
|
144
|
-
} from "./chunk-LFATOGDF.js";
|
|
145
|
-
import "./chunk-PVWWY5NV.js";
|
|
146
|
-
|
|
147
|
-
// src/api/outbound-sanitize.ts
|
|
148
|
-
var KEY_RENAMES = {
|
|
149
|
-
kernel: "browserRuntime",
|
|
150
|
-
kernel_session_id: "browser_session_id",
|
|
151
|
-
kernel_delete_started: "session_cleanup_started",
|
|
152
|
-
kernel_delete_succeeded: "session_cleanup_succeeded",
|
|
153
|
-
kernel_delete_error: "session_cleanup_error",
|
|
154
|
-
kernelSessionId: "browserSessionId",
|
|
155
|
-
kernelDeleteStarted: "sessionCleanupStarted",
|
|
156
|
-
kernelDeleteSucceeded: "sessionCleanupSucceeded",
|
|
157
|
-
kernelDeleteError: "sessionCleanupError",
|
|
158
|
-
kernelProxyId: "proxyId"
|
|
159
|
-
};
|
|
160
|
-
var SANITIZED_VALUE_KEYS = /error|message/i;
|
|
161
|
-
function sanitizeOutboundDiagnostics(value, parentKey = "") {
|
|
162
|
-
if (typeof value === "string") {
|
|
163
|
-
if (SANITIZED_VALUE_KEYS.test(parentKey) && /kernel/i.test(value)) {
|
|
164
|
-
return sanitizeVendorName(value);
|
|
165
|
-
}
|
|
166
|
-
return value;
|
|
167
|
-
}
|
|
168
|
-
if (Array.isArray(value)) return value.map((v) => sanitizeOutboundDiagnostics(v, parentKey));
|
|
169
|
-
if (value !== null && typeof value === "object") {
|
|
170
|
-
const out = {};
|
|
171
|
-
for (const [key, val] of Object.entries(value)) {
|
|
172
|
-
const renamed = KEY_RENAMES[key] ?? key;
|
|
173
|
-
out[renamed] = sanitizeOutboundDiagnostics(val, key);
|
|
174
|
-
}
|
|
175
|
-
return out;
|
|
176
|
-
}
|
|
177
|
-
return value;
|
|
178
|
-
}
|
|
179
|
-
function sanitizeAttempts(attempts) {
|
|
180
|
-
return attempts.map((a) => sanitizeOutboundDiagnostics(a));
|
|
181
|
-
}
|
|
182
|
-
function sanitizeHarvestResult(result) {
|
|
183
|
-
const diagnostics = result?.diagnostics;
|
|
184
|
-
if (!diagnostics?.debug) return result;
|
|
185
|
-
return {
|
|
186
|
-
...result,
|
|
187
|
-
diagnostics: {
|
|
188
|
-
...diagnostics,
|
|
189
|
-
debug: sanitizeOutboundDiagnostics(diagnostics.debug)
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
144
|
|
|
194
145
|
// src/blog/registry.ts
|
|
195
146
|
var posts = [
|
|
@@ -7586,11 +7537,6 @@ async function settleExtractJob(jobId, userId, refundMc, netChargeMc, reference)
|
|
|
7586
7537
|
|
|
7587
7538
|
// src/inngest/functions/site-extract.ts
|
|
7588
7539
|
var BATCH = 30;
|
|
7589
|
-
function chunk(items, size) {
|
|
7590
|
-
const out = [];
|
|
7591
|
-
for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));
|
|
7592
|
-
return out;
|
|
7593
|
-
}
|
|
7594
7540
|
function buildArtifacts(job, pages, branding, imageAudit) {
|
|
7595
7541
|
const { edges, metrics } = buildLinkGraph(pages, job.startUrl);
|
|
7596
7542
|
const issues = computeIssues(pages, metrics);
|
|
@@ -7649,18 +7595,62 @@ var siteExtractFn = inngest.createFunction(
|
|
|
7649
7595
|
const maxPages = Number(job.options.maxPages ?? 1e4);
|
|
7650
7596
|
const concurrency = Number(job.options.concurrency ?? 1);
|
|
7651
7597
|
const urlsPerBrowser = Number(job.options.urlsPerBrowser ?? job.options.rotateProxyEvery ?? 10);
|
|
7652
|
-
const
|
|
7598
|
+
const seed = await step.run("discover", async () => {
|
|
7653
7599
|
const discovered = await discoverUrls(job.startUrl, maxPages, key);
|
|
7654
|
-
|
|
7655
|
-
|
|
7600
|
+
const out = discovered.length ? discovered : [job.startUrl];
|
|
7601
|
+
await setExtractJobTotal(jobId, out.length);
|
|
7602
|
+
return out;
|
|
7656
7603
|
});
|
|
7657
|
-
const
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7604
|
+
const siteHost = (() => {
|
|
7605
|
+
try {
|
|
7606
|
+
return new URL(job.startUrl).hostname.replace(/^www\./, "");
|
|
7607
|
+
} catch {
|
|
7608
|
+
return "";
|
|
7609
|
+
}
|
|
7610
|
+
})();
|
|
7611
|
+
const norm = (u) => {
|
|
7612
|
+
try {
|
|
7613
|
+
const x = new URL(u);
|
|
7614
|
+
x.hash = "";
|
|
7615
|
+
return (x.origin + x.pathname).replace(/\/+$/, "") + x.search;
|
|
7616
|
+
} catch {
|
|
7617
|
+
return u;
|
|
7618
|
+
}
|
|
7619
|
+
};
|
|
7620
|
+
const sameSite = (u) => {
|
|
7621
|
+
try {
|
|
7622
|
+
return new URL(u).hostname.replace(/^www\./, "") === siteHost;
|
|
7623
|
+
} catch {
|
|
7624
|
+
return false;
|
|
7625
|
+
}
|
|
7626
|
+
};
|
|
7627
|
+
const queue = [...seed];
|
|
7628
|
+
const seen = new Set(seed.map(norm));
|
|
7629
|
+
let crawled = 0;
|
|
7630
|
+
const MAX_BATCHES = Math.ceil(maxPages / BATCH) + 30;
|
|
7631
|
+
for (let i = 0; i < MAX_BATCHES && crawled < maxPages && crawled < queue.length; i++) {
|
|
7632
|
+
const batch = queue.slice(crawled, Math.min(crawled + BATCH, maxPages));
|
|
7633
|
+
if (!batch.length) break;
|
|
7634
|
+
const newLinks = await step.run(`crawl-batch-${i}`, async () => {
|
|
7635
|
+
const pages = await extractPagesRotating(batch, { kernelApiKey: key, concurrency, urlsPerBrowser });
|
|
7661
7636
|
await saveExtractPages(jobId, pages);
|
|
7662
|
-
|
|
7637
|
+
const found = [];
|
|
7638
|
+
for (const p of pages) for (const l of p.outlinks ?? []) {
|
|
7639
|
+
if (l.internal && l.href && sameSite(l.href)) found.push(l.href);
|
|
7640
|
+
}
|
|
7641
|
+
return [...new Set(found)];
|
|
7663
7642
|
});
|
|
7643
|
+
crawled += batch.length;
|
|
7644
|
+
let added = false;
|
|
7645
|
+
for (const href of newLinks) {
|
|
7646
|
+
const n = norm(href);
|
|
7647
|
+
if (!seen.has(n) && seen.size < maxPages) {
|
|
7648
|
+
seen.add(n);
|
|
7649
|
+
queue.push(href);
|
|
7650
|
+
added = true;
|
|
7651
|
+
}
|
|
7652
|
+
}
|
|
7653
|
+
if (added) await setExtractJobTotal(jobId, Math.min(seen.size, maxPages));
|
|
7664
7654
|
}
|
|
7665
7655
|
const branding = Array.isArray(job.options.formats) && job.options.formats.includes("branding") ? await step.run("branding", () => extractBranding(job.startUrl, key).catch(() => null)) : null;
|
|
7666
7656
|
const imageAudit = Array.isArray(job.options.formats) && job.options.formats.includes("images") ? await step.run("image-audit", async () => {
|
|
@@ -9343,10 +9333,10 @@ function buildTranscriptMarkdown(result) {
|
|
|
9343
9333
|
if (result.chunks?.length) {
|
|
9344
9334
|
lines.push("## Timestamped Segments");
|
|
9345
9335
|
lines.push("");
|
|
9346
|
-
for (const
|
|
9347
|
-
const start = fmtTs(
|
|
9348
|
-
const end = fmtTs(
|
|
9349
|
-
lines.push(`**[${start} \u2192 ${end}]** ${
|
|
9336
|
+
for (const chunk of result.chunks) {
|
|
9337
|
+
const start = fmtTs(chunk.timestamp[0]);
|
|
9338
|
+
const end = fmtTs(chunk.timestamp[1]);
|
|
9339
|
+
lines.push(`**[${start} \u2192 ${end}]** ${chunk.text.trim()}`);
|
|
9350
9340
|
lines.push("");
|
|
9351
9341
|
}
|
|
9352
9342
|
}
|
|
@@ -9847,20 +9837,20 @@ var FacebookAdExtractor = class {
|
|
|
9847
9837
|
if (splitRe.lastIndex === m.index) splitRe.lastIndex++;
|
|
9848
9838
|
}
|
|
9849
9839
|
if (last < bodyText.length) adChunks.push(bodyText.slice(last));
|
|
9850
|
-
const ads = adChunks.filter((c) => /Library ID[:\s]+\d{10,20}/i.test(c)).slice(0, maxAds).map((
|
|
9851
|
-
const lidM =
|
|
9840
|
+
const ads = adChunks.filter((c) => /Library ID[:\s]+\d{10,20}/i.test(c)).slice(0, maxAds).map((chunk) => {
|
|
9841
|
+
const lidM = chunk.match(/Library ID[:\s]+([0-9]{10,20})/i);
|
|
9852
9842
|
const libraryId = lidM ? lidM[1] : null;
|
|
9853
|
-
const statusM =
|
|
9843
|
+
const statusM = chunk.match(/^(Active|Inactive)/i);
|
|
9854
9844
|
const status = statusM ? statusM[1] : null;
|
|
9855
|
-
const startM =
|
|
9845
|
+
const startM = chunk.match(/Started running on\s+([A-Za-z]+\.?\s+\d{1,2},?\s*\d{4})/i);
|
|
9856
9846
|
const started = startM ? startM[1].replace(/\s+/g, " ").trim() : null;
|
|
9857
9847
|
const visual = adVisuals[libraryId ?? ""] ?? { imageSrc: null, videoSrc: null, videoPoster: null };
|
|
9858
|
-
const hasVideoText = /0:00\s*\/\s*0:00|\d+:\d+\s*\/\s*\d+:\d+/.test(
|
|
9848
|
+
const hasVideoText = /0:00\s*\/\s*0:00|\d+:\d+\s*\/\s*\d+:\d+/.test(chunk);
|
|
9859
9849
|
const creativeType = visual.videoSrc || hasVideoText ? "video" : visual.imageSrc ? "image" : "unknown";
|
|
9860
9850
|
let domain = null;
|
|
9861
9851
|
const domainRe = /\b([A-Z0-9]{2,}(?:\.[A-Z]{2,})+)\b/g;
|
|
9862
9852
|
let dm;
|
|
9863
|
-
while ((dm = domainRe.exec(
|
|
9853
|
+
while ((dm = domainRe.exec(chunk)) !== null) {
|
|
9864
9854
|
const c = dm[1];
|
|
9865
9855
|
if (c.length >= 6 && c !== "LIBRARY") {
|
|
9866
9856
|
domain = c;
|
|
@@ -9869,9 +9859,9 @@ var FacebookAdExtractor = class {
|
|
|
9869
9859
|
}
|
|
9870
9860
|
let primaryText = null;
|
|
9871
9861
|
let headline = null;
|
|
9872
|
-
const sponsoredIdx =
|
|
9862
|
+
const sponsoredIdx = chunk.search(/\bSponsored\b/i);
|
|
9873
9863
|
if (sponsoredIdx >= 0) {
|
|
9874
|
-
let afterSponsored =
|
|
9864
|
+
let afterSponsored = chunk.slice(sponsoredIdx + "Sponsored".length).trim();
|
|
9875
9865
|
afterSponsored = afterSponsored.replace(/\s*\d*:?\d+\s*\/\s*\d*:?\d+.*$/, "");
|
|
9876
9866
|
if (domain) {
|
|
9877
9867
|
const di = afterSponsored.indexOf(domain);
|
|
@@ -9882,18 +9872,18 @@ var FacebookAdExtractor = class {
|
|
|
9882
9872
|
}
|
|
9883
9873
|
const ctaRe2 = new RegExp("\\b(" + CTA_LABELS.map((l) => l.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|") + ")\\b", "i");
|
|
9884
9874
|
if (domain) {
|
|
9885
|
-
const di =
|
|
9875
|
+
const di = chunk.indexOf(domain);
|
|
9886
9876
|
if (di >= 0) {
|
|
9887
|
-
let afterDomain =
|
|
9877
|
+
let afterDomain = chunk.slice(di + domain.length).trim();
|
|
9888
9878
|
const ctaMatch = afterDomain.search(ctaRe2);
|
|
9889
9879
|
if (ctaMatch >= 0) afterDomain = afterDomain.slice(0, ctaMatch).trim();
|
|
9890
9880
|
if (afterDomain.length > 3 && afterDomain.length < 120) headline = afterDomain;
|
|
9891
9881
|
}
|
|
9892
9882
|
}
|
|
9893
9883
|
if (!headline) {
|
|
9894
|
-
const ctaIdx =
|
|
9884
|
+
const ctaIdx = chunk.search(ctaRe2);
|
|
9895
9885
|
if (ctaIdx > 0) {
|
|
9896
|
-
const beforeCta =
|
|
9886
|
+
const beforeCta = chunk.slice(0, ctaIdx).trimEnd();
|
|
9897
9887
|
const sentenceEnd = Math.max(beforeCta.lastIndexOf(". "), beforeCta.lastIndexOf("! "), beforeCta.lastIndexOf("? "));
|
|
9898
9888
|
if (sentenceEnd >= 0) {
|
|
9899
9889
|
const candidate = beforeCta.slice(sentenceEnd + 2).trim();
|
|
@@ -9905,12 +9895,12 @@ var FacebookAdExtractor = class {
|
|
|
9905
9895
|
}
|
|
9906
9896
|
let cta = null;
|
|
9907
9897
|
for (const lbl of CTA_LABELS) {
|
|
9908
|
-
if (
|
|
9898
|
+
if (chunk.toLowerCase().includes(lbl.toLowerCase())) {
|
|
9909
9899
|
cta = lbl;
|
|
9910
9900
|
break;
|
|
9911
9901
|
}
|
|
9912
9902
|
}
|
|
9913
|
-
const multiM =
|
|
9903
|
+
const multiM = chunk.match(/(\d+)\s+ad[s]?\s+use[s]?\s+this/i);
|
|
9914
9904
|
const clusterCount = multiM ? parseInt(multiM[1]) : null;
|
|
9915
9905
|
return {
|
|
9916
9906
|
libraryId,
|
|
@@ -9933,8 +9923,8 @@ var FacebookAdExtractor = class {
|
|
|
9933
9923
|
const unknownCreativeCount = ads.filter((a) => a.creativeType === "unknown").length;
|
|
9934
9924
|
const advertiserPageId = new URL(page.url()).searchParams.get("view_all_page_id") ?? null;
|
|
9935
9925
|
const nameFreq = /* @__PURE__ */ new Map();
|
|
9936
|
-
for (const
|
|
9937
|
-
const detailsParts =
|
|
9926
|
+
for (const chunk of adChunks) {
|
|
9927
|
+
const detailsParts = chunk.split("See ad details ");
|
|
9938
9928
|
if (detailsParts.length < 2) continue;
|
|
9939
9929
|
const sponsoredIdx = detailsParts[1].indexOf(" Sponsored");
|
|
9940
9930
|
if (sponsoredIdx < 0) continue;
|
|
@@ -10674,11 +10664,11 @@ facebookAdApp.post("/search", createApiKeyAuth(), async (c) => {
|
|
|
10674
10664
|
}
|
|
10675
10665
|
if (last < bodyText.length) adChunks.push(bodyText.slice(last));
|
|
10676
10666
|
const advertiserMap = /* @__PURE__ */ new Map();
|
|
10677
|
-
for (const
|
|
10678
|
-
const lidM =
|
|
10667
|
+
for (const chunk of adChunks) {
|
|
10668
|
+
const lidM = chunk.match(/Library ID[:\s]+([0-9]{10,20})/i);
|
|
10679
10669
|
if (!lidM) continue;
|
|
10680
10670
|
const libraryId = lidM[1];
|
|
10681
|
-
const detailsParts =
|
|
10671
|
+
const detailsParts = chunk.split("See ad details ");
|
|
10682
10672
|
if (detailsParts.length < 2) continue;
|
|
10683
10673
|
const afterDetails = detailsParts[1];
|
|
10684
10674
|
const sponsoredIdx = afterDetails.indexOf(" Sponsored");
|
|
@@ -11230,8 +11220,8 @@ function runFfmpegMux(videoPath, audioPath, outPath) {
|
|
|
11230
11220
|
stdio: ["ignore", "ignore", "pipe"]
|
|
11231
11221
|
});
|
|
11232
11222
|
let stderr = "";
|
|
11233
|
-
child.stderr.on("data", (
|
|
11234
|
-
stderr += String(
|
|
11223
|
+
child.stderr.on("data", (chunk) => {
|
|
11224
|
+
stderr += String(chunk);
|
|
11235
11225
|
});
|
|
11236
11226
|
child.on("error", (err) => resolve({ ok: false, error: err.message }));
|
|
11237
11227
|
child.on("close", (code) => resolve({ ok: code === 0, error: code === 0 ? null : stderr.trim() || `ffmpeg exited ${code}` }));
|
|
@@ -14363,8 +14353,64 @@ async function migrateBrowserAgent() {
|
|
|
14363
14353
|
)
|
|
14364
14354
|
`);
|
|
14365
14355
|
await db.execute(`CREATE INDEX IF NOT EXISTS browser_agent_replays_session ON browser_agent_replays(session_id)`);
|
|
14356
|
+
await db.execute(`
|
|
14357
|
+
CREATE TABLE IF NOT EXISTS browser_auth_connections (
|
|
14358
|
+
connection_id TEXT PRIMARY KEY,
|
|
14359
|
+
hosted_url TEXT,
|
|
14360
|
+
domain TEXT,
|
|
14361
|
+
profile TEXT,
|
|
14362
|
+
account_email TEXT,
|
|
14363
|
+
note TEXT,
|
|
14364
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
14365
|
+
updated_at TEXT
|
|
14366
|
+
)
|
|
14367
|
+
`);
|
|
14368
|
+
try {
|
|
14369
|
+
await db.execute(`ALTER TABLE browser_auth_connections ADD COLUMN account_email TEXT`);
|
|
14370
|
+
} catch {
|
|
14371
|
+
}
|
|
14372
|
+
try {
|
|
14373
|
+
await db.execute(`ALTER TABLE browser_auth_connections ADD COLUMN note TEXT`);
|
|
14374
|
+
} catch {
|
|
14375
|
+
}
|
|
14376
|
+
try {
|
|
14377
|
+
await db.execute(`ALTER TABLE browser_auth_connections ADD COLUMN updated_at TEXT`);
|
|
14378
|
+
} catch {
|
|
14379
|
+
}
|
|
14380
|
+
await db.execute(`CREATE INDEX IF NOT EXISTS browser_auth_connections_profile ON browser_auth_connections(profile)`);
|
|
14366
14381
|
_ready = true;
|
|
14367
14382
|
}
|
|
14383
|
+
async function saveAuthConnection(input) {
|
|
14384
|
+
if (!input.connectionId) return;
|
|
14385
|
+
const db = getDb();
|
|
14386
|
+
await db.execute({
|
|
14387
|
+
sql: `INSERT INTO browser_auth_connections (connection_id, hosted_url, domain, profile, account_email, note, updated_at)
|
|
14388
|
+
VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
|
|
14389
|
+
ON CONFLICT(connection_id) DO UPDATE SET
|
|
14390
|
+
hosted_url = COALESCE(excluded.hosted_url, browser_auth_connections.hosted_url),
|
|
14391
|
+
domain = COALESCE(excluded.domain, browser_auth_connections.domain),
|
|
14392
|
+
profile = COALESCE(excluded.profile, browser_auth_connections.profile),
|
|
14393
|
+
account_email = COALESCE(excluded.account_email, browser_auth_connections.account_email),
|
|
14394
|
+
note = COALESCE(excluded.note, browser_auth_connections.note),
|
|
14395
|
+
updated_at = datetime('now')`,
|
|
14396
|
+
args: [input.connectionId, input.hostedUrl, input.domain, input.profile, input.accountEmail ?? null, input.note ?? null]
|
|
14397
|
+
});
|
|
14398
|
+
}
|
|
14399
|
+
async function getAuthConnectionRow(connectionId) {
|
|
14400
|
+
if (!connectionId) return null;
|
|
14401
|
+
const db = getDb();
|
|
14402
|
+
const res = await db.execute({ sql: `SELECT * FROM browser_auth_connections WHERE connection_id = ?`, args: [connectionId] });
|
|
14403
|
+
return res.rows[0] ?? null;
|
|
14404
|
+
}
|
|
14405
|
+
async function listAuthConnectionsByProfile(profile) {
|
|
14406
|
+
if (!profile) return [];
|
|
14407
|
+
const db = getDb();
|
|
14408
|
+
const res = await db.execute({
|
|
14409
|
+
sql: `SELECT * FROM browser_auth_connections WHERE profile = ? ORDER BY COALESCE(updated_at, created_at) DESC`,
|
|
14410
|
+
args: [profile]
|
|
14411
|
+
});
|
|
14412
|
+
return res.rows;
|
|
14413
|
+
}
|
|
14368
14414
|
async function createSessionRow(input) {
|
|
14369
14415
|
const db = getDb();
|
|
14370
14416
|
const id = `bas_${randomUUID2().replace(/-/g, "").slice(0, 20)}`;
|
|
@@ -15197,6 +15243,17 @@ async function findProfileConnection(k, profileName, domain) {
|
|
|
15197
15243
|
}
|
|
15198
15244
|
return null;
|
|
15199
15245
|
}
|
|
15246
|
+
async function listProfileConnections(profileName) {
|
|
15247
|
+
if (!profileName) return [];
|
|
15248
|
+
const k = client();
|
|
15249
|
+
const out = [];
|
|
15250
|
+
for await (const connection of k.auth.connections.list({ profile_name: profileName })) {
|
|
15251
|
+
const data = connection;
|
|
15252
|
+
if (data.profile_name && data.profile_name !== profileName) continue;
|
|
15253
|
+
out.push(profileOnboardResult(connection));
|
|
15254
|
+
}
|
|
15255
|
+
return out;
|
|
15256
|
+
}
|
|
15200
15257
|
async function findOrCreateProfileConnection(k, opts) {
|
|
15201
15258
|
try {
|
|
15202
15259
|
return await k.auth.connections.create({
|
|
@@ -15590,7 +15647,7 @@ function publicSession(row) {
|
|
|
15590
15647
|
session_id: row.id,
|
|
15591
15648
|
status: row.status,
|
|
15592
15649
|
label: row.label,
|
|
15593
|
-
|
|
15650
|
+
watch_url: `/console/${row.id}`,
|
|
15594
15651
|
created_at: row.created_at,
|
|
15595
15652
|
last_action_at: row.last_action_at,
|
|
15596
15653
|
closed_at: row.closed_at,
|
|
@@ -15646,10 +15703,23 @@ function buildBrowserAgentRoutes() {
|
|
|
15646
15703
|
const profileName = typeof body.profile === "string" ? body.profile.trim() : "";
|
|
15647
15704
|
const domain = typeof body.domain === "string" ? body.domain.trim().replace(/^https?:\/\//, "").replace(/\/.*$/, "") : "chatgpt.com";
|
|
15648
15705
|
const loginUrl = typeof body.login_url === "string" ? body.login_url.trim() : void 0;
|
|
15706
|
+
const accountEmail = typeof body.account_email === "string" ? body.account_email.trim() || null : null;
|
|
15707
|
+
const note = typeof body.note === "string" ? body.note.trim() || null : null;
|
|
15649
15708
|
if (!profileName) return c.json({ error: "profile is required" }, 400);
|
|
15650
15709
|
if (!domain) return c.json({ error: "domain is required" }, 400);
|
|
15651
15710
|
try {
|
|
15652
15711
|
const result = await startProfileOnboarding({ profileName, domain, loginUrl });
|
|
15712
|
+
try {
|
|
15713
|
+
await saveAuthConnection({
|
|
15714
|
+
connectionId: result.connectionId,
|
|
15715
|
+
hostedUrl: result.hostedUrl,
|
|
15716
|
+
domain: result.domain,
|
|
15717
|
+
profile: result.profileName,
|
|
15718
|
+
accountEmail,
|
|
15719
|
+
note
|
|
15720
|
+
});
|
|
15721
|
+
} catch {
|
|
15722
|
+
}
|
|
15653
15723
|
return c.json({
|
|
15654
15724
|
connection_id: result.connectionId,
|
|
15655
15725
|
profile: result.profileName,
|
|
@@ -15658,8 +15728,6 @@ function buildBrowserAgentRoutes() {
|
|
|
15658
15728
|
flow_status: result.flowStatus,
|
|
15659
15729
|
flow_step: result.flowStep,
|
|
15660
15730
|
flow_expires_at: result.flowExpiresAt,
|
|
15661
|
-
hosted_url: result.hostedUrl,
|
|
15662
|
-
live_view_url: result.liveViewUrl,
|
|
15663
15731
|
browser_session_id: result.browserSessionId,
|
|
15664
15732
|
post_login_url: result.postLoginUrl
|
|
15665
15733
|
});
|
|
@@ -15674,6 +15742,17 @@ function buildBrowserAgentRoutes() {
|
|
|
15674
15742
|
const domain = typeof body.domain === "string" ? body.domain.trim().replace(/^https?:\/\//, "").replace(/\/.*$/, "") : void 0;
|
|
15675
15743
|
try {
|
|
15676
15744
|
const result = await getProfileOnboardingStatus({ connectionId, profileName, domain });
|
|
15745
|
+
if (result.hostedUrl) {
|
|
15746
|
+
try {
|
|
15747
|
+
await saveAuthConnection({
|
|
15748
|
+
connectionId: result.connectionId,
|
|
15749
|
+
hostedUrl: result.hostedUrl,
|
|
15750
|
+
domain: result.domain,
|
|
15751
|
+
profile: result.profileName
|
|
15752
|
+
});
|
|
15753
|
+
} catch {
|
|
15754
|
+
}
|
|
15755
|
+
}
|
|
15677
15756
|
return c.json({
|
|
15678
15757
|
connection_id: result.connectionId,
|
|
15679
15758
|
profile: result.profileName,
|
|
@@ -15682,8 +15761,6 @@ function buildBrowserAgentRoutes() {
|
|
|
15682
15761
|
flow_status: result.flowStatus,
|
|
15683
15762
|
flow_step: result.flowStep,
|
|
15684
15763
|
flow_expires_at: result.flowExpiresAt,
|
|
15685
|
-
hosted_url: result.hostedUrl,
|
|
15686
|
-
live_view_url: result.liveViewUrl,
|
|
15687
15764
|
browser_session_id: result.browserSessionId,
|
|
15688
15765
|
post_login_url: result.postLoginUrl
|
|
15689
15766
|
});
|
|
@@ -15691,6 +15768,37 @@ function buildBrowserAgentRoutes() {
|
|
|
15691
15768
|
return c.json(failure(err), 404);
|
|
15692
15769
|
}
|
|
15693
15770
|
});
|
|
15771
|
+
app2.post("/profiles/list", async (c) => {
|
|
15772
|
+
const body = await c.req.json().catch(() => ({}));
|
|
15773
|
+
const profileName = typeof body.profile === "string" ? body.profile.trim() : "";
|
|
15774
|
+
if (!profileName) return c.json({ error: "profile is required" }, 400);
|
|
15775
|
+
const domainFilter = typeof body.domain === "string" ? body.domain.trim().replace(/^https?:\/\//, "").replace(/\/.*$/, "") : void 0;
|
|
15776
|
+
const connectionIdFilter = typeof body.connection_id === "string" ? body.connection_id.trim() : void 0;
|
|
15777
|
+
try {
|
|
15778
|
+
const [live, stored] = await Promise.all([
|
|
15779
|
+
listProfileConnections(profileName),
|
|
15780
|
+
listAuthConnectionsByProfile(profileName).catch(() => [])
|
|
15781
|
+
]);
|
|
15782
|
+
const notesByDomain = new Map(stored.map((row) => [row.domain ?? "", row]));
|
|
15783
|
+
const notesByConnection = new Map(stored.map((row) => [row.connection_id, row]));
|
|
15784
|
+
let connections = live.map((conn) => {
|
|
15785
|
+
const record = notesByConnection.get(conn.connectionId) ?? notesByDomain.get(conn.domain);
|
|
15786
|
+
return {
|
|
15787
|
+
connection_id: conn.connectionId,
|
|
15788
|
+
domain: conn.domain,
|
|
15789
|
+
status: conn.status,
|
|
15790
|
+
account_email: record?.account_email ?? null,
|
|
15791
|
+
note: record?.note ?? null,
|
|
15792
|
+
last_connected_at: record?.updated_at ?? record?.created_at ?? null
|
|
15793
|
+
};
|
|
15794
|
+
});
|
|
15795
|
+
if (connectionIdFilter) connections = connections.filter((c2) => c2.connection_id === connectionIdFilter);
|
|
15796
|
+
if (domainFilter) connections = connections.filter((c2) => c2.domain === domainFilter);
|
|
15797
|
+
return c.json({ profile: profileName, connections });
|
|
15798
|
+
} catch (err) {
|
|
15799
|
+
return c.json(failure(err), 502);
|
|
15800
|
+
}
|
|
15801
|
+
});
|
|
15694
15802
|
app2.post("/sessions", async (c) => {
|
|
15695
15803
|
const user = c.get("user");
|
|
15696
15804
|
if (Number(user.balance_mc ?? 0) < BROWSER_OPEN_MIN_BALANCE_MC) {
|
|
@@ -16047,6 +16155,50 @@ function buildBrowserAgentRoutes() {
|
|
|
16047
16155
|
}
|
|
16048
16156
|
|
|
16049
16157
|
// src/api/browser-agent-console.ts
|
|
16158
|
+
function renderAuthConsoleHtml(connectionId, hostedUrl) {
|
|
16159
|
+
const safeId = String(connectionId).replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
16160
|
+
const goUrl = `/console/auth/${encodeURIComponent(connectionId)}/go`;
|
|
16161
|
+
const body = hostedUrl ? `<iframe class="stage" allow="clipboard-read; clipboard-write" src="${goUrl}"></iframe>
|
|
16162
|
+
<div class="fallback">
|
|
16163
|
+
<span>Sign-in window not showing?</span>
|
|
16164
|
+
<a class="btn" href="${goUrl}" target="_blank" rel="noopener">Open sign-in in a new tab</a>
|
|
16165
|
+
</div>` : `<div class="empty">
|
|
16166
|
+
<div>This sign-in link is no longer active.</div>
|
|
16167
|
+
<div class="muted">Ask the assistant to reconnect the profile, then open the new link.</div>
|
|
16168
|
+
</div>`;
|
|
16169
|
+
return `<!DOCTYPE html>
|
|
16170
|
+
<html lang="en">
|
|
16171
|
+
<head>
|
|
16172
|
+
<meta charset="UTF-8" />
|
|
16173
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
16174
|
+
<title>MCP Scraper \u2014 Secure Sign-in</title>
|
|
16175
|
+
<style>
|
|
16176
|
+
:root { color-scheme: dark; }
|
|
16177
|
+
:where(*) { box-sizing: border-box; }
|
|
16178
|
+
body { margin: 0; height: 100vh; display: flex; flex-direction: column; font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, sans-serif; background: #0b0e14; color: #d7dce5; }
|
|
16179
|
+
header { display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-bottom: 1px solid #1c2230; background: #0f131c; }
|
|
16180
|
+
header h1 { font-size: 14px; margin: 0; font-weight: 600; color: #fff; }
|
|
16181
|
+
header .muted { color: #6b7689; font-size: 12px; }
|
|
16182
|
+
.spacer { flex: 1; }
|
|
16183
|
+
.stage { flex: 1; width: 100%; border: 0; display: block; background: #05070b; }
|
|
16184
|
+
.fallback { display: flex; align-items: center; gap: 12px; padding: 10px 18px; border-top: 1px solid #1c2230; background: #0f131c; font-size: 13px; color: #8893a7; }
|
|
16185
|
+
.btn { background: #2b6cff; color: #fff; border-radius: 7px; padding: 7px 12px; text-decoration: none; font-weight: 500; }
|
|
16186
|
+
.empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: #8893a7; }
|
|
16187
|
+
.muted { color: #6b7689; font-size: 12px; }
|
|
16188
|
+
</style>
|
|
16189
|
+
${ATTRIBUTION_PIXEL_SCRIPT}
|
|
16190
|
+
</head>
|
|
16191
|
+
<body>
|
|
16192
|
+
<header>
|
|
16193
|
+
<h1>MCP Scraper</h1>
|
|
16194
|
+
<span class="muted">Secure sign-in \xB7 ${safeId}</span>
|
|
16195
|
+
<span class="spacer"></span>
|
|
16196
|
+
<span class="muted">Complete the login below \u2014 your session is saved to your profile.</span>
|
|
16197
|
+
</header>
|
|
16198
|
+
${body}
|
|
16199
|
+
</body>
|
|
16200
|
+
</html>`;
|
|
16201
|
+
}
|
|
16050
16202
|
function renderConsoleHtml(initialSessionId) {
|
|
16051
16203
|
const initial = JSON.stringify(initialSessionId ?? "");
|
|
16052
16204
|
return `<!DOCTYPE html>
|
|
@@ -17378,7 +17530,7 @@ app.get("/cron/tick", async (c) => {
|
|
|
17378
17530
|
if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
|
|
17379
17531
|
return c.json({ error: "Unauthorized" }, 401);
|
|
17380
17532
|
}
|
|
17381
|
-
const { drainQueue } = await import("./worker-
|
|
17533
|
+
const { drainQueue } = await import("./worker-J6I5XP2F.js");
|
|
17382
17534
|
const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
|
|
17383
17535
|
const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
|
|
17384
17536
|
const [results, sweepResult] = await Promise.all([
|
|
@@ -17400,6 +17552,19 @@ app.route("/serp-intelligence", serpIntelligenceApp);
|
|
|
17400
17552
|
app.route("/mcp", mcpApp);
|
|
17401
17553
|
app.route("/agent", buildBrowserAgentRoutes());
|
|
17402
17554
|
app.get("/console", (c) => c.html(renderConsoleHtml()));
|
|
17555
|
+
app.get("/console/auth/:id", async (c) => {
|
|
17556
|
+
const id = c.req.param("id");
|
|
17557
|
+
await migrateBrowserAgent();
|
|
17558
|
+
const row = await getAuthConnectionRow(id);
|
|
17559
|
+
return c.html(renderAuthConsoleHtml(id, row?.hosted_url ?? null));
|
|
17560
|
+
});
|
|
17561
|
+
app.get("/console/auth/:id/go", async (c) => {
|
|
17562
|
+
const id = c.req.param("id");
|
|
17563
|
+
await migrateBrowserAgent();
|
|
17564
|
+
const row = await getAuthConnectionRow(id);
|
|
17565
|
+
if (!row?.hosted_url) return c.text("This sign-in link is no longer active.", 404);
|
|
17566
|
+
return c.redirect(row.hosted_url, 302);
|
|
17567
|
+
});
|
|
17403
17568
|
app.get("/console/:id", (c) => c.html(renderConsoleHtml(c.req.param("id"))));
|
|
17404
17569
|
app.route("/stripe", stripeApp);
|
|
17405
17570
|
if (!process.env.INNGEST_EVENT_KEY) {
|
|
@@ -17508,4 +17673,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
17508
17673
|
export {
|
|
17509
17674
|
app
|
|
17510
17675
|
};
|
|
17511
|
-
//# sourceMappingURL=server-
|
|
17676
|
+
//# sourceMappingURL=server-3M3XCVOT.js.map
|