@tangle-network/agent-integrations 0.53.48 → 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 +8 -8
- package/dist/{chunk-PXOM5AVK.js → chunk-5UCHLQ3D.js} +4 -3
- package/dist/{chunk-PXOM5AVK.js.map → chunk-5UCHLQ3D.js.map} +1 -1
- package/dist/{chunk-GY4PFAWA.js → chunk-GUZA3U6T.js} +7 -9
- package/dist/chunk-GUZA3U6T.js.map +1 -0
- package/dist/{chunk-HNEEIMQC.js → chunk-H5UCSRF4.js} +437 -236
- package/dist/{chunk-HNEEIMQC.js.map → chunk-H5UCSRF4.js.map} +1 -1
- package/dist/{chunk-EZR72HCQ.js → chunk-KBYYTHXQ.js} +2 -2
- package/dist/{chunk-I5EF5KIT.js → chunk-UI3U62H6.js} +2 -2
- package/dist/{chunk-RRSNINEV.js → chunk-W72KPXXX.js} +9 -1
- package/dist/chunk-W72KPXXX.js.map +1 -0
- package/dist/{chunk-CBWD2IOL.js → chunk-ZSXRS7D7.js} +2 -2
- package/dist/{chunk-Q7TDHVRZ.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 +16 -19
- package/dist/connectors/adapters/index.js +4 -2
- package/dist/connectors/index.d.ts +13 -5
- package/dist/connectors/index.js +7 -3
- package/dist/{consumer-BcFIDgMD.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-CE1oMiuI.d.ts → core-types-D26cY5tD.d.ts} +1 -1
- package/dist/coverage-catalog.d.ts +2 -2
- package/dist/{importers-CHOC-2Y8.d.ts → importers-CQKts3pm.d.ts} +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +12 -8
- package/dist/mcp.d.ts +3 -3
- package/dist/mcp.js +8 -8
- 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 +8 -8
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +8 -8
- package/dist/specs.d.ts +2 -2
- package/dist/specs.js +4 -4
- package/dist/{tangle-id-BL_JQwKA.d.ts → tangle-id-BCOVbWrP.d.ts} +1 -1
- package/dist/{types-EXGqQYoU.d.ts → types-DpKn0frG.d.ts} +4 -0
- package/package.json +1 -1
- package/dist/chunk-GY4PFAWA.js.map +0 -1
- package/dist/chunk-RRSNINEV.js.map +0 -1
- /package/dist/{chunk-EZR72HCQ.js.map → chunk-KBYYTHXQ.js.map} +0 -0
- /package/dist/{chunk-I5EF5KIT.js.map → chunk-UI3U62H6.js.map} +0 -0
- /package/dist/{chunk-CBWD2IOL.js.map → chunk-ZSXRS7D7.js.map} +0 -0
- /package/dist/{chunk-Q7TDHVRZ.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";
|
|
@@ -530,6 +530,7 @@ __export(adapters_exports, {
|
|
|
530
530
|
reachinboxConnector: () => reachinboxConnector,
|
|
531
531
|
recallAiConnector: () => recallAiConnector,
|
|
532
532
|
recurlyConnector: () => recurlyConnector,
|
|
533
|
+
reddit: () => reddit,
|
|
533
534
|
redditConnector: () => redditConnector,
|
|
534
535
|
redisConnector: () => redisConnector,
|
|
535
536
|
redshiftConnector: () => redshiftConnector,
|
|
@@ -978,8 +979,9 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
978
979
|
if (hostOverride) url.host = hostOverride.replace(/\{region\}/g, awsRegion);
|
|
979
980
|
if (inv.expectedEtag) headers["if-match"] = inv.expectedEtag;
|
|
980
981
|
const sendsBody = request4.method !== "GET" && (request4.method !== "DELETE" || request4.body !== void 0);
|
|
982
|
+
const bodyEncoding = request4.bodyEncoding ?? "json";
|
|
981
983
|
if (sendsBody && getHeaderCI(headers, "content-type") === void 0) {
|
|
982
|
-
headers["content-type"] = "application/json";
|
|
984
|
+
headers["content-type"] = bodyEncoding === "form" ? "application/x-www-form-urlencoded" : "application/json";
|
|
983
985
|
}
|
|
984
986
|
let resolvedBody = sendsBody ? resolveBody(request4.body, inv.args, scope, requiredArgs) : void 0;
|
|
985
987
|
if (placement.kind === "structured-json-body") {
|
|
@@ -996,7 +998,7 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
996
998
|
)
|
|
997
999
|
};
|
|
998
1000
|
}
|
|
999
|
-
const bodyString = sendsBody ?
|
|
1001
|
+
const bodyString = sendsBody ? serializeRequestBody(spec.kind, bodyEncoding, resolvedBody) : void 0;
|
|
1000
1002
|
if (placement.kind === "aws-sigv4") {
|
|
1001
1003
|
signAwsRequest(headers, url, {
|
|
1002
1004
|
method: request4.method,
|
|
@@ -1072,6 +1074,21 @@ async function executeRestRequest(spec, request4, inv, requiredArgs) {
|
|
|
1072
1074
|
}
|
|
1073
1075
|
return { data: data4, etag: res.headers.get("etag") ?? void 0 };
|
|
1074
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
|
+
}
|
|
1075
1092
|
function resolveBaseUrl(baseUrl4, metadata, allowedBaseUrls, allowedBaseUrlSuffixes, requirePublicHttpsBaseUrl) {
|
|
1076
1093
|
let resolved;
|
|
1077
1094
|
if (typeof baseUrl4 === "string") {
|
|
@@ -16131,40 +16148,228 @@ var pushbulletConnector = declarativeRestConnector({
|
|
|
16131
16148
|
]
|
|
16132
16149
|
});
|
|
16133
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
|
+
|
|
16134
16332
|
// src/connectors/adapters/reddit.ts
|
|
16135
|
-
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 = {
|
|
16136
16336
|
kind: "reddit",
|
|
16137
16337
|
displayName: "Reddit",
|
|
16138
16338
|
description: "Interact with Reddit \u2014 fetch and submit posts, retrieve comments, create and edit posts/comments.",
|
|
16139
16339
|
auth: {
|
|
16140
16340
|
kind: "oauth2",
|
|
16141
16341
|
authorizationUrl: "https://www.reddit.com/api/v1/authorize",
|
|
16142
|
-
tokenUrl:
|
|
16143
|
-
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 },
|
|
16144
16348
|
clientIdEnv: "REDDIT_OAUTH_CLIENT_ID",
|
|
16145
16349
|
clientSecretEnv: "REDDIT_OAUTH_CLIENT_SECRET"
|
|
16146
16350
|
},
|
|
16147
16351
|
category: "comms",
|
|
16148
16352
|
defaultConsistencyModel: "authoritative",
|
|
16149
16353
|
baseUrl: "https://oauth.reddit.com",
|
|
16354
|
+
defaultHeaders: { "User-Agent": REDDIT_USER_AGENT },
|
|
16150
16355
|
test: { method: "GET", path: "/api/v1/me" },
|
|
16151
16356
|
capabilities: [
|
|
16152
16357
|
{
|
|
16153
16358
|
name: "post.retrieve",
|
|
16154
16359
|
class: "read",
|
|
16155
|
-
description: "Retrieve a Reddit post by its
|
|
16360
|
+
description: "Retrieve a Reddit post by its fullname, such as t3_abc123.",
|
|
16156
16361
|
parameters: {
|
|
16157
16362
|
type: "object",
|
|
16158
16363
|
properties: {
|
|
16159
|
-
postId: { type: "string" }
|
|
16364
|
+
postId: { type: "string", description: "Reddit post fullname, such as t3_abc123." }
|
|
16160
16365
|
},
|
|
16161
16366
|
required: ["postId"]
|
|
16162
16367
|
},
|
|
16163
16368
|
request: {
|
|
16164
16369
|
method: "GET",
|
|
16165
|
-
path: "/
|
|
16166
|
-
|
|
16167
|
-
|
|
16370
|
+
path: "/api/info",
|
|
16371
|
+
query: {
|
|
16372
|
+
id: "{postId}"
|
|
16168
16373
|
}
|
|
16169
16374
|
},
|
|
16170
16375
|
requiredScopes: ["read"]
|
|
@@ -16183,10 +16388,7 @@ var redditConnector = declarativeRestConnector({
|
|
|
16183
16388
|
},
|
|
16184
16389
|
request: {
|
|
16185
16390
|
method: "GET",
|
|
16186
|
-
path: "/r/{subreddit}/comments/{postId}"
|
|
16187
|
-
headers: {
|
|
16188
|
-
"User-Agent": "AgentDev/1.0"
|
|
16189
|
-
}
|
|
16391
|
+
path: "/r/{subreddit}/comments/{postId}"
|
|
16190
16392
|
},
|
|
16191
16393
|
requiredScopes: ["read"]
|
|
16192
16394
|
},
|
|
@@ -16199,27 +16401,28 @@ var redditConnector = declarativeRestConnector({
|
|
|
16199
16401
|
properties: {
|
|
16200
16402
|
subreddit: { type: "string" },
|
|
16201
16403
|
title: { type: "string" },
|
|
16404
|
+
kind: { type: "string", enum: ["self", "link"] },
|
|
16202
16405
|
text: { type: "string" },
|
|
16203
16406
|
url: { type: "string" },
|
|
16204
16407
|
flair_id: { type: "string" }
|
|
16205
16408
|
},
|
|
16206
|
-
required: ["subreddit", "title"]
|
|
16409
|
+
required: ["subreddit", "title", "kind"]
|
|
16207
16410
|
},
|
|
16208
16411
|
request: {
|
|
16209
16412
|
method: "POST",
|
|
16210
|
-
path: "/
|
|
16413
|
+
path: "/api/submit",
|
|
16414
|
+
bodyEncoding: "form",
|
|
16211
16415
|
body: {
|
|
16416
|
+
api_type: "json",
|
|
16417
|
+
sr: "{subreddit}",
|
|
16212
16418
|
title: "{title}",
|
|
16419
|
+
kind: "{kind}",
|
|
16213
16420
|
text: "{text}",
|
|
16214
16421
|
url: "{url}",
|
|
16215
|
-
flair_id: "{flair_id}"
|
|
16216
|
-
kind: "self"
|
|
16217
|
-
},
|
|
16218
|
-
headers: {
|
|
16219
|
-
"User-Agent": "AgentDev/1.0"
|
|
16422
|
+
flair_id: "{flair_id}"
|
|
16220
16423
|
}
|
|
16221
16424
|
},
|
|
16222
|
-
cas: "
|
|
16425
|
+
cas: "none",
|
|
16223
16426
|
externalEffect: true,
|
|
16224
16427
|
requiredScopes: ["submit"]
|
|
16225
16428
|
},
|
|
@@ -16238,15 +16441,14 @@ var redditConnector = declarativeRestConnector({
|
|
|
16238
16441
|
request: {
|
|
16239
16442
|
method: "POST",
|
|
16240
16443
|
path: "/api/comment",
|
|
16444
|
+
bodyEncoding: "form",
|
|
16241
16445
|
body: {
|
|
16446
|
+
api_type: "json",
|
|
16242
16447
|
thing_id: "{parentId}",
|
|
16243
16448
|
text: "{text}"
|
|
16244
|
-
},
|
|
16245
|
-
headers: {
|
|
16246
|
-
"User-Agent": "AgentDev/1.0"
|
|
16247
16449
|
}
|
|
16248
16450
|
},
|
|
16249
|
-
cas: "
|
|
16451
|
+
cas: "none",
|
|
16250
16452
|
externalEffect: true,
|
|
16251
16453
|
requiredScopes: ["submit"]
|
|
16252
16454
|
},
|
|
@@ -16270,9 +16472,6 @@ var redditConnector = declarativeRestConnector({
|
|
|
16270
16472
|
query: {
|
|
16271
16473
|
sort: "{sort}",
|
|
16272
16474
|
limit: "{limit}"
|
|
16273
|
-
},
|
|
16274
|
-
headers: {
|
|
16275
|
-
"User-Agent": "AgentDev/1.0"
|
|
16276
16475
|
}
|
|
16277
16476
|
},
|
|
16278
16477
|
requiredScopes: ["read"]
|
|
@@ -16292,15 +16491,15 @@ var redditConnector = declarativeRestConnector({
|
|
|
16292
16491
|
request: {
|
|
16293
16492
|
method: "POST",
|
|
16294
16493
|
path: "/api/editusertext",
|
|
16494
|
+
bodyEncoding: "form",
|
|
16295
16495
|
body: {
|
|
16496
|
+
api_type: "json",
|
|
16296
16497
|
thing_id: "{thingId}",
|
|
16297
16498
|
text: "{text}"
|
|
16298
|
-
},
|
|
16299
|
-
headers: {
|
|
16300
|
-
"User-Agent": "AgentDev/1.0"
|
|
16301
16499
|
}
|
|
16302
16500
|
},
|
|
16303
|
-
cas: "
|
|
16501
|
+
cas: "none",
|
|
16502
|
+
externalEffect: true,
|
|
16304
16503
|
requiredScopes: ["edit"]
|
|
16305
16504
|
},
|
|
16306
16505
|
{
|
|
@@ -16318,15 +16517,15 @@ var redditConnector = declarativeRestConnector({
|
|
|
16318
16517
|
request: {
|
|
16319
16518
|
method: "POST",
|
|
16320
16519
|
path: "/api/editusertext",
|
|
16520
|
+
bodyEncoding: "form",
|
|
16321
16521
|
body: {
|
|
16522
|
+
api_type: "json",
|
|
16322
16523
|
thing_id: "{thingId}",
|
|
16323
16524
|
text: "{text}"
|
|
16324
|
-
},
|
|
16325
|
-
headers: {
|
|
16326
|
-
"User-Agent": "AgentDev/1.0"
|
|
16327
16525
|
}
|
|
16328
16526
|
},
|
|
16329
|
-
cas: "
|
|
16527
|
+
cas: "none",
|
|
16528
|
+
externalEffect: true,
|
|
16330
16529
|
requiredScopes: ["edit"]
|
|
16331
16530
|
},
|
|
16332
16531
|
{
|
|
@@ -16343,13 +16542,12 @@ var redditConnector = declarativeRestConnector({
|
|
|
16343
16542
|
request: {
|
|
16344
16543
|
method: "POST",
|
|
16345
16544
|
path: "/api/del",
|
|
16545
|
+
bodyEncoding: "form",
|
|
16346
16546
|
body: {
|
|
16347
16547
|
id: "{thingId}"
|
|
16348
|
-
},
|
|
16349
|
-
headers: {
|
|
16350
|
-
"User-Agent": "AgentDev/1.0"
|
|
16351
16548
|
}
|
|
16352
16549
|
},
|
|
16550
|
+
cas: "none",
|
|
16353
16551
|
externalEffect: true,
|
|
16354
16552
|
requiredScopes: ["edit"]
|
|
16355
16553
|
},
|
|
@@ -16367,18 +16565,150 @@ var redditConnector = declarativeRestConnector({
|
|
|
16367
16565
|
request: {
|
|
16368
16566
|
method: "POST",
|
|
16369
16567
|
path: "/api/del",
|
|
16568
|
+
bodyEncoding: "form",
|
|
16370
16569
|
body: {
|
|
16371
16570
|
id: "{thingId}"
|
|
16372
|
-
},
|
|
16373
|
-
headers: {
|
|
16374
|
-
"User-Agent": "AgentDev/1.0"
|
|
16375
16571
|
}
|
|
16376
16572
|
},
|
|
16573
|
+
cas: "none",
|
|
16377
16574
|
externalEffect: true,
|
|
16378
16575
|
requiredScopes: ["edit"]
|
|
16379
16576
|
}
|
|
16380
16577
|
]
|
|
16381
|
-
}
|
|
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
|
+
}
|
|
16382
16712
|
|
|
16383
16713
|
// src/connectors/adapters/rippling.ts
|
|
16384
16714
|
var ripplingConnector = declarativeRestConnector({
|
|
@@ -24774,7 +25104,7 @@ function numberOrUndefined(value) {
|
|
|
24774
25104
|
}
|
|
24775
25105
|
|
|
24776
25106
|
// src/connectors/adapters/azure-event-grid.ts
|
|
24777
|
-
import { createHash as
|
|
25107
|
+
import { createHash as createHash4, timingSafeEqual } from "crypto";
|
|
24778
25108
|
var API_VERSION2 = "2018-01-01";
|
|
24779
25109
|
var MAX_BATCH_BYTES = 1024 * 1024;
|
|
24780
25110
|
var MAX_EVENTS = 5e3;
|
|
@@ -24843,8 +25173,8 @@ var azureEventGridConnector = {
|
|
|
24843
25173
|
}
|
|
24844
25174
|
const provided = headerValue(headers, "x-tangle-eventgrid-secret");
|
|
24845
25175
|
if (!provided) return { valid: false, reason: "Missing x-tangle-eventgrid-secret delivery header" };
|
|
24846
|
-
const expectedDigest =
|
|
24847
|
-
const providedDigest =
|
|
25176
|
+
const expectedDigest = createHash4("sha256").update(credentials.deliverySecret).digest();
|
|
25177
|
+
const providedDigest = createHash4("sha256").update(provided).digest();
|
|
24848
25178
|
return timingSafeEqual(expectedDigest, providedDigest) ? { valid: true } : { valid: false, reason: "Invalid x-tangle-eventgrid-secret delivery header" };
|
|
24849
25179
|
},
|
|
24850
25180
|
async handleInboundEvent({ rawBody }) {
|
|
@@ -27362,186 +27692,6 @@ var billplzConnector = declarativeRestConnector({
|
|
|
27362
27692
|
]
|
|
27363
27693
|
});
|
|
27364
27694
|
|
|
27365
|
-
// src/connectors/oauth.ts
|
|
27366
|
-
import { createHash as createHash4, randomBytes } from "crypto";
|
|
27367
|
-
var PENDING_TTL_MS = 10 * 60 * 1e3;
|
|
27368
|
-
var InMemoryOAuthFlowStore = class {
|
|
27369
|
-
pendingFlows = /* @__PURE__ */ new Map();
|
|
27370
|
-
put(state, flow) {
|
|
27371
|
-
this.pendingFlows.set(state, flow);
|
|
27372
|
-
}
|
|
27373
|
-
consume(state) {
|
|
27374
|
-
const flow = this.pendingFlows.get(state);
|
|
27375
|
-
this.pendingFlows.delete(state);
|
|
27376
|
-
if (!flow || flow.expiresAt <= Date.now()) return void 0;
|
|
27377
|
-
return flow;
|
|
27378
|
-
}
|
|
27379
|
-
sweep(now) {
|
|
27380
|
-
for (const [k, v] of this.pendingFlows) {
|
|
27381
|
-
if (v.expiresAt <= now) this.pendingFlows.delete(k);
|
|
27382
|
-
}
|
|
27383
|
-
}
|
|
27384
|
-
clear() {
|
|
27385
|
-
this.pendingFlows.clear();
|
|
27386
|
-
}
|
|
27387
|
-
};
|
|
27388
|
-
var defaultFlowStore = new InMemoryOAuthFlowStore();
|
|
27389
|
-
function startOAuthFlow(input) {
|
|
27390
|
-
const store = input.store ?? defaultFlowStore;
|
|
27391
|
-
const now = input.now ?? Date.now();
|
|
27392
|
-
store.sweep?.(now);
|
|
27393
|
-
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
27394
|
-
const codeVerifier = usePkce ? base64Url(randomBytes(48)) : void 0;
|
|
27395
|
-
const codeChallenge = codeVerifier ? base64Url(createHash4("sha256").update(codeVerifier).digest()) : void 0;
|
|
27396
|
-
const state = base64Url(randomBytes(24));
|
|
27397
|
-
store.put(state, {
|
|
27398
|
-
codeVerifier,
|
|
27399
|
-
state,
|
|
27400
|
-
projectId: input.projectId,
|
|
27401
|
-
kind: input.kind,
|
|
27402
|
-
label: input.label,
|
|
27403
|
-
redirectUri: input.redirectUri,
|
|
27404
|
-
expiresAt: now + PENDING_TTL_MS
|
|
27405
|
-
});
|
|
27406
|
-
const url = new URL(input.authorizationUrl);
|
|
27407
|
-
url.searchParams.set("response_type", "code");
|
|
27408
|
-
url.searchParams.set(
|
|
27409
|
-
oauthParameterName(input.authorizationClientIdParam, "client_id"),
|
|
27410
|
-
input.clientId
|
|
27411
|
-
);
|
|
27412
|
-
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
27413
|
-
url.searchParams.set("scope", input.scopes.join(input.scopeSeparator ?? " "));
|
|
27414
|
-
url.searchParams.set("state", state);
|
|
27415
|
-
if (input.extraAuthParams) {
|
|
27416
|
-
for (const [k, v] of Object.entries(input.extraAuthParams)) {
|
|
27417
|
-
url.searchParams.set(k, v);
|
|
27418
|
-
}
|
|
27419
|
-
}
|
|
27420
|
-
if (codeChallenge) {
|
|
27421
|
-
url.searchParams.set("code_challenge", codeChallenge);
|
|
27422
|
-
url.searchParams.set("code_challenge_method", "S256");
|
|
27423
|
-
} else {
|
|
27424
|
-
url.searchParams.delete("code_challenge");
|
|
27425
|
-
url.searchParams.delete("code_challenge_method");
|
|
27426
|
-
}
|
|
27427
|
-
return { authorizationUrl: url.toString(), state };
|
|
27428
|
-
}
|
|
27429
|
-
async function consumePendingFlow(state, store = defaultFlowStore) {
|
|
27430
|
-
await store.sweep?.(Date.now());
|
|
27431
|
-
const flow = await store.consume(state);
|
|
27432
|
-
if (!flow) {
|
|
27433
|
-
throw new Error("Unknown or expired OAuth state: possible CSRF, replay, or stale flow");
|
|
27434
|
-
}
|
|
27435
|
-
return flow;
|
|
27436
|
-
}
|
|
27437
|
-
async function exchangeAuthorizationCode(input) {
|
|
27438
|
-
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
27439
|
-
if (usePkce && !input.codeVerifier) {
|
|
27440
|
-
throw new Error("OAuth token exchange requires a PKCE code_verifier");
|
|
27441
|
-
}
|
|
27442
|
-
const body = new URLSearchParams({
|
|
27443
|
-
grant_type: "authorization_code",
|
|
27444
|
-
code: input.code,
|
|
27445
|
-
redirect_uri: input.redirectUri
|
|
27446
|
-
});
|
|
27447
|
-
if (usePkce) body.set("code_verifier", input.codeVerifier);
|
|
27448
|
-
const headers = {
|
|
27449
|
-
"content-type": "application/x-www-form-urlencoded",
|
|
27450
|
-
accept: "application/json"
|
|
27451
|
-
};
|
|
27452
|
-
applyTokenClientAuthentication(input, body, headers);
|
|
27453
|
-
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
27454
|
-
method: "POST",
|
|
27455
|
-
headers,
|
|
27456
|
-
body,
|
|
27457
|
-
signal: input.signal
|
|
27458
|
-
});
|
|
27459
|
-
if (!res.ok) {
|
|
27460
|
-
const text = await res.text().catch(() => "");
|
|
27461
|
-
throw new Error(`OAuth token exchange failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
27462
|
-
}
|
|
27463
|
-
const json = await res.json();
|
|
27464
|
-
return {
|
|
27465
|
-
accessToken: json.access_token,
|
|
27466
|
-
refreshToken: json.refresh_token,
|
|
27467
|
-
expiresIn: json.expires_in,
|
|
27468
|
-
scope: json.scope,
|
|
27469
|
-
tokenType: json.token_type,
|
|
27470
|
-
idToken: json.id_token
|
|
27471
|
-
};
|
|
27472
|
-
}
|
|
27473
|
-
async function refreshAccessToken(input) {
|
|
27474
|
-
const body = new URLSearchParams({
|
|
27475
|
-
grant_type: "refresh_token",
|
|
27476
|
-
refresh_token: input.refreshToken
|
|
27477
|
-
});
|
|
27478
|
-
const headers = {
|
|
27479
|
-
"content-type": "application/x-www-form-urlencoded",
|
|
27480
|
-
accept: "application/json"
|
|
27481
|
-
};
|
|
27482
|
-
applyTokenClientAuthentication(input, body, headers);
|
|
27483
|
-
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
27484
|
-
method: "POST",
|
|
27485
|
-
headers,
|
|
27486
|
-
body,
|
|
27487
|
-
signal: input.signal
|
|
27488
|
-
});
|
|
27489
|
-
if (!res.ok) {
|
|
27490
|
-
const text = await res.text().catch(() => "");
|
|
27491
|
-
throw new Error(`OAuth refresh failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
27492
|
-
}
|
|
27493
|
-
const json = await res.json();
|
|
27494
|
-
return {
|
|
27495
|
-
accessToken: json.access_token,
|
|
27496
|
-
// Some providers omit refresh_token on refresh — keep the previous one
|
|
27497
|
-
// in that case (caller passes through if undefined).
|
|
27498
|
-
refreshToken: json.refresh_token,
|
|
27499
|
-
expiresIn: json.expires_in,
|
|
27500
|
-
scope: json.scope,
|
|
27501
|
-
tokenType: json.token_type,
|
|
27502
|
-
idToken: json.id_token
|
|
27503
|
-
};
|
|
27504
|
-
}
|
|
27505
|
-
function applyTokenClientAuthentication(input, body, headers) {
|
|
27506
|
-
const method = input.tokenClientAuthMethod ?? "client_secret_post";
|
|
27507
|
-
if (method === "none") {
|
|
27508
|
-
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
27509
|
-
return;
|
|
27510
|
-
}
|
|
27511
|
-
if (!input.clientSecret) {
|
|
27512
|
-
throw new Error(`OAuth ${method} client authentication requires a client secret`);
|
|
27513
|
-
}
|
|
27514
|
-
if (method === "client_secret_post") {
|
|
27515
|
-
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
27516
|
-
body.set(
|
|
27517
|
-
oauthParameterName(input.tokenClientSecretParam, "client_secret"),
|
|
27518
|
-
input.clientSecret
|
|
27519
|
-
);
|
|
27520
|
-
return;
|
|
27521
|
-
}
|
|
27522
|
-
if (method === "client_secret_basic") {
|
|
27523
|
-
headers.authorization = `Basic ${Buffer.from(
|
|
27524
|
-
`${input.clientId}:${input.clientSecret}`,
|
|
27525
|
-
"utf8"
|
|
27526
|
-
).toString("base64")}`;
|
|
27527
|
-
return;
|
|
27528
|
-
}
|
|
27529
|
-
throw new Error("Unsupported OAuth token client authentication method");
|
|
27530
|
-
}
|
|
27531
|
-
function base64Url(buf) {
|
|
27532
|
-
return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
27533
|
-
}
|
|
27534
|
-
function oauthParameterName(value, fallback) {
|
|
27535
|
-
const name = value ?? fallback;
|
|
27536
|
-
if (!/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name)) {
|
|
27537
|
-
throw new Error("Invalid OAuth parameter name");
|
|
27538
|
-
}
|
|
27539
|
-
return name;
|
|
27540
|
-
}
|
|
27541
|
-
function _resetPendingFlowsForTests() {
|
|
27542
|
-
defaultFlowStore.clear?.();
|
|
27543
|
-
}
|
|
27544
|
-
|
|
27545
27695
|
// src/connectors/adapters/cal-com.ts
|
|
27546
27696
|
var authorizeUrl = "https://app.cal.com/auth/oauth2/authorize";
|
|
27547
27697
|
var tokenUrl = "https://api.cal.com/v2/auth/oauth2/token";
|
|
@@ -52737,13 +52887,11 @@ function microsoftTeams(opts) {
|
|
|
52737
52887
|
async test(source) {
|
|
52738
52888
|
try {
|
|
52739
52889
|
const accessToken4 = await ensureFreshAccessToken11(source.credentials, clientId, clientSecret);
|
|
52740
|
-
const res = await fetch(`${GRAPH2}/me
|
|
52890
|
+
const res = await fetch(`${GRAPH2}/me/joinedTeams`, {
|
|
52741
52891
|
headers: { authorization: `Bearer ${accessToken4}` },
|
|
52742
52892
|
signal: AbortSignal.timeout(8e3)
|
|
52743
52893
|
});
|
|
52744
|
-
if (res.status === 401 || res.status === 403)
|
|
52745
|
-
return { ok: false, reason: `Microsoft rejected token (${res.status}) \u2014 reconnect required` };
|
|
52746
|
-
}
|
|
52894
|
+
if (res.status === 401 || res.status === 403) return microsoftGraphTestFailure(res);
|
|
52747
52895
|
if (!res.ok) return { ok: false, reason: `Microsoft Graph returned ${res.status}` };
|
|
52748
52896
|
return { ok: true };
|
|
52749
52897
|
} catch (err) {
|
|
@@ -52804,7 +52952,7 @@ async function graphGet2(url, accessToken4, dataSourceId) {
|
|
|
52804
52952
|
signal: AbortSignal.timeout(1e4)
|
|
52805
52953
|
});
|
|
52806
52954
|
if (res.status === 401 || res.status === 403) {
|
|
52807
|
-
|
|
52955
|
+
await throwMicrosoftGraphAccessError(res, dataSourceId);
|
|
52808
52956
|
}
|
|
52809
52957
|
if (!res.ok) {
|
|
52810
52958
|
const text = await res.text().catch(() => "");
|
|
@@ -52824,7 +52972,7 @@ async function graphPost(url, accessToken4, body, dataSourceId, op) {
|
|
|
52824
52972
|
signal: AbortSignal.timeout(15e3)
|
|
52825
52973
|
});
|
|
52826
52974
|
if (res.status === 401 || res.status === 403) {
|
|
52827
|
-
|
|
52975
|
+
await throwMicrosoftGraphAccessError(res, dataSourceId);
|
|
52828
52976
|
}
|
|
52829
52977
|
if (!res.ok) {
|
|
52830
52978
|
const text = await res.text().catch(() => "");
|
|
@@ -52832,6 +52980,57 @@ async function graphPost(url, accessToken4, body, dataSourceId, op) {
|
|
|
52832
52980
|
}
|
|
52833
52981
|
return await res.json();
|
|
52834
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
|
+
}
|
|
52835
53034
|
function escapeOData2(value) {
|
|
52836
53035
|
return value.replace(/'/g, "''");
|
|
52837
53036
|
}
|
|
@@ -83842,7 +84041,7 @@ var CONNECTOR_ADAPTER_FACTORIES = [
|
|
|
83842
84041
|
clientId: "PUSHBULLET_OAUTH_CLIENT_ID",
|
|
83843
84042
|
clientSecret: "PUSHBULLET_OAUTH_CLIENT_SECRET"
|
|
83844
84043
|
}),
|
|
83845
|
-
defineFactoryAdapter(
|
|
84044
|
+
defineFactoryAdapter(reddit, {
|
|
83846
84045
|
clientId: "REDDIT_OAUTH_CLIENT_ID",
|
|
83847
84046
|
clientSecret: "REDDIT_OAUTH_CLIENT_SECRET"
|
|
83848
84047
|
}),
|
|
@@ -148676,6 +148875,7 @@ export {
|
|
|
148676
148875
|
consumePendingFlow,
|
|
148677
148876
|
exchangeAuthorizationCode,
|
|
148678
148877
|
refreshAccessToken,
|
|
148878
|
+
createOAuthTokenRequestHeaders,
|
|
148679
148879
|
_resetPendingFlowsForTests,
|
|
148680
148880
|
declarativeRestConnector,
|
|
148681
148881
|
oktaConnector,
|
|
@@ -148752,6 +148952,7 @@ export {
|
|
|
148752
148952
|
paychexConnector,
|
|
148753
148953
|
pushbulletConnector,
|
|
148754
148954
|
redditConnector,
|
|
148955
|
+
reddit,
|
|
148755
148956
|
ripplingConnector,
|
|
148756
148957
|
sanityConnector,
|
|
148757
148958
|
sendpulseConnector,
|
|
@@ -149332,4 +149533,4 @@ export {
|
|
|
149332
149533
|
getresponseConnector,
|
|
149333
149534
|
adapters_exports
|
|
149334
149535
|
};
|
|
149335
|
-
//# sourceMappingURL=chunk-
|
|
149536
|
+
//# sourceMappingURL=chunk-H5UCSRF4.js.map
|