mcp-scraper 0.3.44 → 0.3.46
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/dist/bin/api-server.cjs +612 -359
- 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 +648 -380
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +2 -2
- package/dist/{chunk-X53SOJSL.js → chunk-BRVX6RDN.js} +2 -2
- package/dist/{chunk-DVRPXPYH.js → chunk-FUVQR6GK.js} +14 -3
- package/dist/chunk-FUVQR6GK.js.map +1 -0
- package/dist/{chunk-GMTS35L6.js → chunk-RXNHY3TF.js} +2 -2
- package/dist/{chunk-NONBSIES.js → chunk-SS5YBZVI.js} +685 -412
- package/dist/chunk-SS5YBZVI.js.map +1 -0
- package/dist/chunk-WT6OT2T3.js +7 -0
- package/dist/chunk-WT6OT2T3.js.map +1 -0
- package/dist/{db-LYQENFPW.js → db-H3S3M6KK.js} +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{server-AN6QUH6C.js → server-MGE3GYJW.js} +38 -80
- package/dist/server-MGE3GYJW.js.map +1 -0
- package/dist/{worker-H4EUD2Q5.js → worker-4CVMSUZR.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-3Q2NSHSR.js +0 -7
- package/dist/chunk-3Q2NSHSR.js.map +0 -1
- package/dist/chunk-DVRPXPYH.js.map +0 -1
- package/dist/chunk-NONBSIES.js.map +0 -1
- package/dist/server-AN6QUH6C.js.map +0 -1
- /package/dist/{chunk-X53SOJSL.js.map → chunk-BRVX6RDN.js.map} +0 -0
- /package/dist/{chunk-GMTS35L6.js.map → chunk-RXNHY3TF.js.map} +0 -0
- /package/dist/{db-LYQENFPW.js.map → db-H3S3M6KK.js.map} +0 -0
- /package/dist/{worker-H4EUD2Q5.js.map → worker-4CVMSUZR.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
harvest
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RXNHY3TF.js";
|
|
4
4
|
import "./chunk-3PRO376E.js";
|
|
5
5
|
import "./chunk-K443GQY5.js";
|
|
6
6
|
import "./chunk-BP27CZ5Q.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-FUVQR6GK.js";
|
|
8
8
|
|
|
9
9
|
// src/video/VideoGenerator.ts
|
|
10
10
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
computeIssues,
|
|
8
8
|
configureReportSaving,
|
|
9
9
|
exportFanout,
|
|
10
|
+
getBlobStore,
|
|
10
11
|
harvestTimeoutBudget,
|
|
12
|
+
hashOwnerId,
|
|
11
13
|
outputBaseDir,
|
|
12
14
|
registerBrowserAgentMcpTools,
|
|
13
15
|
registerSerpIntelligenceCaptureTools,
|
|
@@ -16,7 +18,7 @@ import {
|
|
|
16
18
|
renderLinkReport,
|
|
17
19
|
sanitizeAttempts,
|
|
18
20
|
sanitizeHarvestResult
|
|
19
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-SS5YBZVI.js";
|
|
20
22
|
import {
|
|
21
23
|
csvRecords,
|
|
22
24
|
listWorkflowDefinitions,
|
|
@@ -29,7 +31,7 @@ import {
|
|
|
29
31
|
workflowStepCount,
|
|
30
32
|
workflowSupportsSteps
|
|
31
33
|
} from "./chunk-NNEIXK5L.js";
|
|
32
|
-
import "./chunk-
|
|
34
|
+
import "./chunk-WT6OT2T3.js";
|
|
33
35
|
import {
|
|
34
36
|
BROWSER_OPEN_MIN_BALANCE_MC,
|
|
35
37
|
CONCURRENCY_PRICE_ID,
|
|
@@ -52,7 +54,7 @@ import {
|
|
|
52
54
|
harvestProblemResponse,
|
|
53
55
|
insufficientBalanceResponse,
|
|
54
56
|
serializeHarvestProblem
|
|
55
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-BRVX6RDN.js";
|
|
56
58
|
import {
|
|
57
59
|
BrowserDriver,
|
|
58
60
|
MapsSelectors,
|
|
@@ -65,7 +67,7 @@ import {
|
|
|
65
67
|
recordVendorUsage,
|
|
66
68
|
resolveKernelProxyId,
|
|
67
69
|
runWithCostContext
|
|
68
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-RXNHY3TF.js";
|
|
69
71
|
import {
|
|
70
72
|
CaptchaError,
|
|
71
73
|
RECAPTCHA_INSTRUCTIONS,
|
|
@@ -161,7 +163,7 @@ import {
|
|
|
161
163
|
setSubscriptionTier,
|
|
162
164
|
setUserMemoryCreds,
|
|
163
165
|
verifyPassword
|
|
164
|
-
} from "./chunk-
|
|
166
|
+
} from "./chunk-FUVQR6GK.js";
|
|
165
167
|
|
|
166
168
|
// src/blog/registry.ts
|
|
167
169
|
var posts = [
|
|
@@ -7420,58 +7422,6 @@ var siteAuditFn = inngest.createFunction(
|
|
|
7420
7422
|
}
|
|
7421
7423
|
);
|
|
7422
7424
|
|
|
7423
|
-
// src/api/blob-store.ts
|
|
7424
|
-
import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
7425
|
-
import { homedir as homedir2 } from "os";
|
|
7426
|
-
import { join as join4, dirname as dirname2 } from "path";
|
|
7427
|
-
function byteLength(data) {
|
|
7428
|
-
return Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data);
|
|
7429
|
-
}
|
|
7430
|
-
var LocalBlobStore = class {
|
|
7431
|
-
constructor(baseDir) {
|
|
7432
|
-
this.baseDir = baseDir;
|
|
7433
|
-
}
|
|
7434
|
-
baseDir;
|
|
7435
|
-
kind = "local";
|
|
7436
|
-
async put(key, data, contentType = "application/octet-stream") {
|
|
7437
|
-
const path5 = join4(this.baseDir, "blobs", key);
|
|
7438
|
-
mkdirSync2(dirname2(path5), { recursive: true });
|
|
7439
|
-
writeFileSync(path5, data);
|
|
7440
|
-
return { key, url: `file://${path5}`, bytes: byteLength(data), contentType };
|
|
7441
|
-
}
|
|
7442
|
-
};
|
|
7443
|
-
function localBaseDir() {
|
|
7444
|
-
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join4(homedir2(), "Downloads", "mcp-scraper");
|
|
7445
|
-
}
|
|
7446
|
-
var cached = null;
|
|
7447
|
-
function getBlobStore() {
|
|
7448
|
-
if (cached) return cached;
|
|
7449
|
-
if (process.env.BLOB_READ_WRITE_TOKEN) {
|
|
7450
|
-
cached = new VercelBlobStore(process.env.BLOB_READ_WRITE_TOKEN);
|
|
7451
|
-
} else {
|
|
7452
|
-
cached = new LocalBlobStore(localBaseDir());
|
|
7453
|
-
}
|
|
7454
|
-
return cached;
|
|
7455
|
-
}
|
|
7456
|
-
var VercelBlobStore = class {
|
|
7457
|
-
constructor(token) {
|
|
7458
|
-
this.token = token;
|
|
7459
|
-
}
|
|
7460
|
-
token;
|
|
7461
|
-
kind = "vercel-blob";
|
|
7462
|
-
async put(key, data, contentType = "application/octet-stream") {
|
|
7463
|
-
const { put } = await import("@vercel/blob");
|
|
7464
|
-
const body = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
7465
|
-
const result = await put(key, body, {
|
|
7466
|
-
access: "public",
|
|
7467
|
-
token: this.token,
|
|
7468
|
-
contentType,
|
|
7469
|
-
addRandomSuffix: true
|
|
7470
|
-
});
|
|
7471
|
-
return { key, url: result.url, bytes: byteLength(data), contentType };
|
|
7472
|
-
}
|
|
7473
|
-
};
|
|
7474
|
-
|
|
7475
7425
|
// src/api/site-extract-repository.ts
|
|
7476
7426
|
function rowToJob(r) {
|
|
7477
7427
|
return {
|
|
@@ -11180,9 +11130,9 @@ googleAdsApp.post("/transcribe", createApiKeyAuth(), async (c) => {
|
|
|
11180
11130
|
// src/api/instagram-routes.ts
|
|
11181
11131
|
import { Hono as Hono7 } from "hono";
|
|
11182
11132
|
import { z as z15 } from "zod";
|
|
11183
|
-
import { createWriteStream as createWriteStream2, mkdirSync as
|
|
11184
|
-
import { homedir as
|
|
11185
|
-
import { join as
|
|
11133
|
+
import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync2, statSync, writeFileSync } from "fs";
|
|
11134
|
+
import { homedir as homedir2 } from "os";
|
|
11135
|
+
import { join as join4 } from "path";
|
|
11186
11136
|
import { Readable as Readable2 } from "stream";
|
|
11187
11137
|
import { pipeline as pipeline2 } from "stream/promises";
|
|
11188
11138
|
import { spawn } from "child_process";
|
|
@@ -11609,7 +11559,7 @@ async function resolveInstagramLaunch(body) {
|
|
|
11609
11559
|
};
|
|
11610
11560
|
}
|
|
11611
11561
|
function outputBaseDir2() {
|
|
11612
|
-
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() ||
|
|
11562
|
+
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join4(homedir2(), "Downloads", "mcp-scraper");
|
|
11613
11563
|
}
|
|
11614
11564
|
function safeFilePart(input) {
|
|
11615
11565
|
return input.replace(/^https?:\/\//, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "instagram";
|
|
@@ -11617,8 +11567,8 @@ function safeFilePart(input) {
|
|
|
11617
11567
|
function mediaOutputDir(shortcode, sourceUrl) {
|
|
11618
11568
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
11619
11569
|
const slug = shortcode ? `instagram-${shortcode}` : safeFilePart(sourceUrl);
|
|
11620
|
-
const dir =
|
|
11621
|
-
|
|
11570
|
+
const dir = join4(outputBaseDir2(), "instagram", `${stamp}-${slug}`);
|
|
11571
|
+
mkdirSync2(dir, { recursive: true });
|
|
11622
11572
|
return dir;
|
|
11623
11573
|
}
|
|
11624
11574
|
async function downloadToFile(url, destPath, referer) {
|
|
@@ -11758,8 +11708,8 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
11758
11708
|
let outputDir = null;
|
|
11759
11709
|
if (body.downloadMedia) {
|
|
11760
11710
|
outputDir = mediaOutputDir(extraction.shortcode, sourceUrl.href);
|
|
11761
|
-
const textPath =
|
|
11762
|
-
|
|
11711
|
+
const textPath = join4(outputDir, `${extraction.shortcode ?? "instagram"}-text.txt`);
|
|
11712
|
+
writeFileSync(textPath, [
|
|
11763
11713
|
`URL: ${extraction.pageUrl}`,
|
|
11764
11714
|
extraction.caption ? `Caption: ${extraction.caption}` : "",
|
|
11765
11715
|
"",
|
|
@@ -11767,7 +11717,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
11767
11717
|
].filter(Boolean).join("\n"), "utf8");
|
|
11768
11718
|
downloads.push({ kind: "text", url: null, savedPath: textPath, sizeBytes: statSync(textPath).size, mimeType: "text/plain", error: null });
|
|
11769
11719
|
if (mediaTypes.has("image") && extraction.imageUrl) {
|
|
11770
|
-
const imagePathBase =
|
|
11720
|
+
const imagePathBase = join4(outputDir, `${extraction.shortcode ?? "instagram"}-image`);
|
|
11771
11721
|
try {
|
|
11772
11722
|
const downloaded = await downloadToFile(extraction.imageUrl, imagePathBase, extraction.pageUrl);
|
|
11773
11723
|
const ext = extFromMime(downloaded.mimeType, "jpg");
|
|
@@ -11787,7 +11737,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
11787
11737
|
if (track.streamType === "video" && !mediaTypes.has("video")) continue;
|
|
11788
11738
|
if (track.streamType === "audio" && !mediaTypes.has("audio")) continue;
|
|
11789
11739
|
const kind = track.streamType === "audio" ? "audio" : "video";
|
|
11790
|
-
const target =
|
|
11740
|
+
const target = join4(outputDir, trackFilename(track, index, extraction.shortcode));
|
|
11791
11741
|
try {
|
|
11792
11742
|
const downloaded = await downloadToFile(track.url, target, extraction.pageUrl);
|
|
11793
11743
|
downloads.push({ kind, url: track.url, savedPath: downloaded.savedPath, sizeBytes: downloaded.sizeBytes, mimeType: downloaded.mimeType, error: null });
|
|
@@ -11797,7 +11747,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
11797
11747
|
}
|
|
11798
11748
|
}
|
|
11799
11749
|
if (body.mux && mediaTypes.has("video") && mediaTypes.has("audio") && extraction.selectedVideoTrack && extraction.selectedAudioTrack && savedByUrl.has(extraction.selectedVideoTrack.url) && savedByUrl.has(extraction.selectedAudioTrack.url)) {
|
|
11800
|
-
const outPath =
|
|
11750
|
+
const outPath = join4(outputDir, `${extraction.shortcode ?? "instagram"}-muxed.mp4`);
|
|
11801
11751
|
const muxed = await runFfmpegMux(savedByUrl.get(extraction.selectedVideoTrack.url), savedByUrl.get(extraction.selectedAudioTrack.url), outPath);
|
|
11802
11752
|
if (muxed.ok) {
|
|
11803
11753
|
downloads.push({ kind: "muxed_video", url: null, savedPath: outPath, sizeBytes: statSync(outPath).size, mimeType: "video/mp4", error: null });
|
|
@@ -13136,7 +13086,7 @@ import { Hono as Hono11 } from "hono";
|
|
|
13136
13086
|
|
|
13137
13087
|
// src/directory/directory-workflow.ts
|
|
13138
13088
|
import { mkdir as mkdir2, writeFile } from "fs/promises";
|
|
13139
|
-
import { join as
|
|
13089
|
+
import { join as join5 } from "path";
|
|
13140
13090
|
import { z as z19 } from "zod";
|
|
13141
13091
|
|
|
13142
13092
|
// src/directory/location-db.ts
|
|
@@ -13472,11 +13422,11 @@ function csvRowsFor(result) {
|
|
|
13472
13422
|
return rows;
|
|
13473
13423
|
}
|
|
13474
13424
|
async function saveDirectoryCsv(result) {
|
|
13475
|
-
const outDir =
|
|
13425
|
+
const outDir = join5(outputBaseDir(), "directory-workflows");
|
|
13476
13426
|
await mkdir2(outDir, { recursive: true });
|
|
13477
13427
|
const stamp = result.extractedAt.replace(/[:.]/g, "-");
|
|
13478
13428
|
const slug = `${result.state}-${result.query}`.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
13479
|
-
const path5 =
|
|
13429
|
+
const path5 = join5(outDir, `${stamp}-${slug}-directory-workflow.csv`);
|
|
13480
13430
|
const headers = [
|
|
13481
13431
|
"source_query",
|
|
13482
13432
|
"source_location",
|
|
@@ -15117,9 +15067,9 @@ mcpApp.all("/", async (c) => {
|
|
|
15117
15067
|
enableJsonResponse: true
|
|
15118
15068
|
});
|
|
15119
15069
|
const consoleBaseUrl = process.env.BROWSER_AGENT_CONSOLE_URL?.trim() || baseUrl;
|
|
15120
|
-
const server = buildPaaExtractorMcpServer(executor, { savesReportsLocally: false });
|
|
15070
|
+
const server = buildPaaExtractorMcpServer(executor, { savesReportsLocally: false, ownerId: hashOwnerId(callerKey) });
|
|
15121
15071
|
registerSerpIntelligenceCaptureTools(server, executor);
|
|
15122
|
-
registerBrowserAgentMcpTools(server, { baseUrl, apiKey: callerKey, consoleBaseUrl });
|
|
15072
|
+
registerBrowserAgentMcpTools(server, { baseUrl, apiKey: callerKey, consoleBaseUrl, savesReportsLocally: false });
|
|
15123
15073
|
await server.connect(transport);
|
|
15124
15074
|
return transport.handleRequest(c.req.raw);
|
|
15125
15075
|
} catch {
|
|
@@ -17387,6 +17337,7 @@ function isScraperResource(resource) {
|
|
|
17387
17337
|
var ACCESS_TTL_SECONDS = 3600;
|
|
17388
17338
|
var REFRESH_TTL_SECONDS = 60 * 60 * 24 * 30;
|
|
17389
17339
|
var CODE_TTL_SECONDS = 60;
|
|
17340
|
+
var ROTATION_GRACE_SECONDS = 120;
|
|
17390
17341
|
var secureCookies = process.env.NODE_ENV === "production" || process.env.VERCEL === "1";
|
|
17391
17342
|
var sessionCookieOptions = {
|
|
17392
17343
|
httpOnly: true,
|
|
@@ -17762,6 +17713,13 @@ oauthApp.post("/oauth/token", async (c) => {
|
|
|
17762
17713
|
const refreshToken = get("refresh_token") ?? "";
|
|
17763
17714
|
const clientId = get("client_id") ?? "";
|
|
17764
17715
|
const record = await getRefresh(refreshToken);
|
|
17716
|
+
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)) {
|
|
17717
|
+
const graceUser = await getUserByEmail(record.identity);
|
|
17718
|
+
const gracePlan = graceUser ? resolvePlan(graceUser) : "free";
|
|
17719
|
+
const graceAudience = record.resource ?? RESOURCE();
|
|
17720
|
+
const graceAccess = await mintAccessToken(record.identity, record.scope, gracePlan, graceAudience);
|
|
17721
|
+
return c.json({ access_token: graceAccess, token_type: "Bearer", expires_in: ACCESS_TTL_SECONDS, refresh_token: record.replaced_by, scope: record.scope });
|
|
17722
|
+
}
|
|
17765
17723
|
if (!record || record.revoked) return tokenErrorResponse(c, "invalid_grant", "Refresh token is invalid or revoked", 400);
|
|
17766
17724
|
if (new Date(record.expires_at).getTime() < Date.now()) return tokenErrorResponse(c, "invalid_grant", "Refresh token has expired", 400);
|
|
17767
17725
|
if (clientId && record.client_id !== clientId) return tokenErrorResponse(c, "invalid_grant", "client_id mismatch", 400);
|
|
@@ -18868,8 +18826,8 @@ async function persistScrapeBody(user, opts) {
|
|
|
18868
18826
|
|
|
18869
18827
|
// src/api/scrape-blob-cleanup.ts
|
|
18870
18828
|
import { readdir, stat, unlink } from "fs/promises";
|
|
18871
|
-
import { homedir as
|
|
18872
|
-
import { join as
|
|
18829
|
+
import { homedir as homedir3 } from "os";
|
|
18830
|
+
import { join as join6 } from "path";
|
|
18873
18831
|
async function cleanupVercel(token, cutoff) {
|
|
18874
18832
|
const { list, del } = await import("@vercel/blob");
|
|
18875
18833
|
let cursor;
|
|
@@ -18886,8 +18844,8 @@ async function cleanupVercel(token, cutoff) {
|
|
|
18886
18844
|
return { deleted, store: "vercel-blob" };
|
|
18887
18845
|
}
|
|
18888
18846
|
async function cleanupLocal(cutoff) {
|
|
18889
|
-
const baseDir = process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() ||
|
|
18890
|
-
const dir =
|
|
18847
|
+
const baseDir = process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || join6(homedir3(), "Downloads", "mcp-scraper");
|
|
18848
|
+
const dir = join6(baseDir, "blobs", SCRAPE_FALLBACK_PREFIX.replace(/\/$/, ""));
|
|
18891
18849
|
let deleted = 0;
|
|
18892
18850
|
let entries;
|
|
18893
18851
|
try {
|
|
@@ -18896,7 +18854,7 @@ async function cleanupLocal(cutoff) {
|
|
|
18896
18854
|
return { deleted: 0, store: "local" };
|
|
18897
18855
|
}
|
|
18898
18856
|
for (const name of entries) {
|
|
18899
|
-
const path5 =
|
|
18857
|
+
const path5 = join6(dir, name);
|
|
18900
18858
|
try {
|
|
18901
18859
|
const s = await stat(path5);
|
|
18902
18860
|
if (s.isFile() && s.mtimeMs < cutoff) {
|
|
@@ -20564,7 +20522,7 @@ app.get("/cron/tick", async (c) => {
|
|
|
20564
20522
|
if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
|
|
20565
20523
|
return c.json({ error: "Unauthorized" }, 401);
|
|
20566
20524
|
}
|
|
20567
|
-
const { drainQueue } = await import("./worker-
|
|
20525
|
+
const { drainQueue } = await import("./worker-4CVMSUZR.js");
|
|
20568
20526
|
const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
|
|
20569
20527
|
const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
|
|
20570
20528
|
const [results, sweepResult, reapResult, expiredResult, blobCleanup] = await Promise.all([
|
|
@@ -20717,4 +20675,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
20717
20675
|
export {
|
|
20718
20676
|
app
|
|
20719
20677
|
};
|
|
20720
|
-
//# sourceMappingURL=server-
|
|
20678
|
+
//# sourceMappingURL=server-MGE3GYJW.js.map
|