@tangle-network/agent-integrations 0.37.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +7 -7
- package/dist/{chunk-YV3O5SO2.js → chunk-6MUBOVI4.js} +1839 -1587
- package/dist/chunk-6MUBOVI4.js.map +1 -0
- package/dist/{chunk-O553GSCX.js → chunk-FAFQZJPZ.js} +2 -2
- package/dist/{chunk-53NQJZAT.js → chunk-IA5GCKM6.js} +2 -3
- package/dist/chunk-IA5GCKM6.js.map +1 -0
- package/dist/{chunk-CR35IEKW.js → chunk-IKCXDQVP.js} +2 -2
- package/dist/{chunk-ZDK7Y4QG.js → chunk-OMLQCESJ.js} +1 -1
- package/dist/chunk-OMLQCESJ.js.map +1 -0
- package/dist/{chunk-SPLJV5J7.js → chunk-P3RWMLK3.js} +6 -4
- package/dist/{chunk-SPLJV5J7.js.map → chunk-P3RWMLK3.js.map} +1 -1
- package/dist/{chunk-D57YS6XC.js → chunk-TC5OMANJ.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 +89 -96
- package/dist/connectors/adapters/index.js +8 -12
- package/dist/connectors/index.d.ts +3 -3
- package/dist/connectors/index.js +8 -12
- package/dist/{consumer-Dzt2uOo_.d.ts → consumer-Cxcpp_bi.d.ts} +1 -1
- package/dist/consumer.d.ts +3 -3
- package/dist/consumer.js +2 -2
- package/dist/{core-types-D4MGC44S.d.ts → core-types-DMDmeutI.d.ts} +1 -1
- package/dist/coverage-catalog.d.ts +2 -2
- package/dist/{importers-DANyqwIT.d.ts → importers-BAVOQvUf.d.ts} +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +13 -17
- package/dist/mcp.d.ts +3 -3
- package/dist/mcp.js +7 -7
- 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 +7 -7
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +7 -7
- package/dist/specs.d.ts +2 -2
- package/dist/specs.js +1 -1
- package/dist/{tangle-id-hDDWP-2f.d.ts → tangle-id-BMScmNjp.d.ts} +1 -1
- package/dist/{types-Bxg-wJkW.d.ts → types-eAvAgnKr.d.ts} +4 -0
- package/docs/adapter-triage.md +3 -3
- package/docs/catalog-registry.md +1 -1
- package/package.json +1 -1
- package/dist/chunk-53NQJZAT.js.map +0 -1
- package/dist/chunk-YV3O5SO2.js.map +0 -1
- package/dist/chunk-ZDK7Y4QG.js.map +0 -1
- /package/dist/{chunk-O553GSCX.js.map → chunk-FAFQZJPZ.js.map} +0 -0
- /package/dist/{chunk-CR35IEKW.js.map → chunk-IKCXDQVP.js.map} +0 -0
- /package/dist/{chunk-D57YS6XC.js.map → chunk-TC5OMANJ.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
TangleIdentityUnreachableError,
|
|
13
13
|
createTangleIdentityClient,
|
|
14
14
|
tangleIdentity
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-OMLQCESJ.js";
|
|
16
16
|
import {
|
|
17
17
|
__export
|
|
18
18
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -196,6 +196,7 @@ __export(adapters_exports, {
|
|
|
196
196
|
gitlabConnector: () => gitlabConnector,
|
|
197
197
|
glideConnector: () => glideConnector,
|
|
198
198
|
gmail: () => gmail,
|
|
199
|
+
googleAnalyticsConnector: () => googleAnalyticsConnector,
|
|
199
200
|
googleBigqueryConnector: () => googleBigqueryConnector,
|
|
200
201
|
googleCalendar: () => googleCalendar,
|
|
201
202
|
googleCloudStorageConnector: () => googleCloudStorageConnector,
|
|
@@ -204,6 +205,7 @@ __export(adapters_exports, {
|
|
|
204
205
|
googleDrive: () => googleDrive,
|
|
205
206
|
googleForms: () => googleForms,
|
|
206
207
|
googleGeminiConnector: () => googleGeminiConnector,
|
|
208
|
+
googleMeetConnector: () => googleMeetConnector,
|
|
207
209
|
googleMyBusinessConnector: () => googleMyBusinessConnector,
|
|
208
210
|
googleSearchConnector: () => googleSearchConnector,
|
|
209
211
|
googleSearchConsoleConnector: () => googleSearchConsoleConnector,
|
|
@@ -319,12 +321,8 @@ __export(adapters_exports, {
|
|
|
319
321
|
microsoftDynamicsCrmConnector: () => microsoftDynamicsCrmConnector,
|
|
320
322
|
microsoftExcel365Connector: () => microsoftExcel365Connector,
|
|
321
323
|
microsoftGraph: () => microsoftGraph,
|
|
322
|
-
microsoftOnedriveConnector: () => microsoftOnedriveConnector,
|
|
323
324
|
microsoftOnenoteConnector: () => microsoftOnenoteConnector,
|
|
324
|
-
microsoftOutlookCalendarConnector: () => microsoftOutlookCalendarConnector,
|
|
325
|
-
microsoftOutlookConnector: () => microsoftOutlookConnector,
|
|
326
325
|
microsoftPowerBiConnector: () => microsoftPowerBiConnector,
|
|
327
|
-
microsoftSharepointConnector: () => microsoftSharepointConnector,
|
|
328
326
|
microsoftTeams: () => microsoftTeams,
|
|
329
327
|
microsoftTodoConnector: () => microsoftTodoConnector,
|
|
330
328
|
millionverifierConnector: () => millionverifierConnector,
|
|
@@ -342,8 +340,8 @@ __export(adapters_exports, {
|
|
|
342
340
|
niftyConnector: () => niftyConnector,
|
|
343
341
|
ninjapipeConnector: () => ninjapipeConnector,
|
|
344
342
|
nocodbConnector: () => nocodbConnector,
|
|
343
|
+
notion: () => notion,
|
|
345
344
|
notionConnector: () => notionConnector,
|
|
346
|
-
notionDatabase: () => notionDatabase,
|
|
347
345
|
ntfyConnector: () => ntfyConnector,
|
|
348
346
|
odooConnector: () => odooConnector,
|
|
349
347
|
omniCoConnector: () => omniCoConnector,
|
|
@@ -3134,91 +3132,253 @@ function microsoftCalendar(opts) {
|
|
|
3134
3132
|
attendees: {
|
|
3135
3133
|
type: "array",
|
|
3136
3134
|
items: { type: "string", description: "attendee email" }
|
|
3137
|
-
}
|
|
3135
|
+
},
|
|
3136
|
+
// Optional rich create fields (ported from microsoft-outlook-calendar
|
|
3137
|
+
// create.event). All additive — the freebusy pre-flight and
|
|
3138
|
+
// alternative-slot behavior below is unchanged when these are absent.
|
|
3139
|
+
calendarId: {
|
|
3140
|
+
type: "string",
|
|
3141
|
+
description: "Target calendar id; defaults to the user's primary calendar (/me/events) when omitted."
|
|
3142
|
+
},
|
|
3143
|
+
location: {
|
|
3144
|
+
type: "object",
|
|
3145
|
+
description: 'Graph location resource, e.g. { displayName: "Room 1" }.'
|
|
3146
|
+
},
|
|
3147
|
+
recurrence: {
|
|
3148
|
+
type: "object",
|
|
3149
|
+
description: "Graph patternedRecurrence resource ({ pattern, range })."
|
|
3150
|
+
},
|
|
3151
|
+
isOnlineMeeting: { type: "boolean", description: "Provision an online meeting (Teams) for the event." },
|
|
3152
|
+
onlineMeetingProvider: {
|
|
3153
|
+
type: "string",
|
|
3154
|
+
description: "Online meeting provider, e.g. 'teamsForBusiness'."
|
|
3155
|
+
},
|
|
3156
|
+
reminderMinutesBeforeStart: {
|
|
3157
|
+
type: "integer",
|
|
3158
|
+
description: "Minutes before start to fire the reminder."
|
|
3159
|
+
},
|
|
3160
|
+
isAllDay: { type: "boolean", description: "Mark the event as all-day (start/end must be midnight-aligned)." },
|
|
3161
|
+
categories: {
|
|
3162
|
+
type: "array",
|
|
3163
|
+
items: { type: "string", description: "Outlook category name" }
|
|
3164
|
+
},
|
|
3165
|
+
importance: { type: "string", description: "Event importance: 'low' | 'normal' | 'high'." }
|
|
3138
3166
|
},
|
|
3139
3167
|
required: ["start", "end", "summary"]
|
|
3140
3168
|
}
|
|
3169
|
+
},
|
|
3170
|
+
{
|
|
3171
|
+
name: "delete_event",
|
|
3172
|
+
class: "mutation",
|
|
3173
|
+
description: "Delete an event by id from the connected Outlook calendar. Graph returns 204 on success; a re-delete of a missing event surfaces as 404 mapped to an idempotent tombstone. Honors If-Match against the event etag when the caller supplies expectedEtag.",
|
|
3174
|
+
cas: "native-idempotency",
|
|
3175
|
+
externalEffect: true,
|
|
3176
|
+
parameters: {
|
|
3177
|
+
type: "object",
|
|
3178
|
+
properties: {
|
|
3179
|
+
eventId: { type: "string", description: "Graph event id to delete." }
|
|
3180
|
+
},
|
|
3181
|
+
required: ["eventId"]
|
|
3182
|
+
}
|
|
3183
|
+
},
|
|
3184
|
+
{
|
|
3185
|
+
name: "list_events",
|
|
3186
|
+
class: "read",
|
|
3187
|
+
description: "List actual event objects on a calendar with OData paging/filtering ($top, $skip, $filter, $select, $orderby, $search). Targets the user's primary calendar (/me/events) unless calendarId is supplied. Distinct from list_availability, which returns busy windows.",
|
|
3188
|
+
parameters: {
|
|
3189
|
+
type: "object",
|
|
3190
|
+
properties: {
|
|
3191
|
+
calendarId: { type: "string", description: "Calendar id; defaults to the user's primary calendar when omitted." },
|
|
3192
|
+
$top: { type: "integer", description: "Max events to return (OData page size)." },
|
|
3193
|
+
$skip: { type: "integer", description: "Number of events to skip (OData paging offset)." },
|
|
3194
|
+
$filter: { type: "string", description: "OData $filter expression." },
|
|
3195
|
+
$select: { type: "string", description: "Comma-separated event fields to project." },
|
|
3196
|
+
$orderby: { type: "string", description: "OData $orderby expression." },
|
|
3197
|
+
$search: { type: "string", description: "OData $search query." }
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3141
3200
|
}
|
|
3142
3201
|
]
|
|
3143
3202
|
},
|
|
3144
3203
|
async executeRead(inv) {
|
|
3145
|
-
if (inv.capabilityName !== "list_availability") {
|
|
3146
|
-
throw new Error(`microsoft-calendar: unknown read capability ${inv.capabilityName}`);
|
|
3147
|
-
}
|
|
3148
|
-
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3149
|
-
const { timeMin, timeMax } = inv.args;
|
|
3150
3204
|
const accessToken = await ensureFreshAccessToken5(inv.source.credentials, clientId, clientSecret);
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3205
|
+
if (inv.capabilityName === "list_availability") {
|
|
3206
|
+
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3207
|
+
const { timeMin, timeMax } = inv.args;
|
|
3208
|
+
const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin, timeMax });
|
|
3209
|
+
return {
|
|
3210
|
+
data: { busy },
|
|
3211
|
+
fetchedAt: Date.now()
|
|
3212
|
+
};
|
|
3213
|
+
}
|
|
3214
|
+
if (inv.capabilityName === "list_events") {
|
|
3215
|
+
const {
|
|
3216
|
+
calendarId,
|
|
3217
|
+
$top,
|
|
3218
|
+
$skip,
|
|
3219
|
+
$filter,
|
|
3220
|
+
$select,
|
|
3221
|
+
$orderby,
|
|
3222
|
+
$search
|
|
3223
|
+
} = inv.args;
|
|
3224
|
+
const base = calendarId ? `https://graph.microsoft.com/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events` : "https://graph.microsoft.com/v1.0/me/events";
|
|
3225
|
+
const qs = new URLSearchParams();
|
|
3226
|
+
if ($top !== void 0) qs.set("$top", String($top));
|
|
3227
|
+
if ($skip !== void 0) qs.set("$skip", String($skip));
|
|
3228
|
+
if ($filter) qs.set("$filter", $filter);
|
|
3229
|
+
if ($select) qs.set("$select", $select);
|
|
3230
|
+
if ($orderby) qs.set("$orderby", $orderby);
|
|
3231
|
+
if ($search) qs.set("$search", $search);
|
|
3232
|
+
const query = qs.toString();
|
|
3233
|
+
const url = query ? `${base}?${query}` : base;
|
|
3234
|
+
const res = await fetch(url, {
|
|
3235
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
3236
|
+
signal: AbortSignal.timeout(15e3)
|
|
3237
|
+
});
|
|
3238
|
+
if (res.status === 401 || res.status === 403) {
|
|
3239
|
+
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3240
|
+
}
|
|
3241
|
+
if (!res.ok) {
|
|
3242
|
+
const text = await res.text().catch(() => "");
|
|
3243
|
+
throw new Error(`microsoft-calendar list_events ${res.status}: ${text.slice(0, 200)}`);
|
|
3244
|
+
}
|
|
3245
|
+
const json = await res.json();
|
|
3246
|
+
return {
|
|
3247
|
+
data: { events: json.value ?? [], nextLink: json["@odata.nextLink"] },
|
|
3248
|
+
fetchedAt: Date.now()
|
|
3249
|
+
};
|
|
3250
|
+
}
|
|
3251
|
+
throw new Error(`microsoft-calendar: unknown read capability ${inv.capabilityName}`);
|
|
3156
3252
|
},
|
|
3157
3253
|
async executeMutation(inv) {
|
|
3158
|
-
if (inv.capabilityName !== "book_slot") {
|
|
3159
|
-
throw new Error(`microsoft-calendar: unknown mutation capability ${inv.capabilityName}`);
|
|
3160
|
-
}
|
|
3161
|
-
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3162
|
-
const { start, end, summary, description, attendees } = inv.args;
|
|
3163
3254
|
const accessToken = await ensureFreshAccessToken5(inv.source.credentials, clientId, clientSecret);
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
const
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3255
|
+
if (inv.capabilityName === "book_slot") {
|
|
3256
|
+
const userPrincipal = readMetaString2(inv.source.metadata, "userPrincipal");
|
|
3257
|
+
const {
|
|
3258
|
+
start,
|
|
3259
|
+
end,
|
|
3260
|
+
summary,
|
|
3261
|
+
description,
|
|
3262
|
+
attendees,
|
|
3263
|
+
calendarId,
|
|
3264
|
+
location,
|
|
3265
|
+
recurrence,
|
|
3266
|
+
isOnlineMeeting,
|
|
3267
|
+
onlineMeetingProvider,
|
|
3268
|
+
reminderMinutesBeforeStart,
|
|
3269
|
+
isAllDay,
|
|
3270
|
+
categories,
|
|
3271
|
+
importance
|
|
3272
|
+
} = inv.args;
|
|
3273
|
+
const busy = await getScheduleBusy({ accessToken, userPrincipal, timeMin: start, timeMax: end });
|
|
3274
|
+
if (busy.length > 0) {
|
|
3275
|
+
const startMs = Date.parse(start);
|
|
3276
|
+
const endMs = Date.parse(end);
|
|
3277
|
+
const durMs = endMs - startMs;
|
|
3278
|
+
const alternatives = await findNextFreeSlots2({
|
|
3279
|
+
accessToken,
|
|
3280
|
+
userPrincipal,
|
|
3281
|
+
searchFromMs: endMs,
|
|
3282
|
+
durationMs: durMs,
|
|
3283
|
+
wanted: 3
|
|
3284
|
+
});
|
|
3285
|
+
throw new ResourceContention(
|
|
3286
|
+
`requested slot ${start}\u2013${end} is no longer free`,
|
|
3287
|
+
alternatives,
|
|
3288
|
+
{ busy }
|
|
3289
|
+
);
|
|
3290
|
+
}
|
|
3291
|
+
const event = {
|
|
3292
|
+
subject: summary,
|
|
3293
|
+
body: description ? { contentType: "text", content: description } : void 0,
|
|
3294
|
+
start: { dateTime: start, timeZone: "UTC" },
|
|
3295
|
+
end: { dateTime: end, timeZone: "UTC" },
|
|
3296
|
+
attendees: attendees?.map((email) => ({
|
|
3297
|
+
emailAddress: { address: email },
|
|
3298
|
+
type: "required"
|
|
3299
|
+
}))
|
|
3300
|
+
};
|
|
3301
|
+
if (location !== void 0) event.location = location;
|
|
3302
|
+
if (recurrence !== void 0) event.recurrence = recurrence;
|
|
3303
|
+
if (isOnlineMeeting !== void 0) event.isOnlineMeeting = isOnlineMeeting;
|
|
3304
|
+
if (onlineMeetingProvider !== void 0) event.onlineMeetingProvider = onlineMeetingProvider;
|
|
3305
|
+
if (reminderMinutesBeforeStart !== void 0) event.reminderMinutesBeforeStart = reminderMinutesBeforeStart;
|
|
3306
|
+
if (isAllDay !== void 0) event.isAllDay = isAllDay;
|
|
3307
|
+
if (categories !== void 0) event.categories = categories;
|
|
3308
|
+
if (importance !== void 0) event.importance = importance;
|
|
3309
|
+
const url = calendarId ? `https://graph.microsoft.com/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events` : "https://graph.microsoft.com/v1.0/me/events";
|
|
3310
|
+
const res = await fetch(url, {
|
|
3311
|
+
method: "POST",
|
|
3312
|
+
headers: {
|
|
3313
|
+
authorization: `Bearer ${accessToken}`,
|
|
3314
|
+
"content-type": "application/json"
|
|
3315
|
+
},
|
|
3316
|
+
body: JSON.stringify(event),
|
|
3317
|
+
signal: AbortSignal.timeout(15e3)
|
|
3175
3318
|
});
|
|
3176
|
-
|
|
3177
|
-
`
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
},
|
|
3198
|
-
body: JSON.stringify(event),
|
|
3199
|
-
signal: AbortSignal.timeout(15e3)
|
|
3200
|
-
});
|
|
3201
|
-
if (res.status === 401 || res.status === 403) {
|
|
3202
|
-
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3319
|
+
if (res.status === 401 || res.status === 403) {
|
|
3320
|
+
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3321
|
+
}
|
|
3322
|
+
if (res.status === 412 || res.status === 409) {
|
|
3323
|
+
throw new ResourceContention(
|
|
3324
|
+
`Microsoft Graph reported conflict on book_slot (${res.status})`,
|
|
3325
|
+
[]
|
|
3326
|
+
);
|
|
3327
|
+
}
|
|
3328
|
+
if (!res.ok) {
|
|
3329
|
+
const text = await res.text().catch(() => "");
|
|
3330
|
+
throw new Error(`microsoft-calendar book_slot ${res.status}: ${text.slice(0, 200)}`);
|
|
3331
|
+
}
|
|
3332
|
+
const created = await res.json();
|
|
3333
|
+
return {
|
|
3334
|
+
status: "committed",
|
|
3335
|
+
data: { eventId: created.id, webLink: created.webLink },
|
|
3336
|
+
etagAfter: created["@odata.etag"],
|
|
3337
|
+
committedAt: Date.now(),
|
|
3338
|
+
idempotentReplay: false
|
|
3339
|
+
};
|
|
3203
3340
|
}
|
|
3204
|
-
if (
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3341
|
+
if (inv.capabilityName === "delete_event") {
|
|
3342
|
+
const { eventId } = inv.args;
|
|
3343
|
+
const headers = { authorization: `Bearer ${accessToken}` };
|
|
3344
|
+
if (inv.expectedEtag) headers["if-match"] = inv.expectedEtag;
|
|
3345
|
+
const res = await fetch(
|
|
3346
|
+
`https://graph.microsoft.com/v1.0/me/events/${encodeURIComponent(eventId)}`,
|
|
3347
|
+
{
|
|
3348
|
+
method: "DELETE",
|
|
3349
|
+
headers,
|
|
3350
|
+
signal: AbortSignal.timeout(15e3)
|
|
3351
|
+
}
|
|
3208
3352
|
);
|
|
3353
|
+
if (res.status === 401 || res.status === 403) {
|
|
3354
|
+
throw new CredentialsExpired(`Microsoft Graph rejected token (${res.status})`, inv.source.id);
|
|
3355
|
+
}
|
|
3356
|
+
if (res.status === 412 || res.status === 409) {
|
|
3357
|
+
throw new ResourceContention(
|
|
3358
|
+
`Microsoft Graph reported conflict on delete_event (${res.status})`,
|
|
3359
|
+
[]
|
|
3360
|
+
);
|
|
3361
|
+
}
|
|
3362
|
+
if (res.status === 404) {
|
|
3363
|
+
return {
|
|
3364
|
+
status: "committed",
|
|
3365
|
+
data: { eventId, deleted: true, alreadyMissing: true },
|
|
3366
|
+
committedAt: Date.now(),
|
|
3367
|
+
idempotentReplay: true
|
|
3368
|
+
};
|
|
3369
|
+
}
|
|
3370
|
+
if (!res.ok) {
|
|
3371
|
+
const text = await res.text().catch(() => "");
|
|
3372
|
+
throw new Error(`microsoft-calendar delete_event ${res.status}: ${text.slice(0, 200)}`);
|
|
3373
|
+
}
|
|
3374
|
+
return {
|
|
3375
|
+
status: "committed",
|
|
3376
|
+
data: { eventId, deleted: true },
|
|
3377
|
+
committedAt: Date.now(),
|
|
3378
|
+
idempotentReplay: false
|
|
3379
|
+
};
|
|
3209
3380
|
}
|
|
3210
|
-
|
|
3211
|
-
const text = await res.text().catch(() => "");
|
|
3212
|
-
throw new Error(`microsoft-calendar book_slot ${res.status}: ${text.slice(0, 200)}`);
|
|
3213
|
-
}
|
|
3214
|
-
const created = await res.json();
|
|
3215
|
-
return {
|
|
3216
|
-
status: "committed",
|
|
3217
|
-
data: { eventId: created.id, webLink: created.webLink },
|
|
3218
|
-
etagAfter: created["@odata.etag"],
|
|
3219
|
-
committedAt: Date.now(),
|
|
3220
|
-
idempotentReplay: false
|
|
3221
|
-
};
|
|
3381
|
+
throw new Error(`microsoft-calendar: unknown mutation capability ${inv.capabilityName}`);
|
|
3222
3382
|
},
|
|
3223
3383
|
async exchangeOAuth(input) {
|
|
3224
3384
|
if (!clientId || !clientSecret) {
|
|
@@ -4438,518 +4598,6 @@ async function uploadFile2(inv, accessToken, timeoutMs) {
|
|
|
4438
4598
|
};
|
|
4439
4599
|
}
|
|
4440
4600
|
|
|
4441
|
-
// src/connectors/adapters/notion-database.ts
|
|
4442
|
-
var AUTH_URL8 = "https://api.notion.com/v1/oauth/authorize";
|
|
4443
|
-
var TOKEN_URL8 = "https://api.notion.com/v1/oauth/token";
|
|
4444
|
-
var API5 = "https://api.notion.com/v1";
|
|
4445
|
-
var NOTION_VERSION = "2022-06-28";
|
|
4446
|
-
function notionDatabase(opts) {
|
|
4447
|
-
const { clientId, clientSecret } = opts;
|
|
4448
|
-
const adapter = {
|
|
4449
|
-
manifest: {
|
|
4450
|
-
kind: "notion-database",
|
|
4451
|
-
displayName: "Notion (database)",
|
|
4452
|
-
description: "Query a Notion database, create new pages, and update existing ones with optimistic concurrency via last_edited_time.",
|
|
4453
|
-
auth: {
|
|
4454
|
-
kind: "oauth2",
|
|
4455
|
-
authorizationUrl: AUTH_URL8,
|
|
4456
|
-
tokenUrl: TOKEN_URL8,
|
|
4457
|
-
// Notion does not use OAuth scopes — the workspace owner picks
|
|
4458
|
-
// which pages/databases the integration sees during install. We
|
|
4459
|
-
// declare an empty scope list so the consent screen renders cleanly.
|
|
4460
|
-
scopes: [],
|
|
4461
|
-
clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
|
|
4462
|
-
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
|
|
4463
|
-
extraAuthParams: { owner: "user" }
|
|
4464
|
-
},
|
|
4465
|
-
category: "doc",
|
|
4466
|
-
defaultConsistencyModel: "authoritative",
|
|
4467
|
-
capabilities: [
|
|
4468
|
-
{
|
|
4469
|
-
name: "query_database",
|
|
4470
|
-
class: "read",
|
|
4471
|
-
description: "Query the connected Notion database with an optional filter object (Notion query DSL).",
|
|
4472
|
-
parameters: {
|
|
4473
|
-
type: "object",
|
|
4474
|
-
properties: {
|
|
4475
|
-
filter: { type: "object", description: "Notion API filter object \u2014 passed through verbatim." },
|
|
4476
|
-
pageSize: { type: "integer", minimum: 1, maximum: 100, default: 50 },
|
|
4477
|
-
startCursor: { type: "string" }
|
|
4478
|
-
}
|
|
4479
|
-
}
|
|
4480
|
-
},
|
|
4481
|
-
{
|
|
4482
|
-
name: "create_page",
|
|
4483
|
-
class: "mutation",
|
|
4484
|
-
description: "Create a new page inside the connected database.",
|
|
4485
|
-
cas: "native-idempotency",
|
|
4486
|
-
externalEffect: true,
|
|
4487
|
-
parameters: {
|
|
4488
|
-
type: "object",
|
|
4489
|
-
properties: {
|
|
4490
|
-
properties: {
|
|
4491
|
-
type: "object",
|
|
4492
|
-
description: "Notion property map keyed by property name."
|
|
4493
|
-
}
|
|
4494
|
-
},
|
|
4495
|
-
required: ["properties"]
|
|
4496
|
-
}
|
|
4497
|
-
},
|
|
4498
|
-
{
|
|
4499
|
-
name: "update_page",
|
|
4500
|
-
class: "mutation",
|
|
4501
|
-
description: "Update properties on an existing page. If `expectedLastEditedTime` is supplied and stale, the update is rejected with conflict.",
|
|
4502
|
-
cas: "etag-if-match",
|
|
4503
|
-
externalEffect: true,
|
|
4504
|
-
parameters: {
|
|
4505
|
-
type: "object",
|
|
4506
|
-
properties: {
|
|
4507
|
-
pageId: { type: "string" },
|
|
4508
|
-
properties: { type: "object" },
|
|
4509
|
-
expectedLastEditedTime: {
|
|
4510
|
-
type: "string",
|
|
4511
|
-
description: "RFC3339 timestamp the agent observed on its last read. Drift triggers ResourceContention."
|
|
4512
|
-
}
|
|
4513
|
-
},
|
|
4514
|
-
required: ["pageId", "properties"]
|
|
4515
|
-
}
|
|
4516
|
-
},
|
|
4517
|
-
{
|
|
4518
|
-
name: "pages.archive",
|
|
4519
|
-
class: "mutation",
|
|
4520
|
-
description: "Archive (soft-delete) a Notion page. Restorable via update_page with archived:false.",
|
|
4521
|
-
cas: "native-idempotency",
|
|
4522
|
-
externalEffect: true,
|
|
4523
|
-
parameters: {
|
|
4524
|
-
type: "object",
|
|
4525
|
-
properties: { pageId: { type: "string" } },
|
|
4526
|
-
required: ["pageId"]
|
|
4527
|
-
}
|
|
4528
|
-
},
|
|
4529
|
-
{
|
|
4530
|
-
name: "databases.create",
|
|
4531
|
-
class: "mutation",
|
|
4532
|
-
description: "Create a new Notion database underneath a parent page.",
|
|
4533
|
-
cas: "native-idempotency",
|
|
4534
|
-
externalEffect: true,
|
|
4535
|
-
parameters: {
|
|
4536
|
-
type: "object",
|
|
4537
|
-
properties: {
|
|
4538
|
-
parentPageId: { type: "string", description: "Parent page id under which to create the database." },
|
|
4539
|
-
title: {
|
|
4540
|
-
type: "array",
|
|
4541
|
-
description: "Notion rich_text array used as the database title."
|
|
4542
|
-
},
|
|
4543
|
-
properties: {
|
|
4544
|
-
type: "object",
|
|
4545
|
-
description: "Schema map \u2014 property name \u2192 Notion property schema."
|
|
4546
|
-
}
|
|
4547
|
-
},
|
|
4548
|
-
required: ["parentPageId", "title", "properties"]
|
|
4549
|
-
}
|
|
4550
|
-
},
|
|
4551
|
-
{
|
|
4552
|
-
name: "databases.update",
|
|
4553
|
-
class: "mutation",
|
|
4554
|
-
description: "Update a database title and/or schema.",
|
|
4555
|
-
cas: "native-idempotency",
|
|
4556
|
-
externalEffect: true,
|
|
4557
|
-
parameters: {
|
|
4558
|
-
type: "object",
|
|
4559
|
-
properties: {
|
|
4560
|
-
databaseId: { type: "string" },
|
|
4561
|
-
title: { type: "array", description: "Optional new rich_text title." },
|
|
4562
|
-
properties: { type: "object", description: "Optional partial schema update." }
|
|
4563
|
-
},
|
|
4564
|
-
required: ["databaseId"]
|
|
4565
|
-
}
|
|
4566
|
-
},
|
|
4567
|
-
{
|
|
4568
|
-
name: "blocks.append",
|
|
4569
|
-
class: "mutation",
|
|
4570
|
-
description: "Append child blocks to a page or block.",
|
|
4571
|
-
cas: "native-idempotency",
|
|
4572
|
-
externalEffect: true,
|
|
4573
|
-
parameters: {
|
|
4574
|
-
type: "object",
|
|
4575
|
-
properties: {
|
|
4576
|
-
blockId: { type: "string", description: "Parent page or block id." },
|
|
4577
|
-
children: { type: "array", description: "Block descriptor array per Notion schema." }
|
|
4578
|
-
},
|
|
4579
|
-
required: ["blockId", "children"]
|
|
4580
|
-
}
|
|
4581
|
-
}
|
|
4582
|
-
]
|
|
4583
|
-
},
|
|
4584
|
-
async executeRead(inv) {
|
|
4585
|
-
if (inv.capabilityName !== "query_database") {
|
|
4586
|
-
throw new Error(`notion-database: unknown read capability ${inv.capabilityName}`);
|
|
4587
|
-
}
|
|
4588
|
-
const accessToken = readToken(inv.source.credentials);
|
|
4589
|
-
const databaseId = readMetaString3(inv.source.metadata, "databaseId");
|
|
4590
|
-
const { filter, pageSize, startCursor } = inv.args;
|
|
4591
|
-
const body = {
|
|
4592
|
-
page_size: Math.min(Math.max(1, pageSize ?? 50), 100)
|
|
4593
|
-
};
|
|
4594
|
-
if (filter) body.filter = filter;
|
|
4595
|
-
if (startCursor) body.start_cursor = startCursor;
|
|
4596
|
-
const res = await fetch(`${API5}/databases/${encodeURIComponent(databaseId)}/query`, {
|
|
4597
|
-
method: "POST",
|
|
4598
|
-
headers: notionHeaders(accessToken),
|
|
4599
|
-
body: JSON.stringify(body),
|
|
4600
|
-
signal: AbortSignal.timeout(1e4)
|
|
4601
|
-
});
|
|
4602
|
-
if (res.status === 401) {
|
|
4603
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4604
|
-
}
|
|
4605
|
-
if (!res.ok) {
|
|
4606
|
-
const text = await res.text().catch(() => "");
|
|
4607
|
-
throw new Error(`notion-database query_database ${res.status}: ${text.slice(0, 200)}`);
|
|
4608
|
-
}
|
|
4609
|
-
const json = await res.json();
|
|
4610
|
-
return {
|
|
4611
|
-
data: {
|
|
4612
|
-
results: json.results ?? [],
|
|
4613
|
-
hasMore: json.has_more ?? false,
|
|
4614
|
-
nextCursor: json.next_cursor ?? null
|
|
4615
|
-
},
|
|
4616
|
-
fetchedAt: Date.now()
|
|
4617
|
-
};
|
|
4618
|
-
},
|
|
4619
|
-
async executeMutation(inv) {
|
|
4620
|
-
const accessToken = readToken(inv.source.credentials);
|
|
4621
|
-
if (inv.capabilityName === "create_page") return createPage(inv, accessToken);
|
|
4622
|
-
if (inv.capabilityName === "update_page") return updatePage(inv, accessToken);
|
|
4623
|
-
if (inv.capabilityName === "pages.archive") return archivePage(inv, accessToken);
|
|
4624
|
-
if (inv.capabilityName === "databases.create") return createDatabase(inv, accessToken);
|
|
4625
|
-
if (inv.capabilityName === "databases.update") return updateDatabase(inv, accessToken);
|
|
4626
|
-
if (inv.capabilityName === "blocks.append") return appendBlocks(inv, accessToken);
|
|
4627
|
-
throw new Error(`notion-database: unknown mutation capability ${inv.capabilityName}`);
|
|
4628
|
-
},
|
|
4629
|
-
async exchangeOAuth(input) {
|
|
4630
|
-
if (!clientId || !clientSecret) {
|
|
4631
|
-
throw new Error("Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)");
|
|
4632
|
-
}
|
|
4633
|
-
const body = new URLSearchParams({
|
|
4634
|
-
grant_type: "authorization_code",
|
|
4635
|
-
code: input.code,
|
|
4636
|
-
redirect_uri: input.redirectUri,
|
|
4637
|
-
code_verifier: input.codeVerifier
|
|
4638
|
-
});
|
|
4639
|
-
const res = await fetch(TOKEN_URL8, {
|
|
4640
|
-
method: "POST",
|
|
4641
|
-
headers: {
|
|
4642
|
-
authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
|
|
4643
|
-
"content-type": "application/x-www-form-urlencoded",
|
|
4644
|
-
accept: "application/json",
|
|
4645
|
-
"Notion-Version": NOTION_VERSION
|
|
4646
|
-
},
|
|
4647
|
-
body
|
|
4648
|
-
});
|
|
4649
|
-
if (!res.ok) {
|
|
4650
|
-
const text = await res.text().catch(() => "");
|
|
4651
|
-
throw new Error(`Notion OAuth token exchange failed: ${res.status} \u2014 ${text.slice(0, 200)}`);
|
|
4652
|
-
}
|
|
4653
|
-
const json = await res.json();
|
|
4654
|
-
return {
|
|
4655
|
-
credentials: {
|
|
4656
|
-
kind: "oauth2",
|
|
4657
|
-
accessToken: json.access_token,
|
|
4658
|
-
refreshToken: json.refresh_token
|
|
4659
|
-
},
|
|
4660
|
-
scopes: [],
|
|
4661
|
-
metadata: {
|
|
4662
|
-
botId: json.bot_id,
|
|
4663
|
-
workspaceId: json.workspace_id,
|
|
4664
|
-
workspaceName: json.workspace_name,
|
|
4665
|
-
// Operator picks the database in a follow-up step; default empty.
|
|
4666
|
-
databaseId: ""
|
|
4667
|
-
}
|
|
4668
|
-
};
|
|
4669
|
-
},
|
|
4670
|
-
async refreshToken(creds) {
|
|
4671
|
-
if (creds.kind !== "oauth2" || !creds.refreshToken) {
|
|
4672
|
-
if (creds.kind === "oauth2" && creds.accessToken && !creds.expiresAt) {
|
|
4673
|
-
return creds;
|
|
4674
|
-
}
|
|
4675
|
-
throw new Error("notion-database.refreshToken: missing refresh token");
|
|
4676
|
-
}
|
|
4677
|
-
const refreshed = await refreshAccessToken({
|
|
4678
|
-
tokenUrl: TOKEN_URL8,
|
|
4679
|
-
clientId,
|
|
4680
|
-
clientSecret,
|
|
4681
|
-
refreshToken: creds.refreshToken
|
|
4682
|
-
});
|
|
4683
|
-
return {
|
|
4684
|
-
kind: "oauth2",
|
|
4685
|
-
accessToken: refreshed.accessToken,
|
|
4686
|
-
refreshToken: refreshed.refreshToken ?? creds.refreshToken,
|
|
4687
|
-
expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1e3 : void 0
|
|
4688
|
-
};
|
|
4689
|
-
},
|
|
4690
|
-
async test(source) {
|
|
4691
|
-
try {
|
|
4692
|
-
const accessToken = readToken(source.credentials);
|
|
4693
|
-
const res = await fetch(`${API5}/users/me`, {
|
|
4694
|
-
headers: notionHeaders(accessToken),
|
|
4695
|
-
signal: AbortSignal.timeout(8e3)
|
|
4696
|
-
});
|
|
4697
|
-
if (res.status === 401) return { ok: false, reason: "Notion rejected token (401) \u2014 reconnect required" };
|
|
4698
|
-
if (!res.ok) return { ok: false, reason: `Notion returned ${res.status}` };
|
|
4699
|
-
return { ok: true };
|
|
4700
|
-
} catch (err) {
|
|
4701
|
-
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
4702
|
-
}
|
|
4703
|
-
}
|
|
4704
|
-
};
|
|
4705
|
-
return adapter;
|
|
4706
|
-
}
|
|
4707
|
-
async function createPage(inv, accessToken) {
|
|
4708
|
-
const databaseId = readMetaString3(inv.source.metadata, "databaseId");
|
|
4709
|
-
const { properties } = inv.args;
|
|
4710
|
-
const res = await fetch(`${API5}/pages`, {
|
|
4711
|
-
method: "POST",
|
|
4712
|
-
headers: {
|
|
4713
|
-
...notionHeaders(accessToken),
|
|
4714
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4715
|
-
},
|
|
4716
|
-
body: JSON.stringify({
|
|
4717
|
-
parent: { database_id: databaseId },
|
|
4718
|
-
properties
|
|
4719
|
-
}),
|
|
4720
|
-
signal: AbortSignal.timeout(15e3)
|
|
4721
|
-
});
|
|
4722
|
-
if (res.status === 401) {
|
|
4723
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4724
|
-
}
|
|
4725
|
-
if (res.status === 409) {
|
|
4726
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4727
|
-
}
|
|
4728
|
-
if (!res.ok) {
|
|
4729
|
-
const text = await res.text().catch(() => "");
|
|
4730
|
-
throw new Error(`notion-database create_page ${res.status}: ${text.slice(0, 200)}`);
|
|
4731
|
-
}
|
|
4732
|
-
const created = await res.json();
|
|
4733
|
-
return {
|
|
4734
|
-
status: "committed",
|
|
4735
|
-
data: { pageId: created.id, url: created.url, lastEditedTime: created.last_edited_time },
|
|
4736
|
-
etagAfter: created.last_edited_time,
|
|
4737
|
-
committedAt: Date.now(),
|
|
4738
|
-
idempotentReplay: false
|
|
4739
|
-
};
|
|
4740
|
-
}
|
|
4741
|
-
async function updatePage(inv, accessToken) {
|
|
4742
|
-
const { pageId, properties, expectedLastEditedTime } = inv.args;
|
|
4743
|
-
if (expectedLastEditedTime) {
|
|
4744
|
-
const headRes = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
|
|
4745
|
-
headers: notionHeaders(accessToken),
|
|
4746
|
-
signal: AbortSignal.timeout(1e4)
|
|
4747
|
-
});
|
|
4748
|
-
if (headRes.status === 401) {
|
|
4749
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4750
|
-
}
|
|
4751
|
-
if (!headRes.ok) {
|
|
4752
|
-
const text = await headRes.text().catch(() => "");
|
|
4753
|
-
throw new Error(`notion-database update_page (preflight) ${headRes.status}: ${text.slice(0, 200)}`);
|
|
4754
|
-
}
|
|
4755
|
-
const page = await headRes.json();
|
|
4756
|
-
if (page.last_edited_time && page.last_edited_time !== expectedLastEditedTime) {
|
|
4757
|
-
throw new ResourceContention(
|
|
4758
|
-
`Notion page ${pageId} was modified since the agent last read it`,
|
|
4759
|
-
[],
|
|
4760
|
-
{ last_edited_time: page.last_edited_time, properties: page.properties }
|
|
4761
|
-
);
|
|
4762
|
-
}
|
|
4763
|
-
}
|
|
4764
|
-
const res = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
|
|
4765
|
-
method: "PATCH",
|
|
4766
|
-
headers: notionHeaders(accessToken),
|
|
4767
|
-
body: JSON.stringify({ properties }),
|
|
4768
|
-
signal: AbortSignal.timeout(15e3)
|
|
4769
|
-
});
|
|
4770
|
-
if (res.status === 401) {
|
|
4771
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4772
|
-
}
|
|
4773
|
-
if (res.status === 409 || res.status === 412) {
|
|
4774
|
-
throw new ResourceContention(`Notion update_page conflict (${res.status})`);
|
|
4775
|
-
}
|
|
4776
|
-
if (!res.ok) {
|
|
4777
|
-
const text = await res.text().catch(() => "");
|
|
4778
|
-
throw new Error(`notion-database update_page ${res.status}: ${text.slice(0, 200)}`);
|
|
4779
|
-
}
|
|
4780
|
-
const updated = await res.json();
|
|
4781
|
-
return {
|
|
4782
|
-
status: "committed",
|
|
4783
|
-
data: { pageId: updated.id, url: updated.url, lastEditedTime: updated.last_edited_time },
|
|
4784
|
-
etagAfter: updated.last_edited_time,
|
|
4785
|
-
committedAt: Date.now(),
|
|
4786
|
-
idempotentReplay: false
|
|
4787
|
-
};
|
|
4788
|
-
}
|
|
4789
|
-
async function archivePage(inv, accessToken) {
|
|
4790
|
-
const { pageId } = inv.args;
|
|
4791
|
-
if (typeof pageId !== "string" || pageId.length === 0) {
|
|
4792
|
-
throw new Error("notion-database pages.archive: pageId is required");
|
|
4793
|
-
}
|
|
4794
|
-
const res = await fetch(`${API5}/pages/${encodeURIComponent(pageId)}`, {
|
|
4795
|
-
method: "PATCH",
|
|
4796
|
-
headers: {
|
|
4797
|
-
...notionHeaders(accessToken),
|
|
4798
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4799
|
-
},
|
|
4800
|
-
body: JSON.stringify({ archived: true }),
|
|
4801
|
-
signal: AbortSignal.timeout(15e3)
|
|
4802
|
-
});
|
|
4803
|
-
if (res.status === 401) {
|
|
4804
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4805
|
-
}
|
|
4806
|
-
if (res.status === 409) {
|
|
4807
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4808
|
-
}
|
|
4809
|
-
if (!res.ok) {
|
|
4810
|
-
const text = await res.text().catch(() => "");
|
|
4811
|
-
throw new Error(`notion-database pages.archive ${res.status}: ${text.slice(0, 200)}`);
|
|
4812
|
-
}
|
|
4813
|
-
const archived = await res.json();
|
|
4814
|
-
return {
|
|
4815
|
-
status: "committed",
|
|
4816
|
-
data: { pageId: archived.id, archived: archived.archived ?? true, lastEditedTime: archived.last_edited_time },
|
|
4817
|
-
etagAfter: archived.last_edited_time,
|
|
4818
|
-
committedAt: Date.now(),
|
|
4819
|
-
idempotentReplay: false
|
|
4820
|
-
};
|
|
4821
|
-
}
|
|
4822
|
-
async function createDatabase(inv, accessToken) {
|
|
4823
|
-
const { parentPageId, title, properties } = inv.args;
|
|
4824
|
-
if (typeof parentPageId !== "string" || parentPageId.length === 0) {
|
|
4825
|
-
throw new Error("notion-database databases.create: parentPageId is required");
|
|
4826
|
-
}
|
|
4827
|
-
if (!title) throw new Error("notion-database databases.create: title is required");
|
|
4828
|
-
if (!properties) throw new Error("notion-database databases.create: properties is required");
|
|
4829
|
-
const res = await fetch(`${API5}/databases`, {
|
|
4830
|
-
method: "POST",
|
|
4831
|
-
headers: {
|
|
4832
|
-
...notionHeaders(accessToken),
|
|
4833
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4834
|
-
},
|
|
4835
|
-
body: JSON.stringify({
|
|
4836
|
-
parent: { type: "page_id", page_id: parentPageId },
|
|
4837
|
-
title,
|
|
4838
|
-
properties
|
|
4839
|
-
}),
|
|
4840
|
-
signal: AbortSignal.timeout(15e3)
|
|
4841
|
-
});
|
|
4842
|
-
if (res.status === 401) {
|
|
4843
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4844
|
-
}
|
|
4845
|
-
if (res.status === 409) {
|
|
4846
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4847
|
-
}
|
|
4848
|
-
if (!res.ok) {
|
|
4849
|
-
const text = await res.text().catch(() => "");
|
|
4850
|
-
throw new Error(`notion-database databases.create ${res.status}: ${text.slice(0, 200)}`);
|
|
4851
|
-
}
|
|
4852
|
-
const created = await res.json();
|
|
4853
|
-
return {
|
|
4854
|
-
status: "committed",
|
|
4855
|
-
data: { databaseId: created.id, url: created.url, lastEditedTime: created.last_edited_time },
|
|
4856
|
-
etagAfter: created.last_edited_time,
|
|
4857
|
-
committedAt: Date.now(),
|
|
4858
|
-
idempotentReplay: false
|
|
4859
|
-
};
|
|
4860
|
-
}
|
|
4861
|
-
async function updateDatabase(inv, accessToken) {
|
|
4862
|
-
const { databaseId, title, properties } = inv.args;
|
|
4863
|
-
if (typeof databaseId !== "string" || databaseId.length === 0) {
|
|
4864
|
-
throw new Error("notion-database databases.update: databaseId is required");
|
|
4865
|
-
}
|
|
4866
|
-
const body = {};
|
|
4867
|
-
if (title !== void 0) body.title = title;
|
|
4868
|
-
if (properties !== void 0) body.properties = properties;
|
|
4869
|
-
const res = await fetch(`${API5}/databases/${encodeURIComponent(databaseId)}`, {
|
|
4870
|
-
method: "PATCH",
|
|
4871
|
-
headers: {
|
|
4872
|
-
...notionHeaders(accessToken),
|
|
4873
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4874
|
-
},
|
|
4875
|
-
body: JSON.stringify(body),
|
|
4876
|
-
signal: AbortSignal.timeout(15e3)
|
|
4877
|
-
});
|
|
4878
|
-
if (res.status === 401) {
|
|
4879
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4880
|
-
}
|
|
4881
|
-
if (res.status === 409) {
|
|
4882
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4883
|
-
}
|
|
4884
|
-
if (!res.ok) {
|
|
4885
|
-
const text = await res.text().catch(() => "");
|
|
4886
|
-
throw new Error(`notion-database databases.update ${res.status}: ${text.slice(0, 200)}`);
|
|
4887
|
-
}
|
|
4888
|
-
const updated = await res.json();
|
|
4889
|
-
return {
|
|
4890
|
-
status: "committed",
|
|
4891
|
-
data: { databaseId: updated.id, url: updated.url, lastEditedTime: updated.last_edited_time },
|
|
4892
|
-
etagAfter: updated.last_edited_time,
|
|
4893
|
-
committedAt: Date.now(),
|
|
4894
|
-
idempotentReplay: false
|
|
4895
|
-
};
|
|
4896
|
-
}
|
|
4897
|
-
async function appendBlocks(inv, accessToken) {
|
|
4898
|
-
const { blockId, children } = inv.args;
|
|
4899
|
-
if (typeof blockId !== "string" || blockId.length === 0) {
|
|
4900
|
-
throw new Error("notion-database blocks.append: blockId is required");
|
|
4901
|
-
}
|
|
4902
|
-
if (!Array.isArray(children)) {
|
|
4903
|
-
throw new Error("notion-database blocks.append: children must be an array");
|
|
4904
|
-
}
|
|
4905
|
-
const res = await fetch(`${API5}/blocks/${encodeURIComponent(blockId)}/children`, {
|
|
4906
|
-
method: "PATCH",
|
|
4907
|
-
headers: {
|
|
4908
|
-
...notionHeaders(accessToken),
|
|
4909
|
-
"Idempotency-Key": inv.idempotencyKey
|
|
4910
|
-
},
|
|
4911
|
-
body: JSON.stringify({ children }),
|
|
4912
|
-
signal: AbortSignal.timeout(15e3)
|
|
4913
|
-
});
|
|
4914
|
-
if (res.status === 401) {
|
|
4915
|
-
throw new CredentialsExpired("Notion rejected token (401)", inv.source.id);
|
|
4916
|
-
}
|
|
4917
|
-
if (res.status === 409) {
|
|
4918
|
-
throw new ResourceContention("Notion idempotency-key conflict \u2014 different args under same key");
|
|
4919
|
-
}
|
|
4920
|
-
if (!res.ok) {
|
|
4921
|
-
const text = await res.text().catch(() => "");
|
|
4922
|
-
throw new Error(`notion-database blocks.append ${res.status}: ${text.slice(0, 200)}`);
|
|
4923
|
-
}
|
|
4924
|
-
const json = await res.json();
|
|
4925
|
-
return {
|
|
4926
|
-
status: "committed",
|
|
4927
|
-
data: { results: json.results ?? [] },
|
|
4928
|
-
committedAt: Date.now(),
|
|
4929
|
-
idempotentReplay: false
|
|
4930
|
-
};
|
|
4931
|
-
}
|
|
4932
|
-
function notionHeaders(accessToken) {
|
|
4933
|
-
return {
|
|
4934
|
-
authorization: `Bearer ${accessToken}`,
|
|
4935
|
-
"Notion-Version": NOTION_VERSION,
|
|
4936
|
-
"content-type": "application/json"
|
|
4937
|
-
};
|
|
4938
|
-
}
|
|
4939
|
-
function readToken(creds) {
|
|
4940
|
-
if (creds.kind !== "oauth2" || typeof creds.accessToken !== "string") {
|
|
4941
|
-
throw new Error("notion-database: expected oauth2 credentials");
|
|
4942
|
-
}
|
|
4943
|
-
return creds.accessToken;
|
|
4944
|
-
}
|
|
4945
|
-
function readMetaString3(meta, key) {
|
|
4946
|
-
const v = meta[key];
|
|
4947
|
-
if (typeof v !== "string" || v.length === 0) {
|
|
4948
|
-
throw new Error(`notion-database DataSource.metadata.${key} is missing`);
|
|
4949
|
-
}
|
|
4950
|
-
return v;
|
|
4951
|
-
}
|
|
4952
|
-
|
|
4953
4601
|
// src/connectors/adapters/docuseal.ts
|
|
4954
4602
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
4955
4603
|
var DEFAULT_BASE = "https://api.docuseal.com";
|
|
@@ -5249,7 +4897,7 @@ async function voidSubmission(inv, apiKey, baseUrl, timeoutMs) {
|
|
|
5249
4897
|
}
|
|
5250
4898
|
|
|
5251
4899
|
// src/connectors/adapters/twilio-sms.ts
|
|
5252
|
-
var
|
|
4900
|
+
var API5 = "https://api.twilio.com/2010-04-01";
|
|
5253
4901
|
var LOOKUP_API = "https://lookups.twilio.com/v1";
|
|
5254
4902
|
var twilioSmsConnector = {
|
|
5255
4903
|
manifest: {
|
|
@@ -5406,7 +5054,7 @@ var twilioSmsConnector = {
|
|
|
5406
5054
|
params.set("PageSize", String(Math.min(Math.max(1, limit ?? 20), 100)));
|
|
5407
5055
|
if (to) params.set("To", to);
|
|
5408
5056
|
if (from) params.set("From", from);
|
|
5409
|
-
const url = `${
|
|
5057
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json?${params.toString()}`;
|
|
5410
5058
|
const res = await fetch(url, {
|
|
5411
5059
|
headers: { authorization: basicAuth(auth) },
|
|
5412
5060
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -5427,7 +5075,7 @@ var twilioSmsConnector = {
|
|
|
5427
5075
|
const params = new URLSearchParams();
|
|
5428
5076
|
params.set("PageSize", String(Math.min(Math.max(1, limit ?? 50), 100)));
|
|
5429
5077
|
if (phoneNumber) params.set("PhoneNumber", phoneNumber);
|
|
5430
|
-
const url = `${
|
|
5078
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/IncomingPhoneNumbers.json?${params.toString()}`;
|
|
5431
5079
|
const res = await fetch(url, {
|
|
5432
5080
|
headers: { authorization: basicAuth(auth) },
|
|
5433
5081
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -5449,13 +5097,13 @@ var twilioSmsConnector = {
|
|
|
5449
5097
|
const auth = parseAuth(inv.source.credentials);
|
|
5450
5098
|
if (inv.capabilityName === "send_sms") {
|
|
5451
5099
|
const { to, body, from } = inv.args;
|
|
5452
|
-
const fromNumber = from ??
|
|
5100
|
+
const fromNumber = from ?? readMetaString3(inv.source.metadata, "fromNumber");
|
|
5453
5101
|
const formBody = new URLSearchParams({ To: to, From: fromNumber, Body: body });
|
|
5454
5102
|
return await postMessages(inv, auth, formBody, "send_sms");
|
|
5455
5103
|
}
|
|
5456
5104
|
if (inv.capabilityName === "send_mms") {
|
|
5457
5105
|
const { to, body, from, mediaUrl } = inv.args;
|
|
5458
|
-
const fromNumber = from ??
|
|
5106
|
+
const fromNumber = from ?? readMetaString3(inv.source.metadata, "fromNumber");
|
|
5459
5107
|
const formBody = new URLSearchParams();
|
|
5460
5108
|
formBody.set("To", to);
|
|
5461
5109
|
formBody.set("From", fromNumber);
|
|
@@ -5467,7 +5115,7 @@ var twilioSmsConnector = {
|
|
|
5467
5115
|
if (inv.capabilityName === "send_whatsapp") {
|
|
5468
5116
|
const { to, body, from } = inv.args;
|
|
5469
5117
|
const ensureWhatsapp = (n) => n.startsWith("whatsapp:") ? n : `whatsapp:${n}`;
|
|
5470
|
-
const fromRaw = from ?? readMetaStringOptional(inv.source.metadata, "whatsappFromNumber") ??
|
|
5118
|
+
const fromRaw = from ?? readMetaStringOptional(inv.source.metadata, "whatsappFromNumber") ?? readMetaString3(inv.source.metadata, "fromNumber");
|
|
5471
5119
|
const formBody = new URLSearchParams({
|
|
5472
5120
|
To: ensureWhatsapp(to),
|
|
5473
5121
|
From: ensureWhatsapp(fromRaw),
|
|
@@ -5477,7 +5125,7 @@ var twilioSmsConnector = {
|
|
|
5477
5125
|
}
|
|
5478
5126
|
if (inv.capabilityName === "redact_message") {
|
|
5479
5127
|
const { messageSid } = inv.args;
|
|
5480
|
-
const url = `${
|
|
5128
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages/${encodeURIComponent(messageSid)}.json`;
|
|
5481
5129
|
const formBody = new URLSearchParams({ Body: "" });
|
|
5482
5130
|
const res = await fetch(url, {
|
|
5483
5131
|
method: "POST",
|
|
@@ -5510,7 +5158,7 @@ var twilioSmsConnector = {
|
|
|
5510
5158
|
async test(source) {
|
|
5511
5159
|
try {
|
|
5512
5160
|
const auth = parseAuth(source.credentials);
|
|
5513
|
-
const res = await fetch(`${
|
|
5161
|
+
const res = await fetch(`${API5}/Accounts/${encodeURIComponent(auth.accountSid)}.json`, {
|
|
5514
5162
|
headers: { authorization: basicAuth(auth) },
|
|
5515
5163
|
signal: AbortSignal.timeout(8e3)
|
|
5516
5164
|
});
|
|
@@ -5546,7 +5194,7 @@ function parseAuth(creds) {
|
|
|
5546
5194
|
function basicAuth(auth) {
|
|
5547
5195
|
return `Basic ${Buffer.from(`${auth.username}:${auth.password}`).toString("base64")}`;
|
|
5548
5196
|
}
|
|
5549
|
-
function
|
|
5197
|
+
function readMetaString3(meta, key) {
|
|
5550
5198
|
const v = meta[key];
|
|
5551
5199
|
if (typeof v !== "string" || v.length === 0) {
|
|
5552
5200
|
throw new Error(`twilio-sms DataSource.metadata.${key} is missing`);
|
|
@@ -5558,7 +5206,7 @@ function readMetaStringOptional(meta, key) {
|
|
|
5558
5206
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
5559
5207
|
}
|
|
5560
5208
|
async function postMessages(inv, auth, formBody, label) {
|
|
5561
|
-
const url = `${
|
|
5209
|
+
const url = `${API5}/Accounts/${encodeURIComponent(auth.accountSid)}/Messages.json`;
|
|
5562
5210
|
const res = await fetch(url, {
|
|
5563
5211
|
method: "POST",
|
|
5564
5212
|
headers: {
|
|
@@ -5587,7 +5235,7 @@ async function postMessages(inv, auth, formBody, label) {
|
|
|
5587
5235
|
}
|
|
5588
5236
|
|
|
5589
5237
|
// src/connectors/adapters/phony.ts
|
|
5590
|
-
var
|
|
5238
|
+
var API6 = "https://api.ph0ny.com";
|
|
5591
5239
|
var E164 = /^\+[1-9]\d{7,14}$/;
|
|
5592
5240
|
var phonyConnector = {
|
|
5593
5241
|
manifest: {
|
|
@@ -5857,7 +5505,7 @@ var phonyConnector = {
|
|
|
5857
5505
|
const json = await getJson(
|
|
5858
5506
|
inv,
|
|
5859
5507
|
token,
|
|
5860
|
-
`${
|
|
5508
|
+
`${API6}/v1/agents?${params.toString()}`,
|
|
5861
5509
|
"list_agents"
|
|
5862
5510
|
);
|
|
5863
5511
|
return {
|
|
@@ -5870,7 +5518,7 @@ var phonyConnector = {
|
|
|
5870
5518
|
const json = await getJson(
|
|
5871
5519
|
inv,
|
|
5872
5520
|
token,
|
|
5873
|
-
`${
|
|
5521
|
+
`${API6}/v1/outbound/${encodeURIComponent(id)}`,
|
|
5874
5522
|
"get_call"
|
|
5875
5523
|
);
|
|
5876
5524
|
return { data: { call: json.call ?? null }, fetchedAt: Date.now() };
|
|
@@ -5883,7 +5531,7 @@ var phonyConnector = {
|
|
|
5883
5531
|
const json = await getJson(
|
|
5884
5532
|
inv,
|
|
5885
5533
|
token,
|
|
5886
|
-
`${
|
|
5534
|
+
`${API6}/v1/outbound?${params.toString()}`,
|
|
5887
5535
|
"list_calls"
|
|
5888
5536
|
);
|
|
5889
5537
|
return { data: { calls: json.calls ?? [] }, fetchedAt: Date.now() };
|
|
@@ -5894,7 +5542,7 @@ var phonyConnector = {
|
|
|
5894
5542
|
if (limit !== void 0) payload.limit = limit;
|
|
5895
5543
|
if (threshold !== void 0) payload.threshold = threshold;
|
|
5896
5544
|
if (includeMetadata !== void 0) payload.includeMetadata = includeMetadata;
|
|
5897
|
-
const res = await fetch(`${
|
|
5545
|
+
const res = await fetch(`${API6}/v1/collections/${encodeURIComponent(collectionId)}/search`, {
|
|
5898
5546
|
method: "POST",
|
|
5899
5547
|
headers: {
|
|
5900
5548
|
authorization: `Bearer ${token}`,
|
|
@@ -5935,7 +5583,7 @@ var phonyConnector = {
|
|
|
5935
5583
|
if (args.callerProfile !== void 0) payload.callerProfile = args.callerProfile;
|
|
5936
5584
|
if (args.voiceCloneId !== void 0) payload.voiceCloneId = args.voiceCloneId;
|
|
5937
5585
|
if (args.dryRun !== void 0) payload.dryRun = args.dryRun;
|
|
5938
|
-
const res = await fetch(`${
|
|
5586
|
+
const res = await fetch(`${API6}/v1/outbound/start`, {
|
|
5939
5587
|
method: "POST",
|
|
5940
5588
|
headers: {
|
|
5941
5589
|
authorization: `Bearer ${token}`,
|
|
@@ -5965,7 +5613,7 @@ var phonyConnector = {
|
|
|
5965
5613
|
}
|
|
5966
5614
|
if (inv.capabilityName === "create_agent") {
|
|
5967
5615
|
const payload = pick(inv.args, AGENT_FIELDS);
|
|
5968
|
-
const json = await postJson(inv, token, `${
|
|
5616
|
+
const json = await postJson(inv, token, `${API6}/v1/agents`, payload, "create_agent");
|
|
5969
5617
|
return {
|
|
5970
5618
|
status: "committed",
|
|
5971
5619
|
data: { agent: json },
|
|
@@ -5981,7 +5629,7 @@ var phonyConnector = {
|
|
|
5981
5629
|
const json = await postJson(
|
|
5982
5630
|
inv,
|
|
5983
5631
|
token,
|
|
5984
|
-
`${
|
|
5632
|
+
`${API6}/v1/agents/provision`,
|
|
5985
5633
|
payload,
|
|
5986
5634
|
"provision_agent"
|
|
5987
5635
|
);
|
|
@@ -6001,7 +5649,7 @@ var phonyConnector = {
|
|
|
6001
5649
|
const payload = { name };
|
|
6002
5650
|
if (description !== void 0) payload.description = description;
|
|
6003
5651
|
if (metadata !== void 0) payload.metadata = metadata;
|
|
6004
|
-
const json = await postJson(inv, token, `${
|
|
5652
|
+
const json = await postJson(inv, token, `${API6}/v1/collections`, payload, "kb_create_collection");
|
|
6005
5653
|
return {
|
|
6006
5654
|
status: "committed",
|
|
6007
5655
|
data: { collection: json },
|
|
@@ -6015,7 +5663,7 @@ var phonyConnector = {
|
|
|
6015
5663
|
const json = await postJson(
|
|
6016
5664
|
inv,
|
|
6017
5665
|
token,
|
|
6018
|
-
`${
|
|
5666
|
+
`${API6}/v1/collections/${encodeURIComponent(collectionId)}/ingest`,
|
|
6019
5667
|
payload,
|
|
6020
5668
|
"kb_ingest"
|
|
6021
5669
|
);
|
|
@@ -6035,7 +5683,7 @@ var phonyConnector = {
|
|
|
6035
5683
|
async test(source) {
|
|
6036
5684
|
try {
|
|
6037
5685
|
const token = bearerToken(source.credentials);
|
|
6038
|
-
const res = await fetch(`${
|
|
5686
|
+
const res = await fetch(`${API6}/v1/outbound?limit=1`, {
|
|
6039
5687
|
headers: { authorization: `Bearer ${token}` },
|
|
6040
5688
|
signal: AbortSignal.timeout(8e3)
|
|
6041
5689
|
});
|
|
@@ -6180,9 +5828,9 @@ var INGEST_FIELDS = [
|
|
|
6180
5828
|
|
|
6181
5829
|
// src/connectors/adapters/whatsapp-business.ts
|
|
6182
5830
|
var SCOPES5 = ["whatsapp_business_messaging", "whatsapp_business_management", "business_management"];
|
|
6183
|
-
var
|
|
6184
|
-
var
|
|
6185
|
-
var
|
|
5831
|
+
var AUTH_URL8 = "https://www.facebook.com/v21.0/dialog/oauth";
|
|
5832
|
+
var TOKEN_URL8 = "https://graph.facebook.com/v21.0/oauth/access_token";
|
|
5833
|
+
var API7 = "https://graph.facebook.com/v21.0";
|
|
6186
5834
|
function whatsappBusiness(opts) {
|
|
6187
5835
|
const { clientId, clientSecret } = opts;
|
|
6188
5836
|
const adapter = {
|
|
@@ -6192,8 +5840,8 @@ function whatsappBusiness(opts) {
|
|
|
6192
5840
|
description: "Send text and template messages from a verified WhatsApp Business number, and read your approved message templates. Advisory surface \u2014 WhatsApp sends are append-only.",
|
|
6193
5841
|
auth: {
|
|
6194
5842
|
kind: "oauth2",
|
|
6195
|
-
authorizationUrl:
|
|
6196
|
-
tokenUrl:
|
|
5843
|
+
authorizationUrl: AUTH_URL8,
|
|
5844
|
+
tokenUrl: TOKEN_URL8,
|
|
6197
5845
|
scopes: SCOPES5,
|
|
6198
5846
|
clientIdEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_ID",
|
|
6199
5847
|
clientSecretEnv: "WHATSAPP_BUSINESS_OAUTH_CLIENT_SECRET"
|
|
@@ -6330,12 +5978,12 @@ function whatsappBusiness(opts) {
|
|
|
6330
5978
|
async executeRead(inv) {
|
|
6331
5979
|
const accessToken = readAccessToken(inv.source.credentials);
|
|
6332
5980
|
if (inv.capabilityName === "list_message_templates") {
|
|
6333
|
-
const wabaId =
|
|
5981
|
+
const wabaId = readMetaString4(inv.source.metadata, "wabaId");
|
|
6334
5982
|
const { limit, status } = inv.args;
|
|
6335
5983
|
const params = new URLSearchParams();
|
|
6336
5984
|
params.set("limit", String(Math.min(Math.max(1, limit ?? 50), 200)));
|
|
6337
5985
|
if (status) params.set("status", status);
|
|
6338
|
-
const url = `${
|
|
5986
|
+
const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
|
|
6339
5987
|
const json = await graphGet(url, accessToken, inv.source.id);
|
|
6340
5988
|
const data = json.data ?? [];
|
|
6341
5989
|
return {
|
|
@@ -6352,11 +6000,11 @@ function whatsappBusiness(opts) {
|
|
|
6352
6000
|
};
|
|
6353
6001
|
}
|
|
6354
6002
|
if (inv.capabilityName === "get_business_phone_number") {
|
|
6355
|
-
const phoneNumberId =
|
|
6003
|
+
const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
|
|
6356
6004
|
const params = new URLSearchParams({
|
|
6357
6005
|
fields: "display_phone_number,verified_name,quality_rating,code_verification_status,platform_type"
|
|
6358
6006
|
});
|
|
6359
|
-
const url = `${
|
|
6007
|
+
const url = `${API7}/${encodeURIComponent(phoneNumberId)}?${params.toString()}`;
|
|
6360
6008
|
const json = await graphGet(url, accessToken, inv.source.id);
|
|
6361
6009
|
return {
|
|
6362
6010
|
data: {
|
|
@@ -6382,8 +6030,8 @@ function whatsappBusiness(opts) {
|
|
|
6382
6030
|
if (inv.capabilityName === "templates.delete") {
|
|
6383
6031
|
return deleteTemplate(inv, accessToken);
|
|
6384
6032
|
}
|
|
6385
|
-
const phoneNumberId =
|
|
6386
|
-
const url = `${
|
|
6033
|
+
const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
|
|
6034
|
+
const url = `${API7}/${encodeURIComponent(phoneNumberId)}/messages`;
|
|
6387
6035
|
let body;
|
|
6388
6036
|
if (inv.capabilityName === "send_text_message") {
|
|
6389
6037
|
const { to, body: text, previewUrl } = inv.args;
|
|
@@ -6464,7 +6112,7 @@ function whatsappBusiness(opts) {
|
|
|
6464
6112
|
throw new Error("WhatsApp Business OAuth client not configured (WHATSAPP_BUSINESS_OAUTH_CLIENT_ID / _SECRET)");
|
|
6465
6113
|
}
|
|
6466
6114
|
const tokens = await exchangeAuthorizationCode({
|
|
6467
|
-
tokenUrl:
|
|
6115
|
+
tokenUrl: TOKEN_URL8,
|
|
6468
6116
|
clientId,
|
|
6469
6117
|
clientSecret,
|
|
6470
6118
|
code: input.code,
|
|
@@ -6488,7 +6136,7 @@ function whatsappBusiness(opts) {
|
|
|
6488
6136
|
try {
|
|
6489
6137
|
const accessToken = readAccessToken(source.credentials);
|
|
6490
6138
|
const phoneNumberId = typeof source.metadata.phoneNumberId === "string" ? source.metadata.phoneNumberId : void 0;
|
|
6491
|
-
const probeUrl = phoneNumberId ? `${
|
|
6139
|
+
const probeUrl = phoneNumberId ? `${API7}/${encodeURIComponent(phoneNumberId)}?fields=display_phone_number` : `${API7}/me?fields=id`;
|
|
6492
6140
|
const res = await fetch(probeUrl, {
|
|
6493
6141
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
6494
6142
|
signal: AbortSignal.timeout(8e3)
|
|
@@ -6512,7 +6160,7 @@ function readAccessToken(creds) {
|
|
|
6512
6160
|
}
|
|
6513
6161
|
return creds.accessToken;
|
|
6514
6162
|
}
|
|
6515
|
-
function
|
|
6163
|
+
function readMetaString4(meta, key) {
|
|
6516
6164
|
const v = meta[key];
|
|
6517
6165
|
if (typeof v !== "string" || v.length === 0) {
|
|
6518
6166
|
throw new Error(`whatsapp-business DataSource.metadata.${key} is missing \u2014 set it at connect-time from the Embedded Signup callback`);
|
|
@@ -6541,7 +6189,7 @@ function decodeBase64(value) {
|
|
|
6541
6189
|
return bytes;
|
|
6542
6190
|
}
|
|
6543
6191
|
async function uploadMedia(inv, accessToken) {
|
|
6544
|
-
const phoneNumberId =
|
|
6192
|
+
const phoneNumberId = readMetaString4(inv.source.metadata, "phoneNumberId");
|
|
6545
6193
|
const { dataBase64, mimeType, filename } = inv.args;
|
|
6546
6194
|
if (typeof dataBase64 !== "string" || dataBase64.length === 0) {
|
|
6547
6195
|
throw new Error("whatsapp-business media.upload: dataBase64 is required");
|
|
@@ -6554,7 +6202,7 @@ async function uploadMedia(inv, accessToken) {
|
|
|
6554
6202
|
form.set("messaging_product", "whatsapp");
|
|
6555
6203
|
form.set("type", mimeType);
|
|
6556
6204
|
form.set("file", new Blob([bytes], { type: mimeType }), filename ?? "upload");
|
|
6557
|
-
const url = `${
|
|
6205
|
+
const url = `${API7}/${encodeURIComponent(phoneNumberId)}/media`;
|
|
6558
6206
|
const res = await fetch(url, {
|
|
6559
6207
|
method: "POST",
|
|
6560
6208
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
@@ -6577,7 +6225,7 @@ async function uploadMedia(inv, accessToken) {
|
|
|
6577
6225
|
};
|
|
6578
6226
|
}
|
|
6579
6227
|
async function createTemplate(inv, accessToken) {
|
|
6580
|
-
const wabaId =
|
|
6228
|
+
const wabaId = readMetaString4(inv.source.metadata, "wabaId");
|
|
6581
6229
|
const { name, language, category, components } = inv.args;
|
|
6582
6230
|
if (typeof name !== "string" || name.length === 0) {
|
|
6583
6231
|
throw new Error("whatsapp-business templates.create: name is required");
|
|
@@ -6591,7 +6239,7 @@ async function createTemplate(inv, accessToken) {
|
|
|
6591
6239
|
if (!Array.isArray(components)) {
|
|
6592
6240
|
throw new Error("whatsapp-business templates.create: components must be an array");
|
|
6593
6241
|
}
|
|
6594
|
-
const url = `${
|
|
6242
|
+
const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates`;
|
|
6595
6243
|
const res = await fetch(url, {
|
|
6596
6244
|
method: "POST",
|
|
6597
6245
|
headers: {
|
|
@@ -6617,7 +6265,7 @@ async function createTemplate(inv, accessToken) {
|
|
|
6617
6265
|
};
|
|
6618
6266
|
}
|
|
6619
6267
|
async function deleteTemplate(inv, accessToken) {
|
|
6620
|
-
const wabaId =
|
|
6268
|
+
const wabaId = readMetaString4(inv.source.metadata, "wabaId");
|
|
6621
6269
|
const { name, hsmId } = inv.args;
|
|
6622
6270
|
if (typeof name !== "string" || name.length === 0) {
|
|
6623
6271
|
throw new Error("whatsapp-business templates.delete: name is required");
|
|
@@ -6625,7 +6273,7 @@ async function deleteTemplate(inv, accessToken) {
|
|
|
6625
6273
|
const params = new URLSearchParams();
|
|
6626
6274
|
params.set("name", name);
|
|
6627
6275
|
if (typeof hsmId === "string" && hsmId.length > 0) params.set("hsm_id", hsmId);
|
|
6628
|
-
const url = `${
|
|
6276
|
+
const url = `${API7}/${encodeURIComponent(wabaId)}/message_templates?${params.toString()}`;
|
|
6629
6277
|
const res = await fetch(url, {
|
|
6630
6278
|
method: "DELETE",
|
|
6631
6279
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
@@ -6648,7 +6296,7 @@ async function deleteTemplate(inv, accessToken) {
|
|
|
6648
6296
|
}
|
|
6649
6297
|
|
|
6650
6298
|
// src/connectors/adapters/stripe-pack.ts
|
|
6651
|
-
var
|
|
6299
|
+
var API8 = "https://api.stripe.com/v1";
|
|
6652
6300
|
var stripePackConnector = {
|
|
6653
6301
|
manifest: {
|
|
6654
6302
|
kind: "stripe-pack",
|
|
@@ -6848,7 +6496,7 @@ var stripePackConnector = {
|
|
|
6848
6496
|
throw new Error(`stripe-pack: unknown read capability ${inv.capabilityName}`);
|
|
6849
6497
|
}
|
|
6850
6498
|
const { email } = inv.args;
|
|
6851
|
-
const url = `${
|
|
6499
|
+
const url = `${API8}/customers/search?query=${encodeURIComponent(`email:'${email.toLowerCase()}'`)}&limit=1`;
|
|
6852
6500
|
const res = await fetch(url, {
|
|
6853
6501
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
6854
6502
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -6881,7 +6529,7 @@ var stripePackConnector = {
|
|
|
6881
6529
|
async test(source) {
|
|
6882
6530
|
try {
|
|
6883
6531
|
const apiKey = readApiKey(source.credentials);
|
|
6884
|
-
const res = await fetch(`${
|
|
6532
|
+
const res = await fetch(`${API8}/account`, {
|
|
6885
6533
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
6886
6534
|
signal: AbortSignal.timeout(8e3)
|
|
6887
6535
|
});
|
|
@@ -6907,7 +6555,7 @@ async function createInvoice(inv, apiKey) {
|
|
|
6907
6555
|
quantity: String(it.quantity ?? 1)
|
|
6908
6556
|
});
|
|
6909
6557
|
if (it.description) body.set("description", it.description);
|
|
6910
|
-
const res = await fetch(`${
|
|
6558
|
+
const res = await fetch(`${API8}/invoiceitems`, {
|
|
6911
6559
|
method: "POST",
|
|
6912
6560
|
headers: {
|
|
6913
6561
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -6932,7 +6580,7 @@ async function createInvoice(inv, apiKey) {
|
|
|
6932
6580
|
collection_method: "send_invoice",
|
|
6933
6581
|
days_until_due: "14"
|
|
6934
6582
|
});
|
|
6935
|
-
const invRes = await fetch(`${
|
|
6583
|
+
const invRes = await fetch(`${API8}/invoices`, {
|
|
6936
6584
|
method: "POST",
|
|
6937
6585
|
headers: {
|
|
6938
6586
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -6970,7 +6618,7 @@ async function createCheckoutSession(inv, apiKey) {
|
|
|
6970
6618
|
body.set(`line_items[${i}][price]`, it.price);
|
|
6971
6619
|
body.set(`line_items[${i}][quantity]`, String(it.quantity ?? 1));
|
|
6972
6620
|
});
|
|
6973
|
-
const res = await fetch(`${
|
|
6621
|
+
const res = await fetch(`${API8}/checkout/sessions`, {
|
|
6974
6622
|
method: "POST",
|
|
6975
6623
|
headers: {
|
|
6976
6624
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7001,7 +6649,7 @@ async function listSubscriptions(inv, apiKey) {
|
|
|
7001
6649
|
const params = new URLSearchParams({ customer: customerId, limit: String(limit ?? 10) });
|
|
7002
6650
|
if (status && status !== "all") params.set("status", status);
|
|
7003
6651
|
else params.set("status", "all");
|
|
7004
|
-
const res = await fetch(`${
|
|
6652
|
+
const res = await fetch(`${API8}/subscriptions?${params.toString()}`, {
|
|
7005
6653
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
7006
6654
|
signal: AbortSignal.timeout(1e4)
|
|
7007
6655
|
});
|
|
@@ -7036,7 +6684,7 @@ async function cancelSubscription(inv, apiKey) {
|
|
|
7036
6684
|
let res;
|
|
7037
6685
|
if (atPeriodEnd) {
|
|
7038
6686
|
const body = new URLSearchParams({ cancel_at_period_end: "true" });
|
|
7039
|
-
res = await fetch(`${
|
|
6687
|
+
res = await fetch(`${API8}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
|
|
7040
6688
|
method: "POST",
|
|
7041
6689
|
headers: {
|
|
7042
6690
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7047,7 +6695,7 @@ async function cancelSubscription(inv, apiKey) {
|
|
|
7047
6695
|
signal: AbortSignal.timeout(15e3)
|
|
7048
6696
|
});
|
|
7049
6697
|
} else {
|
|
7050
|
-
res = await fetch(`${
|
|
6698
|
+
res = await fetch(`${API8}/subscriptions/${encodeURIComponent(subscriptionId)}`, {
|
|
7051
6699
|
method: "DELETE",
|
|
7052
6700
|
headers: {
|
|
7053
6701
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7082,7 +6730,7 @@ async function cancelSubscription(inv, apiKey) {
|
|
|
7082
6730
|
async function createBillingPortalSession(inv, apiKey) {
|
|
7083
6731
|
const { customerId, returnUrl } = inv.args;
|
|
7084
6732
|
const body = new URLSearchParams({ customer: customerId, return_url: returnUrl });
|
|
7085
|
-
const res = await fetch(`${
|
|
6733
|
+
const res = await fetch(`${API8}/billing_portal/sessions`, {
|
|
7086
6734
|
method: "POST",
|
|
7087
6735
|
headers: {
|
|
7088
6736
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7130,7 +6778,7 @@ async function createPaymentIntent(inv, apiKey) {
|
|
|
7130
6778
|
body.set(`metadata[${k}]`, String(v));
|
|
7131
6779
|
}
|
|
7132
6780
|
}
|
|
7133
|
-
const res = await fetch(`${
|
|
6781
|
+
const res = await fetch(`${API8}/payment_intents`, {
|
|
7134
6782
|
method: "POST",
|
|
7135
6783
|
headers: {
|
|
7136
6784
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7178,7 +6826,7 @@ async function createRefund(inv, apiKey) {
|
|
|
7178
6826
|
if (args.charge) body.set("charge", args.charge);
|
|
7179
6827
|
if (typeof args.amount === "number") body.set("amount", String(args.amount));
|
|
7180
6828
|
if (args.reason) body.set("reason", args.reason);
|
|
7181
|
-
const res = await fetch(`${
|
|
6829
|
+
const res = await fetch(`${API8}/refunds`, {
|
|
7182
6830
|
method: "POST",
|
|
7183
6831
|
headers: {
|
|
7184
6832
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7226,7 +6874,7 @@ async function createCustomer(inv, apiKey) {
|
|
|
7226
6874
|
body.set(`metadata[${k}]`, String(v));
|
|
7227
6875
|
}
|
|
7228
6876
|
}
|
|
7229
|
-
const res = await fetch(`${
|
|
6877
|
+
const res = await fetch(`${API8}/customers`, {
|
|
7230
6878
|
method: "POST",
|
|
7231
6879
|
headers: {
|
|
7232
6880
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -7302,7 +6950,7 @@ var webhookConnector = {
|
|
|
7302
6950
|
]
|
|
7303
6951
|
},
|
|
7304
6952
|
async executeRead(inv) {
|
|
7305
|
-
const url =
|
|
6953
|
+
const url = readMetaString5(inv.source.metadata, "url");
|
|
7306
6954
|
const params = inv.args && typeof inv.args === "object" ? inv.args : {};
|
|
7307
6955
|
const u = new URL(url);
|
|
7308
6956
|
for (const [k, v] of Object.entries(params)) {
|
|
@@ -7324,7 +6972,7 @@ var webhookConnector = {
|
|
|
7324
6972
|
};
|
|
7325
6973
|
},
|
|
7326
6974
|
async executeMutation(inv) {
|
|
7327
|
-
const url =
|
|
6975
|
+
const url = readMetaString5(inv.source.metadata, "url");
|
|
7328
6976
|
const body = JSON.stringify(inv.args ?? {});
|
|
7329
6977
|
const res = await fetch(url, {
|
|
7330
6978
|
method: "POST",
|
|
@@ -7354,7 +7002,7 @@ var webhookConnector = {
|
|
|
7354
7002
|
},
|
|
7355
7003
|
async test(source) {
|
|
7356
7004
|
try {
|
|
7357
|
-
const url =
|
|
7005
|
+
const url = readMetaString5(source.metadata, "url");
|
|
7358
7006
|
const res = await fetch(url, {
|
|
7359
7007
|
method: "HEAD",
|
|
7360
7008
|
headers: signHeaders(source.credentials, "", `health-${Date.now()}`),
|
|
@@ -7367,7 +7015,7 @@ var webhookConnector = {
|
|
|
7367
7015
|
}
|
|
7368
7016
|
}
|
|
7369
7017
|
};
|
|
7370
|
-
function
|
|
7018
|
+
function readMetaString5(meta, key) {
|
|
7371
7019
|
const v = meta[key];
|
|
7372
7020
|
if (typeof v !== "string" || v.length === 0) {
|
|
7373
7021
|
throw new Error(`webhook DataSource.metadata.${key} is missing`);
|
|
@@ -37415,8 +37063,8 @@ var SCOPES7 = [
|
|
|
37415
37063
|
"request_signature",
|
|
37416
37064
|
"signature_request_access"
|
|
37417
37065
|
];
|
|
37418
|
-
var
|
|
37419
|
-
var
|
|
37066
|
+
var AUTH_URL9 = "https://app.hellosign.com/oauth/authorize";
|
|
37067
|
+
var TOKEN_URL9 = "https://app.hellosign.com/oauth/token";
|
|
37420
37068
|
var DEFAULT_API_BASE = "https://api.hellosign.com/v3";
|
|
37421
37069
|
function hellosign(opts) {
|
|
37422
37070
|
const { clientId, clientSecret } = opts;
|
|
@@ -37429,11 +37077,15 @@ function hellosign(opts) {
|
|
|
37429
37077
|
description: "Send documents for e-signature via Dropbox Sign templates, poll signature-request status, cancel in-flight requests, and react to push events when signers complete.",
|
|
37430
37078
|
auth: {
|
|
37431
37079
|
kind: "oauth2",
|
|
37432
|
-
authorizationUrl:
|
|
37433
|
-
tokenUrl:
|
|
37080
|
+
authorizationUrl: AUTH_URL9,
|
|
37081
|
+
tokenUrl: TOKEN_URL9,
|
|
37434
37082
|
scopes: SCOPES7,
|
|
37435
37083
|
clientIdEnv: "HELLOSIGN_OAUTH_CLIENT_ID",
|
|
37436
|
-
clientSecretEnv: "HELLOSIGN_OAUTH_CLIENT_SECRET"
|
|
37084
|
+
clientSecretEnv: "HELLOSIGN_OAUTH_CLIENT_SECRET",
|
|
37085
|
+
// Dropbox Sign rejects a per-request `scope` param ("Custom scopes
|
|
37086
|
+
// are not supported yet") — scopes are pinned in the API app
|
|
37087
|
+
// settings, so the authorization URL must omit scope.
|
|
37088
|
+
sendScopeParam: false
|
|
37437
37089
|
},
|
|
37438
37090
|
category: "doc",
|
|
37439
37091
|
defaultConsistencyModel: "authoritative",
|
|
@@ -37583,7 +37235,7 @@ function hellosign(opts) {
|
|
|
37583
37235
|
throw new Error("Dropbox Sign OAuth client not configured (HELLOSIGN_OAUTH_CLIENT_ID / _SECRET)");
|
|
37584
37236
|
}
|
|
37585
37237
|
const tokens = await exchangeAuthorizationCode({
|
|
37586
|
-
tokenUrl:
|
|
37238
|
+
tokenUrl: TOKEN_URL9,
|
|
37587
37239
|
clientId,
|
|
37588
37240
|
clientSecret,
|
|
37589
37241
|
code: input.code,
|
|
@@ -37606,7 +37258,7 @@ function hellosign(opts) {
|
|
|
37606
37258
|
throw new Error("hellosign.refreshToken: missing refresh token");
|
|
37607
37259
|
}
|
|
37608
37260
|
const refreshed = await refreshAccessToken({
|
|
37609
|
-
tokenUrl:
|
|
37261
|
+
tokenUrl: TOKEN_URL9,
|
|
37610
37262
|
clientId,
|
|
37611
37263
|
clientSecret,
|
|
37612
37264
|
refreshToken: creds.refreshToken
|
|
@@ -37897,7 +37549,7 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
|
|
|
37897
37549
|
throw new CredentialsExpired("Dropbox Sign access token expired and no refresh token", inv?.source.id ?? "");
|
|
37898
37550
|
}
|
|
37899
37551
|
const refreshed = await refreshAccessToken({
|
|
37900
|
-
tokenUrl:
|
|
37552
|
+
tokenUrl: TOKEN_URL9,
|
|
37901
37553
|
clientId,
|
|
37902
37554
|
clientSecret,
|
|
37903
37555
|
refreshToken: creds.refreshToken
|
|
@@ -37916,12 +37568,12 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
|
|
|
37916
37568
|
|
|
37917
37569
|
// src/connectors/adapters/pandadoc.ts
|
|
37918
37570
|
var SCOPES8 = ["read", "read+write"];
|
|
37919
|
-
var
|
|
37920
|
-
var
|
|
37921
|
-
var
|
|
37571
|
+
var AUTH_URL10 = "https://app.pandadoc.com/oauth2/authorize";
|
|
37572
|
+
var TOKEN_URL10 = "https://api.pandadoc.com/oauth2/access_token";
|
|
37573
|
+
var API9 = "https://api.pandadoc.com/public/v1";
|
|
37922
37574
|
function pandadoc(opts) {
|
|
37923
37575
|
const { clientId, clientSecret } = opts;
|
|
37924
|
-
const baseUrl = (opts.baseUrl ??
|
|
37576
|
+
const baseUrl = (opts.baseUrl ?? API9).replace(/\/$/, "");
|
|
37925
37577
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
37926
37578
|
const adapter = {
|
|
37927
37579
|
manifest: {
|
|
@@ -37930,8 +37582,8 @@ function pandadoc(opts) {
|
|
|
37930
37582
|
description: "Draft contracts and proposals from PandaDoc templates, send them for signature, poll signing status, and cancel in-flight documents.",
|
|
37931
37583
|
auth: {
|
|
37932
37584
|
kind: "oauth2",
|
|
37933
|
-
authorizationUrl:
|
|
37934
|
-
tokenUrl:
|
|
37585
|
+
authorizationUrl: AUTH_URL10,
|
|
37586
|
+
tokenUrl: TOKEN_URL10,
|
|
37935
37587
|
scopes: SCOPES8,
|
|
37936
37588
|
clientIdEnv: "PANDADOC_OAUTH_CLIENT_ID",
|
|
37937
37589
|
clientSecretEnv: "PANDADOC_OAUTH_CLIENT_SECRET"
|
|
@@ -38079,7 +37731,7 @@ function pandadoc(opts) {
|
|
|
38079
37731
|
throw new Error("PandaDoc OAuth client not configured (PANDADOC_OAUTH_CLIENT_ID / _SECRET)");
|
|
38080
37732
|
}
|
|
38081
37733
|
const tokens = await exchangeAuthorizationCode({
|
|
38082
|
-
tokenUrl:
|
|
37734
|
+
tokenUrl: TOKEN_URL10,
|
|
38083
37735
|
clientId,
|
|
38084
37736
|
clientSecret,
|
|
38085
37737
|
code: input.code,
|
|
@@ -38102,7 +37754,7 @@ function pandadoc(opts) {
|
|
|
38102
37754
|
throw new Error("pandadoc.refreshToken: missing refresh token");
|
|
38103
37755
|
}
|
|
38104
37756
|
const refreshed = await refreshAccessToken({
|
|
38105
|
-
tokenUrl:
|
|
37757
|
+
tokenUrl: TOKEN_URL10,
|
|
38106
37758
|
clientId,
|
|
38107
37759
|
clientSecret,
|
|
38108
37760
|
refreshToken: creds.refreshToken
|
|
@@ -38410,7 +38062,7 @@ async function ensureFreshAccessTokenFromCreds(creds, clientId, clientSecret, on
|
|
|
38410
38062
|
throw new CredentialsExpired("PandaDoc access token expired and no refresh token", "");
|
|
38411
38063
|
}
|
|
38412
38064
|
const refreshed = await refreshAccessToken({
|
|
38413
|
-
tokenUrl:
|
|
38065
|
+
tokenUrl: TOKEN_URL10,
|
|
38414
38066
|
clientId,
|
|
38415
38067
|
clientSecret,
|
|
38416
38068
|
refreshToken: creds.refreshToken
|
|
@@ -38434,9 +38086,9 @@ var SCOPES9 = [
|
|
|
38434
38086
|
"https://www.googleapis.com/auth/documents",
|
|
38435
38087
|
"https://www.googleapis.com/auth/drive.file"
|
|
38436
38088
|
];
|
|
38437
|
-
var
|
|
38438
|
-
var
|
|
38439
|
-
var
|
|
38089
|
+
var AUTH_URL11 = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
38090
|
+
var TOKEN_URL11 = "https://oauth2.googleapis.com/token";
|
|
38091
|
+
var API10 = "https://docs.googleapis.com/v1";
|
|
38440
38092
|
var DRIVE_API = "https://www.googleapis.com/drive/v3";
|
|
38441
38093
|
var EXPORT_MIME = {
|
|
38442
38094
|
pdf: "application/pdf",
|
|
@@ -38460,8 +38112,8 @@ function googleDocs(opts) {
|
|
|
38460
38112
|
description: "Read and draft into the user's Google Docs. Fetch a document's plaintext body, create a new doc from a title + initial body, and append text with optional revision-id CAS guarding concurrent edits.",
|
|
38461
38113
|
auth: {
|
|
38462
38114
|
kind: "oauth2",
|
|
38463
|
-
authorizationUrl:
|
|
38464
|
-
tokenUrl:
|
|
38115
|
+
authorizationUrl: AUTH_URL11,
|
|
38116
|
+
tokenUrl: TOKEN_URL11,
|
|
38465
38117
|
scopes: SCOPES9,
|
|
38466
38118
|
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
38467
38119
|
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
@@ -38575,7 +38227,7 @@ function googleDocs(opts) {
|
|
|
38575
38227
|
throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
|
|
38576
38228
|
}
|
|
38577
38229
|
const tokens = await exchangeAuthorizationCode({
|
|
38578
|
-
tokenUrl:
|
|
38230
|
+
tokenUrl: TOKEN_URL11,
|
|
38579
38231
|
clientId,
|
|
38580
38232
|
clientSecret,
|
|
38581
38233
|
code: input.code,
|
|
@@ -38598,7 +38250,7 @@ function googleDocs(opts) {
|
|
|
38598
38250
|
throw new Error("google-docs.refreshToken: missing refresh token");
|
|
38599
38251
|
}
|
|
38600
38252
|
const refreshed = await refreshAccessToken({
|
|
38601
|
-
tokenUrl:
|
|
38253
|
+
tokenUrl: TOKEN_URL11,
|
|
38602
38254
|
clientId,
|
|
38603
38255
|
clientSecret,
|
|
38604
38256
|
refreshToken: creds.refreshToken
|
|
@@ -38652,7 +38304,7 @@ function findAppendIndex(doc) {
|
|
|
38652
38304
|
}
|
|
38653
38305
|
async function getDocument2(inv, accessToken, timeoutMs) {
|
|
38654
38306
|
const { documentId } = inv.args ?? {};
|
|
38655
|
-
const res = await fetch(`${
|
|
38307
|
+
const res = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}`, {
|
|
38656
38308
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38657
38309
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38658
38310
|
});
|
|
@@ -38686,7 +38338,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38686
38338
|
if (!title || typeof title !== "string") {
|
|
38687
38339
|
throw new Error("google-docs create_document: title is required");
|
|
38688
38340
|
}
|
|
38689
|
-
const createRes = await fetch(`${
|
|
38341
|
+
const createRes = await fetch(`${API10}/documents`, {
|
|
38690
38342
|
method: "POST",
|
|
38691
38343
|
headers: {
|
|
38692
38344
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -38706,7 +38358,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38706
38358
|
let revisionId = created.revisionId;
|
|
38707
38359
|
if (typeof body === "string" && body.length > 0) {
|
|
38708
38360
|
const insertRes = await fetch(
|
|
38709
|
-
`${
|
|
38361
|
+
`${API10}/documents/${encodeURIComponent(created.documentId)}:batchUpdate`,
|
|
38710
38362
|
{
|
|
38711
38363
|
method: "POST",
|
|
38712
38364
|
headers: {
|
|
@@ -38749,7 +38401,7 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38749
38401
|
if (!text) {
|
|
38750
38402
|
throw new Error("google-docs append_text: text is required");
|
|
38751
38403
|
}
|
|
38752
|
-
const docRes = await fetch(`${
|
|
38404
|
+
const docRes = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}?fields=documentId,revisionId,body(content(endIndex))`, {
|
|
38753
38405
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38754
38406
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38755
38407
|
});
|
|
@@ -38779,7 +38431,7 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38779
38431
|
body.writeControl = { requiredRevisionId };
|
|
38780
38432
|
}
|
|
38781
38433
|
const res = await fetch(
|
|
38782
|
-
`${
|
|
38434
|
+
`${API10}/documents/${encodeURIComponent(documentId)}:batchUpdate`,
|
|
38783
38435
|
{
|
|
38784
38436
|
method: "POST",
|
|
38785
38437
|
headers: {
|
|
@@ -38900,7 +38552,7 @@ async function ensureFreshAccessToken9(creds, clientId, clientSecret) {
|
|
|
38900
38552
|
throw new CredentialsExpired("Google Docs access token expired and no refresh token", "");
|
|
38901
38553
|
}
|
|
38902
38554
|
const refreshed = await refreshAccessToken({
|
|
38903
|
-
tokenUrl:
|
|
38555
|
+
tokenUrl: TOKEN_URL11,
|
|
38904
38556
|
clientId,
|
|
38905
38557
|
clientSecret,
|
|
38906
38558
|
refreshToken: creds.refreshToken
|
|
@@ -38918,9 +38570,9 @@ var SCOPES10 = [
|
|
|
38918
38570
|
"https://www.googleapis.com/auth/forms.responses.readonly",
|
|
38919
38571
|
SCOPE_WRITE3
|
|
38920
38572
|
];
|
|
38921
|
-
var
|
|
38922
|
-
var
|
|
38923
|
-
var
|
|
38573
|
+
var AUTH_URL12 = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
38574
|
+
var TOKEN_URL12 = "https://oauth2.googleapis.com/token";
|
|
38575
|
+
var API11 = "https://forms.googleapis.com/v1";
|
|
38924
38576
|
function googleForms(opts) {
|
|
38925
38577
|
const { clientId, clientSecret } = opts;
|
|
38926
38578
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -38931,8 +38583,8 @@ function googleForms(opts) {
|
|
|
38931
38583
|
description: "Read a Google Form's schema and paginate its responses for KB ingest, lead routing, or analytics. Returns answers keyed by questionId with the original item tree available for question\u2192title joins.",
|
|
38932
38584
|
auth: {
|
|
38933
38585
|
kind: "oauth2",
|
|
38934
|
-
authorizationUrl:
|
|
38935
|
-
tokenUrl:
|
|
38586
|
+
authorizationUrl: AUTH_URL12,
|
|
38587
|
+
tokenUrl: TOKEN_URL12,
|
|
38936
38588
|
scopes: SCOPES10,
|
|
38937
38589
|
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
38938
38590
|
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
@@ -39076,7 +38728,7 @@ function googleForms(opts) {
|
|
|
39076
38728
|
throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
|
|
39077
38729
|
}
|
|
39078
38730
|
const tokens = await exchangeAuthorizationCode({
|
|
39079
|
-
tokenUrl:
|
|
38731
|
+
tokenUrl: TOKEN_URL12,
|
|
39080
38732
|
clientId,
|
|
39081
38733
|
clientSecret,
|
|
39082
38734
|
code: input.code,
|
|
@@ -39099,7 +38751,7 @@ function googleForms(opts) {
|
|
|
39099
38751
|
throw new Error("google-forms.refreshToken: missing refresh token");
|
|
39100
38752
|
}
|
|
39101
38753
|
const refreshed = await refreshAccessToken({
|
|
39102
|
-
tokenUrl:
|
|
38754
|
+
tokenUrl: TOKEN_URL12,
|
|
39103
38755
|
clientId,
|
|
39104
38756
|
clientSecret,
|
|
39105
38757
|
refreshToken: creds.refreshToken
|
|
@@ -39145,7 +38797,7 @@ function flattenAnswers(answers) {
|
|
|
39145
38797
|
async function getForm(inv, accessToken, timeoutMs) {
|
|
39146
38798
|
const { formId } = inv.args ?? {};
|
|
39147
38799
|
if (!formId) throw new Error("google-forms get_form: formId is required");
|
|
39148
|
-
const res = await fetch(`${
|
|
38800
|
+
const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}`, {
|
|
39149
38801
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39150
38802
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39151
38803
|
});
|
|
@@ -39180,7 +38832,7 @@ async function listResponses(inv, accessToken, timeoutMs) {
|
|
|
39180
38832
|
if (pageToken) params.set("pageToken", pageToken);
|
|
39181
38833
|
if (filter) params.set("filter", filter);
|
|
39182
38834
|
const qs = params.toString();
|
|
39183
|
-
const url = `${
|
|
38835
|
+
const url = `${API11}/forms/${encodeURIComponent(formId)}/responses${qs ? `?${qs}` : ""}`;
|
|
39184
38836
|
const res = await fetch(url, {
|
|
39185
38837
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39186
38838
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39217,7 +38869,7 @@ async function getResponse(inv, accessToken, timeoutMs) {
|
|
|
39217
38869
|
if (!formId) throw new Error("google-forms get_response: formId is required");
|
|
39218
38870
|
if (!responseId) throw new Error("google-forms get_response: responseId is required");
|
|
39219
38871
|
const res = await fetch(
|
|
39220
|
-
`${
|
|
38872
|
+
`${API11}/forms/${encodeURIComponent(formId)}/responses/${encodeURIComponent(responseId)}`,
|
|
39221
38873
|
{
|
|
39222
38874
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39223
38875
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39251,7 +38903,7 @@ async function createForm(inv, accessToken, timeoutMs) {
|
|
|
39251
38903
|
if (!title) throw new Error("google-forms create_form: title is required");
|
|
39252
38904
|
const info = { title };
|
|
39253
38905
|
if (documentTitle) info.documentTitle = documentTitle;
|
|
39254
|
-
const res = await fetch(`${
|
|
38906
|
+
const res = await fetch(`${API11}/forms`, {
|
|
39255
38907
|
method: "POST",
|
|
39256
38908
|
headers: {
|
|
39257
38909
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39290,7 +38942,7 @@ async function batchUpdate(inv, accessToken, timeoutMs) {
|
|
|
39290
38942
|
const body = { requests };
|
|
39291
38943
|
if (typeof includeFormInResponse === "boolean") body.includeFormInResponse = includeFormInResponse;
|
|
39292
38944
|
if (writeControl) body.writeControl = writeControl;
|
|
39293
|
-
const res = await fetch(`${
|
|
38945
|
+
const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}:batchUpdate`, {
|
|
39294
38946
|
method: "POST",
|
|
39295
38947
|
headers: {
|
|
39296
38948
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39330,7 +38982,7 @@ async function ensureFreshAccessToken10(creds, clientId, clientSecret) {
|
|
|
39330
38982
|
throw new CredentialsExpired("Google Forms access token expired and no refresh token", "");
|
|
39331
38983
|
}
|
|
39332
38984
|
const refreshed = await refreshAccessToken({
|
|
39333
|
-
tokenUrl:
|
|
38985
|
+
tokenUrl: TOKEN_URL12,
|
|
39334
38986
|
clientId,
|
|
39335
38987
|
clientSecret,
|
|
39336
38988
|
refreshToken: creds.refreshToken
|
|
@@ -39351,8 +39003,8 @@ var SCOPES11 = [
|
|
|
39351
39003
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
39352
39004
|
"offline_access"
|
|
39353
39005
|
];
|
|
39354
|
-
var
|
|
39355
|
-
var
|
|
39006
|
+
var AUTH_URL13 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
39007
|
+
var TOKEN_URL13 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
39356
39008
|
var GRAPH = "https://graph.microsoft.com/v1.0";
|
|
39357
39009
|
function microsoftGraph(opts) {
|
|
39358
39010
|
const { clientId, clientSecret } = opts;
|
|
@@ -39363,8 +39015,8 @@ function microsoftGraph(opts) {
|
|
|
39363
39015
|
description: "Query the Microsoft 365 directory \u2014 look up users by email, list organizations, enumerate groups, and resolve group membership. Read-only identity surface shared across the Outlook, Teams, SharePoint, and OneDrive adapters.",
|
|
39364
39016
|
auth: {
|
|
39365
39017
|
kind: "oauth2",
|
|
39366
|
-
authorizationUrl:
|
|
39367
|
-
tokenUrl:
|
|
39018
|
+
authorizationUrl: AUTH_URL13,
|
|
39019
|
+
tokenUrl: TOKEN_URL13,
|
|
39368
39020
|
scopes: SCOPES11,
|
|
39369
39021
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
39370
39022
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -39549,7 +39201,7 @@ function microsoftGraph(opts) {
|
|
|
39549
39201
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
39550
39202
|
}
|
|
39551
39203
|
const tokens = await exchangeAuthorizationCode({
|
|
39552
|
-
tokenUrl:
|
|
39204
|
+
tokenUrl: TOKEN_URL13,
|
|
39553
39205
|
clientId,
|
|
39554
39206
|
clientSecret,
|
|
39555
39207
|
code: input.code,
|
|
@@ -39572,7 +39224,7 @@ function microsoftGraph(opts) {
|
|
|
39572
39224
|
throw new Error("microsoft-graph.refreshToken: missing refresh token");
|
|
39573
39225
|
}
|
|
39574
39226
|
const refreshed = await refreshAccessToken({
|
|
39575
|
-
tokenUrl:
|
|
39227
|
+
tokenUrl: TOKEN_URL13,
|
|
39576
39228
|
clientId,
|
|
39577
39229
|
clientSecret,
|
|
39578
39230
|
refreshToken: creds.refreshToken
|
|
@@ -39614,7 +39266,7 @@ async function ensureFreshAccessToken11(creds, clientId, clientSecret) {
|
|
|
39614
39266
|
throw new CredentialsExpired("Microsoft Graph access token expired and no refresh token", "");
|
|
39615
39267
|
}
|
|
39616
39268
|
const refreshed = await refreshAccessToken({
|
|
39617
|
-
tokenUrl:
|
|
39269
|
+
tokenUrl: TOKEN_URL13,
|
|
39618
39270
|
clientId,
|
|
39619
39271
|
clientSecret,
|
|
39620
39272
|
refreshToken: creds.refreshToken
|
|
@@ -39651,9 +39303,9 @@ var SCOPE_READ2 = "https://graph.microsoft.com/Mail.Read";
|
|
|
39651
39303
|
var SCOPE_SEND2 = "https://graph.microsoft.com/Mail.Send";
|
|
39652
39304
|
var SCOPE_RW = "https://graph.microsoft.com/Mail.ReadWrite";
|
|
39653
39305
|
var SCOPE_OFFLINE = "offline_access";
|
|
39654
|
-
var
|
|
39655
|
-
var
|
|
39656
|
-
var
|
|
39306
|
+
var AUTH_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
39307
|
+
var TOKEN_URL14 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
39308
|
+
var API12 = "https://graph.microsoft.com/v1.0";
|
|
39657
39309
|
function outlookMail(opts) {
|
|
39658
39310
|
const { clientId, clientSecret } = opts;
|
|
39659
39311
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -39665,8 +39317,8 @@ function outlookMail(opts) {
|
|
|
39665
39317
|
description: "Read inbox messages from a Microsoft 365 / Outlook mailbox, fetch a single message with body + attachment manifest, reply on a conversation, and subscribe to a folder for new mail webhooks.",
|
|
39666
39318
|
auth: {
|
|
39667
39319
|
kind: "oauth2",
|
|
39668
|
-
authorizationUrl:
|
|
39669
|
-
tokenUrl:
|
|
39320
|
+
authorizationUrl: AUTH_URL14,
|
|
39321
|
+
tokenUrl: TOKEN_URL14,
|
|
39670
39322
|
scopes,
|
|
39671
39323
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
39672
39324
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -39750,6 +39402,19 @@ function outlookMail(opts) {
|
|
|
39750
39402
|
type: "boolean",
|
|
39751
39403
|
default: false,
|
|
39752
39404
|
description: "When true, set Graph body.contentType=HTML and send body as HTML; otherwise text. Graph does NOT auto-derive a plain alternative \u2014 set html only when the body is HTML."
|
|
39405
|
+
},
|
|
39406
|
+
attachments: {
|
|
39407
|
+
type: "array",
|
|
39408
|
+
description: "Optional file attachments. Each item is { name, contentType?, contentBytes } where contentBytes is base64-encoded file data. Sent as Graph #microsoft.graph.fileAttachment entries.",
|
|
39409
|
+
items: {
|
|
39410
|
+
type: "object",
|
|
39411
|
+
properties: {
|
|
39412
|
+
name: { type: "string" },
|
|
39413
|
+
contentType: { type: "string" },
|
|
39414
|
+
contentBytes: { type: "string", description: "Base64-encoded attachment bytes." }
|
|
39415
|
+
},
|
|
39416
|
+
required: ["name", "contentBytes"]
|
|
39417
|
+
}
|
|
39753
39418
|
}
|
|
39754
39419
|
},
|
|
39755
39420
|
required: ["to", "subject", "body"]
|
|
@@ -39780,6 +39445,19 @@ function outlookMail(opts) {
|
|
|
39780
39445
|
type: "boolean",
|
|
39781
39446
|
default: false,
|
|
39782
39447
|
description: "When true, set Graph body.contentType=HTML; otherwise text."
|
|
39448
|
+
},
|
|
39449
|
+
attachments: {
|
|
39450
|
+
type: "array",
|
|
39451
|
+
description: "Optional file attachments. Each item is { name, contentType?, contentBytes } where contentBytes is base64-encoded file data. Stored as Graph #microsoft.graph.fileAttachment entries on the draft.",
|
|
39452
|
+
items: {
|
|
39453
|
+
type: "object",
|
|
39454
|
+
properties: {
|
|
39455
|
+
name: { type: "string" },
|
|
39456
|
+
contentType: { type: "string" },
|
|
39457
|
+
contentBytes: { type: "string", description: "Base64-encoded attachment bytes." }
|
|
39458
|
+
},
|
|
39459
|
+
required: ["name", "contentBytes"]
|
|
39460
|
+
}
|
|
39783
39461
|
}
|
|
39784
39462
|
},
|
|
39785
39463
|
required: ["to", "subject", "body"]
|
|
@@ -39802,6 +39480,94 @@ function outlookMail(opts) {
|
|
|
39802
39480
|
},
|
|
39803
39481
|
required: ["notificationUrl"]
|
|
39804
39482
|
}
|
|
39483
|
+
},
|
|
39484
|
+
{
|
|
39485
|
+
name: "forward_message",
|
|
39486
|
+
class: "mutation",
|
|
39487
|
+
description: "Forward an existing message to one or more recipients with an optional comment. Graph POST /me/messages/{id}/forward.",
|
|
39488
|
+
cas: "native-idempotency",
|
|
39489
|
+
externalEffect: true,
|
|
39490
|
+
requiredScopes: [SCOPE_SEND2],
|
|
39491
|
+
parameters: {
|
|
39492
|
+
type: "object",
|
|
39493
|
+
properties: {
|
|
39494
|
+
messageId: { type: "string", description: "Graph message id to forward." },
|
|
39495
|
+
to: {
|
|
39496
|
+
oneOf: [
|
|
39497
|
+
{ type: "string" },
|
|
39498
|
+
{ type: "array", items: { type: "string" } }
|
|
39499
|
+
],
|
|
39500
|
+
description: "Recipient address(es). String OR array of strings."
|
|
39501
|
+
},
|
|
39502
|
+
comment: { type: "string", description: "Optional comment prepended to the forwarded body." }
|
|
39503
|
+
},
|
|
39504
|
+
required: ["messageId", "to"]
|
|
39505
|
+
}
|
|
39506
|
+
},
|
|
39507
|
+
{
|
|
39508
|
+
name: "move_message",
|
|
39509
|
+
class: "mutation",
|
|
39510
|
+
description: "Move a message to a destination mail folder by id (or well-known name like inbox/archive). Graph POST /me/messages/{id}/move; returns the relocated message (new id).",
|
|
39511
|
+
cas: "native-idempotency",
|
|
39512
|
+
externalEffect: true,
|
|
39513
|
+
requiredScopes: [SCOPE_RW],
|
|
39514
|
+
parameters: {
|
|
39515
|
+
type: "object",
|
|
39516
|
+
properties: {
|
|
39517
|
+
messageId: { type: "string", description: "Graph message id to move." },
|
|
39518
|
+
destinationId: { type: "string", description: "Destination folder id or well-known name (inbox, archive, deleteditems, ...)." }
|
|
39519
|
+
},
|
|
39520
|
+
required: ["messageId", "destinationId"]
|
|
39521
|
+
}
|
|
39522
|
+
},
|
|
39523
|
+
{
|
|
39524
|
+
name: "set_labels",
|
|
39525
|
+
class: "mutation",
|
|
39526
|
+
description: "Set the full set of Outlook categories (labels) on a message. Graph PATCH /me/messages/{id} replaces the categories array, so supply the complete desired set (the caller computes adds/removes against the current set).",
|
|
39527
|
+
cas: "optimistic-read-verify",
|
|
39528
|
+
externalEffect: false,
|
|
39529
|
+
requiredScopes: [SCOPE_RW],
|
|
39530
|
+
parameters: {
|
|
39531
|
+
type: "object",
|
|
39532
|
+
properties: {
|
|
39533
|
+
messageId: { type: "string", description: "Graph message id to tag." },
|
|
39534
|
+
categories: {
|
|
39535
|
+
type: "array",
|
|
39536
|
+
items: { type: "string" },
|
|
39537
|
+
description: "Full desired category set. Graph replaces (not merges) the categories array."
|
|
39538
|
+
}
|
|
39539
|
+
},
|
|
39540
|
+
required: ["messageId", "categories"]
|
|
39541
|
+
}
|
|
39542
|
+
},
|
|
39543
|
+
{
|
|
39544
|
+
name: "send_draft",
|
|
39545
|
+
class: "mutation",
|
|
39546
|
+
description: "Send a previously created draft message by id. Graph POST /me/messages/{id}/send. Pairs with create_draft.",
|
|
39547
|
+
cas: "native-idempotency",
|
|
39548
|
+
externalEffect: true,
|
|
39549
|
+
requiredScopes: [SCOPE_SEND2],
|
|
39550
|
+
parameters: {
|
|
39551
|
+
type: "object",
|
|
39552
|
+
properties: {
|
|
39553
|
+
messageId: { type: "string", description: "Graph draft message id to send." }
|
|
39554
|
+
},
|
|
39555
|
+
required: ["messageId"]
|
|
39556
|
+
}
|
|
39557
|
+
},
|
|
39558
|
+
{
|
|
39559
|
+
name: "download_attachment",
|
|
39560
|
+
class: "read",
|
|
39561
|
+
description: "Read an attachment record for a message including base64 contentBytes for file attachments. Graph GET /me/messages/{messageId}/attachments/{attachmentId}. Fills the attachment-bytes gap that read_message defers.",
|
|
39562
|
+
requiredScopes: [SCOPE_READ2],
|
|
39563
|
+
parameters: {
|
|
39564
|
+
type: "object",
|
|
39565
|
+
properties: {
|
|
39566
|
+
messageId: { type: "string", description: "Graph message id owning the attachment." },
|
|
39567
|
+
attachmentId: { type: "string", description: "Graph attachment id (from read_message attachments[].id)." }
|
|
39568
|
+
},
|
|
39569
|
+
required: ["messageId", "attachmentId"]
|
|
39570
|
+
}
|
|
39805
39571
|
}
|
|
39806
39572
|
]
|
|
39807
39573
|
},
|
|
@@ -39809,6 +39575,7 @@ function outlookMail(opts) {
|
|
|
39809
39575
|
const accessToken = await ensureFreshAccessToken12(inv.source.credentials, clientId, clientSecret, inv.onCredentialsRotated);
|
|
39810
39576
|
if (inv.capabilityName === "list_messages") return listMessages2(inv, accessToken, timeoutMs);
|
|
39811
39577
|
if (inv.capabilityName === "read_message") return readMessage2(inv, accessToken, timeoutMs);
|
|
39578
|
+
if (inv.capabilityName === "download_attachment") return downloadAttachment(inv, accessToken, timeoutMs);
|
|
39812
39579
|
throw new Error(`outlook-mail: unknown read capability ${inv.capabilityName}`);
|
|
39813
39580
|
},
|
|
39814
39581
|
async executeMutation(inv) {
|
|
@@ -39817,6 +39584,10 @@ function outlookMail(opts) {
|
|
|
39817
39584
|
if (inv.capabilityName === "send_message") return sendMessage(inv, accessToken, timeoutMs);
|
|
39818
39585
|
if (inv.capabilityName === "create_draft") return createDraft(inv, accessToken, timeoutMs);
|
|
39819
39586
|
if (inv.capabilityName === "subscribe_folder") return subscribeFolder(inv, accessToken, timeoutMs);
|
|
39587
|
+
if (inv.capabilityName === "forward_message") return forwardMessage(inv, accessToken, timeoutMs);
|
|
39588
|
+
if (inv.capabilityName === "move_message") return moveMessage(inv, accessToken, timeoutMs);
|
|
39589
|
+
if (inv.capabilityName === "set_labels") return setLabels(inv, accessToken, timeoutMs);
|
|
39590
|
+
if (inv.capabilityName === "send_draft") return sendDraft(inv, accessToken, timeoutMs);
|
|
39820
39591
|
throw new Error(`outlook-mail: unknown mutation capability ${inv.capabilityName}`);
|
|
39821
39592
|
},
|
|
39822
39593
|
async exchangeOAuth(input) {
|
|
@@ -39824,7 +39595,7 @@ function outlookMail(opts) {
|
|
|
39824
39595
|
throw new Error("Outlook Mail OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
39825
39596
|
}
|
|
39826
39597
|
const tokens = await exchangeAuthorizationCode({
|
|
39827
|
-
tokenUrl:
|
|
39598
|
+
tokenUrl: TOKEN_URL14,
|
|
39828
39599
|
clientId,
|
|
39829
39600
|
clientSecret,
|
|
39830
39601
|
code: input.code,
|
|
@@ -39847,7 +39618,7 @@ function outlookMail(opts) {
|
|
|
39847
39618
|
throw new Error("outlook-mail.refreshToken: missing refresh token");
|
|
39848
39619
|
}
|
|
39849
39620
|
const refreshed = await refreshAccessToken({
|
|
39850
|
-
tokenUrl:
|
|
39621
|
+
tokenUrl: TOKEN_URL14,
|
|
39851
39622
|
clientId,
|
|
39852
39623
|
clientSecret,
|
|
39853
39624
|
refreshToken: creds.refreshToken
|
|
@@ -39862,7 +39633,7 @@ function outlookMail(opts) {
|
|
|
39862
39633
|
async test(source) {
|
|
39863
39634
|
try {
|
|
39864
39635
|
const accessToken = await ensureFreshAccessToken12(source.credentials, clientId, clientSecret);
|
|
39865
|
-
const res = await fetch(`${
|
|
39636
|
+
const res = await fetch(`${API12}/me?$select=id,userPrincipalName`, {
|
|
39866
39637
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39867
39638
|
signal: AbortSignal.timeout(8e3)
|
|
39868
39639
|
});
|
|
@@ -39890,7 +39661,7 @@ async function listMessages2(inv, accessToken, timeoutMs) {
|
|
|
39890
39661
|
if (args.skipToken) params.set("$skiptoken", args.skipToken);
|
|
39891
39662
|
const headers = { authorization: `Bearer ${accessToken}` };
|
|
39892
39663
|
if (args.query) headers["ConsistencyLevel"] = "eventual";
|
|
39893
|
-
const res = await fetch(`${
|
|
39664
|
+
const res = await fetch(`${API12}/me/mailFolders/${folder}/messages?${params.toString()}`, {
|
|
39894
39665
|
headers,
|
|
39895
39666
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39896
39667
|
});
|
|
@@ -39924,7 +39695,7 @@ function toMessageSummary2(m) {
|
|
|
39924
39695
|
}
|
|
39925
39696
|
async function readMessage2(inv, accessToken, timeoutMs) {
|
|
39926
39697
|
const { id } = inv.args;
|
|
39927
|
-
const url = `${
|
|
39698
|
+
const url = `${API12}/me/messages/${encodeURIComponent(id)}?$expand=attachments($select=id,name,contentType,size,isInline)`;
|
|
39928
39699
|
const res = await fetch(url, {
|
|
39929
39700
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39930
39701
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39967,7 +39738,7 @@ async function readMessage2(inv, accessToken, timeoutMs) {
|
|
|
39967
39738
|
async function sendReply2(inv, accessToken, timeoutMs) {
|
|
39968
39739
|
const { messageId, body, bodyType, replyAll, comment } = inv.args;
|
|
39969
39740
|
const action = replyAll ? "createReplyAll" : "createReply";
|
|
39970
|
-
const draftRes = await fetch(`${
|
|
39741
|
+
const draftRes = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/${action}`, {
|
|
39971
39742
|
method: "POST",
|
|
39972
39743
|
headers: {
|
|
39973
39744
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39990,7 +39761,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
|
|
|
39990
39761
|
{ name: "X-Tangle-Idempotency-Key", value: inv.idempotencyKey }
|
|
39991
39762
|
]
|
|
39992
39763
|
};
|
|
39993
|
-
const patchRes = await fetch(`${
|
|
39764
|
+
const patchRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}`, {
|
|
39994
39765
|
method: "PATCH",
|
|
39995
39766
|
headers: {
|
|
39996
39767
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40006,7 +39777,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
|
|
|
40006
39777
|
const text = await patchRes.text().catch(() => "");
|
|
40007
39778
|
throw new Error(`outlook-mail send_reply patch ${patchRes.status}: ${text.slice(0, 200)}`);
|
|
40008
39779
|
}
|
|
40009
|
-
const sendRes = await fetch(`${
|
|
39780
|
+
const sendRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}/send`, {
|
|
40010
39781
|
method: "POST",
|
|
40011
39782
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40012
39783
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40053,12 +39824,25 @@ function buildMessagePayload(args, idempotencyKey, cap) {
|
|
|
40053
39824
|
if (args.bcc?.length) {
|
|
40054
39825
|
payload.bccRecipients = args.bcc.map((address) => ({ emailAddress: { address } }));
|
|
40055
39826
|
}
|
|
39827
|
+
if (args.attachments?.length) {
|
|
39828
|
+
payload.attachments = args.attachments.map((a) => {
|
|
39829
|
+
if (!a?.name) throw new Error(`outlook-mail ${cap}: attachment \`name\` is required`);
|
|
39830
|
+
if (!a?.contentBytes) throw new Error(`outlook-mail ${cap}: attachment \`contentBytes\` (base64) is required`);
|
|
39831
|
+
const att = {
|
|
39832
|
+
"@odata.type": "#microsoft.graph.fileAttachment",
|
|
39833
|
+
name: a.name,
|
|
39834
|
+
contentBytes: a.contentBytes
|
|
39835
|
+
};
|
|
39836
|
+
if (a.contentType) att.contentType = a.contentType;
|
|
39837
|
+
return att;
|
|
39838
|
+
});
|
|
39839
|
+
}
|
|
40056
39840
|
return payload;
|
|
40057
39841
|
}
|
|
40058
39842
|
async function sendMessage(inv, accessToken, timeoutMs) {
|
|
40059
39843
|
const args = inv.args ?? {};
|
|
40060
39844
|
const message = buildMessagePayload(args, inv.idempotencyKey, "send_message");
|
|
40061
|
-
const res = await fetch(`${
|
|
39845
|
+
const res = await fetch(`${API12}/me/sendMail`, {
|
|
40062
39846
|
method: "POST",
|
|
40063
39847
|
headers: {
|
|
40064
39848
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40088,7 +39872,7 @@ async function sendMessage(inv, accessToken, timeoutMs) {
|
|
|
40088
39872
|
async function createDraft(inv, accessToken, timeoutMs) {
|
|
40089
39873
|
const args = inv.args ?? {};
|
|
40090
39874
|
const message = buildMessagePayload(args, inv.idempotencyKey, "create_draft");
|
|
40091
|
-
const res = await fetch(`${
|
|
39875
|
+
const res = await fetch(`${API12}/me/messages`, {
|
|
40092
39876
|
method: "POST",
|
|
40093
39877
|
headers: {
|
|
40094
39878
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40129,7 +39913,7 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
|
|
|
40129
39913
|
expirationDateTime,
|
|
40130
39914
|
clientState: clientState ?? inv.idempotencyKey
|
|
40131
39915
|
};
|
|
40132
|
-
const res = await fetch(`${
|
|
39916
|
+
const res = await fetch(`${API12}/subscriptions`, {
|
|
40133
39917
|
method: "POST",
|
|
40134
39918
|
headers: {
|
|
40135
39919
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40158,6 +39942,162 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
|
|
|
40158
39942
|
idempotentReplay: false
|
|
40159
39943
|
};
|
|
40160
39944
|
}
|
|
39945
|
+
async function forwardMessage(inv, accessToken, timeoutMs) {
|
|
39946
|
+
const { messageId, to, comment } = inv.args;
|
|
39947
|
+
if (!messageId) throw new Error("outlook-mail forward_message: `messageId` is required");
|
|
39948
|
+
if (!to || Array.isArray(to) && to.length === 0) {
|
|
39949
|
+
throw new Error("outlook-mail forward_message: `to` is required");
|
|
39950
|
+
}
|
|
39951
|
+
const toList = Array.isArray(to) ? to : [to];
|
|
39952
|
+
const toRecipients = toList.map((address) => ({ emailAddress: { address } }));
|
|
39953
|
+
const fwdBody = {
|
|
39954
|
+
toRecipients
|
|
39955
|
+
};
|
|
39956
|
+
if (comment !== void 0) fwdBody.comment = comment;
|
|
39957
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/forward`, {
|
|
39958
|
+
method: "POST",
|
|
39959
|
+
headers: {
|
|
39960
|
+
authorization: `Bearer ${accessToken}`,
|
|
39961
|
+
"content-type": "application/json"
|
|
39962
|
+
},
|
|
39963
|
+
body: JSON.stringify(fwdBody),
|
|
39964
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
39965
|
+
});
|
|
39966
|
+
if (res.status === 401 || res.status === 403) {
|
|
39967
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
39968
|
+
}
|
|
39969
|
+
if (!res.ok && res.status !== 202) {
|
|
39970
|
+
const text = await res.text().catch(() => "");
|
|
39971
|
+
throw new Error(`outlook-mail forward_message ${res.status}: ${text.slice(0, 200)}`);
|
|
39972
|
+
}
|
|
39973
|
+
return {
|
|
39974
|
+
status: "committed",
|
|
39975
|
+
data: { forwarded: true, messageId, to: toList },
|
|
39976
|
+
committedAt: Date.now(),
|
|
39977
|
+
idempotentReplay: false
|
|
39978
|
+
};
|
|
39979
|
+
}
|
|
39980
|
+
async function moveMessage(inv, accessToken, timeoutMs) {
|
|
39981
|
+
const { messageId, destinationId } = inv.args;
|
|
39982
|
+
if (!messageId) throw new Error("outlook-mail move_message: `messageId` is required");
|
|
39983
|
+
if (!destinationId) throw new Error("outlook-mail move_message: `destinationId` is required");
|
|
39984
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/move`, {
|
|
39985
|
+
method: "POST",
|
|
39986
|
+
headers: {
|
|
39987
|
+
authorization: `Bearer ${accessToken}`,
|
|
39988
|
+
"content-type": "application/json"
|
|
39989
|
+
},
|
|
39990
|
+
body: JSON.stringify({ destinationId }),
|
|
39991
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
39992
|
+
});
|
|
39993
|
+
if (res.status === 401 || res.status === 403) {
|
|
39994
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
39995
|
+
}
|
|
39996
|
+
if (!res.ok) {
|
|
39997
|
+
const text = await res.text().catch(() => "");
|
|
39998
|
+
throw new Error(`outlook-mail move_message ${res.status}: ${text.slice(0, 200)}`);
|
|
39999
|
+
}
|
|
40000
|
+
const json = await res.json().catch(() => ({}));
|
|
40001
|
+
return {
|
|
40002
|
+
status: "committed",
|
|
40003
|
+
data: {
|
|
40004
|
+
moved: true,
|
|
40005
|
+
messageId: json.id ?? messageId,
|
|
40006
|
+
parentFolderId: json.parentFolderId ?? destinationId,
|
|
40007
|
+
destinationId
|
|
40008
|
+
},
|
|
40009
|
+
committedAt: Date.now(),
|
|
40010
|
+
idempotentReplay: false
|
|
40011
|
+
};
|
|
40012
|
+
}
|
|
40013
|
+
async function setLabels(inv, accessToken, timeoutMs) {
|
|
40014
|
+
const { messageId, categories } = inv.args;
|
|
40015
|
+
if (!messageId) throw new Error("outlook-mail set_labels: `messageId` is required");
|
|
40016
|
+
if (!Array.isArray(categories)) {
|
|
40017
|
+
throw new Error("outlook-mail set_labels: `categories` must be an array (the full desired set)");
|
|
40018
|
+
}
|
|
40019
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}`, {
|
|
40020
|
+
method: "PATCH",
|
|
40021
|
+
headers: {
|
|
40022
|
+
authorization: `Bearer ${accessToken}`,
|
|
40023
|
+
"content-type": "application/json"
|
|
40024
|
+
},
|
|
40025
|
+
body: JSON.stringify({ categories }),
|
|
40026
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40027
|
+
});
|
|
40028
|
+
if (res.status === 401 || res.status === 403) {
|
|
40029
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
40030
|
+
}
|
|
40031
|
+
if (!res.ok) {
|
|
40032
|
+
const text = await res.text().catch(() => "");
|
|
40033
|
+
throw new Error(`outlook-mail set_labels ${res.status}: ${text.slice(0, 200)}`);
|
|
40034
|
+
}
|
|
40035
|
+
const json = await res.json().catch(() => ({}));
|
|
40036
|
+
return {
|
|
40037
|
+
status: "committed",
|
|
40038
|
+
data: {
|
|
40039
|
+
messageId: json.id ?? messageId,
|
|
40040
|
+
categories: json.categories ?? categories
|
|
40041
|
+
},
|
|
40042
|
+
committedAt: Date.now(),
|
|
40043
|
+
idempotentReplay: false
|
|
40044
|
+
};
|
|
40045
|
+
}
|
|
40046
|
+
async function sendDraft(inv, accessToken, timeoutMs) {
|
|
40047
|
+
const { messageId } = inv.args;
|
|
40048
|
+
if (!messageId) throw new Error("outlook-mail send_draft: `messageId` is required");
|
|
40049
|
+
const res = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/send`, {
|
|
40050
|
+
method: "POST",
|
|
40051
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
40052
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40053
|
+
});
|
|
40054
|
+
if (res.status === 401 || res.status === 403) {
|
|
40055
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
40056
|
+
}
|
|
40057
|
+
if (!res.ok && res.status !== 202) {
|
|
40058
|
+
const text = await res.text().catch(() => "");
|
|
40059
|
+
throw new Error(`outlook-mail send_draft ${res.status}: ${text.slice(0, 200)}`);
|
|
40060
|
+
}
|
|
40061
|
+
return {
|
|
40062
|
+
status: "committed",
|
|
40063
|
+
data: { sent: true, messageId },
|
|
40064
|
+
committedAt: Date.now(),
|
|
40065
|
+
idempotentReplay: false
|
|
40066
|
+
};
|
|
40067
|
+
}
|
|
40068
|
+
async function downloadAttachment(inv, accessToken, timeoutMs) {
|
|
40069
|
+
const { messageId, attachmentId } = inv.args;
|
|
40070
|
+
const url = `${API12}/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`;
|
|
40071
|
+
const res = await fetch(url, {
|
|
40072
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
40073
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
40074
|
+
});
|
|
40075
|
+
if (res.status === 401 || res.status === 403) {
|
|
40076
|
+
throw new CredentialsExpired(`Outlook Mail rejected token (${res.status})`, inv.source.id);
|
|
40077
|
+
}
|
|
40078
|
+
if (res.status === 404) {
|
|
40079
|
+
throw new Error(`outlook-mail download_attachment: attachment ${attachmentId} on message ${messageId} not found`);
|
|
40080
|
+
}
|
|
40081
|
+
if (!res.ok) {
|
|
40082
|
+
const text = await res.text().catch(() => "");
|
|
40083
|
+
throw new Error(`outlook-mail download_attachment ${res.status}: ${text.slice(0, 200)}`);
|
|
40084
|
+
}
|
|
40085
|
+
const a = await res.json();
|
|
40086
|
+
return {
|
|
40087
|
+
data: {
|
|
40088
|
+
id: a.id ?? attachmentId,
|
|
40089
|
+
name: a.name ?? "",
|
|
40090
|
+
contentType: a.contentType ?? "application/octet-stream",
|
|
40091
|
+
size: a.size ?? 0,
|
|
40092
|
+
isInline: a.isInline ?? false,
|
|
40093
|
+
attachmentType: a["@odata.type"],
|
|
40094
|
+
// Base64 bytes for file attachments; null for item/reference attachments
|
|
40095
|
+
// which carry no inline contentBytes.
|
|
40096
|
+
contentBytes: a.contentBytes ?? null
|
|
40097
|
+
},
|
|
40098
|
+
fetchedAt: Date.now()
|
|
40099
|
+
};
|
|
40100
|
+
}
|
|
40161
40101
|
async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredentialsRotated) {
|
|
40162
40102
|
if (creds.kind !== "oauth2") {
|
|
40163
40103
|
throw new Error("outlook-mail: expected oauth2 credentials");
|
|
@@ -40169,7 +40109,7 @@ async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredent
|
|
|
40169
40109
|
throw new CredentialsExpired("Outlook Mail access token expired and no refresh token", "");
|
|
40170
40110
|
}
|
|
40171
40111
|
const refreshed = await refreshAccessToken({
|
|
40172
|
-
tokenUrl:
|
|
40112
|
+
tokenUrl: TOKEN_URL14,
|
|
40173
40113
|
clientId,
|
|
40174
40114
|
clientSecret,
|
|
40175
40115
|
refreshToken: creds.refreshToken
|
|
@@ -40197,8 +40137,8 @@ var SCOPES12 = [
|
|
|
40197
40137
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
40198
40138
|
"offline_access"
|
|
40199
40139
|
];
|
|
40200
|
-
var
|
|
40201
|
-
var
|
|
40140
|
+
var AUTH_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
40141
|
+
var TOKEN_URL15 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
40202
40142
|
var GRAPH2 = "https://graph.microsoft.com/v1.0";
|
|
40203
40143
|
function microsoftTeams(opts) {
|
|
40204
40144
|
const { clientId, clientSecret } = opts;
|
|
@@ -40209,8 +40149,8 @@ function microsoftTeams(opts) {
|
|
|
40209
40149
|
description: "Post messages from the agent into Microsoft Teams channels and 1:1/group chats, list teams and channels, and look up users by email. Advisory surface \u2014 Teams posts are informational, not transactional.",
|
|
40210
40150
|
auth: {
|
|
40211
40151
|
kind: "oauth2",
|
|
40212
|
-
authorizationUrl:
|
|
40213
|
-
tokenUrl:
|
|
40152
|
+
authorizationUrl: AUTH_URL15,
|
|
40153
|
+
tokenUrl: TOKEN_URL15,
|
|
40214
40154
|
scopes: SCOPES12,
|
|
40215
40155
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
40216
40156
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -40396,7 +40336,7 @@ function microsoftTeams(opts) {
|
|
|
40396
40336
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
40397
40337
|
}
|
|
40398
40338
|
const tokens = await exchangeAuthorizationCode({
|
|
40399
|
-
tokenUrl:
|
|
40339
|
+
tokenUrl: TOKEN_URL15,
|
|
40400
40340
|
clientId,
|
|
40401
40341
|
clientSecret,
|
|
40402
40342
|
code: input.code,
|
|
@@ -40419,7 +40359,7 @@ function microsoftTeams(opts) {
|
|
|
40419
40359
|
throw new Error("microsoft-teams.refreshToken: missing refresh token");
|
|
40420
40360
|
}
|
|
40421
40361
|
const refreshed = await refreshAccessToken({
|
|
40422
|
-
tokenUrl:
|
|
40362
|
+
tokenUrl: TOKEN_URL15,
|
|
40423
40363
|
clientId,
|
|
40424
40364
|
clientSecret,
|
|
40425
40365
|
refreshToken: creds.refreshToken
|
|
@@ -40461,7 +40401,7 @@ async function ensureFreshAccessToken13(creds, clientId, clientSecret) {
|
|
|
40461
40401
|
throw new CredentialsExpired("Microsoft Teams access token expired and no refresh token", "");
|
|
40462
40402
|
}
|
|
40463
40403
|
const refreshed = await refreshAccessToken({
|
|
40464
|
-
tokenUrl:
|
|
40404
|
+
tokenUrl: TOKEN_URL15,
|
|
40465
40405
|
clientId,
|
|
40466
40406
|
clientSecret,
|
|
40467
40407
|
refreshToken: creds.refreshToken
|
|
@@ -40513,9 +40453,9 @@ function escapeOData2(value) {
|
|
|
40513
40453
|
var SCOPE_READ3 = "https://graph.microsoft.com/Files.Read";
|
|
40514
40454
|
var SCOPE_WRITE4 = "https://graph.microsoft.com/Files.ReadWrite";
|
|
40515
40455
|
var SCOPE_OFFLINE2 = "offline_access";
|
|
40516
|
-
var
|
|
40517
|
-
var
|
|
40518
|
-
var
|
|
40456
|
+
var AUTH_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
40457
|
+
var TOKEN_URL16 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
40458
|
+
var API13 = "https://graph.microsoft.com/v1.0";
|
|
40519
40459
|
function oneDrive(opts) {
|
|
40520
40460
|
const { clientId, clientSecret } = opts;
|
|
40521
40461
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -40527,8 +40467,8 @@ function oneDrive(opts) {
|
|
|
40527
40467
|
description: "Read and watch files in the user's OneDrive. List a folder, fetch a document's contents (Word/Excel/PowerPoint/PDF/images), and subscribe to folder change notifications via Graph subscriptions.",
|
|
40528
40468
|
auth: {
|
|
40529
40469
|
kind: "oauth2",
|
|
40530
|
-
authorizationUrl:
|
|
40531
|
-
tokenUrl:
|
|
40470
|
+
authorizationUrl: AUTH_URL16,
|
|
40471
|
+
tokenUrl: TOKEN_URL16,
|
|
40532
40472
|
scopes,
|
|
40533
40473
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
40534
40474
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -40705,7 +40645,7 @@ function oneDrive(opts) {
|
|
|
40705
40645
|
throw new Error("OneDrive OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
40706
40646
|
}
|
|
40707
40647
|
const tokens = await exchangeAuthorizationCode({
|
|
40708
|
-
tokenUrl:
|
|
40648
|
+
tokenUrl: TOKEN_URL16,
|
|
40709
40649
|
clientId,
|
|
40710
40650
|
clientSecret,
|
|
40711
40651
|
code: input.code,
|
|
@@ -40728,7 +40668,7 @@ function oneDrive(opts) {
|
|
|
40728
40668
|
throw new Error("onedrive.refreshToken: missing refresh token");
|
|
40729
40669
|
}
|
|
40730
40670
|
const refreshed = await refreshAccessToken({
|
|
40731
|
-
tokenUrl:
|
|
40671
|
+
tokenUrl: TOKEN_URL16,
|
|
40732
40672
|
clientId,
|
|
40733
40673
|
clientSecret,
|
|
40734
40674
|
refreshToken: creds.refreshToken
|
|
@@ -40743,7 +40683,7 @@ function oneDrive(opts) {
|
|
|
40743
40683
|
async test(source) {
|
|
40744
40684
|
try {
|
|
40745
40685
|
const accessToken = await ensureFreshAccessToken14(source.credentials, clientId, clientSecret);
|
|
40746
|
-
const res = await fetch(`${
|
|
40686
|
+
const res = await fetch(`${API13}/me/drive?$select=id`, {
|
|
40747
40687
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40748
40688
|
signal: AbortSignal.timeout(8e3)
|
|
40749
40689
|
});
|
|
@@ -40772,7 +40712,7 @@ async function listFiles2(inv, accessToken, timeoutMs) {
|
|
|
40772
40712
|
if (args.query) headers["ConsistencyLevel"] = "eventual";
|
|
40773
40713
|
const path = args.folderId ? `/me/drive/items/${encodeURIComponent(args.folderId)}/children` : "/me/drive/root/children";
|
|
40774
40714
|
const useSearchEndpoint = !!args.query && !args.folderId;
|
|
40775
|
-
const url = useSearchEndpoint ? `${
|
|
40715
|
+
const url = useSearchEndpoint ? `${API13}/me/drive/root/search(q=${encodeURIComponent(`'${args.query.replace(/'/g, "''")}'`)})?${stripSearch(params).toString()}` : `${API13}${path}?${params.toString()}`;
|
|
40776
40716
|
const res = await fetch(url, {
|
|
40777
40717
|
headers,
|
|
40778
40718
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40802,7 +40742,7 @@ function stripSearch(params) {
|
|
|
40802
40742
|
async function readFile2(inv, accessToken, timeoutMs) {
|
|
40803
40743
|
const { fileId } = inv.args ?? {};
|
|
40804
40744
|
if (!fileId) throw new Error("onedrive read_file: fileId is required");
|
|
40805
|
-
const metaUrl = `${
|
|
40745
|
+
const metaUrl = `${API13}/me/drive/items/${encodeURIComponent(fileId)}?$select=id,name,eTag,lastModifiedDateTime,size,file,folder`;
|
|
40806
40746
|
const metaRes = await fetch(metaUrl, {
|
|
40807
40747
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40808
40748
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40823,7 +40763,7 @@ async function readFile2(inv, accessToken, timeoutMs) {
|
|
|
40823
40763
|
}
|
|
40824
40764
|
const mimeType = meta.file?.mimeType ?? "application/octet-stream";
|
|
40825
40765
|
const fetchedAt = Date.now();
|
|
40826
|
-
const contentRes = await fetch(`${
|
|
40766
|
+
const contentRes = await fetch(`${API13}/me/drive/items/${encodeURIComponent(fileId)}/content`, {
|
|
40827
40767
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40828
40768
|
signal: AbortSignal.timeout(timeoutMs)
|
|
40829
40769
|
});
|
|
@@ -40876,7 +40816,7 @@ async function watchFolder2(inv, accessToken, timeoutMs) {
|
|
|
40876
40816
|
expirationDateTime,
|
|
40877
40817
|
clientState: clientState ?? inv.idempotencyKey
|
|
40878
40818
|
};
|
|
40879
|
-
const res = await fetch(`${
|
|
40819
|
+
const res = await fetch(`${API13}/subscriptions`, {
|
|
40880
40820
|
method: "POST",
|
|
40881
40821
|
headers: {
|
|
40882
40822
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40916,7 +40856,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
|
|
|
40916
40856
|
}
|
|
40917
40857
|
const body = encoding === "base64" ? Buffer.from(fileContent, "base64") : Buffer.from(fileContent, "utf-8");
|
|
40918
40858
|
const parentSegment = folderId === "root" ? "/me/drive/root" : `/me/drive/items/${encodeURIComponent(folderId)}`;
|
|
40919
|
-
const url = `${
|
|
40859
|
+
const url = `${API13}${parentSegment}:/${encodeURIComponent(fileName)}:/content`;
|
|
40920
40860
|
const res = await fetch(url, {
|
|
40921
40861
|
method: "PUT",
|
|
40922
40862
|
headers: {
|
|
@@ -40952,7 +40892,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
|
|
|
40952
40892
|
async function deleteItem(inv, accessToken, timeoutMs) {
|
|
40953
40893
|
const { itemId } = inv.args ?? {};
|
|
40954
40894
|
if (!itemId) throw new Error("onedrive files.delete: itemId is required");
|
|
40955
|
-
const res = await fetch(`${
|
|
40895
|
+
const res = await fetch(`${API13}${itemPath(itemId)}`, {
|
|
40956
40896
|
method: "DELETE",
|
|
40957
40897
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40958
40898
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40990,7 +40930,7 @@ async function moveItem(inv, accessToken, timeoutMs) {
|
|
|
40990
40930
|
body.parentReference = newParentId === "root" ? { path: "/drive/root" } : { id: newParentId };
|
|
40991
40931
|
}
|
|
40992
40932
|
if (newName) body.name = newName;
|
|
40993
|
-
const res = await fetch(`${
|
|
40933
|
+
const res = await fetch(`${API13}${itemPath(itemId)}`, {
|
|
40994
40934
|
method: "PATCH",
|
|
40995
40935
|
headers: {
|
|
40996
40936
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41030,7 +40970,7 @@ async function shareItem(inv, accessToken, timeoutMs) {
|
|
|
41030
40970
|
};
|
|
41031
40971
|
if (password) body.password = password;
|
|
41032
40972
|
if (expirationDateTime) body.expirationDateTime = expirationDateTime;
|
|
41033
|
-
const res = await fetch(`${
|
|
40973
|
+
const res = await fetch(`${API13}${itemPath(itemId)}/createLink`, {
|
|
41034
40974
|
method: "POST",
|
|
41035
40975
|
headers: {
|
|
41036
40976
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41069,7 +41009,7 @@ async function createFolder2(inv, accessToken, timeoutMs) {
|
|
|
41069
41009
|
folder: {},
|
|
41070
41010
|
"@microsoft.graph.conflictBehavior": conflictBehavior ?? "fail"
|
|
41071
41011
|
};
|
|
41072
|
-
const res = await fetch(`${
|
|
41012
|
+
const res = await fetch(`${API13}${parentSegment}`, {
|
|
41073
41013
|
method: "POST",
|
|
41074
41014
|
headers: {
|
|
41075
41015
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41111,7 +41051,7 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
|
|
|
41111
41051
|
throw new CredentialsExpired("OneDrive access token expired and no refresh token", "");
|
|
41112
41052
|
}
|
|
41113
41053
|
const refreshed = await refreshAccessToken({
|
|
41114
|
-
tokenUrl:
|
|
41054
|
+
tokenUrl: TOKEN_URL16,
|
|
41115
41055
|
clientId,
|
|
41116
41056
|
clientSecret,
|
|
41117
41057
|
refreshToken: creds.refreshToken
|
|
@@ -41130,13 +41070,13 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
|
|
|
41130
41070
|
|
|
41131
41071
|
// src/connectors/adapters/sharepoint.ts
|
|
41132
41072
|
var SCOPES13 = [
|
|
41133
|
-
"https://graph.microsoft.com/Sites.
|
|
41073
|
+
"https://graph.microsoft.com/Sites.ReadWrite.All",
|
|
41134
41074
|
"https://graph.microsoft.com/Files.ReadWrite.All",
|
|
41135
41075
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
41136
41076
|
"offline_access"
|
|
41137
41077
|
];
|
|
41138
|
-
var
|
|
41139
|
-
var
|
|
41078
|
+
var AUTH_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
|
|
41079
|
+
var TOKEN_URL17 = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
|
41140
41080
|
var GRAPH3 = "https://graph.microsoft.com/v1.0";
|
|
41141
41081
|
var MAX_INLINE_BYTES = 4 * 1024 * 1024;
|
|
41142
41082
|
function sharepoint(opts) {
|
|
@@ -41148,8 +41088,8 @@ function sharepoint(opts) {
|
|
|
41148
41088
|
description: "Let your agent discover SharePoint sites, list/search their document libraries, read small file contents, upload files, and create folders. Etag-CAS available on every DriveItem for follow-up patch/delete flows.",
|
|
41149
41089
|
auth: {
|
|
41150
41090
|
kind: "oauth2",
|
|
41151
|
-
authorizationUrl:
|
|
41152
|
-
tokenUrl:
|
|
41091
|
+
authorizationUrl: AUTH_URL17,
|
|
41092
|
+
tokenUrl: TOKEN_URL17,
|
|
41153
41093
|
scopes: SCOPES13,
|
|
41154
41094
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
41155
41095
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -41352,6 +41292,136 @@ function sharepoint(opts) {
|
|
|
41352
41292
|
},
|
|
41353
41293
|
required: ["siteId", "listId", "fields"]
|
|
41354
41294
|
}
|
|
41295
|
+
},
|
|
41296
|
+
{
|
|
41297
|
+
name: "get_site_info",
|
|
41298
|
+
class: "read",
|
|
41299
|
+
description: "Read the metadata for a SharePoint site by site id (id, name, displayName, webUrl, description).",
|
|
41300
|
+
parameters: {
|
|
41301
|
+
type: "object",
|
|
41302
|
+
properties: {
|
|
41303
|
+
siteId: { type: "string", description: 'Graph site id (composite "host,site-id,web-id").' }
|
|
41304
|
+
},
|
|
41305
|
+
required: ["siteId"]
|
|
41306
|
+
}
|
|
41307
|
+
},
|
|
41308
|
+
{
|
|
41309
|
+
name: "lists.items.find",
|
|
41310
|
+
class: "read",
|
|
41311
|
+
description: "List items in a SharePoint list, optionally filtered with $filter and shaped with $expand (e.g. fields($select=...)).",
|
|
41312
|
+
parameters: {
|
|
41313
|
+
type: "object",
|
|
41314
|
+
properties: {
|
|
41315
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41316
|
+
listId: { type: "string", description: "SharePoint list id (or list display name resolved by the caller)." },
|
|
41317
|
+
filter: { type: "string", description: "Optional OData $filter expression." },
|
|
41318
|
+
expand: { type: "string", description: "Optional OData $expand, e.g. fields($select=Title,Status)." },
|
|
41319
|
+
top: { type: "integer", minimum: 1, maximum: 200, default: 50 }
|
|
41320
|
+
},
|
|
41321
|
+
required: ["siteId", "listId"]
|
|
41322
|
+
}
|
|
41323
|
+
},
|
|
41324
|
+
{
|
|
41325
|
+
name: "copy_item",
|
|
41326
|
+
class: "mutation",
|
|
41327
|
+
description: "Copy a file or folder DriveItem. Graph copy is asynchronous \u2014 it returns 202 Accepted with a Location monitor URL rather than the new DriveItem. Supply either a cross-drive parentReference (driveId + id) or a same-site target parent id via targetParentId; optionally rename via name.",
|
|
41328
|
+
cas: "native-idempotency",
|
|
41329
|
+
externalEffect: true,
|
|
41330
|
+
parameters: {
|
|
41331
|
+
type: "object",
|
|
41332
|
+
properties: {
|
|
41333
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41334
|
+
itemId: { type: "string", description: "DriveItem id of the file or folder to copy." },
|
|
41335
|
+
parentReference: {
|
|
41336
|
+
type: "object",
|
|
41337
|
+
description: "Cross-drive destination reference (driveId + id). Provide this OR targetParentId.",
|
|
41338
|
+
additionalProperties: true
|
|
41339
|
+
},
|
|
41340
|
+
targetParentId: {
|
|
41341
|
+
type: "string",
|
|
41342
|
+
description: "Same-site destination parent folder DriveItem id. Provide this OR parentReference."
|
|
41343
|
+
},
|
|
41344
|
+
name: { type: "string", description: "Optional new name for the copied item." }
|
|
41345
|
+
},
|
|
41346
|
+
required: ["siteId", "itemId"]
|
|
41347
|
+
}
|
|
41348
|
+
},
|
|
41349
|
+
{
|
|
41350
|
+
name: "lists.create",
|
|
41351
|
+
class: "mutation",
|
|
41352
|
+
description: "Create a SharePoint list on the site. displayName is required; columns and list (e.g. { template }) are optional.",
|
|
41353
|
+
cas: "native-idempotency",
|
|
41354
|
+
externalEffect: true,
|
|
41355
|
+
parameters: {
|
|
41356
|
+
type: "object",
|
|
41357
|
+
properties: {
|
|
41358
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41359
|
+
displayName: { type: "string", description: "Display name of the new list." },
|
|
41360
|
+
columns: {
|
|
41361
|
+
type: "array",
|
|
41362
|
+
description: "Optional column definitions for the list.",
|
|
41363
|
+
items: { type: "object", additionalProperties: true }
|
|
41364
|
+
},
|
|
41365
|
+
list: {
|
|
41366
|
+
type: "object",
|
|
41367
|
+
description: 'Optional list facet, e.g. { template: "genericList" }.',
|
|
41368
|
+
additionalProperties: true
|
|
41369
|
+
}
|
|
41370
|
+
},
|
|
41371
|
+
required: ["siteId", "displayName"]
|
|
41372
|
+
}
|
|
41373
|
+
},
|
|
41374
|
+
{
|
|
41375
|
+
name: "lists.items.update",
|
|
41376
|
+
class: "mutation",
|
|
41377
|
+
description: "Patch the fields on an existing list item. Supports etag-CAS via If-Match \u2014 pass the item's etag to guard against concurrent writes; a mismatch surfaces as ResourceContention.",
|
|
41378
|
+
cas: "etag-if-match",
|
|
41379
|
+
externalEffect: true,
|
|
41380
|
+
parameters: {
|
|
41381
|
+
type: "object",
|
|
41382
|
+
properties: {
|
|
41383
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41384
|
+
listId: { type: "string", description: "SharePoint list id." },
|
|
41385
|
+
itemId: { type: "string", description: "List item id to update." },
|
|
41386
|
+
fields: {
|
|
41387
|
+
type: "object",
|
|
41388
|
+
description: "Map of column internal-name \u2192 new value.",
|
|
41389
|
+
additionalProperties: true
|
|
41390
|
+
}
|
|
41391
|
+
},
|
|
41392
|
+
required: ["siteId", "listId", "itemId", "fields"]
|
|
41393
|
+
}
|
|
41394
|
+
},
|
|
41395
|
+
{
|
|
41396
|
+
name: "lists.items.delete",
|
|
41397
|
+
class: "mutation",
|
|
41398
|
+
description: "Delete a list item by id. Graph returns 204 on success. (siteId, listId, itemId) is the natural idempotency tuple \u2014 a re-delete of a missing item surfaces as 404 mapped to a tombstone result.",
|
|
41399
|
+
cas: "native-idempotency",
|
|
41400
|
+
externalEffect: true,
|
|
41401
|
+
parameters: {
|
|
41402
|
+
type: "object",
|
|
41403
|
+
properties: {
|
|
41404
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41405
|
+
listId: { type: "string", description: "SharePoint list id." },
|
|
41406
|
+
itemId: { type: "string", description: "List item id to delete." }
|
|
41407
|
+
},
|
|
41408
|
+
required: ["siteId", "listId", "itemId"]
|
|
41409
|
+
}
|
|
41410
|
+
},
|
|
41411
|
+
{
|
|
41412
|
+
name: "pages.publish",
|
|
41413
|
+
class: "mutation",
|
|
41414
|
+
description: "Publish a SharePoint site page by page id.",
|
|
41415
|
+
cas: "native-idempotency",
|
|
41416
|
+
externalEffect: true,
|
|
41417
|
+
parameters: {
|
|
41418
|
+
type: "object",
|
|
41419
|
+
properties: {
|
|
41420
|
+
siteId: { type: "string", description: "Graph site id." },
|
|
41421
|
+
pageId: { type: "string", description: "Site page id to publish." }
|
|
41422
|
+
},
|
|
41423
|
+
required: ["siteId", "pageId"]
|
|
41424
|
+
}
|
|
41355
41425
|
}
|
|
41356
41426
|
]
|
|
41357
41427
|
},
|
|
@@ -41501,6 +41571,41 @@ function sharepoint(opts) {
|
|
|
41501
41571
|
fetchedAt: Date.now()
|
|
41502
41572
|
};
|
|
41503
41573
|
}
|
|
41574
|
+
if (inv.capabilityName === "get_site_info") {
|
|
41575
|
+
const { siteId } = inv.args;
|
|
41576
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}?$select=id,name,displayName,webUrl,description`;
|
|
41577
|
+
const site = await graphGet4(url, accessToken, inv.source.id);
|
|
41578
|
+
return {
|
|
41579
|
+
data: {
|
|
41580
|
+
id: site.id,
|
|
41581
|
+
name: site.displayName ?? site.name,
|
|
41582
|
+
webUrl: site.webUrl,
|
|
41583
|
+
description: site.description
|
|
41584
|
+
},
|
|
41585
|
+
fetchedAt: Date.now()
|
|
41586
|
+
};
|
|
41587
|
+
}
|
|
41588
|
+
if (inv.capabilityName === "lists.items.find") {
|
|
41589
|
+
const { siteId, listId, filter, expand, top } = inv.args;
|
|
41590
|
+
const t = clamp(top ?? 50, 1, 200);
|
|
41591
|
+
const params = new URLSearchParams();
|
|
41592
|
+
params.set("$top", String(t));
|
|
41593
|
+
if (typeof filter === "string" && filter.length > 0) params.set("$filter", filter);
|
|
41594
|
+
if (typeof expand === "string" && expand.length > 0) params.set("$expand", expand);
|
|
41595
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items?${params.toString()}`;
|
|
41596
|
+
const json = await graphGet4(url, accessToken, inv.source.id);
|
|
41597
|
+
const items = (json.value ?? []).map((it) => ({
|
|
41598
|
+
id: it.id,
|
|
41599
|
+
webUrl: it.webUrl,
|
|
41600
|
+
etag: it.eTag,
|
|
41601
|
+
lastModifiedAt: it.lastModifiedDateTime,
|
|
41602
|
+
fields: it.fields
|
|
41603
|
+
}));
|
|
41604
|
+
return {
|
|
41605
|
+
data: { items, nextLink: json["@odata.nextLink"] },
|
|
41606
|
+
fetchedAt: Date.now()
|
|
41607
|
+
};
|
|
41608
|
+
}
|
|
41504
41609
|
throw new Error(`sharepoint: unknown read capability ${inv.capabilityName}`);
|
|
41505
41610
|
},
|
|
41506
41611
|
async executeMutation(inv) {
|
|
@@ -41810,6 +41915,211 @@ function sharepoint(opts) {
|
|
|
41810
41915
|
idempotentReplay: false
|
|
41811
41916
|
};
|
|
41812
41917
|
}
|
|
41918
|
+
if (inv.capabilityName === "copy_item") {
|
|
41919
|
+
const { siteId, itemId, parentReference, targetParentId, name } = inv.args;
|
|
41920
|
+
const ref = parentReference && Object.keys(parentReference).length > 0 ? parentReference : typeof targetParentId === "string" && targetParentId.length > 0 ? { id: targetParentId } : void 0;
|
|
41921
|
+
if (!ref) {
|
|
41922
|
+
throw new Error(
|
|
41923
|
+
"sharepoint copy_item: provide either parentReference (cross-drive) or targetParentId (same-site)"
|
|
41924
|
+
);
|
|
41925
|
+
}
|
|
41926
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/drive/items/${encodeURIComponent(itemId)}/copy`;
|
|
41927
|
+
const body = { parentReference: ref };
|
|
41928
|
+
if (typeof name === "string" && name.length > 0) body.name = name;
|
|
41929
|
+
const res = await fetch(url, {
|
|
41930
|
+
method: "POST",
|
|
41931
|
+
headers: {
|
|
41932
|
+
authorization: `Bearer ${accessToken}`,
|
|
41933
|
+
"content-type": "application/json",
|
|
41934
|
+
accept: "application/json"
|
|
41935
|
+
},
|
|
41936
|
+
body: JSON.stringify(body),
|
|
41937
|
+
signal: AbortSignal.timeout(15e3)
|
|
41938
|
+
});
|
|
41939
|
+
if (res.status === 401 || res.status === 403) {
|
|
41940
|
+
throw new CredentialsExpired(
|
|
41941
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
41942
|
+
inv.source.id
|
|
41943
|
+
);
|
|
41944
|
+
}
|
|
41945
|
+
if (res.status === 409 || res.status === 412) {
|
|
41946
|
+
throw new ResourceContention(
|
|
41947
|
+
`Microsoft Graph reported conflict on copy_item (${res.status})`,
|
|
41948
|
+
[]
|
|
41949
|
+
);
|
|
41950
|
+
}
|
|
41951
|
+
if (!res.ok && res.status !== 202) {
|
|
41952
|
+
const text = await res.text().catch(() => "");
|
|
41953
|
+
throw new Error(`sharepoint copy_item ${res.status}: ${text.slice(0, 200)}`);
|
|
41954
|
+
}
|
|
41955
|
+
const monitorUrl = res.headers.get("location") ?? void 0;
|
|
41956
|
+
return {
|
|
41957
|
+
status: "committed",
|
|
41958
|
+
data: { id: itemId, accepted: true, async: true, monitorUrl },
|
|
41959
|
+
committedAt: Date.now(),
|
|
41960
|
+
idempotentReplay: false
|
|
41961
|
+
};
|
|
41962
|
+
}
|
|
41963
|
+
if (inv.capabilityName === "lists.create") {
|
|
41964
|
+
const { siteId, displayName, columns, list } = inv.args;
|
|
41965
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists`;
|
|
41966
|
+
const body = { displayName };
|
|
41967
|
+
if (Array.isArray(columns)) body.columns = columns;
|
|
41968
|
+
if (list && typeof list === "object") body.list = list;
|
|
41969
|
+
const res = await fetch(url, {
|
|
41970
|
+
method: "POST",
|
|
41971
|
+
headers: {
|
|
41972
|
+
authorization: `Bearer ${accessToken}`,
|
|
41973
|
+
"content-type": "application/json",
|
|
41974
|
+
accept: "application/json"
|
|
41975
|
+
},
|
|
41976
|
+
body: JSON.stringify(body),
|
|
41977
|
+
signal: AbortSignal.timeout(15e3)
|
|
41978
|
+
});
|
|
41979
|
+
if (res.status === 401 || res.status === 403) {
|
|
41980
|
+
throw new CredentialsExpired(
|
|
41981
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
41982
|
+
inv.source.id
|
|
41983
|
+
);
|
|
41984
|
+
}
|
|
41985
|
+
if (res.status === 409 || res.status === 412) {
|
|
41986
|
+
throw new ResourceContention(
|
|
41987
|
+
`Microsoft Graph reported conflict on lists.create (${res.status})`,
|
|
41988
|
+
[]
|
|
41989
|
+
);
|
|
41990
|
+
}
|
|
41991
|
+
if (!res.ok) {
|
|
41992
|
+
const text = await res.text().catch(() => "");
|
|
41993
|
+
throw new Error(`sharepoint lists.create ${res.status}: ${text.slice(0, 200)}`);
|
|
41994
|
+
}
|
|
41995
|
+
const created = await res.json();
|
|
41996
|
+
return {
|
|
41997
|
+
status: "committed",
|
|
41998
|
+
data: {
|
|
41999
|
+
id: created.id,
|
|
42000
|
+
displayName: created.displayName ?? created.name,
|
|
42001
|
+
webUrl: created.webUrl
|
|
42002
|
+
},
|
|
42003
|
+
etagAfter: created["@odata.etag"] ?? created.eTag,
|
|
42004
|
+
committedAt: Date.now(),
|
|
42005
|
+
idempotentReplay: false
|
|
42006
|
+
};
|
|
42007
|
+
}
|
|
42008
|
+
if (inv.capabilityName === "lists.items.update") {
|
|
42009
|
+
const { siteId, listId, itemId, fields } = inv.args;
|
|
42010
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}/fields`;
|
|
42011
|
+
const headers = {
|
|
42012
|
+
authorization: `Bearer ${accessToken}`,
|
|
42013
|
+
"content-type": "application/json",
|
|
42014
|
+
accept: "application/json"
|
|
42015
|
+
};
|
|
42016
|
+
if (typeof inv.expectedEtag === "string" && inv.expectedEtag.length > 0) {
|
|
42017
|
+
headers["if-match"] = inv.expectedEtag;
|
|
42018
|
+
}
|
|
42019
|
+
const res = await fetch(url, {
|
|
42020
|
+
method: "PATCH",
|
|
42021
|
+
headers,
|
|
42022
|
+
body: JSON.stringify(fields),
|
|
42023
|
+
signal: AbortSignal.timeout(15e3)
|
|
42024
|
+
});
|
|
42025
|
+
if (res.status === 401 || res.status === 403) {
|
|
42026
|
+
throw new CredentialsExpired(
|
|
42027
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
42028
|
+
inv.source.id
|
|
42029
|
+
);
|
|
42030
|
+
}
|
|
42031
|
+
if (res.status === 409 || res.status === 412) {
|
|
42032
|
+
throw new ResourceContention(
|
|
42033
|
+
`Microsoft Graph reported conflict on lists.items.update (${res.status})`,
|
|
42034
|
+
[]
|
|
42035
|
+
);
|
|
42036
|
+
}
|
|
42037
|
+
if (!res.ok) {
|
|
42038
|
+
const text = await res.text().catch(() => "");
|
|
42039
|
+
throw new Error(`sharepoint lists.items.update ${res.status}: ${text.slice(0, 200)}`);
|
|
42040
|
+
}
|
|
42041
|
+
const updated = await res.json();
|
|
42042
|
+
return {
|
|
42043
|
+
status: "committed",
|
|
42044
|
+
data: { id: itemId, fields: updated },
|
|
42045
|
+
etagAfter: updated["@odata.etag"] ?? updated.eTag,
|
|
42046
|
+
committedAt: Date.now(),
|
|
42047
|
+
idempotentReplay: false
|
|
42048
|
+
};
|
|
42049
|
+
}
|
|
42050
|
+
if (inv.capabilityName === "lists.items.delete") {
|
|
42051
|
+
const { siteId, listId, itemId } = inv.args;
|
|
42052
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listId)}/items/${encodeURIComponent(itemId)}`;
|
|
42053
|
+
const res = await fetch(url, {
|
|
42054
|
+
method: "DELETE",
|
|
42055
|
+
headers: { authorization: `Bearer ${accessToken}` },
|
|
42056
|
+
signal: AbortSignal.timeout(15e3)
|
|
42057
|
+
});
|
|
42058
|
+
if (res.status === 401 || res.status === 403) {
|
|
42059
|
+
throw new CredentialsExpired(
|
|
42060
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
42061
|
+
inv.source.id
|
|
42062
|
+
);
|
|
42063
|
+
}
|
|
42064
|
+
if (res.status === 412 || res.status === 409) {
|
|
42065
|
+
throw new ResourceContention(
|
|
42066
|
+
`Microsoft Graph reported conflict on lists.items.delete (${res.status})`,
|
|
42067
|
+
[]
|
|
42068
|
+
);
|
|
42069
|
+
}
|
|
42070
|
+
if (res.status === 404) {
|
|
42071
|
+
return {
|
|
42072
|
+
status: "committed",
|
|
42073
|
+
data: { id: itemId, deleted: true, alreadyMissing: true },
|
|
42074
|
+
committedAt: Date.now(),
|
|
42075
|
+
idempotentReplay: true
|
|
42076
|
+
};
|
|
42077
|
+
}
|
|
42078
|
+
if (!res.ok) {
|
|
42079
|
+
const text = await res.text().catch(() => "");
|
|
42080
|
+
throw new Error(`sharepoint lists.items.delete ${res.status}: ${text.slice(0, 200)}`);
|
|
42081
|
+
}
|
|
42082
|
+
return {
|
|
42083
|
+
status: "committed",
|
|
42084
|
+
data: { id: itemId, deleted: true },
|
|
42085
|
+
committedAt: Date.now(),
|
|
42086
|
+
idempotentReplay: false
|
|
42087
|
+
};
|
|
42088
|
+
}
|
|
42089
|
+
if (inv.capabilityName === "pages.publish") {
|
|
42090
|
+
const { siteId, pageId } = inv.args;
|
|
42091
|
+
const url = `${GRAPH3}/sites/${encodeURIComponent(siteId)}/pages/${encodeURIComponent(pageId)}/microsoft.graph.sitePage/publish`;
|
|
42092
|
+
const res = await fetch(url, {
|
|
42093
|
+
method: "POST",
|
|
42094
|
+
headers: {
|
|
42095
|
+
authorization: `Bearer ${accessToken}`,
|
|
42096
|
+
accept: "application/json"
|
|
42097
|
+
},
|
|
42098
|
+
signal: AbortSignal.timeout(15e3)
|
|
42099
|
+
});
|
|
42100
|
+
if (res.status === 401 || res.status === 403) {
|
|
42101
|
+
throw new CredentialsExpired(
|
|
42102
|
+
`Microsoft Graph rejected token (${res.status})`,
|
|
42103
|
+
inv.source.id
|
|
42104
|
+
);
|
|
42105
|
+
}
|
|
42106
|
+
if (res.status === 409 || res.status === 412) {
|
|
42107
|
+
throw new ResourceContention(
|
|
42108
|
+
`Microsoft Graph reported conflict on pages.publish (${res.status})`,
|
|
42109
|
+
[]
|
|
42110
|
+
);
|
|
42111
|
+
}
|
|
42112
|
+
if (!res.ok) {
|
|
42113
|
+
const text = await res.text().catch(() => "");
|
|
42114
|
+
throw new Error(`sharepoint pages.publish ${res.status}: ${text.slice(0, 200)}`);
|
|
42115
|
+
}
|
|
42116
|
+
return {
|
|
42117
|
+
status: "committed",
|
|
42118
|
+
data: { id: pageId, published: true },
|
|
42119
|
+
committedAt: Date.now(),
|
|
42120
|
+
idempotentReplay: false
|
|
42121
|
+
};
|
|
42122
|
+
}
|
|
41813
42123
|
throw new Error(`sharepoint: unknown mutation capability ${inv.capabilityName}`);
|
|
41814
42124
|
},
|
|
41815
42125
|
async exchangeOAuth(input) {
|
|
@@ -41817,7 +42127,7 @@ function sharepoint(opts) {
|
|
|
41817
42127
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
41818
42128
|
}
|
|
41819
42129
|
const tokens = await exchangeAuthorizationCode({
|
|
41820
|
-
tokenUrl:
|
|
42130
|
+
tokenUrl: TOKEN_URL17,
|
|
41821
42131
|
clientId,
|
|
41822
42132
|
clientSecret,
|
|
41823
42133
|
code: input.code,
|
|
@@ -41840,7 +42150,7 @@ function sharepoint(opts) {
|
|
|
41840
42150
|
throw new Error("sharepoint.refreshToken: missing refresh token");
|
|
41841
42151
|
}
|
|
41842
42152
|
const refreshed = await refreshAccessToken({
|
|
41843
|
-
tokenUrl:
|
|
42153
|
+
tokenUrl: TOKEN_URL17,
|
|
41844
42154
|
clientId,
|
|
41845
42155
|
clientSecret,
|
|
41846
42156
|
refreshToken: creds.refreshToken
|
|
@@ -41889,7 +42199,7 @@ async function ensureFreshAccessToken15(creds, clientId, clientSecret) {
|
|
|
41889
42199
|
throw new CredentialsExpired("SharePoint access token expired and no refresh token", "");
|
|
41890
42200
|
}
|
|
41891
42201
|
const refreshed = await refreshAccessToken({
|
|
41892
|
-
tokenUrl:
|
|
42202
|
+
tokenUrl: TOKEN_URL17,
|
|
41893
42203
|
clientId,
|
|
41894
42204
|
clientSecret,
|
|
41895
42205
|
refreshToken: creds.refreshToken
|
|
@@ -71097,6 +71407,609 @@ var googleSearchConsoleConnector = declarativeRestConnector({
|
|
|
71097
71407
|
]
|
|
71098
71408
|
});
|
|
71099
71409
|
|
|
71410
|
+
// src/connectors/adapters/google-analytics.ts
|
|
71411
|
+
var googleAnalyticsConnector = declarativeRestConnector({
|
|
71412
|
+
kind: "google-analytics",
|
|
71413
|
+
displayName: "Google Analytics",
|
|
71414
|
+
description: "Run reports, pivot reports, realtime reports, and batch reports against connected GA4 properties. Read-only: GA4 ingest happens through gtag / Measurement Protocol, not the management API.",
|
|
71415
|
+
auth: {
|
|
71416
|
+
kind: "oauth2",
|
|
71417
|
+
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
71418
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
71419
|
+
scopes: ["https://www.googleapis.com/auth/analytics.readonly"],
|
|
71420
|
+
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
71421
|
+
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
71422
|
+
extraAuthParams: { access_type: "offline", prompt: "consent", include_granted_scopes: "true" }
|
|
71423
|
+
},
|
|
71424
|
+
category: "database",
|
|
71425
|
+
defaultConsistencyModel: "cache",
|
|
71426
|
+
baseUrl: "https://analyticsdata.googleapis.com",
|
|
71427
|
+
// accountSummaries.list lives on the Admin API host and is the cheapest
|
|
71428
|
+
// probe that confirms the token can reach GA4 at all. Absolute URL routes
|
|
71429
|
+
// around the single-baseUrl constraint of the declarative-rest runtime.
|
|
71430
|
+
test: {
|
|
71431
|
+
method: "GET",
|
|
71432
|
+
path: "https://analyticsadmin.googleapis.com/v1beta/accountSummaries",
|
|
71433
|
+
query: { pageSize: 1 }
|
|
71434
|
+
},
|
|
71435
|
+
capabilities: [
|
|
71436
|
+
{
|
|
71437
|
+
name: "accountSummaries.list",
|
|
71438
|
+
class: "read",
|
|
71439
|
+
description: "List GA4 account summaries reachable by the connected identity. Each summary nests its properties so the agent can discover propertyId values without a second round-trip (GET analyticsadmin.googleapis.com/v1beta/accountSummaries).",
|
|
71440
|
+
parameters: {
|
|
71441
|
+
type: "object",
|
|
71442
|
+
properties: {
|
|
71443
|
+
pageSize: { type: "integer", minimum: 1, maximum: 200, description: "Max account summaries per page; server caps at 200." },
|
|
71444
|
+
pageToken: { type: "string", description: "Continuation token returned by a prior call." }
|
|
71445
|
+
}
|
|
71446
|
+
},
|
|
71447
|
+
request: {
|
|
71448
|
+
method: "GET",
|
|
71449
|
+
path: "https://analyticsadmin.googleapis.com/v1beta/accountSummaries",
|
|
71450
|
+
query: { pageSize: "{pageSize}", pageToken: "{pageToken}" }
|
|
71451
|
+
},
|
|
71452
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71453
|
+
},
|
|
71454
|
+
{
|
|
71455
|
+
name: "properties.get",
|
|
71456
|
+
class: "read",
|
|
71457
|
+
description: "Fetch GA4 property settings (display name, timezone, currency, industry) by numeric property id (GET analyticsadmin.googleapis.com/v1beta/properties/{propertyId}).",
|
|
71458
|
+
parameters: {
|
|
71459
|
+
type: "object",
|
|
71460
|
+
properties: {
|
|
71461
|
+
propertyId: { type: "string", description: 'Numeric GA4 property id, e.g. "123456789".' }
|
|
71462
|
+
},
|
|
71463
|
+
required: ["propertyId"]
|
|
71464
|
+
},
|
|
71465
|
+
request: {
|
|
71466
|
+
method: "GET",
|
|
71467
|
+
path: "https://analyticsadmin.googleapis.com/v1beta/properties/{propertyId}"
|
|
71468
|
+
},
|
|
71469
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71470
|
+
},
|
|
71471
|
+
{
|
|
71472
|
+
name: "properties.metadata.get",
|
|
71473
|
+
class: "read",
|
|
71474
|
+
description: "List every dimension and metric available on a GA4 property, including custom dimensions/metrics defined by the customer. Use this before runReport to discover valid dimension/metric names (GET /v1beta/properties/{propertyId}/metadata).",
|
|
71475
|
+
parameters: {
|
|
71476
|
+
type: "object",
|
|
71477
|
+
properties: {
|
|
71478
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." }
|
|
71479
|
+
},
|
|
71480
|
+
required: ["propertyId"]
|
|
71481
|
+
},
|
|
71482
|
+
request: {
|
|
71483
|
+
method: "GET",
|
|
71484
|
+
path: "/v1beta/properties/{propertyId}/metadata"
|
|
71485
|
+
},
|
|
71486
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71487
|
+
},
|
|
71488
|
+
{
|
|
71489
|
+
name: "properties.runReport",
|
|
71490
|
+
class: "read",
|
|
71491
|
+
description: 'Run a core report against a GA4 property. Pass dimensions, metrics, dateRanges (e.g. {startDate:"7daysAgo",endDate:"today"}), optional filters, ordering, and a row limit. Returns the rows, totals, and metadata GA4 emits in the standard runReport response (POST /v1beta/properties/{propertyId}:runReport).',
|
|
71492
|
+
parameters: {
|
|
71493
|
+
type: "object",
|
|
71494
|
+
properties: {
|
|
71495
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71496
|
+
dimensions: {
|
|
71497
|
+
type: "array",
|
|
71498
|
+
description: 'Dimension specs, e.g. [{ "name": "country" }, { "name": "deviceCategory" }].',
|
|
71499
|
+
items: {
|
|
71500
|
+
type: "object",
|
|
71501
|
+
properties: {
|
|
71502
|
+
name: { type: "string" },
|
|
71503
|
+
dimensionExpression: { type: "object", description: "Composite/lower-case/concatenate expression (optional)." }
|
|
71504
|
+
},
|
|
71505
|
+
required: ["name"]
|
|
71506
|
+
}
|
|
71507
|
+
},
|
|
71508
|
+
metrics: {
|
|
71509
|
+
type: "array",
|
|
71510
|
+
description: 'Metric specs, e.g. [{ "name": "activeUsers" }, { "name": "sessions" }].',
|
|
71511
|
+
items: {
|
|
71512
|
+
type: "object",
|
|
71513
|
+
properties: {
|
|
71514
|
+
name: { type: "string" },
|
|
71515
|
+
expression: { type: "string", description: "Derived metric expression (optional)." },
|
|
71516
|
+
invisible: { type: "boolean" }
|
|
71517
|
+
},
|
|
71518
|
+
required: ["name"]
|
|
71519
|
+
}
|
|
71520
|
+
},
|
|
71521
|
+
dateRanges: {
|
|
71522
|
+
type: "array",
|
|
71523
|
+
description: 'One or two date ranges; GA4 accepts ISO dates ("2026-05-01"), "today", "yesterday", or "NdaysAgo".',
|
|
71524
|
+
items: {
|
|
71525
|
+
type: "object",
|
|
71526
|
+
properties: {
|
|
71527
|
+
startDate: { type: "string" },
|
|
71528
|
+
endDate: { type: "string" },
|
|
71529
|
+
name: { type: "string", description: "Optional label included in the response row keys when comparing two ranges." }
|
|
71530
|
+
},
|
|
71531
|
+
required: ["startDate", "endDate"]
|
|
71532
|
+
}
|
|
71533
|
+
},
|
|
71534
|
+
dimensionFilter: { type: "object", description: "GA4 FilterExpression (and/or/not) applied to dimensions." },
|
|
71535
|
+
metricFilter: { type: "object", description: "GA4 FilterExpression applied to metrics after aggregation." },
|
|
71536
|
+
orderBys: { type: "array", items: { type: "object" } },
|
|
71537
|
+
limit: { type: "integer", minimum: 1, maximum: 25e4, description: "Max rows per page; GA4 caps at 250000." },
|
|
71538
|
+
offset: { type: "integer", minimum: 0 },
|
|
71539
|
+
keepEmptyRows: { type: "boolean" },
|
|
71540
|
+
returnPropertyQuota: { type: "boolean", description: "Include per-property quota consumption in the response \u2014 useful for back-pressure decisions." },
|
|
71541
|
+
currencyCode: { type: "string", description: "ISO-4217 currency, overrides the property default for monetary metrics." },
|
|
71542
|
+
cohortSpec: { type: "object", description: "CohortSpec for cohort analysis (optional)." }
|
|
71543
|
+
},
|
|
71544
|
+
required: ["propertyId", "metrics", "dateRanges"]
|
|
71545
|
+
},
|
|
71546
|
+
request: {
|
|
71547
|
+
method: "POST",
|
|
71548
|
+
path: "/v1beta/properties/{propertyId}:runReport",
|
|
71549
|
+
body: {
|
|
71550
|
+
dimensions: "{dimensions}",
|
|
71551
|
+
metrics: "{metrics}",
|
|
71552
|
+
dateRanges: "{dateRanges}",
|
|
71553
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71554
|
+
metricFilter: "{metricFilter}",
|
|
71555
|
+
orderBys: "{orderBys}",
|
|
71556
|
+
limit: "{limit}",
|
|
71557
|
+
offset: "{offset}",
|
|
71558
|
+
keepEmptyRows: "{keepEmptyRows}",
|
|
71559
|
+
returnPropertyQuota: "{returnPropertyQuota}",
|
|
71560
|
+
currencyCode: "{currencyCode}",
|
|
71561
|
+
cohortSpec: "{cohortSpec}"
|
|
71562
|
+
}
|
|
71563
|
+
},
|
|
71564
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71565
|
+
},
|
|
71566
|
+
{
|
|
71567
|
+
name: "properties.batchRunReports",
|
|
71568
|
+
class: "read",
|
|
71569
|
+
description: "Run up to 5 reports against the same GA4 property in a single request \u2014 cheaper than 5 round-trips and counted as fewer quota tokens (POST /v1beta/properties/{propertyId}:batchRunReports).",
|
|
71570
|
+
parameters: {
|
|
71571
|
+
type: "object",
|
|
71572
|
+
properties: {
|
|
71573
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71574
|
+
requests: {
|
|
71575
|
+
type: "array",
|
|
71576
|
+
description: "Up to 5 report requests; each takes the same shape as runReport (dimensions/metrics/dateRanges/etc.).",
|
|
71577
|
+
items: { type: "object" },
|
|
71578
|
+
maxItems: 5
|
|
71579
|
+
}
|
|
71580
|
+
},
|
|
71581
|
+
required: ["propertyId", "requests"]
|
|
71582
|
+
},
|
|
71583
|
+
request: {
|
|
71584
|
+
method: "POST",
|
|
71585
|
+
path: "/v1beta/properties/{propertyId}:batchRunReports",
|
|
71586
|
+
body: { requests: "{requests}" }
|
|
71587
|
+
},
|
|
71588
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71589
|
+
},
|
|
71590
|
+
{
|
|
71591
|
+
name: "properties.runPivotReport",
|
|
71592
|
+
class: "read",
|
|
71593
|
+
description: "Run a pivot report \u2014 like runReport but with one or more pivot specifications that rotate dimensions into columns (POST /v1beta/properties/{propertyId}:runPivotReport).",
|
|
71594
|
+
parameters: {
|
|
71595
|
+
type: "object",
|
|
71596
|
+
properties: {
|
|
71597
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71598
|
+
dimensions: { type: "array", items: { type: "object" } },
|
|
71599
|
+
metrics: { type: "array", items: { type: "object" } },
|
|
71600
|
+
dateRanges: { type: "array", items: { type: "object" } },
|
|
71601
|
+
pivots: {
|
|
71602
|
+
type: "array",
|
|
71603
|
+
description: "Pivot specifications \u2014 each names the dimensions to pivot, an order, a limit, and optional offset.",
|
|
71604
|
+
items: {
|
|
71605
|
+
type: "object",
|
|
71606
|
+
properties: {
|
|
71607
|
+
fieldNames: { type: "array", items: { type: "string" } },
|
|
71608
|
+
orderBys: { type: "array", items: { type: "object" } },
|
|
71609
|
+
offset: { type: "string", description: "String-encoded long." },
|
|
71610
|
+
limit: { type: "string", description: "String-encoded long." },
|
|
71611
|
+
metricAggregations: { type: "array", items: { type: "string" } }
|
|
71612
|
+
},
|
|
71613
|
+
required: ["fieldNames"]
|
|
71614
|
+
}
|
|
71615
|
+
},
|
|
71616
|
+
dimensionFilter: { type: "object" },
|
|
71617
|
+
metricFilter: { type: "object" },
|
|
71618
|
+
currencyCode: { type: "string" },
|
|
71619
|
+
cohortSpec: { type: "object" },
|
|
71620
|
+
keepEmptyRows: { type: "boolean" },
|
|
71621
|
+
returnPropertyQuota: { type: "boolean" }
|
|
71622
|
+
},
|
|
71623
|
+
required: ["propertyId", "metrics", "dateRanges", "pivots"]
|
|
71624
|
+
},
|
|
71625
|
+
request: {
|
|
71626
|
+
method: "POST",
|
|
71627
|
+
path: "/v1beta/properties/{propertyId}:runPivotReport",
|
|
71628
|
+
body: {
|
|
71629
|
+
dimensions: "{dimensions}",
|
|
71630
|
+
metrics: "{metrics}",
|
|
71631
|
+
dateRanges: "{dateRanges}",
|
|
71632
|
+
pivots: "{pivots}",
|
|
71633
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71634
|
+
metricFilter: "{metricFilter}",
|
|
71635
|
+
currencyCode: "{currencyCode}",
|
|
71636
|
+
cohortSpec: "{cohortSpec}",
|
|
71637
|
+
keepEmptyRows: "{keepEmptyRows}",
|
|
71638
|
+
returnPropertyQuota: "{returnPropertyQuota}"
|
|
71639
|
+
}
|
|
71640
|
+
},
|
|
71641
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71642
|
+
},
|
|
71643
|
+
{
|
|
71644
|
+
name: "properties.runRealtimeReport",
|
|
71645
|
+
class: "read",
|
|
71646
|
+
description: "Run a realtime report \u2014 surfaces events that happened in the last 30 minutes. No dateRanges; the realtime window is implicit (POST /v1beta/properties/{propertyId}:runRealtimeReport).",
|
|
71647
|
+
parameters: {
|
|
71648
|
+
type: "object",
|
|
71649
|
+
properties: {
|
|
71650
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71651
|
+
dimensions: { type: "array", items: { type: "object" } },
|
|
71652
|
+
metrics: { type: "array", items: { type: "object" } },
|
|
71653
|
+
dimensionFilter: { type: "object" },
|
|
71654
|
+
metricFilter: { type: "object" },
|
|
71655
|
+
limit: { type: "integer", minimum: 1, maximum: 25e4 },
|
|
71656
|
+
metricAggregations: { type: "array", items: { type: "string" } },
|
|
71657
|
+
orderBys: { type: "array", items: { type: "object" } },
|
|
71658
|
+
returnPropertyQuota: { type: "boolean" },
|
|
71659
|
+
minuteRanges: {
|
|
71660
|
+
type: "array",
|
|
71661
|
+
description: 'Optional minute-window specifications, e.g. [{ "name": "last5", "startMinutesAgo": 5, "endMinutesAgo": 0 }]. Defaults to the last 30 minutes.',
|
|
71662
|
+
items: {
|
|
71663
|
+
type: "object",
|
|
71664
|
+
properties: {
|
|
71665
|
+
name: { type: "string" },
|
|
71666
|
+
startMinutesAgo: { type: "integer", minimum: 0, maximum: 29 },
|
|
71667
|
+
endMinutesAgo: { type: "integer", minimum: 0, maximum: 29 }
|
|
71668
|
+
}
|
|
71669
|
+
}
|
|
71670
|
+
}
|
|
71671
|
+
},
|
|
71672
|
+
required: ["propertyId", "metrics"]
|
|
71673
|
+
},
|
|
71674
|
+
request: {
|
|
71675
|
+
method: "POST",
|
|
71676
|
+
path: "/v1beta/properties/{propertyId}:runRealtimeReport",
|
|
71677
|
+
body: {
|
|
71678
|
+
dimensions: "{dimensions}",
|
|
71679
|
+
metrics: "{metrics}",
|
|
71680
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71681
|
+
metricFilter: "{metricFilter}",
|
|
71682
|
+
limit: "{limit}",
|
|
71683
|
+
metricAggregations: "{metricAggregations}",
|
|
71684
|
+
orderBys: "{orderBys}",
|
|
71685
|
+
returnPropertyQuota: "{returnPropertyQuota}",
|
|
71686
|
+
minuteRanges: "{minuteRanges}"
|
|
71687
|
+
}
|
|
71688
|
+
},
|
|
71689
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71690
|
+
},
|
|
71691
|
+
{
|
|
71692
|
+
name: "properties.checkCompatibility",
|
|
71693
|
+
class: "read",
|
|
71694
|
+
description: "Check whether a given dimension/metric combination is compatible before issuing a full runReport \u2014 GA4 rejects incompatible combos (e.g. cohort dimensions with non-cohort metrics) with a hard error (POST /v1beta/properties/{propertyId}:checkCompatibility).",
|
|
71695
|
+
parameters: {
|
|
71696
|
+
type: "object",
|
|
71697
|
+
properties: {
|
|
71698
|
+
propertyId: { type: "string", description: "Numeric GA4 property id." },
|
|
71699
|
+
dimensions: { type: "array", items: { type: "object" } },
|
|
71700
|
+
metrics: { type: "array", items: { type: "object" } },
|
|
71701
|
+
dimensionFilter: { type: "object" },
|
|
71702
|
+
metricFilter: { type: "object" },
|
|
71703
|
+
compatibilityFilter: {
|
|
71704
|
+
type: "string",
|
|
71705
|
+
enum: ["COMPATIBILITY_UNSPECIFIED", "COMPATIBLE", "INCOMPATIBLE"],
|
|
71706
|
+
description: "Restrict the response to compatible or incompatible entries only."
|
|
71707
|
+
}
|
|
71708
|
+
},
|
|
71709
|
+
required: ["propertyId"]
|
|
71710
|
+
},
|
|
71711
|
+
request: {
|
|
71712
|
+
method: "POST",
|
|
71713
|
+
path: "/v1beta/properties/{propertyId}:checkCompatibility",
|
|
71714
|
+
body: {
|
|
71715
|
+
dimensions: "{dimensions}",
|
|
71716
|
+
metrics: "{metrics}",
|
|
71717
|
+
dimensionFilter: "{dimensionFilter}",
|
|
71718
|
+
metricFilter: "{metricFilter}",
|
|
71719
|
+
compatibilityFilter: "{compatibilityFilter}"
|
|
71720
|
+
}
|
|
71721
|
+
},
|
|
71722
|
+
requiredScopes: ["https://www.googleapis.com/auth/analytics.readonly"]
|
|
71723
|
+
}
|
|
71724
|
+
]
|
|
71725
|
+
});
|
|
71726
|
+
|
|
71727
|
+
// src/connectors/adapters/google-meet.ts
|
|
71728
|
+
var googleMeetConnector = declarativeRestConnector({
|
|
71729
|
+
kind: "google-meet",
|
|
71730
|
+
displayName: "Google Meet",
|
|
71731
|
+
description: "Create Google Meet spaces, fetch post-meeting conference records, and read participants, recordings, and transcripts via the Google Meet REST API v2.",
|
|
71732
|
+
auth: {
|
|
71733
|
+
kind: "oauth2",
|
|
71734
|
+
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
71735
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
71736
|
+
scopes: [
|
|
71737
|
+
"https://www.googleapis.com/auth/meetings.space.created",
|
|
71738
|
+
"https://www.googleapis.com/auth/meetings.space.readonly",
|
|
71739
|
+
"https://www.googleapis.com/auth/meetings.space.settings",
|
|
71740
|
+
"https://www.googleapis.com/auth/drive.readonly"
|
|
71741
|
+
],
|
|
71742
|
+
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
71743
|
+
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
71744
|
+
extraAuthParams: {
|
|
71745
|
+
access_type: "offline",
|
|
71746
|
+
prompt: "consent",
|
|
71747
|
+
include_granted_scopes: "true"
|
|
71748
|
+
}
|
|
71749
|
+
},
|
|
71750
|
+
category: "calendar",
|
|
71751
|
+
defaultConsistencyModel: "authoritative",
|
|
71752
|
+
baseUrl: "https://meet.googleapis.com",
|
|
71753
|
+
// /v2/spaces/{name} requires a real space id; the cheapest token-validity
|
|
71754
|
+
// probe Meet exposes is creating a throwaway space, which has a side effect
|
|
71755
|
+
// we don't want in a connection test. Skip the in-band test — the adapter
|
|
71756
|
+
// contract treats a missing `test` as ok and connection issuance still
|
|
71757
|
+
// catches the auth handshake at exchange time.
|
|
71758
|
+
capabilities: [
|
|
71759
|
+
{
|
|
71760
|
+
name: "spaces.create",
|
|
71761
|
+
class: "mutation",
|
|
71762
|
+
description: "Create a Meet space and return its meet.google.com URL. The space lives until the calling user deletes it or it expires per Google retention rules.",
|
|
71763
|
+
parameters: {
|
|
71764
|
+
type: "object",
|
|
71765
|
+
properties: {
|
|
71766
|
+
config: {
|
|
71767
|
+
type: "object",
|
|
71768
|
+
description: "Optional SpaceConfig: accessType (OPEN | TRUSTED | RESTRICTED), entryPointAccess (ALL | CREATOR_APP_ONLY), moderation, attendanceReport, artifactConfig, chatRestriction, presentRestriction, defaultJoinAsViewerType."
|
|
71769
|
+
}
|
|
71770
|
+
}
|
|
71771
|
+
},
|
|
71772
|
+
request: {
|
|
71773
|
+
method: "POST",
|
|
71774
|
+
path: "/v2/spaces",
|
|
71775
|
+
body: {
|
|
71776
|
+
config: "{config}"
|
|
71777
|
+
}
|
|
71778
|
+
},
|
|
71779
|
+
// Meet's spaces.create is a pure side-effect; no upstream idempotency
|
|
71780
|
+
// key on this endpoint, so a retry produces a second space. Mark
|
|
71781
|
+
// accordingly so the MutationGuard layer enforces idempotency.
|
|
71782
|
+
cas: "none",
|
|
71783
|
+
externalEffect: true,
|
|
71784
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.created"]
|
|
71785
|
+
},
|
|
71786
|
+
{
|
|
71787
|
+
name: "spaces.get",
|
|
71788
|
+
class: "read",
|
|
71789
|
+
description: 'Read a Meet space by resource name (e.g. "spaces/abc-defg-hij") or by short meeting code.',
|
|
71790
|
+
parameters: {
|
|
71791
|
+
type: "object",
|
|
71792
|
+
properties: {
|
|
71793
|
+
name: {
|
|
71794
|
+
type: "string",
|
|
71795
|
+
description: 'Resource name like "spaces/{space_id}" or "spaces/{meeting_code}".'
|
|
71796
|
+
}
|
|
71797
|
+
},
|
|
71798
|
+
required: ["name"]
|
|
71799
|
+
},
|
|
71800
|
+
request: {
|
|
71801
|
+
method: "GET",
|
|
71802
|
+
path: "/v2/{name}"
|
|
71803
|
+
},
|
|
71804
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71805
|
+
},
|
|
71806
|
+
{
|
|
71807
|
+
name: "spaces.update",
|
|
71808
|
+
class: "mutation",
|
|
71809
|
+
description: "Patch a Meet space (accessType, entryPointAccess, moderation toggles, artifactConfig, chat/present restrictions). Caller supplies updateMask to specify mutated fields.",
|
|
71810
|
+
parameters: {
|
|
71811
|
+
type: "object",
|
|
71812
|
+
properties: {
|
|
71813
|
+
name: { type: "string", description: 'Resource name like "spaces/{space_id}".' },
|
|
71814
|
+
updateMask: {
|
|
71815
|
+
type: "string",
|
|
71816
|
+
description: 'Comma-separated FieldMask of mutated fields, e.g. "config.accessType,config.moderation".'
|
|
71817
|
+
},
|
|
71818
|
+
config: { type: "object", description: "New SpaceConfig values." }
|
|
71819
|
+
},
|
|
71820
|
+
required: ["name"]
|
|
71821
|
+
},
|
|
71822
|
+
request: {
|
|
71823
|
+
method: "PATCH",
|
|
71824
|
+
path: "/v2/{name}",
|
|
71825
|
+
query: {
|
|
71826
|
+
updateMask: "{updateMask}"
|
|
71827
|
+
},
|
|
71828
|
+
body: {
|
|
71829
|
+
config: "{config}"
|
|
71830
|
+
}
|
|
71831
|
+
},
|
|
71832
|
+
cas: "native-idempotency",
|
|
71833
|
+
externalEffect: true,
|
|
71834
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.settings"]
|
|
71835
|
+
},
|
|
71836
|
+
{
|
|
71837
|
+
name: "spaces.endActiveConference",
|
|
71838
|
+
class: "mutation",
|
|
71839
|
+
description: "Terminate the currently active conference inside a Meet space. No-op (HTTP 200) if no conference is active.",
|
|
71840
|
+
parameters: {
|
|
71841
|
+
type: "object",
|
|
71842
|
+
properties: {
|
|
71843
|
+
name: { type: "string", description: 'Resource name like "spaces/{space_id}".' }
|
|
71844
|
+
},
|
|
71845
|
+
required: ["name"]
|
|
71846
|
+
},
|
|
71847
|
+
request: {
|
|
71848
|
+
method: "POST",
|
|
71849
|
+
path: "/v2/{name}:endActiveConference",
|
|
71850
|
+
body: {}
|
|
71851
|
+
},
|
|
71852
|
+
cas: "native-idempotency",
|
|
71853
|
+
externalEffect: true,
|
|
71854
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.created"]
|
|
71855
|
+
},
|
|
71856
|
+
{
|
|
71857
|
+
name: "conferenceRecords.list",
|
|
71858
|
+
class: "read",
|
|
71859
|
+
description: "List conference records for meetings the calling user attended or hosted. Supports server-side filtering by space.name and end_time.",
|
|
71860
|
+
parameters: {
|
|
71861
|
+
type: "object",
|
|
71862
|
+
properties: {
|
|
71863
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100 },
|
|
71864
|
+
pageToken: { type: "string" },
|
|
71865
|
+
filter: {
|
|
71866
|
+
type: "string",
|
|
71867
|
+
description: `EBNF filter, e.g. 'space.name="spaces/abc"' or 'end_time>="2024-01-01T00:00:00Z"'.`
|
|
71868
|
+
}
|
|
71869
|
+
}
|
|
71870
|
+
},
|
|
71871
|
+
request: {
|
|
71872
|
+
method: "GET",
|
|
71873
|
+
path: "/v2/conferenceRecords",
|
|
71874
|
+
query: {
|
|
71875
|
+
pageSize: "{pageSize}",
|
|
71876
|
+
pageToken: "{pageToken}",
|
|
71877
|
+
filter: "{filter}"
|
|
71878
|
+
}
|
|
71879
|
+
},
|
|
71880
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71881
|
+
},
|
|
71882
|
+
{
|
|
71883
|
+
name: "conferenceRecords.get",
|
|
71884
|
+
class: "read",
|
|
71885
|
+
description: 'Read a conference record by resource name (e.g. "conferenceRecords/abc123").',
|
|
71886
|
+
parameters: {
|
|
71887
|
+
type: "object",
|
|
71888
|
+
properties: {
|
|
71889
|
+
name: { type: "string", description: 'Resource name like "conferenceRecords/{conference_record_id}".' }
|
|
71890
|
+
},
|
|
71891
|
+
required: ["name"]
|
|
71892
|
+
},
|
|
71893
|
+
request: {
|
|
71894
|
+
method: "GET",
|
|
71895
|
+
path: "/v2/{name}"
|
|
71896
|
+
},
|
|
71897
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71898
|
+
},
|
|
71899
|
+
{
|
|
71900
|
+
name: "conferenceRecords.participants.list",
|
|
71901
|
+
class: "read",
|
|
71902
|
+
description: "List participants for a finished conference, including anonymous and phone-dial-in attendees.",
|
|
71903
|
+
parameters: {
|
|
71904
|
+
type: "object",
|
|
71905
|
+
properties: {
|
|
71906
|
+
parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
|
|
71907
|
+
pageSize: { type: "integer", minimum: 1, maximum: 250 },
|
|
71908
|
+
pageToken: { type: "string" },
|
|
71909
|
+
filter: { type: "string", description: `EBNF filter, e.g. 'earliest_start_time<="2024-01-01T00:00:00Z"'.` }
|
|
71910
|
+
},
|
|
71911
|
+
required: ["parent"]
|
|
71912
|
+
},
|
|
71913
|
+
request: {
|
|
71914
|
+
method: "GET",
|
|
71915
|
+
path: "/v2/{parent}/participants",
|
|
71916
|
+
query: {
|
|
71917
|
+
pageSize: "{pageSize}",
|
|
71918
|
+
pageToken: "{pageToken}",
|
|
71919
|
+
filter: "{filter}"
|
|
71920
|
+
}
|
|
71921
|
+
},
|
|
71922
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71923
|
+
},
|
|
71924
|
+
{
|
|
71925
|
+
name: "conferenceRecords.recordings.list",
|
|
71926
|
+
class: "read",
|
|
71927
|
+
description: "List recordings for a conference record. Each entry includes the Drive file id and DriveFileExportUri for downstream Drive fetches.",
|
|
71928
|
+
parameters: {
|
|
71929
|
+
type: "object",
|
|
71930
|
+
properties: {
|
|
71931
|
+
parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
|
|
71932
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100 },
|
|
71933
|
+
pageToken: { type: "string" }
|
|
71934
|
+
},
|
|
71935
|
+
required: ["parent"]
|
|
71936
|
+
},
|
|
71937
|
+
request: {
|
|
71938
|
+
method: "GET",
|
|
71939
|
+
path: "/v2/{parent}/recordings",
|
|
71940
|
+
query: {
|
|
71941
|
+
pageSize: "{pageSize}",
|
|
71942
|
+
pageToken: "{pageToken}"
|
|
71943
|
+
}
|
|
71944
|
+
},
|
|
71945
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71946
|
+
},
|
|
71947
|
+
{
|
|
71948
|
+
name: "conferenceRecords.recordings.get",
|
|
71949
|
+
class: "read",
|
|
71950
|
+
description: "Read a single recording by resource name.",
|
|
71951
|
+
parameters: {
|
|
71952
|
+
type: "object",
|
|
71953
|
+
properties: {
|
|
71954
|
+
name: {
|
|
71955
|
+
type: "string",
|
|
71956
|
+
description: 'Resource name like "conferenceRecords/{conference_record_id}/recordings/{recording_id}".'
|
|
71957
|
+
}
|
|
71958
|
+
},
|
|
71959
|
+
required: ["name"]
|
|
71960
|
+
},
|
|
71961
|
+
request: {
|
|
71962
|
+
method: "GET",
|
|
71963
|
+
path: "/v2/{name}"
|
|
71964
|
+
},
|
|
71965
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71966
|
+
},
|
|
71967
|
+
{
|
|
71968
|
+
name: "conferenceRecords.transcripts.list",
|
|
71969
|
+
class: "read",
|
|
71970
|
+
description: "List transcripts (auto-generated captions exports) for a conference record.",
|
|
71971
|
+
parameters: {
|
|
71972
|
+
type: "object",
|
|
71973
|
+
properties: {
|
|
71974
|
+
parent: { type: "string", description: "Parent conferenceRecords/{conference_record_id}." },
|
|
71975
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100 },
|
|
71976
|
+
pageToken: { type: "string" }
|
|
71977
|
+
},
|
|
71978
|
+
required: ["parent"]
|
|
71979
|
+
},
|
|
71980
|
+
request: {
|
|
71981
|
+
method: "GET",
|
|
71982
|
+
path: "/v2/{parent}/transcripts",
|
|
71983
|
+
query: {
|
|
71984
|
+
pageSize: "{pageSize}",
|
|
71985
|
+
pageToken: "{pageToken}"
|
|
71986
|
+
}
|
|
71987
|
+
},
|
|
71988
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
71989
|
+
},
|
|
71990
|
+
{
|
|
71991
|
+
name: "conferenceRecords.transcripts.get",
|
|
71992
|
+
class: "read",
|
|
71993
|
+
description: "Read a transcript by resource name; payload links to the Drive Doc holding the transcript text.",
|
|
71994
|
+
parameters: {
|
|
71995
|
+
type: "object",
|
|
71996
|
+
properties: {
|
|
71997
|
+
name: {
|
|
71998
|
+
type: "string",
|
|
71999
|
+
description: 'Resource name like "conferenceRecords/{conference_record_id}/transcripts/{transcript_id}".'
|
|
72000
|
+
}
|
|
72001
|
+
},
|
|
72002
|
+
required: ["name"]
|
|
72003
|
+
},
|
|
72004
|
+
request: {
|
|
72005
|
+
method: "GET",
|
|
72006
|
+
path: "/v2/{name}"
|
|
72007
|
+
},
|
|
72008
|
+
requiredScopes: ["https://www.googleapis.com/auth/meetings.space.readonly"]
|
|
72009
|
+
}
|
|
72010
|
+
]
|
|
72011
|
+
});
|
|
72012
|
+
|
|
71100
72013
|
// src/connectors/adapters/youtube-data.ts
|
|
71101
72014
|
var youtubeDataConnector = declarativeRestConnector({
|
|
71102
72015
|
kind: "youtube",
|
|
@@ -86860,123 +87773,6 @@ var microsoftPowerBiConnector = declarativeRestConnector({
|
|
|
86860
87773
|
]
|
|
86861
87774
|
});
|
|
86862
87775
|
|
|
86863
|
-
// src/connectors/adapters/microsoft-outlook-calendar.ts
|
|
86864
|
-
var microsoftOutlookCalendarConnector = declarativeRestConnector({
|
|
86865
|
-
kind: "microsoft-outlook-calendar",
|
|
86866
|
-
displayName: "Microsoft Outlook Calendar",
|
|
86867
|
-
description: "Create, list, and delete Outlook/Microsoft 365 calendar events via Microsoft Graph.",
|
|
86868
|
-
auth: {
|
|
86869
|
-
kind: "oauth2",
|
|
86870
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
86871
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
86872
|
-
scopes: ["offline_access", "Calendars.ReadWrite", "User.Read"],
|
|
86873
|
-
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
86874
|
-
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
86875
|
-
},
|
|
86876
|
-
category: "calendar",
|
|
86877
|
-
defaultConsistencyModel: "authoritative",
|
|
86878
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
86879
|
-
test: { method: "GET", path: "/me" },
|
|
86880
|
-
capabilities: [
|
|
86881
|
-
{
|
|
86882
|
-
name: "create.event",
|
|
86883
|
-
class: "mutation",
|
|
86884
|
-
description: "Create a calendar event on the signed-in user's primary calendar, or on a specific calendarId when supplied.",
|
|
86885
|
-
parameters: {
|
|
86886
|
-
type: "object",
|
|
86887
|
-
properties: {
|
|
86888
|
-
calendarId: { type: "string" },
|
|
86889
|
-
subject: { type: "string" },
|
|
86890
|
-
body: { type: "object" },
|
|
86891
|
-
start: { type: "object" },
|
|
86892
|
-
end: { type: "object" },
|
|
86893
|
-
location: { type: "object" },
|
|
86894
|
-
attendees: { type: "array", items: { type: "object" } },
|
|
86895
|
-
isOnlineMeeting: { type: "boolean" },
|
|
86896
|
-
onlineMeetingProvider: { type: "string" },
|
|
86897
|
-
showAs: { type: "string" },
|
|
86898
|
-
sensitivity: { type: "string" },
|
|
86899
|
-
importance: { type: "string" },
|
|
86900
|
-
categories: { type: "array", items: { type: "string" } },
|
|
86901
|
-
reminderMinutesBeforeStart: { type: "integer" },
|
|
86902
|
-
isAllDay: { type: "boolean" },
|
|
86903
|
-
recurrence: { type: "object" },
|
|
86904
|
-
transactionId: { type: "string" }
|
|
86905
|
-
},
|
|
86906
|
-
required: ["subject", "start", "end"]
|
|
86907
|
-
},
|
|
86908
|
-
request: {
|
|
86909
|
-
method: "POST",
|
|
86910
|
-
path: "/me/calendars/{calendarId}/events",
|
|
86911
|
-
body: {
|
|
86912
|
-
subject: "{subject}",
|
|
86913
|
-
body: "{body}",
|
|
86914
|
-
start: "{start}",
|
|
86915
|
-
end: "{end}",
|
|
86916
|
-
location: "{location}",
|
|
86917
|
-
attendees: "{attendees}",
|
|
86918
|
-
isOnlineMeeting: "{isOnlineMeeting}",
|
|
86919
|
-
onlineMeetingProvider: "{onlineMeetingProvider}",
|
|
86920
|
-
showAs: "{showAs}",
|
|
86921
|
-
sensitivity: "{sensitivity}",
|
|
86922
|
-
importance: "{importance}",
|
|
86923
|
-
categories: "{categories}",
|
|
86924
|
-
reminderMinutesBeforeStart: "{reminderMinutesBeforeStart}",
|
|
86925
|
-
isAllDay: "{isAllDay}",
|
|
86926
|
-
recurrence: "{recurrence}",
|
|
86927
|
-
transactionId: "{transactionId}"
|
|
86928
|
-
}
|
|
86929
|
-
},
|
|
86930
|
-
cas: "native-idempotency",
|
|
86931
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86932
|
-
},
|
|
86933
|
-
{
|
|
86934
|
-
name: "delete.event",
|
|
86935
|
-
class: "mutation",
|
|
86936
|
-
description: "Delete a calendar event by id from the signed-in user mailbox.",
|
|
86937
|
-
parameters: {
|
|
86938
|
-
type: "object",
|
|
86939
|
-
properties: { eventId: { type: "string" } },
|
|
86940
|
-
required: ["eventId"]
|
|
86941
|
-
},
|
|
86942
|
-
request: { method: "DELETE", path: "/me/events/{eventId}" },
|
|
86943
|
-
cas: "native-idempotency",
|
|
86944
|
-
externalEffect: true,
|
|
86945
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86946
|
-
},
|
|
86947
|
-
{
|
|
86948
|
-
name: "list.events",
|
|
86949
|
-
class: "read",
|
|
86950
|
-
description: "List events on a calendar with OData paging/filtering ($top, $skip, $filter, $select, $orderby, $search). Targets the user's primary calendar unless calendarId is supplied.",
|
|
86951
|
-
parameters: {
|
|
86952
|
-
type: "object",
|
|
86953
|
-
properties: {
|
|
86954
|
-
calendarId: { type: "string" },
|
|
86955
|
-
$top: { type: "integer" },
|
|
86956
|
-
$skip: { type: "integer" },
|
|
86957
|
-
$filter: { type: "string" },
|
|
86958
|
-
$select: { type: "string" },
|
|
86959
|
-
$orderby: { type: "string" },
|
|
86960
|
-
$search: { type: "string" }
|
|
86961
|
-
}
|
|
86962
|
-
},
|
|
86963
|
-
request: {
|
|
86964
|
-
method: "GET",
|
|
86965
|
-
path: "/me/calendars/{calendarId}/events",
|
|
86966
|
-
query: {
|
|
86967
|
-
$top: "{$top}",
|
|
86968
|
-
$skip: "{$skip}",
|
|
86969
|
-
$filter: "{$filter}",
|
|
86970
|
-
$select: "{$select}",
|
|
86971
|
-
$orderby: "{$orderby}",
|
|
86972
|
-
$search: "{$search}"
|
|
86973
|
-
}
|
|
86974
|
-
},
|
|
86975
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86976
|
-
}
|
|
86977
|
-
]
|
|
86978
|
-
});
|
|
86979
|
-
|
|
86980
87776
|
// src/connectors/adapters/microsoft-onenote.ts
|
|
86981
87777
|
var microsoftOnenoteConnector = declarativeRestConnector({
|
|
86982
87778
|
kind: "microsoft-onenote",
|
|
@@ -87196,299 +87992,6 @@ var microsoftOnenoteConnector = declarativeRestConnector({
|
|
|
87196
87992
|
]
|
|
87197
87993
|
});
|
|
87198
87994
|
|
|
87199
|
-
// src/connectors/adapters/microsoft-outlook.ts
|
|
87200
|
-
var microsoftOutlookConnector = declarativeRestConnector({
|
|
87201
|
-
kind: "microsoft-outlook",
|
|
87202
|
-
displayName: "Microsoft Outlook",
|
|
87203
|
-
description: "Send, draft, reply to, forward, search, label, and organize email in the signed-in user's Outlook mailbox via Microsoft Graph.",
|
|
87204
|
-
auth: {
|
|
87205
|
-
kind: "oauth2",
|
|
87206
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
87207
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
87208
|
-
scopes: [
|
|
87209
|
-
"offline_access",
|
|
87210
|
-
"User.Read",
|
|
87211
|
-
"Mail.ReadWrite",
|
|
87212
|
-
"Mail.Send",
|
|
87213
|
-
"MailboxSettings.Read"
|
|
87214
|
-
],
|
|
87215
|
-
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
87216
|
-
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
87217
|
-
},
|
|
87218
|
-
category: "comms",
|
|
87219
|
-
defaultConsistencyModel: "authoritative",
|
|
87220
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
87221
|
-
test: { method: "GET", path: "/me" },
|
|
87222
|
-
capabilities: [
|
|
87223
|
-
{
|
|
87224
|
-
name: "email.send",
|
|
87225
|
-
class: "mutation",
|
|
87226
|
-
description: "Send an email immediately from the signed-in user's mailbox. Optionally saves the sent message to the Sent Items folder.",
|
|
87227
|
-
parameters: {
|
|
87228
|
-
type: "object",
|
|
87229
|
-
properties: {
|
|
87230
|
-
subject: { type: "string" },
|
|
87231
|
-
body: { type: "object" },
|
|
87232
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87233
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87234
|
-
bccRecipients: { type: "array", items: { type: "object" } },
|
|
87235
|
-
attachments: { type: "array", items: { type: "object" } },
|
|
87236
|
-
saveToSentItems: { type: "boolean" }
|
|
87237
|
-
},
|
|
87238
|
-
required: ["subject", "body", "toRecipients"]
|
|
87239
|
-
},
|
|
87240
|
-
request: {
|
|
87241
|
-
method: "POST",
|
|
87242
|
-
path: "/me/sendMail",
|
|
87243
|
-
body: {
|
|
87244
|
-
message: {
|
|
87245
|
-
subject: "{subject}",
|
|
87246
|
-
body: "{body}",
|
|
87247
|
-
toRecipients: "{toRecipients}",
|
|
87248
|
-
ccRecipients: "{ccRecipients}",
|
|
87249
|
-
bccRecipients: "{bccRecipients}",
|
|
87250
|
-
attachments: "{attachments}"
|
|
87251
|
-
},
|
|
87252
|
-
saveToSentItems: "{saveToSentItems}"
|
|
87253
|
-
}
|
|
87254
|
-
},
|
|
87255
|
-
cas: "none",
|
|
87256
|
-
externalEffect: true,
|
|
87257
|
-
requiredScopes: ["Mail.Send"]
|
|
87258
|
-
},
|
|
87259
|
-
{
|
|
87260
|
-
name: "email.draft.create",
|
|
87261
|
-
class: "mutation",
|
|
87262
|
-
description: "Create a draft email in the signed-in user mailbox without sending it.",
|
|
87263
|
-
parameters: {
|
|
87264
|
-
type: "object",
|
|
87265
|
-
properties: {
|
|
87266
|
-
subject: { type: "string" },
|
|
87267
|
-
body: { type: "object" },
|
|
87268
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87269
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87270
|
-
bccRecipients: { type: "array", items: { type: "object" } },
|
|
87271
|
-
importance: { type: "string" },
|
|
87272
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87273
|
-
},
|
|
87274
|
-
required: ["subject", "body"]
|
|
87275
|
-
},
|
|
87276
|
-
request: {
|
|
87277
|
-
method: "POST",
|
|
87278
|
-
path: "/me/messages",
|
|
87279
|
-
body: {
|
|
87280
|
-
subject: "{subject}",
|
|
87281
|
-
body: "{body}",
|
|
87282
|
-
toRecipients: "{toRecipients}",
|
|
87283
|
-
ccRecipients: "{ccRecipients}",
|
|
87284
|
-
bccRecipients: "{bccRecipients}",
|
|
87285
|
-
importance: "{importance}",
|
|
87286
|
-
categories: "{categories}"
|
|
87287
|
-
}
|
|
87288
|
-
},
|
|
87289
|
-
cas: "native-idempotency",
|
|
87290
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87291
|
-
},
|
|
87292
|
-
{
|
|
87293
|
-
name: "email.draft.send",
|
|
87294
|
-
class: "mutation",
|
|
87295
|
-
description: "Send a previously created draft message by id.",
|
|
87296
|
-
parameters: {
|
|
87297
|
-
type: "object",
|
|
87298
|
-
properties: { messageId: { type: "string" } },
|
|
87299
|
-
required: ["messageId"]
|
|
87300
|
-
},
|
|
87301
|
-
request: { method: "POST", path: "/me/messages/{messageId}/send" },
|
|
87302
|
-
cas: "none",
|
|
87303
|
-
externalEffect: true,
|
|
87304
|
-
requiredScopes: ["Mail.Send"]
|
|
87305
|
-
},
|
|
87306
|
-
{
|
|
87307
|
-
name: "email.reply",
|
|
87308
|
-
class: "mutation",
|
|
87309
|
-
description: "Reply to an existing message. When comment is provided alone, Graph generates the reply body; when message is provided, it overrides recipients/body.",
|
|
87310
|
-
parameters: {
|
|
87311
|
-
type: "object",
|
|
87312
|
-
properties: {
|
|
87313
|
-
messageId: { type: "string" },
|
|
87314
|
-
comment: { type: "string" },
|
|
87315
|
-
message: { type: "object" }
|
|
87316
|
-
},
|
|
87317
|
-
required: ["messageId"]
|
|
87318
|
-
},
|
|
87319
|
-
request: {
|
|
87320
|
-
method: "POST",
|
|
87321
|
-
path: "/me/messages/{messageId}/reply",
|
|
87322
|
-
body: { comment: "{comment}", message: "{message}" }
|
|
87323
|
-
},
|
|
87324
|
-
cas: "none",
|
|
87325
|
-
externalEffect: true,
|
|
87326
|
-
requiredScopes: ["Mail.Send"]
|
|
87327
|
-
},
|
|
87328
|
-
{
|
|
87329
|
-
name: "email.forward",
|
|
87330
|
-
class: "mutation",
|
|
87331
|
-
description: "Forward an existing message to one or more recipients with an optional comment.",
|
|
87332
|
-
parameters: {
|
|
87333
|
-
type: "object",
|
|
87334
|
-
properties: {
|
|
87335
|
-
messageId: { type: "string" },
|
|
87336
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87337
|
-
comment: { type: "string" }
|
|
87338
|
-
},
|
|
87339
|
-
required: ["messageId", "toRecipients"]
|
|
87340
|
-
},
|
|
87341
|
-
request: {
|
|
87342
|
-
method: "POST",
|
|
87343
|
-
path: "/me/messages/{messageId}/forward",
|
|
87344
|
-
body: { toRecipients: "{toRecipients}", comment: "{comment}" }
|
|
87345
|
-
},
|
|
87346
|
-
cas: "none",
|
|
87347
|
-
externalEffect: true,
|
|
87348
|
-
requiredScopes: ["Mail.Send"]
|
|
87349
|
-
},
|
|
87350
|
-
{
|
|
87351
|
-
name: "email.move",
|
|
87352
|
-
class: "mutation",
|
|
87353
|
-
description: "Move a message to a destination mail folder by id (or well-known name like inbox/archive).",
|
|
87354
|
-
parameters: {
|
|
87355
|
-
type: "object",
|
|
87356
|
-
properties: {
|
|
87357
|
-
messageId: { type: "string" },
|
|
87358
|
-
destinationId: { type: "string" }
|
|
87359
|
-
},
|
|
87360
|
-
required: ["messageId", "destinationId"]
|
|
87361
|
-
},
|
|
87362
|
-
request: {
|
|
87363
|
-
method: "POST",
|
|
87364
|
-
path: "/me/messages/{messageId}/move",
|
|
87365
|
-
body: { destinationId: "{destinationId}" }
|
|
87366
|
-
},
|
|
87367
|
-
cas: "native-idempotency",
|
|
87368
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87369
|
-
},
|
|
87370
|
-
{
|
|
87371
|
-
name: "email.label.add",
|
|
87372
|
-
class: "mutation",
|
|
87373
|
-
description: "Tag a message with one or more Outlook categories (labels). Pass the desired full set; Graph replaces the categories array.",
|
|
87374
|
-
parameters: {
|
|
87375
|
-
type: "object",
|
|
87376
|
-
properties: {
|
|
87377
|
-
messageId: { type: "string" },
|
|
87378
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87379
|
-
},
|
|
87380
|
-
required: ["messageId", "categories"]
|
|
87381
|
-
},
|
|
87382
|
-
request: {
|
|
87383
|
-
method: "PATCH",
|
|
87384
|
-
path: "/me/messages/{messageId}",
|
|
87385
|
-
body: { categories: "{categories}" }
|
|
87386
|
-
},
|
|
87387
|
-
cas: "optimistic-read-verify",
|
|
87388
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87389
|
-
},
|
|
87390
|
-
{
|
|
87391
|
-
name: "email.label.remove",
|
|
87392
|
-
class: "mutation",
|
|
87393
|
-
description: "Remove labels from a message by writing the surviving categories array. Caller computes the remaining set and supplies it explicitly.",
|
|
87394
|
-
parameters: {
|
|
87395
|
-
type: "object",
|
|
87396
|
-
properties: {
|
|
87397
|
-
messageId: { type: "string" },
|
|
87398
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87399
|
-
},
|
|
87400
|
-
required: ["messageId", "categories"]
|
|
87401
|
-
},
|
|
87402
|
-
request: {
|
|
87403
|
-
method: "PATCH",
|
|
87404
|
-
path: "/me/messages/{messageId}",
|
|
87405
|
-
body: { categories: "{categories}" }
|
|
87406
|
-
},
|
|
87407
|
-
cas: "optimistic-read-verify",
|
|
87408
|
-
externalEffect: true,
|
|
87409
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87410
|
-
},
|
|
87411
|
-
{
|
|
87412
|
-
name: "email.find",
|
|
87413
|
-
class: "read",
|
|
87414
|
-
description: "Search messages in a folder using OData $search/$filter with $top, $select, $orderby. Folder defaults to the well-known inbox if omitted.",
|
|
87415
|
-
parameters: {
|
|
87416
|
-
type: "object",
|
|
87417
|
-
properties: {
|
|
87418
|
-
mailFolderId: { type: "string" },
|
|
87419
|
-
$search: { type: "string" },
|
|
87420
|
-
$filter: { type: "string" },
|
|
87421
|
-
$select: { type: "string" },
|
|
87422
|
-
$top: { type: "integer" },
|
|
87423
|
-
$orderby: { type: "string" }
|
|
87424
|
-
}
|
|
87425
|
-
},
|
|
87426
|
-
request: {
|
|
87427
|
-
method: "GET",
|
|
87428
|
-
path: "/me/mailFolders/{mailFolderId}/messages",
|
|
87429
|
-
query: {
|
|
87430
|
-
$search: "{$search}",
|
|
87431
|
-
$filter: "{$filter}",
|
|
87432
|
-
$select: "{$select}",
|
|
87433
|
-
$top: "{$top}",
|
|
87434
|
-
$orderby: "{$orderby}"
|
|
87435
|
-
}
|
|
87436
|
-
},
|
|
87437
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87438
|
-
},
|
|
87439
|
-
{
|
|
87440
|
-
name: "email.attachment.download",
|
|
87441
|
-
class: "read",
|
|
87442
|
-
description: "Read an attachment record (metadata plus base64 contentBytes for file attachments) for a message by attachment id.",
|
|
87443
|
-
parameters: {
|
|
87444
|
-
type: "object",
|
|
87445
|
-
properties: {
|
|
87446
|
-
messageId: { type: "string" },
|
|
87447
|
-
attachmentId: { type: "string" }
|
|
87448
|
-
},
|
|
87449
|
-
required: ["messageId", "attachmentId"]
|
|
87450
|
-
},
|
|
87451
|
-
request: {
|
|
87452
|
-
method: "GET",
|
|
87453
|
-
path: "/me/messages/{messageId}/attachments/{attachmentId}"
|
|
87454
|
-
},
|
|
87455
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87456
|
-
},
|
|
87457
|
-
{
|
|
87458
|
-
name: "email.approval.request",
|
|
87459
|
-
class: "mutation",
|
|
87460
|
-
description: "Send an approval-request email by composing a structured message body and sending it through /me/sendMail. The body should encode the approval prompt and reply-handling instructions.",
|
|
87461
|
-
parameters: {
|
|
87462
|
-
type: "object",
|
|
87463
|
-
properties: {
|
|
87464
|
-
subject: { type: "string" },
|
|
87465
|
-
body: { type: "object" },
|
|
87466
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87467
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87468
|
-
saveToSentItems: { type: "boolean" }
|
|
87469
|
-
},
|
|
87470
|
-
required: ["subject", "body", "toRecipients"]
|
|
87471
|
-
},
|
|
87472
|
-
request: {
|
|
87473
|
-
method: "POST",
|
|
87474
|
-
path: "/me/sendMail",
|
|
87475
|
-
body: {
|
|
87476
|
-
message: {
|
|
87477
|
-
subject: "{subject}",
|
|
87478
|
-
body: "{body}",
|
|
87479
|
-
toRecipients: "{toRecipients}",
|
|
87480
|
-
ccRecipients: "{ccRecipients}"
|
|
87481
|
-
},
|
|
87482
|
-
saveToSentItems: "{saveToSentItems}"
|
|
87483
|
-
}
|
|
87484
|
-
},
|
|
87485
|
-
cas: "none",
|
|
87486
|
-
externalEffect: true,
|
|
87487
|
-
requiredScopes: ["Mail.Send"]
|
|
87488
|
-
}
|
|
87489
|
-
]
|
|
87490
|
-
});
|
|
87491
|
-
|
|
87492
87995
|
// src/connectors/adapters/microsoft-excel-365.ts
|
|
87493
87996
|
var microsoftExcel365Connector = declarativeRestConnector({
|
|
87494
87997
|
kind: "microsoft-excel-365",
|
|
@@ -88362,348 +88865,6 @@ var microsoftTodoConnector = declarativeRestConnector({
|
|
|
88362
88865
|
]
|
|
88363
88866
|
});
|
|
88364
88867
|
|
|
88365
|
-
// src/connectors/adapters/microsoft-sharepoint.ts
|
|
88366
|
-
var microsoftSharepointConnector = declarativeRestConnector({
|
|
88367
|
-
kind: "microsoft-sharepoint",
|
|
88368
|
-
displayName: "Microsoft SharePoint",
|
|
88369
|
-
description: "Read SharePoint site metadata, list items, and files; create folders, lists, list items, and pages via Microsoft Graph.",
|
|
88370
|
-
auth: {
|
|
88371
|
-
kind: "oauth2",
|
|
88372
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
88373
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
88374
|
-
scopes: [
|
|
88375
|
-
"offline_access",
|
|
88376
|
-
"Sites.ReadWrite.All",
|
|
88377
|
-
"Files.ReadWrite.All"
|
|
88378
|
-
],
|
|
88379
|
-
clientIdEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_ID",
|
|
88380
|
-
clientSecretEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_SECRET"
|
|
88381
|
-
},
|
|
88382
|
-
category: "storage",
|
|
88383
|
-
defaultConsistencyModel: "authoritative",
|
|
88384
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
88385
|
-
test: { method: "GET", path: "/sites/root" },
|
|
88386
|
-
capabilities: [
|
|
88387
|
-
// ---------- Sites ----------
|
|
88388
|
-
{
|
|
88389
|
-
name: "find.site",
|
|
88390
|
-
class: "read",
|
|
88391
|
-
description: "Search SharePoint sites by display name or keyword (Graph $search).",
|
|
88392
|
-
parameters: {
|
|
88393
|
-
type: "object",
|
|
88394
|
-
properties: {
|
|
88395
|
-
search: { type: "string" },
|
|
88396
|
-
$top: { type: "integer" }
|
|
88397
|
-
},
|
|
88398
|
-
required: ["search"]
|
|
88399
|
-
},
|
|
88400
|
-
request: {
|
|
88401
|
-
method: "GET",
|
|
88402
|
-
path: "/sites",
|
|
88403
|
-
query: { search: "{search}", $top: "{$top}" }
|
|
88404
|
-
},
|
|
88405
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88406
|
-
},
|
|
88407
|
-
{
|
|
88408
|
-
name: "get.site.information",
|
|
88409
|
-
class: "read",
|
|
88410
|
-
description: "Read the metadata for a SharePoint site by site id.",
|
|
88411
|
-
parameters: {
|
|
88412
|
-
type: "object",
|
|
88413
|
-
properties: { siteId: { type: "string" } },
|
|
88414
|
-
required: ["siteId"]
|
|
88415
|
-
},
|
|
88416
|
-
request: { method: "GET", path: "/sites/{siteId}" },
|
|
88417
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88418
|
-
},
|
|
88419
|
-
// ---------- Folders / files ----------
|
|
88420
|
-
{
|
|
88421
|
-
name: "create.folder",
|
|
88422
|
-
class: "mutation",
|
|
88423
|
-
description: "Create a folder inside a site drive. Parent is identified by its drive item id (use the drive root id for top-level folders).",
|
|
88424
|
-
parameters: {
|
|
88425
|
-
type: "object",
|
|
88426
|
-
properties: {
|
|
88427
|
-
siteId: { type: "string" },
|
|
88428
|
-
parentItemId: { type: "string" },
|
|
88429
|
-
name: { type: "string" },
|
|
88430
|
-
conflictBehavior: { type: "string" }
|
|
88431
|
-
},
|
|
88432
|
-
required: ["siteId", "parentItemId", "name"]
|
|
88433
|
-
},
|
|
88434
|
-
request: {
|
|
88435
|
-
method: "POST",
|
|
88436
|
-
path: "/sites/{siteId}/drive/items/{parentItemId}/children",
|
|
88437
|
-
body: {
|
|
88438
|
-
name: "{name}",
|
|
88439
|
-
folder: {},
|
|
88440
|
-
"@microsoft.graph.conflictBehavior": "{conflictBehavior}"
|
|
88441
|
-
}
|
|
88442
|
-
},
|
|
88443
|
-
cas: "native-idempotency",
|
|
88444
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88445
|
-
},
|
|
88446
|
-
{
|
|
88447
|
-
name: "get.folder.contents",
|
|
88448
|
-
class: "read",
|
|
88449
|
-
description: "List the children of a folder in a site drive.",
|
|
88450
|
-
parameters: {
|
|
88451
|
-
type: "object",
|
|
88452
|
-
properties: {
|
|
88453
|
-
siteId: { type: "string" },
|
|
88454
|
-
itemId: { type: "string" },
|
|
88455
|
-
$top: { type: "integer" },
|
|
88456
|
-
$select: { type: "string" }
|
|
88457
|
-
},
|
|
88458
|
-
required: ["siteId", "itemId"]
|
|
88459
|
-
},
|
|
88460
|
-
request: {
|
|
88461
|
-
method: "GET",
|
|
88462
|
-
path: "/sites/{siteId}/drive/items/{itemId}/children",
|
|
88463
|
-
query: { $top: "{$top}", $select: "{$select}" }
|
|
88464
|
-
},
|
|
88465
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88466
|
-
},
|
|
88467
|
-
{
|
|
88468
|
-
name: "find.file",
|
|
88469
|
-
class: "read",
|
|
88470
|
-
description: "Search drive items inside a site drive by name or content (Graph drive search).",
|
|
88471
|
-
parameters: {
|
|
88472
|
-
type: "object",
|
|
88473
|
-
properties: {
|
|
88474
|
-
siteId: { type: "string" },
|
|
88475
|
-
query: { type: "string" },
|
|
88476
|
-
$top: { type: "integer" }
|
|
88477
|
-
},
|
|
88478
|
-
required: ["siteId", "query"]
|
|
88479
|
-
},
|
|
88480
|
-
request: {
|
|
88481
|
-
method: "GET",
|
|
88482
|
-
path: "/sites/{siteId}/drive/root/search(q='{query}')",
|
|
88483
|
-
query: { $top: "{$top}" }
|
|
88484
|
-
},
|
|
88485
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88486
|
-
},
|
|
88487
|
-
{
|
|
88488
|
-
name: "upload.file",
|
|
88489
|
-
class: "mutation",
|
|
88490
|
-
description: "Upload (or replace) a small file at the given drive path. The body must be the JSON-encoded contents the agent provides as `content` (base64-encoded for binary payloads). For files larger than 4 MiB the caller should use the upload-session flow instead.",
|
|
88491
|
-
parameters: {
|
|
88492
|
-
type: "object",
|
|
88493
|
-
properties: {
|
|
88494
|
-
siteId: { type: "string" },
|
|
88495
|
-
parentItemId: { type: "string" },
|
|
88496
|
-
fileName: { type: "string" },
|
|
88497
|
-
content: { type: "string" },
|
|
88498
|
-
conflictBehavior: { type: "string" }
|
|
88499
|
-
},
|
|
88500
|
-
required: ["siteId", "parentItemId", "fileName", "content"]
|
|
88501
|
-
},
|
|
88502
|
-
request: {
|
|
88503
|
-
method: "PUT",
|
|
88504
|
-
path: "/sites/{siteId}/drive/items/{parentItemId}:/{fileName}:/content",
|
|
88505
|
-
body: "{content}"
|
|
88506
|
-
},
|
|
88507
|
-
cas: "optimistic-read-verify",
|
|
88508
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88509
|
-
},
|
|
88510
|
-
{
|
|
88511
|
-
name: "copy.item",
|
|
88512
|
-
class: "mutation",
|
|
88513
|
-
description: "Copy a drive item into another drive. The destination is identified by a parentReference (driveId + id) and an optional new name.",
|
|
88514
|
-
parameters: {
|
|
88515
|
-
type: "object",
|
|
88516
|
-
properties: {
|
|
88517
|
-
siteId: { type: "string" },
|
|
88518
|
-
itemId: { type: "string" },
|
|
88519
|
-
parentReference: { type: "object" },
|
|
88520
|
-
name: { type: "string" }
|
|
88521
|
-
},
|
|
88522
|
-
required: ["siteId", "itemId", "parentReference"]
|
|
88523
|
-
},
|
|
88524
|
-
request: {
|
|
88525
|
-
method: "POST",
|
|
88526
|
-
path: "/sites/{siteId}/drive/items/{itemId}/copy",
|
|
88527
|
-
body: { parentReference: "{parentReference}", name: "{name}" }
|
|
88528
|
-
},
|
|
88529
|
-
cas: "native-idempotency",
|
|
88530
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88531
|
-
},
|
|
88532
|
-
{
|
|
88533
|
-
name: "copy.item.within.site",
|
|
88534
|
-
class: "mutation",
|
|
88535
|
-
description: "Copy a drive item to another folder inside the same site drive. The destination parent is identified by the target folder id.",
|
|
88536
|
-
parameters: {
|
|
88537
|
-
type: "object",
|
|
88538
|
-
properties: {
|
|
88539
|
-
siteId: { type: "string" },
|
|
88540
|
-
itemId: { type: "string" },
|
|
88541
|
-
targetParentId: { type: "string" },
|
|
88542
|
-
name: { type: "string" }
|
|
88543
|
-
},
|
|
88544
|
-
required: ["siteId", "itemId", "targetParentId"]
|
|
88545
|
-
},
|
|
88546
|
-
request: {
|
|
88547
|
-
method: "POST",
|
|
88548
|
-
path: "/sites/{siteId}/drive/items/{itemId}/copy",
|
|
88549
|
-
body: { parentReference: { id: "{targetParentId}" }, name: "{name}" }
|
|
88550
|
-
},
|
|
88551
|
-
cas: "native-idempotency",
|
|
88552
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88553
|
-
},
|
|
88554
|
-
{
|
|
88555
|
-
name: "move.file",
|
|
88556
|
-
class: "mutation",
|
|
88557
|
-
description: "Move (re-parent or rename) a drive item by patching its parentReference and/or name.",
|
|
88558
|
-
parameters: {
|
|
88559
|
-
type: "object",
|
|
88560
|
-
properties: {
|
|
88561
|
-
siteId: { type: "string" },
|
|
88562
|
-
itemId: { type: "string" },
|
|
88563
|
-
parentReference: { type: "object" },
|
|
88564
|
-
name: { type: "string" }
|
|
88565
|
-
},
|
|
88566
|
-
required: ["siteId", "itemId", "parentReference"]
|
|
88567
|
-
},
|
|
88568
|
-
request: {
|
|
88569
|
-
method: "PATCH",
|
|
88570
|
-
path: "/sites/{siteId}/drive/items/{itemId}",
|
|
88571
|
-
body: { parentReference: "{parentReference}", name: "{name}" }
|
|
88572
|
-
},
|
|
88573
|
-
cas: "etag-if-match",
|
|
88574
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88575
|
-
},
|
|
88576
|
-
// ---------- Lists & list items ----------
|
|
88577
|
-
{
|
|
88578
|
-
name: "create.list",
|
|
88579
|
-
class: "mutation",
|
|
88580
|
-
description: "Create a SharePoint list on the site. `displayName` is required; `columns` and `list.template` are optional.",
|
|
88581
|
-
parameters: {
|
|
88582
|
-
type: "object",
|
|
88583
|
-
properties: {
|
|
88584
|
-
siteId: { type: "string" },
|
|
88585
|
-
displayName: { type: "string" },
|
|
88586
|
-
columns: { type: "array", items: { type: "object" } },
|
|
88587
|
-
list: { type: "object" }
|
|
88588
|
-
},
|
|
88589
|
-
required: ["siteId", "displayName"]
|
|
88590
|
-
},
|
|
88591
|
-
request: {
|
|
88592
|
-
method: "POST",
|
|
88593
|
-
path: "/sites/{siteId}/lists",
|
|
88594
|
-
body: { displayName: "{displayName}", columns: "{columns}", list: "{list}" }
|
|
88595
|
-
},
|
|
88596
|
-
cas: "native-idempotency",
|
|
88597
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88598
|
-
},
|
|
88599
|
-
{
|
|
88600
|
-
name: "create.list.item",
|
|
88601
|
-
class: "mutation",
|
|
88602
|
-
description: "Create a new list item. `fields` is the column -> value map.",
|
|
88603
|
-
parameters: {
|
|
88604
|
-
type: "object",
|
|
88605
|
-
properties: {
|
|
88606
|
-
siteId: { type: "string" },
|
|
88607
|
-
listId: { type: "string" },
|
|
88608
|
-
fields: { type: "object" }
|
|
88609
|
-
},
|
|
88610
|
-
required: ["siteId", "listId", "fields"]
|
|
88611
|
-
},
|
|
88612
|
-
request: {
|
|
88613
|
-
method: "POST",
|
|
88614
|
-
path: "/sites/{siteId}/lists/{listId}/items",
|
|
88615
|
-
body: { fields: "{fields}" }
|
|
88616
|
-
},
|
|
88617
|
-
cas: "native-idempotency",
|
|
88618
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88619
|
-
},
|
|
88620
|
-
{
|
|
88621
|
-
name: "update.list.item",
|
|
88622
|
-
class: "mutation",
|
|
88623
|
-
description: "Patch the fields on an existing list item.",
|
|
88624
|
-
parameters: {
|
|
88625
|
-
type: "object",
|
|
88626
|
-
properties: {
|
|
88627
|
-
siteId: { type: "string" },
|
|
88628
|
-
listId: { type: "string" },
|
|
88629
|
-
itemId: { type: "string" },
|
|
88630
|
-
fields: { type: "object" }
|
|
88631
|
-
},
|
|
88632
|
-
required: ["siteId", "listId", "itemId", "fields"]
|
|
88633
|
-
},
|
|
88634
|
-
request: {
|
|
88635
|
-
method: "PATCH",
|
|
88636
|
-
path: "/sites/{siteId}/lists/{listId}/items/{itemId}/fields",
|
|
88637
|
-
body: "{fields}"
|
|
88638
|
-
},
|
|
88639
|
-
cas: "etag-if-match",
|
|
88640
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88641
|
-
},
|
|
88642
|
-
{
|
|
88643
|
-
name: "delete.list.item",
|
|
88644
|
-
class: "mutation",
|
|
88645
|
-
description: "Delete a list item by id.",
|
|
88646
|
-
parameters: {
|
|
88647
|
-
type: "object",
|
|
88648
|
-
properties: {
|
|
88649
|
-
siteId: { type: "string" },
|
|
88650
|
-
listId: { type: "string" },
|
|
88651
|
-
itemId: { type: "string" }
|
|
88652
|
-
},
|
|
88653
|
-
required: ["siteId", "listId", "itemId"]
|
|
88654
|
-
},
|
|
88655
|
-
request: {
|
|
88656
|
-
method: "DELETE",
|
|
88657
|
-
path: "/sites/{siteId}/lists/{listId}/items/{itemId}"
|
|
88658
|
-
},
|
|
88659
|
-
cas: "native-idempotency",
|
|
88660
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88661
|
-
},
|
|
88662
|
-
{
|
|
88663
|
-
name: "find.list.item",
|
|
88664
|
-
class: "read",
|
|
88665
|
-
description: "List items in a SharePoint list, optionally filtered with $filter / $expand=fields($select=...).",
|
|
88666
|
-
parameters: {
|
|
88667
|
-
type: "object",
|
|
88668
|
-
properties: {
|
|
88669
|
-
siteId: { type: "string" },
|
|
88670
|
-
listId: { type: "string" },
|
|
88671
|
-
$filter: { type: "string" },
|
|
88672
|
-
$expand: { type: "string" },
|
|
88673
|
-
$top: { type: "integer" }
|
|
88674
|
-
},
|
|
88675
|
-
required: ["siteId", "listId"]
|
|
88676
|
-
},
|
|
88677
|
-
request: {
|
|
88678
|
-
method: "GET",
|
|
88679
|
-
path: "/sites/{siteId}/lists/{listId}/items",
|
|
88680
|
-
query: { $filter: "{$filter}", $expand: "{$expand}", $top: "{$top}" }
|
|
88681
|
-
},
|
|
88682
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88683
|
-
},
|
|
88684
|
-
// ---------- Pages ----------
|
|
88685
|
-
{
|
|
88686
|
-
name: "publish.page",
|
|
88687
|
-
class: "mutation",
|
|
88688
|
-
description: "Publish a SharePoint site page by page id.",
|
|
88689
|
-
parameters: {
|
|
88690
|
-
type: "object",
|
|
88691
|
-
properties: {
|
|
88692
|
-
siteId: { type: "string" },
|
|
88693
|
-
pageId: { type: "string" }
|
|
88694
|
-
},
|
|
88695
|
-
required: ["siteId", "pageId"]
|
|
88696
|
-
},
|
|
88697
|
-
request: {
|
|
88698
|
-
method: "POST",
|
|
88699
|
-
path: "/sites/{siteId}/pages/{pageId}/microsoft.graph.sitePage/publish"
|
|
88700
|
-
},
|
|
88701
|
-
cas: "native-idempotency",
|
|
88702
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88703
|
-
}
|
|
88704
|
-
]
|
|
88705
|
-
});
|
|
88706
|
-
|
|
88707
88868
|
// src/connectors/adapters/millionverifier.ts
|
|
88708
88869
|
var millionverifierConnector = declarativeRestConnector({
|
|
88709
88870
|
kind: "millionverifier",
|
|
@@ -92605,82 +92766,6 @@ var mindStudioConnector = declarativeRestConnector({
|
|
|
92605
92766
|
]
|
|
92606
92767
|
});
|
|
92607
92768
|
|
|
92608
|
-
// src/connectors/adapters/microsoft-onedrive.ts
|
|
92609
|
-
var microsoftOnedriveConnector = declarativeRestConnector({
|
|
92610
|
-
kind: "microsoft-onedrive",
|
|
92611
|
-
displayName: "Microsoft OneDrive",
|
|
92612
|
-
description: "Upload, download, list files and folders in Microsoft OneDrive.",
|
|
92613
|
-
auth: {
|
|
92614
|
-
kind: "oauth2",
|
|
92615
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
92616
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
92617
|
-
scopes: ["Files.ReadWrite"],
|
|
92618
|
-
clientIdEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_ID",
|
|
92619
|
-
clientSecretEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_SECRET"
|
|
92620
|
-
},
|
|
92621
|
-
category: "storage",
|
|
92622
|
-
defaultConsistencyModel: "authoritative",
|
|
92623
|
-
baseUrl: "https://graph.microsoft.com/v1.0/me/drive",
|
|
92624
|
-
test: { method: "GET", path: "/root" },
|
|
92625
|
-
capabilities: [
|
|
92626
|
-
{
|
|
92627
|
-
name: "files.list",
|
|
92628
|
-
class: "read",
|
|
92629
|
-
description: "List files in OneDrive.",
|
|
92630
|
-
parameters: {
|
|
92631
|
-
type: "object",
|
|
92632
|
-
properties: {
|
|
92633
|
-
folderId: { type: "string", description: "Folder ID to list files from (optional, defaults to root)" }
|
|
92634
|
-
},
|
|
92635
|
-
required: []
|
|
92636
|
-
},
|
|
92637
|
-
request: { method: "GET", path: "/items/{folderId}/children", query: { $select: "id,name,size,webUrl,folder,file" } }
|
|
92638
|
-
},
|
|
92639
|
-
{
|
|
92640
|
-
name: "folders.list",
|
|
92641
|
-
class: "read",
|
|
92642
|
-
description: "List folders in OneDrive.",
|
|
92643
|
-
parameters: {
|
|
92644
|
-
type: "object",
|
|
92645
|
-
properties: {
|
|
92646
|
-
parentId: { type: "string", description: "Parent folder ID (optional, defaults to root)" }
|
|
92647
|
-
},
|
|
92648
|
-
required: []
|
|
92649
|
-
},
|
|
92650
|
-
request: { method: "GET", path: "/items/{parentId}/children", query: { $filter: "folder ne null", $select: "id,name,webUrl" } }
|
|
92651
|
-
},
|
|
92652
|
-
{
|
|
92653
|
-
name: "files.download",
|
|
92654
|
-
class: "read",
|
|
92655
|
-
description: "Download a file from OneDrive.",
|
|
92656
|
-
parameters: {
|
|
92657
|
-
type: "object",
|
|
92658
|
-
properties: {
|
|
92659
|
-
fileId: { type: "string" }
|
|
92660
|
-
},
|
|
92661
|
-
required: ["fileId"]
|
|
92662
|
-
},
|
|
92663
|
-
request: { method: "GET", path: "/items/{fileId}/content" }
|
|
92664
|
-
},
|
|
92665
|
-
{
|
|
92666
|
-
name: "files.upload",
|
|
92667
|
-
class: "mutation",
|
|
92668
|
-
description: "Upload a file to OneDrive.",
|
|
92669
|
-
parameters: {
|
|
92670
|
-
type: "object",
|
|
92671
|
-
properties: {
|
|
92672
|
-
folderId: { type: "string", description: "Destination folder ID (optional, defaults to root)" },
|
|
92673
|
-
fileName: { type: "string", description: "Name of the file to upload" },
|
|
92674
|
-
fileContent: { type: "string", description: "File content (base64-encoded or raw)" }
|
|
92675
|
-
},
|
|
92676
|
-
required: ["fileName", "fileContent"]
|
|
92677
|
-
},
|
|
92678
|
-
request: { method: "PUT", path: "/items/{folderId}:/{fileName}:/content", body: "{fileContent}" },
|
|
92679
|
-
cas: "native-idempotency"
|
|
92680
|
-
}
|
|
92681
|
-
]
|
|
92682
|
-
});
|
|
92683
|
-
|
|
92684
92769
|
// src/connectors/adapters/mongodb.ts
|
|
92685
92770
|
var mongodbConnector = declarativeRestConnector({
|
|
92686
92771
|
kind: "mongodb",
|
|
@@ -93842,21 +93927,31 @@ var nocodbConnector = declarativeRestConnector({
|
|
|
93842
93927
|
});
|
|
93843
93928
|
|
|
93844
93929
|
// src/connectors/adapters/notion.ts
|
|
93845
|
-
var
|
|
93930
|
+
var TOKEN_URL18 = "https://api.notion.com/v1/oauth/token";
|
|
93931
|
+
var NOTION_VERSION = "2022-06-28";
|
|
93932
|
+
var NOTION_SPEC = {
|
|
93846
93933
|
kind: "notion",
|
|
93847
93934
|
displayName: "Notion",
|
|
93848
93935
|
description: "Query and manipulate Notion databases, pages, and blocks.",
|
|
93849
93936
|
auth: {
|
|
93850
93937
|
kind: "oauth2",
|
|
93851
|
-
authorizationUrl: "https://api.notion.com/oauth/authorize",
|
|
93938
|
+
authorizationUrl: "https://api.notion.com/v1/oauth/authorize",
|
|
93852
93939
|
tokenUrl: "https://api.notion.com/v1/oauth/token",
|
|
93853
|
-
scopes
|
|
93940
|
+
// Notion does not use OAuth scopes — the workspace owner picks which
|
|
93941
|
+
// pages/databases the integration sees during install. We declare an
|
|
93942
|
+
// empty scope list so the consent screen renders cleanly.
|
|
93943
|
+
scopes: [],
|
|
93854
93944
|
clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
|
|
93855
|
-
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET"
|
|
93945
|
+
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
|
|
93946
|
+
extraAuthParams: { owner: "user" }
|
|
93856
93947
|
},
|
|
93857
93948
|
category: "doc",
|
|
93858
93949
|
defaultConsistencyModel: "authoritative",
|
|
93859
93950
|
baseUrl: "https://api.notion.com/v1",
|
|
93951
|
+
// Notion rejects any request without a Notion-Version header (400
|
|
93952
|
+
// invalid_request). The declarative executor merges defaultHeaders into
|
|
93953
|
+
// every read/mutation, so the whole surface carries it.
|
|
93954
|
+
defaultHeaders: { "Notion-Version": NOTION_VERSION },
|
|
93860
93955
|
test: { method: "GET", path: "/users/me" },
|
|
93861
93956
|
capabilities: [
|
|
93862
93957
|
{
|
|
@@ -94087,9 +94182,168 @@ var notionConnector = declarativeRestConnector({
|
|
|
94087
94182
|
},
|
|
94088
94183
|
cas: "native-idempotency",
|
|
94089
94184
|
externalEffect: true
|
|
94185
|
+
},
|
|
94186
|
+
{
|
|
94187
|
+
name: "databases.create",
|
|
94188
|
+
class: "mutation",
|
|
94189
|
+
description: "Create a new Notion database underneath a parent page.",
|
|
94190
|
+
parameters: {
|
|
94191
|
+
type: "object",
|
|
94192
|
+
properties: {
|
|
94193
|
+
parentPageId: { type: "string", description: "Parent page id under which to create the database." },
|
|
94194
|
+
title: {
|
|
94195
|
+
type: "array",
|
|
94196
|
+
description: "Notion rich_text array used as the database title."
|
|
94197
|
+
},
|
|
94198
|
+
properties: {
|
|
94199
|
+
type: "object",
|
|
94200
|
+
description: "Schema map \u2014 property name \u2192 Notion property schema."
|
|
94201
|
+
}
|
|
94202
|
+
},
|
|
94203
|
+
required: ["parentPageId", "title", "properties"]
|
|
94204
|
+
},
|
|
94205
|
+
request: {
|
|
94206
|
+
method: "POST",
|
|
94207
|
+
path: "/databases",
|
|
94208
|
+
body: {
|
|
94209
|
+
parent: { type: "page_id", page_id: "{parentPageId}" },
|
|
94210
|
+
title: "{title}",
|
|
94211
|
+
properties: "{properties}"
|
|
94212
|
+
}
|
|
94213
|
+
},
|
|
94214
|
+
cas: "native-idempotency",
|
|
94215
|
+
externalEffect: true
|
|
94216
|
+
},
|
|
94217
|
+
{
|
|
94218
|
+
name: "databases.update",
|
|
94219
|
+
class: "mutation",
|
|
94220
|
+
description: "Update a database title and/or schema.",
|
|
94221
|
+
parameters: {
|
|
94222
|
+
type: "object",
|
|
94223
|
+
properties: {
|
|
94224
|
+
databaseId: { type: "string" },
|
|
94225
|
+
title: { type: "array", description: "Optional new rich_text title." },
|
|
94226
|
+
properties: { type: "object", description: "Optional partial schema update." }
|
|
94227
|
+
},
|
|
94228
|
+
required: ["databaseId"]
|
|
94229
|
+
},
|
|
94230
|
+
request: {
|
|
94231
|
+
method: "PATCH",
|
|
94232
|
+
path: "/databases/{databaseId}",
|
|
94233
|
+
body: { title: "{title}", properties: "{properties}" }
|
|
94234
|
+
},
|
|
94235
|
+
cas: "native-idempotency",
|
|
94236
|
+
externalEffect: true
|
|
94090
94237
|
}
|
|
94091
94238
|
]
|
|
94092
|
-
}
|
|
94239
|
+
};
|
|
94240
|
+
async function databasesUpdate(inv) {
|
|
94241
|
+
const { title, properties } = inv.args;
|
|
94242
|
+
const body = {};
|
|
94243
|
+
if (title !== void 0) body.title = "{title}";
|
|
94244
|
+
if (properties !== void 0) body.properties = "{properties}";
|
|
94245
|
+
const response = await executeRestRequest(
|
|
94246
|
+
NOTION_SPEC,
|
|
94247
|
+
{ method: "PATCH", path: "/databases/{databaseId}", body },
|
|
94248
|
+
inv
|
|
94249
|
+
);
|
|
94250
|
+
return {
|
|
94251
|
+
status: "committed",
|
|
94252
|
+
data: response.data,
|
|
94253
|
+
etagAfter: response.etag,
|
|
94254
|
+
committedAt: Date.now(),
|
|
94255
|
+
idempotentReplay: false
|
|
94256
|
+
};
|
|
94257
|
+
}
|
|
94258
|
+
function withNotionOverrides(base) {
|
|
94259
|
+
return {
|
|
94260
|
+
...base,
|
|
94261
|
+
async executeMutation(inv) {
|
|
94262
|
+
if (inv.capabilityName === "databases.update") return databasesUpdate(inv);
|
|
94263
|
+
return base.executeMutation(inv);
|
|
94264
|
+
}
|
|
94265
|
+
};
|
|
94266
|
+
}
|
|
94267
|
+
var notionConnector = withNotionOverrides(declarativeRestConnector(NOTION_SPEC));
|
|
94268
|
+
function notion(opts) {
|
|
94269
|
+
const { clientId, clientSecret } = opts;
|
|
94270
|
+
return {
|
|
94271
|
+
...withNotionOverrides(declarativeRestConnector(NOTION_SPEC)),
|
|
94272
|
+
/**
|
|
94273
|
+
* Notion's token endpoint follows RFC 6749 with one twist — it REQUIRES
|
|
94274
|
+
* HTTP Basic auth (client_id:client_secret) and does NOT accept the client
|
|
94275
|
+
* credentials in the form body, so we POST inline rather than via the
|
|
94276
|
+
* generic `exchangeAuthorizationCode` helper. The workspace_id/bot_id come
|
|
94277
|
+
* back in the response and we stash them in `metadata` so the agent can
|
|
94278
|
+
* address resources by workspace where useful.
|
|
94279
|
+
*/
|
|
94280
|
+
async exchangeOAuth(input) {
|
|
94281
|
+
if (!clientId || !clientSecret) {
|
|
94282
|
+
throw new Error("Notion OAuth client not configured (NOTION_OAUTH_CLIENT_ID / _SECRET)");
|
|
94283
|
+
}
|
|
94284
|
+
const body = new URLSearchParams({
|
|
94285
|
+
grant_type: "authorization_code",
|
|
94286
|
+
code: input.code,
|
|
94287
|
+
redirect_uri: input.redirectUri,
|
|
94288
|
+
code_verifier: input.codeVerifier
|
|
94289
|
+
});
|
|
94290
|
+
const res = await fetch(TOKEN_URL18, {
|
|
94291
|
+
method: "POST",
|
|
94292
|
+
headers: {
|
|
94293
|
+
authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
|
|
94294
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
94295
|
+
accept: "application/json",
|
|
94296
|
+
"Notion-Version": NOTION_VERSION
|
|
94297
|
+
},
|
|
94298
|
+
body,
|
|
94299
|
+
signal: AbortSignal.timeout(15e3)
|
|
94300
|
+
});
|
|
94301
|
+
if (!res.ok) {
|
|
94302
|
+
const text = await res.text().catch(() => "");
|
|
94303
|
+
throw new Error(`Notion OAuth token exchange failed: ${res.status} \u2014 ${text.slice(0, 200)}`);
|
|
94304
|
+
}
|
|
94305
|
+
const json = await res.json();
|
|
94306
|
+
return {
|
|
94307
|
+
credentials: {
|
|
94308
|
+
kind: "oauth2",
|
|
94309
|
+
accessToken: json.access_token,
|
|
94310
|
+
refreshToken: json.refresh_token
|
|
94311
|
+
},
|
|
94312
|
+
scopes: [],
|
|
94313
|
+
metadata: {
|
|
94314
|
+
botId: json.bot_id,
|
|
94315
|
+
workspaceId: json.workspace_id,
|
|
94316
|
+
workspaceName: json.workspace_name,
|
|
94317
|
+
// Operator picks the database in a follow-up step; default empty.
|
|
94318
|
+
databaseId: ""
|
|
94319
|
+
}
|
|
94320
|
+
};
|
|
94321
|
+
},
|
|
94322
|
+
/** Notion's standard tokens don't expire and don't ship a refresh_token.
|
|
94323
|
+
* If we have neither expiresAt nor refreshToken, treat the existing
|
|
94324
|
+
* access token as durable and return it unchanged. */
|
|
94325
|
+
async refreshToken(creds) {
|
|
94326
|
+
if (creds.kind !== "oauth2" || !creds.refreshToken) {
|
|
94327
|
+
if (creds.kind === "oauth2" && creds.accessToken && !creds.expiresAt) {
|
|
94328
|
+
return creds;
|
|
94329
|
+
}
|
|
94330
|
+
throw new Error("notion.refreshToken: missing refresh token");
|
|
94331
|
+
}
|
|
94332
|
+
const refreshed = await refreshAccessToken({
|
|
94333
|
+
tokenUrl: TOKEN_URL18,
|
|
94334
|
+
clientId,
|
|
94335
|
+
clientSecret,
|
|
94336
|
+
refreshToken: creds.refreshToken
|
|
94337
|
+
});
|
|
94338
|
+
return {
|
|
94339
|
+
kind: "oauth2",
|
|
94340
|
+
accessToken: refreshed.accessToken,
|
|
94341
|
+
refreshToken: refreshed.refreshToken ?? creds.refreshToken,
|
|
94342
|
+
expiresAt: refreshed.expiresIn ? Date.now() + refreshed.expiresIn * 1e3 : void 0
|
|
94343
|
+
};
|
|
94344
|
+
}
|
|
94345
|
+
};
|
|
94346
|
+
}
|
|
94093
94347
|
|
|
94094
94348
|
// src/connectors/adapters/ntfy.ts
|
|
94095
94349
|
var ntfyConnector = declarativeRestConnector({
|
|
@@ -111280,7 +111534,7 @@ var twinLabsConnector = declarativeRestConnector({
|
|
|
111280
111534
|
});
|
|
111281
111535
|
|
|
111282
111536
|
// src/connectors/adapters/twitter.ts
|
|
111283
|
-
var
|
|
111537
|
+
var AUTH_URL18 = "https://twitter.com/i/oauth2/authorize";
|
|
111284
111538
|
var TOKEN_URL19 = "https://api.twitter.com/2/oauth2/token";
|
|
111285
111539
|
var SCOPES14 = ["tweet.read", "tweet.write", "users.read", "like.write", "offline.access"];
|
|
111286
111540
|
var TWITTER_SPEC = {
|
|
@@ -111293,7 +111547,7 @@ var TWITTER_SPEC = {
|
|
|
111293
111547
|
options: [
|
|
111294
111548
|
{
|
|
111295
111549
|
kind: "oauth2",
|
|
111296
|
-
authorizationUrl:
|
|
111550
|
+
authorizationUrl: AUTH_URL18,
|
|
111297
111551
|
tokenUrl: TOKEN_URL19,
|
|
111298
111552
|
scopes: SCOPES14,
|
|
111299
111553
|
clientIdEnv: "TWITTER_OAUTH_CLIENT_ID",
|
|
@@ -118452,7 +118706,6 @@ export {
|
|
|
118452
118706
|
microsoftCalendar,
|
|
118453
118707
|
hubspot,
|
|
118454
118708
|
slack,
|
|
118455
|
-
notionDatabase,
|
|
118456
118709
|
docuseal,
|
|
118457
118710
|
twilioSmsConnector,
|
|
118458
118711
|
phonyConnector,
|
|
@@ -118689,6 +118942,8 @@ export {
|
|
|
118689
118942
|
ghostcmsConnector,
|
|
118690
118943
|
gistlyConnector,
|
|
118691
118944
|
googleSearchConsoleConnector,
|
|
118945
|
+
googleAnalyticsConnector,
|
|
118946
|
+
googleMeetConnector,
|
|
118692
118947
|
youtubeDataConnector,
|
|
118693
118948
|
googleCloudStorageConnector,
|
|
118694
118949
|
googleBigqueryConnector,
|
|
@@ -118766,12 +119021,9 @@ export {
|
|
|
118766
119021
|
microsoftDynamics365BusinessCentralConnector,
|
|
118767
119022
|
microsoft365PlannerConnector,
|
|
118768
119023
|
microsoftPowerBiConnector,
|
|
118769
|
-
microsoftOutlookCalendarConnector,
|
|
118770
119024
|
microsoftOnenoteConnector,
|
|
118771
|
-
microsoftOutlookConnector,
|
|
118772
119025
|
microsoftExcel365Connector,
|
|
118773
119026
|
microsoftTodoConnector,
|
|
118774
|
-
microsoftSharepointConnector,
|
|
118775
119027
|
millionverifierConnector,
|
|
118776
119028
|
mindeeConnector,
|
|
118777
119029
|
mixmaxConnector,
|
|
@@ -118802,12 +119054,12 @@ export {
|
|
|
118802
119054
|
mollieConnector,
|
|
118803
119055
|
metabaseConnector,
|
|
118804
119056
|
mindStudioConnector,
|
|
118805
|
-
microsoftOnedriveConnector,
|
|
118806
119057
|
mongodbConnector,
|
|
118807
119058
|
niftyConnector,
|
|
118808
119059
|
ninjapipeConnector,
|
|
118809
119060
|
nocodbConnector,
|
|
118810
119061
|
notionConnector,
|
|
119062
|
+
notion,
|
|
118811
119063
|
ntfyConnector,
|
|
118812
119064
|
odooConnector,
|
|
118813
119065
|
omniCoConnector,
|
|
@@ -118936,4 +119188,4 @@ export {
|
|
|
118936
119188
|
pipedreamConnector,
|
|
118937
119189
|
adapters_exports
|
|
118938
119190
|
};
|
|
118939
|
-
//# sourceMappingURL=chunk-
|
|
119191
|
+
//# sourceMappingURL=chunk-6MUBOVI4.js.map
|