@tangle-network/agent-integrations 0.53.47 → 0.53.49
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/catalog.d.ts +2 -2
- package/dist/catalog.js +9 -9
- package/dist/{chunk-DHF5EXLO.js → chunk-5UCHLQ3D.js} +9 -3
- package/dist/{chunk-DHF5EXLO.js.map → chunk-5UCHLQ3D.js.map} +1 -1
- package/dist/{chunk-C7SE5X44.js → chunk-GUZA3U6T.js} +383 -68
- package/dist/chunk-GUZA3U6T.js.map +1 -0
- package/dist/{chunk-AGXTCR34.js → chunk-H5UCSRF4.js} +2682 -259
- package/dist/{chunk-AGXTCR34.js.map → chunk-H5UCSRF4.js.map} +1 -1
- package/dist/{chunk-TP4MD4PD.js → chunk-KBYYTHXQ.js} +2 -2
- package/dist/{chunk-AG4ORH2A.js → chunk-TKEVCGAI.js} +6 -6
- package/dist/chunk-TKEVCGAI.js.map +1 -0
- package/dist/{chunk-JR2RWYQO.js → chunk-UI3U62H6.js} +2 -2
- package/dist/{chunk-WE7SQ7PB.js → chunk-W72KPXXX.js} +23 -3
- package/dist/chunk-W72KPXXX.js.map +1 -0
- package/dist/{chunk-U36WHHML.js → chunk-ZSXRS7D7.js} +251 -10
- package/dist/chunk-ZSXRS7D7.js.map +1 -0
- package/dist/{chunk-EKSAOR2I.js → chunk-ZZA4HOBE.js} +2 -2
- package/dist/connect/index.d.ts +2 -2
- package/dist/connect/index.js +2 -2
- package/dist/connectors/adapters/index.d.ts +58 -19
- package/dist/connectors/adapters/index.js +18 -2
- package/dist/connectors/index.d.ts +45 -12
- package/dist/connectors/index.js +21 -3
- package/dist/{consumer-UnsjK9iM.d.ts → consumer-DrLnbqYt.d.ts} +1 -1
- package/dist/consumer.d.ts +3 -3
- package/dist/consumer.js +2 -2
- package/dist/{core-types-Cx53j2Xp.d.ts → core-types-D26cY5tD.d.ts} +7 -1
- package/dist/coverage-catalog.d.ts +2 -2
- package/dist/coverage-catalog.js +1 -1
- package/dist/{importers-YLXwPCz_.d.ts → importers-CQKts3pm.d.ts} +1 -1
- package/dist/index.d.ts +13 -12
- package/dist/index.js +27 -9
- package/dist/mcp.d.ts +3 -3
- package/dist/mcp.js +9 -9
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.js +2 -2
- package/dist/registry.d.ts +2 -2
- package/dist/registry.js +9 -9
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +9 -9
- package/dist/specs.d.ts +11 -3
- package/dist/specs.js +5 -5
- package/dist/{tangle-id--7mgjNkq.d.ts → tangle-id-BCOVbWrP.d.ts} +1 -1
- package/dist/{types-qFsboS2G.d.ts → types-DpKn0frG.d.ts} +29 -10
- package/docs/integration-execution-audit.md +17 -11
- package/docs/integration-execution-matrix.json +837 -304
- package/package.json +1 -1
- package/dist/chunk-AG4ORH2A.js.map +0 -1
- package/dist/chunk-C7SE5X44.js.map +0 -1
- package/dist/chunk-U36WHHML.js.map +0 -1
- package/dist/chunk-WE7SQ7PB.js.map +0 -1
- /package/dist/{chunk-TP4MD4PD.js.map → chunk-KBYYTHXQ.js.map} +0 -0
- /package/dist/{chunk-JR2RWYQO.js.map → chunk-UI3U62H6.js.map} +0 -0
- /package/dist/{chunk-EKSAOR2I.js.map → chunk-ZZA4HOBE.js.map} +0 -0
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
TangleIdentityUnreachableError,
|
|
15
15
|
createTangleIdentityClient,
|
|
16
16
|
tangleIdentity
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-W72KPXXX.js";
|
|
18
18
|
import {
|
|
19
19
|
__export
|
|
20
20
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -50,7 +50,9 @@ __export(adapters_exports, {
|
|
|
50
50
|
altTextAiConnector: () => altTextAiConnector,
|
|
51
51
|
alttextifyConnector: () => alttextifyConnector,
|
|
52
52
|
amazonBedrockConnector: () => amazonBedrockConnector,
|
|
53
|
+
amazonCloudWatchConnector: () => amazonCloudWatchConnector,
|
|
53
54
|
amazonEventBridgeConnector: () => amazonEventBridgeConnector,
|
|
55
|
+
amazonLambdaConnector: () => amazonLambdaConnector,
|
|
54
56
|
amazonS3Connector: () => amazonS3Connector,
|
|
55
57
|
amazonSecretsManagerConnector: () => amazonSecretsManagerConnector,
|
|
56
58
|
amazonSesConnector: () => amazonSesConnector,
|
|
@@ -60,6 +62,7 @@ __export(adapters_exports, {
|
|
|
60
62
|
aminosConnector: () => aminosConnector,
|
|
61
63
|
ampecoConnector: () => ampecoConnector,
|
|
62
64
|
amplemarketConnector: () => amplemarketConnector,
|
|
65
|
+
amplitudeConnector: () => amplitudeConnector,
|
|
63
66
|
anthropicConnector: () => anthropicConnector,
|
|
64
67
|
anyhookWebsocketConnector: () => anyhookWebsocketConnector,
|
|
65
68
|
apifyConnector: () => apifyConnector,
|
|
@@ -118,6 +121,7 @@ __export(adapters_exports, {
|
|
|
118
121
|
browseAiConnector: () => browseAiConnector,
|
|
119
122
|
builtwithConnector: () => builtwithConnector,
|
|
120
123
|
buttondownConnector: () => buttondownConnector,
|
|
124
|
+
calCom: () => calCom,
|
|
121
125
|
calComConnector: () => calComConnector,
|
|
122
126
|
calendlyConnector: () => calendlyConnector,
|
|
123
127
|
cambAiConnector: () => cambAiConnector,
|
|
@@ -161,6 +165,7 @@ __export(adapters_exports, {
|
|
|
161
165
|
clockodoConnector: () => clockodoConnector,
|
|
162
166
|
closeConnector: () => closeConnector,
|
|
163
167
|
cloudconvertConnector: () => cloudconvertConnector,
|
|
168
|
+
cloudflareConnector: () => cloudflareConnector,
|
|
164
169
|
cloudinaryConnector: () => cloudinaryConnector,
|
|
165
170
|
cloutlyConnector: () => cloutlyConnector,
|
|
166
171
|
codaConnector: () => codaConnector,
|
|
@@ -525,6 +530,7 @@ __export(adapters_exports, {
|
|
|
525
530
|
reachinboxConnector: () => reachinboxConnector,
|
|
526
531
|
recallAiConnector: () => recallAiConnector,
|
|
527
532
|
recurlyConnector: () => recurlyConnector,
|
|
533
|
+
reddit: () => reddit,
|
|
528
534
|
redditConnector: () => redditConnector,
|
|
529
535
|
redisConnector: () => redisConnector,
|
|
530
536
|
redshiftConnector: () => redshiftConnector,
|
|
@@ -604,6 +610,8 @@ __export(adapters_exports, {
|
|
|
604
610
|
textcortexAiConnector: () => textcortexAiConnector,
|
|
605
611
|
theirstackConnector: () => theirstackConnector,
|
|
606
612
|
ticktickConnector: () => ticktickConnector,
|
|
613
|
+
tiktok: () => tiktok,
|
|
614
|
+
tiktokConnector: () => tiktokConnector,
|
|
607
615
|
timeOpsConnector: () => timeOpsConnector,
|
|
608
616
|
timelinesAiConnector: () => timelinesAiConnector,
|
|
609
617
|
tlDvConnector: () => tlDvConnector,
|
|
@@ -747,8 +755,8 @@ function signSigV4(input) {
|
|
|
747
755
|
const authorization = `${ALGORITHM} Credential=${accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
|
|
748
756
|
return { amzDate, signedHeaders, canonicalRequest, stringToSign, signature, authorization };
|
|
749
757
|
}
|
|
750
|
-
function amzDateNow(
|
|
751
|
-
return
|
|
758
|
+
function amzDateNow(date2 = /* @__PURE__ */ new Date()) {
|
|
759
|
+
return date2.toISOString().replace(/[:-]|\.\d{3}/g, "");
|
|
752
760
|
}
|
|
753
761
|
function hashSha256Hex(data4) {
|
|
754
762
|
return createHash("sha256").update(data4, "utf8").digest("hex");
|
|
@@ -957,7 +965,7 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
957
965
|
const headers = {
|
|
958
966
|
accept: "application/json",
|
|
959
967
|
...renderHeaders(spec.defaultHeaders ?? {}, scope, true),
|
|
960
|
-
...renderHeaders(renderableHeaders, scope)
|
|
968
|
+
...renderHeaders(renderableHeaders, scope, false, requiredArgs)
|
|
961
969
|
};
|
|
962
970
|
const structuredCredentials = placement.kind === "structured-headers" || placement.kind === "structured-json-body" ? readStructuredCredentials(inv.source.credentials, placement.fields) : placement.kind === "basic-structured" ? readStructuredCredentials(inv.source.credentials, {
|
|
963
971
|
[placement.usernameField]: placement.usernameField,
|
|
@@ -971,8 +979,9 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
971
979
|
if (hostOverride) url.host = hostOverride.replace(/\{region\}/g, awsRegion);
|
|
972
980
|
if (inv.expectedEtag) headers["if-match"] = inv.expectedEtag;
|
|
973
981
|
const sendsBody = request4.method !== "GET" && (request4.method !== "DELETE" || request4.body !== void 0);
|
|
982
|
+
const bodyEncoding = request4.bodyEncoding ?? "json";
|
|
974
983
|
if (sendsBody && getHeaderCI(headers, "content-type") === void 0) {
|
|
975
|
-
headers["content-type"] = "application/json";
|
|
984
|
+
headers["content-type"] = bodyEncoding === "form" ? "application/x-www-form-urlencoded" : "application/json";
|
|
976
985
|
}
|
|
977
986
|
let resolvedBody = sendsBody ? resolveBody(request4.body, inv.args, scope, requiredArgs) : void 0;
|
|
978
987
|
if (placement.kind === "structured-json-body") {
|
|
@@ -989,7 +998,7 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
989
998
|
)
|
|
990
999
|
};
|
|
991
1000
|
}
|
|
992
|
-
const bodyString = sendsBody ?
|
|
1001
|
+
const bodyString = sendsBody ? serializeRequestBody(spec.kind, bodyEncoding, resolvedBody) : void 0;
|
|
993
1002
|
if (placement.kind === "aws-sigv4") {
|
|
994
1003
|
signAwsRequest(headers, url, {
|
|
995
1004
|
method: request4.method,
|
|
@@ -1011,7 +1020,8 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
1011
1020
|
body: bodyString,
|
|
1012
1021
|
signal: AbortSignal.timeout(2e4)
|
|
1013
1022
|
});
|
|
1014
|
-
|
|
1023
|
+
const credentialsExpiredStatuses = spec.credentialsExpiredStatuses ?? [401, 403];
|
|
1024
|
+
if (credentialsExpiredStatuses.includes(res.status)) {
|
|
1015
1025
|
throw new CredentialsExpired(`${spec.displayName} rejected credentials (${res.status})`, inv.source.id);
|
|
1016
1026
|
}
|
|
1017
1027
|
if (res.status === 409 || res.status === 412) {
|
|
@@ -1064,6 +1074,21 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
1064
1074
|
}
|
|
1065
1075
|
return { data: data4, etag: res.headers.get("etag") ?? void 0 };
|
|
1066
1076
|
}
|
|
1077
|
+
function serializeRequestBody(connectorKind, encoding, body) {
|
|
1078
|
+
if (encoding === "json") return JSON.stringify(body);
|
|
1079
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
1080
|
+
throw new Error(`${connectorKind}: form request bodies require a flat object`);
|
|
1081
|
+
}
|
|
1082
|
+
const form2 = new URLSearchParams();
|
|
1083
|
+
for (const [key, value] of Object.entries(body)) {
|
|
1084
|
+
if (value === void 0 || value === null) continue;
|
|
1085
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
|
|
1086
|
+
throw new Error(`${connectorKind}: form field ${key} must be a scalar value`);
|
|
1087
|
+
}
|
|
1088
|
+
form2.set(key, String(value));
|
|
1089
|
+
}
|
|
1090
|
+
return form2.toString();
|
|
1091
|
+
}
|
|
1067
1092
|
function resolveBaseUrl(baseUrl4, metadata, allowedBaseUrls, allowedBaseUrlSuffixes, requirePublicHttpsBaseUrl) {
|
|
1068
1093
|
let resolved;
|
|
1069
1094
|
if (typeof baseUrl4 === "string") {
|
|
@@ -1188,7 +1213,12 @@ function credentialToken(credentials) {
|
|
|
1188
1213
|
}
|
|
1189
1214
|
function redactCredentialText(text, credentials, additionalSecrets = []) {
|
|
1190
1215
|
const candidates = credentials.kind === "oauth2" ? [credentials.accessToken, credentials.refreshToken] : credentials.kind === "api-key" ? [credentials.apiKey, ...jsonStringValues(credentials.apiKey)] : credentials.kind === "custom" ? Object.values(credentials.values) : [];
|
|
1191
|
-
const
|
|
1216
|
+
const authorizationSecrets = additionalSecrets.flatMap((secret) => {
|
|
1217
|
+
if (typeof secret !== "string") return [];
|
|
1218
|
+
const credential2 = secret.match(/^(?:Basic|Bearer)\s+(.+)$/i)?.[1];
|
|
1219
|
+
return credential2 ? [secret, credential2] : [secret];
|
|
1220
|
+
});
|
|
1221
|
+
const secrets = [...candidates, ...authorizationSecrets].filter(
|
|
1192
1222
|
(secret) => typeof secret === "string" && secret.length > 0
|
|
1193
1223
|
);
|
|
1194
1224
|
return secrets.reduce(
|
|
@@ -1270,12 +1300,24 @@ function retryAfterMsFromHeader(raw) {
|
|
|
1270
1300
|
function renderScope(inv, credentialDefaults) {
|
|
1271
1301
|
return { ...credentialDefaults, ...inv.args, connection: inv.source.metadata };
|
|
1272
1302
|
}
|
|
1273
|
-
function renderHeaders(headers, args, rawExact = false) {
|
|
1274
|
-
|
|
1303
|
+
function renderHeaders(headers, args, rawExact = false, requiredArgs) {
|
|
1304
|
+
const out = {};
|
|
1305
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1275
1306
|
const exact = value.match(/^\{([a-zA-Z0-9_.-]+)\}$/);
|
|
1276
|
-
if (
|
|
1277
|
-
|
|
1278
|
-
|
|
1307
|
+
if (exact) {
|
|
1308
|
+
const resolved = readPath(args, exact[1]);
|
|
1309
|
+
if (resolved === void 0 || resolved === null) {
|
|
1310
|
+
if (rawExact || requiredArgs?.includes(exact[1])) {
|
|
1311
|
+
throw new Error(`missing required argument: ${exact[1]}`);
|
|
1312
|
+
}
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
out[key] = rawExact ? String(resolved) : encodeURIComponent(String(resolved));
|
|
1316
|
+
continue;
|
|
1317
|
+
}
|
|
1318
|
+
out[key] = interpolate(value, args);
|
|
1319
|
+
}
|
|
1320
|
+
return out;
|
|
1279
1321
|
}
|
|
1280
1322
|
function renderObject(input, args, requiredArgs) {
|
|
1281
1323
|
const out = {};
|
|
@@ -16106,40 +16148,228 @@ var pushbulletConnector = declarativeRestConnector({
|
|
|
16106
16148
|
]
|
|
16107
16149
|
});
|
|
16108
16150
|
|
|
16151
|
+
// src/connectors/oauth.ts
|
|
16152
|
+
import { createHash as createHash3, randomBytes } from "crypto";
|
|
16153
|
+
var PENDING_TTL_MS = 10 * 60 * 1e3;
|
|
16154
|
+
var InMemoryOAuthFlowStore = class {
|
|
16155
|
+
pendingFlows = /* @__PURE__ */ new Map();
|
|
16156
|
+
put(state, flow) {
|
|
16157
|
+
this.pendingFlows.set(state, flow);
|
|
16158
|
+
}
|
|
16159
|
+
consume(state) {
|
|
16160
|
+
const flow = this.pendingFlows.get(state);
|
|
16161
|
+
this.pendingFlows.delete(state);
|
|
16162
|
+
if (!flow || flow.expiresAt <= Date.now()) return void 0;
|
|
16163
|
+
return flow;
|
|
16164
|
+
}
|
|
16165
|
+
sweep(now) {
|
|
16166
|
+
for (const [k, v] of this.pendingFlows) {
|
|
16167
|
+
if (v.expiresAt <= now) this.pendingFlows.delete(k);
|
|
16168
|
+
}
|
|
16169
|
+
}
|
|
16170
|
+
clear() {
|
|
16171
|
+
this.pendingFlows.clear();
|
|
16172
|
+
}
|
|
16173
|
+
};
|
|
16174
|
+
var defaultFlowStore = new InMemoryOAuthFlowStore();
|
|
16175
|
+
function startOAuthFlow(input) {
|
|
16176
|
+
const store = input.store ?? defaultFlowStore;
|
|
16177
|
+
const now = input.now ?? Date.now();
|
|
16178
|
+
store.sweep?.(now);
|
|
16179
|
+
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
16180
|
+
const codeVerifier = usePkce ? base64Url(randomBytes(48)) : void 0;
|
|
16181
|
+
const codeChallenge = codeVerifier ? base64Url(createHash3("sha256").update(codeVerifier).digest()) : void 0;
|
|
16182
|
+
const state = base64Url(randomBytes(24));
|
|
16183
|
+
store.put(state, {
|
|
16184
|
+
codeVerifier,
|
|
16185
|
+
state,
|
|
16186
|
+
projectId: input.projectId,
|
|
16187
|
+
kind: input.kind,
|
|
16188
|
+
label: input.label,
|
|
16189
|
+
redirectUri: input.redirectUri,
|
|
16190
|
+
expiresAt: now + PENDING_TTL_MS
|
|
16191
|
+
});
|
|
16192
|
+
const url = new URL(input.authorizationUrl);
|
|
16193
|
+
url.searchParams.set("response_type", "code");
|
|
16194
|
+
url.searchParams.set(
|
|
16195
|
+
oauthParameterName(input.authorizationClientIdParam, "client_id"),
|
|
16196
|
+
input.clientId
|
|
16197
|
+
);
|
|
16198
|
+
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
16199
|
+
url.searchParams.set("scope", input.scopes.join(input.scopeSeparator ?? " "));
|
|
16200
|
+
url.searchParams.set("state", state);
|
|
16201
|
+
if (input.extraAuthParams) {
|
|
16202
|
+
for (const [k, v] of Object.entries(input.extraAuthParams)) {
|
|
16203
|
+
url.searchParams.set(k, v);
|
|
16204
|
+
}
|
|
16205
|
+
}
|
|
16206
|
+
if (codeChallenge) {
|
|
16207
|
+
url.searchParams.set("code_challenge", codeChallenge);
|
|
16208
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
16209
|
+
} else {
|
|
16210
|
+
url.searchParams.delete("code_challenge");
|
|
16211
|
+
url.searchParams.delete("code_challenge_method");
|
|
16212
|
+
}
|
|
16213
|
+
return { authorizationUrl: url.toString(), state };
|
|
16214
|
+
}
|
|
16215
|
+
async function consumePendingFlow(state, store = defaultFlowStore) {
|
|
16216
|
+
await store.sweep?.(Date.now());
|
|
16217
|
+
const flow = await store.consume(state);
|
|
16218
|
+
if (!flow) {
|
|
16219
|
+
throw new Error("Unknown or expired OAuth state: possible CSRF, replay, or stale flow");
|
|
16220
|
+
}
|
|
16221
|
+
return flow;
|
|
16222
|
+
}
|
|
16223
|
+
async function exchangeAuthorizationCode(input) {
|
|
16224
|
+
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
16225
|
+
if (usePkce && !input.codeVerifier) {
|
|
16226
|
+
throw new Error("OAuth token exchange requires a PKCE code_verifier");
|
|
16227
|
+
}
|
|
16228
|
+
const body = new URLSearchParams({
|
|
16229
|
+
grant_type: "authorization_code",
|
|
16230
|
+
code: input.code,
|
|
16231
|
+
redirect_uri: input.redirectUri
|
|
16232
|
+
});
|
|
16233
|
+
if (usePkce) body.set("code_verifier", input.codeVerifier);
|
|
16234
|
+
const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
|
|
16235
|
+
applyTokenClientAuthentication(input, body, headers);
|
|
16236
|
+
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
16237
|
+
method: "POST",
|
|
16238
|
+
headers,
|
|
16239
|
+
body,
|
|
16240
|
+
signal: input.signal
|
|
16241
|
+
});
|
|
16242
|
+
if (!res.ok) {
|
|
16243
|
+
const text = await res.text().catch(() => "");
|
|
16244
|
+
throw new Error(`OAuth token exchange failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
16245
|
+
}
|
|
16246
|
+
const json = await res.json();
|
|
16247
|
+
return {
|
|
16248
|
+
accessToken: json.access_token,
|
|
16249
|
+
refreshToken: json.refresh_token,
|
|
16250
|
+
expiresIn: json.expires_in,
|
|
16251
|
+
scope: json.scope,
|
|
16252
|
+
tokenType: json.token_type,
|
|
16253
|
+
idToken: json.id_token
|
|
16254
|
+
};
|
|
16255
|
+
}
|
|
16256
|
+
async function refreshAccessToken(input) {
|
|
16257
|
+
const body = new URLSearchParams({
|
|
16258
|
+
grant_type: "refresh_token",
|
|
16259
|
+
refresh_token: input.refreshToken
|
|
16260
|
+
});
|
|
16261
|
+
const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
|
|
16262
|
+
applyTokenClientAuthentication(input, body, headers);
|
|
16263
|
+
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
16264
|
+
method: "POST",
|
|
16265
|
+
headers,
|
|
16266
|
+
body,
|
|
16267
|
+
signal: input.signal
|
|
16268
|
+
});
|
|
16269
|
+
if (!res.ok) {
|
|
16270
|
+
const text = await res.text().catch(() => "");
|
|
16271
|
+
throw new Error(`OAuth refresh failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
16272
|
+
}
|
|
16273
|
+
const json = await res.json();
|
|
16274
|
+
return {
|
|
16275
|
+
accessToken: json.access_token,
|
|
16276
|
+
// Some providers omit refresh_token on refresh — keep the previous one
|
|
16277
|
+
// in that case (caller passes through if undefined).
|
|
16278
|
+
refreshToken: json.refresh_token,
|
|
16279
|
+
expiresIn: json.expires_in,
|
|
16280
|
+
scope: json.scope,
|
|
16281
|
+
tokenType: json.token_type,
|
|
16282
|
+
idToken: json.id_token
|
|
16283
|
+
};
|
|
16284
|
+
}
|
|
16285
|
+
function createOAuthTokenRequestHeaders(additional) {
|
|
16286
|
+
const headers = new Headers(additional);
|
|
16287
|
+
headers.set("content-type", "application/x-www-form-urlencoded");
|
|
16288
|
+
headers.set("accept", "application/json");
|
|
16289
|
+
headers.delete("authorization");
|
|
16290
|
+
return Object.fromEntries(headers.entries());
|
|
16291
|
+
}
|
|
16292
|
+
function applyTokenClientAuthentication(input, body, headers) {
|
|
16293
|
+
const method = input.tokenClientAuthMethod ?? "client_secret_post";
|
|
16294
|
+
if (method === "none") {
|
|
16295
|
+
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
16296
|
+
return;
|
|
16297
|
+
}
|
|
16298
|
+
if (!input.clientSecret) {
|
|
16299
|
+
throw new Error(`OAuth ${method} client authentication requires a client secret`);
|
|
16300
|
+
}
|
|
16301
|
+
if (method === "client_secret_post") {
|
|
16302
|
+
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
16303
|
+
body.set(
|
|
16304
|
+
oauthParameterName(input.tokenClientSecretParam, "client_secret"),
|
|
16305
|
+
input.clientSecret
|
|
16306
|
+
);
|
|
16307
|
+
return;
|
|
16308
|
+
}
|
|
16309
|
+
if (method === "client_secret_basic") {
|
|
16310
|
+
headers.authorization = `Basic ${Buffer.from(
|
|
16311
|
+
`${input.clientId}:${input.clientSecret}`,
|
|
16312
|
+
"utf8"
|
|
16313
|
+
).toString("base64")}`;
|
|
16314
|
+
return;
|
|
16315
|
+
}
|
|
16316
|
+
throw new Error("Unsupported OAuth token client authentication method");
|
|
16317
|
+
}
|
|
16318
|
+
function base64Url(buf) {
|
|
16319
|
+
return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
16320
|
+
}
|
|
16321
|
+
function oauthParameterName(value, fallback) {
|
|
16322
|
+
const name = value ?? fallback;
|
|
16323
|
+
if (!/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name)) {
|
|
16324
|
+
throw new Error("Invalid OAuth parameter name");
|
|
16325
|
+
}
|
|
16326
|
+
return name;
|
|
16327
|
+
}
|
|
16328
|
+
function _resetPendingFlowsForTests() {
|
|
16329
|
+
defaultFlowStore.clear?.();
|
|
16330
|
+
}
|
|
16331
|
+
|
|
16109
16332
|
// src/connectors/adapters/reddit.ts
|
|
16110
|
-
var
|
|
16333
|
+
var REDDIT_USER_AGENT = "web:tools.tangle.integration-hub:v1.0 (contact: https://tangle.tools)";
|
|
16334
|
+
var REDDIT_TOKEN_URL = "https://www.reddit.com/api/v1/access_token";
|
|
16335
|
+
var redditSpec = {
|
|
16111
16336
|
kind: "reddit",
|
|
16112
16337
|
displayName: "Reddit",
|
|
16113
16338
|
description: "Interact with Reddit \u2014 fetch and submit posts, retrieve comments, create and edit posts/comments.",
|
|
16114
16339
|
auth: {
|
|
16115
16340
|
kind: "oauth2",
|
|
16116
16341
|
authorizationUrl: "https://www.reddit.com/api/v1/authorize",
|
|
16117
|
-
tokenUrl:
|
|
16118
|
-
scopes: ["read", "submit", "edit"],
|
|
16342
|
+
tokenUrl: REDDIT_TOKEN_URL,
|
|
16343
|
+
scopes: ["identity", "read", "submit", "edit"],
|
|
16344
|
+
pkce: "unsupported",
|
|
16345
|
+
tokenClientAuthMethod: "client_secret_basic",
|
|
16346
|
+
extraAuthParams: { duration: "permanent" },
|
|
16347
|
+
tokenRequestHeaders: { "User-Agent": REDDIT_USER_AGENT },
|
|
16119
16348
|
clientIdEnv: "REDDIT_OAUTH_CLIENT_ID",
|
|
16120
16349
|
clientSecretEnv: "REDDIT_OAUTH_CLIENT_SECRET"
|
|
16121
16350
|
},
|
|
16122
16351
|
category: "comms",
|
|
16123
16352
|
defaultConsistencyModel: "authoritative",
|
|
16124
16353
|
baseUrl: "https://oauth.reddit.com",
|
|
16354
|
+
defaultHeaders: { "User-Agent": REDDIT_USER_AGENT },
|
|
16125
16355
|
test: { method: "GET", path: "/api/v1/me" },
|
|
16126
16356
|
capabilities: [
|
|
16127
16357
|
{
|
|
16128
16358
|
name: "post.retrieve",
|
|
16129
16359
|
class: "read",
|
|
16130
|
-
description: "Retrieve a Reddit post by its
|
|
16360
|
+
description: "Retrieve a Reddit post by its fullname, such as t3_abc123.",
|
|
16131
16361
|
parameters: {
|
|
16132
16362
|
type: "object",
|
|
16133
16363
|
properties: {
|
|
16134
|
-
postId: { type: "string" }
|
|
16364
|
+
postId: { type: "string", description: "Reddit post fullname, such as t3_abc123." }
|
|
16135
16365
|
},
|
|
16136
16366
|
required: ["postId"]
|
|
16137
16367
|
},
|
|
16138
16368
|
request: {
|
|
16139
16369
|
method: "GET",
|
|
16140
|
-
path: "/
|
|
16141
|
-
|
|
16142
|
-
|
|
16370
|
+
path: "/api/info",
|
|
16371
|
+
query: {
|
|
16372
|
+
id: "{postId}"
|
|
16143
16373
|
}
|
|
16144
16374
|
},
|
|
16145
16375
|
requiredScopes: ["read"]
|
|
@@ -16158,10 +16388,7 @@ var redditConnector = declarativeRestConnector({
|
|
|
16158
16388
|
},
|
|
16159
16389
|
request: {
|
|
16160
16390
|
method: "GET",
|
|
16161
|
-
path: "/r/{subreddit}/comments/{postId}"
|
|
16162
|
-
headers: {
|
|
16163
|
-
"User-Agent": "AgentDev/1.0"
|
|
16164
|
-
}
|
|
16391
|
+
path: "/r/{subreddit}/comments/{postId}"
|
|
16165
16392
|
},
|
|
16166
16393
|
requiredScopes: ["read"]
|
|
16167
16394
|
},
|
|
@@ -16174,27 +16401,28 @@ var redditConnector = declarativeRestConnector({
|
|
|
16174
16401
|
properties: {
|
|
16175
16402
|
subreddit: { type: "string" },
|
|
16176
16403
|
title: { type: "string" },
|
|
16404
|
+
kind: { type: "string", enum: ["self", "link"] },
|
|
16177
16405
|
text: { type: "string" },
|
|
16178
16406
|
url: { type: "string" },
|
|
16179
16407
|
flair_id: { type: "string" }
|
|
16180
16408
|
},
|
|
16181
|
-
required: ["subreddit", "title"]
|
|
16409
|
+
required: ["subreddit", "title", "kind"]
|
|
16182
16410
|
},
|
|
16183
16411
|
request: {
|
|
16184
16412
|
method: "POST",
|
|
16185
|
-
path: "/
|
|
16413
|
+
path: "/api/submit",
|
|
16414
|
+
bodyEncoding: "form",
|
|
16186
16415
|
body: {
|
|
16416
|
+
api_type: "json",
|
|
16417
|
+
sr: "{subreddit}",
|
|
16187
16418
|
title: "{title}",
|
|
16419
|
+
kind: "{kind}",
|
|
16188
16420
|
text: "{text}",
|
|
16189
16421
|
url: "{url}",
|
|
16190
|
-
flair_id: "{flair_id}"
|
|
16191
|
-
kind: "self"
|
|
16192
|
-
},
|
|
16193
|
-
headers: {
|
|
16194
|
-
"User-Agent": "AgentDev/1.0"
|
|
16422
|
+
flair_id: "{flair_id}"
|
|
16195
16423
|
}
|
|
16196
16424
|
},
|
|
16197
|
-
cas: "
|
|
16425
|
+
cas: "none",
|
|
16198
16426
|
externalEffect: true,
|
|
16199
16427
|
requiredScopes: ["submit"]
|
|
16200
16428
|
},
|
|
@@ -16213,15 +16441,14 @@ var redditConnector = declarativeRestConnector({
|
|
|
16213
16441
|
request: {
|
|
16214
16442
|
method: "POST",
|
|
16215
16443
|
path: "/api/comment",
|
|
16444
|
+
bodyEncoding: "form",
|
|
16216
16445
|
body: {
|
|
16446
|
+
api_type: "json",
|
|
16217
16447
|
thing_id: "{parentId}",
|
|
16218
16448
|
text: "{text}"
|
|
16219
|
-
},
|
|
16220
|
-
headers: {
|
|
16221
|
-
"User-Agent": "AgentDev/1.0"
|
|
16222
16449
|
}
|
|
16223
16450
|
},
|
|
16224
|
-
cas: "
|
|
16451
|
+
cas: "none",
|
|
16225
16452
|
externalEffect: true,
|
|
16226
16453
|
requiredScopes: ["submit"]
|
|
16227
16454
|
},
|
|
@@ -16245,9 +16472,6 @@ var redditConnector = declarativeRestConnector({
|
|
|
16245
16472
|
query: {
|
|
16246
16473
|
sort: "{sort}",
|
|
16247
16474
|
limit: "{limit}"
|
|
16248
|
-
},
|
|
16249
|
-
headers: {
|
|
16250
|
-
"User-Agent": "AgentDev/1.0"
|
|
16251
16475
|
}
|
|
16252
16476
|
},
|
|
16253
16477
|
requiredScopes: ["read"]
|
|
@@ -16267,15 +16491,15 @@ var redditConnector = declarativeRestConnector({
|
|
|
16267
16491
|
request: {
|
|
16268
16492
|
method: "POST",
|
|
16269
16493
|
path: "/api/editusertext",
|
|
16494
|
+
bodyEncoding: "form",
|
|
16270
16495
|
body: {
|
|
16496
|
+
api_type: "json",
|
|
16271
16497
|
thing_id: "{thingId}",
|
|
16272
16498
|
text: "{text}"
|
|
16273
|
-
},
|
|
16274
|
-
headers: {
|
|
16275
|
-
"User-Agent": "AgentDev/1.0"
|
|
16276
16499
|
}
|
|
16277
16500
|
},
|
|
16278
|
-
cas: "
|
|
16501
|
+
cas: "none",
|
|
16502
|
+
externalEffect: true,
|
|
16279
16503
|
requiredScopes: ["edit"]
|
|
16280
16504
|
},
|
|
16281
16505
|
{
|
|
@@ -16293,15 +16517,15 @@ var redditConnector = declarativeRestConnector({
|
|
|
16293
16517
|
request: {
|
|
16294
16518
|
method: "POST",
|
|
16295
16519
|
path: "/api/editusertext",
|
|
16520
|
+
bodyEncoding: "form",
|
|
16296
16521
|
body: {
|
|
16522
|
+
api_type: "json",
|
|
16297
16523
|
thing_id: "{thingId}",
|
|
16298
16524
|
text: "{text}"
|
|
16299
|
-
},
|
|
16300
|
-
headers: {
|
|
16301
|
-
"User-Agent": "AgentDev/1.0"
|
|
16302
16525
|
}
|
|
16303
16526
|
},
|
|
16304
|
-
cas: "
|
|
16527
|
+
cas: "none",
|
|
16528
|
+
externalEffect: true,
|
|
16305
16529
|
requiredScopes: ["edit"]
|
|
16306
16530
|
},
|
|
16307
16531
|
{
|
|
@@ -16318,13 +16542,12 @@ var redditConnector = declarativeRestConnector({
|
|
|
16318
16542
|
request: {
|
|
16319
16543
|
method: "POST",
|
|
16320
16544
|
path: "/api/del",
|
|
16545
|
+
bodyEncoding: "form",
|
|
16321
16546
|
body: {
|
|
16322
16547
|
id: "{thingId}"
|
|
16323
|
-
},
|
|
16324
|
-
headers: {
|
|
16325
|
-
"User-Agent": "AgentDev/1.0"
|
|
16326
16548
|
}
|
|
16327
16549
|
},
|
|
16550
|
+
cas: "none",
|
|
16328
16551
|
externalEffect: true,
|
|
16329
16552
|
requiredScopes: ["edit"]
|
|
16330
16553
|
},
|
|
@@ -16342,18 +16565,150 @@ var redditConnector = declarativeRestConnector({
|
|
|
16342
16565
|
request: {
|
|
16343
16566
|
method: "POST",
|
|
16344
16567
|
path: "/api/del",
|
|
16568
|
+
bodyEncoding: "form",
|
|
16345
16569
|
body: {
|
|
16346
16570
|
id: "{thingId}"
|
|
16347
|
-
},
|
|
16348
|
-
headers: {
|
|
16349
|
-
"User-Agent": "AgentDev/1.0"
|
|
16350
16571
|
}
|
|
16351
16572
|
},
|
|
16573
|
+
cas: "none",
|
|
16352
16574
|
externalEffect: true,
|
|
16353
16575
|
requiredScopes: ["edit"]
|
|
16354
16576
|
}
|
|
16355
16577
|
]
|
|
16356
|
-
}
|
|
16578
|
+
};
|
|
16579
|
+
var redditConnector = declarativeRestConnector(redditSpec);
|
|
16580
|
+
function reddit(options) {
|
|
16581
|
+
const adapter = declarativeRestConnector(redditSpec);
|
|
16582
|
+
const now = options.now ?? Date.now;
|
|
16583
|
+
const refreshes = /* @__PURE__ */ new Map();
|
|
16584
|
+
const refresh = async (credentials) => {
|
|
16585
|
+
if (credentials.kind !== "oauth2" || !credentials.refreshToken) {
|
|
16586
|
+
throw new Error("reddit.refreshToken: missing refresh token");
|
|
16587
|
+
}
|
|
16588
|
+
const tokens = await refreshAccessToken({
|
|
16589
|
+
tokenUrl: REDDIT_TOKEN_URL,
|
|
16590
|
+
clientId: options.clientId,
|
|
16591
|
+
clientSecret: options.clientSecret,
|
|
16592
|
+
tokenClientAuthMethod: "client_secret_basic",
|
|
16593
|
+
refreshToken: credentials.refreshToken,
|
|
16594
|
+
tokenRequestHeaders: { "User-Agent": REDDIT_USER_AGENT },
|
|
16595
|
+
fetchImpl: options.fetchImpl
|
|
16596
|
+
});
|
|
16597
|
+
if (!tokens.accessToken || !tokens.expiresIn) {
|
|
16598
|
+
throw new Error("Reddit token refresh returned an incomplete grant");
|
|
16599
|
+
}
|
|
16600
|
+
return {
|
|
16601
|
+
kind: "oauth2",
|
|
16602
|
+
accessToken: tokens.accessToken,
|
|
16603
|
+
refreshToken: tokens.refreshToken ?? credentials.refreshToken,
|
|
16604
|
+
expiresAt: now() + tokens.expiresIn * 1e3
|
|
16605
|
+
};
|
|
16606
|
+
};
|
|
16607
|
+
adapter.refreshToken = refresh;
|
|
16608
|
+
const withFreshCredentials = async (invocation) => {
|
|
16609
|
+
const credentials = invocation.source.credentials;
|
|
16610
|
+
if (credentials.kind !== "oauth2") {
|
|
16611
|
+
throw new CredentialsExpired("Reddit requires OAuth2 credentials.", invocation.source.id);
|
|
16612
|
+
}
|
|
16613
|
+
if (credentials.expiresAt !== void 0 && credentials.expiresAt > now() + 6e4) {
|
|
16614
|
+
return invocation;
|
|
16615
|
+
}
|
|
16616
|
+
if (!credentials.refreshToken) {
|
|
16617
|
+
throw new CredentialsExpired(
|
|
16618
|
+
"Reddit access token expired and no refresh token is available.",
|
|
16619
|
+
invocation.source.id
|
|
16620
|
+
);
|
|
16621
|
+
}
|
|
16622
|
+
let pending = refreshes.get(invocation.source.id);
|
|
16623
|
+
if (!pending) {
|
|
16624
|
+
let next;
|
|
16625
|
+
const promise = Promise.resolve().then(() => {
|
|
16626
|
+
if (!next.onCredentialsRotated) {
|
|
16627
|
+
throw new Error("reddit: credential rotation persistence callback is required before refreshing");
|
|
16628
|
+
}
|
|
16629
|
+
return refresh(credentials);
|
|
16630
|
+
});
|
|
16631
|
+
next = {
|
|
16632
|
+
promise,
|
|
16633
|
+
onCredentialsRotated: invocation.onCredentialsRotated
|
|
16634
|
+
};
|
|
16635
|
+
pending = next;
|
|
16636
|
+
refreshes.set(invocation.source.id, pending);
|
|
16637
|
+
} else if (!pending.onCredentialsRotated && invocation.onCredentialsRotated) {
|
|
16638
|
+
pending.onCredentialsRotated = invocation.onCredentialsRotated;
|
|
16639
|
+
}
|
|
16640
|
+
const current = pending;
|
|
16641
|
+
try {
|
|
16642
|
+
const refreshed = await current.promise;
|
|
16643
|
+
current.persistence ??= Promise.resolve().then(
|
|
16644
|
+
() => current.onCredentialsRotated?.(refreshed)
|
|
16645
|
+
);
|
|
16646
|
+
await current.persistence;
|
|
16647
|
+
return {
|
|
16648
|
+
...invocation,
|
|
16649
|
+
source: { ...invocation.source, credentials: refreshed }
|
|
16650
|
+
};
|
|
16651
|
+
} finally {
|
|
16652
|
+
if (refreshes.get(invocation.source.id) === current) {
|
|
16653
|
+
refreshes.delete(invocation.source.id);
|
|
16654
|
+
}
|
|
16655
|
+
}
|
|
16656
|
+
};
|
|
16657
|
+
return {
|
|
16658
|
+
...adapter,
|
|
16659
|
+
async exchangeOAuth(input) {
|
|
16660
|
+
const tokens = await exchangeAuthorizationCode({
|
|
16661
|
+
tokenUrl: REDDIT_TOKEN_URL,
|
|
16662
|
+
clientId: options.clientId,
|
|
16663
|
+
clientSecret: options.clientSecret,
|
|
16664
|
+
tokenClientAuthMethod: "client_secret_basic",
|
|
16665
|
+
code: input.code,
|
|
16666
|
+
codeVerifier: input.codeVerifier,
|
|
16667
|
+
pkce: "unsupported",
|
|
16668
|
+
redirectUri: input.redirectUri,
|
|
16669
|
+
tokenRequestHeaders: { "User-Agent": REDDIT_USER_AGENT },
|
|
16670
|
+
fetchImpl: options.fetchImpl
|
|
16671
|
+
});
|
|
16672
|
+
if (!tokens.accessToken || !tokens.refreshToken || !tokens.expiresIn) {
|
|
16673
|
+
throw new Error("Reddit token exchange returned an incomplete permanent grant");
|
|
16674
|
+
}
|
|
16675
|
+
return {
|
|
16676
|
+
credentials: {
|
|
16677
|
+
kind: "oauth2",
|
|
16678
|
+
accessToken: tokens.accessToken,
|
|
16679
|
+
refreshToken: tokens.refreshToken,
|
|
16680
|
+
expiresAt: now() + tokens.expiresIn * 1e3
|
|
16681
|
+
},
|
|
16682
|
+
scopes: tokens.scope?.split(/[\s,]+/).filter(Boolean) ?? [...redditSpec.auth.scopes],
|
|
16683
|
+
metadata: {}
|
|
16684
|
+
};
|
|
16685
|
+
},
|
|
16686
|
+
refreshToken: refresh,
|
|
16687
|
+
async executeRead(invocation) {
|
|
16688
|
+
return adapter.executeRead(await withFreshCredentials(invocation));
|
|
16689
|
+
},
|
|
16690
|
+
async executeMutation(invocation) {
|
|
16691
|
+
return adapter.executeMutation(await withFreshCredentials(invocation));
|
|
16692
|
+
},
|
|
16693
|
+
async test(source, onCredentialsRotated) {
|
|
16694
|
+
try {
|
|
16695
|
+
const invocation = await withFreshCredentials({
|
|
16696
|
+
source,
|
|
16697
|
+
capabilityName: "__test__",
|
|
16698
|
+
args: {},
|
|
16699
|
+
idempotencyKey: "reddit-connection-test",
|
|
16700
|
+
onCredentialsRotated
|
|
16701
|
+
});
|
|
16702
|
+
return adapter.test(invocation.source);
|
|
16703
|
+
} catch (error) {
|
|
16704
|
+
return {
|
|
16705
|
+
ok: false,
|
|
16706
|
+
reason: error instanceof Error ? error.message : "unknown error"
|
|
16707
|
+
};
|
|
16708
|
+
}
|
|
16709
|
+
}
|
|
16710
|
+
};
|
|
16711
|
+
}
|
|
16357
16712
|
|
|
16358
16713
|
// src/connectors/adapters/rippling.ts
|
|
16359
16714
|
var ripplingConnector = declarativeRestConnector({
|
|
@@ -20103,6 +20458,332 @@ function arbitraryBodyParameters() {
|
|
|
20103
20458
|
};
|
|
20104
20459
|
}
|
|
20105
20460
|
|
|
20461
|
+
// src/connectors/adapters/amplitude.ts
|
|
20462
|
+
var date = {
|
|
20463
|
+
type: "string",
|
|
20464
|
+
pattern: "^[0-9]{8}$",
|
|
20465
|
+
description: "Inclusive date in YYYYMMDD format."
|
|
20466
|
+
};
|
|
20467
|
+
var isoTimestamp = {
|
|
20468
|
+
type: "string",
|
|
20469
|
+
description: "ISO 8601 timestamp with a time-zone offset."
|
|
20470
|
+
};
|
|
20471
|
+
var annotationId = {
|
|
20472
|
+
annotationId: { type: "integer", minimum: 1, description: "Amplitude annotation ID." }
|
|
20473
|
+
};
|
|
20474
|
+
var categoryId = {
|
|
20475
|
+
categoryId: { type: "integer", minimum: 1, description: "Amplitude annotation category ID." }
|
|
20476
|
+
};
|
|
20477
|
+
var annotation = {
|
|
20478
|
+
type: "object",
|
|
20479
|
+
properties: {
|
|
20480
|
+
label: { type: "string", minLength: 1 },
|
|
20481
|
+
start: isoTimestamp,
|
|
20482
|
+
category: { type: "string" },
|
|
20483
|
+
chart_id: { type: ["string", "null"] },
|
|
20484
|
+
details: { type: "string" },
|
|
20485
|
+
end: { ...isoTimestamp, type: ["string", "null"] }
|
|
20486
|
+
},
|
|
20487
|
+
required: ["label", "start"],
|
|
20488
|
+
additionalProperties: false
|
|
20489
|
+
};
|
|
20490
|
+
var amplitudeConnector = declarativeRestConnector({
|
|
20491
|
+
kind: "amplitude",
|
|
20492
|
+
displayName: "Amplitude",
|
|
20493
|
+
description: "Query project analytics and manage chart annotations with Amplitude project API credentials.",
|
|
20494
|
+
auth: {
|
|
20495
|
+
kind: "api-key",
|
|
20496
|
+
hint: 'JSON credential bundle: {"apiKey":"...","secretKey":"..."} from Project Settings \u2192 General. Set metadata.apiBaseUrl to https://analytics.eu.amplitude.com only for an EU-resident project; the default is https://amplitude.com.'
|
|
20497
|
+
},
|
|
20498
|
+
category: "other",
|
|
20499
|
+
defaultConsistencyModel: "authoritative",
|
|
20500
|
+
baseUrl: { metadataKey: "apiBaseUrl", fallback: "https://amplitude.com" },
|
|
20501
|
+
allowedBaseUrls: ["https://amplitude.com", "https://analytics.eu.amplitude.com"],
|
|
20502
|
+
credentialPlacement: {
|
|
20503
|
+
kind: "basic-structured",
|
|
20504
|
+
usernameField: "apiKey",
|
|
20505
|
+
passwordField: "secretKey"
|
|
20506
|
+
},
|
|
20507
|
+
test: { method: "GET", path: "/api/2/events/list" },
|
|
20508
|
+
capabilities: [
|
|
20509
|
+
{
|
|
20510
|
+
name: "events.list",
|
|
20511
|
+
class: "read",
|
|
20512
|
+
description: "List visible project events with current-week totals, uniques, and daily-active-user share.",
|
|
20513
|
+
parameters: { type: "object", properties: {} },
|
|
20514
|
+
request: { method: "GET", path: "/api/2/events/list" }
|
|
20515
|
+
},
|
|
20516
|
+
{
|
|
20517
|
+
name: "events.segment",
|
|
20518
|
+
class: "read",
|
|
20519
|
+
description: "Query event totals, uniques, percentages, averages, or formulas over a date range.",
|
|
20520
|
+
parameters: {
|
|
20521
|
+
type: "object",
|
|
20522
|
+
properties: {
|
|
20523
|
+
event: {
|
|
20524
|
+
type: "string",
|
|
20525
|
+
description: 'JSON event definition, for example {"event_type":"_active"}.'
|
|
20526
|
+
},
|
|
20527
|
+
secondEvent: { type: "string", description: "Optional second JSON event definition." },
|
|
20528
|
+
metric: {
|
|
20529
|
+
type: "string",
|
|
20530
|
+
enum: ["uniques", "totals", "pct_dau", "average", "histogram", "sums", "value_avg", "formula"]
|
|
20531
|
+
},
|
|
20532
|
+
activeUserType: { type: "string", enum: ["any", "active"] },
|
|
20533
|
+
start: date,
|
|
20534
|
+
end: date,
|
|
20535
|
+
interval: { type: "integer", enum: [-3e5, -36e5, 1, 7, 30] },
|
|
20536
|
+
segment: { type: "string", description: "JSON array of Amplitude segment definitions." },
|
|
20537
|
+
groupBy: { type: "string" },
|
|
20538
|
+
secondGroupBy: { type: "string" },
|
|
20539
|
+
limit: { type: "integer", minimum: 1, maximum: 1e3 },
|
|
20540
|
+
formula: { type: "string" },
|
|
20541
|
+
rollingWindow: { type: "integer", minimum: 1 },
|
|
20542
|
+
rollingAverage: { type: "integer", minimum: 1 }
|
|
20543
|
+
},
|
|
20544
|
+
required: ["event", "start", "end"]
|
|
20545
|
+
},
|
|
20546
|
+
request: {
|
|
20547
|
+
method: "GET",
|
|
20548
|
+
path: "/api/2/events/segmentation",
|
|
20549
|
+
query: {
|
|
20550
|
+
e: "{event}",
|
|
20551
|
+
e2: "{secondEvent}",
|
|
20552
|
+
m: "{metric}",
|
|
20553
|
+
n: "{activeUserType}",
|
|
20554
|
+
start: "{start}",
|
|
20555
|
+
end: "{end}",
|
|
20556
|
+
i: "{interval}",
|
|
20557
|
+
s: "{segment}",
|
|
20558
|
+
g: "{groupBy}",
|
|
20559
|
+
g2: "{secondGroupBy}",
|
|
20560
|
+
limit: "{limit}",
|
|
20561
|
+
formula: "{formula}",
|
|
20562
|
+
rollingWindow: "{rollingWindow}",
|
|
20563
|
+
rollingAverage: "{rollingAverage}"
|
|
20564
|
+
}
|
|
20565
|
+
}
|
|
20566
|
+
},
|
|
20567
|
+
{
|
|
20568
|
+
name: "users.counts",
|
|
20569
|
+
class: "read",
|
|
20570
|
+
description: "Get active or new user counts over a date range.",
|
|
20571
|
+
parameters: {
|
|
20572
|
+
type: "object",
|
|
20573
|
+
properties: {
|
|
20574
|
+
start: date,
|
|
20575
|
+
end: date,
|
|
20576
|
+
mode: { type: "string", enum: ["active", "new"] },
|
|
20577
|
+
interval: { type: "integer", enum: [1, 7, 30] },
|
|
20578
|
+
segment: { type: "string", description: "JSON array of Amplitude segment definitions." },
|
|
20579
|
+
groupBy: { type: "string" }
|
|
20580
|
+
},
|
|
20581
|
+
required: ["start", "end"]
|
|
20582
|
+
},
|
|
20583
|
+
request: {
|
|
20584
|
+
method: "GET",
|
|
20585
|
+
path: "/api/2/users",
|
|
20586
|
+
query: {
|
|
20587
|
+
start: "{start}",
|
|
20588
|
+
end: "{end}",
|
|
20589
|
+
m: "{mode}",
|
|
20590
|
+
i: "{interval}",
|
|
20591
|
+
s: "{segment}",
|
|
20592
|
+
g: "{groupBy}"
|
|
20593
|
+
}
|
|
20594
|
+
}
|
|
20595
|
+
},
|
|
20596
|
+
{
|
|
20597
|
+
name: "sessions.average-length",
|
|
20598
|
+
class: "read",
|
|
20599
|
+
description: "Get average session length in seconds for each day in a date range.",
|
|
20600
|
+
parameters: {
|
|
20601
|
+
type: "object",
|
|
20602
|
+
properties: { start: date, end: date },
|
|
20603
|
+
required: ["start", "end"]
|
|
20604
|
+
},
|
|
20605
|
+
request: {
|
|
20606
|
+
method: "GET",
|
|
20607
|
+
path: "/api/2/sessions/average",
|
|
20608
|
+
query: { start: "{start}", end: "{end}" }
|
|
20609
|
+
}
|
|
20610
|
+
},
|
|
20611
|
+
{
|
|
20612
|
+
name: "users.search",
|
|
20613
|
+
class: "read",
|
|
20614
|
+
description: "Search for a user by Amplitude ID, device ID, user ID, or user ID prefix.",
|
|
20615
|
+
parameters: {
|
|
20616
|
+
type: "object",
|
|
20617
|
+
properties: { user: { type: "string", minLength: 1 } },
|
|
20618
|
+
required: ["user"]
|
|
20619
|
+
},
|
|
20620
|
+
request: { method: "GET", path: "/api/2/usersearch", query: { user: "{user}" } }
|
|
20621
|
+
},
|
|
20622
|
+
{
|
|
20623
|
+
name: "users.activity",
|
|
20624
|
+
class: "read",
|
|
20625
|
+
description: "Read one user summary and a bounded window of recent or earliest events.",
|
|
20626
|
+
parameters: {
|
|
20627
|
+
type: "object",
|
|
20628
|
+
properties: {
|
|
20629
|
+
user: { type: "string", minLength: 1, description: "Amplitude user ID." },
|
|
20630
|
+
offset: { type: "integer", minimum: 0 },
|
|
20631
|
+
limit: { type: "integer", minimum: 0, maximum: 1e3 },
|
|
20632
|
+
direction: { type: "string", enum: ["earliest", "latest"] }
|
|
20633
|
+
},
|
|
20634
|
+
required: ["user"]
|
|
20635
|
+
},
|
|
20636
|
+
request: {
|
|
20637
|
+
method: "GET",
|
|
20638
|
+
path: "/api/2/useractivity",
|
|
20639
|
+
query: { user: "{user}", offset: "{offset}", limit: "{limit}", direction: "{direction}" }
|
|
20640
|
+
}
|
|
20641
|
+
},
|
|
20642
|
+
{
|
|
20643
|
+
name: "charts.results",
|
|
20644
|
+
class: "read",
|
|
20645
|
+
description: "Export results from one saved Amplitude chart by chart ID.",
|
|
20646
|
+
parameters: {
|
|
20647
|
+
type: "object",
|
|
20648
|
+
properties: { chartId: { type: "string", minLength: 1 } },
|
|
20649
|
+
required: ["chartId"]
|
|
20650
|
+
},
|
|
20651
|
+
request: { method: "GET", path: "/api/3/chart/{chartId}/csv" }
|
|
20652
|
+
},
|
|
20653
|
+
{
|
|
20654
|
+
name: "annotations.list",
|
|
20655
|
+
class: "read",
|
|
20656
|
+
description: "List project chart annotations with optional category, chart, and date filters.",
|
|
20657
|
+
parameters: {
|
|
20658
|
+
type: "object",
|
|
20659
|
+
properties: {
|
|
20660
|
+
category: { type: "string" },
|
|
20661
|
+
chartId: { type: "string" },
|
|
20662
|
+
start: isoTimestamp,
|
|
20663
|
+
end: isoTimestamp
|
|
20664
|
+
}
|
|
20665
|
+
},
|
|
20666
|
+
request: {
|
|
20667
|
+
method: "GET",
|
|
20668
|
+
path: "/api/3/annotations",
|
|
20669
|
+
query: { category: "{category}", chart_id: "{chartId}", start: "{start}", end: "{end}" }
|
|
20670
|
+
}
|
|
20671
|
+
},
|
|
20672
|
+
{
|
|
20673
|
+
name: "annotations.get",
|
|
20674
|
+
class: "read",
|
|
20675
|
+
description: "Read one chart annotation by ID.",
|
|
20676
|
+
parameters: { type: "object", properties: annotationId, required: ["annotationId"] },
|
|
20677
|
+
request: { method: "GET", path: "/api/3/annotations/{annotationId}" }
|
|
20678
|
+
},
|
|
20679
|
+
{
|
|
20680
|
+
name: "annotations.create",
|
|
20681
|
+
class: "mutation",
|
|
20682
|
+
description: "Create a project-wide or chart-specific annotation.",
|
|
20683
|
+
parameters: {
|
|
20684
|
+
type: "object",
|
|
20685
|
+
properties: { annotation },
|
|
20686
|
+
required: ["annotation"]
|
|
20687
|
+
},
|
|
20688
|
+
request: { method: "POST", path: "/api/3/annotations", body: "{annotation}" },
|
|
20689
|
+
cas: "none",
|
|
20690
|
+
externalEffect: true
|
|
20691
|
+
},
|
|
20692
|
+
{
|
|
20693
|
+
name: "annotations.update",
|
|
20694
|
+
class: "mutation",
|
|
20695
|
+
description: "Partially update one annotation.",
|
|
20696
|
+
parameters: {
|
|
20697
|
+
type: "object",
|
|
20698
|
+
properties: {
|
|
20699
|
+
...annotationId,
|
|
20700
|
+
changes: {
|
|
20701
|
+
...annotation,
|
|
20702
|
+
required: []
|
|
20703
|
+
}
|
|
20704
|
+
},
|
|
20705
|
+
required: ["annotationId", "changes"]
|
|
20706
|
+
},
|
|
20707
|
+
request: { method: "PUT", path: "/api/3/annotations/{annotationId}", body: "{changes}" },
|
|
20708
|
+
cas: "optimistic-read-verify",
|
|
20709
|
+
externalEffect: true
|
|
20710
|
+
},
|
|
20711
|
+
{
|
|
20712
|
+
name: "annotations.delete",
|
|
20713
|
+
class: "mutation",
|
|
20714
|
+
description: "Permanently delete one annotation.",
|
|
20715
|
+
parameters: { type: "object", properties: annotationId, required: ["annotationId"] },
|
|
20716
|
+
request: { method: "DELETE", path: "/api/3/annotations/{annotationId}" },
|
|
20717
|
+
cas: "optimistic-read-verify",
|
|
20718
|
+
externalEffect: true
|
|
20719
|
+
},
|
|
20720
|
+
{
|
|
20721
|
+
name: "annotation-categories.list",
|
|
20722
|
+
class: "read",
|
|
20723
|
+
description: "List annotation categories or filter by exact category name.",
|
|
20724
|
+
parameters: {
|
|
20725
|
+
type: "object",
|
|
20726
|
+
properties: { category: { type: "string" } }
|
|
20727
|
+
},
|
|
20728
|
+
request: {
|
|
20729
|
+
method: "GET",
|
|
20730
|
+
path: "/api/3/annotation-categories",
|
|
20731
|
+
query: { category: "{category}" }
|
|
20732
|
+
}
|
|
20733
|
+
},
|
|
20734
|
+
{
|
|
20735
|
+
name: "annotation-categories.get",
|
|
20736
|
+
class: "read",
|
|
20737
|
+
description: "Read one annotation category by ID.",
|
|
20738
|
+
parameters: { type: "object", properties: categoryId, required: ["categoryId"] },
|
|
20739
|
+
request: { method: "GET", path: "/api/3/annotation-categories/{categoryId}" }
|
|
20740
|
+
},
|
|
20741
|
+
{
|
|
20742
|
+
name: "annotation-categories.create",
|
|
20743
|
+
class: "mutation",
|
|
20744
|
+
description: "Create an annotation category.",
|
|
20745
|
+
parameters: {
|
|
20746
|
+
type: "object",
|
|
20747
|
+
properties: { category: { type: "string", minLength: 1 } },
|
|
20748
|
+
required: ["category"]
|
|
20749
|
+
},
|
|
20750
|
+
request: {
|
|
20751
|
+
method: "POST",
|
|
20752
|
+
path: "/api/3/annotation-categories",
|
|
20753
|
+
body: { category: "{category}" }
|
|
20754
|
+
},
|
|
20755
|
+
cas: "none",
|
|
20756
|
+
externalEffect: true
|
|
20757
|
+
},
|
|
20758
|
+
{
|
|
20759
|
+
name: "annotation-categories.update",
|
|
20760
|
+
class: "mutation",
|
|
20761
|
+
description: "Rename one annotation category.",
|
|
20762
|
+
parameters: {
|
|
20763
|
+
type: "object",
|
|
20764
|
+
properties: { ...categoryId, category: { type: "string", minLength: 1 } },
|
|
20765
|
+
required: ["categoryId", "category"]
|
|
20766
|
+
},
|
|
20767
|
+
request: {
|
|
20768
|
+
method: "PUT",
|
|
20769
|
+
path: "/api/3/annotation-categories/{categoryId}",
|
|
20770
|
+
body: { category: "{category}" }
|
|
20771
|
+
},
|
|
20772
|
+
cas: "optimistic-read-verify",
|
|
20773
|
+
externalEffect: true
|
|
20774
|
+
},
|
|
20775
|
+
{
|
|
20776
|
+
name: "annotation-categories.delete",
|
|
20777
|
+
class: "mutation",
|
|
20778
|
+
description: "Permanently delete one annotation category.",
|
|
20779
|
+
parameters: { type: "object", properties: categoryId, required: ["categoryId"] },
|
|
20780
|
+
request: { method: "DELETE", path: "/api/3/annotation-categories/{categoryId}" },
|
|
20781
|
+
cas: "optimistic-read-verify",
|
|
20782
|
+
externalEffect: true
|
|
20783
|
+
}
|
|
20784
|
+
]
|
|
20785
|
+
});
|
|
20786
|
+
|
|
20106
20787
|
// src/connectors/adapters/amazon-eventbridge.ts
|
|
20107
20788
|
var amazonEventBridgeConnector = declarativeRestConnector({
|
|
20108
20789
|
kind: "amazon-eventbridge",
|
|
@@ -20442,6 +21123,717 @@ var amazonEventBridgeConnector = declarativeRestConnector({
|
|
|
20442
21123
|
]
|
|
20443
21124
|
});
|
|
20444
21125
|
|
|
21126
|
+
// src/connectors/adapters/amazon-cloudwatch.ts
|
|
21127
|
+
var target = (operation) => `GraniteServiceVersion20100801.${operation}`;
|
|
21128
|
+
var amazonCloudWatchConnector = declarativeRestConnector({
|
|
21129
|
+
kind: "aws-cloudwatch",
|
|
21130
|
+
displayName: "AWS CloudWatch",
|
|
21131
|
+
description: "Read and publish CloudWatch metrics, manage metric alarms, and manage dashboards.",
|
|
21132
|
+
auth: {
|
|
21133
|
+
kind: "api-key",
|
|
21134
|
+
hint: 'AWS credentials as JSON: {"accessKeyId":"AKIA\u2026","secretAccessKey":"\u2026","region":"us-east-1"}. Optional "sessionToken" and "endpoint" support temporary credentials and local AWS-compatible endpoints.'
|
|
21135
|
+
},
|
|
21136
|
+
category: "other",
|
|
21137
|
+
// Metric publication is eventually consistent and cannot be deduplicated by
|
|
21138
|
+
// a caller-provided key. Alarm and dashboard writes use stronger CAS labels.
|
|
21139
|
+
defaultConsistencyModel: "advisory",
|
|
21140
|
+
credentialPlacement: { kind: "aws-sigv4", service: "monitoring" },
|
|
21141
|
+
baseUrl: {
|
|
21142
|
+
metadataKey: "endpoint",
|
|
21143
|
+
fallback: "https://monitoring.{region}.amazonaws.com"
|
|
21144
|
+
},
|
|
21145
|
+
defaultHeaders: {
|
|
21146
|
+
"Content-Type": "application/x-amz-json-1.0"
|
|
21147
|
+
},
|
|
21148
|
+
test: {
|
|
21149
|
+
method: "POST",
|
|
21150
|
+
path: "/",
|
|
21151
|
+
headers: { "X-Amz-Target": target("ListMetrics") },
|
|
21152
|
+
body: {}
|
|
21153
|
+
},
|
|
21154
|
+
capabilities: [
|
|
21155
|
+
{
|
|
21156
|
+
name: "metrics.list",
|
|
21157
|
+
class: "read",
|
|
21158
|
+
description: "List available CloudWatch metrics and their dimensions.",
|
|
21159
|
+
parameters: {
|
|
21160
|
+
type: "object",
|
|
21161
|
+
properties: {
|
|
21162
|
+
namespace: { type: "string" },
|
|
21163
|
+
metricName: { type: "string" },
|
|
21164
|
+
dimensions: { type: "array", description: "AWS DimensionFilter objects." },
|
|
21165
|
+
nextToken: { type: "string" },
|
|
21166
|
+
recentlyActive: { type: "string", enum: ["PT3H"] },
|
|
21167
|
+
includeLinkedAccounts: { type: "boolean" },
|
|
21168
|
+
owningAccount: { type: "string" }
|
|
21169
|
+
}
|
|
21170
|
+
},
|
|
21171
|
+
request: {
|
|
21172
|
+
method: "POST",
|
|
21173
|
+
path: "/",
|
|
21174
|
+
headers: { "X-Amz-Target": target("ListMetrics") },
|
|
21175
|
+
body: {
|
|
21176
|
+
Namespace: "{namespace}",
|
|
21177
|
+
MetricName: "{metricName}",
|
|
21178
|
+
Dimensions: "{dimensions}",
|
|
21179
|
+
NextToken: "{nextToken}",
|
|
21180
|
+
RecentlyActive: "{recentlyActive}",
|
|
21181
|
+
IncludeLinkedAccounts: "{includeLinkedAccounts}",
|
|
21182
|
+
OwningAccount: "{owningAccount}"
|
|
21183
|
+
}
|
|
21184
|
+
}
|
|
21185
|
+
},
|
|
21186
|
+
{
|
|
21187
|
+
name: "metrics.statistics.get",
|
|
21188
|
+
class: "read",
|
|
21189
|
+
description: "Get statistics for one metric over a time range.",
|
|
21190
|
+
parameters: {
|
|
21191
|
+
type: "object",
|
|
21192
|
+
properties: {
|
|
21193
|
+
namespace: { type: "string" },
|
|
21194
|
+
metricName: { type: "string" },
|
|
21195
|
+
dimensions: { type: "array", description: "AWS Dimension objects." },
|
|
21196
|
+
startTime: { type: "number", description: "Unix epoch seconds." },
|
|
21197
|
+
endTime: { type: "number", description: "Unix epoch seconds." },
|
|
21198
|
+
period: { type: "integer", description: "Aggregation period in seconds." },
|
|
21199
|
+
statistics: { type: "array", items: { type: "string" } },
|
|
21200
|
+
extendedStatistics: { type: "array", items: { type: "string" } },
|
|
21201
|
+
unit: { type: "string" }
|
|
21202
|
+
},
|
|
21203
|
+
required: ["namespace", "metricName", "startTime", "endTime", "period"]
|
|
21204
|
+
},
|
|
21205
|
+
request: {
|
|
21206
|
+
method: "POST",
|
|
21207
|
+
path: "/",
|
|
21208
|
+
headers: { "X-Amz-Target": target("GetMetricStatistics") },
|
|
21209
|
+
body: {
|
|
21210
|
+
Namespace: "{namespace}",
|
|
21211
|
+
MetricName: "{metricName}",
|
|
21212
|
+
Dimensions: "{dimensions}",
|
|
21213
|
+
StartTime: "{startTime}",
|
|
21214
|
+
EndTime: "{endTime}",
|
|
21215
|
+
Period: "{period}",
|
|
21216
|
+
Statistics: "{statistics}",
|
|
21217
|
+
ExtendedStatistics: "{extendedStatistics}",
|
|
21218
|
+
Unit: "{unit}"
|
|
21219
|
+
}
|
|
21220
|
+
}
|
|
21221
|
+
},
|
|
21222
|
+
{
|
|
21223
|
+
name: "metrics.data.get",
|
|
21224
|
+
class: "read",
|
|
21225
|
+
description: "Run up to 500 metric-data or metric-math queries in one request.",
|
|
21226
|
+
parameters: {
|
|
21227
|
+
type: "object",
|
|
21228
|
+
properties: {
|
|
21229
|
+
metricDataQueries: { type: "array", description: "AWS MetricDataQuery objects." },
|
|
21230
|
+
startTime: { type: "number", description: "Unix epoch seconds." },
|
|
21231
|
+
endTime: { type: "number", description: "Unix epoch seconds." },
|
|
21232
|
+
nextToken: { type: "string" },
|
|
21233
|
+
scanBy: { type: "string", enum: ["TimestampDescending", "TimestampAscending"] },
|
|
21234
|
+
maxDatapoints: { type: "integer" },
|
|
21235
|
+
labelOptions: { type: "object" }
|
|
21236
|
+
},
|
|
21237
|
+
required: ["metricDataQueries", "startTime", "endTime"]
|
|
21238
|
+
},
|
|
21239
|
+
request: {
|
|
21240
|
+
method: "POST",
|
|
21241
|
+
path: "/",
|
|
21242
|
+
headers: { "X-Amz-Target": target("GetMetricData") },
|
|
21243
|
+
body: {
|
|
21244
|
+
MetricDataQueries: "{metricDataQueries}",
|
|
21245
|
+
StartTime: "{startTime}",
|
|
21246
|
+
EndTime: "{endTime}",
|
|
21247
|
+
NextToken: "{nextToken}",
|
|
21248
|
+
ScanBy: "{scanBy}",
|
|
21249
|
+
MaxDatapoints: "{maxDatapoints}",
|
|
21250
|
+
LabelOptions: "{labelOptions}"
|
|
21251
|
+
}
|
|
21252
|
+
}
|
|
21253
|
+
},
|
|
21254
|
+
{
|
|
21255
|
+
name: "alarms.list",
|
|
21256
|
+
class: "read",
|
|
21257
|
+
description: "List metric and composite alarms with optional filters.",
|
|
21258
|
+
parameters: {
|
|
21259
|
+
type: "object",
|
|
21260
|
+
properties: {
|
|
21261
|
+
alarmNames: { type: "array", items: { type: "string" } },
|
|
21262
|
+
alarmNamePrefix: { type: "string" },
|
|
21263
|
+
alarmTypes: { type: "array", items: { type: "string" } },
|
|
21264
|
+
childrenOfAlarmName: { type: "string" },
|
|
21265
|
+
parentsOfAlarmName: { type: "string" },
|
|
21266
|
+
stateValue: { type: "string", enum: ["OK", "ALARM", "INSUFFICIENT_DATA"] },
|
|
21267
|
+
actionPrefix: { type: "string" },
|
|
21268
|
+
maxRecords: { type: "integer" },
|
|
21269
|
+
nextToken: { type: "string" }
|
|
21270
|
+
}
|
|
21271
|
+
},
|
|
21272
|
+
request: {
|
|
21273
|
+
method: "POST",
|
|
21274
|
+
path: "/",
|
|
21275
|
+
headers: { "X-Amz-Target": target("DescribeAlarms") },
|
|
21276
|
+
body: {
|
|
21277
|
+
AlarmNames: "{alarmNames}",
|
|
21278
|
+
AlarmNamePrefix: "{alarmNamePrefix}",
|
|
21279
|
+
AlarmTypes: "{alarmTypes}",
|
|
21280
|
+
ChildrenOfAlarmName: "{childrenOfAlarmName}",
|
|
21281
|
+
ParentsOfAlarmName: "{parentsOfAlarmName}",
|
|
21282
|
+
StateValue: "{stateValue}",
|
|
21283
|
+
ActionPrefix: "{actionPrefix}",
|
|
21284
|
+
MaxRecords: "{maxRecords}",
|
|
21285
|
+
NextToken: "{nextToken}"
|
|
21286
|
+
}
|
|
21287
|
+
}
|
|
21288
|
+
},
|
|
21289
|
+
{
|
|
21290
|
+
name: "dashboards.list",
|
|
21291
|
+
class: "read",
|
|
21292
|
+
description: "List CloudWatch dashboards in the account.",
|
|
21293
|
+
parameters: {
|
|
21294
|
+
type: "object",
|
|
21295
|
+
properties: {
|
|
21296
|
+
dashboardNamePrefix: { type: "string" },
|
|
21297
|
+
nextToken: { type: "string" }
|
|
21298
|
+
}
|
|
21299
|
+
},
|
|
21300
|
+
request: {
|
|
21301
|
+
method: "POST",
|
|
21302
|
+
path: "/",
|
|
21303
|
+
headers: { "X-Amz-Target": target("ListDashboards") },
|
|
21304
|
+
body: {
|
|
21305
|
+
DashboardNamePrefix: "{dashboardNamePrefix}",
|
|
21306
|
+
NextToken: "{nextToken}"
|
|
21307
|
+
}
|
|
21308
|
+
}
|
|
21309
|
+
},
|
|
21310
|
+
{
|
|
21311
|
+
name: "dashboards.get",
|
|
21312
|
+
class: "read",
|
|
21313
|
+
description: "Get one CloudWatch dashboard definition.",
|
|
21314
|
+
parameters: {
|
|
21315
|
+
type: "object",
|
|
21316
|
+
properties: { dashboardName: { type: "string" } },
|
|
21317
|
+
required: ["dashboardName"]
|
|
21318
|
+
},
|
|
21319
|
+
request: {
|
|
21320
|
+
method: "POST",
|
|
21321
|
+
path: "/",
|
|
21322
|
+
headers: { "X-Amz-Target": target("GetDashboard") },
|
|
21323
|
+
body: { DashboardName: "{dashboardName}" }
|
|
21324
|
+
}
|
|
21325
|
+
},
|
|
21326
|
+
{
|
|
21327
|
+
name: "metrics.publish",
|
|
21328
|
+
class: "mutation",
|
|
21329
|
+
description: "Publish custom metric data or entity metric data to CloudWatch.",
|
|
21330
|
+
parameters: {
|
|
21331
|
+
type: "object",
|
|
21332
|
+
properties: {
|
|
21333
|
+
namespace: { type: "string" },
|
|
21334
|
+
metricData: { type: "array", description: "AWS MetricDatum objects." },
|
|
21335
|
+
entityMetricData: { type: "array", description: "AWS EntityMetricData objects." },
|
|
21336
|
+
strictEntityValidation: { type: "boolean" }
|
|
21337
|
+
},
|
|
21338
|
+
required: ["namespace"]
|
|
21339
|
+
},
|
|
21340
|
+
request: {
|
|
21341
|
+
method: "POST",
|
|
21342
|
+
path: "/",
|
|
21343
|
+
headers: { "X-Amz-Target": target("PutMetricData") },
|
|
21344
|
+
body: {
|
|
21345
|
+
Namespace: "{namespace}",
|
|
21346
|
+
MetricData: "{metricData}",
|
|
21347
|
+
EntityMetricData: "{entityMetricData}",
|
|
21348
|
+
StrictEntityValidation: "{strictEntityValidation}"
|
|
21349
|
+
}
|
|
21350
|
+
},
|
|
21351
|
+
cas: "none",
|
|
21352
|
+
externalEffect: true
|
|
21353
|
+
},
|
|
21354
|
+
{
|
|
21355
|
+
name: "alarms.put",
|
|
21356
|
+
class: "mutation",
|
|
21357
|
+
description: "Create or fully replace a CloudWatch metric alarm.",
|
|
21358
|
+
parameters: {
|
|
21359
|
+
type: "object",
|
|
21360
|
+
properties: {
|
|
21361
|
+
alarm: {
|
|
21362
|
+
type: "object",
|
|
21363
|
+
description: "AWS PutMetricAlarm input without undeclared transport fields."
|
|
21364
|
+
}
|
|
21365
|
+
},
|
|
21366
|
+
required: ["alarm"]
|
|
21367
|
+
},
|
|
21368
|
+
request: {
|
|
21369
|
+
method: "POST",
|
|
21370
|
+
path: "/",
|
|
21371
|
+
headers: { "X-Amz-Target": target("PutMetricAlarm") },
|
|
21372
|
+
body: "{alarm}"
|
|
21373
|
+
},
|
|
21374
|
+
cas: "optimistic-read-verify",
|
|
21375
|
+
externalEffect: true
|
|
21376
|
+
},
|
|
21377
|
+
{
|
|
21378
|
+
name: "alarms.delete",
|
|
21379
|
+
class: "mutation",
|
|
21380
|
+
description: "Delete up to 100 CloudWatch alarms by name.",
|
|
21381
|
+
parameters: {
|
|
21382
|
+
type: "object",
|
|
21383
|
+
properties: {
|
|
21384
|
+
alarmNames: { type: "array", items: { type: "string" } }
|
|
21385
|
+
},
|
|
21386
|
+
required: ["alarmNames"]
|
|
21387
|
+
},
|
|
21388
|
+
request: {
|
|
21389
|
+
method: "POST",
|
|
21390
|
+
path: "/",
|
|
21391
|
+
headers: { "X-Amz-Target": target("DeleteAlarms") },
|
|
21392
|
+
body: { AlarmNames: "{alarmNames}" }
|
|
21393
|
+
},
|
|
21394
|
+
cas: "native-idempotency",
|
|
21395
|
+
externalEffect: true
|
|
21396
|
+
},
|
|
21397
|
+
{
|
|
21398
|
+
name: "dashboards.put",
|
|
21399
|
+
class: "mutation",
|
|
21400
|
+
description: "Create or fully replace a CloudWatch dashboard.",
|
|
21401
|
+
parameters: {
|
|
21402
|
+
type: "object",
|
|
21403
|
+
properties: {
|
|
21404
|
+
dashboardName: { type: "string" },
|
|
21405
|
+
dashboardBody: { type: "string", description: "CloudWatch dashboard JSON string." }
|
|
21406
|
+
},
|
|
21407
|
+
required: ["dashboardName", "dashboardBody"]
|
|
21408
|
+
},
|
|
21409
|
+
request: {
|
|
21410
|
+
method: "POST",
|
|
21411
|
+
path: "/",
|
|
21412
|
+
headers: { "X-Amz-Target": target("PutDashboard") },
|
|
21413
|
+
body: {
|
|
21414
|
+
DashboardName: "{dashboardName}",
|
|
21415
|
+
DashboardBody: "{dashboardBody}"
|
|
21416
|
+
}
|
|
21417
|
+
},
|
|
21418
|
+
cas: "optimistic-read-verify",
|
|
21419
|
+
externalEffect: true
|
|
21420
|
+
},
|
|
21421
|
+
{
|
|
21422
|
+
name: "dashboards.delete",
|
|
21423
|
+
class: "mutation",
|
|
21424
|
+
description: "Delete up to 100 CloudWatch dashboards by name.",
|
|
21425
|
+
parameters: {
|
|
21426
|
+
type: "object",
|
|
21427
|
+
properties: {
|
|
21428
|
+
dashboardNames: { type: "array", items: { type: "string" } }
|
|
21429
|
+
},
|
|
21430
|
+
required: ["dashboardNames"]
|
|
21431
|
+
},
|
|
21432
|
+
request: {
|
|
21433
|
+
method: "POST",
|
|
21434
|
+
path: "/",
|
|
21435
|
+
headers: { "X-Amz-Target": target("DeleteDashboards") },
|
|
21436
|
+
body: { DashboardNames: "{dashboardNames}" }
|
|
21437
|
+
},
|
|
21438
|
+
cas: "native-idempotency",
|
|
21439
|
+
externalEffect: true
|
|
21440
|
+
}
|
|
21441
|
+
]
|
|
21442
|
+
});
|
|
21443
|
+
|
|
21444
|
+
// src/connectors/adapters/amazon-lambda.ts
|
|
21445
|
+
var awsCredentialHint = 'AWS credentials as JSON: {"accessKeyId":"AKIA\u2026","secretAccessKey":"\u2026","region":"us-east-1"}. Optional "sessionToken" and "endpoint" support temporary credentials and local AWS-compatible endpoints.';
|
|
21446
|
+
var amazonLambdaConnector = declarativeRestConnector({
|
|
21447
|
+
kind: "aws-lambda",
|
|
21448
|
+
displayName: "AWS Lambda",
|
|
21449
|
+
description: "Inspect, invoke, create, update, version, alias, and delete AWS Lambda functions.",
|
|
21450
|
+
auth: { kind: "api-key", hint: awsCredentialHint },
|
|
21451
|
+
category: "other",
|
|
21452
|
+
// Lambda invocation is at-least-once and can cause arbitrary downstream
|
|
21453
|
+
// effects. The connection cannot promise authoritative mutation replay.
|
|
21454
|
+
defaultConsistencyModel: "advisory",
|
|
21455
|
+
credentialPlacement: { kind: "aws-sigv4", service: "lambda" },
|
|
21456
|
+
baseUrl: {
|
|
21457
|
+
metadataKey: "endpoint",
|
|
21458
|
+
fallback: "https://lambda.{region}.amazonaws.com"
|
|
21459
|
+
},
|
|
21460
|
+
test: {
|
|
21461
|
+
method: "GET",
|
|
21462
|
+
path: "/2015-03-31/functions",
|
|
21463
|
+
query: { MaxItems: "1" }
|
|
21464
|
+
},
|
|
21465
|
+
capabilities: [
|
|
21466
|
+
{
|
|
21467
|
+
name: "functions.list",
|
|
21468
|
+
class: "read",
|
|
21469
|
+
description: "List Lambda functions in the configured AWS region.",
|
|
21470
|
+
parameters: {
|
|
21471
|
+
type: "object",
|
|
21472
|
+
properties: {
|
|
21473
|
+
marker: { type: "string", description: "Pagination marker." },
|
|
21474
|
+
maxItems: { type: "integer", description: "Maximum functions to return (1-50)." },
|
|
21475
|
+
functionVersion: {
|
|
21476
|
+
type: "string",
|
|
21477
|
+
enum: ["ALL"],
|
|
21478
|
+
description: "Include published versions when set to ALL."
|
|
21479
|
+
},
|
|
21480
|
+
masterRegion: { type: "string", description: "Filter Lambda@Edge replicas by region." }
|
|
21481
|
+
}
|
|
21482
|
+
},
|
|
21483
|
+
request: {
|
|
21484
|
+
method: "GET",
|
|
21485
|
+
path: "/2015-03-31/functions",
|
|
21486
|
+
query: {
|
|
21487
|
+
Marker: "{marker}",
|
|
21488
|
+
MaxItems: "{maxItems}",
|
|
21489
|
+
FunctionVersion: "{functionVersion}",
|
|
21490
|
+
MasterRegion: "{masterRegion}"
|
|
21491
|
+
}
|
|
21492
|
+
}
|
|
21493
|
+
},
|
|
21494
|
+
{
|
|
21495
|
+
name: "functions.get",
|
|
21496
|
+
class: "read",
|
|
21497
|
+
description: "Get one function configuration and its temporary deployment-package URL.",
|
|
21498
|
+
parameters: {
|
|
21499
|
+
type: "object",
|
|
21500
|
+
properties: {
|
|
21501
|
+
functionName: { type: "string", description: "Function name or ARN." },
|
|
21502
|
+
qualifier: { type: "string", description: "Version number or alias." }
|
|
21503
|
+
},
|
|
21504
|
+
required: ["functionName"]
|
|
21505
|
+
},
|
|
21506
|
+
request: {
|
|
21507
|
+
method: "GET",
|
|
21508
|
+
path: "/2015-03-31/functions/{functionName}",
|
|
21509
|
+
query: { Qualifier: "{qualifier}" }
|
|
21510
|
+
}
|
|
21511
|
+
},
|
|
21512
|
+
{
|
|
21513
|
+
name: "aliases.list",
|
|
21514
|
+
class: "read",
|
|
21515
|
+
description: "List aliases for a Lambda function.",
|
|
21516
|
+
parameters: {
|
|
21517
|
+
type: "object",
|
|
21518
|
+
properties: {
|
|
21519
|
+
functionName: { type: "string" },
|
|
21520
|
+
functionVersion: { type: "string" },
|
|
21521
|
+
marker: { type: "string" },
|
|
21522
|
+
maxItems: { type: "integer" }
|
|
21523
|
+
},
|
|
21524
|
+
required: ["functionName"]
|
|
21525
|
+
},
|
|
21526
|
+
request: {
|
|
21527
|
+
method: "GET",
|
|
21528
|
+
path: "/2015-03-31/functions/{functionName}/aliases",
|
|
21529
|
+
query: {
|
|
21530
|
+
FunctionVersion: "{functionVersion}",
|
|
21531
|
+
Marker: "{marker}",
|
|
21532
|
+
MaxItems: "{maxItems}"
|
|
21533
|
+
}
|
|
21534
|
+
}
|
|
21535
|
+
},
|
|
21536
|
+
{
|
|
21537
|
+
name: "functions.invoke",
|
|
21538
|
+
class: "mutation",
|
|
21539
|
+
description: "Invoke a Lambda function synchronously, asynchronously, or as a dry-run permission check.",
|
|
21540
|
+
parameters: {
|
|
21541
|
+
type: "object",
|
|
21542
|
+
properties: {
|
|
21543
|
+
functionName: { type: "string", description: "Function name or ARN." },
|
|
21544
|
+
qualifier: { type: "string", description: "Version number or alias." },
|
|
21545
|
+
invocationType: {
|
|
21546
|
+
type: "string",
|
|
21547
|
+
enum: ["RequestResponse", "Event", "DryRun"]
|
|
21548
|
+
},
|
|
21549
|
+
logType: { type: "string", enum: ["None", "Tail"] },
|
|
21550
|
+
clientContext: {
|
|
21551
|
+
type: "string",
|
|
21552
|
+
description: "Base64-encoded client context for synchronous invocation."
|
|
21553
|
+
},
|
|
21554
|
+
payload: {
|
|
21555
|
+
description: "JSON payload passed directly to the function."
|
|
21556
|
+
}
|
|
21557
|
+
},
|
|
21558
|
+
required: ["functionName", "payload"]
|
|
21559
|
+
},
|
|
21560
|
+
request: {
|
|
21561
|
+
method: "POST",
|
|
21562
|
+
path: "/2015-03-31/functions/{functionName}/invocations",
|
|
21563
|
+
query: { Qualifier: "{qualifier}" },
|
|
21564
|
+
headers: {
|
|
21565
|
+
"X-Amz-Invocation-Type": "{invocationType}",
|
|
21566
|
+
"X-Amz-Log-Type": "{logType}",
|
|
21567
|
+
"X-Amz-Client-Context": "{clientContext}"
|
|
21568
|
+
},
|
|
21569
|
+
body: "{payload}"
|
|
21570
|
+
},
|
|
21571
|
+
cas: "none",
|
|
21572
|
+
externalEffect: true
|
|
21573
|
+
},
|
|
21574
|
+
{
|
|
21575
|
+
name: "functions.create",
|
|
21576
|
+
class: "mutation",
|
|
21577
|
+
description: "Create a Lambda function from an S3 object, inline zip, or ECR image.",
|
|
21578
|
+
parameters: {
|
|
21579
|
+
type: "object",
|
|
21580
|
+
properties: {
|
|
21581
|
+
functionName: { type: "string" },
|
|
21582
|
+
role: { type: "string", description: "Execution-role ARN." },
|
|
21583
|
+
code: {
|
|
21584
|
+
type: "object",
|
|
21585
|
+
description: "AWS FunctionCode shape: S3Bucket/S3Key/S3ObjectVersion, ZipFile, or ImageUri."
|
|
21586
|
+
},
|
|
21587
|
+
runtime: { type: "string" },
|
|
21588
|
+
handler: { type: "string" },
|
|
21589
|
+
description: { type: "string" },
|
|
21590
|
+
timeout: { type: "integer" },
|
|
21591
|
+
memorySize: { type: "integer" },
|
|
21592
|
+
publish: { type: "boolean" },
|
|
21593
|
+
packageType: { type: "string", enum: ["Zip", "Image"] },
|
|
21594
|
+
architectures: { type: "array", items: { type: "string" } },
|
|
21595
|
+
environment: { type: "object", description: "AWS Environment shape." },
|
|
21596
|
+
vpcConfig: { type: "object", description: "AWS VpcConfig shape." },
|
|
21597
|
+
layers: { type: "array", items: { type: "string" } },
|
|
21598
|
+
tags: { type: "object" },
|
|
21599
|
+
ephemeralStorage: { type: "object" },
|
|
21600
|
+
loggingConfig: { type: "object" }
|
|
21601
|
+
},
|
|
21602
|
+
required: ["functionName", "role", "code"]
|
|
21603
|
+
},
|
|
21604
|
+
request: {
|
|
21605
|
+
method: "POST",
|
|
21606
|
+
path: "/2015-03-31/functions",
|
|
21607
|
+
body: {
|
|
21608
|
+
FunctionName: "{functionName}",
|
|
21609
|
+
Role: "{role}",
|
|
21610
|
+
Code: "{code}",
|
|
21611
|
+
Runtime: "{runtime}",
|
|
21612
|
+
Handler: "{handler}",
|
|
21613
|
+
Description: "{description}",
|
|
21614
|
+
Timeout: "{timeout}",
|
|
21615
|
+
MemorySize: "{memorySize}",
|
|
21616
|
+
Publish: "{publish}",
|
|
21617
|
+
PackageType: "{packageType}",
|
|
21618
|
+
Architectures: "{architectures}",
|
|
21619
|
+
Environment: "{environment}",
|
|
21620
|
+
VpcConfig: "{vpcConfig}",
|
|
21621
|
+
Layers: "{layers}",
|
|
21622
|
+
Tags: "{tags}",
|
|
21623
|
+
EphemeralStorage: "{ephemeralStorage}",
|
|
21624
|
+
LoggingConfig: "{loggingConfig}"
|
|
21625
|
+
}
|
|
21626
|
+
},
|
|
21627
|
+
cas: "native-idempotency",
|
|
21628
|
+
externalEffect: true
|
|
21629
|
+
},
|
|
21630
|
+
{
|
|
21631
|
+
name: "functions.code.update",
|
|
21632
|
+
class: "mutation",
|
|
21633
|
+
description: "Replace the unpublished code for a Lambda function.",
|
|
21634
|
+
parameters: {
|
|
21635
|
+
type: "object",
|
|
21636
|
+
properties: {
|
|
21637
|
+
functionName: { type: "string" },
|
|
21638
|
+
s3Bucket: { type: "string" },
|
|
21639
|
+
s3Key: { type: "string" },
|
|
21640
|
+
s3ObjectVersion: { type: "string" },
|
|
21641
|
+
imageUri: { type: "string" },
|
|
21642
|
+
zipFile: { type: "string", description: "Base64-encoded zip bytes." },
|
|
21643
|
+
publish: { type: "boolean" },
|
|
21644
|
+
dryRun: { type: "boolean" },
|
|
21645
|
+
revisionId: { type: "string" },
|
|
21646
|
+
architectures: { type: "array", items: { type: "string" } }
|
|
21647
|
+
},
|
|
21648
|
+
required: ["functionName"]
|
|
21649
|
+
},
|
|
21650
|
+
request: {
|
|
21651
|
+
method: "PUT",
|
|
21652
|
+
path: "/2015-03-31/functions/{functionName}/code",
|
|
21653
|
+
body: {
|
|
21654
|
+
S3Bucket: "{s3Bucket}",
|
|
21655
|
+
S3Key: "{s3Key}",
|
|
21656
|
+
S3ObjectVersion: "{s3ObjectVersion}",
|
|
21657
|
+
ImageUri: "{imageUri}",
|
|
21658
|
+
ZipFile: "{zipFile}",
|
|
21659
|
+
Publish: "{publish}",
|
|
21660
|
+
DryRun: "{dryRun}",
|
|
21661
|
+
RevisionId: "{revisionId}",
|
|
21662
|
+
Architectures: "{architectures}"
|
|
21663
|
+
}
|
|
21664
|
+
},
|
|
21665
|
+
cas: "optimistic-read-verify",
|
|
21666
|
+
externalEffect: true
|
|
21667
|
+
},
|
|
21668
|
+
{
|
|
21669
|
+
name: "functions.configuration.update",
|
|
21670
|
+
class: "mutation",
|
|
21671
|
+
description: "Update the unpublished configuration for a Lambda function.",
|
|
21672
|
+
parameters: {
|
|
21673
|
+
type: "object",
|
|
21674
|
+
properties: {
|
|
21675
|
+
functionName: { type: "string" },
|
|
21676
|
+
role: { type: "string" },
|
|
21677
|
+
handler: { type: "string" },
|
|
21678
|
+
description: { type: "string" },
|
|
21679
|
+
timeout: { type: "integer" },
|
|
21680
|
+
memorySize: { type: "integer" },
|
|
21681
|
+
runtime: { type: "string" },
|
|
21682
|
+
environment: { type: "object" },
|
|
21683
|
+
layers: { type: "array", items: { type: "string" } },
|
|
21684
|
+
vpcConfig: { type: "object" },
|
|
21685
|
+
revisionId: { type: "string" },
|
|
21686
|
+
ephemeralStorage: { type: "object" },
|
|
21687
|
+
loggingConfig: { type: "object" }
|
|
21688
|
+
},
|
|
21689
|
+
required: ["functionName"]
|
|
21690
|
+
},
|
|
21691
|
+
request: {
|
|
21692
|
+
method: "PUT",
|
|
21693
|
+
path: "/2015-03-31/functions/{functionName}/configuration",
|
|
21694
|
+
body: {
|
|
21695
|
+
Role: "{role}",
|
|
21696
|
+
Handler: "{handler}",
|
|
21697
|
+
Description: "{description}",
|
|
21698
|
+
Timeout: "{timeout}",
|
|
21699
|
+
MemorySize: "{memorySize}",
|
|
21700
|
+
Runtime: "{runtime}",
|
|
21701
|
+
Environment: "{environment}",
|
|
21702
|
+
Layers: "{layers}",
|
|
21703
|
+
VpcConfig: "{vpcConfig}",
|
|
21704
|
+
RevisionId: "{revisionId}",
|
|
21705
|
+
EphemeralStorage: "{ephemeralStorage}",
|
|
21706
|
+
LoggingConfig: "{loggingConfig}"
|
|
21707
|
+
}
|
|
21708
|
+
},
|
|
21709
|
+
cas: "optimistic-read-verify",
|
|
21710
|
+
externalEffect: true
|
|
21711
|
+
},
|
|
21712
|
+
{
|
|
21713
|
+
name: "versions.publish",
|
|
21714
|
+
class: "mutation",
|
|
21715
|
+
description: "Publish an immutable version from the current function code and configuration.",
|
|
21716
|
+
parameters: {
|
|
21717
|
+
type: "object",
|
|
21718
|
+
properties: {
|
|
21719
|
+
functionName: { type: "string" },
|
|
21720
|
+
codeSha256: { type: "string" },
|
|
21721
|
+
description: { type: "string" },
|
|
21722
|
+
revisionId: { type: "string" }
|
|
21723
|
+
},
|
|
21724
|
+
required: ["functionName"]
|
|
21725
|
+
},
|
|
21726
|
+
request: {
|
|
21727
|
+
method: "POST",
|
|
21728
|
+
path: "/2015-03-31/functions/{functionName}/versions",
|
|
21729
|
+
body: {
|
|
21730
|
+
CodeSha256: "{codeSha256}",
|
|
21731
|
+
Description: "{description}",
|
|
21732
|
+
RevisionId: "{revisionId}"
|
|
21733
|
+
}
|
|
21734
|
+
},
|
|
21735
|
+
cas: "optimistic-read-verify",
|
|
21736
|
+
externalEffect: true
|
|
21737
|
+
},
|
|
21738
|
+
{
|
|
21739
|
+
name: "aliases.create",
|
|
21740
|
+
class: "mutation",
|
|
21741
|
+
description: "Create an alias that points to a published function version.",
|
|
21742
|
+
parameters: {
|
|
21743
|
+
type: "object",
|
|
21744
|
+
properties: {
|
|
21745
|
+
functionName: { type: "string" },
|
|
21746
|
+
name: { type: "string" },
|
|
21747
|
+
functionVersion: { type: "string" },
|
|
21748
|
+
description: { type: "string" },
|
|
21749
|
+
routingConfig: { type: "object" }
|
|
21750
|
+
},
|
|
21751
|
+
required: ["functionName", "name", "functionVersion"]
|
|
21752
|
+
},
|
|
21753
|
+
request: {
|
|
21754
|
+
method: "POST",
|
|
21755
|
+
path: "/2015-03-31/functions/{functionName}/aliases",
|
|
21756
|
+
body: {
|
|
21757
|
+
Name: "{name}",
|
|
21758
|
+
FunctionVersion: "{functionVersion}",
|
|
21759
|
+
Description: "{description}",
|
|
21760
|
+
RoutingConfig: "{routingConfig}"
|
|
21761
|
+
}
|
|
21762
|
+
},
|
|
21763
|
+
cas: "native-idempotency",
|
|
21764
|
+
externalEffect: true
|
|
21765
|
+
},
|
|
21766
|
+
{
|
|
21767
|
+
name: "aliases.update",
|
|
21768
|
+
class: "mutation",
|
|
21769
|
+
description: "Move or reconfigure an existing function alias.",
|
|
21770
|
+
parameters: {
|
|
21771
|
+
type: "object",
|
|
21772
|
+
properties: {
|
|
21773
|
+
functionName: { type: "string" },
|
|
21774
|
+
name: { type: "string" },
|
|
21775
|
+
functionVersion: { type: "string" },
|
|
21776
|
+
description: { type: "string" },
|
|
21777
|
+
routingConfig: { type: "object" },
|
|
21778
|
+
revisionId: { type: "string" }
|
|
21779
|
+
},
|
|
21780
|
+
required: ["functionName", "name"]
|
|
21781
|
+
},
|
|
21782
|
+
request: {
|
|
21783
|
+
method: "PUT",
|
|
21784
|
+
path: "/2015-03-31/functions/{functionName}/aliases/{name}",
|
|
21785
|
+
body: {
|
|
21786
|
+
FunctionVersion: "{functionVersion}",
|
|
21787
|
+
Description: "{description}",
|
|
21788
|
+
RoutingConfig: "{routingConfig}",
|
|
21789
|
+
RevisionId: "{revisionId}"
|
|
21790
|
+
}
|
|
21791
|
+
},
|
|
21792
|
+
cas: "optimistic-read-verify",
|
|
21793
|
+
externalEffect: true
|
|
21794
|
+
},
|
|
21795
|
+
{
|
|
21796
|
+
name: "aliases.delete",
|
|
21797
|
+
class: "mutation",
|
|
21798
|
+
description: "Delete a function alias without deleting the function version.",
|
|
21799
|
+
parameters: {
|
|
21800
|
+
type: "object",
|
|
21801
|
+
properties: {
|
|
21802
|
+
functionName: { type: "string" },
|
|
21803
|
+
name: { type: "string" }
|
|
21804
|
+
},
|
|
21805
|
+
required: ["functionName", "name"]
|
|
21806
|
+
},
|
|
21807
|
+
request: {
|
|
21808
|
+
method: "DELETE",
|
|
21809
|
+
path: "/2015-03-31/functions/{functionName}/aliases/{name}"
|
|
21810
|
+
},
|
|
21811
|
+
cas: "native-idempotency",
|
|
21812
|
+
externalEffect: true
|
|
21813
|
+
},
|
|
21814
|
+
{
|
|
21815
|
+
name: "functions.delete",
|
|
21816
|
+
class: "mutation",
|
|
21817
|
+
description: "Permanently delete a Lambda function or one published version.",
|
|
21818
|
+
parameters: {
|
|
21819
|
+
type: "object",
|
|
21820
|
+
properties: {
|
|
21821
|
+
functionName: { type: "string" },
|
|
21822
|
+
qualifier: { type: "string", description: "Version to delete. Omit to delete all versions." }
|
|
21823
|
+
},
|
|
21824
|
+
required: ["functionName"]
|
|
21825
|
+
},
|
|
21826
|
+
request: {
|
|
21827
|
+
method: "DELETE",
|
|
21828
|
+
path: "/2015-03-31/functions/{functionName}",
|
|
21829
|
+
query: { Qualifier: "{qualifier}" }
|
|
21830
|
+
},
|
|
21831
|
+
cas: "native-idempotency",
|
|
21832
|
+
externalEffect: true
|
|
21833
|
+
}
|
|
21834
|
+
]
|
|
21835
|
+
});
|
|
21836
|
+
|
|
20445
21837
|
// src/connectors/adapters/amazon-s3.ts
|
|
20446
21838
|
var amazonS3Connector = declarativeRestConnector({
|
|
20447
21839
|
kind: "amazon-s3",
|
|
@@ -23712,7 +25104,7 @@ function numberOrUndefined(value) {
|
|
|
23712
25104
|
}
|
|
23713
25105
|
|
|
23714
25106
|
// src/connectors/adapters/azure-event-grid.ts
|
|
23715
|
-
import { createHash as
|
|
25107
|
+
import { createHash as createHash4, timingSafeEqual } from "crypto";
|
|
23716
25108
|
var API_VERSION2 = "2018-01-01";
|
|
23717
25109
|
var MAX_BATCH_BYTES = 1024 * 1024;
|
|
23718
25110
|
var MAX_EVENTS = 5e3;
|
|
@@ -23781,8 +25173,8 @@ var azureEventGridConnector = {
|
|
|
23781
25173
|
}
|
|
23782
25174
|
const provided = headerValue(headers, "x-tangle-eventgrid-secret");
|
|
23783
25175
|
if (!provided) return { valid: false, reason: "Missing x-tangle-eventgrid-secret delivery header" };
|
|
23784
|
-
const expectedDigest =
|
|
23785
|
-
const providedDigest =
|
|
25176
|
+
const expectedDigest = createHash4("sha256").update(credentials.deliverySecret).digest();
|
|
25177
|
+
const providedDigest = createHash4("sha256").update(provided).digest();
|
|
23786
25178
|
return timingSafeEqual(expectedDigest, providedDigest) ? { valid: true } : { valid: false, reason: "Invalid x-tangle-eventgrid-secret delivery header" };
|
|
23787
25179
|
},
|
|
23788
25180
|
async handleInboundEvent({ rawBody }) {
|
|
@@ -23995,9 +25387,9 @@ function requiredString4(value, field) {
|
|
|
23995
25387
|
}
|
|
23996
25388
|
function isoDate(value, field) {
|
|
23997
25389
|
const parsed = requiredString4(value, field);
|
|
23998
|
-
const
|
|
23999
|
-
if (!Number.isFinite(
|
|
24000
|
-
return
|
|
25390
|
+
const date2 = new Date(parsed);
|
|
25391
|
+
if (!Number.isFinite(date2.getTime())) throw new Error(`${field} must be an ISO 8601 timestamp`);
|
|
25392
|
+
return date2.toISOString();
|
|
24001
25393
|
}
|
|
24002
25394
|
function requiredJsonValue(value, field) {
|
|
24003
25395
|
if (value === void 0) throw new Error(`${field} is required`);
|
|
@@ -24015,8 +25407,8 @@ function retryAfterMs3(value) {
|
|
|
24015
25407
|
if (!value) return 6e4;
|
|
24016
25408
|
const seconds = Number(value);
|
|
24017
25409
|
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
|
|
24018
|
-
const
|
|
24019
|
-
return Number.isFinite(
|
|
25410
|
+
const date2 = Date.parse(value);
|
|
25411
|
+
return Number.isFinite(date2) ? Math.max(0, date2 - Date.now()) : 6e4;
|
|
24020
25412
|
}
|
|
24021
25413
|
function isRecord(value) {
|
|
24022
25414
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -24573,8 +25965,8 @@ function retryAfterMs4(value) {
|
|
|
24573
25965
|
if (!value) return 6e4;
|
|
24574
25966
|
const seconds = Number(value);
|
|
24575
25967
|
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
|
|
24576
|
-
const
|
|
24577
|
-
return Number.isFinite(
|
|
25968
|
+
const date2 = Date.parse(value);
|
|
25969
|
+
return Number.isFinite(date2) ? Math.max(0, date2 - Date.now()) : 6e4;
|
|
24578
25970
|
}
|
|
24579
25971
|
function redactProviderText(value) {
|
|
24580
25972
|
return value.replace(/SharedAccessSignature\s+[^\s<]+/gi, "SharedAccessSignature [redacted]").replace(/SharedAccessKey=[^;\s<]+/gi, "SharedAccessKey=[redacted]");
|
|
@@ -26303,7 +27695,7 @@ var billplzConnector = declarativeRestConnector({
|
|
|
26303
27695
|
// src/connectors/adapters/cal-com.ts
|
|
26304
27696
|
var authorizeUrl = "https://app.cal.com/auth/oauth2/authorize";
|
|
26305
27697
|
var tokenUrl = "https://api.cal.com/v2/auth/oauth2/token";
|
|
26306
|
-
var
|
|
27698
|
+
var calComSpec = {
|
|
26307
27699
|
kind: "cal-com",
|
|
26308
27700
|
displayName: "Cal.com",
|
|
26309
27701
|
description: "Schedule, query, and cancel Cal.com bookings and read event types through the Platform v2 API.",
|
|
@@ -26320,8 +27712,9 @@ var calComConnector = declarativeRestConnector({
|
|
|
26320
27712
|
"SCHEDULE_READ",
|
|
26321
27713
|
"SCHEDULE_WRITE"
|
|
26322
27714
|
],
|
|
26323
|
-
|
|
26324
|
-
|
|
27715
|
+
pkce: "required",
|
|
27716
|
+
tokenClientAuthMethod: "none",
|
|
27717
|
+
clientIdEnv: "CALCOM_OAUTH_CLIENT_ID"
|
|
26325
27718
|
},
|
|
26326
27719
|
category: "calendar",
|
|
26327
27720
|
defaultConsistencyModel: "authoritative",
|
|
@@ -26642,7 +28035,100 @@ var calComConnector = declarativeRestConnector({
|
|
|
26642
28035
|
requiredScopes: ["EVENT_TYPE_READ"]
|
|
26643
28036
|
}
|
|
26644
28037
|
]
|
|
26645
|
-
}
|
|
28038
|
+
};
|
|
28039
|
+
var calComConnector = declarativeRestConnector(calComSpec);
|
|
28040
|
+
function calCom(options) {
|
|
28041
|
+
const adapter = declarativeRestConnector(calComSpec);
|
|
28042
|
+
const now = options.now ?? Date.now;
|
|
28043
|
+
const refreshes = /* @__PURE__ */ new Map();
|
|
28044
|
+
adapter.exchangeOAuth = async (input) => {
|
|
28045
|
+
const tokens = await exchangeAuthorizationCode({
|
|
28046
|
+
tokenUrl,
|
|
28047
|
+
clientId: options.clientId,
|
|
28048
|
+
tokenClientAuthMethod: "none",
|
|
28049
|
+
code: input.code,
|
|
28050
|
+
codeVerifier: input.codeVerifier,
|
|
28051
|
+
redirectUri: input.redirectUri,
|
|
28052
|
+
fetchImpl: options.fetchImpl
|
|
28053
|
+
});
|
|
28054
|
+
return {
|
|
28055
|
+
credentials: {
|
|
28056
|
+
kind: "oauth2",
|
|
28057
|
+
accessToken: tokens.accessToken,
|
|
28058
|
+
refreshToken: tokens.refreshToken,
|
|
28059
|
+
expiresAt: tokens.expiresIn ? now() + tokens.expiresIn * 1e3 : void 0
|
|
28060
|
+
},
|
|
28061
|
+
scopes: tokens.scope?.split(/[\s,]+/).filter(Boolean) ?? calComSpec.auth.scopes,
|
|
28062
|
+
metadata: {}
|
|
28063
|
+
};
|
|
28064
|
+
};
|
|
28065
|
+
adapter.refreshToken = async (credentials) => {
|
|
28066
|
+
if (credentials.kind !== "oauth2" || !credentials.refreshToken) {
|
|
28067
|
+
throw new Error("cal-com.refreshToken: missing refresh token");
|
|
28068
|
+
}
|
|
28069
|
+
const refreshed = await refreshAccessToken({
|
|
28070
|
+
tokenUrl,
|
|
28071
|
+
clientId: options.clientId,
|
|
28072
|
+
tokenClientAuthMethod: "none",
|
|
28073
|
+
refreshToken: credentials.refreshToken,
|
|
28074
|
+
fetchImpl: options.fetchImpl
|
|
28075
|
+
});
|
|
28076
|
+
return {
|
|
28077
|
+
kind: "oauth2",
|
|
28078
|
+
accessToken: refreshed.accessToken,
|
|
28079
|
+
refreshToken: refreshed.refreshToken ?? credentials.refreshToken,
|
|
28080
|
+
expiresAt: refreshed.expiresIn ? now() + refreshed.expiresIn * 1e3 : void 0
|
|
28081
|
+
};
|
|
28082
|
+
};
|
|
28083
|
+
const executeRead2 = adapter.executeRead?.bind(adapter);
|
|
28084
|
+
const executeMutation = adapter.executeMutation?.bind(adapter);
|
|
28085
|
+
if (executeRead2) {
|
|
28086
|
+
adapter.executeRead = async (invocation) => executeRead2(
|
|
28087
|
+
await withFreshCalComCredentials(invocation, adapter, refreshes, now)
|
|
28088
|
+
);
|
|
28089
|
+
}
|
|
28090
|
+
if (executeMutation) {
|
|
28091
|
+
adapter.executeMutation = async (invocation) => executeMutation(
|
|
28092
|
+
await withFreshCalComCredentials(invocation, adapter, refreshes, now)
|
|
28093
|
+
);
|
|
28094
|
+
}
|
|
28095
|
+
return adapter;
|
|
28096
|
+
}
|
|
28097
|
+
async function withFreshCalComCredentials(invocation, adapter, refreshes, now) {
|
|
28098
|
+
const credentials = invocation.source.credentials;
|
|
28099
|
+
if (credentials.kind !== "oauth2") {
|
|
28100
|
+
throw new CredentialsExpired("Cal.com requires OAuth2 credentials.", invocation.source.id);
|
|
28101
|
+
}
|
|
28102
|
+
if (!credentials.expiresAt || credentials.expiresAt > now() + 6e4) {
|
|
28103
|
+
return invocation;
|
|
28104
|
+
}
|
|
28105
|
+
if (!credentials.refreshToken || !adapter.refreshToken) {
|
|
28106
|
+
throw new CredentialsExpired(
|
|
28107
|
+
"Cal.com access token expired and no refresh token is available.",
|
|
28108
|
+
invocation.source.id
|
|
28109
|
+
);
|
|
28110
|
+
}
|
|
28111
|
+
let refresh = refreshes.get(invocation.source.id);
|
|
28112
|
+
if (!refresh) {
|
|
28113
|
+
refresh = adapter.refreshToken(credentials);
|
|
28114
|
+
refreshes.set(invocation.source.id, refresh);
|
|
28115
|
+
const clear = () => {
|
|
28116
|
+
if (refreshes.get(invocation.source.id) === refresh) {
|
|
28117
|
+
refreshes.delete(invocation.source.id);
|
|
28118
|
+
}
|
|
28119
|
+
};
|
|
28120
|
+
void refresh.then(clear, clear);
|
|
28121
|
+
}
|
|
28122
|
+
const rotated = await refresh;
|
|
28123
|
+
await invocation.onCredentialsRotated?.(rotated);
|
|
28124
|
+
return {
|
|
28125
|
+
...invocation,
|
|
28126
|
+
source: {
|
|
28127
|
+
...invocation.source,
|
|
28128
|
+
credentials: rotated
|
|
28129
|
+
}
|
|
28130
|
+
};
|
|
28131
|
+
}
|
|
26646
28132
|
|
|
26647
28133
|
// src/connectors/adapters/calendly.ts
|
|
26648
28134
|
var calendlyConnector = declarativeRestConnector({
|
|
@@ -27840,6 +29326,273 @@ var clickupConnector = declarativeRestConnector({
|
|
|
27840
29326
|
]
|
|
27841
29327
|
});
|
|
27842
29328
|
|
|
29329
|
+
// src/connectors/adapters/cloudflare.ts
|
|
29330
|
+
var pagination = {
|
|
29331
|
+
page: { type: "integer", minimum: 1 },
|
|
29332
|
+
perPage: { type: "integer", minimum: 5, maximum: 50 }
|
|
29333
|
+
};
|
|
29334
|
+
var paginationQuery = { page: "{page}", per_page: "{perPage}" };
|
|
29335
|
+
var zoneId = {
|
|
29336
|
+
zoneId: { type: "string", minLength: 1, description: "Cloudflare zone identifier." }
|
|
29337
|
+
};
|
|
29338
|
+
var recordId = {
|
|
29339
|
+
recordId: { type: "string", minLength: 1, description: "Cloudflare DNS record identifier." }
|
|
29340
|
+
};
|
|
29341
|
+
var recordFields = {
|
|
29342
|
+
type: {
|
|
29343
|
+
type: "string",
|
|
29344
|
+
enum: [
|
|
29345
|
+
"A",
|
|
29346
|
+
"AAAA",
|
|
29347
|
+
"CAA",
|
|
29348
|
+
"CERT",
|
|
29349
|
+
"CNAME",
|
|
29350
|
+
"DNSKEY",
|
|
29351
|
+
"DS",
|
|
29352
|
+
"HTTPS",
|
|
29353
|
+
"LOC",
|
|
29354
|
+
"MX",
|
|
29355
|
+
"NAPTR",
|
|
29356
|
+
"NS",
|
|
29357
|
+
"OPENPGPKEY",
|
|
29358
|
+
"PTR",
|
|
29359
|
+
"SMIMEA",
|
|
29360
|
+
"SRV",
|
|
29361
|
+
"SSHFP",
|
|
29362
|
+
"SVCB",
|
|
29363
|
+
"TLSA",
|
|
29364
|
+
"TXT",
|
|
29365
|
+
"URI"
|
|
29366
|
+
]
|
|
29367
|
+
},
|
|
29368
|
+
name: { type: "string", minLength: 1, description: "Complete DNS record name." },
|
|
29369
|
+
content: { type: "string", description: "Provider-native record content." },
|
|
29370
|
+
ttl: {
|
|
29371
|
+
type: "integer",
|
|
29372
|
+
minimum: 1,
|
|
29373
|
+
maximum: 86400,
|
|
29374
|
+
description: "TTL in seconds. Use 1 for automatic."
|
|
29375
|
+
},
|
|
29376
|
+
proxied: { type: "boolean" },
|
|
29377
|
+
priority: { type: "integer" },
|
|
29378
|
+
comment: { type: ["string", "null"] },
|
|
29379
|
+
tags: { type: "array", items: { type: "string" } },
|
|
29380
|
+
data: { type: "object", description: "Provider-native structured data for records such as SRV or CAA." },
|
|
29381
|
+
settings: { type: "object", description: "Provider-native DNS record settings." }
|
|
29382
|
+
};
|
|
29383
|
+
var cloudflareConnector = declarativeRestConnector({
|
|
29384
|
+
kind: "cloudflare",
|
|
29385
|
+
displayName: "Cloudflare",
|
|
29386
|
+
description: "Inspect Cloudflare accounts and zones, then manage DNS records with a dedicated scoped API token.",
|
|
29387
|
+
auth: {
|
|
29388
|
+
kind: "api-key",
|
|
29389
|
+
hint: "Create a dedicated Cloudflare API token for Tangle Integration Hub. Grant Account Settings Read, Zone Read, Zone Settings Read, and DNS Read or DNS Edit only on selected resources. Never reuse a Tangle deployment, Workers, Terraform, or infrastructure token."
|
|
29390
|
+
},
|
|
29391
|
+
category: "other",
|
|
29392
|
+
defaultConsistencyModel: "authoritative",
|
|
29393
|
+
baseUrl: "https://api.cloudflare.com/client/v4",
|
|
29394
|
+
credentialPlacement: { kind: "bearer" },
|
|
29395
|
+
test: {
|
|
29396
|
+
method: "GET",
|
|
29397
|
+
path: "/user/tokens/verify",
|
|
29398
|
+
expectResponse: [
|
|
29399
|
+
{ path: "success", equals: true },
|
|
29400
|
+
{ path: "result.status", equals: "active" }
|
|
29401
|
+
]
|
|
29402
|
+
},
|
|
29403
|
+
capabilities: [
|
|
29404
|
+
{
|
|
29405
|
+
name: "auth.verify",
|
|
29406
|
+
class: "read",
|
|
29407
|
+
description: "Verify that the current API token is valid and active.",
|
|
29408
|
+
parameters: { type: "object", properties: {} },
|
|
29409
|
+
request: { method: "GET", path: "/user/tokens/verify" }
|
|
29410
|
+
},
|
|
29411
|
+
{
|
|
29412
|
+
name: "accounts.get",
|
|
29413
|
+
class: "read",
|
|
29414
|
+
description: "Read one Cloudflare account and its settings.",
|
|
29415
|
+
parameters: {
|
|
29416
|
+
type: "object",
|
|
29417
|
+
properties: { accountId: { type: "string", minLength: 1 } },
|
|
29418
|
+
required: ["accountId"]
|
|
29419
|
+
},
|
|
29420
|
+
request: { method: "GET", path: "/accounts/{accountId}" }
|
|
29421
|
+
},
|
|
29422
|
+
{
|
|
29423
|
+
name: "zones.list",
|
|
29424
|
+
class: "read",
|
|
29425
|
+
description: "List or filter zones by account, domain, status, and type.",
|
|
29426
|
+
parameters: {
|
|
29427
|
+
type: "object",
|
|
29428
|
+
properties: {
|
|
29429
|
+
...pagination,
|
|
29430
|
+
accountId: { type: "string" },
|
|
29431
|
+
name: { type: "string" },
|
|
29432
|
+
status: { type: "string", enum: ["initializing", "pending", "active", "moved"] },
|
|
29433
|
+
type: { type: "string", description: "Comma-separated zone types." },
|
|
29434
|
+
match: { type: "string", enum: ["any", "all"] },
|
|
29435
|
+
order: { type: "string", enum: ["name", "status", "account.id", "account.name", "plan.id"] },
|
|
29436
|
+
direction: { type: "string", enum: ["asc", "desc"] }
|
|
29437
|
+
}
|
|
29438
|
+
},
|
|
29439
|
+
request: {
|
|
29440
|
+
method: "GET",
|
|
29441
|
+
path: "/zones",
|
|
29442
|
+
query: {
|
|
29443
|
+
...paginationQuery,
|
|
29444
|
+
"account.id": "{accountId}",
|
|
29445
|
+
name: "{name}",
|
|
29446
|
+
status: "{status}",
|
|
29447
|
+
type: "{type}",
|
|
29448
|
+
match: "{match}",
|
|
29449
|
+
order: "{order}",
|
|
29450
|
+
direction: "{direction}"
|
|
29451
|
+
}
|
|
29452
|
+
}
|
|
29453
|
+
},
|
|
29454
|
+
{
|
|
29455
|
+
name: "zones.get",
|
|
29456
|
+
class: "read",
|
|
29457
|
+
description: "Read one zone with status, nameservers, plan, and ownership metadata.",
|
|
29458
|
+
parameters: { type: "object", properties: zoneId, required: ["zoneId"] },
|
|
29459
|
+
request: { method: "GET", path: "/zones/{zoneId}" }
|
|
29460
|
+
},
|
|
29461
|
+
{
|
|
29462
|
+
name: "zones.settings.list",
|
|
29463
|
+
class: "read",
|
|
29464
|
+
description: "List all settings for one zone.",
|
|
29465
|
+
parameters: { type: "object", properties: zoneId, required: ["zoneId"] },
|
|
29466
|
+
request: { method: "GET", path: "/zones/{zoneId}/settings" }
|
|
29467
|
+
},
|
|
29468
|
+
{
|
|
29469
|
+
name: "zones.settings.get",
|
|
29470
|
+
class: "read",
|
|
29471
|
+
description: "Read one setting for a zone.",
|
|
29472
|
+
parameters: {
|
|
29473
|
+
type: "object",
|
|
29474
|
+
properties: {
|
|
29475
|
+
...zoneId,
|
|
29476
|
+
settingId: { type: "string", minLength: 1 }
|
|
29477
|
+
},
|
|
29478
|
+
required: ["zoneId", "settingId"]
|
|
29479
|
+
},
|
|
29480
|
+
request: { method: "GET", path: "/zones/{zoneId}/settings/{settingId}" }
|
|
29481
|
+
},
|
|
29482
|
+
{
|
|
29483
|
+
name: "dns.records.list",
|
|
29484
|
+
class: "read",
|
|
29485
|
+
description: "List and filter DNS records in one zone.",
|
|
29486
|
+
parameters: {
|
|
29487
|
+
type: "object",
|
|
29488
|
+
properties: {
|
|
29489
|
+
...zoneId,
|
|
29490
|
+
...pagination,
|
|
29491
|
+
type: { type: "string" },
|
|
29492
|
+
name: { type: "string", description: "Exact record name." },
|
|
29493
|
+
content: { type: "string", description: "Exact record content." },
|
|
29494
|
+
proxied: { type: "boolean" },
|
|
29495
|
+
match: { type: "string", enum: ["any", "all"] },
|
|
29496
|
+
order: { type: "string", enum: ["type", "name", "content", "ttl", "proxied"] },
|
|
29497
|
+
direction: { type: "string", enum: ["asc", "desc"] }
|
|
29498
|
+
},
|
|
29499
|
+
required: ["zoneId"]
|
|
29500
|
+
},
|
|
29501
|
+
request: {
|
|
29502
|
+
method: "GET",
|
|
29503
|
+
path: "/zones/{zoneId}/dns_records",
|
|
29504
|
+
query: {
|
|
29505
|
+
...paginationQuery,
|
|
29506
|
+
type: "{type}",
|
|
29507
|
+
"name.exact": "{name}",
|
|
29508
|
+
"content.exact": "{content}",
|
|
29509
|
+
proxied: "{proxied}",
|
|
29510
|
+
match: "{match}",
|
|
29511
|
+
order: "{order}",
|
|
29512
|
+
direction: "{direction}"
|
|
29513
|
+
}
|
|
29514
|
+
}
|
|
29515
|
+
},
|
|
29516
|
+
{
|
|
29517
|
+
name: "dns.records.get",
|
|
29518
|
+
class: "read",
|
|
29519
|
+
description: "Read one DNS record by zone and record ID.",
|
|
29520
|
+
parameters: {
|
|
29521
|
+
type: "object",
|
|
29522
|
+
properties: { ...zoneId, ...recordId },
|
|
29523
|
+
required: ["zoneId", "recordId"]
|
|
29524
|
+
},
|
|
29525
|
+
request: { method: "GET", path: "/zones/{zoneId}/dns_records/{recordId}" }
|
|
29526
|
+
},
|
|
29527
|
+
{
|
|
29528
|
+
name: "dns.records.export",
|
|
29529
|
+
class: "read",
|
|
29530
|
+
description: "Export the current zone records as a BIND zone file before a change.",
|
|
29531
|
+
parameters: { type: "object", properties: zoneId, required: ["zoneId"] },
|
|
29532
|
+
request: { method: "GET", path: "/zones/{zoneId}/dns_records/export" }
|
|
29533
|
+
},
|
|
29534
|
+
{
|
|
29535
|
+
name: "dns.records.create",
|
|
29536
|
+
class: "mutation",
|
|
29537
|
+
description: "Create one DNS record in a selected zone.",
|
|
29538
|
+
parameters: {
|
|
29539
|
+
type: "object",
|
|
29540
|
+
properties: {
|
|
29541
|
+
...zoneId,
|
|
29542
|
+
record: {
|
|
29543
|
+
type: "object",
|
|
29544
|
+
properties: recordFields,
|
|
29545
|
+
required: ["type", "name"],
|
|
29546
|
+
additionalProperties: false
|
|
29547
|
+
}
|
|
29548
|
+
},
|
|
29549
|
+
required: ["zoneId", "record"]
|
|
29550
|
+
},
|
|
29551
|
+
request: { method: "POST", path: "/zones/{zoneId}/dns_records", body: "{record}" },
|
|
29552
|
+
cas: "none",
|
|
29553
|
+
externalEffect: true
|
|
29554
|
+
},
|
|
29555
|
+
{
|
|
29556
|
+
name: "dns.records.update",
|
|
29557
|
+
class: "mutation",
|
|
29558
|
+
description: "Partially update one DNS record.",
|
|
29559
|
+
parameters: {
|
|
29560
|
+
type: "object",
|
|
29561
|
+
properties: {
|
|
29562
|
+
...zoneId,
|
|
29563
|
+
...recordId,
|
|
29564
|
+
changes: {
|
|
29565
|
+
type: "object",
|
|
29566
|
+
properties: recordFields,
|
|
29567
|
+
additionalProperties: false
|
|
29568
|
+
}
|
|
29569
|
+
},
|
|
29570
|
+
required: ["zoneId", "recordId", "changes"]
|
|
29571
|
+
},
|
|
29572
|
+
request: {
|
|
29573
|
+
method: "PATCH",
|
|
29574
|
+
path: "/zones/{zoneId}/dns_records/{recordId}",
|
|
29575
|
+
body: "{changes}"
|
|
29576
|
+
},
|
|
29577
|
+
cas: "optimistic-read-verify",
|
|
29578
|
+
externalEffect: true
|
|
29579
|
+
},
|
|
29580
|
+
{
|
|
29581
|
+
name: "dns.records.delete",
|
|
29582
|
+
class: "mutation",
|
|
29583
|
+
description: "Permanently delete one DNS record.",
|
|
29584
|
+
parameters: {
|
|
29585
|
+
type: "object",
|
|
29586
|
+
properties: { ...zoneId, ...recordId },
|
|
29587
|
+
required: ["zoneId", "recordId"]
|
|
29588
|
+
},
|
|
29589
|
+
request: { method: "DELETE", path: "/zones/{zoneId}/dns_records/{recordId}" },
|
|
29590
|
+
cas: "optimistic-read-verify",
|
|
29591
|
+
externalEffect: true
|
|
29592
|
+
}
|
|
29593
|
+
]
|
|
29594
|
+
});
|
|
29595
|
+
|
|
27843
29596
|
// src/connectors/adapters/cloudinary.ts
|
|
27844
29597
|
var cloudinaryConnector = declarativeRestConnector({
|
|
27845
29598
|
kind: "cloudinary",
|
|
@@ -36164,134 +37917,6 @@ var frontConnector = declarativeRestConnector({
|
|
|
36164
37917
|
]
|
|
36165
37918
|
});
|
|
36166
37919
|
|
|
36167
|
-
// src/connectors/oauth.ts
|
|
36168
|
-
import { createHash as createHash4, randomBytes } from "crypto";
|
|
36169
|
-
var PENDING_TTL_MS = 10 * 60 * 1e3;
|
|
36170
|
-
var InMemoryOAuthFlowStore = class {
|
|
36171
|
-
pendingFlows = /* @__PURE__ */ new Map();
|
|
36172
|
-
put(state, flow) {
|
|
36173
|
-
this.pendingFlows.set(state, flow);
|
|
36174
|
-
}
|
|
36175
|
-
consume(state) {
|
|
36176
|
-
const flow = this.pendingFlows.get(state);
|
|
36177
|
-
this.pendingFlows.delete(state);
|
|
36178
|
-
if (!flow || flow.expiresAt <= Date.now()) return void 0;
|
|
36179
|
-
return flow;
|
|
36180
|
-
}
|
|
36181
|
-
sweep(now) {
|
|
36182
|
-
for (const [k, v] of this.pendingFlows) {
|
|
36183
|
-
if (v.expiresAt <= now) this.pendingFlows.delete(k);
|
|
36184
|
-
}
|
|
36185
|
-
}
|
|
36186
|
-
clear() {
|
|
36187
|
-
this.pendingFlows.clear();
|
|
36188
|
-
}
|
|
36189
|
-
};
|
|
36190
|
-
var defaultFlowStore = new InMemoryOAuthFlowStore();
|
|
36191
|
-
function startOAuthFlow(input) {
|
|
36192
|
-
const store = input.store ?? defaultFlowStore;
|
|
36193
|
-
const now = input.now ?? Date.now();
|
|
36194
|
-
store.sweep?.(now);
|
|
36195
|
-
const codeVerifier = base64Url(randomBytes(48));
|
|
36196
|
-
const codeChallenge = base64Url(createHash4("sha256").update(codeVerifier).digest());
|
|
36197
|
-
const state = base64Url(randomBytes(24));
|
|
36198
|
-
store.put(state, {
|
|
36199
|
-
codeVerifier,
|
|
36200
|
-
state,
|
|
36201
|
-
projectId: input.projectId,
|
|
36202
|
-
kind: input.kind,
|
|
36203
|
-
label: input.label,
|
|
36204
|
-
redirectUri: input.redirectUri,
|
|
36205
|
-
expiresAt: now + PENDING_TTL_MS
|
|
36206
|
-
});
|
|
36207
|
-
const url = new URL(input.authorizationUrl);
|
|
36208
|
-
url.searchParams.set("response_type", "code");
|
|
36209
|
-
url.searchParams.set("client_id", input.clientId);
|
|
36210
|
-
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
36211
|
-
url.searchParams.set("scope", input.scopes.join(input.scopeSeparator ?? " "));
|
|
36212
|
-
url.searchParams.set("state", state);
|
|
36213
|
-
url.searchParams.set("code_challenge", codeChallenge);
|
|
36214
|
-
url.searchParams.set("code_challenge_method", "S256");
|
|
36215
|
-
if (input.extraAuthParams) {
|
|
36216
|
-
for (const [k, v] of Object.entries(input.extraAuthParams)) {
|
|
36217
|
-
url.searchParams.set(k, v);
|
|
36218
|
-
}
|
|
36219
|
-
}
|
|
36220
|
-
return { authorizationUrl: url.toString(), state };
|
|
36221
|
-
}
|
|
36222
|
-
async function consumePendingFlow(state, store = defaultFlowStore) {
|
|
36223
|
-
await store.sweep?.(Date.now());
|
|
36224
|
-
const flow = await store.consume(state);
|
|
36225
|
-
if (!flow) {
|
|
36226
|
-
throw new Error("Unknown or expired OAuth state: possible CSRF, replay, or stale flow");
|
|
36227
|
-
}
|
|
36228
|
-
return flow;
|
|
36229
|
-
}
|
|
36230
|
-
async function exchangeAuthorizationCode(input) {
|
|
36231
|
-
const body = new URLSearchParams({
|
|
36232
|
-
grant_type: "authorization_code",
|
|
36233
|
-
client_id: input.clientId,
|
|
36234
|
-
client_secret: input.clientSecret,
|
|
36235
|
-
code: input.code,
|
|
36236
|
-
redirect_uri: input.redirectUri,
|
|
36237
|
-
code_verifier: input.codeVerifier
|
|
36238
|
-
});
|
|
36239
|
-
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
36240
|
-
method: "POST",
|
|
36241
|
-
headers: { "content-type": "application/x-www-form-urlencoded", accept: "application/json" },
|
|
36242
|
-
body,
|
|
36243
|
-
signal: input.signal
|
|
36244
|
-
});
|
|
36245
|
-
if (!res.ok) {
|
|
36246
|
-
const text = await res.text().catch(() => "");
|
|
36247
|
-
throw new Error(`OAuth token exchange failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
36248
|
-
}
|
|
36249
|
-
const json = await res.json();
|
|
36250
|
-
return {
|
|
36251
|
-
accessToken: json.access_token,
|
|
36252
|
-
refreshToken: json.refresh_token,
|
|
36253
|
-
expiresIn: json.expires_in,
|
|
36254
|
-
scope: json.scope,
|
|
36255
|
-
tokenType: json.token_type,
|
|
36256
|
-
idToken: json.id_token
|
|
36257
|
-
};
|
|
36258
|
-
}
|
|
36259
|
-
async function refreshAccessToken(input) {
|
|
36260
|
-
const body = new URLSearchParams({
|
|
36261
|
-
grant_type: "refresh_token",
|
|
36262
|
-
client_id: input.clientId,
|
|
36263
|
-
client_secret: input.clientSecret,
|
|
36264
|
-
refresh_token: input.refreshToken
|
|
36265
|
-
});
|
|
36266
|
-
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
36267
|
-
method: "POST",
|
|
36268
|
-
headers: { "content-type": "application/x-www-form-urlencoded", accept: "application/json" },
|
|
36269
|
-
body,
|
|
36270
|
-
signal: input.signal
|
|
36271
|
-
});
|
|
36272
|
-
if (!res.ok) {
|
|
36273
|
-
const text = await res.text().catch(() => "");
|
|
36274
|
-
throw new Error(`OAuth refresh failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
36275
|
-
}
|
|
36276
|
-
const json = await res.json();
|
|
36277
|
-
return {
|
|
36278
|
-
accessToken: json.access_token,
|
|
36279
|
-
// Some providers omit refresh_token on refresh — keep the previous one
|
|
36280
|
-
// in that case (caller passes through if undefined).
|
|
36281
|
-
refreshToken: json.refresh_token,
|
|
36282
|
-
expiresIn: json.expires_in,
|
|
36283
|
-
scope: json.scope,
|
|
36284
|
-
tokenType: json.token_type,
|
|
36285
|
-
idToken: json.id_token
|
|
36286
|
-
};
|
|
36287
|
-
}
|
|
36288
|
-
function base64Url(buf) {
|
|
36289
|
-
return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
36290
|
-
}
|
|
36291
|
-
function _resetPendingFlowsForTests() {
|
|
36292
|
-
defaultFlowStore.clear?.();
|
|
36293
|
-
}
|
|
36294
|
-
|
|
36295
37920
|
// src/connectors/adapters/google-errors.ts
|
|
36296
37921
|
var AUTH_REASONS = /* @__PURE__ */ new Set([
|
|
36297
37922
|
"autherror",
|
|
@@ -38527,13 +40152,13 @@ var googlePubSubConnector = {
|
|
|
38527
40152
|
let data4;
|
|
38528
40153
|
switch (inv.capabilityName) {
|
|
38529
40154
|
case "topics.list":
|
|
38530
|
-
data4 = await pubSubRequest(credentials, inv, "GET", projectPath(credentials, "topics"),
|
|
40155
|
+
data4 = await pubSubRequest(credentials, inv, "GET", projectPath(credentials, "topics"), pagination2(inv.args));
|
|
38531
40156
|
break;
|
|
38532
40157
|
case "topics.get":
|
|
38533
40158
|
data4 = await pubSubRequest(credentials, inv, "GET", topicPath(credentials, inv.args.topic));
|
|
38534
40159
|
break;
|
|
38535
40160
|
case "subscriptions.list":
|
|
38536
|
-
data4 = await pubSubRequest(credentials, inv, "GET", projectPath(credentials, "subscriptions"),
|
|
40161
|
+
data4 = await pubSubRequest(credentials, inv, "GET", projectPath(credentials, "subscriptions"), pagination2(inv.args));
|
|
38537
40162
|
break;
|
|
38538
40163
|
case "subscriptions.get":
|
|
38539
40164
|
data4 = await pubSubRequest(credentials, inv, "GET", subscriptionPath(credentials, inv.args.subscription));
|
|
@@ -38817,7 +40442,7 @@ function resourceId(value, field) {
|
|
|
38817
40442
|
}
|
|
38818
40443
|
return id2;
|
|
38819
40444
|
}
|
|
38820
|
-
function
|
|
40445
|
+
function pagination2(args) {
|
|
38821
40446
|
const query2 = new URLSearchParams();
|
|
38822
40447
|
if (args.pageSize !== void 0) query2.set("pageSize", String(boundedInteger2(args.pageSize, "pageSize", 1, 1e3)));
|
|
38823
40448
|
if (args.pageToken !== void 0) query2.set("pageToken", requiredString6(args.pageToken, "pageToken"));
|
|
@@ -38969,8 +40594,8 @@ function retryAfterMs5(value) {
|
|
|
38969
40594
|
if (!value) return 6e4;
|
|
38970
40595
|
const seconds = Number(value);
|
|
38971
40596
|
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
|
|
38972
|
-
const
|
|
38973
|
-
return Number.isFinite(
|
|
40597
|
+
const date2 = Date.parse(value);
|
|
40598
|
+
return Number.isFinite(date2) ? Math.max(0, date2 - Date.now()) : 6e4;
|
|
38974
40599
|
}
|
|
38975
40600
|
function isRecord3(value) {
|
|
38976
40601
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -41903,25 +43528,25 @@ async function updateRow(inv, accessToken4, timeoutMs) {
|
|
|
41903
43528
|
const meta = readSheetMeta(inv.source.metadata);
|
|
41904
43529
|
const { rowKey, patch, expectedFingerprint } = inv.args;
|
|
41905
43530
|
const rows = await fetchAllRows(accessToken4, meta);
|
|
41906
|
-
const
|
|
41907
|
-
if (!
|
|
43531
|
+
const target2 = rows.find((r) => normalizeKey(r.values[meta.keyColumn]) === normalizeKey(rowKey));
|
|
43532
|
+
if (!target2) {
|
|
41908
43533
|
throw new ResourceContention(
|
|
41909
43534
|
`row with key "${rowKey}" not found`,
|
|
41910
43535
|
[],
|
|
41911
43536
|
{ availableRows: rows.length }
|
|
41912
43537
|
);
|
|
41913
43538
|
}
|
|
41914
|
-
if (expectedFingerprint && expectedFingerprint !==
|
|
43539
|
+
if (expectedFingerprint && expectedFingerprint !== target2.fingerprint) {
|
|
41915
43540
|
throw new ResourceContention(
|
|
41916
43541
|
`row "${rowKey}" was modified since the agent last read it; re-read and try again`,
|
|
41917
43542
|
[],
|
|
41918
|
-
{ current:
|
|
43543
|
+
{ current: target2.values, currentFingerprint: target2.fingerprint }
|
|
41919
43544
|
);
|
|
41920
43545
|
}
|
|
41921
43546
|
const updatedValues = meta.headers.map(
|
|
41922
|
-
(h) => h in patch ? String(patch[h]) :
|
|
43547
|
+
(h) => h in patch ? String(patch[h]) : target2.values[h] ?? ""
|
|
41923
43548
|
);
|
|
41924
|
-
const range = `${meta.sheetName}!A${
|
|
43549
|
+
const range = `${meta.sheetName}!A${target2.rowIndex + 1}:${columnIndexToLetter(meta.headers.length - 1)}${target2.rowIndex + 1}`;
|
|
41925
43550
|
const url = `https://sheets.googleapis.com/v4/spreadsheets/${encodeURIComponent(meta.spreadsheetId)}/values/${encodeURIComponent(range)}?valueInputOption=USER_ENTERED`;
|
|
41926
43551
|
const res = await fetch(url, {
|
|
41927
43552
|
method: "PUT",
|
|
@@ -44534,9 +46159,9 @@ function parseRetryAfterMs(header2) {
|
|
|
44534
46159
|
if (!header2) return 1e3;
|
|
44535
46160
|
const seconds = Number(header2);
|
|
44536
46161
|
if (Number.isFinite(seconds) && seconds >= 0) return Math.floor(seconds * 1e3);
|
|
44537
|
-
const
|
|
44538
|
-
if (!Number.isFinite(
|
|
44539
|
-
return Math.max(0,
|
|
46162
|
+
const date2 = Date.parse(header2);
|
|
46163
|
+
if (!Number.isFinite(date2)) return 1e3;
|
|
46164
|
+
return Math.max(0, date2 - Date.now());
|
|
44540
46165
|
}
|
|
44541
46166
|
function stringify2(value) {
|
|
44542
46167
|
if (typeof value === "string") return value;
|
|
@@ -49683,7 +51308,7 @@ function microsoftCalendar(opts) {
|
|
|
49683
51308
|
return adapter;
|
|
49684
51309
|
}
|
|
49685
51310
|
async function getScheduleBusy(input) {
|
|
49686
|
-
const
|
|
51311
|
+
const target2 = input.userPrincipal === "me" ? "me" : input.userPrincipal;
|
|
49687
51312
|
const url = "https://graph.microsoft.com/v1.0/me/calendar/getSchedule";
|
|
49688
51313
|
const res = await fetch(url, {
|
|
49689
51314
|
method: "POST",
|
|
@@ -49692,7 +51317,7 @@ async function getScheduleBusy(input) {
|
|
|
49692
51317
|
"content-type": "application/json"
|
|
49693
51318
|
},
|
|
49694
51319
|
body: JSON.stringify({
|
|
49695
|
-
schedules: [
|
|
51320
|
+
schedules: [target2],
|
|
49696
51321
|
startTime: { dateTime: input.timeMin, timeZone: "UTC" },
|
|
49697
51322
|
endTime: { dateTime: input.timeMax, timeZone: "UTC" },
|
|
49698
51323
|
availabilityViewInterval: 30
|
|
@@ -51262,13 +52887,11 @@ function microsoftTeams(opts) {
|
|
|
51262
52887
|
async test(source) {
|
|
51263
52888
|
try {
|
|
51264
52889
|
const accessToken4 = await ensureFreshAccessToken11(source.credentials, clientId, clientSecret);
|
|
51265
|
-
const res = await fetch(`${GRAPH2}/me
|
|
52890
|
+
const res = await fetch(`${GRAPH2}/me/joinedTeams`, {
|
|
51266
52891
|
headers: { authorization: `Bearer ${accessToken4}` },
|
|
51267
52892
|
signal: AbortSignal.timeout(8e3)
|
|
51268
52893
|
});
|
|
51269
|
-
if (res.status === 401 || res.status === 403)
|
|
51270
|
-
return { ok: false, reason: `Microsoft rejected token (${res.status}) \u2014 reconnect required` };
|
|
51271
|
-
}
|
|
52894
|
+
if (res.status === 401 || res.status === 403) return microsoftGraphTestFailure(res);
|
|
51272
52895
|
if (!res.ok) return { ok: false, reason: `Microsoft Graph returned ${res.status}` };
|
|
51273
52896
|
return { ok: true };
|
|
51274
52897
|
} catch (err) {
|
|
@@ -51329,7 +52952,7 @@ async function graphGet2(url, accessToken4, dataSourceId) {
|
|
|
51329
52952
|
signal: AbortSignal.timeout(1e4)
|
|
51330
52953
|
});
|
|
51331
52954
|
if (res.status === 401 || res.status === 403) {
|
|
51332
|
-
|
|
52955
|
+
await throwMicrosoftGraphAccessError(res, dataSourceId);
|
|
51333
52956
|
}
|
|
51334
52957
|
if (!res.ok) {
|
|
51335
52958
|
const text = await res.text().catch(() => "");
|
|
@@ -51349,7 +52972,7 @@ async function graphPost(url, accessToken4, body, dataSourceId, op) {
|
|
|
51349
52972
|
signal: AbortSignal.timeout(15e3)
|
|
51350
52973
|
});
|
|
51351
52974
|
if (res.status === 401 || res.status === 403) {
|
|
51352
|
-
|
|
52975
|
+
await throwMicrosoftGraphAccessError(res, dataSourceId);
|
|
51353
52976
|
}
|
|
51354
52977
|
if (!res.ok) {
|
|
51355
52978
|
const text = await res.text().catch(() => "");
|
|
@@ -51357,6 +52980,57 @@ async function graphPost(url, accessToken4, body, dataSourceId, op) {
|
|
|
51357
52980
|
}
|
|
51358
52981
|
return await res.json();
|
|
51359
52982
|
}
|
|
52983
|
+
async function microsoftGraphErrorBody(res) {
|
|
52984
|
+
try {
|
|
52985
|
+
const body = await res.json();
|
|
52986
|
+
return body && typeof body === "object" ? body : void 0;
|
|
52987
|
+
} catch {
|
|
52988
|
+
return void 0;
|
|
52989
|
+
}
|
|
52990
|
+
}
|
|
52991
|
+
function microsoftGraphErrorText(body) {
|
|
52992
|
+
const code = typeof body?.error?.code === "string" ? body.error.code : "";
|
|
52993
|
+
const message = typeof body?.error?.message === "string" ? body.error.message : "";
|
|
52994
|
+
return `${code} ${message}`.trim();
|
|
52995
|
+
}
|
|
52996
|
+
function microsoftGraphRequiresLicense(body) {
|
|
52997
|
+
return /\b(?:valid\s+)?licen[cs]e\b/i.test(microsoftGraphErrorText(body));
|
|
52998
|
+
}
|
|
52999
|
+
async function throwMicrosoftGraphAccessError(res, dataSourceId) {
|
|
53000
|
+
const body = await microsoftGraphErrorBody(res);
|
|
53001
|
+
if (microsoftGraphRequiresLicense(body)) {
|
|
53002
|
+
throw new ProviderConfigError(
|
|
53003
|
+
"Microsoft Teams requires a valid Microsoft 365 or Teams license",
|
|
53004
|
+
dataSourceId,
|
|
53005
|
+
{ status: res.status, reason: "licenseRequired", body }
|
|
53006
|
+
);
|
|
53007
|
+
}
|
|
53008
|
+
if (res.status === 403) {
|
|
53009
|
+
throw new ProviderConfigError("Microsoft Graph denied the requested permission", dataSourceId, {
|
|
53010
|
+
status: res.status,
|
|
53011
|
+
reason: typeof body?.error?.code === "string" && body.error.code ? body.error.code : "forbidden",
|
|
53012
|
+
body
|
|
53013
|
+
});
|
|
53014
|
+
}
|
|
53015
|
+
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, dataSourceId, {
|
|
53016
|
+
status: res.status,
|
|
53017
|
+
reason: typeof body?.error?.code === "string" && body.error.code ? body.error.code : "unauthorized",
|
|
53018
|
+
body
|
|
53019
|
+
});
|
|
53020
|
+
}
|
|
53021
|
+
async function microsoftGraphTestFailure(res) {
|
|
53022
|
+
const body = await microsoftGraphErrorBody(res);
|
|
53023
|
+
if (microsoftGraphRequiresLicense(body)) {
|
|
53024
|
+
return {
|
|
53025
|
+
ok: false,
|
|
53026
|
+
reason: "Microsoft Teams requires a valid Microsoft 365 or Teams license"
|
|
53027
|
+
};
|
|
53028
|
+
}
|
|
53029
|
+
if (res.status === 403) {
|
|
53030
|
+
return { ok: false, reason: "Microsoft Graph denied the requested permission" };
|
|
53031
|
+
}
|
|
53032
|
+
return { ok: false, reason: `Microsoft rejected token (${res.status}) \u2014 reconnect required` };
|
|
53033
|
+
}
|
|
51360
53034
|
function escapeOData2(value) {
|
|
51361
53035
|
return value.replace(/'/g, "''");
|
|
51362
53036
|
}
|
|
@@ -54684,6 +56358,9 @@ function notion(opts) {
|
|
|
54684
56358
|
if (!clientId || !clientSecret) {
|
|
54685
56359
|
throw new Error("Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)");
|
|
54686
56360
|
}
|
|
56361
|
+
if (!input.codeVerifier) {
|
|
56362
|
+
throw new Error("notion.exchangeOAuth: missing PKCE code verifier");
|
|
56363
|
+
}
|
|
54687
56364
|
const body = new URLSearchParams({
|
|
54688
56365
|
grant_type: "authorization_code",
|
|
54689
56366
|
code: input.code,
|
|
@@ -61455,9 +63132,9 @@ function mutablePath(rootPath, value) {
|
|
|
61455
63132
|
}
|
|
61456
63133
|
async function canonicalizeExistingPath(client, configuredRoot, path) {
|
|
61457
63134
|
const root = posix.normalize(await client.realPath(configuredRoot));
|
|
61458
|
-
const
|
|
61459
|
-
assertWithinCanonicalRoot(root,
|
|
61460
|
-
return
|
|
63135
|
+
const target2 = posix.normalize(await client.realPath(path));
|
|
63136
|
+
assertWithinCanonicalRoot(root, target2);
|
|
63137
|
+
return target2;
|
|
61461
63138
|
}
|
|
61462
63139
|
async function canonicalizeDestinationPath(client, configuredRoot, path) {
|
|
61463
63140
|
const root = posix.normalize(await client.realPath(configuredRoot));
|
|
@@ -61479,8 +63156,8 @@ async function canonicalizeDestinationPath(client, configuredRoot, path) {
|
|
|
61479
63156
|
assertWithinCanonicalRoot(root, destination);
|
|
61480
63157
|
return destination;
|
|
61481
63158
|
}
|
|
61482
|
-
function assertWithinCanonicalRoot(root,
|
|
61483
|
-
if (root !== "/" &&
|
|
63159
|
+
function assertWithinCanonicalRoot(root, target2) {
|
|
63160
|
+
if (root !== "/" && target2 !== root && !target2.startsWith(`${root}/`)) {
|
|
61484
63161
|
throw new Error("SFTP path resolves outside the configured root");
|
|
61485
63162
|
}
|
|
61486
63163
|
}
|
|
@@ -67939,6 +69616,9 @@ function twitter(opts) {
|
|
|
67939
69616
|
if (!clientId || !clientSecret) {
|
|
67940
69617
|
throw new Error("Twitter OAuth client not configured (TWITTER_OAUTH_CLIENT_ID / _SECRET)");
|
|
67941
69618
|
}
|
|
69619
|
+
if (!input.codeVerifier) {
|
|
69620
|
+
throw new Error("twitter.exchangeOAuth: missing PKCE code verifier");
|
|
69621
|
+
}
|
|
67942
69622
|
const tokens = await twitterTokenRequest(clientId, clientSecret, {
|
|
67943
69623
|
grant_type: "authorization_code",
|
|
67944
69624
|
code: input.code,
|
|
@@ -67999,6 +69679,733 @@ async function twitterTokenRequest(clientId, clientSecret, params) {
|
|
|
67999
69679
|
};
|
|
68000
69680
|
}
|
|
68001
69681
|
|
|
69682
|
+
// src/connectors/adapters/tiktok.ts
|
|
69683
|
+
var AUTHORIZATION_URL = "https://www.tiktok.com/v2/auth/authorize/";
|
|
69684
|
+
var TOKEN_URL20 = "https://open.tiktokapis.com/v2/oauth/token/";
|
|
69685
|
+
var API_BASE_URL = "https://open.tiktokapis.com";
|
|
69686
|
+
var SCOPES14 = ["user.info.basic", "video.list", "video.publish"];
|
|
69687
|
+
var VIDEO_FIELDS = [
|
|
69688
|
+
"id",
|
|
69689
|
+
"create_time",
|
|
69690
|
+
"cover_image_url",
|
|
69691
|
+
"share_url",
|
|
69692
|
+
"video_description",
|
|
69693
|
+
"duration",
|
|
69694
|
+
"height",
|
|
69695
|
+
"width",
|
|
69696
|
+
"title",
|
|
69697
|
+
"embed_link",
|
|
69698
|
+
"like_count",
|
|
69699
|
+
"comment_count",
|
|
69700
|
+
"share_count",
|
|
69701
|
+
"view_count"
|
|
69702
|
+
].join(",");
|
|
69703
|
+
var PRIVACY_LEVELS = [
|
|
69704
|
+
"PUBLIC_TO_EVERYONE",
|
|
69705
|
+
"MUTUAL_FOLLOW_FRIENDS",
|
|
69706
|
+
"FOLLOWER_OF_CREATOR",
|
|
69707
|
+
"SELF_ONLY"
|
|
69708
|
+
];
|
|
69709
|
+
var jsonPostHeaders = {
|
|
69710
|
+
"content-type": "application/json; charset=UTF-8"
|
|
69711
|
+
};
|
|
69712
|
+
var TIKTOK_SPEC = {
|
|
69713
|
+
kind: "tiktok",
|
|
69714
|
+
displayName: "TikTok",
|
|
69715
|
+
description: "Read the connected TikTok profile and videos, then publish approved videos or photo posts from verified HTTPS URLs.",
|
|
69716
|
+
auth: {
|
|
69717
|
+
kind: "oauth2",
|
|
69718
|
+
authorizationUrl: AUTHORIZATION_URL,
|
|
69719
|
+
tokenUrl: TOKEN_URL20,
|
|
69720
|
+
scopes: [...SCOPES14],
|
|
69721
|
+
scopeSeparator: ",",
|
|
69722
|
+
pkce: "unsupported",
|
|
69723
|
+
authorizationClientIdParam: "client_key",
|
|
69724
|
+
tokenClientIdParam: "client_key",
|
|
69725
|
+
tokenClientSecretParam: "client_secret",
|
|
69726
|
+
clientIdEnv: "TIKTOK_OAUTH_CLIENT_KEY",
|
|
69727
|
+
clientSecretEnv: "TIKTOK_OAUTH_CLIENT_SECRET",
|
|
69728
|
+
tokenMetadata: { openId: "open_id" }
|
|
69729
|
+
},
|
|
69730
|
+
category: "comms",
|
|
69731
|
+
defaultConsistencyModel: "advisory",
|
|
69732
|
+
baseUrl: API_BASE_URL,
|
|
69733
|
+
credentialsExpiredStatuses: [401],
|
|
69734
|
+
test: {
|
|
69735
|
+
method: "GET",
|
|
69736
|
+
path: "/v2/user/info/",
|
|
69737
|
+
query: { fields: "open_id,union_id,avatar_url,display_name" }
|
|
69738
|
+
},
|
|
69739
|
+
capabilities: [
|
|
69740
|
+
{
|
|
69741
|
+
name: "user.info",
|
|
69742
|
+
class: "read",
|
|
69743
|
+
description: "Read the connected TikTok account identity, display name, and avatar.",
|
|
69744
|
+
parameters: { type: "object", properties: {} },
|
|
69745
|
+
requiredScopes: ["user.info.basic"],
|
|
69746
|
+
request: {
|
|
69747
|
+
method: "GET",
|
|
69748
|
+
path: "/v2/user/info/",
|
|
69749
|
+
query: { fields: "open_id,union_id,avatar_url,display_name" }
|
|
69750
|
+
}
|
|
69751
|
+
},
|
|
69752
|
+
{
|
|
69753
|
+
name: "videos.list",
|
|
69754
|
+
class: "read",
|
|
69755
|
+
description: "List videos for the connected creator, including public URLs, dimensions, duration, and engagement counts.",
|
|
69756
|
+
parameters: {
|
|
69757
|
+
type: "object",
|
|
69758
|
+
properties: {
|
|
69759
|
+
cursor: {
|
|
69760
|
+
type: "integer",
|
|
69761
|
+
minimum: 0,
|
|
69762
|
+
description: "UTC millisecond cursor returned by the previous page."
|
|
69763
|
+
},
|
|
69764
|
+
max_count: {
|
|
69765
|
+
type: "integer",
|
|
69766
|
+
minimum: 1,
|
|
69767
|
+
maximum: 20,
|
|
69768
|
+
default: 10
|
|
69769
|
+
}
|
|
69770
|
+
}
|
|
69771
|
+
},
|
|
69772
|
+
requiredScopes: ["video.list"],
|
|
69773
|
+
request: {
|
|
69774
|
+
method: "POST",
|
|
69775
|
+
path: "/v2/video/list/",
|
|
69776
|
+
query: { fields: VIDEO_FIELDS },
|
|
69777
|
+
headers: jsonPostHeaders,
|
|
69778
|
+
body: { cursor: "{cursor}", max_count: "{max_count}" }
|
|
69779
|
+
}
|
|
69780
|
+
},
|
|
69781
|
+
{
|
|
69782
|
+
name: "videos.query",
|
|
69783
|
+
class: "read",
|
|
69784
|
+
description: "Read up to 20 TikTok videos by their exact video ids.",
|
|
69785
|
+
parameters: {
|
|
69786
|
+
type: "object",
|
|
69787
|
+
properties: {
|
|
69788
|
+
video_ids: {
|
|
69789
|
+
type: "array",
|
|
69790
|
+
minItems: 1,
|
|
69791
|
+
maxItems: 20,
|
|
69792
|
+
uniqueItems: true,
|
|
69793
|
+
items: { type: "string", minLength: 1 }
|
|
69794
|
+
}
|
|
69795
|
+
},
|
|
69796
|
+
required: ["video_ids"]
|
|
69797
|
+
},
|
|
69798
|
+
requiredScopes: ["video.list"],
|
|
69799
|
+
request: {
|
|
69800
|
+
method: "POST",
|
|
69801
|
+
path: "/v2/video/query/",
|
|
69802
|
+
query: { fields: VIDEO_FIELDS },
|
|
69803
|
+
headers: jsonPostHeaders,
|
|
69804
|
+
body: { filters: { video_ids: "{video_ids}" } }
|
|
69805
|
+
}
|
|
69806
|
+
},
|
|
69807
|
+
{
|
|
69808
|
+
name: "publishing.creatorInfo",
|
|
69809
|
+
class: "read",
|
|
69810
|
+
description: "Read the latest creator posting limits, privacy choices, and interaction settings before presenting a publish confirmation.",
|
|
69811
|
+
parameters: { type: "object", properties: {} },
|
|
69812
|
+
requiredScopes: ["video.publish"],
|
|
69813
|
+
request: {
|
|
69814
|
+
method: "POST",
|
|
69815
|
+
path: "/v2/post/publish/creator_info/query/",
|
|
69816
|
+
headers: jsonPostHeaders,
|
|
69817
|
+
body: {}
|
|
69818
|
+
}
|
|
69819
|
+
},
|
|
69820
|
+
{
|
|
69821
|
+
name: "publishing.status",
|
|
69822
|
+
class: "read",
|
|
69823
|
+
description: "Read processing, moderation, and publication status for one publish request.",
|
|
69824
|
+
parameters: {
|
|
69825
|
+
type: "object",
|
|
69826
|
+
properties: {
|
|
69827
|
+
publish_id: { type: "string", minLength: 1, maxLength: 64 }
|
|
69828
|
+
},
|
|
69829
|
+
required: ["publish_id"]
|
|
69830
|
+
},
|
|
69831
|
+
requiredScopes: ["video.publish"],
|
|
69832
|
+
request: {
|
|
69833
|
+
method: "POST",
|
|
69834
|
+
path: "/v2/post/publish/status/fetch/",
|
|
69835
|
+
headers: jsonPostHeaders,
|
|
69836
|
+
body: { publish_id: "{publish_id}" }
|
|
69837
|
+
}
|
|
69838
|
+
},
|
|
69839
|
+
{
|
|
69840
|
+
name: "publishing.videoFromUrl",
|
|
69841
|
+
class: "mutation",
|
|
69842
|
+
description: "Directly publish one approved video from an app-verified HTTPS URL. The adapter refreshes creator limits before it sends the post.",
|
|
69843
|
+
parameters: {
|
|
69844
|
+
type: "object",
|
|
69845
|
+
properties: {
|
|
69846
|
+
video_url: {
|
|
69847
|
+
type: "string",
|
|
69848
|
+
format: "uri",
|
|
69849
|
+
pattern: "^https://",
|
|
69850
|
+
description: "Public HTTPS URL covered by the domain or URL prefix verified in the TikTok app."
|
|
69851
|
+
},
|
|
69852
|
+
video_duration_sec: {
|
|
69853
|
+
type: "number",
|
|
69854
|
+
exclusiveMinimum: 0,
|
|
69855
|
+
description: "Measured video duration used to enforce the creator-specific limit."
|
|
69856
|
+
},
|
|
69857
|
+
privacy_level: { type: "string", enum: [...PRIVACY_LEVELS] },
|
|
69858
|
+
title: { type: "string", maxLength: 2200 },
|
|
69859
|
+
disable_duet: { type: "boolean" },
|
|
69860
|
+
disable_comment: { type: "boolean" },
|
|
69861
|
+
disable_stitch: { type: "boolean" },
|
|
69862
|
+
video_cover_timestamp_ms: { type: "integer", minimum: 0 },
|
|
69863
|
+
brand_content_toggle: {
|
|
69864
|
+
type: "boolean",
|
|
69865
|
+
description: "True for a paid partnership that promotes a third-party business."
|
|
69866
|
+
},
|
|
69867
|
+
brand_organic_toggle: {
|
|
69868
|
+
type: "boolean",
|
|
69869
|
+
description: "True when the post promotes the creator's own business."
|
|
69870
|
+
},
|
|
69871
|
+
is_aigc: {
|
|
69872
|
+
type: "boolean",
|
|
69873
|
+
description: "True when TikTok must label the video as AI-generated content."
|
|
69874
|
+
}
|
|
69875
|
+
},
|
|
69876
|
+
required: [
|
|
69877
|
+
"video_url",
|
|
69878
|
+
"video_duration_sec",
|
|
69879
|
+
"privacy_level",
|
|
69880
|
+
"disable_duet",
|
|
69881
|
+
"disable_comment",
|
|
69882
|
+
"disable_stitch",
|
|
69883
|
+
"brand_content_toggle",
|
|
69884
|
+
"brand_organic_toggle"
|
|
69885
|
+
]
|
|
69886
|
+
},
|
|
69887
|
+
requiredScopes: ["video.publish"],
|
|
69888
|
+
request: {
|
|
69889
|
+
method: "POST",
|
|
69890
|
+
path: "/v2/post/publish/video/init/",
|
|
69891
|
+
headers: jsonPostHeaders,
|
|
69892
|
+
body: {
|
|
69893
|
+
post_info: {
|
|
69894
|
+
title: "{title}",
|
|
69895
|
+
privacy_level: "{privacy_level}",
|
|
69896
|
+
disable_duet: "{disable_duet}",
|
|
69897
|
+
disable_comment: "{disable_comment}",
|
|
69898
|
+
disable_stitch: "{disable_stitch}",
|
|
69899
|
+
video_cover_timestamp_ms: "{video_cover_timestamp_ms}",
|
|
69900
|
+
brand_content_toggle: "{brand_content_toggle}",
|
|
69901
|
+
brand_organic_toggle: "{brand_organic_toggle}",
|
|
69902
|
+
is_aigc: "{is_aigc}"
|
|
69903
|
+
},
|
|
69904
|
+
source_info: {
|
|
69905
|
+
source: "PULL_FROM_URL",
|
|
69906
|
+
video_url: "{video_url}"
|
|
69907
|
+
}
|
|
69908
|
+
}
|
|
69909
|
+
},
|
|
69910
|
+
cas: "none",
|
|
69911
|
+
externalEffect: true
|
|
69912
|
+
},
|
|
69913
|
+
{
|
|
69914
|
+
name: "publishing.photosFromUrls",
|
|
69915
|
+
class: "mutation",
|
|
69916
|
+
description: "Directly publish 1\u201335 approved photos from app-verified HTTPS URLs. The adapter refreshes creator options before it sends the post.",
|
|
69917
|
+
parameters: {
|
|
69918
|
+
type: "object",
|
|
69919
|
+
properties: {
|
|
69920
|
+
photo_images: {
|
|
69921
|
+
type: "array",
|
|
69922
|
+
minItems: 1,
|
|
69923
|
+
maxItems: 35,
|
|
69924
|
+
items: { type: "string", format: "uri", pattern: "^https://" }
|
|
69925
|
+
},
|
|
69926
|
+
photo_cover_index: { type: "integer", minimum: 0 },
|
|
69927
|
+
privacy_level: { type: "string", enum: [...PRIVACY_LEVELS] },
|
|
69928
|
+
title: { type: "string", maxLength: 90 },
|
|
69929
|
+
description: { type: "string", maxLength: 4e3 },
|
|
69930
|
+
disable_comment: { type: "boolean" },
|
|
69931
|
+
auto_add_music: { type: "boolean" },
|
|
69932
|
+
brand_content_toggle: {
|
|
69933
|
+
type: "boolean",
|
|
69934
|
+
description: "True for a paid partnership that promotes a third-party business."
|
|
69935
|
+
},
|
|
69936
|
+
brand_organic_toggle: {
|
|
69937
|
+
type: "boolean",
|
|
69938
|
+
description: "True when the post promotes the creator's own business."
|
|
69939
|
+
}
|
|
69940
|
+
},
|
|
69941
|
+
required: [
|
|
69942
|
+
"photo_images",
|
|
69943
|
+
"photo_cover_index",
|
|
69944
|
+
"privacy_level",
|
|
69945
|
+
"disable_comment",
|
|
69946
|
+
"auto_add_music",
|
|
69947
|
+
"brand_content_toggle",
|
|
69948
|
+
"brand_organic_toggle"
|
|
69949
|
+
]
|
|
69950
|
+
},
|
|
69951
|
+
requiredScopes: ["video.publish"],
|
|
69952
|
+
request: {
|
|
69953
|
+
method: "POST",
|
|
69954
|
+
path: "/v2/post/publish/content/init/",
|
|
69955
|
+
headers: jsonPostHeaders,
|
|
69956
|
+
body: {
|
|
69957
|
+
media_type: "PHOTO",
|
|
69958
|
+
post_mode: "DIRECT_POST",
|
|
69959
|
+
post_info: {
|
|
69960
|
+
title: "{title}",
|
|
69961
|
+
description: "{description}",
|
|
69962
|
+
privacy_level: "{privacy_level}",
|
|
69963
|
+
disable_comment: "{disable_comment}",
|
|
69964
|
+
auto_add_music: "{auto_add_music}",
|
|
69965
|
+
brand_content_toggle: "{brand_content_toggle}",
|
|
69966
|
+
brand_organic_toggle: "{brand_organic_toggle}"
|
|
69967
|
+
},
|
|
69968
|
+
source_info: {
|
|
69969
|
+
source: "PULL_FROM_URL",
|
|
69970
|
+
photo_images: "{photo_images}",
|
|
69971
|
+
photo_cover_index: "{photo_cover_index}"
|
|
69972
|
+
}
|
|
69973
|
+
}
|
|
69974
|
+
},
|
|
69975
|
+
cas: "none",
|
|
69976
|
+
externalEffect: true
|
|
69977
|
+
}
|
|
69978
|
+
]
|
|
69979
|
+
};
|
|
69980
|
+
var tiktokConnector = createTikTokConnector();
|
|
69981
|
+
function tiktok(options) {
|
|
69982
|
+
const adapter = createTikTokConnector();
|
|
69983
|
+
const inFlightRefreshes = /* @__PURE__ */ new Map();
|
|
69984
|
+
const refresh = async (credentials) => {
|
|
69985
|
+
assertOAuthClient(options);
|
|
69986
|
+
if (credentials.kind !== "oauth2" || !credentials.refreshToken) {
|
|
69987
|
+
throw new Error("tiktok.refreshToken: missing refresh token");
|
|
69988
|
+
}
|
|
69989
|
+
const token = await tiktokTokenRequest(
|
|
69990
|
+
options,
|
|
69991
|
+
{
|
|
69992
|
+
grant_type: "refresh_token",
|
|
69993
|
+
refresh_token: credentials.refreshToken
|
|
69994
|
+
},
|
|
69995
|
+
[credentials.refreshToken]
|
|
69996
|
+
);
|
|
69997
|
+
if (!token.expiresIn) {
|
|
69998
|
+
throw new Error("tiktok token request returned an incomplete refresh grant");
|
|
69999
|
+
}
|
|
70000
|
+
return {
|
|
70001
|
+
...tokenCredentials(token),
|
|
70002
|
+
refreshToken: token.refreshToken ?? credentials.refreshToken
|
|
70003
|
+
};
|
|
70004
|
+
};
|
|
70005
|
+
const withFreshCredentials = async (invocation) => {
|
|
70006
|
+
const credentials = invocation.source.credentials;
|
|
70007
|
+
if (credentials.kind !== "oauth2") return invocation;
|
|
70008
|
+
if (credentials.expiresAt !== void 0 && credentials.expiresAt > Date.now() + 6e4) {
|
|
70009
|
+
return invocation;
|
|
70010
|
+
}
|
|
70011
|
+
if (!credentials.refreshToken) {
|
|
70012
|
+
throw new CredentialsExpired(
|
|
70013
|
+
"TikTok access token expired and no refresh token is available",
|
|
70014
|
+
invocation.source.id
|
|
70015
|
+
);
|
|
70016
|
+
}
|
|
70017
|
+
let pending = inFlightRefreshes.get(invocation.source.id);
|
|
70018
|
+
if (!pending) {
|
|
70019
|
+
let next;
|
|
70020
|
+
const promise = Promise.resolve().then(() => {
|
|
70021
|
+
if (!next.onCredentialsRotated) {
|
|
70022
|
+
throw new Error(
|
|
70023
|
+
"tiktok: credential rotation persistence callback is required before refreshing"
|
|
70024
|
+
);
|
|
70025
|
+
}
|
|
70026
|
+
return refresh(credentials);
|
|
70027
|
+
});
|
|
70028
|
+
next = {
|
|
70029
|
+
promise,
|
|
70030
|
+
onCredentialsRotated: invocation.onCredentialsRotated
|
|
70031
|
+
};
|
|
70032
|
+
pending = next;
|
|
70033
|
+
inFlightRefreshes.set(invocation.source.id, pending);
|
|
70034
|
+
} else if (!pending.onCredentialsRotated && invocation.onCredentialsRotated) {
|
|
70035
|
+
pending.onCredentialsRotated = invocation.onCredentialsRotated;
|
|
70036
|
+
}
|
|
70037
|
+
const current = pending;
|
|
70038
|
+
try {
|
|
70039
|
+
const refreshed = await current.promise;
|
|
70040
|
+
current.persistence ??= Promise.resolve().then(
|
|
70041
|
+
() => current.onCredentialsRotated?.(refreshed)
|
|
70042
|
+
);
|
|
70043
|
+
await current.persistence;
|
|
70044
|
+
return {
|
|
70045
|
+
...invocation,
|
|
70046
|
+
source: { ...invocation.source, credentials: refreshed }
|
|
70047
|
+
};
|
|
70048
|
+
} finally {
|
|
70049
|
+
if (inFlightRefreshes.get(invocation.source.id) === current) {
|
|
70050
|
+
inFlightRefreshes.delete(invocation.source.id);
|
|
70051
|
+
}
|
|
70052
|
+
}
|
|
70053
|
+
};
|
|
70054
|
+
return {
|
|
70055
|
+
...adapter,
|
|
70056
|
+
async executeRead(invocation) {
|
|
70057
|
+
return adapter.executeRead(await withFreshCredentials(invocation));
|
|
70058
|
+
},
|
|
70059
|
+
async executeMutation(invocation) {
|
|
70060
|
+
return adapter.executeMutation(await withFreshCredentials(invocation));
|
|
70061
|
+
},
|
|
70062
|
+
async test(source, onCredentialsRotated) {
|
|
70063
|
+
try {
|
|
70064
|
+
const invocation = await withFreshCredentials({
|
|
70065
|
+
source,
|
|
70066
|
+
capabilityName: "user.info",
|
|
70067
|
+
args: {},
|
|
70068
|
+
idempotencyKey: "tiktok-connection-test",
|
|
70069
|
+
onCredentialsRotated
|
|
70070
|
+
});
|
|
70071
|
+
return adapter.test(invocation.source);
|
|
70072
|
+
} catch (error) {
|
|
70073
|
+
return {
|
|
70074
|
+
ok: false,
|
|
70075
|
+
reason: error instanceof Error ? error.message : "unknown error"
|
|
70076
|
+
};
|
|
70077
|
+
}
|
|
70078
|
+
},
|
|
70079
|
+
async exchangeOAuth(input) {
|
|
70080
|
+
assertOAuthClient(options);
|
|
70081
|
+
const token = await tiktokTokenRequest(
|
|
70082
|
+
options,
|
|
70083
|
+
{
|
|
70084
|
+
grant_type: "authorization_code",
|
|
70085
|
+
code: input.code,
|
|
70086
|
+
redirect_uri: input.redirectUri
|
|
70087
|
+
},
|
|
70088
|
+
[input.code]
|
|
70089
|
+
);
|
|
70090
|
+
const grant = requireTikTokAuthorizationGrant(token);
|
|
70091
|
+
return {
|
|
70092
|
+
credentials: tokenCredentials(grant),
|
|
70093
|
+
scopes: grant.scopes,
|
|
70094
|
+
metadata: { openId: grant.openId }
|
|
70095
|
+
};
|
|
70096
|
+
},
|
|
70097
|
+
refreshToken: refresh
|
|
70098
|
+
};
|
|
70099
|
+
}
|
|
70100
|
+
function createTikTokConnector() {
|
|
70101
|
+
const base = declarativeRestConnector(TIKTOK_SPEC);
|
|
70102
|
+
const executeRead2 = async (invocation) => {
|
|
70103
|
+
const result = await base.executeRead(invocation);
|
|
70104
|
+
assertTikTokEnvelope(
|
|
70105
|
+
result.data,
|
|
70106
|
+
invocation.capabilityName,
|
|
70107
|
+
invocation.source.credentials
|
|
70108
|
+
);
|
|
70109
|
+
return result;
|
|
70110
|
+
};
|
|
70111
|
+
return {
|
|
70112
|
+
...base,
|
|
70113
|
+
executeRead: executeRead2,
|
|
70114
|
+
async executeMutation(invocation) {
|
|
70115
|
+
validatePublishInput(invocation);
|
|
70116
|
+
const creator = await executeRead2({
|
|
70117
|
+
...invocation,
|
|
70118
|
+
capabilityName: "publishing.creatorInfo",
|
|
70119
|
+
args: {}
|
|
70120
|
+
});
|
|
70121
|
+
validateCreatorLimits(invocation, creator.data);
|
|
70122
|
+
const result = await base.executeMutation(invocation);
|
|
70123
|
+
if (result.status === "committed") {
|
|
70124
|
+
assertTikTokPublishResult(
|
|
70125
|
+
result.data,
|
|
70126
|
+
invocation.capabilityName,
|
|
70127
|
+
invocation.source.credentials
|
|
70128
|
+
);
|
|
70129
|
+
}
|
|
70130
|
+
return result;
|
|
70131
|
+
},
|
|
70132
|
+
async test(source) {
|
|
70133
|
+
try {
|
|
70134
|
+
await executeRead2({
|
|
70135
|
+
source,
|
|
70136
|
+
capabilityName: "user.info",
|
|
70137
|
+
args: {},
|
|
70138
|
+
idempotencyKey: "tiktok-connection-test"
|
|
70139
|
+
});
|
|
70140
|
+
return { ok: true };
|
|
70141
|
+
} catch (error) {
|
|
70142
|
+
return {
|
|
70143
|
+
ok: false,
|
|
70144
|
+
reason: error instanceof Error ? error.message : "unknown error"
|
|
70145
|
+
};
|
|
70146
|
+
}
|
|
70147
|
+
}
|
|
70148
|
+
};
|
|
70149
|
+
}
|
|
70150
|
+
function validatePublishInput(invocation) {
|
|
70151
|
+
if (invocation.capabilityName === "publishing.videoFromUrl") {
|
|
70152
|
+
const url = requiredString7(invocation.args, "video_url");
|
|
70153
|
+
requireHttpsUrl(url, "video_url");
|
|
70154
|
+
const duration2 = requiredNumber(invocation.args, "video_duration_sec");
|
|
70155
|
+
if (duration2 <= 0) throw new Error("tiktok: video_duration_sec must be greater than zero");
|
|
70156
|
+
requiredPrivacy(invocation.args);
|
|
70157
|
+
requiredBoolean(invocation.args, "disable_duet");
|
|
70158
|
+
requiredBoolean(invocation.args, "disable_comment");
|
|
70159
|
+
requiredBoolean(invocation.args, "disable_stitch");
|
|
70160
|
+
requiredBoolean(invocation.args, "brand_content_toggle");
|
|
70161
|
+
requiredBoolean(invocation.args, "brand_organic_toggle");
|
|
70162
|
+
optionalUtf16Length(invocation.args, "title", 2200);
|
|
70163
|
+
return;
|
|
70164
|
+
}
|
|
70165
|
+
if (invocation.capabilityName === "publishing.photosFromUrls") {
|
|
70166
|
+
const photos = invocation.args.photo_images;
|
|
70167
|
+
if (!Array.isArray(photos) || photos.length < 1 || photos.length > 35) {
|
|
70168
|
+
throw new Error("tiktok: photo_images must contain between 1 and 35 URLs");
|
|
70169
|
+
}
|
|
70170
|
+
for (const [index, value] of photos.entries()) {
|
|
70171
|
+
if (typeof value !== "string") {
|
|
70172
|
+
throw new Error(`tiktok: photo_images[${index}] must be a string`);
|
|
70173
|
+
}
|
|
70174
|
+
requireHttpsUrl(value, `photo_images[${index}]`);
|
|
70175
|
+
}
|
|
70176
|
+
const cover = requiredNumber(invocation.args, "photo_cover_index");
|
|
70177
|
+
if (!Number.isInteger(cover) || cover < 0 || cover >= photos.length) {
|
|
70178
|
+
throw new Error("tiktok: photo_cover_index must identify one supplied photo");
|
|
70179
|
+
}
|
|
70180
|
+
requiredPrivacy(invocation.args);
|
|
70181
|
+
requiredBoolean(invocation.args, "disable_comment");
|
|
70182
|
+
requiredBoolean(invocation.args, "auto_add_music");
|
|
70183
|
+
requiredBoolean(invocation.args, "brand_content_toggle");
|
|
70184
|
+
requiredBoolean(invocation.args, "brand_organic_toggle");
|
|
70185
|
+
optionalUtf16Length(invocation.args, "title", 90);
|
|
70186
|
+
optionalUtf16Length(invocation.args, "description", 4e3);
|
|
70187
|
+
return;
|
|
70188
|
+
}
|
|
70189
|
+
throw new Error(`tiktok: unknown mutation capability ${invocation.capabilityName}`);
|
|
70190
|
+
}
|
|
70191
|
+
function validateCreatorLimits(invocation, envelope) {
|
|
70192
|
+
const data4 = readEnvelopeData(envelope, "publishing.creatorInfo");
|
|
70193
|
+
const privacy = requiredString7(invocation.args, "privacy_level");
|
|
70194
|
+
const choices = data4.privacy_level_options;
|
|
70195
|
+
if (!Array.isArray(choices) || !choices.every((value) => typeof value === "string")) {
|
|
70196
|
+
throw new Error("tiktok publishing.creatorInfo returned invalid privacy_level_options");
|
|
70197
|
+
}
|
|
70198
|
+
if (!choices.includes(privacy)) {
|
|
70199
|
+
throw new Error(`tiktok: privacy_level ${privacy} is unavailable for this creator`);
|
|
70200
|
+
}
|
|
70201
|
+
requireDisabledInteraction(invocation.args, data4, "disable_comment", "comment_disabled");
|
|
70202
|
+
if (invocation.capabilityName === "publishing.videoFromUrl") {
|
|
70203
|
+
requireDisabledInteraction(invocation.args, data4, "disable_duet", "duet_disabled");
|
|
70204
|
+
requireDisabledInteraction(invocation.args, data4, "disable_stitch", "stitch_disabled");
|
|
70205
|
+
const maximum = data4.max_video_post_duration_sec;
|
|
70206
|
+
if (typeof maximum !== "number" || !Number.isFinite(maximum) || maximum <= 0) {
|
|
70207
|
+
throw new Error("tiktok publishing.creatorInfo returned an invalid video-duration limit");
|
|
70208
|
+
}
|
|
70209
|
+
const duration2 = requiredNumber(invocation.args, "video_duration_sec");
|
|
70210
|
+
if (duration2 > maximum) {
|
|
70211
|
+
throw new Error(
|
|
70212
|
+
`tiktok: video duration ${duration2}s exceeds this creator's ${maximum}s limit`
|
|
70213
|
+
);
|
|
70214
|
+
}
|
|
70215
|
+
}
|
|
70216
|
+
}
|
|
70217
|
+
function assertTikTokEnvelope(value, capabilityName, credentials) {
|
|
70218
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
70219
|
+
throw new Error(`tiktok ${capabilityName} returned a malformed response`);
|
|
70220
|
+
}
|
|
70221
|
+
const error = value.error;
|
|
70222
|
+
if (!error || typeof error !== "object" || Array.isArray(error)) {
|
|
70223
|
+
throw new Error(`tiktok ${capabilityName} returned no error status`);
|
|
70224
|
+
}
|
|
70225
|
+
const code = error.code;
|
|
70226
|
+
if (code !== "ok") {
|
|
70227
|
+
const message = error.message;
|
|
70228
|
+
const detail = typeof message === "string" && message ? ` \u2014 ${redact2(message.slice(0, 200), credentialValues(credentials))}` : "";
|
|
70229
|
+
const safeCode = redact2(
|
|
70230
|
+
safeProviderValue(code),
|
|
70231
|
+
credentialValues(credentials)
|
|
70232
|
+
);
|
|
70233
|
+
throw new Error(`tiktok ${capabilityName} failed: ${safeCode}${detail}`);
|
|
70234
|
+
}
|
|
70235
|
+
}
|
|
70236
|
+
function requireDisabledInteraction(args, creator, argumentName, creatorField) {
|
|
70237
|
+
const disabled = creator[creatorField];
|
|
70238
|
+
if (typeof disabled !== "boolean") {
|
|
70239
|
+
throw new Error(`tiktok publishing.creatorInfo returned invalid ${creatorField}`);
|
|
70240
|
+
}
|
|
70241
|
+
if (disabled && args[argumentName] !== true) {
|
|
70242
|
+
throw new Error(
|
|
70243
|
+
`tiktok: ${argumentName} must be true because the creator disabled this interaction`
|
|
70244
|
+
);
|
|
70245
|
+
}
|
|
70246
|
+
}
|
|
70247
|
+
function readEnvelopeData(envelope, capabilityName, credentials) {
|
|
70248
|
+
assertTikTokEnvelope(envelope, capabilityName, credentials);
|
|
70249
|
+
const data4 = envelope.data;
|
|
70250
|
+
if (!data4 || typeof data4 !== "object" || Array.isArray(data4)) {
|
|
70251
|
+
throw new Error(`tiktok ${capabilityName} returned malformed data`);
|
|
70252
|
+
}
|
|
70253
|
+
return data4;
|
|
70254
|
+
}
|
|
70255
|
+
function assertTikTokPublishResult(envelope, capabilityName, credentials) {
|
|
70256
|
+
const data4 = readEnvelopeData(envelope, capabilityName, credentials);
|
|
70257
|
+
const publishId = data4.publish_id;
|
|
70258
|
+
if (typeof publishId !== "string" || !publishId.trim() || publishId.length > 64) {
|
|
70259
|
+
throw new Error(`tiktok ${capabilityName} returned an invalid publish_id`);
|
|
70260
|
+
}
|
|
70261
|
+
}
|
|
70262
|
+
function requiredString7(args, name) {
|
|
70263
|
+
const value = args[name];
|
|
70264
|
+
if (typeof value !== "string" || !value) {
|
|
70265
|
+
throw new Error(`tiktok: missing required argument: ${name}`);
|
|
70266
|
+
}
|
|
70267
|
+
return value;
|
|
70268
|
+
}
|
|
70269
|
+
function requiredNumber(args, name) {
|
|
70270
|
+
const value = args[name];
|
|
70271
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
70272
|
+
throw new Error(`tiktok: missing required argument: ${name}`);
|
|
70273
|
+
}
|
|
70274
|
+
return value;
|
|
70275
|
+
}
|
|
70276
|
+
function requiredBoolean(args, name) {
|
|
70277
|
+
const value = args[name];
|
|
70278
|
+
if (typeof value !== "boolean") {
|
|
70279
|
+
throw new Error(`tiktok: missing required argument: ${name}`);
|
|
70280
|
+
}
|
|
70281
|
+
return value;
|
|
70282
|
+
}
|
|
70283
|
+
function requiredPrivacy(args) {
|
|
70284
|
+
const value = requiredString7(args, "privacy_level");
|
|
70285
|
+
if (!PRIVACY_LEVELS.includes(value)) {
|
|
70286
|
+
throw new Error(`tiktok: unsupported privacy_level ${value}`);
|
|
70287
|
+
}
|
|
70288
|
+
return value;
|
|
70289
|
+
}
|
|
70290
|
+
function optionalUtf16Length(args, name, maximum) {
|
|
70291
|
+
const value = args[name];
|
|
70292
|
+
if (value === void 0) return;
|
|
70293
|
+
if (typeof value !== "string") throw new Error(`tiktok: ${name} must be a string`);
|
|
70294
|
+
if (value.length > maximum) {
|
|
70295
|
+
throw new Error(`tiktok: ${name} exceeds the ${maximum} UTF-16-unit limit`);
|
|
70296
|
+
}
|
|
70297
|
+
}
|
|
70298
|
+
function requireHttpsUrl(value, name) {
|
|
70299
|
+
let url;
|
|
70300
|
+
try {
|
|
70301
|
+
url = new URL(value);
|
|
70302
|
+
} catch {
|
|
70303
|
+
throw new Error(`tiktok: ${name} must be a valid HTTPS URL`);
|
|
70304
|
+
}
|
|
70305
|
+
if (url.protocol !== "https:" || url.username || url.password) {
|
|
70306
|
+
throw new Error(`tiktok: ${name} must be a valid HTTPS URL`);
|
|
70307
|
+
}
|
|
70308
|
+
}
|
|
70309
|
+
async function tiktokTokenRequest(options, grant, extraRedactions) {
|
|
70310
|
+
const body = new URLSearchParams({
|
|
70311
|
+
client_key: options.clientId,
|
|
70312
|
+
client_secret: options.clientSecret,
|
|
70313
|
+
...grant
|
|
70314
|
+
});
|
|
70315
|
+
let response;
|
|
70316
|
+
try {
|
|
70317
|
+
response = await fetch(TOKEN_URL20, {
|
|
70318
|
+
method: "POST",
|
|
70319
|
+
headers: {
|
|
70320
|
+
accept: "application/json",
|
|
70321
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
70322
|
+
"cache-control": "no-cache"
|
|
70323
|
+
},
|
|
70324
|
+
body,
|
|
70325
|
+
signal: AbortSignal.timeout(15e3)
|
|
70326
|
+
});
|
|
70327
|
+
} catch (cause) {
|
|
70328
|
+
const message = cause instanceof Error ? cause.message : "unknown transport error";
|
|
70329
|
+
throw new Error(`tiktok token request failed: ${redact2(message, [options.clientId, options.clientSecret, ...extraRedactions])}`);
|
|
70330
|
+
}
|
|
70331
|
+
if (!response.ok) {
|
|
70332
|
+
const detail = await response.text().catch(() => "");
|
|
70333
|
+
throw new Error(
|
|
70334
|
+
`tiktok token request failed: ${response.status} ${response.statusText} \u2014 ${redact2(
|
|
70335
|
+
detail.slice(0, 300),
|
|
70336
|
+
[options.clientId, options.clientSecret, ...extraRedactions]
|
|
70337
|
+
)}`
|
|
70338
|
+
);
|
|
70339
|
+
}
|
|
70340
|
+
const json = await response.json();
|
|
70341
|
+
if (typeof json.access_token !== "string" || !json.access_token) {
|
|
70342
|
+
throw new Error("tiktok token request returned no access_token");
|
|
70343
|
+
}
|
|
70344
|
+
return {
|
|
70345
|
+
accessToken: json.access_token,
|
|
70346
|
+
refreshToken: typeof json.refresh_token === "string" && json.refresh_token ? json.refresh_token : void 0,
|
|
70347
|
+
expiresIn: typeof json.expires_in === "number" && json.expires_in > 0 ? json.expires_in : void 0,
|
|
70348
|
+
scope: typeof json.scope === "string" ? json.scope : void 0,
|
|
70349
|
+
openId: typeof json.open_id === "string" ? json.open_id : void 0
|
|
70350
|
+
};
|
|
70351
|
+
}
|
|
70352
|
+
function tokenCredentials(token) {
|
|
70353
|
+
return {
|
|
70354
|
+
kind: "oauth2",
|
|
70355
|
+
accessToken: token.accessToken,
|
|
70356
|
+
refreshToken: token.refreshToken,
|
|
70357
|
+
expiresAt: token.expiresIn ? Date.now() + token.expiresIn * 1e3 : void 0
|
|
70358
|
+
};
|
|
70359
|
+
}
|
|
70360
|
+
function requireTikTokAuthorizationGrant(token) {
|
|
70361
|
+
const scopes2 = token.scope ? splitScopes(token.scope) : [];
|
|
70362
|
+
if (!token.refreshToken || !token.expiresIn || !token.openId || scopes2.length === 0) {
|
|
70363
|
+
throw new Error(
|
|
70364
|
+
"tiktok token request returned an incomplete authorization grant"
|
|
70365
|
+
);
|
|
70366
|
+
}
|
|
70367
|
+
return { ...token, scopes: scopes2 };
|
|
70368
|
+
}
|
|
70369
|
+
function splitScopes(scope) {
|
|
70370
|
+
return scope.split(",").map((value) => value.trim()).filter(Boolean);
|
|
70371
|
+
}
|
|
70372
|
+
function assertOAuthClient(options) {
|
|
70373
|
+
if (!options.clientId || !options.clientSecret) {
|
|
70374
|
+
throw new Error(
|
|
70375
|
+
"TikTok OAuth client not configured (TIKTOK_OAUTH_CLIENT_KEY / TIKTOK_OAUTH_CLIENT_SECRET)"
|
|
70376
|
+
);
|
|
70377
|
+
}
|
|
70378
|
+
}
|
|
70379
|
+
function redact2(value, secrets) {
|
|
70380
|
+
let redacted = value;
|
|
70381
|
+
for (const secret of secrets) {
|
|
70382
|
+
if (!secret) continue;
|
|
70383
|
+
redacted = redacted.split(secret).join("[REDACTED]");
|
|
70384
|
+
}
|
|
70385
|
+
return redacted;
|
|
70386
|
+
}
|
|
70387
|
+
function credentialValues(credentials) {
|
|
70388
|
+
if (!credentials) return [];
|
|
70389
|
+
switch (credentials.kind) {
|
|
70390
|
+
case "oauth2":
|
|
70391
|
+
return [credentials.accessToken, credentials.refreshToken ?? ""];
|
|
70392
|
+
case "api-key":
|
|
70393
|
+
return [credentials.apiKey];
|
|
70394
|
+
case "hmac":
|
|
70395
|
+
return [credentials.secret];
|
|
70396
|
+
case "custom":
|
|
70397
|
+
return Object.values(credentials.values).filter(
|
|
70398
|
+
(value) => typeof value === "string"
|
|
70399
|
+
);
|
|
70400
|
+
case "none":
|
|
70401
|
+
return [];
|
|
70402
|
+
}
|
|
70403
|
+
}
|
|
70404
|
+
function safeProviderValue(value) {
|
|
70405
|
+
if (typeof value === "string") return value.slice(0, 80);
|
|
70406
|
+
return "unknown_error";
|
|
70407
|
+
}
|
|
70408
|
+
|
|
68002
70409
|
// src/connectors/adapters/twilio-sms.ts
|
|
68003
70410
|
var API11 = "https://api.twilio.com/2010-04-01";
|
|
68004
70411
|
var LOOKUP_API = "https://lookups.twilio.com/v1";
|
|
@@ -68459,9 +70866,9 @@ var voucheryIoConnector = declarativeRestConnector({
|
|
|
68459
70866
|
});
|
|
68460
70867
|
|
|
68461
70868
|
// src/connectors/adapters/whatsapp-business.ts
|
|
68462
|
-
var
|
|
70869
|
+
var SCOPES15 = ["whatsapp_business_messaging", "whatsapp_business_management", "business_management"];
|
|
68463
70870
|
var AUTH_URL18 = "https://www.facebook.com/v21.0/dialog/oauth";
|
|
68464
|
-
var
|
|
70871
|
+
var TOKEN_URL21 = "https://graph.facebook.com/v21.0/oauth/access_token";
|
|
68465
70872
|
var API12 = "https://graph.facebook.com/v21.0";
|
|
68466
70873
|
function whatsappBusiness(opts) {
|
|
68467
70874
|
const { clientId, clientSecret } = opts;
|
|
@@ -68473,8 +70880,8 @@ function whatsappBusiness(opts) {
|
|
|
68473
70880
|
auth: {
|
|
68474
70881
|
kind: "oauth2",
|
|
68475
70882
|
authorizationUrl: AUTH_URL18,
|
|
68476
|
-
tokenUrl:
|
|
68477
|
-
scopes:
|
|
70883
|
+
tokenUrl: TOKEN_URL21,
|
|
70884
|
+
scopes: SCOPES15,
|
|
68478
70885
|
clientIdEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_ID",
|
|
68479
70886
|
clientSecretEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_SECRET"
|
|
68480
70887
|
},
|
|
@@ -68744,7 +71151,7 @@ function whatsappBusiness(opts) {
|
|
|
68744
71151
|
throw new Error("WhatsApp Business OAuth client not configured (WHATSAPP_BUSINESS_OAUTH_CLIENT_ID / _SECRET)");
|
|
68745
71152
|
}
|
|
68746
71153
|
const tokens = await exchangeAuthorizationCode({
|
|
68747
|
-
tokenUrl:
|
|
71154
|
+
tokenUrl: TOKEN_URL21,
|
|
68748
71155
|
clientId,
|
|
68749
71156
|
clientSecret,
|
|
68750
71157
|
code: input.code,
|
|
@@ -68760,7 +71167,7 @@ function whatsappBusiness(opts) {
|
|
|
68760
71167
|
refreshToken: tokens.refreshToken,
|
|
68761
71168
|
expiresAt: tokens.expiresIn ? Date.now() + tokens.expiresIn * 1e3 : void 0
|
|
68762
71169
|
},
|
|
68763
|
-
scopes: tokens.scope?.split(/[,\s]+/) ??
|
|
71170
|
+
scopes: tokens.scope?.split(/[,\s]+/) ?? SCOPES15,
|
|
68764
71171
|
metadata: {}
|
|
68765
71172
|
};
|
|
68766
71173
|
},
|
|
@@ -78031,8 +80438,8 @@ var discourseConnector = declarativeRestConnector({
|
|
|
78031
80438
|
});
|
|
78032
80439
|
|
|
78033
80440
|
// src/connectors/adapters/digital-ocean.ts
|
|
78034
|
-
var
|
|
78035
|
-
var
|
|
80441
|
+
var pagination3 = { page: { type: "integer", minimum: 1 }, perPage: { type: "integer", minimum: 1, maximum: 200 } };
|
|
80442
|
+
var paginationQuery2 = { page: "{page}", per_page: "{perPage}" };
|
|
78036
80443
|
var digitalOceanConnector = declarativeRestConnector({
|
|
78037
80444
|
kind: "digital-ocean",
|
|
78038
80445
|
displayName: "DigitalOcean",
|
|
@@ -78045,24 +80452,24 @@ var digitalOceanConnector = declarativeRestConnector({
|
|
|
78045
80452
|
test: { method: "GET", path: "/v2/account" },
|
|
78046
80453
|
capabilities: [
|
|
78047
80454
|
{ name: "account.get", class: "read", description: "Read the current account and status.", parameters: { type: "object", properties: {} }, request: { method: "GET", path: "/v2/account" } },
|
|
78048
|
-
{ name: "projects.list", class: "read", description: "List projects.", parameters: { type: "object", properties:
|
|
80455
|
+
{ name: "projects.list", class: "read", description: "List projects.", parameters: { type: "object", properties: pagination3 }, request: { method: "GET", path: "/v2/projects", query: paginationQuery2 } },
|
|
78049
80456
|
{ name: "projects.get", class: "read", description: "Read one project.", parameters: { type: "object", properties: { projectId: { type: "string" } }, required: ["projectId"] }, request: { method: "GET", path: "/v2/projects/{projectId}" } },
|
|
78050
80457
|
{ name: "projects.create", class: "mutation", description: "Create a project.", parameters: { type: "object", properties: { project: { type: "object" } }, required: ["project"] }, request: { method: "POST", path: "/v2/projects", body: "{project}" }, cas: "none", externalEffect: true },
|
|
78051
80458
|
{ name: "projects.update", class: "mutation", description: "Update a project.", parameters: { type: "object", properties: { projectId: { type: "string" }, project: { type: "object" } }, required: ["projectId", "project"] }, request: { method: "PATCH", path: "/v2/projects/{projectId}", body: "{project}" }, cas: "optimistic-read-verify", externalEffect: true },
|
|
78052
80459
|
{ name: "projects.delete", class: "mutation", description: "Delete a project.", parameters: { type: "object", properties: { projectId: { type: "string" } }, required: ["projectId"] }, request: { method: "DELETE", path: "/v2/projects/{projectId}" }, cas: "optimistic-read-verify", externalEffect: true },
|
|
78053
|
-
{ name: "droplets.list", class: "read", description: "List Droplets.", parameters: { type: "object", properties: { ...
|
|
80460
|
+
{ name: "droplets.list", class: "read", description: "List Droplets.", parameters: { type: "object", properties: { ...pagination3, tagName: { type: "string" }, name: { type: "string" } } }, request: { method: "GET", path: "/v2/droplets", query: { ...paginationQuery2, tag_name: "{tagName}", name: "{name}" } } },
|
|
78054
80461
|
{ name: "droplets.get", class: "read", description: "Read one Droplet.", parameters: { type: "object", properties: { dropletId: { type: "integer" } }, required: ["dropletId"] }, request: { method: "GET", path: "/v2/droplets/{dropletId}" } },
|
|
78055
80462
|
{ name: "droplets.create", class: "mutation", description: "Create one or more Droplets.", parameters: { type: "object", properties: { droplet: { type: "object" } }, required: ["droplet"] }, request: { method: "POST", path: "/v2/droplets", body: "{droplet}" }, cas: "none", externalEffect: true },
|
|
78056
80463
|
{ name: "droplets.action", class: "mutation", description: "Run a provider-native Droplet action such as power_on, shutdown, snapshot, resize, or rebuild.", parameters: { type: "object", properties: { dropletId: { type: "integer" }, action: { type: "object" } }, required: ["dropletId", "action"] }, request: { method: "POST", path: "/v2/droplets/{dropletId}/actions", body: "{action}" }, cas: "none", externalEffect: true },
|
|
78057
80464
|
{ name: "droplets.delete", class: "mutation", description: "Delete a Droplet.", parameters: { type: "object", properties: { dropletId: { type: "integer" } }, required: ["dropletId"] }, request: { method: "DELETE", path: "/v2/droplets/{dropletId}" }, cas: "optimistic-read-verify", externalEffect: true },
|
|
78058
|
-
{ name: "volumes.list", class: "read", description: "List block-storage volumes.", parameters: { type: "object", properties: { ...
|
|
80465
|
+
{ name: "volumes.list", class: "read", description: "List block-storage volumes.", parameters: { type: "object", properties: { ...pagination3, region: { type: "string" }, name: { type: "string" } } }, request: { method: "GET", path: "/v2/volumes", query: { ...paginationQuery2, region: "{region}", name: "{name}" } } },
|
|
78059
80466
|
{ name: "volumes.create", class: "mutation", description: "Create a block-storage volume.", parameters: { type: "object", properties: { volume: { type: "object" } }, required: ["volume"] }, request: { method: "POST", path: "/v2/volumes", body: "{volume}" }, cas: "none", externalEffect: true },
|
|
78060
80467
|
{ name: "volumes.delete", class: "mutation", description: "Delete a block-storage volume.", parameters: { type: "object", properties: { volumeId: { type: "string" } }, required: ["volumeId"] }, request: { method: "DELETE", path: "/v2/volumes/{volumeId}" }, cas: "optimistic-read-verify", externalEffect: true },
|
|
78061
|
-
{ name: "databases.list", class: "read", description: "List managed database clusters.", parameters: { type: "object", properties: { ...
|
|
80468
|
+
{ name: "databases.list", class: "read", description: "List managed database clusters.", parameters: { type: "object", properties: { ...pagination3, tagName: { type: "string" } } }, request: { method: "GET", path: "/v2/databases", query: { ...paginationQuery2, tag_name: "{tagName}" } } },
|
|
78062
80469
|
{ name: "databases.get", class: "read", description: "Read a managed database cluster.", parameters: { type: "object", properties: { databaseId: { type: "string" } }, required: ["databaseId"] }, request: { method: "GET", path: "/v2/databases/{databaseId}" } },
|
|
78063
80470
|
{ name: "databases.create", class: "mutation", description: "Create a managed database cluster.", parameters: { type: "object", properties: { database: { type: "object" } }, required: ["database"] }, request: { method: "POST", path: "/v2/databases", body: "{database}" }, cas: "none", externalEffect: true },
|
|
78064
80471
|
{ name: "databases.delete", class: "mutation", description: "Delete a managed database cluster.", parameters: { type: "object", properties: { databaseId: { type: "string" } }, required: ["databaseId"] }, request: { method: "DELETE", path: "/v2/databases/{databaseId}" }, cas: "optimistic-read-verify", externalEffect: true },
|
|
78065
|
-
{ name: "apps.list", class: "read", description: "List App Platform apps.", parameters: { type: "object", properties:
|
|
80472
|
+
{ name: "apps.list", class: "read", description: "List App Platform apps.", parameters: { type: "object", properties: pagination3 }, request: { method: "GET", path: "/v2/apps", query: paginationQuery2 } },
|
|
78066
80473
|
{ name: "apps.get", class: "read", description: "Read an App Platform app.", parameters: { type: "object", properties: { appId: { type: "string" } }, required: ["appId"] }, request: { method: "GET", path: "/v2/apps/{appId}" } },
|
|
78067
80474
|
{ name: "apps.create", class: "mutation", description: "Create an App Platform app.", parameters: { type: "object", properties: { spec: { type: "object" } }, required: ["spec"] }, request: { method: "POST", path: "/v2/apps", body: { spec: "{spec}" } }, cas: "none", externalEffect: true },
|
|
78068
80475
|
{ name: "apps.update", class: "mutation", description: "Update an App Platform app specification.", parameters: { type: "object", properties: { appId: { type: "string" }, spec: { type: "object" } }, required: ["appId", "spec"] }, request: { method: "PUT", path: "/v2/apps/{appId}", body: { spec: "{spec}" } }, cas: "optimistic-read-verify", externalEffect: true },
|
|
@@ -78071,11 +80478,11 @@ var digitalOceanConnector = declarativeRestConnector({
|
|
|
78071
80478
|
});
|
|
78072
80479
|
|
|
78073
80480
|
// src/connectors/adapters/clicksend.ts
|
|
78074
|
-
var
|
|
80481
|
+
var pagination4 = {
|
|
78075
80482
|
page: { type: "integer", minimum: 1 },
|
|
78076
80483
|
limit: { type: "integer", minimum: 1 }
|
|
78077
80484
|
};
|
|
78078
|
-
var
|
|
80485
|
+
var paginationQuery3 = { page: "{page}", limit: "{limit}" };
|
|
78079
80486
|
var listId = { listId: { type: "integer" } };
|
|
78080
80487
|
var contactId = { contactId: { type: "integer" } };
|
|
78081
80488
|
var clicksendConnector = declarativeRestConnector({
|
|
@@ -78107,8 +80514,8 @@ var clicksendConnector = declarativeRestConnector({
|
|
|
78107
80514
|
name: "lists.list",
|
|
78108
80515
|
class: "read",
|
|
78109
80516
|
description: "List contact lists.",
|
|
78110
|
-
parameters: { type: "object", properties:
|
|
78111
|
-
request: { method: "GET", path: "/lists", query:
|
|
80517
|
+
parameters: { type: "object", properties: pagination4 },
|
|
80518
|
+
request: { method: "GET", path: "/lists", query: paginationQuery3 }
|
|
78112
80519
|
},
|
|
78113
80520
|
{
|
|
78114
80521
|
name: "lists.get",
|
|
@@ -78158,13 +80565,13 @@ var clicksendConnector = declarativeRestConnector({
|
|
|
78158
80565
|
description: "List contacts in a list.",
|
|
78159
80566
|
parameters: {
|
|
78160
80567
|
type: "object",
|
|
78161
|
-
properties: { ...listId, ...
|
|
80568
|
+
properties: { ...listId, ...pagination4, updatedAfter: { type: "integer" } },
|
|
78162
80569
|
required: ["listId"]
|
|
78163
80570
|
},
|
|
78164
80571
|
request: {
|
|
78165
80572
|
method: "GET",
|
|
78166
80573
|
path: "/lists/{listId}/contacts",
|
|
78167
|
-
query: { ...
|
|
80574
|
+
query: { ...paginationQuery3, updated_after: "{updatedAfter}" }
|
|
78168
80575
|
}
|
|
78169
80576
|
},
|
|
78170
80577
|
{
|
|
@@ -78234,7 +80641,7 @@ var clicksendConnector = declarativeRestConnector({
|
|
|
78234
80641
|
query: { type: "string" },
|
|
78235
80642
|
dateFrom: { type: "integer" },
|
|
78236
80643
|
dateTo: { type: "integer" },
|
|
78237
|
-
...
|
|
80644
|
+
...pagination4
|
|
78238
80645
|
}
|
|
78239
80646
|
},
|
|
78240
80647
|
request: {
|
|
@@ -78244,7 +80651,7 @@ var clicksendConnector = declarativeRestConnector({
|
|
|
78244
80651
|
q: "{query}",
|
|
78245
80652
|
date_from: "{dateFrom}",
|
|
78246
80653
|
date_to: "{dateTo}",
|
|
78247
|
-
...
|
|
80654
|
+
...paginationQuery3
|
|
78248
80655
|
}
|
|
78249
80656
|
}
|
|
78250
80657
|
},
|
|
@@ -78254,16 +80661,16 @@ var clicksendConnector = declarativeRestConnector({
|
|
|
78254
80661
|
description: "List inbound SMS messages.",
|
|
78255
80662
|
parameters: {
|
|
78256
80663
|
type: "object",
|
|
78257
|
-
properties: { query: { type: "string" }, ...
|
|
80664
|
+
properties: { query: { type: "string" }, ...pagination4 }
|
|
78258
80665
|
},
|
|
78259
|
-
request: { method: "GET", path: "/sms/inbound", query: { q: "{query}", ...
|
|
80666
|
+
request: { method: "GET", path: "/sms/inbound", query: { q: "{query}", ...paginationQuery3 } }
|
|
78260
80667
|
},
|
|
78261
80668
|
{
|
|
78262
80669
|
name: "sms.receipts.list",
|
|
78263
80670
|
class: "read",
|
|
78264
80671
|
description: "List SMS delivery receipts.",
|
|
78265
|
-
parameters: { type: "object", properties:
|
|
78266
|
-
request: { method: "GET", path: "/sms/receipts", query:
|
|
80672
|
+
parameters: { type: "object", properties: pagination4 },
|
|
80673
|
+
request: { method: "GET", path: "/sms/receipts", query: paginationQuery3 }
|
|
78267
80674
|
},
|
|
78268
80675
|
{
|
|
78269
80676
|
name: "sms.send",
|
|
@@ -78299,12 +80706,12 @@ var clicksendConnector = declarativeRestConnector({
|
|
|
78299
80706
|
description: "List voice message history.",
|
|
78300
80707
|
parameters: {
|
|
78301
80708
|
type: "object",
|
|
78302
|
-
properties: { dateFrom: { type: "integer" }, dateTo: { type: "integer" }, ...
|
|
80709
|
+
properties: { dateFrom: { type: "integer" }, dateTo: { type: "integer" }, ...pagination4 }
|
|
78303
80710
|
},
|
|
78304
80711
|
request: {
|
|
78305
80712
|
method: "GET",
|
|
78306
80713
|
path: "/voice/history",
|
|
78307
|
-
query: { date_from: "{dateFrom}", date_to: "{dateTo}", ...
|
|
80714
|
+
query: { date_from: "{dateFrom}", date_to: "{dateTo}", ...paginationQuery3 }
|
|
78308
80715
|
}
|
|
78309
80716
|
},
|
|
78310
80717
|
{
|
|
@@ -79474,7 +81881,7 @@ function readQuery2(inv) {
|
|
|
79474
81881
|
throw new Error(`Unknown MySQL read capability: ${inv.capabilityName}`);
|
|
79475
81882
|
}
|
|
79476
81883
|
function readStatementArgs(args) {
|
|
79477
|
-
const statement =
|
|
81884
|
+
const statement = requiredString8(args.statement, "statement");
|
|
79478
81885
|
if (Buffer.byteLength(statement, "utf8") > 1024 * 1024) throw new Error("statement exceeds the 1 MiB limit");
|
|
79479
81886
|
const parameters = args.parameters === void 0 ? [] : args.parameters;
|
|
79480
81887
|
if (!Array.isArray(parameters) || parameters.length > MAX_PARAMETERS) {
|
|
@@ -79565,7 +81972,7 @@ function readDatabase(value, source) {
|
|
|
79565
81972
|
function queryTimeout(source) {
|
|
79566
81973
|
return readCredentials7(source).queryTimeoutMs;
|
|
79567
81974
|
}
|
|
79568
|
-
function
|
|
81975
|
+
function requiredString8(value, label) {
|
|
79569
81976
|
const parsed = readOptionalString(value, label);
|
|
79570
81977
|
if (!parsed) throw new Error(`${label} is required`);
|
|
79571
81978
|
return parsed;
|
|
@@ -79577,7 +81984,7 @@ function requiredCredentialString3(value, label, maxLength) {
|
|
|
79577
81984
|
return parsed;
|
|
79578
81985
|
}
|
|
79579
81986
|
function readIdentifier2(value, label) {
|
|
79580
|
-
const parsed =
|
|
81987
|
+
const parsed = requiredString8(value, label);
|
|
79581
81988
|
if (parsed.length > 64) throw new Error(`${label} exceeds 64 characters`);
|
|
79582
81989
|
return parsed;
|
|
79583
81990
|
}
|
|
@@ -81147,6 +83554,8 @@ var CONNECTOR_ADAPTER_FACTORIES = [
|
|
|
81147
83554
|
defineFactoryAdapter(() => segmentConnector, {}),
|
|
81148
83555
|
defineFactoryAdapter(() => hightouchConnector, {}),
|
|
81149
83556
|
defineFactoryAdapter(() => datadogConnector, {}),
|
|
83557
|
+
defineFactoryAdapter(() => amplitudeConnector, {}),
|
|
83558
|
+
defineFactoryAdapter(() => cloudflareConnector, {}),
|
|
81150
83559
|
defineFactoryAdapter(() => discourseConnector, {}),
|
|
81151
83560
|
defineFactoryAdapter(() => digitalOceanConnector, {}),
|
|
81152
83561
|
defineFactoryAdapter(() => clicksendConnector, {}),
|
|
@@ -81177,6 +83586,10 @@ var CONNECTOR_ADAPTER_FACTORIES = [
|
|
|
81177
83586
|
clientId: "TWITTER_OAUTH_CLIENT_ID",
|
|
81178
83587
|
clientSecret: "TWITTER_OAUTH_CLIENT_SECRET"
|
|
81179
83588
|
}),
|
|
83589
|
+
defineFactoryAdapter(tiktok, {
|
|
83590
|
+
clientId: "TIKTOK_OAUTH_CLIENT_KEY",
|
|
83591
|
+
clientSecret: "TIKTOK_OAUTH_CLIENT_SECRET"
|
|
83592
|
+
}),
|
|
81180
83593
|
// Declarative OAuth2 connectors: the manifest already pins clientIdEnv /
|
|
81181
83594
|
// clientSecretEnv; the envMap re-pins the same names so registration is
|
|
81182
83595
|
// gated on the OAuth app actually being configured (no half-live connector).
|
|
@@ -81204,6 +83617,8 @@ var CONNECTOR_ADAPTER_FACTORIES = [
|
|
|
81204
83617
|
// credentials from each connection; OAuth providers are registered only
|
|
81205
83618
|
// when the shared application credentials are present.
|
|
81206
83619
|
defineFactoryAdapter(() => amazonEventBridgeConnector, {}),
|
|
83620
|
+
defineFactoryAdapter(() => amazonLambdaConnector, {}),
|
|
83621
|
+
defineFactoryAdapter(() => amazonCloudWatchConnector, {}),
|
|
81207
83622
|
defineFactoryAdapter(() => amazonS3Connector, {}),
|
|
81208
83623
|
defineFactoryAdapter(() => amazonSnsConnector, {}),
|
|
81209
83624
|
defineFactoryAdapter(() => amazonSqsConnector, {}),
|
|
@@ -81253,9 +83668,8 @@ var CONNECTOR_ADAPTER_FACTORIES = [
|
|
|
81253
83668
|
clientId: "ACUITY_OAUTH_CLIENT_ID",
|
|
81254
83669
|
clientSecret: "ACUITY_OAUTH_CLIENT_SECRET"
|
|
81255
83670
|
}),
|
|
81256
|
-
defineFactoryAdapter(
|
|
81257
|
-
clientId: "CALCOM_OAUTH_CLIENT_ID"
|
|
81258
|
-
clientSecret: "CALCOM_OAUTH_CLIENT_SECRET"
|
|
83671
|
+
defineFactoryAdapter(calCom, {
|
|
83672
|
+
clientId: "CALCOM_OAUTH_CLIENT_ID"
|
|
81259
83673
|
}),
|
|
81260
83674
|
defineFactoryAdapter(() => savvycalConnector, {
|
|
81261
83675
|
clientId: "SAVVYCAL_OAUTH_CLIENT_ID",
|
|
@@ -81627,7 +84041,7 @@ var CONNECTOR_ADAPTER_FACTORIES = [
|
|
|
81627
84041
|
clientId: "PUSHBULLET_OAUTH_CLIENT_ID",
|
|
81628
84042
|
clientSecret: "PUSHBULLET_OAUTH_CLIENT_SECRET"
|
|
81629
84043
|
}),
|
|
81630
|
-
defineFactoryAdapter(
|
|
84044
|
+
defineFactoryAdapter(reddit, {
|
|
81631
84045
|
clientId: "REDDIT_OAUTH_CLIENT_ID",
|
|
81632
84046
|
clientSecret: "REDDIT_OAUTH_CLIENT_SECRET"
|
|
81633
84047
|
}),
|
|
@@ -146461,6 +148875,7 @@ export {
|
|
|
146461
148875
|
consumePendingFlow,
|
|
146462
148876
|
exchangeAuthorizationCode,
|
|
146463
148877
|
refreshAccessToken,
|
|
148878
|
+
createOAuthTokenRequestHeaders,
|
|
146464
148879
|
_resetPendingFlowsForTests,
|
|
146465
148880
|
declarativeRestConnector,
|
|
146466
148881
|
oktaConnector,
|
|
@@ -146537,6 +148952,7 @@ export {
|
|
|
146537
148952
|
paychexConnector,
|
|
146538
148953
|
pushbulletConnector,
|
|
146539
148954
|
redditConnector,
|
|
148955
|
+
reddit,
|
|
146540
148956
|
ripplingConnector,
|
|
146541
148957
|
sanityConnector,
|
|
146542
148958
|
sendpulseConnector,
|
|
@@ -146552,7 +148968,10 @@ export {
|
|
|
146552
148968
|
adobeSignConnector,
|
|
146553
148969
|
aircallConnector,
|
|
146554
148970
|
affinityConnector,
|
|
148971
|
+
amplitudeConnector,
|
|
146555
148972
|
amazonEventBridgeConnector,
|
|
148973
|
+
amazonCloudWatchConnector,
|
|
148974
|
+
amazonLambdaConnector,
|
|
146556
148975
|
amazonS3Connector,
|
|
146557
148976
|
amazonSnsConnector,
|
|
146558
148977
|
amazonSqsConnector,
|
|
@@ -146575,10 +148994,12 @@ export {
|
|
|
146575
148994
|
billComConnector,
|
|
146576
148995
|
billplzConnector,
|
|
146577
148996
|
calComConnector,
|
|
148997
|
+
calCom,
|
|
146578
148998
|
calendlyConnector,
|
|
146579
148999
|
capsuleCrmConnector,
|
|
146580
149000
|
closeConnector,
|
|
146581
149001
|
clickupConnector,
|
|
149002
|
+
cloudflareConnector,
|
|
146582
149003
|
cloudinaryConnector,
|
|
146583
149004
|
codaConnector,
|
|
146584
149005
|
confluenceConnector,
|
|
@@ -146723,6 +149144,8 @@ export {
|
|
|
146723
149144
|
typeformConnector,
|
|
146724
149145
|
twitterConnector,
|
|
146725
149146
|
twitter,
|
|
149147
|
+
tiktokConnector,
|
|
149148
|
+
tiktok,
|
|
146726
149149
|
twilioSmsConnector,
|
|
146727
149150
|
voucheryIoConnector,
|
|
146728
149151
|
whatsappBusiness,
|
|
@@ -147110,4 +149533,4 @@ export {
|
|
|
147110
149533
|
getresponseConnector,
|
|
147111
149534
|
adapters_exports
|
|
147112
149535
|
};
|
|
147113
|
-
//# sourceMappingURL=chunk-
|
|
149536
|
+
//# sourceMappingURL=chunk-H5UCSRF4.js.map
|