mcp-scraper 0.21.5 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,7 +35,7 @@ import {
35
35
  sanitizeAttempts,
36
36
  sanitizeHarvestResult,
37
37
  transcribeMediaUrl
38
- } from "./chunk-QO7HX67W.js";
38
+ } from "./chunk-CGFJD7C6.js";
39
39
  import {
40
40
  auditImages,
41
41
  buildLinkReport,
@@ -76,7 +76,7 @@ import {
76
76
  RawMapsOverviewSchema,
77
77
  RawMapsReviewStatsSchema
78
78
  } from "./chunk-XGIPATLV.js";
79
- import "./chunk-YLX3SKJN.js";
79
+ import "./chunk-64DNEO5R.js";
80
80
  import {
81
81
  completeExtractJob,
82
82
  countSuccessfulPages,
@@ -21463,6 +21463,130 @@ ${lines.length ? `${lines.join("\n")}
21463
21463
  };
21464
21464
  }
21465
21465
 
21466
+ // src/api/search-console-table-export.ts
21467
+ import { randomUUID as randomUUID8 } from "crypto";
21468
+ var SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS = 5e4;
21469
+ var SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE = 2e3;
21470
+ var SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES = 50 * 1024 * 1024;
21471
+ var SEARCH_CONSOLE_TABLE_COLUMNS = [
21472
+ "id",
21473
+ "provider_record_id",
21474
+ "connection_id",
21475
+ "site_url",
21476
+ "permission_level",
21477
+ "date",
21478
+ "query",
21479
+ "page",
21480
+ "country",
21481
+ "device",
21482
+ "clicks",
21483
+ "impressions",
21484
+ "ctr",
21485
+ "position",
21486
+ "captured_at",
21487
+ "content_hash",
21488
+ "created_at",
21489
+ "updated_at"
21490
+ ];
21491
+ var SearchConsoleTableExportValidationError = class extends Error {
21492
+ };
21493
+ function validateSearchConsoleTableExportRequest(args) {
21494
+ const tableName = typeof args.tableName === "string" ? args.tableName.trim() : "";
21495
+ if (!/^gsc_performance_[a-f0-9]{12}$/.test(tableName)) {
21496
+ throw new SearchConsoleTableExportValidationError("tableName must be a Search Console performance table returned by list_service_connections.");
21497
+ }
21498
+ const allowedColumns = new Set(SEARCH_CONSOLE_TABLE_COLUMNS);
21499
+ const allowedOps = /* @__PURE__ */ new Set(["eq", "neq", "gt", "gte", "lt", "lte", "like", "in"]);
21500
+ const rawFilters = args.filters === void 0 ? [] : args.filters;
21501
+ if (!Array.isArray(rawFilters) || rawFilters.length > 20) {
21502
+ throw new SearchConsoleTableExportValidationError("filters must be an array with at most 20 entries.");
21503
+ }
21504
+ const filters = rawFilters.map((value) => {
21505
+ const filter = value && typeof value === "object" && !Array.isArray(value) ? value : null;
21506
+ if (!filter || typeof filter.column !== "string" || !allowedColumns.has(filter.column) || typeof filter.op !== "string" || !allowedOps.has(filter.op)) {
21507
+ throw new SearchConsoleTableExportValidationError("Each filter must use a documented Search Console table column and supported operator.");
21508
+ }
21509
+ if (filter.op === "in" && !Array.isArray(filter.value)) {
21510
+ throw new SearchConsoleTableExportValidationError("The in filter operator requires an array value.");
21511
+ }
21512
+ return {
21513
+ column: filter.column,
21514
+ op: filter.op,
21515
+ value: filter.value
21516
+ };
21517
+ });
21518
+ let sort;
21519
+ if (args.sort !== void 0) {
21520
+ const raw = args.sort && typeof args.sort === "object" && !Array.isArray(args.sort) ? args.sort : null;
21521
+ if (!raw || typeof raw.column !== "string" || !allowedColumns.has(raw.column) || raw.direction !== void 0 && raw.direction !== "asc" && raw.direction !== "desc") {
21522
+ throw new SearchConsoleTableExportValidationError("sort must use a documented Search Console table column and asc or desc direction.");
21523
+ }
21524
+ sort = {
21525
+ column: raw.column,
21526
+ ...raw.direction ? { direction: raw.direction } : {}
21527
+ };
21528
+ }
21529
+ const maxRows = args.maxRows === void 0 ? 1e4 : Number(args.maxRows);
21530
+ if (!Number.isInteger(maxRows) || maxRows < 1 || maxRows > SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS) {
21531
+ throw new SearchConsoleTableExportValidationError(`maxRows must be an integer from 1 to ${SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS}.`);
21532
+ }
21533
+ return { tableName, filters, ...sort ? { sort } : {}, maxRows };
21534
+ }
21535
+ async function exportSearchConsoleTableData(args) {
21536
+ const lines = [];
21537
+ let bytes = 0;
21538
+ let offset = 0;
21539
+ let matchedRows = 0;
21540
+ let stoppedForBytes = false;
21541
+ while (offset < args.maxRows) {
21542
+ const limit = Math.min(SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE, args.maxRows - offset);
21543
+ const page = await args.queryPage({
21544
+ tableName: args.tableName,
21545
+ filters: args.filters,
21546
+ ...args.sort ? { sort: args.sort } : {},
21547
+ limit,
21548
+ offset
21549
+ });
21550
+ if (!page.ok) throw new Error(page.error || "Search Console table query failed.");
21551
+ const rows = Array.isArray(page.rows) ? page.rows : [];
21552
+ matchedRows = Number.isSafeInteger(page.count) && Number(page.count) >= 0 ? Number(page.count) : rows.length;
21553
+ for (const row of rows) {
21554
+ const line = `${JSON.stringify(row)}
21555
+ `;
21556
+ const lineBytes = Buffer.byteLength(line);
21557
+ if (bytes + lineBytes > SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES) {
21558
+ stoppedForBytes = true;
21559
+ break;
21560
+ }
21561
+ lines.push(line);
21562
+ bytes += lineBytes;
21563
+ }
21564
+ offset += rows.length;
21565
+ if (stoppedForBytes || rows.length < limit || offset >= matchedRows) break;
21566
+ }
21567
+ const exportId = randomUUID8();
21568
+ const artifact = await args.writeArtifact({
21569
+ ownerId: args.ownerId,
21570
+ exportId,
21571
+ filename: `search-console-filtered-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`,
21572
+ content: lines.join("")
21573
+ });
21574
+ const complete = lines.length >= matchedRows;
21575
+ const warnings = [];
21576
+ if (!complete && lines.length >= args.maxRows) warnings.push("max_rows_reached");
21577
+ if (stoppedForBytes) warnings.push("artifact_size_limit_reached");
21578
+ warnings.push("search_console_source_returns_top_rows_not_guaranteed_exhaustive");
21579
+ return {
21580
+ ok: true,
21581
+ tableName: args.tableName,
21582
+ rowsExported: lines.length,
21583
+ matchedRows,
21584
+ complete,
21585
+ artifact,
21586
+ warnings
21587
+ };
21588
+ }
21589
+
21466
21590
  // src/api/credit-operations.ts
21467
21591
  async function applyMonthlyFreeRefresh(user) {
21468
21592
  return user;
@@ -23359,6 +23483,21 @@ function providerConfigKeyFrom(value) {
23359
23483
  const key = value.trim();
23360
23484
  return key && key.length <= 200 ? key : null;
23361
23485
  }
23486
+ function calendarAttendeesFrom(value) {
23487
+ if (!Array.isArray(value) || value.length > 100) return null;
23488
+ const attendees = [];
23489
+ for (const item of value) {
23490
+ if (!item || typeof item !== "object" || Array.isArray(item)) return null;
23491
+ const attendee = item;
23492
+ if (typeof attendee.email !== "string" || !attendee.email.trim()) return null;
23493
+ if (attendee.displayName !== void 0 && typeof attendee.displayName !== "string") return null;
23494
+ attendees.push({
23495
+ email: attendee.email.trim(),
23496
+ ...typeof attendee.displayName === "string" && attendee.displayName.trim() ? { displayName: attendee.displayName.trim() } : {}
23497
+ });
23498
+ }
23499
+ return attendees;
23500
+ }
23362
23501
  function bindingsForSchedule(bindings, scheduleActionId) {
23363
23502
  return bindings.filter((binding) => binding.scheduleActionId === scheduleActionId);
23364
23503
  }
@@ -23575,18 +23714,20 @@ app.post("/schedule-connections/actions/google-calendar/create-event", auth2, re
23575
23714
  const user = c.get("user");
23576
23715
  const body = await c.req.json().catch(() => ({}));
23577
23716
  const connectionId = providerConfigKeyFrom(body.connectionId);
23578
- if (!connectionId || typeof body.summary !== "string" || typeof body.startDateTime !== "string" || typeof body.endDateTime !== "string") {
23579
- return c.json({ ok: false, error: "connectionId, summary, startDateTime, and endDateTime are required." }, 400);
23717
+ const attendees = calendarAttendeesFrom(body.attendees);
23718
+ if (!connectionId || typeof body.summary !== "string" || typeof body.description !== "string" || typeof body.startDateTime !== "string" || typeof body.endDateTime !== "string" || !attendees) {
23719
+ return c.json({ ok: false, error: "connectionId, summary, description, startDateTime, endDateTime, and attendees are required." }, 400);
23580
23720
  }
23581
23721
  const timeZone = typeof body.timeZone === "string" ? body.timeZone : void 0;
23582
23722
  try {
23583
23723
  const result = await callScheduleConnectionAction(user.email, connectionId, {
23584
23724
  calendarId: typeof body.calendarId === "string" ? body.calendarId : "primary",
23585
23725
  summary: body.summary,
23586
- description: typeof body.description === "string" ? body.description : void 0,
23726
+ description: body.description,
23587
23727
  location: typeof body.location === "string" ? body.location : void 0,
23588
23728
  start: { dateTime: body.startDateTime, timeZone },
23589
- end: { dateTime: body.endDateTime, timeZone }
23729
+ end: { dateTime: body.endDateTime, timeZone },
23730
+ attendees
23590
23731
  });
23591
23732
  return c.json({ ok: true, result });
23592
23733
  } catch (err) {
@@ -23597,8 +23738,8 @@ app.post("/schedule-connections/actions/zoom/create-meeting", auth2, requireInte
23597
23738
  const user = c.get("user");
23598
23739
  const body = await c.req.json().catch(() => ({}));
23599
23740
  const connectionId = providerConfigKeyFrom(body.connectionId);
23600
- if (!connectionId || typeof body.topic !== "string" || typeof body.startDateTime !== "string") {
23601
- return c.json({ ok: false, error: "connectionId, topic, and startDateTime are required." }, 400);
23741
+ if (!connectionId || typeof body.topic !== "string" || typeof body.startDateTime !== "string" || typeof body.agenda !== "string") {
23742
+ return c.json({ ok: false, error: "connectionId, topic, startDateTime, and agenda are required." }, 400);
23602
23743
  }
23603
23744
  try {
23604
23745
  const result = await callScheduleConnectionAction(user.email, connectionId, {
@@ -23606,7 +23747,7 @@ app.post("/schedule-connections/actions/zoom/create-meeting", auth2, requireInte
23606
23747
  startDateTime: body.startDateTime,
23607
23748
  durationMinutes: typeof body.durationMinutes === "number" ? body.durationMinutes : 30,
23608
23749
  timezone: typeof body.timezone === "string" ? body.timezone : void 0,
23609
- agenda: typeof body.agenda === "string" ? body.agenda : void 0
23750
+ agenda: body.agenda
23610
23751
  });
23611
23752
  return c.json({ ok: true, result });
23612
23753
  } catch (err) {
@@ -23764,6 +23905,31 @@ app.post("/schedule-connections/actions/export", auth2, requireIntegrationsTier,
23764
23905
  return scheduleConnectionError(c, err, "Unable to export this connected service.");
23765
23906
  }
23766
23907
  });
23908
+ app.post("/schedule-connections/actions/export-search-console-table", auth2, requireIntegrationsTier, async (c) => {
23909
+ const user = c.get("user");
23910
+ const body = await c.req.json().catch(() => ({}));
23911
+ try {
23912
+ const request = validateSearchConsoleTableExportRequest(body);
23913
+ const { key, error } = await getOrCreateUserMemoryKey(user);
23914
+ if (!key) return c.json({ ok: false, error: error ?? "Memory table access is unavailable." }, 503);
23915
+ const result = await exportSearchConsoleTableData({
23916
+ ownerId: sha256Hex(user.api_key).slice(0, 24),
23917
+ ...request,
23918
+ queryPage: (input) => memoryCall("queryTableTool", input, key),
23919
+ writeArtifact: createConnectedDataArtifact
23920
+ });
23921
+ return c.json(result);
23922
+ } catch (err) {
23923
+ if (err instanceof SearchConsoleTableExportValidationError) {
23924
+ return c.json({ ok: false, error: err.message }, 400);
23925
+ }
23926
+ if (err instanceof Error && err.message === "connected_data_private_blob_not_configured") {
23927
+ return c.json({ ok: false, error: "Private connected-data artifact storage is not configured." }, 503);
23928
+ }
23929
+ console.error("[search-console-table-export]", err instanceof Error ? err.name : "unknown_error");
23930
+ return c.json({ ok: false, error: "Unable to export the persisted Search Console table." }, 502);
23931
+ }
23932
+ });
23767
23933
  app.post("/schedule-connections/actions/export-download", auth2, requireIntegrationsTier, async (c) => {
23768
23934
  const user = c.get("user");
23769
23935
  const body = await c.req.json().catch(() => ({}));
@@ -25025,4 +25191,4 @@ app.get("/blog/:slug/", (c) => {
25025
25191
  export {
25026
25192
  app
25027
25193
  };
25028
- //# sourceMappingURL=server-POMKHEXJ.js.map
25194
+ //# sourceMappingURL=server-XO2J5KFL.js.map