mcp-scraper 0.13.0 → 0.15.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.
- package/README.md +14 -2
- package/dist/bin/api-server.cjs +519 -22
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- 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 +6 -3
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +43 -11
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +3 -3
- package/dist/{chunk-DYGJKB3D.js → chunk-ETJBTYZX.js} +39 -10
- package/dist/chunk-ETJBTYZX.js.map +1 -0
- package/dist/{chunk-NIRP5LU7.js → chunk-IKABQWYQ.js} +6 -3
- package/dist/chunk-IKABQWYQ.js.map +1 -0
- package/dist/chunk-TK2S2M7G.js +7 -0
- package/dist/chunk-TK2S2M7G.js.map +1 -0
- package/dist/{server-ZVCJ4HXC.js → server-DDKXWYTO.js} +473 -14
- package/dist/server-DDKXWYTO.js.map +1 -0
- package/docs/mcp-tool-manifest.generated.json +7109 -324
- package/package.json +1 -1
- package/dist/chunk-4ZYUWN5V.js +0 -7
- package/dist/chunk-4ZYUWN5V.js.map +0 -1
- package/dist/chunk-DYGJKB3D.js.map +0 -1
- package/dist/chunk-NIRP5LU7.js.map +0 -1
- package/dist/server-ZVCJ4HXC.js.map +0 -1
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
renewConnectedDataArtifactDownload,
|
|
38
38
|
sanitizeAttempts,
|
|
39
39
|
sanitizeHarvestResult
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-ETJBTYZX.js";
|
|
41
41
|
import {
|
|
42
42
|
auditImages,
|
|
43
43
|
buildLinkReport,
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
RawMapsOverviewSchema,
|
|
74
74
|
RawMapsReviewStatsSchema
|
|
75
75
|
} from "./chunk-XGIPATLV.js";
|
|
76
|
-
import "./chunk-
|
|
76
|
+
import "./chunk-TK2S2M7G.js";
|
|
77
77
|
import {
|
|
78
78
|
completeExtractJob,
|
|
79
79
|
countSuccessfulPages,
|
|
@@ -20193,6 +20193,20 @@ var CONNECTED_DATA_EXPORT_BUDGET_MS = Number(
|
|
|
20193
20193
|
var CONNECTED_DATA_PAGE_START_HEADROOM_MS = Number(
|
|
20194
20194
|
process.env.MCP_SCRAPER_CONNECTED_DATA_PAGE_START_HEADROOM_MS ?? 13e4
|
|
20195
20195
|
);
|
|
20196
|
+
var CONNECTED_DATA_DATASETS = [
|
|
20197
|
+
"auto",
|
|
20198
|
+
"emails",
|
|
20199
|
+
"calendar_events",
|
|
20200
|
+
"zoom_recordings",
|
|
20201
|
+
"zoom_transcripts",
|
|
20202
|
+
"resend_data",
|
|
20203
|
+
"resend_emails",
|
|
20204
|
+
"resend_received_emails",
|
|
20205
|
+
"resend_logs",
|
|
20206
|
+
"resend_contacts",
|
|
20207
|
+
"resend_broadcasts",
|
|
20208
|
+
"resend_templates"
|
|
20209
|
+
];
|
|
20196
20210
|
var ConnectedDataExportValidationError = class extends Error {
|
|
20197
20211
|
constructor(message) {
|
|
20198
20212
|
super(message);
|
|
@@ -20226,7 +20240,7 @@ function resolveConnectedDataExportRequest(args) {
|
|
|
20226
20240
|
...args.cursor ? { cursor: args.cursor } : {}
|
|
20227
20241
|
};
|
|
20228
20242
|
}
|
|
20229
|
-
const supported =
|
|
20243
|
+
const supported = CONNECTED_DATA_DATASETS.filter((dataset2) => dataset2 !== "auto");
|
|
20230
20244
|
if (typeof continuation.cursor !== "string" || !continuation.cursor || typeof continuation.from !== "string" || !continuation.from || typeof continuation.to !== "string" || !continuation.to || !supported.includes(continuation.dataset)) {
|
|
20231
20245
|
throw new ConnectedDataExportValidationError("continuation is missing its cursor, from, to, or dataset.");
|
|
20232
20246
|
}
|
|
@@ -20258,6 +20272,7 @@ function previewRecord(value) {
|
|
|
20258
20272
|
const preview = {};
|
|
20259
20273
|
for (const key of [
|
|
20260
20274
|
"recordType",
|
|
20275
|
+
"dataset",
|
|
20261
20276
|
"id",
|
|
20262
20277
|
"providerRecordId",
|
|
20263
20278
|
"threadId",
|
|
@@ -20271,6 +20286,11 @@ function previewRecord(value) {
|
|
|
20271
20286
|
"snippet",
|
|
20272
20287
|
"topic",
|
|
20273
20288
|
"startTime",
|
|
20289
|
+
"email",
|
|
20290
|
+
"name",
|
|
20291
|
+
"status",
|
|
20292
|
+
"createdAt",
|
|
20293
|
+
"updatedAt",
|
|
20274
20294
|
"hasTranscript",
|
|
20275
20295
|
"contentTruncated"
|
|
20276
20296
|
]) {
|
|
@@ -20623,6 +20643,29 @@ var CONNECTION_SYNC_REQUIRED_TOOLS = {
|
|
|
20623
20643
|
"list-recordings",
|
|
20624
20644
|
"get-recording",
|
|
20625
20645
|
"get-meeting-transcript"
|
|
20646
|
+
],
|
|
20647
|
+
"github-getting-started": [
|
|
20648
|
+
"list-repositories",
|
|
20649
|
+
"list-issues",
|
|
20650
|
+
"list-pull-requests",
|
|
20651
|
+
"list-commits",
|
|
20652
|
+
"list-releases",
|
|
20653
|
+
"list-workflows",
|
|
20654
|
+
"list-workflow-runs"
|
|
20655
|
+
],
|
|
20656
|
+
resend: [
|
|
20657
|
+
"list-emails",
|
|
20658
|
+
"get-email",
|
|
20659
|
+
"list-received-emails",
|
|
20660
|
+
"get-received-email",
|
|
20661
|
+
"list-logs",
|
|
20662
|
+
"get-log",
|
|
20663
|
+
"list-contacts",
|
|
20664
|
+
"get-contact",
|
|
20665
|
+
"list-broadcasts",
|
|
20666
|
+
"get-broadcast",
|
|
20667
|
+
"list-templates",
|
|
20668
|
+
"get-template"
|
|
20626
20669
|
]
|
|
20627
20670
|
};
|
|
20628
20671
|
function connectionSyncPolicyIssues(selections) {
|
|
@@ -20992,7 +21035,7 @@ async function callScheduleConnectionExportPage(identity, input) {
|
|
|
20992
21035
|
}
|
|
20993
21036
|
const providerConfigKey = cleanString(data.providerConfigKey, 128);
|
|
20994
21037
|
const dataset = cleanString(data.dataset, 64);
|
|
20995
|
-
if (!providerConfigKey ||
|
|
21038
|
+
if (!providerConfigKey || dataset === "auto" || !CONNECTED_DATA_DATASETS.includes(dataset)) {
|
|
20996
21039
|
throw new NangoControlError("Connected-data export returned invalid provider metadata.");
|
|
20997
21040
|
}
|
|
20998
21041
|
if (!Array.isArray(data.records)) {
|
|
@@ -21019,6 +21062,315 @@ async function callScheduleConnectionExportPage(identity, input) {
|
|
|
21019
21062
|
};
|
|
21020
21063
|
}
|
|
21021
21064
|
|
|
21065
|
+
// src/api/resend-control.ts
|
|
21066
|
+
var DEFAULT_CONNECTION_CONTROL_URL = "https://mcp-scraper-scheduler.vercel.app";
|
|
21067
|
+
var RESEND_PROVIDER_CONFIG_KEY = "resend";
|
|
21068
|
+
var RESEND_LOGO_URL = "https://cdn.resend.com/brand/resend-icon-black.svg";
|
|
21069
|
+
var RESEND_DOCS_URL = "https://resend.com/docs/mcp-server";
|
|
21070
|
+
var RESEND_ADMIN_BLOCKED_TOOLS = [
|
|
21071
|
+
"connect-to-editor",
|
|
21072
|
+
"create-webhook",
|
|
21073
|
+
"create-api-key",
|
|
21074
|
+
"list-api-keys",
|
|
21075
|
+
"remove-api-key",
|
|
21076
|
+
"list-oauth-grants",
|
|
21077
|
+
"revoke-oauth-grant"
|
|
21078
|
+
];
|
|
21079
|
+
var RESEND_CONNECTION_SYNC_REQUIRED_TOOLS = [
|
|
21080
|
+
"list-emails",
|
|
21081
|
+
"get-email",
|
|
21082
|
+
"list-received-emails",
|
|
21083
|
+
"get-received-email",
|
|
21084
|
+
"list-logs",
|
|
21085
|
+
"get-log",
|
|
21086
|
+
"list-contacts",
|
|
21087
|
+
"get-contact",
|
|
21088
|
+
"list-broadcasts",
|
|
21089
|
+
"get-broadcast",
|
|
21090
|
+
"list-templates",
|
|
21091
|
+
"get-template"
|
|
21092
|
+
];
|
|
21093
|
+
var ResendControlError = class extends Error {
|
|
21094
|
+
status;
|
|
21095
|
+
constructor(message, status = 502) {
|
|
21096
|
+
super(message);
|
|
21097
|
+
this.name = "ResendControlError";
|
|
21098
|
+
this.status = status;
|
|
21099
|
+
}
|
|
21100
|
+
};
|
|
21101
|
+
function controlBaseUrl2() {
|
|
21102
|
+
return (process.env.SCHEDULE_INTEGRATIONS_CONTROL_URL?.trim() || process.env.NANGO_CONTROL_URL?.trim() || DEFAULT_CONNECTION_CONTROL_URL).replace(/\/$/, "");
|
|
21103
|
+
}
|
|
21104
|
+
function controlSecret2() {
|
|
21105
|
+
const secret2 = process.env.SCHEDULE_INTEGRATIONS_SECRET?.trim();
|
|
21106
|
+
if (!secret2) throw new ResendControlError("Resend connections are not configured.", 503);
|
|
21107
|
+
return secret2;
|
|
21108
|
+
}
|
|
21109
|
+
function isRecord2(value) {
|
|
21110
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
21111
|
+
}
|
|
21112
|
+
function unwrapData2(value) {
|
|
21113
|
+
return isRecord2(value) && isRecord2(value.data) ? value.data : value;
|
|
21114
|
+
}
|
|
21115
|
+
function cleanString2(value, max = 300) {
|
|
21116
|
+
if (typeof value !== "string") return null;
|
|
21117
|
+
const trimmed = value.trim();
|
|
21118
|
+
return trimmed ? trimmed.slice(0, max) : null;
|
|
21119
|
+
}
|
|
21120
|
+
function firstString2(record, keys, max = 300) {
|
|
21121
|
+
for (const key of keys) {
|
|
21122
|
+
const value = cleanString2(record[key], max);
|
|
21123
|
+
if (value) return value;
|
|
21124
|
+
}
|
|
21125
|
+
return null;
|
|
21126
|
+
}
|
|
21127
|
+
function cleanTools2(value) {
|
|
21128
|
+
if (!Array.isArray(value)) return [];
|
|
21129
|
+
return [...new Set(value.map((tool) => cleanString2(tool, 200)).filter((tool) => !!tool))].slice(0, 200);
|
|
21130
|
+
}
|
|
21131
|
+
function cleanStringArray2(value, maxItems = 50, maxLength = 500) {
|
|
21132
|
+
if (!Array.isArray(value)) return [];
|
|
21133
|
+
return [...new Set(value.map((item) => cleanString2(item, maxLength)).filter((item) => !!item))].slice(0, maxItems);
|
|
21134
|
+
}
|
|
21135
|
+
function cleanHttpsUrl2(value) {
|
|
21136
|
+
const candidate = cleanString2(value, 2e3);
|
|
21137
|
+
if (!candidate) return null;
|
|
21138
|
+
try {
|
|
21139
|
+
const url = new URL(candidate);
|
|
21140
|
+
return url.protocol === "https:" ? url.toString() : null;
|
|
21141
|
+
} catch {
|
|
21142
|
+
return null;
|
|
21143
|
+
}
|
|
21144
|
+
}
|
|
21145
|
+
function cleanAuthorizationUrl(value) {
|
|
21146
|
+
const candidate = cleanHttpsUrl2(value);
|
|
21147
|
+
if (!candidate) return null;
|
|
21148
|
+
const url = new URL(candidate);
|
|
21149
|
+
return url.hostname.toLowerCase() === "api.resend.com" && url.pathname === "/oauth/authorize" ? candidate : null;
|
|
21150
|
+
}
|
|
21151
|
+
function arrayFromPayload2(value, keys) {
|
|
21152
|
+
const unwrapped = unwrapData2(value);
|
|
21153
|
+
if (Array.isArray(unwrapped)) return unwrapped;
|
|
21154
|
+
if (!isRecord2(unwrapped)) return [];
|
|
21155
|
+
for (const key of keys) {
|
|
21156
|
+
if (Array.isArray(unwrapped[key])) return unwrapped[key];
|
|
21157
|
+
}
|
|
21158
|
+
return [];
|
|
21159
|
+
}
|
|
21160
|
+
async function controlRequest2(path5, init, timeoutMs = 2e4) {
|
|
21161
|
+
const response = await fetch(`${controlBaseUrl2()}${path5}`, {
|
|
21162
|
+
...init,
|
|
21163
|
+
headers: {
|
|
21164
|
+
accept: "application/json",
|
|
21165
|
+
authorization: `Bearer ${controlSecret2()}`,
|
|
21166
|
+
...init?.body ? { "content-type": "application/json" } : {},
|
|
21167
|
+
...init?.headers ?? {}
|
|
21168
|
+
},
|
|
21169
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
21170
|
+
}).catch((err) => {
|
|
21171
|
+
throw new ResendControlError(`Resend connection control is unavailable: ${err instanceof Error ? err.message : "network error"}`);
|
|
21172
|
+
});
|
|
21173
|
+
const text = await response.text();
|
|
21174
|
+
let body = {};
|
|
21175
|
+
try {
|
|
21176
|
+
body = text ? JSON.parse(text) : {};
|
|
21177
|
+
} catch {
|
|
21178
|
+
body = {};
|
|
21179
|
+
}
|
|
21180
|
+
if (!response.ok) {
|
|
21181
|
+
const upstream = isRecord2(body) ? cleanString2(body.error, 300) : null;
|
|
21182
|
+
throw new ResendControlError(upstream || `Resend connection control failed (${response.status}).`);
|
|
21183
|
+
}
|
|
21184
|
+
return body;
|
|
21185
|
+
}
|
|
21186
|
+
async function getResendCatalog() {
|
|
21187
|
+
const body = await controlRequest2("/api/internal/resend/catalog");
|
|
21188
|
+
const rows = arrayFromPayload2(body, ["providers", "catalog", "integrations", "services"]);
|
|
21189
|
+
const result = [];
|
|
21190
|
+
for (const row of rows) {
|
|
21191
|
+
if (!isRecord2(row)) continue;
|
|
21192
|
+
const id = firstString2(row, ["providerConfigKey", "provider_config_key", "id"]);
|
|
21193
|
+
if (id !== RESEND_PROVIDER_CONFIG_KEY) continue;
|
|
21194
|
+
const safeDefaultAllowedTools = cleanTools2(
|
|
21195
|
+
row.safeDefaultAllowedTools ?? row.safe_default_allowed_tools ?? row.readTools ?? row.read_tools
|
|
21196
|
+
);
|
|
21197
|
+
const actionTools = cleanTools2(row.actionTools ?? row.action_tools ?? row.writeTools ?? row.write_tools);
|
|
21198
|
+
const adminBlockedTools = cleanTools2(row.adminBlockedTools ?? row.admin_blocked_tools);
|
|
21199
|
+
result.push({
|
|
21200
|
+
providerConfigKey: RESEND_PROVIDER_CONFIG_KEY,
|
|
21201
|
+
provider: RESEND_PROVIDER_CONFIG_KEY,
|
|
21202
|
+
label: firstString2(row, ["label", "displayName", "display_name", "name"]) || "Resend",
|
|
21203
|
+
description: firstString2(row, ["description"], 500) || "Connect Resend through its official remote MCP to read email operations and run explicitly enabled delivery workflows.",
|
|
21204
|
+
logoUrl: cleanHttpsUrl2(row.logoUrl ?? row.logo_url ?? row.logo) || RESEND_LOGO_URL,
|
|
21205
|
+
docsUrl: cleanHttpsUrl2(row.docsUrl ?? row.docs_url ?? row.docs) || RESEND_DOCS_URL,
|
|
21206
|
+
authMode: "REMOTE_MCP_OAUTH2",
|
|
21207
|
+
categories: ["Email", "Developer tools"],
|
|
21208
|
+
safeDefaultAllowedTools,
|
|
21209
|
+
actionTools,
|
|
21210
|
+
adminBlockedTools: adminBlockedTools.length > 0 ? adminBlockedTools : [...RESEND_ADMIN_BLOCKED_TOOLS],
|
|
21211
|
+
connectionSyncSupported: true,
|
|
21212
|
+
connectionSyncRequiredTools: [...RESEND_CONNECTION_SYNC_REQUIRED_TOOLS],
|
|
21213
|
+
platformSetupStatus: firstString2(row, ["platformSetupStatus", "platform_setup_status", "setupStatus", "setup_status"], 100) || "ready",
|
|
21214
|
+
appReviewStatus: null,
|
|
21215
|
+
appReviewNote: "Secret-returning webhook creation, API-key, OAuth-grant, and raw editor-session access is permanently blocked from agents and schedules.",
|
|
21216
|
+
transport: "remote_mcp"
|
|
21217
|
+
});
|
|
21218
|
+
}
|
|
21219
|
+
return result;
|
|
21220
|
+
}
|
|
21221
|
+
async function getResendConnections(identity) {
|
|
21222
|
+
const query = new URLSearchParams({ identity }).toString();
|
|
21223
|
+
const body = await controlRequest2(`/api/internal/resend/connections?${query}`);
|
|
21224
|
+
const rows = arrayFromPayload2(body, ["connections"]);
|
|
21225
|
+
const result = [];
|
|
21226
|
+
for (const row of rows) {
|
|
21227
|
+
if (!isRecord2(row)) continue;
|
|
21228
|
+
const connectionId = firstString2(row, ["connectionId", "connection_id", "id"]);
|
|
21229
|
+
const providerConfigKey = firstString2(row, ["providerConfigKey", "provider_config_key", "provider"]) || RESEND_PROVIDER_CONFIG_KEY;
|
|
21230
|
+
if (!connectionId || providerConfigKey !== RESEND_PROVIDER_CONFIG_KEY) continue;
|
|
21231
|
+
const rawStatus = (firstString2(row, ["status"], 64) || "needs_reauth").toLowerCase();
|
|
21232
|
+
const pending = ["pending", "pending_oauth", "authorizing", "authorization_pending"].includes(rawStatus);
|
|
21233
|
+
const active = ["active", "connected", "ready"].includes(rawStatus);
|
|
21234
|
+
const reconnectRequired = row.reconnectRequired === true || row.reconnect_required === true || !pending && !active;
|
|
21235
|
+
result.push({
|
|
21236
|
+
connectionId,
|
|
21237
|
+
providerConfigKey: RESEND_PROVIDER_CONFIG_KEY,
|
|
21238
|
+
provider: RESEND_PROVIDER_CONFIG_KEY,
|
|
21239
|
+
label: firstString2(row, ["label", "accountLabel", "account_label", "displayName", "display_name"]) || "Resend account",
|
|
21240
|
+
status: pending ? "pending_oauth" : reconnectRequired ? "needs_reauth" : "connected",
|
|
21241
|
+
reconnectRequired,
|
|
21242
|
+
actionsEnabled: row.actionsEnabled === true || row.actions_enabled === true,
|
|
21243
|
+
readTools: cleanTools2(row.readTools ?? row.read_tools),
|
|
21244
|
+
actionTools: cleanTools2(row.actionTools ?? row.action_tools ?? row.writeTools ?? row.write_tools),
|
|
21245
|
+
adminBlockedTools: cleanTools2(row.adminBlockedTools ?? row.admin_blocked_tools).length > 0 ? cleanTools2(row.adminBlockedTools ?? row.admin_blocked_tools) : [...RESEND_ADMIN_BLOCKED_TOOLS],
|
|
21246
|
+
vaultName: firstString2(row, ["vaultName", "vault_name"], 100),
|
|
21247
|
+
tableName: firstString2(row, ["tableName", "table_name"], 100),
|
|
21248
|
+
createdAt: firstString2(row, ["createdAt", "created_at"], 100),
|
|
21249
|
+
updatedAt: firstString2(row, ["updatedAt", "updated_at"], 100),
|
|
21250
|
+
transport: "remote_mcp"
|
|
21251
|
+
});
|
|
21252
|
+
}
|
|
21253
|
+
return result;
|
|
21254
|
+
}
|
|
21255
|
+
function sanitizeConnectSession2(body) {
|
|
21256
|
+
const data = unwrapData2(body);
|
|
21257
|
+
if (!isRecord2(data)) throw new ResendControlError("The Resend connection service returned an invalid connect session.");
|
|
21258
|
+
const connectLink = cleanAuthorizationUrl(data.authorizationUrl ?? data.authorization_url ?? data.connectLink ?? data.connect_link);
|
|
21259
|
+
if (!connectLink) throw new ResendControlError("The Resend connection service did not return a trusted authorization link.");
|
|
21260
|
+
return {
|
|
21261
|
+
connectLink,
|
|
21262
|
+
sessionToken: null,
|
|
21263
|
+
expiresAt: firstString2(data, ["expiresAt", "expires_at"], 100)
|
|
21264
|
+
};
|
|
21265
|
+
}
|
|
21266
|
+
async function createResendConnectSession(identity, redirectUri) {
|
|
21267
|
+
const body = await controlRequest2("/api/internal/resend/connect-session", {
|
|
21268
|
+
method: "POST",
|
|
21269
|
+
body: JSON.stringify({ identity, email: identity, redirectUri })
|
|
21270
|
+
});
|
|
21271
|
+
return sanitizeConnectSession2(body);
|
|
21272
|
+
}
|
|
21273
|
+
async function createResendReconnectSession(identity, connectionId, redirectUri) {
|
|
21274
|
+
const body = await controlRequest2("/api/internal/resend/reconnect-session", {
|
|
21275
|
+
method: "POST",
|
|
21276
|
+
body: JSON.stringify({ identity, email: identity, connectionId, redirectUri })
|
|
21277
|
+
});
|
|
21278
|
+
return sanitizeConnectSession2(body);
|
|
21279
|
+
}
|
|
21280
|
+
async function completeResendOAuthCallback(input) {
|
|
21281
|
+
await controlRequest2("/api/internal/resend/oauth/callback", {
|
|
21282
|
+
method: "POST",
|
|
21283
|
+
body: JSON.stringify(input)
|
|
21284
|
+
});
|
|
21285
|
+
}
|
|
21286
|
+
async function deleteResendConnection(identity, connectionId) {
|
|
21287
|
+
await controlRequest2("/api/internal/resend/connections", {
|
|
21288
|
+
method: "DELETE",
|
|
21289
|
+
body: JSON.stringify({ identity, connectionId })
|
|
21290
|
+
});
|
|
21291
|
+
}
|
|
21292
|
+
async function setResendActionsEnabled(identity, connectionId, enabled) {
|
|
21293
|
+
const body = await controlRequest2("/api/internal/resend/connections/actions", {
|
|
21294
|
+
method: "PUT",
|
|
21295
|
+
body: JSON.stringify({ identity, connectionId, enabled })
|
|
21296
|
+
});
|
|
21297
|
+
const data = unwrapData2(body);
|
|
21298
|
+
if (!isRecord2(data) || !isRecord2(data.connection)) return enabled;
|
|
21299
|
+
return data.connection.actionsEnabled === true || data.connection.actions_enabled === true;
|
|
21300
|
+
}
|
|
21301
|
+
async function callResendRead(identity, connectionId, tool, args) {
|
|
21302
|
+
const body = await controlRequest2("/api/internal/resend/read", {
|
|
21303
|
+
method: "POST",
|
|
21304
|
+
body: JSON.stringify({ identity, connectionId, tool, input: args ?? {} })
|
|
21305
|
+
});
|
|
21306
|
+
const data = unwrapData2(body);
|
|
21307
|
+
return isRecord2(data) ? data.result ?? data : data;
|
|
21308
|
+
}
|
|
21309
|
+
async function callResendAction(identity, connectionId, tool, input) {
|
|
21310
|
+
const body = await controlRequest2("/api/internal/resend/actions/call", {
|
|
21311
|
+
method: "POST",
|
|
21312
|
+
body: JSON.stringify({ identity, connectionId, tool, input })
|
|
21313
|
+
});
|
|
21314
|
+
const data = unwrapData2(body);
|
|
21315
|
+
return isRecord2(data) ? data.result ?? data : data;
|
|
21316
|
+
}
|
|
21317
|
+
async function describeResendTool(identity, connectionId, tool) {
|
|
21318
|
+
const body = await controlRequest2("/api/internal/resend/describe", {
|
|
21319
|
+
method: "POST",
|
|
21320
|
+
body: JSON.stringify({ identity, connectionId, tool })
|
|
21321
|
+
});
|
|
21322
|
+
const data = unwrapData2(body);
|
|
21323
|
+
const rawTool = isRecord2(data) && isRecord2(data.tool) ? data.tool : data;
|
|
21324
|
+
if (!isRecord2(rawTool)) throw new ResendControlError("Resend returned an invalid tool description.");
|
|
21325
|
+
const name = firstString2(rawTool, ["name"], 200);
|
|
21326
|
+
const classification = firstString2(rawTool, ["classification", "kind"], 20);
|
|
21327
|
+
const inputSchema = rawTool.inputSchema ?? rawTool.input_schema;
|
|
21328
|
+
if (!name || name !== tool || classification !== "read" && classification !== "action" || !isRecord2(inputSchema)) {
|
|
21329
|
+
throw new ResendControlError("Resend returned an invalid tool description.");
|
|
21330
|
+
}
|
|
21331
|
+
return {
|
|
21332
|
+
name,
|
|
21333
|
+
title: firstString2(rawTool, ["title"], 300),
|
|
21334
|
+
description: firstString2(rawTool, ["description"], 2e3),
|
|
21335
|
+
inputSchema,
|
|
21336
|
+
classification
|
|
21337
|
+
};
|
|
21338
|
+
}
|
|
21339
|
+
async function callResendExportPage(identity, input) {
|
|
21340
|
+
const body = await controlRequest2("/api/internal/resend/export-page", {
|
|
21341
|
+
method: "POST",
|
|
21342
|
+
body: JSON.stringify({ identity, ...input })
|
|
21343
|
+
}, 9e4);
|
|
21344
|
+
const data = unwrapData2(body);
|
|
21345
|
+
if (!isRecord2(data) || data.ok !== true || data.providerConfigKey !== RESEND_PROVIDER_CONFIG_KEY) {
|
|
21346
|
+
throw new ResendControlError("Resend export returned an invalid page response.");
|
|
21347
|
+
}
|
|
21348
|
+
const dataset = cleanString2(data.dataset, 64);
|
|
21349
|
+
if (!dataset || dataset === "auto" || !CONNECTED_DATA_DATASETS.includes(dataset)) {
|
|
21350
|
+
throw new ResendControlError("Resend export returned invalid dataset metadata.");
|
|
21351
|
+
}
|
|
21352
|
+
if (!Array.isArray(data.records)) throw new ResendControlError("Resend export returned invalid records.");
|
|
21353
|
+
if (data.nextCursor !== void 0 && data.nextCursor !== null && typeof data.nextCursor !== "string") {
|
|
21354
|
+
throw new ResendControlError("Resend export returned an invalid continuation cursor.");
|
|
21355
|
+
}
|
|
21356
|
+
const rawCounts = isRecord2(data.counts) ? data.counts : {};
|
|
21357
|
+
const numberOrZero = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
21358
|
+
return {
|
|
21359
|
+
providerConfigKey: RESEND_PROVIDER_CONFIG_KEY,
|
|
21360
|
+
dataset,
|
|
21361
|
+
records: data.records,
|
|
21362
|
+
nextCursor: typeof data.nextCursor === "string" ? data.nextCursor : null,
|
|
21363
|
+
complete: data.complete === true,
|
|
21364
|
+
counts: {
|
|
21365
|
+
listed: numberOrZero(rawCounts.listed),
|
|
21366
|
+
exported: numberOrZero(rawCounts.exported ?? rawCounts.returned),
|
|
21367
|
+
failed: numberOrZero(rawCounts.failed)
|
|
21368
|
+
},
|
|
21369
|
+
warnings: cleanStringArray2(data.warnings),
|
|
21370
|
+
untrustedContent: true
|
|
21371
|
+
};
|
|
21372
|
+
}
|
|
21373
|
+
|
|
21022
21374
|
// src/api/server.ts
|
|
21023
21375
|
var secureCookies2 = process.env.NODE_ENV === "production" || process.env.VERCEL === "1";
|
|
21024
21376
|
var isProduction2 = secureCookies2;
|
|
@@ -21634,6 +21986,7 @@ app.post("/schedule-checkout", auth2, async (c) => {
|
|
|
21634
21986
|
function scheduleConnectionError(c, err, fallback) {
|
|
21635
21987
|
if (err instanceof ScheduleConnectionValidationError) return c.json({ ok: false, error: err.message }, 400);
|
|
21636
21988
|
if (err instanceof NangoControlError) return c.json({ ok: false, error: err.message }, err.status);
|
|
21989
|
+
if (err instanceof ResendControlError) return c.json({ ok: false, error: err.message }, err.status);
|
|
21637
21990
|
console.error("[schedule-connections]", err instanceof Error ? err.message : String(err));
|
|
21638
21991
|
return c.json({ ok: false, error: fallback }, 502);
|
|
21639
21992
|
}
|
|
@@ -21645,6 +21998,52 @@ function providerConfigKeyFrom(value) {
|
|
|
21645
21998
|
function bindingsForSchedule(bindings, scheduleActionId) {
|
|
21646
21999
|
return bindings.filter((binding) => binding.scheduleActionId === scheduleActionId);
|
|
21647
22000
|
}
|
|
22001
|
+
function resendOAuthCallbackUrl() {
|
|
22002
|
+
return new URL("/oauth/resend/callback", appOrigin()).toString();
|
|
22003
|
+
}
|
|
22004
|
+
async function combinedConnectionCatalog() {
|
|
22005
|
+
const [nango, resend] = await Promise.allSettled([getNangoCatalog(), getResendCatalog()]);
|
|
22006
|
+
if (nango.status === "rejected") {
|
|
22007
|
+
console.warn("[schedule-connections] Nango catalog unavailable:", nango.reason instanceof Error ? nango.reason.message : "unknown error");
|
|
22008
|
+
}
|
|
22009
|
+
if (resend.status === "rejected") {
|
|
22010
|
+
console.warn("[schedule-connections] Resend catalog unavailable:", resend.reason instanceof Error ? resend.reason.message : "unknown error");
|
|
22011
|
+
}
|
|
22012
|
+
if (nango.status === "rejected" && resend.status === "rejected") throw nango.reason;
|
|
22013
|
+
return [
|
|
22014
|
+
...nango.status === "fulfilled" ? nango.value : [],
|
|
22015
|
+
...resend.status === "fulfilled" ? resend.value : []
|
|
22016
|
+
];
|
|
22017
|
+
}
|
|
22018
|
+
async function combinedConnections(identity) {
|
|
22019
|
+
const [nango, resend] = await Promise.allSettled([getNangoConnections(identity), getResendConnections(identity)]);
|
|
22020
|
+
if (nango.status === "rejected") {
|
|
22021
|
+
console.warn("[schedule-connections] Nango connection listing unavailable:", nango.reason instanceof Error ? nango.reason.message : "unknown error");
|
|
22022
|
+
}
|
|
22023
|
+
if (resend.status === "rejected") {
|
|
22024
|
+
console.warn("[schedule-connections] Resend connection listing unavailable:", resend.reason instanceof Error ? resend.reason.message : "unknown error");
|
|
22025
|
+
}
|
|
22026
|
+
if (nango.status === "rejected" && resend.status === "rejected") throw nango.reason;
|
|
22027
|
+
return [
|
|
22028
|
+
...nango.status === "fulfilled" ? nango.value.map((connection) => ({ ...connection, transport: "nango", adminBlockedTools: [] })) : [],
|
|
22029
|
+
...resend.status === "fulfilled" ? resend.value : []
|
|
22030
|
+
];
|
|
22031
|
+
}
|
|
22032
|
+
async function isResendConnection(identity, connectionId, providerHint) {
|
|
22033
|
+
if (providerHint === "resend") return true;
|
|
22034
|
+
if (providerHint) return false;
|
|
22035
|
+
try {
|
|
22036
|
+
return (await getResendConnections(identity)).some((connection) => connection.connectionId === connectionId);
|
|
22037
|
+
} catch (err) {
|
|
22038
|
+
console.warn("[schedule-connections] Resend connection resolution unavailable:", err instanceof Error ? err.message : "unknown error");
|
|
22039
|
+
return false;
|
|
22040
|
+
}
|
|
22041
|
+
}
|
|
22042
|
+
function renderResendOAuthResult(ok) {
|
|
22043
|
+
const title = ok ? "Resend connected" : "Resend connection not completed";
|
|
22044
|
+
const message = ok ? "Your Resend account is connected privately to MCP Scraper. You can close this tab." : "The connection could not be completed. Close this tab and try again from Integrations.";
|
|
22045
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="referrer" content="no-referrer"><title>${title}</title><style>:root{color-scheme:light dark}*{box-sizing:border-box}body{margin:0;min-height:100vh;display:grid;place-items:center;padding:24px;background:#f5f2ee;color:#26211d;font-family:ui-sans-serif,system-ui,-apple-system,sans-serif}.card{width:min(100%,440px);padding:32px;border:1px solid #d8d0c8;border-radius:16px;background:#fff;box-shadow:0 18px 55px rgba(31,24,18,.1)}.mark{width:38px;height:38px;display:grid;place-items:center;border-radius:10px;background:#26211d;color:#fff;font-size:20px;font-weight:700}h1{margin:18px 0 8px;font-size:24px;line-height:1.15}p{margin:0;color:#71675f;line-height:1.55}a{display:inline-flex;margin-top:20px;color:#b44d36;font-weight:650;text-underline-offset:3px}@media(prefers-color-scheme:dark){body{background:#171411;color:#f4eee8}.card{background:#211d19;border-color:#3b342d}.mark{background:#f4eee8;color:#211d19}p{color:#b9aea5}}</style></head><body><main class="card"><div class="mark" aria-hidden="true">R</div><h1>${title}</h1><p>${message}</p><a href="/dashboard/integrations">Return to Integrations</a></main><script>if(window.opener){try{window.opener.postMessage({type:'mcp-scraper:resend-oauth',ok:${ok}},window.location.origin)}catch(e){}}setTimeout(function(){window.close()},1200)</script></body></html>`;
|
|
22046
|
+
}
|
|
21648
22047
|
app.get("/schedule-status", auth2, async (c) => {
|
|
21649
22048
|
try {
|
|
21650
22049
|
const user = c.get("user");
|
|
@@ -21660,7 +22059,7 @@ app.get("/schedule-status", auth2, async (c) => {
|
|
|
21660
22059
|
});
|
|
21661
22060
|
app.get("/schedule-connection-catalog", auth2, async (c) => {
|
|
21662
22061
|
try {
|
|
21663
|
-
return c.json({ ok: true, catalog: await
|
|
22062
|
+
return c.json({ ok: true, catalog: await combinedConnectionCatalog() });
|
|
21664
22063
|
} catch (err) {
|
|
21665
22064
|
return scheduleConnectionError(c, err, "Unable to load the service connection catalog.");
|
|
21666
22065
|
}
|
|
@@ -21668,7 +22067,7 @@ app.get("/schedule-connection-catalog", auth2, async (c) => {
|
|
|
21668
22067
|
app.get("/schedule-connections", auth2, async (c) => {
|
|
21669
22068
|
try {
|
|
21670
22069
|
const user = c.get("user");
|
|
21671
|
-
return c.json({ ok: true, connections: await
|
|
22070
|
+
return c.json({ ok: true, connections: await combinedConnections(user.email) });
|
|
21672
22071
|
} catch (err) {
|
|
21673
22072
|
return scheduleConnectionError(c, err, "Unable to load service connections.");
|
|
21674
22073
|
}
|
|
@@ -21679,7 +22078,7 @@ app.post("/schedule-connections/session", auth2, async (c) => {
|
|
|
21679
22078
|
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
21680
22079
|
if (!providerConfigKey) return c.json({ ok: false, error: "providerConfigKey is required." }, 400);
|
|
21681
22080
|
try {
|
|
21682
|
-
const session = await createNangoConnectSession(user.email, providerConfigKey);
|
|
22081
|
+
const session = providerConfigKey === "resend" ? await createResendConnectSession(user.email, resendOAuthCallbackUrl()) : await createNangoConnectSession(user.email, providerConfigKey);
|
|
21683
22082
|
return c.json({ ok: true, ...session });
|
|
21684
22083
|
} catch (err) {
|
|
21685
22084
|
return scheduleConnectionError(c, err, "Unable to start the service connection flow.");
|
|
@@ -21687,24 +22086,65 @@ app.post("/schedule-connections/session", auth2, async (c) => {
|
|
|
21687
22086
|
});
|
|
21688
22087
|
app.post("/schedule-connections/:id/reconnect-session", auth2, async (c) => {
|
|
21689
22088
|
const user = c.get("user");
|
|
22089
|
+
const body = await c.req.json().catch(() => ({}));
|
|
22090
|
+
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
21690
22091
|
try {
|
|
21691
|
-
const session = await createNangoReconnectSession(user.email, c.req.param("id"));
|
|
22092
|
+
const session = await isResendConnection(user.email, c.req.param("id"), providerConfigKey) ? await createResendReconnectSession(user.email, c.req.param("id"), resendOAuthCallbackUrl()) : await createNangoReconnectSession(user.email, c.req.param("id"));
|
|
21692
22093
|
return c.json({ ok: true, ...session });
|
|
21693
22094
|
} catch (err) {
|
|
21694
22095
|
return scheduleConnectionError(c, err, "Unable to start the service reconnection flow.");
|
|
21695
22096
|
}
|
|
21696
22097
|
});
|
|
22098
|
+
app.delete("/schedule-connections/:id", auth2, async (c) => {
|
|
22099
|
+
const user = c.get("user");
|
|
22100
|
+
const body = await c.req.json().catch(() => ({}));
|
|
22101
|
+
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
22102
|
+
try {
|
|
22103
|
+
if (!await isResendConnection(user.email, c.req.param("id"), providerConfigKey)) {
|
|
22104
|
+
return c.json({ ok: false, error: "Disconnect is not available for this connection type yet." }, 409);
|
|
22105
|
+
}
|
|
22106
|
+
await deleteResendConnection(user.email, c.req.param("id"));
|
|
22107
|
+
return c.json({ ok: true });
|
|
22108
|
+
} catch (err) {
|
|
22109
|
+
return scheduleConnectionError(c, err, "Unable to disconnect this service connection.");
|
|
22110
|
+
}
|
|
22111
|
+
});
|
|
21697
22112
|
app.post("/schedule-connections/:id/enable-actions", auth2, async (c) => {
|
|
21698
22113
|
const user = c.get("user");
|
|
21699
22114
|
const body = await c.req.json().catch(() => ({}));
|
|
21700
22115
|
if (typeof body.enabled !== "boolean") return c.json({ ok: false, error: "enabled must be a boolean." }, 400);
|
|
22116
|
+
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
21701
22117
|
try {
|
|
21702
|
-
const actionsEnabled = await setScheduleConnectionActionsEnabled(user.email, c.req.param("id"), body.enabled);
|
|
22118
|
+
const actionsEnabled = await isResendConnection(user.email, c.req.param("id"), providerConfigKey) ? await setResendActionsEnabled(user.email, c.req.param("id"), body.enabled) : await setScheduleConnectionActionsEnabled(user.email, c.req.param("id"), body.enabled);
|
|
21703
22119
|
return c.json({ ok: true, actionsEnabled });
|
|
21704
22120
|
} catch (err) {
|
|
21705
22121
|
return scheduleConnectionError(c, err, "Unable to update this connection's action setting.");
|
|
21706
22122
|
}
|
|
21707
22123
|
});
|
|
22124
|
+
app.get("/oauth/resend/callback", async (c) => {
|
|
22125
|
+
const code = c.req.query("code")?.trim();
|
|
22126
|
+
const state = c.req.query("state")?.trim();
|
|
22127
|
+
const providerError = c.req.query("error")?.trim();
|
|
22128
|
+
c.header("cache-control", "no-store");
|
|
22129
|
+
c.header("content-security-policy", "default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'; base-uri 'none'; frame-ancestors 'none'");
|
|
22130
|
+
c.header("referrer-policy", "no-referrer");
|
|
22131
|
+
c.header("x-content-type-options", "nosniff");
|
|
22132
|
+
if (!state || state.length > 4e3 || !code && !providerError || (code?.length ?? 0) > 4e3 || (providerError?.length ?? 0) > 200) {
|
|
22133
|
+
return c.html(renderResendOAuthResult(false), 400);
|
|
22134
|
+
}
|
|
22135
|
+
try {
|
|
22136
|
+
await completeResendOAuthCallback({
|
|
22137
|
+
...code ? { code } : {},
|
|
22138
|
+
state,
|
|
22139
|
+
...providerError ? { error: providerError } : {},
|
|
22140
|
+
redirectUri: resendOAuthCallbackUrl()
|
|
22141
|
+
});
|
|
22142
|
+
return c.html(renderResendOAuthResult(!providerError));
|
|
22143
|
+
} catch (err) {
|
|
22144
|
+
console.warn("[resend-oauth-callback]", err instanceof Error ? err.name : "unknown_error");
|
|
22145
|
+
return c.html(renderResendOAuthResult(false), 502);
|
|
22146
|
+
}
|
|
22147
|
+
});
|
|
21708
22148
|
app.post("/schedule-connections/actions/slack/send-message", auth2, async (c) => {
|
|
21709
22149
|
const user = c.get("user");
|
|
21710
22150
|
const body = await c.req.json().catch(() => ({}));
|
|
@@ -21779,25 +22219,42 @@ app.post("/schedule-connections/actions/read", auth2, async (c) => {
|
|
|
21779
22219
|
const user = c.get("user");
|
|
21780
22220
|
const body = await c.req.json().catch(() => ({}));
|
|
21781
22221
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
22222
|
+
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
21782
22223
|
const tool = providerConfigKeyFrom(body.tool);
|
|
21783
22224
|
if (!connectionId || !tool) {
|
|
21784
22225
|
return c.json({ ok: false, error: "connectionId and tool are required." }, 400);
|
|
21785
22226
|
}
|
|
21786
22227
|
const args = body.args && typeof body.args === "object" && !Array.isArray(body.args) ? body.args : {};
|
|
21787
22228
|
try {
|
|
21788
|
-
const result = await callScheduleConnectionRead(user.email, connectionId, tool, args);
|
|
22229
|
+
const result = await isResendConnection(user.email, connectionId, providerConfigKey) ? await callResendRead(user.email, connectionId, tool, args) : await callScheduleConnectionRead(user.email, connectionId, tool, args);
|
|
21789
22230
|
return c.json({ ok: true, result });
|
|
21790
22231
|
} catch (err) {
|
|
21791
22232
|
return scheduleConnectionError(c, err, "Unable to read from this connection.");
|
|
21792
22233
|
}
|
|
21793
22234
|
});
|
|
22235
|
+
app.post("/schedule-connections/actions/describe", auth2, async (c) => {
|
|
22236
|
+
const user = c.get("user");
|
|
22237
|
+
const body = await c.req.json().catch(() => ({}));
|
|
22238
|
+
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
22239
|
+
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
22240
|
+
const tool = providerConfigKeyFrom(body.tool);
|
|
22241
|
+
if (!connectionId || !tool) return c.json({ ok: false, error: "connectionId and tool are required." }, 400);
|
|
22242
|
+
try {
|
|
22243
|
+
if (!await isResendConnection(user.email, connectionId, providerConfigKey)) {
|
|
22244
|
+
return c.json({ ok: false, error: "Typed tool descriptions are not available for this connection transport yet." }, 501);
|
|
22245
|
+
}
|
|
22246
|
+
return c.json({ ok: true, tool: await describeResendTool(user.email, connectionId, tool) });
|
|
22247
|
+
} catch (err) {
|
|
22248
|
+
return scheduleConnectionError(c, err, "Unable to describe this connection tool.");
|
|
22249
|
+
}
|
|
22250
|
+
});
|
|
21794
22251
|
app.post("/schedule-connections/actions/export", auth2, async (c) => {
|
|
21795
22252
|
const user = c.get("user");
|
|
21796
22253
|
const body = await c.req.json().catch(() => ({}));
|
|
21797
22254
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
21798
22255
|
if (!connectionId) return c.json({ ok: false, error: "connectionId is required." }, 400);
|
|
21799
22256
|
const requestedDataset = typeof body.dataset === "string" ? body.dataset.trim() : "auto";
|
|
21800
|
-
const datasets = [
|
|
22257
|
+
const datasets = [...CONNECTED_DATA_DATASETS];
|
|
21801
22258
|
if (!datasets.includes(requestedDataset)) {
|
|
21802
22259
|
return c.json({ ok: false, error: `dataset must be one of: ${datasets.join(", ")}.` }, 400);
|
|
21803
22260
|
}
|
|
@@ -21820,6 +22277,7 @@ app.post("/schedule-connections/actions/export", auth2, async (c) => {
|
|
|
21820
22277
|
return c.json({ ok: false, error: "continuation must be the complete object returned by a prior export." }, 400);
|
|
21821
22278
|
}
|
|
21822
22279
|
try {
|
|
22280
|
+
const useResend = await isResendConnection(user.email, connectionId);
|
|
21823
22281
|
const resolved = resolveConnectedDataExportRequest({
|
|
21824
22282
|
requestedDataset,
|
|
21825
22283
|
from: typeof body.from === "string" ? body.from : void 0,
|
|
@@ -21836,7 +22294,7 @@ app.post("/schedule-connections/actions/export", auth2, async (c) => {
|
|
|
21836
22294
|
maxItems,
|
|
21837
22295
|
forceArtifact: body.delivery === "artifact",
|
|
21838
22296
|
...resolved.cursor ? { cursor: resolved.cursor } : {},
|
|
21839
|
-
fetchPage: (input) => callScheduleConnectionExportPage(user.email, input),
|
|
22297
|
+
fetchPage: (input) => useResend ? callResendExportPage(user.email, input) : callScheduleConnectionExportPage(user.email, input),
|
|
21840
22298
|
writeArtifact: createConnectedDataArtifact
|
|
21841
22299
|
});
|
|
21842
22300
|
return c.json(result);
|
|
@@ -21871,12 +22329,13 @@ app.post("/schedule-connections/actions/call", auth2, async (c) => {
|
|
|
21871
22329
|
const user = c.get("user");
|
|
21872
22330
|
const body = await c.req.json().catch(() => ({}));
|
|
21873
22331
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
22332
|
+
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
21874
22333
|
const tool = providerConfigKeyFrom(body.tool);
|
|
21875
22334
|
if (!connectionId || !tool || !body.args || typeof body.args !== "object" || Array.isArray(body.args)) {
|
|
21876
22335
|
return c.json({ ok: false, error: "connectionId, tool, and an args object are required." }, 400);
|
|
21877
22336
|
}
|
|
21878
22337
|
try {
|
|
21879
|
-
const result = await callScheduleConnectionAction(
|
|
22338
|
+
const result = await isResendConnection(user.email, connectionId, providerConfigKey) ? await callResendAction(user.email, connectionId, tool, body.args) : await callScheduleConnectionAction(
|
|
21880
22339
|
user.email,
|
|
21881
22340
|
connectionId,
|
|
21882
22341
|
body.args,
|
|
@@ -23103,4 +23562,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
23103
23562
|
export {
|
|
23104
23563
|
app
|
|
23105
23564
|
};
|
|
23106
|
-
//# sourceMappingURL=server-
|
|
23565
|
+
//# sourceMappingURL=server-DDKXWYTO.js.map
|