@tangle-network/agent-integrations 0.38.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.js +3 -3
- package/dist/{chunk-ZMAMOCJZ.js → chunk-6MUBOVI4.js} +1832 -1584
- package/dist/chunk-6MUBOVI4.js.map +1 -0
- package/dist/{chunk-53NQJZAT.js → chunk-IA5GCKM6.js} +2 -3
- package/dist/chunk-IA5GCKM6.js.map +1 -0
- package/dist/{chunk-FC7GL2DI.js → chunk-P3RWMLK3.js} +6 -4
- package/dist/{chunk-FC7GL2DI.js.map → chunk-P3RWMLK3.js.map} +1 -1
- package/dist/connectors/adapters/index.d.ts +87 -94
- package/dist/connectors/adapters/index.js +7 -11
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +7 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -13
- package/dist/mcp.js +3 -3
- package/dist/registry.js +3 -3
- package/dist/runtime.js +3 -3
- package/dist/specs.js +1 -1
- 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-ZMAMOCJZ.js.map +0 -1
|
@@ -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,8 +37077,8 @@ 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
37084
|
clientSecretEnv: "HELLOSIGN_OAUTH_CLIENT_SECRET",
|
|
@@ -37587,7 +37235,7 @@ function hellosign(opts) {
|
|
|
37587
37235
|
throw new Error("Dropbox Sign OAuth client not configured (HELLOSIGN_OAUTH_CLIENT_ID / _SECRET)");
|
|
37588
37236
|
}
|
|
37589
37237
|
const tokens = await exchangeAuthorizationCode({
|
|
37590
|
-
tokenUrl:
|
|
37238
|
+
tokenUrl: TOKEN_URL9,
|
|
37591
37239
|
clientId,
|
|
37592
37240
|
clientSecret,
|
|
37593
37241
|
code: input.code,
|
|
@@ -37610,7 +37258,7 @@ function hellosign(opts) {
|
|
|
37610
37258
|
throw new Error("hellosign.refreshToken: missing refresh token");
|
|
37611
37259
|
}
|
|
37612
37260
|
const refreshed = await refreshAccessToken({
|
|
37613
|
-
tokenUrl:
|
|
37261
|
+
tokenUrl: TOKEN_URL9,
|
|
37614
37262
|
clientId,
|
|
37615
37263
|
clientSecret,
|
|
37616
37264
|
refreshToken: creds.refreshToken
|
|
@@ -37901,7 +37549,7 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
|
|
|
37901
37549
|
throw new CredentialsExpired("Dropbox Sign access token expired and no refresh token", inv?.source.id ?? "");
|
|
37902
37550
|
}
|
|
37903
37551
|
const refreshed = await refreshAccessToken({
|
|
37904
|
-
tokenUrl:
|
|
37552
|
+
tokenUrl: TOKEN_URL9,
|
|
37905
37553
|
clientId,
|
|
37906
37554
|
clientSecret,
|
|
37907
37555
|
refreshToken: creds.refreshToken
|
|
@@ -37920,12 +37568,12 @@ async function ensureFreshAccessToken7(creds, clientId, clientSecret, inv) {
|
|
|
37920
37568
|
|
|
37921
37569
|
// src/connectors/adapters/pandadoc.ts
|
|
37922
37570
|
var SCOPES8 = ["read", "read+write"];
|
|
37923
|
-
var
|
|
37924
|
-
var
|
|
37925
|
-
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";
|
|
37926
37574
|
function pandadoc(opts) {
|
|
37927
37575
|
const { clientId, clientSecret } = opts;
|
|
37928
|
-
const baseUrl = (opts.baseUrl ??
|
|
37576
|
+
const baseUrl = (opts.baseUrl ?? API9).replace(/\/$/, "");
|
|
37929
37577
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
37930
37578
|
const adapter = {
|
|
37931
37579
|
manifest: {
|
|
@@ -37934,8 +37582,8 @@ function pandadoc(opts) {
|
|
|
37934
37582
|
description: "Draft contracts and proposals from PandaDoc templates, send them for signature, poll signing status, and cancel in-flight documents.",
|
|
37935
37583
|
auth: {
|
|
37936
37584
|
kind: "oauth2",
|
|
37937
|
-
authorizationUrl:
|
|
37938
|
-
tokenUrl:
|
|
37585
|
+
authorizationUrl: AUTH_URL10,
|
|
37586
|
+
tokenUrl: TOKEN_URL10,
|
|
37939
37587
|
scopes: SCOPES8,
|
|
37940
37588
|
clientIdEnv: "PANDADOC_OAUTH_CLIENT_ID",
|
|
37941
37589
|
clientSecretEnv: "PANDADOC_OAUTH_CLIENT_SECRET"
|
|
@@ -38083,7 +37731,7 @@ function pandadoc(opts) {
|
|
|
38083
37731
|
throw new Error("PandaDoc OAuth client not configured (PANDADOC_OAUTH_CLIENT_ID / _SECRET)");
|
|
38084
37732
|
}
|
|
38085
37733
|
const tokens = await exchangeAuthorizationCode({
|
|
38086
|
-
tokenUrl:
|
|
37734
|
+
tokenUrl: TOKEN_URL10,
|
|
38087
37735
|
clientId,
|
|
38088
37736
|
clientSecret,
|
|
38089
37737
|
code: input.code,
|
|
@@ -38106,7 +37754,7 @@ function pandadoc(opts) {
|
|
|
38106
37754
|
throw new Error("pandadoc.refreshToken: missing refresh token");
|
|
38107
37755
|
}
|
|
38108
37756
|
const refreshed = await refreshAccessToken({
|
|
38109
|
-
tokenUrl:
|
|
37757
|
+
tokenUrl: TOKEN_URL10,
|
|
38110
37758
|
clientId,
|
|
38111
37759
|
clientSecret,
|
|
38112
37760
|
refreshToken: creds.refreshToken
|
|
@@ -38414,7 +38062,7 @@ async function ensureFreshAccessTokenFromCreds(creds, clientId, clientSecret, on
|
|
|
38414
38062
|
throw new CredentialsExpired("PandaDoc access token expired and no refresh token", "");
|
|
38415
38063
|
}
|
|
38416
38064
|
const refreshed = await refreshAccessToken({
|
|
38417
|
-
tokenUrl:
|
|
38065
|
+
tokenUrl: TOKEN_URL10,
|
|
38418
38066
|
clientId,
|
|
38419
38067
|
clientSecret,
|
|
38420
38068
|
refreshToken: creds.refreshToken
|
|
@@ -38438,9 +38086,9 @@ var SCOPES9 = [
|
|
|
38438
38086
|
"https://www.googleapis.com/auth/documents",
|
|
38439
38087
|
"https://www.googleapis.com/auth/drive.file"
|
|
38440
38088
|
];
|
|
38441
|
-
var
|
|
38442
|
-
var
|
|
38443
|
-
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";
|
|
38444
38092
|
var DRIVE_API = "https://www.googleapis.com/drive/v3";
|
|
38445
38093
|
var EXPORT_MIME = {
|
|
38446
38094
|
pdf: "application/pdf",
|
|
@@ -38464,8 +38112,8 @@ function googleDocs(opts) {
|
|
|
38464
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.",
|
|
38465
38113
|
auth: {
|
|
38466
38114
|
kind: "oauth2",
|
|
38467
|
-
authorizationUrl:
|
|
38468
|
-
tokenUrl:
|
|
38115
|
+
authorizationUrl: AUTH_URL11,
|
|
38116
|
+
tokenUrl: TOKEN_URL11,
|
|
38469
38117
|
scopes: SCOPES9,
|
|
38470
38118
|
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
38471
38119
|
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
@@ -38579,7 +38227,7 @@ function googleDocs(opts) {
|
|
|
38579
38227
|
throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
|
|
38580
38228
|
}
|
|
38581
38229
|
const tokens = await exchangeAuthorizationCode({
|
|
38582
|
-
tokenUrl:
|
|
38230
|
+
tokenUrl: TOKEN_URL11,
|
|
38583
38231
|
clientId,
|
|
38584
38232
|
clientSecret,
|
|
38585
38233
|
code: input.code,
|
|
@@ -38602,7 +38250,7 @@ function googleDocs(opts) {
|
|
|
38602
38250
|
throw new Error("google-docs.refreshToken: missing refresh token");
|
|
38603
38251
|
}
|
|
38604
38252
|
const refreshed = await refreshAccessToken({
|
|
38605
|
-
tokenUrl:
|
|
38253
|
+
tokenUrl: TOKEN_URL11,
|
|
38606
38254
|
clientId,
|
|
38607
38255
|
clientSecret,
|
|
38608
38256
|
refreshToken: creds.refreshToken
|
|
@@ -38656,7 +38304,7 @@ function findAppendIndex(doc) {
|
|
|
38656
38304
|
}
|
|
38657
38305
|
async function getDocument2(inv, accessToken, timeoutMs) {
|
|
38658
38306
|
const { documentId } = inv.args ?? {};
|
|
38659
|
-
const res = await fetch(`${
|
|
38307
|
+
const res = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}`, {
|
|
38660
38308
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38661
38309
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38662
38310
|
});
|
|
@@ -38690,7 +38338,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38690
38338
|
if (!title || typeof title !== "string") {
|
|
38691
38339
|
throw new Error("google-docs create_document: title is required");
|
|
38692
38340
|
}
|
|
38693
|
-
const createRes = await fetch(`${
|
|
38341
|
+
const createRes = await fetch(`${API10}/documents`, {
|
|
38694
38342
|
method: "POST",
|
|
38695
38343
|
headers: {
|
|
38696
38344
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -38710,7 +38358,7 @@ async function createDocument2(inv, accessToken, timeoutMs) {
|
|
|
38710
38358
|
let revisionId = created.revisionId;
|
|
38711
38359
|
if (typeof body === "string" && body.length > 0) {
|
|
38712
38360
|
const insertRes = await fetch(
|
|
38713
|
-
`${
|
|
38361
|
+
`${API10}/documents/${encodeURIComponent(created.documentId)}:batchUpdate`,
|
|
38714
38362
|
{
|
|
38715
38363
|
method: "POST",
|
|
38716
38364
|
headers: {
|
|
@@ -38753,7 +38401,7 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38753
38401
|
if (!text) {
|
|
38754
38402
|
throw new Error("google-docs append_text: text is required");
|
|
38755
38403
|
}
|
|
38756
|
-
const docRes = await fetch(`${
|
|
38404
|
+
const docRes = await fetch(`${API10}/documents/${encodeURIComponent(documentId)}?fields=documentId,revisionId,body(content(endIndex))`, {
|
|
38757
38405
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
38758
38406
|
signal: AbortSignal.timeout(timeoutMs)
|
|
38759
38407
|
});
|
|
@@ -38783,7 +38431,7 @@ async function appendText(inv, accessToken, timeoutMs) {
|
|
|
38783
38431
|
body.writeControl = { requiredRevisionId };
|
|
38784
38432
|
}
|
|
38785
38433
|
const res = await fetch(
|
|
38786
|
-
`${
|
|
38434
|
+
`${API10}/documents/${encodeURIComponent(documentId)}:batchUpdate`,
|
|
38787
38435
|
{
|
|
38788
38436
|
method: "POST",
|
|
38789
38437
|
headers: {
|
|
@@ -38904,7 +38552,7 @@ async function ensureFreshAccessToken9(creds, clientId, clientSecret) {
|
|
|
38904
38552
|
throw new CredentialsExpired("Google Docs access token expired and no refresh token", "");
|
|
38905
38553
|
}
|
|
38906
38554
|
const refreshed = await refreshAccessToken({
|
|
38907
|
-
tokenUrl:
|
|
38555
|
+
tokenUrl: TOKEN_URL11,
|
|
38908
38556
|
clientId,
|
|
38909
38557
|
clientSecret,
|
|
38910
38558
|
refreshToken: creds.refreshToken
|
|
@@ -38922,9 +38570,9 @@ var SCOPES10 = [
|
|
|
38922
38570
|
"https://www.googleapis.com/auth/forms.responses.readonly",
|
|
38923
38571
|
SCOPE_WRITE3
|
|
38924
38572
|
];
|
|
38925
|
-
var
|
|
38926
|
-
var
|
|
38927
|
-
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";
|
|
38928
38576
|
function googleForms(opts) {
|
|
38929
38577
|
const { clientId, clientSecret } = opts;
|
|
38930
38578
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -38935,8 +38583,8 @@ function googleForms(opts) {
|
|
|
38935
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.",
|
|
38936
38584
|
auth: {
|
|
38937
38585
|
kind: "oauth2",
|
|
38938
|
-
authorizationUrl:
|
|
38939
|
-
tokenUrl:
|
|
38586
|
+
authorizationUrl: AUTH_URL12,
|
|
38587
|
+
tokenUrl: TOKEN_URL12,
|
|
38940
38588
|
scopes: SCOPES10,
|
|
38941
38589
|
clientIdEnv: "GOOGLE_OAUTH_CLIENT_ID",
|
|
38942
38590
|
clientSecretEnv: "GOOGLE_OAUTH_CLIENT_SECRET",
|
|
@@ -39080,7 +38728,7 @@ function googleForms(opts) {
|
|
|
39080
38728
|
throw new Error("Google OAuth client not configured (GOOGLE_OAUTH_CLIENT_ID / _SECRET)");
|
|
39081
38729
|
}
|
|
39082
38730
|
const tokens = await exchangeAuthorizationCode({
|
|
39083
|
-
tokenUrl:
|
|
38731
|
+
tokenUrl: TOKEN_URL12,
|
|
39084
38732
|
clientId,
|
|
39085
38733
|
clientSecret,
|
|
39086
38734
|
code: input.code,
|
|
@@ -39103,7 +38751,7 @@ function googleForms(opts) {
|
|
|
39103
38751
|
throw new Error("google-forms.refreshToken: missing refresh token");
|
|
39104
38752
|
}
|
|
39105
38753
|
const refreshed = await refreshAccessToken({
|
|
39106
|
-
tokenUrl:
|
|
38754
|
+
tokenUrl: TOKEN_URL12,
|
|
39107
38755
|
clientId,
|
|
39108
38756
|
clientSecret,
|
|
39109
38757
|
refreshToken: creds.refreshToken
|
|
@@ -39149,7 +38797,7 @@ function flattenAnswers(answers) {
|
|
|
39149
38797
|
async function getForm(inv, accessToken, timeoutMs) {
|
|
39150
38798
|
const { formId } = inv.args ?? {};
|
|
39151
38799
|
if (!formId) throw new Error("google-forms get_form: formId is required");
|
|
39152
|
-
const res = await fetch(`${
|
|
38800
|
+
const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}`, {
|
|
39153
38801
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39154
38802
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39155
38803
|
});
|
|
@@ -39184,7 +38832,7 @@ async function listResponses(inv, accessToken, timeoutMs) {
|
|
|
39184
38832
|
if (pageToken) params.set("pageToken", pageToken);
|
|
39185
38833
|
if (filter) params.set("filter", filter);
|
|
39186
38834
|
const qs = params.toString();
|
|
39187
|
-
const url = `${
|
|
38835
|
+
const url = `${API11}/forms/${encodeURIComponent(formId)}/responses${qs ? `?${qs}` : ""}`;
|
|
39188
38836
|
const res = await fetch(url, {
|
|
39189
38837
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39190
38838
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39221,7 +38869,7 @@ async function getResponse(inv, accessToken, timeoutMs) {
|
|
|
39221
38869
|
if (!formId) throw new Error("google-forms get_response: formId is required");
|
|
39222
38870
|
if (!responseId) throw new Error("google-forms get_response: responseId is required");
|
|
39223
38871
|
const res = await fetch(
|
|
39224
|
-
`${
|
|
38872
|
+
`${API11}/forms/${encodeURIComponent(formId)}/responses/${encodeURIComponent(responseId)}`,
|
|
39225
38873
|
{
|
|
39226
38874
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39227
38875
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39255,7 +38903,7 @@ async function createForm(inv, accessToken, timeoutMs) {
|
|
|
39255
38903
|
if (!title) throw new Error("google-forms create_form: title is required");
|
|
39256
38904
|
const info = { title };
|
|
39257
38905
|
if (documentTitle) info.documentTitle = documentTitle;
|
|
39258
|
-
const res = await fetch(`${
|
|
38906
|
+
const res = await fetch(`${API11}/forms`, {
|
|
39259
38907
|
method: "POST",
|
|
39260
38908
|
headers: {
|
|
39261
38909
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39294,7 +38942,7 @@ async function batchUpdate(inv, accessToken, timeoutMs) {
|
|
|
39294
38942
|
const body = { requests };
|
|
39295
38943
|
if (typeof includeFormInResponse === "boolean") body.includeFormInResponse = includeFormInResponse;
|
|
39296
38944
|
if (writeControl) body.writeControl = writeControl;
|
|
39297
|
-
const res = await fetch(`${
|
|
38945
|
+
const res = await fetch(`${API11}/forms/${encodeURIComponent(formId)}:batchUpdate`, {
|
|
39298
38946
|
method: "POST",
|
|
39299
38947
|
headers: {
|
|
39300
38948
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39334,7 +38982,7 @@ async function ensureFreshAccessToken10(creds, clientId, clientSecret) {
|
|
|
39334
38982
|
throw new CredentialsExpired("Google Forms access token expired and no refresh token", "");
|
|
39335
38983
|
}
|
|
39336
38984
|
const refreshed = await refreshAccessToken({
|
|
39337
|
-
tokenUrl:
|
|
38985
|
+
tokenUrl: TOKEN_URL12,
|
|
39338
38986
|
clientId,
|
|
39339
38987
|
clientSecret,
|
|
39340
38988
|
refreshToken: creds.refreshToken
|
|
@@ -39355,8 +39003,8 @@ var SCOPES11 = [
|
|
|
39355
39003
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
39356
39004
|
"offline_access"
|
|
39357
39005
|
];
|
|
39358
|
-
var
|
|
39359
|
-
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";
|
|
39360
39008
|
var GRAPH = "https://graph.microsoft.com/v1.0";
|
|
39361
39009
|
function microsoftGraph(opts) {
|
|
39362
39010
|
const { clientId, clientSecret } = opts;
|
|
@@ -39367,8 +39015,8 @@ function microsoftGraph(opts) {
|
|
|
39367
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.",
|
|
39368
39016
|
auth: {
|
|
39369
39017
|
kind: "oauth2",
|
|
39370
|
-
authorizationUrl:
|
|
39371
|
-
tokenUrl:
|
|
39018
|
+
authorizationUrl: AUTH_URL13,
|
|
39019
|
+
tokenUrl: TOKEN_URL13,
|
|
39372
39020
|
scopes: SCOPES11,
|
|
39373
39021
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
39374
39022
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -39553,7 +39201,7 @@ function microsoftGraph(opts) {
|
|
|
39553
39201
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
39554
39202
|
}
|
|
39555
39203
|
const tokens = await exchangeAuthorizationCode({
|
|
39556
|
-
tokenUrl:
|
|
39204
|
+
tokenUrl: TOKEN_URL13,
|
|
39557
39205
|
clientId,
|
|
39558
39206
|
clientSecret,
|
|
39559
39207
|
code: input.code,
|
|
@@ -39576,7 +39224,7 @@ function microsoftGraph(opts) {
|
|
|
39576
39224
|
throw new Error("microsoft-graph.refreshToken: missing refresh token");
|
|
39577
39225
|
}
|
|
39578
39226
|
const refreshed = await refreshAccessToken({
|
|
39579
|
-
tokenUrl:
|
|
39227
|
+
tokenUrl: TOKEN_URL13,
|
|
39580
39228
|
clientId,
|
|
39581
39229
|
clientSecret,
|
|
39582
39230
|
refreshToken: creds.refreshToken
|
|
@@ -39618,7 +39266,7 @@ async function ensureFreshAccessToken11(creds, clientId, clientSecret) {
|
|
|
39618
39266
|
throw new CredentialsExpired("Microsoft Graph access token expired and no refresh token", "");
|
|
39619
39267
|
}
|
|
39620
39268
|
const refreshed = await refreshAccessToken({
|
|
39621
|
-
tokenUrl:
|
|
39269
|
+
tokenUrl: TOKEN_URL13,
|
|
39622
39270
|
clientId,
|
|
39623
39271
|
clientSecret,
|
|
39624
39272
|
refreshToken: creds.refreshToken
|
|
@@ -39655,9 +39303,9 @@ var SCOPE_READ2 = "https://graph.microsoft.com/Mail.Read";
|
|
|
39655
39303
|
var SCOPE_SEND2 = "https://graph.microsoft.com/Mail.Send";
|
|
39656
39304
|
var SCOPE_RW = "https://graph.microsoft.com/Mail.ReadWrite";
|
|
39657
39305
|
var SCOPE_OFFLINE = "offline_access";
|
|
39658
|
-
var
|
|
39659
|
-
var
|
|
39660
|
-
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";
|
|
39661
39309
|
function outlookMail(opts) {
|
|
39662
39310
|
const { clientId, clientSecret } = opts;
|
|
39663
39311
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -39669,8 +39317,8 @@ function outlookMail(opts) {
|
|
|
39669
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.",
|
|
39670
39318
|
auth: {
|
|
39671
39319
|
kind: "oauth2",
|
|
39672
|
-
authorizationUrl:
|
|
39673
|
-
tokenUrl:
|
|
39320
|
+
authorizationUrl: AUTH_URL14,
|
|
39321
|
+
tokenUrl: TOKEN_URL14,
|
|
39674
39322
|
scopes,
|
|
39675
39323
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
39676
39324
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -39754,6 +39402,19 @@ function outlookMail(opts) {
|
|
|
39754
39402
|
type: "boolean",
|
|
39755
39403
|
default: false,
|
|
39756
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
|
+
}
|
|
39757
39418
|
}
|
|
39758
39419
|
},
|
|
39759
39420
|
required: ["to", "subject", "body"]
|
|
@@ -39784,6 +39445,19 @@ function outlookMail(opts) {
|
|
|
39784
39445
|
type: "boolean",
|
|
39785
39446
|
default: false,
|
|
39786
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
|
+
}
|
|
39787
39461
|
}
|
|
39788
39462
|
},
|
|
39789
39463
|
required: ["to", "subject", "body"]
|
|
@@ -39806,6 +39480,94 @@ function outlookMail(opts) {
|
|
|
39806
39480
|
},
|
|
39807
39481
|
required: ["notificationUrl"]
|
|
39808
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
|
+
}
|
|
39809
39571
|
}
|
|
39810
39572
|
]
|
|
39811
39573
|
},
|
|
@@ -39813,6 +39575,7 @@ function outlookMail(opts) {
|
|
|
39813
39575
|
const accessToken = await ensureFreshAccessToken12(inv.source.credentials, clientId, clientSecret, inv.onCredentialsRotated);
|
|
39814
39576
|
if (inv.capabilityName === "list_messages") return listMessages2(inv, accessToken, timeoutMs);
|
|
39815
39577
|
if (inv.capabilityName === "read_message") return readMessage2(inv, accessToken, timeoutMs);
|
|
39578
|
+
if (inv.capabilityName === "download_attachment") return downloadAttachment(inv, accessToken, timeoutMs);
|
|
39816
39579
|
throw new Error(`outlook-mail: unknown read capability ${inv.capabilityName}`);
|
|
39817
39580
|
},
|
|
39818
39581
|
async executeMutation(inv) {
|
|
@@ -39821,6 +39584,10 @@ function outlookMail(opts) {
|
|
|
39821
39584
|
if (inv.capabilityName === "send_message") return sendMessage(inv, accessToken, timeoutMs);
|
|
39822
39585
|
if (inv.capabilityName === "create_draft") return createDraft(inv, accessToken, timeoutMs);
|
|
39823
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);
|
|
39824
39591
|
throw new Error(`outlook-mail: unknown mutation capability ${inv.capabilityName}`);
|
|
39825
39592
|
},
|
|
39826
39593
|
async exchangeOAuth(input) {
|
|
@@ -39828,7 +39595,7 @@ function outlookMail(opts) {
|
|
|
39828
39595
|
throw new Error("Outlook Mail OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
39829
39596
|
}
|
|
39830
39597
|
const tokens = await exchangeAuthorizationCode({
|
|
39831
|
-
tokenUrl:
|
|
39598
|
+
tokenUrl: TOKEN_URL14,
|
|
39832
39599
|
clientId,
|
|
39833
39600
|
clientSecret,
|
|
39834
39601
|
code: input.code,
|
|
@@ -39851,7 +39618,7 @@ function outlookMail(opts) {
|
|
|
39851
39618
|
throw new Error("outlook-mail.refreshToken: missing refresh token");
|
|
39852
39619
|
}
|
|
39853
39620
|
const refreshed = await refreshAccessToken({
|
|
39854
|
-
tokenUrl:
|
|
39621
|
+
tokenUrl: TOKEN_URL14,
|
|
39855
39622
|
clientId,
|
|
39856
39623
|
clientSecret,
|
|
39857
39624
|
refreshToken: creds.refreshToken
|
|
@@ -39866,7 +39633,7 @@ function outlookMail(opts) {
|
|
|
39866
39633
|
async test(source) {
|
|
39867
39634
|
try {
|
|
39868
39635
|
const accessToken = await ensureFreshAccessToken12(source.credentials, clientId, clientSecret);
|
|
39869
|
-
const res = await fetch(`${
|
|
39636
|
+
const res = await fetch(`${API12}/me?$select=id,userPrincipalName`, {
|
|
39870
39637
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39871
39638
|
signal: AbortSignal.timeout(8e3)
|
|
39872
39639
|
});
|
|
@@ -39894,7 +39661,7 @@ async function listMessages2(inv, accessToken, timeoutMs) {
|
|
|
39894
39661
|
if (args.skipToken) params.set("$skiptoken", args.skipToken);
|
|
39895
39662
|
const headers = { authorization: `Bearer ${accessToken}` };
|
|
39896
39663
|
if (args.query) headers["ConsistencyLevel"] = "eventual";
|
|
39897
|
-
const res = await fetch(`${
|
|
39664
|
+
const res = await fetch(`${API12}/me/mailFolders/${folder}/messages?${params.toString()}`, {
|
|
39898
39665
|
headers,
|
|
39899
39666
|
signal: AbortSignal.timeout(timeoutMs)
|
|
39900
39667
|
});
|
|
@@ -39928,7 +39695,7 @@ function toMessageSummary2(m) {
|
|
|
39928
39695
|
}
|
|
39929
39696
|
async function readMessage2(inv, accessToken, timeoutMs) {
|
|
39930
39697
|
const { id } = inv.args;
|
|
39931
|
-
const url = `${
|
|
39698
|
+
const url = `${API12}/me/messages/${encodeURIComponent(id)}?$expand=attachments($select=id,name,contentType,size,isInline)`;
|
|
39932
39699
|
const res = await fetch(url, {
|
|
39933
39700
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
39934
39701
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -39971,7 +39738,7 @@ async function readMessage2(inv, accessToken, timeoutMs) {
|
|
|
39971
39738
|
async function sendReply2(inv, accessToken, timeoutMs) {
|
|
39972
39739
|
const { messageId, body, bodyType, replyAll, comment } = inv.args;
|
|
39973
39740
|
const action = replyAll ? "createReplyAll" : "createReply";
|
|
39974
|
-
const draftRes = await fetch(`${
|
|
39741
|
+
const draftRes = await fetch(`${API12}/me/messages/${encodeURIComponent(messageId)}/${action}`, {
|
|
39975
39742
|
method: "POST",
|
|
39976
39743
|
headers: {
|
|
39977
39744
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -39994,7 +39761,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
|
|
|
39994
39761
|
{ name: "X-Tangle-Idempotency-Key", value: inv.idempotencyKey }
|
|
39995
39762
|
]
|
|
39996
39763
|
};
|
|
39997
|
-
const patchRes = await fetch(`${
|
|
39764
|
+
const patchRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}`, {
|
|
39998
39765
|
method: "PATCH",
|
|
39999
39766
|
headers: {
|
|
40000
39767
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40010,7 +39777,7 @@ async function sendReply2(inv, accessToken, timeoutMs) {
|
|
|
40010
39777
|
const text = await patchRes.text().catch(() => "");
|
|
40011
39778
|
throw new Error(`outlook-mail send_reply patch ${patchRes.status}: ${text.slice(0, 200)}`);
|
|
40012
39779
|
}
|
|
40013
|
-
const sendRes = await fetch(`${
|
|
39780
|
+
const sendRes = await fetch(`${API12}/me/messages/${encodeURIComponent(draft.id)}/send`, {
|
|
40014
39781
|
method: "POST",
|
|
40015
39782
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40016
39783
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40057,12 +39824,25 @@ function buildMessagePayload(args, idempotencyKey, cap) {
|
|
|
40057
39824
|
if (args.bcc?.length) {
|
|
40058
39825
|
payload.bccRecipients = args.bcc.map((address) => ({ emailAddress: { address } }));
|
|
40059
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
|
+
}
|
|
40060
39840
|
return payload;
|
|
40061
39841
|
}
|
|
40062
39842
|
async function sendMessage(inv, accessToken, timeoutMs) {
|
|
40063
39843
|
const args = inv.args ?? {};
|
|
40064
39844
|
const message = buildMessagePayload(args, inv.idempotencyKey, "send_message");
|
|
40065
|
-
const res = await fetch(`${
|
|
39845
|
+
const res = await fetch(`${API12}/me/sendMail`, {
|
|
40066
39846
|
method: "POST",
|
|
40067
39847
|
headers: {
|
|
40068
39848
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40092,7 +39872,7 @@ async function sendMessage(inv, accessToken, timeoutMs) {
|
|
|
40092
39872
|
async function createDraft(inv, accessToken, timeoutMs) {
|
|
40093
39873
|
const args = inv.args ?? {};
|
|
40094
39874
|
const message = buildMessagePayload(args, inv.idempotencyKey, "create_draft");
|
|
40095
|
-
const res = await fetch(`${
|
|
39875
|
+
const res = await fetch(`${API12}/me/messages`, {
|
|
40096
39876
|
method: "POST",
|
|
40097
39877
|
headers: {
|
|
40098
39878
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40133,7 +39913,7 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
|
|
|
40133
39913
|
expirationDateTime,
|
|
40134
39914
|
clientState: clientState ?? inv.idempotencyKey
|
|
40135
39915
|
};
|
|
40136
|
-
const res = await fetch(`${
|
|
39916
|
+
const res = await fetch(`${API12}/subscriptions`, {
|
|
40137
39917
|
method: "POST",
|
|
40138
39918
|
headers: {
|
|
40139
39919
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40162,6 +39942,162 @@ async function subscribeFolder(inv, accessToken, timeoutMs) {
|
|
|
40162
39942
|
idempotentReplay: false
|
|
40163
39943
|
};
|
|
40164
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
|
+
}
|
|
40165
40101
|
async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredentialsRotated) {
|
|
40166
40102
|
if (creds.kind !== "oauth2") {
|
|
40167
40103
|
throw new Error("outlook-mail: expected oauth2 credentials");
|
|
@@ -40173,7 +40109,7 @@ async function ensureFreshAccessToken12(creds, clientId, clientSecret, onCredent
|
|
|
40173
40109
|
throw new CredentialsExpired("Outlook Mail access token expired and no refresh token", "");
|
|
40174
40110
|
}
|
|
40175
40111
|
const refreshed = await refreshAccessToken({
|
|
40176
|
-
tokenUrl:
|
|
40112
|
+
tokenUrl: TOKEN_URL14,
|
|
40177
40113
|
clientId,
|
|
40178
40114
|
clientSecret,
|
|
40179
40115
|
refreshToken: creds.refreshToken
|
|
@@ -40201,8 +40137,8 @@ var SCOPES12 = [
|
|
|
40201
40137
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
40202
40138
|
"offline_access"
|
|
40203
40139
|
];
|
|
40204
|
-
var
|
|
40205
|
-
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";
|
|
40206
40142
|
var GRAPH2 = "https://graph.microsoft.com/v1.0";
|
|
40207
40143
|
function microsoftTeams(opts) {
|
|
40208
40144
|
const { clientId, clientSecret } = opts;
|
|
@@ -40213,8 +40149,8 @@ function microsoftTeams(opts) {
|
|
|
40213
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.",
|
|
40214
40150
|
auth: {
|
|
40215
40151
|
kind: "oauth2",
|
|
40216
|
-
authorizationUrl:
|
|
40217
|
-
tokenUrl:
|
|
40152
|
+
authorizationUrl: AUTH_URL15,
|
|
40153
|
+
tokenUrl: TOKEN_URL15,
|
|
40218
40154
|
scopes: SCOPES12,
|
|
40219
40155
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
40220
40156
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -40400,7 +40336,7 @@ function microsoftTeams(opts) {
|
|
|
40400
40336
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
40401
40337
|
}
|
|
40402
40338
|
const tokens = await exchangeAuthorizationCode({
|
|
40403
|
-
tokenUrl:
|
|
40339
|
+
tokenUrl: TOKEN_URL15,
|
|
40404
40340
|
clientId,
|
|
40405
40341
|
clientSecret,
|
|
40406
40342
|
code: input.code,
|
|
@@ -40423,7 +40359,7 @@ function microsoftTeams(opts) {
|
|
|
40423
40359
|
throw new Error("microsoft-teams.refreshToken: missing refresh token");
|
|
40424
40360
|
}
|
|
40425
40361
|
const refreshed = await refreshAccessToken({
|
|
40426
|
-
tokenUrl:
|
|
40362
|
+
tokenUrl: TOKEN_URL15,
|
|
40427
40363
|
clientId,
|
|
40428
40364
|
clientSecret,
|
|
40429
40365
|
refreshToken: creds.refreshToken
|
|
@@ -40465,7 +40401,7 @@ async function ensureFreshAccessToken13(creds, clientId, clientSecret) {
|
|
|
40465
40401
|
throw new CredentialsExpired("Microsoft Teams access token expired and no refresh token", "");
|
|
40466
40402
|
}
|
|
40467
40403
|
const refreshed = await refreshAccessToken({
|
|
40468
|
-
tokenUrl:
|
|
40404
|
+
tokenUrl: TOKEN_URL15,
|
|
40469
40405
|
clientId,
|
|
40470
40406
|
clientSecret,
|
|
40471
40407
|
refreshToken: creds.refreshToken
|
|
@@ -40517,9 +40453,9 @@ function escapeOData2(value) {
|
|
|
40517
40453
|
var SCOPE_READ3 = "https://graph.microsoft.com/Files.Read";
|
|
40518
40454
|
var SCOPE_WRITE4 = "https://graph.microsoft.com/Files.ReadWrite";
|
|
40519
40455
|
var SCOPE_OFFLINE2 = "offline_access";
|
|
40520
|
-
var
|
|
40521
|
-
var
|
|
40522
|
-
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";
|
|
40523
40459
|
function oneDrive(opts) {
|
|
40524
40460
|
const { clientId, clientSecret } = opts;
|
|
40525
40461
|
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
@@ -40531,8 +40467,8 @@ function oneDrive(opts) {
|
|
|
40531
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.",
|
|
40532
40468
|
auth: {
|
|
40533
40469
|
kind: "oauth2",
|
|
40534
|
-
authorizationUrl:
|
|
40535
|
-
tokenUrl:
|
|
40470
|
+
authorizationUrl: AUTH_URL16,
|
|
40471
|
+
tokenUrl: TOKEN_URL16,
|
|
40536
40472
|
scopes,
|
|
40537
40473
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
40538
40474
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -40709,7 +40645,7 @@ function oneDrive(opts) {
|
|
|
40709
40645
|
throw new Error("OneDrive OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
40710
40646
|
}
|
|
40711
40647
|
const tokens = await exchangeAuthorizationCode({
|
|
40712
|
-
tokenUrl:
|
|
40648
|
+
tokenUrl: TOKEN_URL16,
|
|
40713
40649
|
clientId,
|
|
40714
40650
|
clientSecret,
|
|
40715
40651
|
code: input.code,
|
|
@@ -40732,7 +40668,7 @@ function oneDrive(opts) {
|
|
|
40732
40668
|
throw new Error("onedrive.refreshToken: missing refresh token");
|
|
40733
40669
|
}
|
|
40734
40670
|
const refreshed = await refreshAccessToken({
|
|
40735
|
-
tokenUrl:
|
|
40671
|
+
tokenUrl: TOKEN_URL16,
|
|
40736
40672
|
clientId,
|
|
40737
40673
|
clientSecret,
|
|
40738
40674
|
refreshToken: creds.refreshToken
|
|
@@ -40747,7 +40683,7 @@ function oneDrive(opts) {
|
|
|
40747
40683
|
async test(source) {
|
|
40748
40684
|
try {
|
|
40749
40685
|
const accessToken = await ensureFreshAccessToken14(source.credentials, clientId, clientSecret);
|
|
40750
|
-
const res = await fetch(`${
|
|
40686
|
+
const res = await fetch(`${API13}/me/drive?$select=id`, {
|
|
40751
40687
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40752
40688
|
signal: AbortSignal.timeout(8e3)
|
|
40753
40689
|
});
|
|
@@ -40776,7 +40712,7 @@ async function listFiles2(inv, accessToken, timeoutMs) {
|
|
|
40776
40712
|
if (args.query) headers["ConsistencyLevel"] = "eventual";
|
|
40777
40713
|
const path = args.folderId ? `/me/drive/items/${encodeURIComponent(args.folderId)}/children` : "/me/drive/root/children";
|
|
40778
40714
|
const useSearchEndpoint = !!args.query && !args.folderId;
|
|
40779
|
-
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()}`;
|
|
40780
40716
|
const res = await fetch(url, {
|
|
40781
40717
|
headers,
|
|
40782
40718
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40806,7 +40742,7 @@ function stripSearch(params) {
|
|
|
40806
40742
|
async function readFile2(inv, accessToken, timeoutMs) {
|
|
40807
40743
|
const { fileId } = inv.args ?? {};
|
|
40808
40744
|
if (!fileId) throw new Error("onedrive read_file: fileId is required");
|
|
40809
|
-
const metaUrl = `${
|
|
40745
|
+
const metaUrl = `${API13}/me/drive/items/${encodeURIComponent(fileId)}?$select=id,name,eTag,lastModifiedDateTime,size,file,folder`;
|
|
40810
40746
|
const metaRes = await fetch(metaUrl, {
|
|
40811
40747
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40812
40748
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40827,7 +40763,7 @@ async function readFile2(inv, accessToken, timeoutMs) {
|
|
|
40827
40763
|
}
|
|
40828
40764
|
const mimeType = meta.file?.mimeType ?? "application/octet-stream";
|
|
40829
40765
|
const fetchedAt = Date.now();
|
|
40830
|
-
const contentRes = await fetch(`${
|
|
40766
|
+
const contentRes = await fetch(`${API13}/me/drive/items/${encodeURIComponent(fileId)}/content`, {
|
|
40831
40767
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40832
40768
|
signal: AbortSignal.timeout(timeoutMs)
|
|
40833
40769
|
});
|
|
@@ -40880,7 +40816,7 @@ async function watchFolder2(inv, accessToken, timeoutMs) {
|
|
|
40880
40816
|
expirationDateTime,
|
|
40881
40817
|
clientState: clientState ?? inv.idempotencyKey
|
|
40882
40818
|
};
|
|
40883
|
-
const res = await fetch(`${
|
|
40819
|
+
const res = await fetch(`${API13}/subscriptions`, {
|
|
40884
40820
|
method: "POST",
|
|
40885
40821
|
headers: {
|
|
40886
40822
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -40920,7 +40856,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
|
|
|
40920
40856
|
}
|
|
40921
40857
|
const body = encoding === "base64" ? Buffer.from(fileContent, "base64") : Buffer.from(fileContent, "utf-8");
|
|
40922
40858
|
const parentSegment = folderId === "root" ? "/me/drive/root" : `/me/drive/items/${encodeURIComponent(folderId)}`;
|
|
40923
|
-
const url = `${
|
|
40859
|
+
const url = `${API13}${parentSegment}:/${encodeURIComponent(fileName)}:/content`;
|
|
40924
40860
|
const res = await fetch(url, {
|
|
40925
40861
|
method: "PUT",
|
|
40926
40862
|
headers: {
|
|
@@ -40956,7 +40892,7 @@ async function uploadFile3(inv, accessToken, timeoutMs) {
|
|
|
40956
40892
|
async function deleteItem(inv, accessToken, timeoutMs) {
|
|
40957
40893
|
const { itemId } = inv.args ?? {};
|
|
40958
40894
|
if (!itemId) throw new Error("onedrive files.delete: itemId is required");
|
|
40959
|
-
const res = await fetch(`${
|
|
40895
|
+
const res = await fetch(`${API13}${itemPath(itemId)}`, {
|
|
40960
40896
|
method: "DELETE",
|
|
40961
40897
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
40962
40898
|
signal: AbortSignal.timeout(timeoutMs)
|
|
@@ -40994,7 +40930,7 @@ async function moveItem(inv, accessToken, timeoutMs) {
|
|
|
40994
40930
|
body.parentReference = newParentId === "root" ? { path: "/drive/root" } : { id: newParentId };
|
|
40995
40931
|
}
|
|
40996
40932
|
if (newName) body.name = newName;
|
|
40997
|
-
const res = await fetch(`${
|
|
40933
|
+
const res = await fetch(`${API13}${itemPath(itemId)}`, {
|
|
40998
40934
|
method: "PATCH",
|
|
40999
40935
|
headers: {
|
|
41000
40936
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41034,7 +40970,7 @@ async function shareItem(inv, accessToken, timeoutMs) {
|
|
|
41034
40970
|
};
|
|
41035
40971
|
if (password) body.password = password;
|
|
41036
40972
|
if (expirationDateTime) body.expirationDateTime = expirationDateTime;
|
|
41037
|
-
const res = await fetch(`${
|
|
40973
|
+
const res = await fetch(`${API13}${itemPath(itemId)}/createLink`, {
|
|
41038
40974
|
method: "POST",
|
|
41039
40975
|
headers: {
|
|
41040
40976
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41073,7 +41009,7 @@ async function createFolder2(inv, accessToken, timeoutMs) {
|
|
|
41073
41009
|
folder: {},
|
|
41074
41010
|
"@microsoft.graph.conflictBehavior": conflictBehavior ?? "fail"
|
|
41075
41011
|
};
|
|
41076
|
-
const res = await fetch(`${
|
|
41012
|
+
const res = await fetch(`${API13}${parentSegment}`, {
|
|
41077
41013
|
method: "POST",
|
|
41078
41014
|
headers: {
|
|
41079
41015
|
authorization: `Bearer ${accessToken}`,
|
|
@@ -41115,7 +41051,7 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
|
|
|
41115
41051
|
throw new CredentialsExpired("OneDrive access token expired and no refresh token", "");
|
|
41116
41052
|
}
|
|
41117
41053
|
const refreshed = await refreshAccessToken({
|
|
41118
|
-
tokenUrl:
|
|
41054
|
+
tokenUrl: TOKEN_URL16,
|
|
41119
41055
|
clientId,
|
|
41120
41056
|
clientSecret,
|
|
41121
41057
|
refreshToken: creds.refreshToken
|
|
@@ -41134,13 +41070,13 @@ async function ensureFreshAccessToken14(creds, clientId, clientSecret, onCredent
|
|
|
41134
41070
|
|
|
41135
41071
|
// src/connectors/adapters/sharepoint.ts
|
|
41136
41072
|
var SCOPES13 = [
|
|
41137
|
-
"https://graph.microsoft.com/Sites.
|
|
41073
|
+
"https://graph.microsoft.com/Sites.ReadWrite.All",
|
|
41138
41074
|
"https://graph.microsoft.com/Files.ReadWrite.All",
|
|
41139
41075
|
// offline_access is required on v2.0 to receive a refresh_token.
|
|
41140
41076
|
"offline_access"
|
|
41141
41077
|
];
|
|
41142
|
-
var
|
|
41143
|
-
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";
|
|
41144
41080
|
var GRAPH3 = "https://graph.microsoft.com/v1.0";
|
|
41145
41081
|
var MAX_INLINE_BYTES = 4 * 1024 * 1024;
|
|
41146
41082
|
function sharepoint(opts) {
|
|
@@ -41152,8 +41088,8 @@ function sharepoint(opts) {
|
|
|
41152
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.",
|
|
41153
41089
|
auth: {
|
|
41154
41090
|
kind: "oauth2",
|
|
41155
|
-
authorizationUrl:
|
|
41156
|
-
tokenUrl:
|
|
41091
|
+
authorizationUrl: AUTH_URL17,
|
|
41092
|
+
tokenUrl: TOKEN_URL17,
|
|
41157
41093
|
scopes: SCOPES13,
|
|
41158
41094
|
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
41159
41095
|
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
@@ -41356,6 +41292,136 @@ function sharepoint(opts) {
|
|
|
41356
41292
|
},
|
|
41357
41293
|
required: ["siteId", "listId", "fields"]
|
|
41358
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
|
+
}
|
|
41359
41425
|
}
|
|
41360
41426
|
]
|
|
41361
41427
|
},
|
|
@@ -41505,6 +41571,41 @@ function sharepoint(opts) {
|
|
|
41505
41571
|
fetchedAt: Date.now()
|
|
41506
41572
|
};
|
|
41507
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
|
+
}
|
|
41508
41609
|
throw new Error(`sharepoint: unknown read capability ${inv.capabilityName}`);
|
|
41509
41610
|
},
|
|
41510
41611
|
async executeMutation(inv) {
|
|
@@ -41814,6 +41915,211 @@ function sharepoint(opts) {
|
|
|
41814
41915
|
idempotentReplay: false
|
|
41815
41916
|
};
|
|
41816
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
|
+
}
|
|
41817
42123
|
throw new Error(`sharepoint: unknown mutation capability ${inv.capabilityName}`);
|
|
41818
42124
|
},
|
|
41819
42125
|
async exchangeOAuth(input) {
|
|
@@ -41821,7 +42127,7 @@ function sharepoint(opts) {
|
|
|
41821
42127
|
throw new Error("Microsoft OAuth client not configured (MS_OAUTH_CLIENT_ID / _SECRET)");
|
|
41822
42128
|
}
|
|
41823
42129
|
const tokens = await exchangeAuthorizationCode({
|
|
41824
|
-
tokenUrl:
|
|
42130
|
+
tokenUrl: TOKEN_URL17,
|
|
41825
42131
|
clientId,
|
|
41826
42132
|
clientSecret,
|
|
41827
42133
|
code: input.code,
|
|
@@ -41844,7 +42150,7 @@ function sharepoint(opts) {
|
|
|
41844
42150
|
throw new Error("sharepoint.refreshToken: missing refresh token");
|
|
41845
42151
|
}
|
|
41846
42152
|
const refreshed = await refreshAccessToken({
|
|
41847
|
-
tokenUrl:
|
|
42153
|
+
tokenUrl: TOKEN_URL17,
|
|
41848
42154
|
clientId,
|
|
41849
42155
|
clientSecret,
|
|
41850
42156
|
refreshToken: creds.refreshToken
|
|
@@ -41893,7 +42199,7 @@ async function ensureFreshAccessToken15(creds, clientId, clientSecret) {
|
|
|
41893
42199
|
throw new CredentialsExpired("SharePoint access token expired and no refresh token", "");
|
|
41894
42200
|
}
|
|
41895
42201
|
const refreshed = await refreshAccessToken({
|
|
41896
|
-
tokenUrl:
|
|
42202
|
+
tokenUrl: TOKEN_URL17,
|
|
41897
42203
|
clientId,
|
|
41898
42204
|
clientSecret,
|
|
41899
42205
|
refreshToken: creds.refreshToken
|
|
@@ -71101,6 +71407,609 @@ var googleSearchConsoleConnector = declarativeRestConnector({
|
|
|
71101
71407
|
]
|
|
71102
71408
|
});
|
|
71103
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
|
+
|
|
71104
72013
|
// src/connectors/adapters/youtube-data.ts
|
|
71105
72014
|
var youtubeDataConnector = declarativeRestConnector({
|
|
71106
72015
|
kind: "youtube",
|
|
@@ -86864,123 +87773,6 @@ var microsoftPowerBiConnector = declarativeRestConnector({
|
|
|
86864
87773
|
]
|
|
86865
87774
|
});
|
|
86866
87775
|
|
|
86867
|
-
// src/connectors/adapters/microsoft-outlook-calendar.ts
|
|
86868
|
-
var microsoftOutlookCalendarConnector = declarativeRestConnector({
|
|
86869
|
-
kind: "microsoft-outlook-calendar",
|
|
86870
|
-
displayName: "Microsoft Outlook Calendar",
|
|
86871
|
-
description: "Create, list, and delete Outlook/Microsoft 365 calendar events via Microsoft Graph.",
|
|
86872
|
-
auth: {
|
|
86873
|
-
kind: "oauth2",
|
|
86874
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
86875
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
86876
|
-
scopes: ["offline_access", "Calendars.ReadWrite", "User.Read"],
|
|
86877
|
-
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
86878
|
-
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
86879
|
-
},
|
|
86880
|
-
category: "calendar",
|
|
86881
|
-
defaultConsistencyModel: "authoritative",
|
|
86882
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
86883
|
-
test: { method: "GET", path: "/me" },
|
|
86884
|
-
capabilities: [
|
|
86885
|
-
{
|
|
86886
|
-
name: "create.event",
|
|
86887
|
-
class: "mutation",
|
|
86888
|
-
description: "Create a calendar event on the signed-in user's primary calendar, or on a specific calendarId when supplied.",
|
|
86889
|
-
parameters: {
|
|
86890
|
-
type: "object",
|
|
86891
|
-
properties: {
|
|
86892
|
-
calendarId: { type: "string" },
|
|
86893
|
-
subject: { type: "string" },
|
|
86894
|
-
body: { type: "object" },
|
|
86895
|
-
start: { type: "object" },
|
|
86896
|
-
end: { type: "object" },
|
|
86897
|
-
location: { type: "object" },
|
|
86898
|
-
attendees: { type: "array", items: { type: "object" } },
|
|
86899
|
-
isOnlineMeeting: { type: "boolean" },
|
|
86900
|
-
onlineMeetingProvider: { type: "string" },
|
|
86901
|
-
showAs: { type: "string" },
|
|
86902
|
-
sensitivity: { type: "string" },
|
|
86903
|
-
importance: { type: "string" },
|
|
86904
|
-
categories: { type: "array", items: { type: "string" } },
|
|
86905
|
-
reminderMinutesBeforeStart: { type: "integer" },
|
|
86906
|
-
isAllDay: { type: "boolean" },
|
|
86907
|
-
recurrence: { type: "object" },
|
|
86908
|
-
transactionId: { type: "string" }
|
|
86909
|
-
},
|
|
86910
|
-
required: ["subject", "start", "end"]
|
|
86911
|
-
},
|
|
86912
|
-
request: {
|
|
86913
|
-
method: "POST",
|
|
86914
|
-
path: "/me/calendars/{calendarId}/events",
|
|
86915
|
-
body: {
|
|
86916
|
-
subject: "{subject}",
|
|
86917
|
-
body: "{body}",
|
|
86918
|
-
start: "{start}",
|
|
86919
|
-
end: "{end}",
|
|
86920
|
-
location: "{location}",
|
|
86921
|
-
attendees: "{attendees}",
|
|
86922
|
-
isOnlineMeeting: "{isOnlineMeeting}",
|
|
86923
|
-
onlineMeetingProvider: "{onlineMeetingProvider}",
|
|
86924
|
-
showAs: "{showAs}",
|
|
86925
|
-
sensitivity: "{sensitivity}",
|
|
86926
|
-
importance: "{importance}",
|
|
86927
|
-
categories: "{categories}",
|
|
86928
|
-
reminderMinutesBeforeStart: "{reminderMinutesBeforeStart}",
|
|
86929
|
-
isAllDay: "{isAllDay}",
|
|
86930
|
-
recurrence: "{recurrence}",
|
|
86931
|
-
transactionId: "{transactionId}"
|
|
86932
|
-
}
|
|
86933
|
-
},
|
|
86934
|
-
cas: "native-idempotency",
|
|
86935
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86936
|
-
},
|
|
86937
|
-
{
|
|
86938
|
-
name: "delete.event",
|
|
86939
|
-
class: "mutation",
|
|
86940
|
-
description: "Delete a calendar event by id from the signed-in user mailbox.",
|
|
86941
|
-
parameters: {
|
|
86942
|
-
type: "object",
|
|
86943
|
-
properties: { eventId: { type: "string" } },
|
|
86944
|
-
required: ["eventId"]
|
|
86945
|
-
},
|
|
86946
|
-
request: { method: "DELETE", path: "/me/events/{eventId}" },
|
|
86947
|
-
cas: "native-idempotency",
|
|
86948
|
-
externalEffect: true,
|
|
86949
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86950
|
-
},
|
|
86951
|
-
{
|
|
86952
|
-
name: "list.events",
|
|
86953
|
-
class: "read",
|
|
86954
|
-
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.",
|
|
86955
|
-
parameters: {
|
|
86956
|
-
type: "object",
|
|
86957
|
-
properties: {
|
|
86958
|
-
calendarId: { type: "string" },
|
|
86959
|
-
$top: { type: "integer" },
|
|
86960
|
-
$skip: { type: "integer" },
|
|
86961
|
-
$filter: { type: "string" },
|
|
86962
|
-
$select: { type: "string" },
|
|
86963
|
-
$orderby: { type: "string" },
|
|
86964
|
-
$search: { type: "string" }
|
|
86965
|
-
}
|
|
86966
|
-
},
|
|
86967
|
-
request: {
|
|
86968
|
-
method: "GET",
|
|
86969
|
-
path: "/me/calendars/{calendarId}/events",
|
|
86970
|
-
query: {
|
|
86971
|
-
$top: "{$top}",
|
|
86972
|
-
$skip: "{$skip}",
|
|
86973
|
-
$filter: "{$filter}",
|
|
86974
|
-
$select: "{$select}",
|
|
86975
|
-
$orderby: "{$orderby}",
|
|
86976
|
-
$search: "{$search}"
|
|
86977
|
-
}
|
|
86978
|
-
},
|
|
86979
|
-
requiredScopes: ["Calendars.ReadWrite"]
|
|
86980
|
-
}
|
|
86981
|
-
]
|
|
86982
|
-
});
|
|
86983
|
-
|
|
86984
87776
|
// src/connectors/adapters/microsoft-onenote.ts
|
|
86985
87777
|
var microsoftOnenoteConnector = declarativeRestConnector({
|
|
86986
87778
|
kind: "microsoft-onenote",
|
|
@@ -87200,299 +87992,6 @@ var microsoftOnenoteConnector = declarativeRestConnector({
|
|
|
87200
87992
|
]
|
|
87201
87993
|
});
|
|
87202
87994
|
|
|
87203
|
-
// src/connectors/adapters/microsoft-outlook.ts
|
|
87204
|
-
var microsoftOutlookConnector = declarativeRestConnector({
|
|
87205
|
-
kind: "microsoft-outlook",
|
|
87206
|
-
displayName: "Microsoft Outlook",
|
|
87207
|
-
description: "Send, draft, reply to, forward, search, label, and organize email in the signed-in user's Outlook mailbox via Microsoft Graph.",
|
|
87208
|
-
auth: {
|
|
87209
|
-
kind: "oauth2",
|
|
87210
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
87211
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
87212
|
-
scopes: [
|
|
87213
|
-
"offline_access",
|
|
87214
|
-
"User.Read",
|
|
87215
|
-
"Mail.ReadWrite",
|
|
87216
|
-
"Mail.Send",
|
|
87217
|
-
"MailboxSettings.Read"
|
|
87218
|
-
],
|
|
87219
|
-
clientIdEnv: "MS_OAUTH_CLIENT_ID",
|
|
87220
|
-
clientSecretEnv: "MS_OAUTH_CLIENT_SECRET"
|
|
87221
|
-
},
|
|
87222
|
-
category: "comms",
|
|
87223
|
-
defaultConsistencyModel: "authoritative",
|
|
87224
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
87225
|
-
test: { method: "GET", path: "/me" },
|
|
87226
|
-
capabilities: [
|
|
87227
|
-
{
|
|
87228
|
-
name: "email.send",
|
|
87229
|
-
class: "mutation",
|
|
87230
|
-
description: "Send an email immediately from the signed-in user's mailbox. Optionally saves the sent message to the Sent Items folder.",
|
|
87231
|
-
parameters: {
|
|
87232
|
-
type: "object",
|
|
87233
|
-
properties: {
|
|
87234
|
-
subject: { type: "string" },
|
|
87235
|
-
body: { type: "object" },
|
|
87236
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87237
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87238
|
-
bccRecipients: { type: "array", items: { type: "object" } },
|
|
87239
|
-
attachments: { type: "array", items: { type: "object" } },
|
|
87240
|
-
saveToSentItems: { type: "boolean" }
|
|
87241
|
-
},
|
|
87242
|
-
required: ["subject", "body", "toRecipients"]
|
|
87243
|
-
},
|
|
87244
|
-
request: {
|
|
87245
|
-
method: "POST",
|
|
87246
|
-
path: "/me/sendMail",
|
|
87247
|
-
body: {
|
|
87248
|
-
message: {
|
|
87249
|
-
subject: "{subject}",
|
|
87250
|
-
body: "{body}",
|
|
87251
|
-
toRecipients: "{toRecipients}",
|
|
87252
|
-
ccRecipients: "{ccRecipients}",
|
|
87253
|
-
bccRecipients: "{bccRecipients}",
|
|
87254
|
-
attachments: "{attachments}"
|
|
87255
|
-
},
|
|
87256
|
-
saveToSentItems: "{saveToSentItems}"
|
|
87257
|
-
}
|
|
87258
|
-
},
|
|
87259
|
-
cas: "none",
|
|
87260
|
-
externalEffect: true,
|
|
87261
|
-
requiredScopes: ["Mail.Send"]
|
|
87262
|
-
},
|
|
87263
|
-
{
|
|
87264
|
-
name: "email.draft.create",
|
|
87265
|
-
class: "mutation",
|
|
87266
|
-
description: "Create a draft email in the signed-in user mailbox without sending it.",
|
|
87267
|
-
parameters: {
|
|
87268
|
-
type: "object",
|
|
87269
|
-
properties: {
|
|
87270
|
-
subject: { type: "string" },
|
|
87271
|
-
body: { type: "object" },
|
|
87272
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87273
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87274
|
-
bccRecipients: { type: "array", items: { type: "object" } },
|
|
87275
|
-
importance: { type: "string" },
|
|
87276
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87277
|
-
},
|
|
87278
|
-
required: ["subject", "body"]
|
|
87279
|
-
},
|
|
87280
|
-
request: {
|
|
87281
|
-
method: "POST",
|
|
87282
|
-
path: "/me/messages",
|
|
87283
|
-
body: {
|
|
87284
|
-
subject: "{subject}",
|
|
87285
|
-
body: "{body}",
|
|
87286
|
-
toRecipients: "{toRecipients}",
|
|
87287
|
-
ccRecipients: "{ccRecipients}",
|
|
87288
|
-
bccRecipients: "{bccRecipients}",
|
|
87289
|
-
importance: "{importance}",
|
|
87290
|
-
categories: "{categories}"
|
|
87291
|
-
}
|
|
87292
|
-
},
|
|
87293
|
-
cas: "native-idempotency",
|
|
87294
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87295
|
-
},
|
|
87296
|
-
{
|
|
87297
|
-
name: "email.draft.send",
|
|
87298
|
-
class: "mutation",
|
|
87299
|
-
description: "Send a previously created draft message by id.",
|
|
87300
|
-
parameters: {
|
|
87301
|
-
type: "object",
|
|
87302
|
-
properties: { messageId: { type: "string" } },
|
|
87303
|
-
required: ["messageId"]
|
|
87304
|
-
},
|
|
87305
|
-
request: { method: "POST", path: "/me/messages/{messageId}/send" },
|
|
87306
|
-
cas: "none",
|
|
87307
|
-
externalEffect: true,
|
|
87308
|
-
requiredScopes: ["Mail.Send"]
|
|
87309
|
-
},
|
|
87310
|
-
{
|
|
87311
|
-
name: "email.reply",
|
|
87312
|
-
class: "mutation",
|
|
87313
|
-
description: "Reply to an existing message. When comment is provided alone, Graph generates the reply body; when message is provided, it overrides recipients/body.",
|
|
87314
|
-
parameters: {
|
|
87315
|
-
type: "object",
|
|
87316
|
-
properties: {
|
|
87317
|
-
messageId: { type: "string" },
|
|
87318
|
-
comment: { type: "string" },
|
|
87319
|
-
message: { type: "object" }
|
|
87320
|
-
},
|
|
87321
|
-
required: ["messageId"]
|
|
87322
|
-
},
|
|
87323
|
-
request: {
|
|
87324
|
-
method: "POST",
|
|
87325
|
-
path: "/me/messages/{messageId}/reply",
|
|
87326
|
-
body: { comment: "{comment}", message: "{message}" }
|
|
87327
|
-
},
|
|
87328
|
-
cas: "none",
|
|
87329
|
-
externalEffect: true,
|
|
87330
|
-
requiredScopes: ["Mail.Send"]
|
|
87331
|
-
},
|
|
87332
|
-
{
|
|
87333
|
-
name: "email.forward",
|
|
87334
|
-
class: "mutation",
|
|
87335
|
-
description: "Forward an existing message to one or more recipients with an optional comment.",
|
|
87336
|
-
parameters: {
|
|
87337
|
-
type: "object",
|
|
87338
|
-
properties: {
|
|
87339
|
-
messageId: { type: "string" },
|
|
87340
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87341
|
-
comment: { type: "string" }
|
|
87342
|
-
},
|
|
87343
|
-
required: ["messageId", "toRecipients"]
|
|
87344
|
-
},
|
|
87345
|
-
request: {
|
|
87346
|
-
method: "POST",
|
|
87347
|
-
path: "/me/messages/{messageId}/forward",
|
|
87348
|
-
body: { toRecipients: "{toRecipients}", comment: "{comment}" }
|
|
87349
|
-
},
|
|
87350
|
-
cas: "none",
|
|
87351
|
-
externalEffect: true,
|
|
87352
|
-
requiredScopes: ["Mail.Send"]
|
|
87353
|
-
},
|
|
87354
|
-
{
|
|
87355
|
-
name: "email.move",
|
|
87356
|
-
class: "mutation",
|
|
87357
|
-
description: "Move a message to a destination mail folder by id (or well-known name like inbox/archive).",
|
|
87358
|
-
parameters: {
|
|
87359
|
-
type: "object",
|
|
87360
|
-
properties: {
|
|
87361
|
-
messageId: { type: "string" },
|
|
87362
|
-
destinationId: { type: "string" }
|
|
87363
|
-
},
|
|
87364
|
-
required: ["messageId", "destinationId"]
|
|
87365
|
-
},
|
|
87366
|
-
request: {
|
|
87367
|
-
method: "POST",
|
|
87368
|
-
path: "/me/messages/{messageId}/move",
|
|
87369
|
-
body: { destinationId: "{destinationId}" }
|
|
87370
|
-
},
|
|
87371
|
-
cas: "native-idempotency",
|
|
87372
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87373
|
-
},
|
|
87374
|
-
{
|
|
87375
|
-
name: "email.label.add",
|
|
87376
|
-
class: "mutation",
|
|
87377
|
-
description: "Tag a message with one or more Outlook categories (labels). Pass the desired full set; Graph replaces the categories array.",
|
|
87378
|
-
parameters: {
|
|
87379
|
-
type: "object",
|
|
87380
|
-
properties: {
|
|
87381
|
-
messageId: { type: "string" },
|
|
87382
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87383
|
-
},
|
|
87384
|
-
required: ["messageId", "categories"]
|
|
87385
|
-
},
|
|
87386
|
-
request: {
|
|
87387
|
-
method: "PATCH",
|
|
87388
|
-
path: "/me/messages/{messageId}",
|
|
87389
|
-
body: { categories: "{categories}" }
|
|
87390
|
-
},
|
|
87391
|
-
cas: "optimistic-read-verify",
|
|
87392
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87393
|
-
},
|
|
87394
|
-
{
|
|
87395
|
-
name: "email.label.remove",
|
|
87396
|
-
class: "mutation",
|
|
87397
|
-
description: "Remove labels from a message by writing the surviving categories array. Caller computes the remaining set and supplies it explicitly.",
|
|
87398
|
-
parameters: {
|
|
87399
|
-
type: "object",
|
|
87400
|
-
properties: {
|
|
87401
|
-
messageId: { type: "string" },
|
|
87402
|
-
categories: { type: "array", items: { type: "string" } }
|
|
87403
|
-
},
|
|
87404
|
-
required: ["messageId", "categories"]
|
|
87405
|
-
},
|
|
87406
|
-
request: {
|
|
87407
|
-
method: "PATCH",
|
|
87408
|
-
path: "/me/messages/{messageId}",
|
|
87409
|
-
body: { categories: "{categories}" }
|
|
87410
|
-
},
|
|
87411
|
-
cas: "optimistic-read-verify",
|
|
87412
|
-
externalEffect: true,
|
|
87413
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87414
|
-
},
|
|
87415
|
-
{
|
|
87416
|
-
name: "email.find",
|
|
87417
|
-
class: "read",
|
|
87418
|
-
description: "Search messages in a folder using OData $search/$filter with $top, $select, $orderby. Folder defaults to the well-known inbox if omitted.",
|
|
87419
|
-
parameters: {
|
|
87420
|
-
type: "object",
|
|
87421
|
-
properties: {
|
|
87422
|
-
mailFolderId: { type: "string" },
|
|
87423
|
-
$search: { type: "string" },
|
|
87424
|
-
$filter: { type: "string" },
|
|
87425
|
-
$select: { type: "string" },
|
|
87426
|
-
$top: { type: "integer" },
|
|
87427
|
-
$orderby: { type: "string" }
|
|
87428
|
-
}
|
|
87429
|
-
},
|
|
87430
|
-
request: {
|
|
87431
|
-
method: "GET",
|
|
87432
|
-
path: "/me/mailFolders/{mailFolderId}/messages",
|
|
87433
|
-
query: {
|
|
87434
|
-
$search: "{$search}",
|
|
87435
|
-
$filter: "{$filter}",
|
|
87436
|
-
$select: "{$select}",
|
|
87437
|
-
$top: "{$top}",
|
|
87438
|
-
$orderby: "{$orderby}"
|
|
87439
|
-
}
|
|
87440
|
-
},
|
|
87441
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87442
|
-
},
|
|
87443
|
-
{
|
|
87444
|
-
name: "email.attachment.download",
|
|
87445
|
-
class: "read",
|
|
87446
|
-
description: "Read an attachment record (metadata plus base64 contentBytes for file attachments) for a message by attachment id.",
|
|
87447
|
-
parameters: {
|
|
87448
|
-
type: "object",
|
|
87449
|
-
properties: {
|
|
87450
|
-
messageId: { type: "string" },
|
|
87451
|
-
attachmentId: { type: "string" }
|
|
87452
|
-
},
|
|
87453
|
-
required: ["messageId", "attachmentId"]
|
|
87454
|
-
},
|
|
87455
|
-
request: {
|
|
87456
|
-
method: "GET",
|
|
87457
|
-
path: "/me/messages/{messageId}/attachments/{attachmentId}"
|
|
87458
|
-
},
|
|
87459
|
-
requiredScopes: ["Mail.ReadWrite"]
|
|
87460
|
-
},
|
|
87461
|
-
{
|
|
87462
|
-
name: "email.approval.request",
|
|
87463
|
-
class: "mutation",
|
|
87464
|
-
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.",
|
|
87465
|
-
parameters: {
|
|
87466
|
-
type: "object",
|
|
87467
|
-
properties: {
|
|
87468
|
-
subject: { type: "string" },
|
|
87469
|
-
body: { type: "object" },
|
|
87470
|
-
toRecipients: { type: "array", items: { type: "object" } },
|
|
87471
|
-
ccRecipients: { type: "array", items: { type: "object" } },
|
|
87472
|
-
saveToSentItems: { type: "boolean" }
|
|
87473
|
-
},
|
|
87474
|
-
required: ["subject", "body", "toRecipients"]
|
|
87475
|
-
},
|
|
87476
|
-
request: {
|
|
87477
|
-
method: "POST",
|
|
87478
|
-
path: "/me/sendMail",
|
|
87479
|
-
body: {
|
|
87480
|
-
message: {
|
|
87481
|
-
subject: "{subject}",
|
|
87482
|
-
body: "{body}",
|
|
87483
|
-
toRecipients: "{toRecipients}",
|
|
87484
|
-
ccRecipients: "{ccRecipients}"
|
|
87485
|
-
},
|
|
87486
|
-
saveToSentItems: "{saveToSentItems}"
|
|
87487
|
-
}
|
|
87488
|
-
},
|
|
87489
|
-
cas: "none",
|
|
87490
|
-
externalEffect: true,
|
|
87491
|
-
requiredScopes: ["Mail.Send"]
|
|
87492
|
-
}
|
|
87493
|
-
]
|
|
87494
|
-
});
|
|
87495
|
-
|
|
87496
87995
|
// src/connectors/adapters/microsoft-excel-365.ts
|
|
87497
87996
|
var microsoftExcel365Connector = declarativeRestConnector({
|
|
87498
87997
|
kind: "microsoft-excel-365",
|
|
@@ -88366,348 +88865,6 @@ var microsoftTodoConnector = declarativeRestConnector({
|
|
|
88366
88865
|
]
|
|
88367
88866
|
});
|
|
88368
88867
|
|
|
88369
|
-
// src/connectors/adapters/microsoft-sharepoint.ts
|
|
88370
|
-
var microsoftSharepointConnector = declarativeRestConnector({
|
|
88371
|
-
kind: "microsoft-sharepoint",
|
|
88372
|
-
displayName: "Microsoft SharePoint",
|
|
88373
|
-
description: "Read SharePoint site metadata, list items, and files; create folders, lists, list items, and pages via Microsoft Graph.",
|
|
88374
|
-
auth: {
|
|
88375
|
-
kind: "oauth2",
|
|
88376
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
88377
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
88378
|
-
scopes: [
|
|
88379
|
-
"offline_access",
|
|
88380
|
-
"Sites.ReadWrite.All",
|
|
88381
|
-
"Files.ReadWrite.All"
|
|
88382
|
-
],
|
|
88383
|
-
clientIdEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_ID",
|
|
88384
|
-
clientSecretEnv: "MICROSOFT_SHAREPOINT_OAUTH_CLIENT_SECRET"
|
|
88385
|
-
},
|
|
88386
|
-
category: "storage",
|
|
88387
|
-
defaultConsistencyModel: "authoritative",
|
|
88388
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
88389
|
-
test: { method: "GET", path: "/sites/root" },
|
|
88390
|
-
capabilities: [
|
|
88391
|
-
// ---------- Sites ----------
|
|
88392
|
-
{
|
|
88393
|
-
name: "find.site",
|
|
88394
|
-
class: "read",
|
|
88395
|
-
description: "Search SharePoint sites by display name or keyword (Graph $search).",
|
|
88396
|
-
parameters: {
|
|
88397
|
-
type: "object",
|
|
88398
|
-
properties: {
|
|
88399
|
-
search: { type: "string" },
|
|
88400
|
-
$top: { type: "integer" }
|
|
88401
|
-
},
|
|
88402
|
-
required: ["search"]
|
|
88403
|
-
},
|
|
88404
|
-
request: {
|
|
88405
|
-
method: "GET",
|
|
88406
|
-
path: "/sites",
|
|
88407
|
-
query: { search: "{search}", $top: "{$top}" }
|
|
88408
|
-
},
|
|
88409
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88410
|
-
},
|
|
88411
|
-
{
|
|
88412
|
-
name: "get.site.information",
|
|
88413
|
-
class: "read",
|
|
88414
|
-
description: "Read the metadata for a SharePoint site by site id.",
|
|
88415
|
-
parameters: {
|
|
88416
|
-
type: "object",
|
|
88417
|
-
properties: { siteId: { type: "string" } },
|
|
88418
|
-
required: ["siteId"]
|
|
88419
|
-
},
|
|
88420
|
-
request: { method: "GET", path: "/sites/{siteId}" },
|
|
88421
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88422
|
-
},
|
|
88423
|
-
// ---------- Folders / files ----------
|
|
88424
|
-
{
|
|
88425
|
-
name: "create.folder",
|
|
88426
|
-
class: "mutation",
|
|
88427
|
-
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).",
|
|
88428
|
-
parameters: {
|
|
88429
|
-
type: "object",
|
|
88430
|
-
properties: {
|
|
88431
|
-
siteId: { type: "string" },
|
|
88432
|
-
parentItemId: { type: "string" },
|
|
88433
|
-
name: { type: "string" },
|
|
88434
|
-
conflictBehavior: { type: "string" }
|
|
88435
|
-
},
|
|
88436
|
-
required: ["siteId", "parentItemId", "name"]
|
|
88437
|
-
},
|
|
88438
|
-
request: {
|
|
88439
|
-
method: "POST",
|
|
88440
|
-
path: "/sites/{siteId}/drive/items/{parentItemId}/children",
|
|
88441
|
-
body: {
|
|
88442
|
-
name: "{name}",
|
|
88443
|
-
folder: {},
|
|
88444
|
-
"@microsoft.graph.conflictBehavior": "{conflictBehavior}"
|
|
88445
|
-
}
|
|
88446
|
-
},
|
|
88447
|
-
cas: "native-idempotency",
|
|
88448
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88449
|
-
},
|
|
88450
|
-
{
|
|
88451
|
-
name: "get.folder.contents",
|
|
88452
|
-
class: "read",
|
|
88453
|
-
description: "List the children of a folder in a site drive.",
|
|
88454
|
-
parameters: {
|
|
88455
|
-
type: "object",
|
|
88456
|
-
properties: {
|
|
88457
|
-
siteId: { type: "string" },
|
|
88458
|
-
itemId: { type: "string" },
|
|
88459
|
-
$top: { type: "integer" },
|
|
88460
|
-
$select: { type: "string" }
|
|
88461
|
-
},
|
|
88462
|
-
required: ["siteId", "itemId"]
|
|
88463
|
-
},
|
|
88464
|
-
request: {
|
|
88465
|
-
method: "GET",
|
|
88466
|
-
path: "/sites/{siteId}/drive/items/{itemId}/children",
|
|
88467
|
-
query: { $top: "{$top}", $select: "{$select}" }
|
|
88468
|
-
},
|
|
88469
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88470
|
-
},
|
|
88471
|
-
{
|
|
88472
|
-
name: "find.file",
|
|
88473
|
-
class: "read",
|
|
88474
|
-
description: "Search drive items inside a site drive by name or content (Graph drive search).",
|
|
88475
|
-
parameters: {
|
|
88476
|
-
type: "object",
|
|
88477
|
-
properties: {
|
|
88478
|
-
siteId: { type: "string" },
|
|
88479
|
-
query: { type: "string" },
|
|
88480
|
-
$top: { type: "integer" }
|
|
88481
|
-
},
|
|
88482
|
-
required: ["siteId", "query"]
|
|
88483
|
-
},
|
|
88484
|
-
request: {
|
|
88485
|
-
method: "GET",
|
|
88486
|
-
path: "/sites/{siteId}/drive/root/search(q='{query}')",
|
|
88487
|
-
query: { $top: "{$top}" }
|
|
88488
|
-
},
|
|
88489
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88490
|
-
},
|
|
88491
|
-
{
|
|
88492
|
-
name: "upload.file",
|
|
88493
|
-
class: "mutation",
|
|
88494
|
-
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.",
|
|
88495
|
-
parameters: {
|
|
88496
|
-
type: "object",
|
|
88497
|
-
properties: {
|
|
88498
|
-
siteId: { type: "string" },
|
|
88499
|
-
parentItemId: { type: "string" },
|
|
88500
|
-
fileName: { type: "string" },
|
|
88501
|
-
content: { type: "string" },
|
|
88502
|
-
conflictBehavior: { type: "string" }
|
|
88503
|
-
},
|
|
88504
|
-
required: ["siteId", "parentItemId", "fileName", "content"]
|
|
88505
|
-
},
|
|
88506
|
-
request: {
|
|
88507
|
-
method: "PUT",
|
|
88508
|
-
path: "/sites/{siteId}/drive/items/{parentItemId}:/{fileName}:/content",
|
|
88509
|
-
body: "{content}"
|
|
88510
|
-
},
|
|
88511
|
-
cas: "optimistic-read-verify",
|
|
88512
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88513
|
-
},
|
|
88514
|
-
{
|
|
88515
|
-
name: "copy.item",
|
|
88516
|
-
class: "mutation",
|
|
88517
|
-
description: "Copy a drive item into another drive. The destination is identified by a parentReference (driveId + id) and an optional new name.",
|
|
88518
|
-
parameters: {
|
|
88519
|
-
type: "object",
|
|
88520
|
-
properties: {
|
|
88521
|
-
siteId: { type: "string" },
|
|
88522
|
-
itemId: { type: "string" },
|
|
88523
|
-
parentReference: { type: "object" },
|
|
88524
|
-
name: { type: "string" }
|
|
88525
|
-
},
|
|
88526
|
-
required: ["siteId", "itemId", "parentReference"]
|
|
88527
|
-
},
|
|
88528
|
-
request: {
|
|
88529
|
-
method: "POST",
|
|
88530
|
-
path: "/sites/{siteId}/drive/items/{itemId}/copy",
|
|
88531
|
-
body: { parentReference: "{parentReference}", name: "{name}" }
|
|
88532
|
-
},
|
|
88533
|
-
cas: "native-idempotency",
|
|
88534
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88535
|
-
},
|
|
88536
|
-
{
|
|
88537
|
-
name: "copy.item.within.site",
|
|
88538
|
-
class: "mutation",
|
|
88539
|
-
description: "Copy a drive item to another folder inside the same site drive. The destination parent is identified by the target folder id.",
|
|
88540
|
-
parameters: {
|
|
88541
|
-
type: "object",
|
|
88542
|
-
properties: {
|
|
88543
|
-
siteId: { type: "string" },
|
|
88544
|
-
itemId: { type: "string" },
|
|
88545
|
-
targetParentId: { type: "string" },
|
|
88546
|
-
name: { type: "string" }
|
|
88547
|
-
},
|
|
88548
|
-
required: ["siteId", "itemId", "targetParentId"]
|
|
88549
|
-
},
|
|
88550
|
-
request: {
|
|
88551
|
-
method: "POST",
|
|
88552
|
-
path: "/sites/{siteId}/drive/items/{itemId}/copy",
|
|
88553
|
-
body: { parentReference: { id: "{targetParentId}" }, name: "{name}" }
|
|
88554
|
-
},
|
|
88555
|
-
cas: "native-idempotency",
|
|
88556
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88557
|
-
},
|
|
88558
|
-
{
|
|
88559
|
-
name: "move.file",
|
|
88560
|
-
class: "mutation",
|
|
88561
|
-
description: "Move (re-parent or rename) a drive item by patching its parentReference and/or name.",
|
|
88562
|
-
parameters: {
|
|
88563
|
-
type: "object",
|
|
88564
|
-
properties: {
|
|
88565
|
-
siteId: { type: "string" },
|
|
88566
|
-
itemId: { type: "string" },
|
|
88567
|
-
parentReference: { type: "object" },
|
|
88568
|
-
name: { type: "string" }
|
|
88569
|
-
},
|
|
88570
|
-
required: ["siteId", "itemId", "parentReference"]
|
|
88571
|
-
},
|
|
88572
|
-
request: {
|
|
88573
|
-
method: "PATCH",
|
|
88574
|
-
path: "/sites/{siteId}/drive/items/{itemId}",
|
|
88575
|
-
body: { parentReference: "{parentReference}", name: "{name}" }
|
|
88576
|
-
},
|
|
88577
|
-
cas: "etag-if-match",
|
|
88578
|
-
requiredScopes: ["Files.ReadWrite.All", "Sites.ReadWrite.All"]
|
|
88579
|
-
},
|
|
88580
|
-
// ---------- Lists & list items ----------
|
|
88581
|
-
{
|
|
88582
|
-
name: "create.list",
|
|
88583
|
-
class: "mutation",
|
|
88584
|
-
description: "Create a SharePoint list on the site. `displayName` is required; `columns` and `list.template` are optional.",
|
|
88585
|
-
parameters: {
|
|
88586
|
-
type: "object",
|
|
88587
|
-
properties: {
|
|
88588
|
-
siteId: { type: "string" },
|
|
88589
|
-
displayName: { type: "string" },
|
|
88590
|
-
columns: { type: "array", items: { type: "object" } },
|
|
88591
|
-
list: { type: "object" }
|
|
88592
|
-
},
|
|
88593
|
-
required: ["siteId", "displayName"]
|
|
88594
|
-
},
|
|
88595
|
-
request: {
|
|
88596
|
-
method: "POST",
|
|
88597
|
-
path: "/sites/{siteId}/lists",
|
|
88598
|
-
body: { displayName: "{displayName}", columns: "{columns}", list: "{list}" }
|
|
88599
|
-
},
|
|
88600
|
-
cas: "native-idempotency",
|
|
88601
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88602
|
-
},
|
|
88603
|
-
{
|
|
88604
|
-
name: "create.list.item",
|
|
88605
|
-
class: "mutation",
|
|
88606
|
-
description: "Create a new list item. `fields` is the column -> value map.",
|
|
88607
|
-
parameters: {
|
|
88608
|
-
type: "object",
|
|
88609
|
-
properties: {
|
|
88610
|
-
siteId: { type: "string" },
|
|
88611
|
-
listId: { type: "string" },
|
|
88612
|
-
fields: { type: "object" }
|
|
88613
|
-
},
|
|
88614
|
-
required: ["siteId", "listId", "fields"]
|
|
88615
|
-
},
|
|
88616
|
-
request: {
|
|
88617
|
-
method: "POST",
|
|
88618
|
-
path: "/sites/{siteId}/lists/{listId}/items",
|
|
88619
|
-
body: { fields: "{fields}" }
|
|
88620
|
-
},
|
|
88621
|
-
cas: "native-idempotency",
|
|
88622
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88623
|
-
},
|
|
88624
|
-
{
|
|
88625
|
-
name: "update.list.item",
|
|
88626
|
-
class: "mutation",
|
|
88627
|
-
description: "Patch the fields on an existing list item.",
|
|
88628
|
-
parameters: {
|
|
88629
|
-
type: "object",
|
|
88630
|
-
properties: {
|
|
88631
|
-
siteId: { type: "string" },
|
|
88632
|
-
listId: { type: "string" },
|
|
88633
|
-
itemId: { type: "string" },
|
|
88634
|
-
fields: { type: "object" }
|
|
88635
|
-
},
|
|
88636
|
-
required: ["siteId", "listId", "itemId", "fields"]
|
|
88637
|
-
},
|
|
88638
|
-
request: {
|
|
88639
|
-
method: "PATCH",
|
|
88640
|
-
path: "/sites/{siteId}/lists/{listId}/items/{itemId}/fields",
|
|
88641
|
-
body: "{fields}"
|
|
88642
|
-
},
|
|
88643
|
-
cas: "etag-if-match",
|
|
88644
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88645
|
-
},
|
|
88646
|
-
{
|
|
88647
|
-
name: "delete.list.item",
|
|
88648
|
-
class: "mutation",
|
|
88649
|
-
description: "Delete a list item by id.",
|
|
88650
|
-
parameters: {
|
|
88651
|
-
type: "object",
|
|
88652
|
-
properties: {
|
|
88653
|
-
siteId: { type: "string" },
|
|
88654
|
-
listId: { type: "string" },
|
|
88655
|
-
itemId: { type: "string" }
|
|
88656
|
-
},
|
|
88657
|
-
required: ["siteId", "listId", "itemId"]
|
|
88658
|
-
},
|
|
88659
|
-
request: {
|
|
88660
|
-
method: "DELETE",
|
|
88661
|
-
path: "/sites/{siteId}/lists/{listId}/items/{itemId}"
|
|
88662
|
-
},
|
|
88663
|
-
cas: "native-idempotency",
|
|
88664
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88665
|
-
},
|
|
88666
|
-
{
|
|
88667
|
-
name: "find.list.item",
|
|
88668
|
-
class: "read",
|
|
88669
|
-
description: "List items in a SharePoint list, optionally filtered with $filter / $expand=fields($select=...).",
|
|
88670
|
-
parameters: {
|
|
88671
|
-
type: "object",
|
|
88672
|
-
properties: {
|
|
88673
|
-
siteId: { type: "string" },
|
|
88674
|
-
listId: { type: "string" },
|
|
88675
|
-
$filter: { type: "string" },
|
|
88676
|
-
$expand: { type: "string" },
|
|
88677
|
-
$top: { type: "integer" }
|
|
88678
|
-
},
|
|
88679
|
-
required: ["siteId", "listId"]
|
|
88680
|
-
},
|
|
88681
|
-
request: {
|
|
88682
|
-
method: "GET",
|
|
88683
|
-
path: "/sites/{siteId}/lists/{listId}/items",
|
|
88684
|
-
query: { $filter: "{$filter}", $expand: "{$expand}", $top: "{$top}" }
|
|
88685
|
-
},
|
|
88686
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88687
|
-
},
|
|
88688
|
-
// ---------- Pages ----------
|
|
88689
|
-
{
|
|
88690
|
-
name: "publish.page",
|
|
88691
|
-
class: "mutation",
|
|
88692
|
-
description: "Publish a SharePoint site page by page id.",
|
|
88693
|
-
parameters: {
|
|
88694
|
-
type: "object",
|
|
88695
|
-
properties: {
|
|
88696
|
-
siteId: { type: "string" },
|
|
88697
|
-
pageId: { type: "string" }
|
|
88698
|
-
},
|
|
88699
|
-
required: ["siteId", "pageId"]
|
|
88700
|
-
},
|
|
88701
|
-
request: {
|
|
88702
|
-
method: "POST",
|
|
88703
|
-
path: "/sites/{siteId}/pages/{pageId}/microsoft.graph.sitePage/publish"
|
|
88704
|
-
},
|
|
88705
|
-
cas: "native-idempotency",
|
|
88706
|
-
requiredScopes: ["Sites.ReadWrite.All"]
|
|
88707
|
-
}
|
|
88708
|
-
]
|
|
88709
|
-
});
|
|
88710
|
-
|
|
88711
88868
|
// src/connectors/adapters/millionverifier.ts
|
|
88712
88869
|
var millionverifierConnector = declarativeRestConnector({
|
|
88713
88870
|
kind: "millionverifier",
|
|
@@ -92609,82 +92766,6 @@ var mindStudioConnector = declarativeRestConnector({
|
|
|
92609
92766
|
]
|
|
92610
92767
|
});
|
|
92611
92768
|
|
|
92612
|
-
// src/connectors/adapters/microsoft-onedrive.ts
|
|
92613
|
-
var microsoftOnedriveConnector = declarativeRestConnector({
|
|
92614
|
-
kind: "microsoft-onedrive",
|
|
92615
|
-
displayName: "Microsoft OneDrive",
|
|
92616
|
-
description: "Upload, download, list files and folders in Microsoft OneDrive.",
|
|
92617
|
-
auth: {
|
|
92618
|
-
kind: "oauth2",
|
|
92619
|
-
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
92620
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
92621
|
-
scopes: ["Files.ReadWrite"],
|
|
92622
|
-
clientIdEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_ID",
|
|
92623
|
-
clientSecretEnv: "MICROSOFT_ONEDRIVE_OAUTH_CLIENT_SECRET"
|
|
92624
|
-
},
|
|
92625
|
-
category: "storage",
|
|
92626
|
-
defaultConsistencyModel: "authoritative",
|
|
92627
|
-
baseUrl: "https://graph.microsoft.com/v1.0/me/drive",
|
|
92628
|
-
test: { method: "GET", path: "/root" },
|
|
92629
|
-
capabilities: [
|
|
92630
|
-
{
|
|
92631
|
-
name: "files.list",
|
|
92632
|
-
class: "read",
|
|
92633
|
-
description: "List files in OneDrive.",
|
|
92634
|
-
parameters: {
|
|
92635
|
-
type: "object",
|
|
92636
|
-
properties: {
|
|
92637
|
-
folderId: { type: "string", description: "Folder ID to list files from (optional, defaults to root)" }
|
|
92638
|
-
},
|
|
92639
|
-
required: []
|
|
92640
|
-
},
|
|
92641
|
-
request: { method: "GET", path: "/items/{folderId}/children", query: { $select: "id,name,size,webUrl,folder,file" } }
|
|
92642
|
-
},
|
|
92643
|
-
{
|
|
92644
|
-
name: "folders.list",
|
|
92645
|
-
class: "read",
|
|
92646
|
-
description: "List folders in OneDrive.",
|
|
92647
|
-
parameters: {
|
|
92648
|
-
type: "object",
|
|
92649
|
-
properties: {
|
|
92650
|
-
parentId: { type: "string", description: "Parent folder ID (optional, defaults to root)" }
|
|
92651
|
-
},
|
|
92652
|
-
required: []
|
|
92653
|
-
},
|
|
92654
|
-
request: { method: "GET", path: "/items/{parentId}/children", query: { $filter: "folder ne null", $select: "id,name,webUrl" } }
|
|
92655
|
-
},
|
|
92656
|
-
{
|
|
92657
|
-
name: "files.download",
|
|
92658
|
-
class: "read",
|
|
92659
|
-
description: "Download a file from OneDrive.",
|
|
92660
|
-
parameters: {
|
|
92661
|
-
type: "object",
|
|
92662
|
-
properties: {
|
|
92663
|
-
fileId: { type: "string" }
|
|
92664
|
-
},
|
|
92665
|
-
required: ["fileId"]
|
|
92666
|
-
},
|
|
92667
|
-
request: { method: "GET", path: "/items/{fileId}/content" }
|
|
92668
|
-
},
|
|
92669
|
-
{
|
|
92670
|
-
name: "files.upload",
|
|
92671
|
-
class: "mutation",
|
|
92672
|
-
description: "Upload a file to OneDrive.",
|
|
92673
|
-
parameters: {
|
|
92674
|
-
type: "object",
|
|
92675
|
-
properties: {
|
|
92676
|
-
folderId: { type: "string", description: "Destination folder ID (optional, defaults to root)" },
|
|
92677
|
-
fileName: { type: "string", description: "Name of the file to upload" },
|
|
92678
|
-
fileContent: { type: "string", description: "File content (base64-encoded or raw)" }
|
|
92679
|
-
},
|
|
92680
|
-
required: ["fileName", "fileContent"]
|
|
92681
|
-
},
|
|
92682
|
-
request: { method: "PUT", path: "/items/{folderId}:/{fileName}:/content", body: "{fileContent}" },
|
|
92683
|
-
cas: "native-idempotency"
|
|
92684
|
-
}
|
|
92685
|
-
]
|
|
92686
|
-
});
|
|
92687
|
-
|
|
92688
92769
|
// src/connectors/adapters/mongodb.ts
|
|
92689
92770
|
var mongodbConnector = declarativeRestConnector({
|
|
92690
92771
|
kind: "mongodb",
|
|
@@ -93846,7 +93927,9 @@ var nocodbConnector = declarativeRestConnector({
|
|
|
93846
93927
|
});
|
|
93847
93928
|
|
|
93848
93929
|
// src/connectors/adapters/notion.ts
|
|
93849
|
-
var
|
|
93930
|
+
var TOKEN_URL18 = "https://api.notion.com/v1/oauth/token";
|
|
93931
|
+
var NOTION_VERSION = "2022-06-28";
|
|
93932
|
+
var NOTION_SPEC = {
|
|
93850
93933
|
kind: "notion",
|
|
93851
93934
|
displayName: "Notion",
|
|
93852
93935
|
description: "Query and manipulate Notion databases, pages, and blocks.",
|
|
@@ -93854,13 +93937,21 @@ var notionConnector = declarativeRestConnector({
|
|
|
93854
93937
|
kind: "oauth2",
|
|
93855
93938
|
authorizationUrl: "https://api.notion.com/v1/oauth/authorize",
|
|
93856
93939
|
tokenUrl: "https://api.notion.com/v1/oauth/token",
|
|
93857
|
-
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: [],
|
|
93858
93944
|
clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
|
|
93859
|
-
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET"
|
|
93945
|
+
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
|
|
93946
|
+
extraAuthParams: { owner: "user" }
|
|
93860
93947
|
},
|
|
93861
93948
|
category: "doc",
|
|
93862
93949
|
defaultConsistencyModel: "authoritative",
|
|
93863
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 },
|
|
93864
93955
|
test: { method: "GET", path: "/users/me" },
|
|
93865
93956
|
capabilities: [
|
|
93866
93957
|
{
|
|
@@ -94091,9 +94182,168 @@ var notionConnector = declarativeRestConnector({
|
|
|
94091
94182
|
},
|
|
94092
94183
|
cas: "native-idempotency",
|
|
94093
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
|
|
94094
94237
|
}
|
|
94095
94238
|
]
|
|
94096
|
-
}
|
|
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
|
+
}
|
|
94097
94347
|
|
|
94098
94348
|
// src/connectors/adapters/ntfy.ts
|
|
94099
94349
|
var ntfyConnector = declarativeRestConnector({
|
|
@@ -111284,7 +111534,7 @@ var twinLabsConnector = declarativeRestConnector({
|
|
|
111284
111534
|
});
|
|
111285
111535
|
|
|
111286
111536
|
// src/connectors/adapters/twitter.ts
|
|
111287
|
-
var
|
|
111537
|
+
var AUTH_URL18 = "https://twitter.com/i/oauth2/authorize";
|
|
111288
111538
|
var TOKEN_URL19 = "https://api.twitter.com/2/oauth2/token";
|
|
111289
111539
|
var SCOPES14 = ["tweet.read", "tweet.write", "users.read", "like.write", "offline.access"];
|
|
111290
111540
|
var TWITTER_SPEC = {
|
|
@@ -111297,7 +111547,7 @@ var TWITTER_SPEC = {
|
|
|
111297
111547
|
options: [
|
|
111298
111548
|
{
|
|
111299
111549
|
kind: "oauth2",
|
|
111300
|
-
authorizationUrl:
|
|
111550
|
+
authorizationUrl: AUTH_URL18,
|
|
111301
111551
|
tokenUrl: TOKEN_URL19,
|
|
111302
111552
|
scopes: SCOPES14,
|
|
111303
111553
|
clientIdEnv: "TWITTER_OAUTH_CLIENT_ID",
|
|
@@ -118456,7 +118706,6 @@ export {
|
|
|
118456
118706
|
microsoftCalendar,
|
|
118457
118707
|
hubspot,
|
|
118458
118708
|
slack,
|
|
118459
|
-
notionDatabase,
|
|
118460
118709
|
docuseal,
|
|
118461
118710
|
twilioSmsConnector,
|
|
118462
118711
|
phonyConnector,
|
|
@@ -118693,6 +118942,8 @@ export {
|
|
|
118693
118942
|
ghostcmsConnector,
|
|
118694
118943
|
gistlyConnector,
|
|
118695
118944
|
googleSearchConsoleConnector,
|
|
118945
|
+
googleAnalyticsConnector,
|
|
118946
|
+
googleMeetConnector,
|
|
118696
118947
|
youtubeDataConnector,
|
|
118697
118948
|
googleCloudStorageConnector,
|
|
118698
118949
|
googleBigqueryConnector,
|
|
@@ -118770,12 +119021,9 @@ export {
|
|
|
118770
119021
|
microsoftDynamics365BusinessCentralConnector,
|
|
118771
119022
|
microsoft365PlannerConnector,
|
|
118772
119023
|
microsoftPowerBiConnector,
|
|
118773
|
-
microsoftOutlookCalendarConnector,
|
|
118774
119024
|
microsoftOnenoteConnector,
|
|
118775
|
-
microsoftOutlookConnector,
|
|
118776
119025
|
microsoftExcel365Connector,
|
|
118777
119026
|
microsoftTodoConnector,
|
|
118778
|
-
microsoftSharepointConnector,
|
|
118779
119027
|
millionverifierConnector,
|
|
118780
119028
|
mindeeConnector,
|
|
118781
119029
|
mixmaxConnector,
|
|
@@ -118806,12 +119054,12 @@ export {
|
|
|
118806
119054
|
mollieConnector,
|
|
118807
119055
|
metabaseConnector,
|
|
118808
119056
|
mindStudioConnector,
|
|
118809
|
-
microsoftOnedriveConnector,
|
|
118810
119057
|
mongodbConnector,
|
|
118811
119058
|
niftyConnector,
|
|
118812
119059
|
ninjapipeConnector,
|
|
118813
119060
|
nocodbConnector,
|
|
118814
119061
|
notionConnector,
|
|
119062
|
+
notion,
|
|
118815
119063
|
ntfyConnector,
|
|
118816
119064
|
odooConnector,
|
|
118817
119065
|
omniCoConnector,
|
|
@@ -118940,4 +119188,4 @@ export {
|
|
|
118940
119188
|
pipedreamConnector,
|
|
118941
119189
|
adapters_exports
|
|
118942
119190
|
};
|
|
118943
|
-
//# sourceMappingURL=chunk-
|
|
119191
|
+
//# sourceMappingURL=chunk-6MUBOVI4.js.map
|