@pipedream/microsoft_outlook_calendar 8.0.1 → 8.2.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.
@@ -9,7 +9,7 @@ import {
9
9
  export default {
10
10
  type: "action",
11
11
  key: "microsoft_outlook_calendar-create-calendar-event",
12
- version: "0.0.13",
12
+ version: "0.0.14",
13
13
  annotations: {
14
14
  destructiveHint: false,
15
15
  openWorldHint: true,
@@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook_calendar.app.mjs";
3
3
  export default {
4
4
  type: "action",
5
5
  key: "microsoft_outlook_calendar-delete-calendar-event",
6
- version: "0.0.8",
6
+ version: "0.0.9",
7
7
  annotations: {
8
8
  destructiveHint: true,
9
9
  openWorldHint: true,
@@ -4,7 +4,7 @@ import { ConfigurationError } from "@pipedream/platform";
4
4
  export default {
5
5
  type: "action",
6
6
  key: "microsoft_outlook_calendar-delete-recurring-event-instance",
7
- version: "0.0.5",
7
+ version: "0.0.6",
8
8
  annotations: {
9
9
  destructiveHint: true,
10
10
  openWorldHint: true,
@@ -0,0 +1,256 @@
1
+ import { ConfigurationError } from "@pipedream/platform";
2
+ import microsoftOutlook from "../../microsoft_outlook_calendar.app.mjs";
3
+ import utils from "../../common/utils.mjs";
4
+
5
+ export default {
6
+ key: "microsoft_outlook_calendar-find-meeting-times",
7
+ name: "Find Meeting Times",
8
+ description: "Suggest meeting times and locations based on organizer and attendee availability. [See the documentation](https://learn.microsoft.com/en-us/graph/api/user-findmeetingtimes?view=graph-rest-1.0)",
9
+ version: "0.0.1",
10
+ type: "action",
11
+ annotations: {
12
+ destructiveHint: false,
13
+ openWorldHint: true,
14
+ readOnlyHint: true,
15
+ },
16
+ props: {
17
+ microsoftOutlook,
18
+ userId: {
19
+ type: "string",
20
+ label: "User ID or UPN",
21
+ description: "Optional. If set, runs the request for a specific user (`/users/{id|userPrincipalName}/findMeetingTimes`). If unset, uses the signed-in user (`/me/findMeetingTimes`).",
22
+ optional: true,
23
+ },
24
+ attendees: {
25
+ type: "string[]",
26
+ label: "Attendees",
27
+ description: "Optional. A list of attendee email addresses.",
28
+ optional: true,
29
+ },
30
+ resourceAttendees: {
31
+ type: "string[]",
32
+ label: "Resource Attendees",
33
+ description: "Optional. A list of resource email addresses (for example, rooms/equipment).",
34
+ optional: true,
35
+ },
36
+ start: {
37
+ propDefinition: [
38
+ microsoftOutlook,
39
+ "start",
40
+ ],
41
+ },
42
+ end: {
43
+ propDefinition: [
44
+ microsoftOutlook,
45
+ "end",
46
+ ],
47
+ },
48
+ timeZone: {
49
+ propDefinition: [
50
+ microsoftOutlook,
51
+ "timeZone",
52
+ ],
53
+ },
54
+ activityDomain: {
55
+ type: "string",
56
+ label: "Activity Domain",
57
+ description: "Optional. Restrict suggestions to work hours, personal hours, or unrestricted.",
58
+ options: [
59
+ "work",
60
+ "personal",
61
+ "unrestricted",
62
+ ],
63
+ default: "work",
64
+ optional: true,
65
+ },
66
+ duration: {
67
+ type: "integer",
68
+ label: "Duration (Minutes)",
69
+ description: "Optional. Meeting duration in minutes. Defaults to 30.",
70
+ optional: true,
71
+ default: 30,
72
+ min: 1,
73
+ },
74
+ maxResults: {
75
+ type: "integer",
76
+ label: "Max Results",
77
+ description: "Optional. Maximum number of meeting time suggestions to return (default: 20, max: 50).",
78
+ optional: true,
79
+ min: 1,
80
+ max: 50,
81
+ default: 20,
82
+ },
83
+ minimumAttendeePercentage: {
84
+ type: "integer",
85
+ label: "Minimum Attendee Percentage",
86
+ description: "Optional. Minimum confidence (0-100) for a suggestion to be returned.",
87
+ optional: true,
88
+ min: 0,
89
+ max: 100,
90
+ },
91
+ isOrganizerOptional: {
92
+ type: "boolean",
93
+ label: "Is Organizer Optional",
94
+ description: "Optional. Set to true if the organizer doesn't necessarily have to attend.",
95
+ optional: true,
96
+ },
97
+ returnSuggestionReasons: {
98
+ type: "boolean",
99
+ label: "Return Suggestion Reasons",
100
+ description: "Optional. Set to true to include a reason for each suggestion in the response.",
101
+ optional: true,
102
+ default: true,
103
+ },
104
+ suggestLocation: {
105
+ type: "boolean",
106
+ label: "Suggest Location",
107
+ description: "Optional. Set to true to ask Microsoft Graph to suggest meeting locations.",
108
+ optional: true,
109
+ },
110
+ locations: {
111
+ type: "string[]",
112
+ label: "Locations",
113
+ description: "Optional. A list of location display names to constrain suggestions (for example, conference room names).",
114
+ optional: true,
115
+ },
116
+ isLocationRequired: {
117
+ type: "boolean",
118
+ label: "Location Required",
119
+ description: "Optional. Set to true if a location is required for the suggestion.",
120
+ optional: true,
121
+ },
122
+ },
123
+ methods: {
124
+ _toAttendeeBase(address, type) {
125
+ return {
126
+ type,
127
+ emailAddress: {
128
+ address,
129
+ },
130
+ };
131
+ },
132
+ },
133
+ async run({ $ }) {
134
+ const userId = this.userId?.trim();
135
+
136
+ const cleanedAttendees = utils.normalizeStringArray(this.attendees);
137
+ const cleanedResourceAttendees = utils.normalizeStringArray(this.resourceAttendees);
138
+ const cleanedLocations = utils.normalizeStringArray(this.locations);
139
+ const startMs = Date.parse(this.start);
140
+ const endMs = Date.parse(this.end);
141
+ if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || startMs >= endMs) {
142
+ throw new Error("`start` must be before `end` and both must be valid date-time strings.");
143
+ }
144
+
145
+ const attendees = [
146
+ ...cleanedAttendees.map((address) => this._toAttendeeBase(address, "required")),
147
+ ...cleanedResourceAttendees.map((address) => this._toAttendeeBase(address, "resource")),
148
+ ];
149
+ if (!attendees.length) {
150
+ throw new ConfigurationError("Provide at least one attendee or resource attendee email address.");
151
+ }
152
+
153
+ const durationMinutes = utils.clampInt(this.duration, {
154
+ min: 1,
155
+ max: 24 * 60,
156
+ }) ?? 30;
157
+ const meetingDuration = `PT${durationMinutes}M`;
158
+
159
+ const maxCandidates = utils.clampInt(this.maxResults, {
160
+ min: 1,
161
+ max: 50,
162
+ }) ?? 20;
163
+
164
+ const body = {
165
+ ...(attendees.length
166
+ ? {
167
+ attendees,
168
+ }
169
+ : {}),
170
+ ...(this.isOrganizerOptional !== undefined
171
+ ? {
172
+ isOrganizerOptional: this.isOrganizerOptional,
173
+ }
174
+ : {}),
175
+ maxCandidates,
176
+ meetingDuration,
177
+ ...(this.minimumAttendeePercentage !== undefined
178
+ ? {
179
+ minimumAttendeePercentage: this.minimumAttendeePercentage,
180
+ }
181
+ : {}),
182
+ returnSuggestionReasons: this.returnSuggestionReasons ?? true,
183
+ timeConstraint: {
184
+ activityDomain: this.activityDomain,
185
+ timeSlots: [
186
+ {
187
+ start: {
188
+ dateTime: this.start,
189
+ timeZone: this.timeZone,
190
+ },
191
+ end: {
192
+ dateTime: this.end,
193
+ timeZone: this.timeZone,
194
+ },
195
+ },
196
+ ],
197
+ },
198
+ ...(this.suggestLocation !== undefined
199
+ || cleanedLocations.length
200
+ || this.isLocationRequired !== undefined
201
+ ? {
202
+ locationConstraint: {
203
+ ...(this.isLocationRequired !== undefined
204
+ ? {
205
+ isRequired: this.isLocationRequired,
206
+ }
207
+ : {}),
208
+ ...(this.suggestLocation !== undefined
209
+ ? {
210
+ suggestLocation: this.suggestLocation,
211
+ }
212
+ : {}),
213
+ ...(cleanedLocations.length
214
+ ? {
215
+ locations: cleanedLocations.map((displayName) => ({
216
+ resolveAvailability: false,
217
+ displayName,
218
+ })),
219
+ }
220
+ : {}),
221
+ },
222
+ }
223
+ : {}),
224
+ };
225
+
226
+ const graphResponse = await this.microsoftOutlook.findMeetingTimes({
227
+ $,
228
+ userId,
229
+ timeZone: this.timeZone,
230
+ data: body,
231
+ });
232
+
233
+ const suggestionCount = graphResponse?.meetingTimeSuggestions?.length ?? 0;
234
+ $.export("$summary", suggestionCount
235
+ ? `Successfully found ${suggestionCount} meeting time suggestion${suggestionCount === 1
236
+ ? ""
237
+ : "s"}`
238
+ : `No meeting time suggestions found${graphResponse?.emptySuggestionsReason
239
+ ? ` (${graphResponse.emptySuggestionsReason})`
240
+ : ""}`);
241
+
242
+ const meetingTimesData = (graphResponse?.meetingTimeSuggestions ?? []).map((time) => ({
243
+ confidence: time.confidence,
244
+ organizerAvailability: time.organizerAvailability,
245
+ attendeeAvailability: time.attendeeAvailability,
246
+ meetingTimeSlot: time.meetingTimeSlot,
247
+ suggestionReason: time.suggestionReason,
248
+ locations: time.locations,
249
+ }));
250
+
251
+ return {
252
+ data: meetingTimesData,
253
+ };
254
+ },
255
+ };
256
+
@@ -4,7 +4,7 @@ export default {
4
4
  key: "microsoft_outlook_calendar-get-current-user",
5
5
  name: "Get Current User",
6
6
  description: "Returns the authenticated Microsoft user's ID, display name, email, and principal name via Microsoft Graph. Call this first when the user says 'my calendar', 'my events', or needs to identify themselves as organizer/attendee. Use `id` or `mail` to filter results from **List Events** or set the organizer in **Create Calendar Event**. [See the documentation](https://learn.microsoft.com/en-us/graph/api/user-get).",
7
- version: "0.0.1",
7
+ version: "0.0.2",
8
8
  type: "action",
9
9
  annotations: {
10
10
  destructiveHint: false,
@@ -0,0 +1,54 @@
1
+ import microsoftOutlook from "../../microsoft_outlook_calendar.app.mjs";
2
+
3
+ export default {
4
+ type: "action",
5
+ key: "microsoft_outlook_calendar-get-event",
6
+ name: "Get Event",
7
+ description: "Retrieve a calendar event by its Microsoft Graph event ID. Pass the `id` from **List Events** when you need full details (for example `body`, `attendees`, or `recurrence`) that list responses may omit or truncate. [See the documentation](https://learn.microsoft.com/en-us/graph/api/event-get?view=graph-rest-1.0&tabs=http)",
8
+ version: "0.0.1",
9
+ annotations: {
10
+ destructiveHint: false,
11
+ openWorldHint: true,
12
+ readOnlyHint: true,
13
+ },
14
+ props: {
15
+ microsoftOutlook,
16
+ eventId: {
17
+ propDefinition: [
18
+ microsoftOutlook,
19
+ "eventId",
20
+ ],
21
+ description: "The Microsoft Graph event ID — the `id` field on each object returned by **List Events** (including occurrences from calendar view when **Include Recurring** is enabled).",
22
+ },
23
+ select: {
24
+ type: "string",
25
+ label: "Properties to return ($select)",
26
+ description: "Optional. Comma-separated Microsoft Graph [event](https://learn.microsoft.com/en-us/graph/api/resources/event) property names (for example `subject,body,bodyPreview,start,end,attendees,organizer,location`). When empty, the API returns its default property set.",
27
+ optional: true,
28
+ },
29
+ },
30
+ async run({ $ }) {
31
+ const normalizedSelect = this.select?.trim()
32
+ ? this.select.split(",")
33
+ .map((p) => p.trim())
34
+ .filter(Boolean)
35
+ .join(",")
36
+ : "";
37
+
38
+ const params = normalizedSelect
39
+ ? {
40
+ $select: normalizedSelect,
41
+ }
42
+ : {};
43
+
44
+ const event = await this.microsoftOutlook.getCalendarEvent({
45
+ $,
46
+ eventId: this.eventId,
47
+ params,
48
+ });
49
+
50
+ const label = event?.subject ?? this.eventId;
51
+ $.export("$summary", `Successfully retrieved event "${label}"`);
52
+ return event;
53
+ },
54
+ };
@@ -8,7 +8,7 @@ export default {
8
8
  key: "microsoft_outlook_calendar-get-schedule",
9
9
  name: "Get Free/Busy Schedule",
10
10
  description: "Get the free/busy availability information for a collection of users, distributions lists, or resources (rooms or equipment) for a specified time period. [See the documentation](https://learn.microsoft.com/en-us/graph/api/calendar-getschedule)",
11
- version: "0.0.10",
11
+ version: "0.0.11",
12
12
  annotations: {
13
13
  destructiveHint: false,
14
14
  openWorldHint: true,
@@ -5,7 +5,7 @@ export default {
5
5
  key: "microsoft_outlook_calendar-list-events",
6
6
  name: "List Events",
7
7
  description: "Get a list of event objects in the user's mailbox. [See the documentation](https://learn.microsoft.com/en-us/graph/api/user-list-events)",
8
- version: "0.0.11",
8
+ version: "0.0.12",
9
9
  annotations: {
10
10
  destructiveHint: false,
11
11
  openWorldHint: true,
@@ -4,7 +4,7 @@ export default {
4
4
  key: "microsoft_outlook_calendar-search-contacts",
5
5
  name: "Search Contacts",
6
6
  description: "Search for contacts by name from your saved contacts list and retrieve their email addresses. [See the documentation](https://learn.microsoft.com/en-us/graph/api/user-list-contacts)",
7
- version: "0.0.4",
7
+ version: "0.0.5",
8
8
  type: "action",
9
9
  annotations: {
10
10
  destructiveHint: false,
@@ -4,7 +4,7 @@ export default {
4
4
  key: "microsoft_outlook_calendar-search-people",
5
5
  name: "Search People",
6
6
  description: "Retrieve a collection of person objects ordered by their relevance to the user, based on communication and collaboration patterns and business relationships. [See the documentation](https://learn.microsoft.com/en-us/graph/api/user-list-people)",
7
- version: "0.0.4",
7
+ version: "0.0.5",
8
8
  type: "action",
9
9
  annotations: {
10
10
  destructiveHint: false,
@@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook_calendar.app.mjs";
3
3
  export default {
4
4
  type: "action",
5
5
  key: "microsoft_outlook_calendar-update-calendar-event",
6
- version: "0.0.8",
6
+ version: "0.0.9",
7
7
  annotations: {
8
8
  destructiveHint: true,
9
9
  openWorldHint: true,
@@ -4,7 +4,7 @@ import { ConfigurationError } from "@pipedream/platform";
4
4
  export default {
5
5
  type: "action",
6
6
  key: "microsoft_outlook_calendar-update-recurring-event-instance",
7
- version: "0.0.5",
7
+ version: "0.0.6",
8
8
  annotations: {
9
9
  destructiveHint: false,
10
10
  openWorldHint: true,
package/common/utils.mjs CHANGED
@@ -35,4 +35,19 @@ export default {
35
35
  String(input),
36
36
  ];
37
37
  },
38
+ normalizeStringArray(values) {
39
+ return (values ?? [])
40
+ .map((v) => v?.toString?.().trim())
41
+ .filter(Boolean);
42
+ },
43
+ clampInt(value, {
44
+ min,
45
+ max,
46
+ }) {
47
+ if (value === null || value === undefined) return undefined;
48
+ const n = Number(value);
49
+ if (!Number.isFinite(n)) return undefined;
50
+ const rounded = Math.round(n);
51
+ return Math.max(min, Math.min(max, rounded));
52
+ },
38
53
  };
@@ -281,5 +281,19 @@ export default {
281
281
  .header("Prefer", `outlook.timezone="${timeZone}"`)
282
282
  .post(data);
283
283
  },
284
+ async findMeetingTimes({
285
+ userId,
286
+ timeZone,
287
+ data = {},
288
+ } = {}) {
289
+ const basePath = userId
290
+ ? `/users/${encodeURIComponent(userId)}`
291
+ : "/me";
292
+ let request = this.client().api(`${basePath}/findMeetingTimes`);
293
+ if (timeZone) {
294
+ request = request.header("Prefer", `outlook.timezone="${timeZone}"`);
295
+ }
296
+ return await request.post(data);
297
+ },
284
298
  },
285
299
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/microsoft_outlook_calendar",
3
- "version": "8.0.1",
3
+ "version": "8.2.0",
4
4
  "description": "Pipedream Microsoft Outlook Calendar Components",
5
5
  "main": "microsoft_outlook_calendar.app.mjs",
6
6
  "keywords": [
@@ -5,7 +5,7 @@ export default {
5
5
  key: "microsoft_outlook_calendar-new-calendar-event",
6
6
  name: "New Calendar Event (Instant)",
7
7
  description: "Emit new event when a new Calendar event is created",
8
- version: "0.0.13",
8
+ version: "0.0.14",
9
9
  type: "source",
10
10
  hooks: {
11
11
  ...common.hooks,
@@ -6,7 +6,7 @@ export default {
6
6
  key: "microsoft_outlook_calendar-new-upcoming-event",
7
7
  name: "New Upcoming Calendar Event",
8
8
  description: "Emit new event when a Calendar event is upcoming, this source is using `reminderMinutesBeforeStart` property of the event to determine the time it should emit.",
9
- version: "0.0.9",
9
+ version: "0.0.10",
10
10
  type: "source",
11
11
  props: {
12
12
  ...common.props,
@@ -5,7 +5,7 @@ export default {
5
5
  key: "microsoft_outlook_calendar-new-upcoming-event-polling",
6
6
  name: "New Upcoming Calendar Event (Polling)",
7
7
  description: "Emit new event based on a time interval before an upcoming calendar event. [See the documentation](https://docs.microsoft.com/en-us/graph/api/user-list-events)",
8
- version: "0.0.5",
8
+ version: "0.0.6",
9
9
  type: "source",
10
10
  dedupe: "unique",
11
11
  props: {
@@ -5,7 +5,7 @@ export default {
5
5
  key: "microsoft_outlook_calendar-updated-calendar-event",
6
6
  name: "New Calendar Event Update (Instant)",
7
7
  description: "Emit new event when a Calendar event is updated",
8
- version: "0.0.13",
8
+ version: "0.0.14",
9
9
  type: "source",
10
10
  hooks: {
11
11
  ...common.hooks,