@zapier/microsoft-outlook-connector 0.0.0 → 0.1.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/LICENSE +93 -0
- package/NOTICE +8 -0
- package/NOTICE.md +8 -0
- package/README.md +145 -2
- package/SKILL.md +159 -0
- package/cli.js +71 -0
- package/cli.ts +5 -0
- package/connections.ts +69 -0
- package/dist/cli.js +4 -0
- package/dist/index.js +1823 -0
- package/index.ts +103 -0
- package/package.json +65 -4
- package/preflight.sh +157 -0
- package/references/microsoft-outlook-api-gotchas.md +210 -0
- package/scripts/copyMessage.ts +68 -0
- package/scripts/createContact.ts +39 -0
- package/scripts/createDraft.ts +71 -0
- package/scripts/createEvent.ts +61 -0
- package/scripts/createMailFolder.ts +68 -0
- package/scripts/createReplyDraft.ts +81 -0
- package/scripts/deleteContact.ts +47 -0
- package/scripts/deleteEvent.ts +61 -0
- package/scripts/deleteMessage.ts +57 -0
- package/scripts/forwardMessage.ts +75 -0
- package/scripts/getAttachment.ts +60 -0
- package/scripts/getContact.ts +44 -0
- package/scripts/getEvent.ts +63 -0
- package/scripts/getMe.ts +42 -0
- package/scripts/getMessage.ts +68 -0
- package/scripts/listAttachments.ts +94 -0
- package/scripts/listCalendarView.ts +99 -0
- package/scripts/listCalendars.ts +85 -0
- package/scripts/listCategories.ts +49 -0
- package/scripts/listContacts.ts +81 -0
- package/scripts/listEvents.ts +94 -0
- package/scripts/listMailFolders.ts +98 -0
- package/scripts/listMessages.ts +106 -0
- package/scripts/moveMessage.ts +68 -0
- package/scripts/replyToMessage.ts +73 -0
- package/scripts/sendDraft.ts +55 -0
- package/scripts/sendMail.ts +68 -0
- package/scripts/updateContact.ts +49 -0
- package/scripts/updateEvent.ts +69 -0
- package/scripts/updateMessage.ts +99 -0
- package/tsup.config.ts +63 -0
package/scripts/getMe.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import { GRAPH_BASE, outlookFetch, parseGraphResponse } from "../lib/graph.ts";
|
|
7
|
+
|
|
8
|
+
const inputSchema = z.object({}).strict();
|
|
9
|
+
|
|
10
|
+
const outputSchema = z.object({
|
|
11
|
+
id: z.string(),
|
|
12
|
+
displayName: z.string().optional(),
|
|
13
|
+
mail: z.string().optional(),
|
|
14
|
+
userPrincipalName: z.string(),
|
|
15
|
+
jobTitle: z.string().optional(),
|
|
16
|
+
mobilePhone: z.string().optional(),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const definition = defineTool({
|
|
20
|
+
name: "getMe",
|
|
21
|
+
title: "Get Me",
|
|
22
|
+
description:
|
|
23
|
+
'Retrieve the signed-in user\'s profile — id, displayName, mail, and userPrincipalName. Doubles as the auth probe (a 200 confirms the connection works). Call this first to resolve "my email" before composing or filtering mail.',
|
|
24
|
+
inputSchema,
|
|
25
|
+
outputSchema,
|
|
26
|
+
annotations: {
|
|
27
|
+
readOnlyHint: true,
|
|
28
|
+
destructiveHint: false,
|
|
29
|
+
idempotentHint: true,
|
|
30
|
+
openWorldHint: true,
|
|
31
|
+
},
|
|
32
|
+
connection: "microsoft-outlook",
|
|
33
|
+
run: async (_input, ctx) => {
|
|
34
|
+
const url = `${GRAPH_BASE}/me`;
|
|
35
|
+
const res = await outlookFetch(ctx.fetch, "getMe", url);
|
|
36
|
+
return parseGraphResponse(res);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export default definition;
|
|
41
|
+
|
|
42
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import {
|
|
7
|
+
GRAPH_BASE,
|
|
8
|
+
mailboxRoot,
|
|
9
|
+
outlookFetch,
|
|
10
|
+
parseGraphResponse,
|
|
11
|
+
} from "../lib/graph.ts";
|
|
12
|
+
import { messageSchema } from "../lib/schemas.ts";
|
|
13
|
+
|
|
14
|
+
const inputSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
messageId: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe(
|
|
19
|
+
"Message id from listMessages or another message tool. Opaque and case-sensitive; changes when the message is moved between folders.",
|
|
20
|
+
),
|
|
21
|
+
bodyContentType: z
|
|
22
|
+
.enum(["text", "html"])
|
|
23
|
+
.describe(
|
|
24
|
+
"Format for the returned body. Defaults to text (smaller, keeps visible URLs); pass html to preserve formatting.",
|
|
25
|
+
)
|
|
26
|
+
.optional(),
|
|
27
|
+
mailbox: z
|
|
28
|
+
.string()
|
|
29
|
+
.describe(
|
|
30
|
+
"Shared-mailbox address (UPN/email) to read from instead of your own. Requires shared-mailbox delegation. Omit for your own mailbox.",
|
|
31
|
+
)
|
|
32
|
+
.optional(),
|
|
33
|
+
})
|
|
34
|
+
.strict();
|
|
35
|
+
|
|
36
|
+
const outputSchema = messageSchema;
|
|
37
|
+
|
|
38
|
+
const definition = defineTool({
|
|
39
|
+
name: "getMessage",
|
|
40
|
+
title: "Get Message",
|
|
41
|
+
description:
|
|
42
|
+
"Retrieve a single message by id, including its full body, recipient lists, flag, and categories. Resolve the id via listMessages first. The body is returned as plain text by default; pass bodyContentType: html for the original markup.",
|
|
43
|
+
inputSchema,
|
|
44
|
+
outputSchema,
|
|
45
|
+
annotations: {
|
|
46
|
+
readOnlyHint: true,
|
|
47
|
+
destructiveHint: false,
|
|
48
|
+
idempotentHint: true,
|
|
49
|
+
openWorldHint: true,
|
|
50
|
+
},
|
|
51
|
+
connection: "microsoft-outlook",
|
|
52
|
+
run: async (input, ctx) => {
|
|
53
|
+
const url = `${GRAPH_BASE}${mailboxRoot(input.mailbox)}/messages/${encodeURIComponent(
|
|
54
|
+
input.messageId,
|
|
55
|
+
)}`;
|
|
56
|
+
// Body content type is a Prefer header, not a query param; default to text.
|
|
57
|
+
const res = await outlookFetch(ctx.fetch, "getMessage", url, {
|
|
58
|
+
headers: {
|
|
59
|
+
Prefer: `outlook.body-content-type="${input.bodyContentType ?? "text"}"`,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
return parseGraphResponse(res);
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export default definition;
|
|
67
|
+
|
|
68
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import {
|
|
7
|
+
buildListQuery,
|
|
8
|
+
GRAPH_BASE,
|
|
9
|
+
mailboxRoot,
|
|
10
|
+
outlookFetch,
|
|
11
|
+
toListResult,
|
|
12
|
+
} from "../lib/graph.ts";
|
|
13
|
+
import {
|
|
14
|
+
attachmentListItemSchema,
|
|
15
|
+
normalizeAttachment,
|
|
16
|
+
} from "../lib/schemas.ts";
|
|
17
|
+
|
|
18
|
+
const inputSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
messageId: z
|
|
21
|
+
.string()
|
|
22
|
+
.describe(
|
|
23
|
+
"Message id from listMessages or another message tool. Opaque and case-sensitive; changes when the message is moved between folders.",
|
|
24
|
+
),
|
|
25
|
+
mailbox: z
|
|
26
|
+
.string()
|
|
27
|
+
.describe(
|
|
28
|
+
"Shared-mailbox address (UPN/email) to read from instead of your own, e.g. team@contoso.com. Requires shared-mailbox delegation. Omit for your own mailbox.",
|
|
29
|
+
)
|
|
30
|
+
.optional(),
|
|
31
|
+
limit: z
|
|
32
|
+
.number()
|
|
33
|
+
.int()
|
|
34
|
+
.gte(1)
|
|
35
|
+
.describe(
|
|
36
|
+
"Attachments per page. Defaults to 20 when omitted; pass a value when you need a specific number.",
|
|
37
|
+
)
|
|
38
|
+
.optional(),
|
|
39
|
+
cursor: z
|
|
40
|
+
.string()
|
|
41
|
+
.describe(
|
|
42
|
+
"Pagination cursor from a previous response's next_cursor. Omit for the first page.",
|
|
43
|
+
)
|
|
44
|
+
.optional(),
|
|
45
|
+
})
|
|
46
|
+
.strict();
|
|
47
|
+
|
|
48
|
+
const outputSchema = z.object({
|
|
49
|
+
items: z.array(attachmentListItemSchema),
|
|
50
|
+
next_cursor: z
|
|
51
|
+
.string()
|
|
52
|
+
.describe("Pass as cursor to fetch the next page. Absent on the last page.")
|
|
53
|
+
.optional(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const definition = defineTool({
|
|
57
|
+
name: "listAttachments",
|
|
58
|
+
title: "List Attachments",
|
|
59
|
+
description:
|
|
60
|
+
"List the attachments on a message — name, content type, size, kind, and inline flag. Resolve the messageId via listMessages first, then use getAttachment to download a specific one's bytes. A message's hasAttachments is false when it has only inline attachments, so still call this to check for them.",
|
|
61
|
+
inputSchema,
|
|
62
|
+
outputSchema,
|
|
63
|
+
annotations: {
|
|
64
|
+
readOnlyHint: true,
|
|
65
|
+
destructiveHint: false,
|
|
66
|
+
idempotentHint: true,
|
|
67
|
+
openWorldHint: true,
|
|
68
|
+
},
|
|
69
|
+
connection: "microsoft-outlook",
|
|
70
|
+
run: async (input, ctx) => {
|
|
71
|
+
// `@odata.nextLink` is an opaque full URL — when paging, fetch it verbatim
|
|
72
|
+
// and skip rebuilding the path/query.
|
|
73
|
+
let url: string;
|
|
74
|
+
if (input.cursor !== undefined) {
|
|
75
|
+
url = input.cursor;
|
|
76
|
+
} else {
|
|
77
|
+
const path = `${mailboxRoot(input.mailbox)}/messages/${encodeURIComponent(
|
|
78
|
+
input.messageId,
|
|
79
|
+
)}/attachments`;
|
|
80
|
+
const query = buildListQuery({ limit: input.limit ?? 20 });
|
|
81
|
+
url = `${GRAPH_BASE}${path}${query}`;
|
|
82
|
+
}
|
|
83
|
+
const res = await outlookFetch(ctx.fetch, "listAttachments", url);
|
|
84
|
+
const result = toListResult<Record<string, unknown>>(await res.json());
|
|
85
|
+
return {
|
|
86
|
+
...result,
|
|
87
|
+
items: result.items.map((item) => normalizeAttachment(item)),
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export default definition;
|
|
93
|
+
|
|
94
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import {
|
|
7
|
+
calendarRoot,
|
|
8
|
+
GRAPH_BASE,
|
|
9
|
+
outlookFetch,
|
|
10
|
+
toListResult,
|
|
11
|
+
} from "../lib/graph.ts";
|
|
12
|
+
import { eventListItemSchema } from "../lib/schemas.ts";
|
|
13
|
+
|
|
14
|
+
const inputSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
startDateTime: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe(
|
|
19
|
+
'Window start, ISO 8601 (e.g. "2026-07-01T00:00:00"). Interpreted as UTC unless it carries an offset.',
|
|
20
|
+
),
|
|
21
|
+
endDateTime: z
|
|
22
|
+
.string()
|
|
23
|
+
.describe(
|
|
24
|
+
"Window end, ISO 8601. Interpreted as UTC unless it carries an offset.",
|
|
25
|
+
),
|
|
26
|
+
mailbox: z
|
|
27
|
+
.string()
|
|
28
|
+
.describe(
|
|
29
|
+
"Shared-mailbox address (UPN/email) to read instead of your own, e.g. team@contoso.com. Requires shared-mailbox delegation. Omit for your own mailbox.",
|
|
30
|
+
)
|
|
31
|
+
.optional(),
|
|
32
|
+
calendarId: z
|
|
33
|
+
.string()
|
|
34
|
+
.describe(
|
|
35
|
+
"Target a specific calendar (id from listCalendars). Omit to use the default calendar.",
|
|
36
|
+
)
|
|
37
|
+
.optional(),
|
|
38
|
+
limit: z
|
|
39
|
+
.number()
|
|
40
|
+
.int()
|
|
41
|
+
.gte(1)
|
|
42
|
+
.describe(
|
|
43
|
+
"Events per page. Defaults to 20 when omitted; pass a value when you need a specific number of results.",
|
|
44
|
+
)
|
|
45
|
+
.optional(),
|
|
46
|
+
cursor: z
|
|
47
|
+
.string()
|
|
48
|
+
.describe(
|
|
49
|
+
"Pagination cursor from a previous response's next_cursor. Omit for the first page.",
|
|
50
|
+
)
|
|
51
|
+
.optional(),
|
|
52
|
+
})
|
|
53
|
+
.strict();
|
|
54
|
+
|
|
55
|
+
const outputSchema = z.object({
|
|
56
|
+
items: z.array(eventListItemSchema),
|
|
57
|
+
next_cursor: z
|
|
58
|
+
.string()
|
|
59
|
+
.describe("Pass as cursor to fetch the next page. Absent on the last page.")
|
|
60
|
+
.optional(),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const definition = defineTool({
|
|
64
|
+
name: "listCalendarView",
|
|
65
|
+
title: "List Calendar View",
|
|
66
|
+
description:
|
|
67
|
+
'The primary "what\'s on my calendar" tool: list everything occurring between startDateTime and endDateTime, expanding recurring series into their individual occurrences. Targets the default calendar unless calendarId is set.',
|
|
68
|
+
inputSchema,
|
|
69
|
+
outputSchema,
|
|
70
|
+
annotations: {
|
|
71
|
+
readOnlyHint: true,
|
|
72
|
+
destructiveHint: false,
|
|
73
|
+
idempotentHint: true,
|
|
74
|
+
openWorldHint: true,
|
|
75
|
+
},
|
|
76
|
+
connection: "microsoft-outlook",
|
|
77
|
+
run: async (input, ctx) => {
|
|
78
|
+
// `@odata.nextLink` is an opaque full URL — when paging, fetch it verbatim
|
|
79
|
+
// and skip rebuilding the path/query.
|
|
80
|
+
let url: string;
|
|
81
|
+
if (input.cursor !== undefined) {
|
|
82
|
+
url = input.cursor;
|
|
83
|
+
} else {
|
|
84
|
+
// calendarView takes literal startDateTime/endDateTime params (not
|
|
85
|
+
// $-prefixed), plus the standard $top page size.
|
|
86
|
+
const sp = new URLSearchParams();
|
|
87
|
+
sp.set("startDateTime", input.startDateTime);
|
|
88
|
+
sp.set("endDateTime", input.endDateTime);
|
|
89
|
+
sp.set("$top", String(input.limit ?? 20));
|
|
90
|
+
url = `${GRAPH_BASE}${calendarRoot(input.mailbox, input.calendarId)}/calendarView?${sp.toString()}`;
|
|
91
|
+
}
|
|
92
|
+
const res = await outlookFetch(ctx.fetch, "listCalendarView", url);
|
|
93
|
+
return toListResult(await res.json());
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export default definition;
|
|
98
|
+
|
|
99
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import {
|
|
7
|
+
buildListQuery,
|
|
8
|
+
GRAPH_BASE,
|
|
9
|
+
mailboxRoot,
|
|
10
|
+
outlookFetch,
|
|
11
|
+
toListResult,
|
|
12
|
+
} from "../lib/graph.ts";
|
|
13
|
+
|
|
14
|
+
const inputSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
mailbox: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe(
|
|
19
|
+
"Shared-mailbox address (UPN/email) to read instead of your own, e.g. team@contoso.com. Requires shared-mailbox delegation. Omit for your own mailbox.",
|
|
20
|
+
)
|
|
21
|
+
.optional(),
|
|
22
|
+
limit: z
|
|
23
|
+
.number()
|
|
24
|
+
.int()
|
|
25
|
+
.gte(1)
|
|
26
|
+
.describe(
|
|
27
|
+
"Calendars per page. Defaults to 20 when omitted; pass a value when you need a specific number of results.",
|
|
28
|
+
)
|
|
29
|
+
.optional(),
|
|
30
|
+
cursor: z
|
|
31
|
+
.string()
|
|
32
|
+
.describe(
|
|
33
|
+
"Pagination cursor from a previous response's next_cursor. Omit for the first page.",
|
|
34
|
+
)
|
|
35
|
+
.optional(),
|
|
36
|
+
})
|
|
37
|
+
.strict();
|
|
38
|
+
|
|
39
|
+
const outputSchema = z.object({
|
|
40
|
+
items: z.array(
|
|
41
|
+
z.object({
|
|
42
|
+
id: z.string(),
|
|
43
|
+
name: z.string(),
|
|
44
|
+
isDefaultCalendar: z.boolean().optional(),
|
|
45
|
+
canEdit: z.boolean().optional(),
|
|
46
|
+
}),
|
|
47
|
+
),
|
|
48
|
+
next_cursor: z
|
|
49
|
+
.string()
|
|
50
|
+
.describe("Pass as cursor to fetch the next page. Absent on the last page.")
|
|
51
|
+
.optional(),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const definition = defineTool({
|
|
55
|
+
name: "listCalendars",
|
|
56
|
+
title: "List Calendars",
|
|
57
|
+
description:
|
|
58
|
+
"List the available calendars in a mailbox. The entry point for resolving a calendarId to pass to the event tools (listEvents, listCalendarView, createEvent, ...); omit calendarId on those tools to use the default calendar.",
|
|
59
|
+
inputSchema,
|
|
60
|
+
outputSchema,
|
|
61
|
+
annotations: {
|
|
62
|
+
readOnlyHint: true,
|
|
63
|
+
destructiveHint: false,
|
|
64
|
+
idempotentHint: true,
|
|
65
|
+
openWorldHint: true,
|
|
66
|
+
},
|
|
67
|
+
connection: "microsoft-outlook",
|
|
68
|
+
run: async (input, ctx) => {
|
|
69
|
+
// `@odata.nextLink` is an opaque full URL — when paging, fetch it verbatim
|
|
70
|
+
// and skip rebuilding the path/query.
|
|
71
|
+
let url: string;
|
|
72
|
+
if (input.cursor !== undefined) {
|
|
73
|
+
url = input.cursor;
|
|
74
|
+
} else {
|
|
75
|
+
const query = buildListQuery({ limit: input.limit ?? 20 });
|
|
76
|
+
url = `${GRAPH_BASE}${mailboxRoot(input.mailbox)}/calendars${query}`;
|
|
77
|
+
}
|
|
78
|
+
const res = await outlookFetch(ctx.fetch, "listCalendars", url);
|
|
79
|
+
return toListResult(await res.json());
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export default definition;
|
|
84
|
+
|
|
85
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import { GRAPH_BASE, outlookFetch, stripNullsDeep } from "../lib/graph.ts";
|
|
7
|
+
|
|
8
|
+
const inputSchema = z.object({}).strict();
|
|
9
|
+
|
|
10
|
+
const outputSchema = z.object({
|
|
11
|
+
items: z.array(
|
|
12
|
+
z.object({
|
|
13
|
+
id: z.string().optional(),
|
|
14
|
+
displayName: z.string(),
|
|
15
|
+
color: z
|
|
16
|
+
.string()
|
|
17
|
+
.describe('Preset color name, e.g. "preset0".')
|
|
18
|
+
.optional(),
|
|
19
|
+
}),
|
|
20
|
+
),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const definition = defineTool({
|
|
24
|
+
name: "listCategories",
|
|
25
|
+
title: "List Categories",
|
|
26
|
+
description:
|
|
27
|
+
"List the signed-in user's category names and colors. A discovery tool for the valid category names passed to updateMessage or createEvent — a category's color comes from the user's master list (you apply a category by its displayName). Only your own categories (no mailbox option).",
|
|
28
|
+
inputSchema,
|
|
29
|
+
outputSchema,
|
|
30
|
+
annotations: {
|
|
31
|
+
readOnlyHint: true,
|
|
32
|
+
destructiveHint: false,
|
|
33
|
+
idempotentHint: true,
|
|
34
|
+
openWorldHint: true,
|
|
35
|
+
},
|
|
36
|
+
connection: "microsoft-outlook",
|
|
37
|
+
run: async (_input, ctx) => {
|
|
38
|
+
// masterCategories is not paginated (no @odata.nextLink), so read the
|
|
39
|
+
// `value` array directly instead of going through toListResult.
|
|
40
|
+
const url = `${GRAPH_BASE}/me/outlook/masterCategories`;
|
|
41
|
+
const res = await outlookFetch(ctx.fetch, "listCategories", url);
|
|
42
|
+
const body = (await res.json()) as { value?: unknown[] };
|
|
43
|
+
return { items: (body.value ?? []).map((c) => stripNullsDeep(c)) };
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export default definition;
|
|
48
|
+
|
|
49
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import {
|
|
7
|
+
buildListQuery,
|
|
8
|
+
GRAPH_BASE,
|
|
9
|
+
outlookFetch,
|
|
10
|
+
toListResult,
|
|
11
|
+
} from "../lib/graph.ts";
|
|
12
|
+
import { contactSchema } from "../lib/schemas.ts";
|
|
13
|
+
|
|
14
|
+
const inputSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
filter: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe(
|
|
19
|
+
"OData $filter predicate. Only the email-match form is supported server-side, e.g. \"emailAddresses/any(a:a/address eq 'jane@contoso.com')\". Name search is NOT filterable — list and filter the returned results client-side instead. Omit to list all contacts.",
|
|
20
|
+
)
|
|
21
|
+
.optional(),
|
|
22
|
+
limit: z
|
|
23
|
+
.number()
|
|
24
|
+
.int()
|
|
25
|
+
.gte(1)
|
|
26
|
+
.describe(
|
|
27
|
+
"Contacts per page. Defaults to 20 when omitted; pass a value when you need a specific number of results.",
|
|
28
|
+
)
|
|
29
|
+
.optional(),
|
|
30
|
+
cursor: z
|
|
31
|
+
.string()
|
|
32
|
+
.describe(
|
|
33
|
+
"Pagination cursor from a previous response's next_cursor. Omit for the first page.",
|
|
34
|
+
)
|
|
35
|
+
.optional(),
|
|
36
|
+
})
|
|
37
|
+
.strict();
|
|
38
|
+
|
|
39
|
+
const outputSchema = z.object({
|
|
40
|
+
items: z.array(contactSchema),
|
|
41
|
+
next_cursor: z
|
|
42
|
+
.string()
|
|
43
|
+
.describe("Pass as cursor to fetch the next page. Absent on the last page.")
|
|
44
|
+
.optional(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const definition = defineTool({
|
|
48
|
+
name: "listContacts",
|
|
49
|
+
title: "List Contacts",
|
|
50
|
+
description:
|
|
51
|
+
"List or search the user's personal contacts. Use filter to match by email, e.g. \"emailAddresses/any(a:a/address eq 'jane@contoso.com')\"; name search isn't filterable server-side, so list and match the returned results yourself. The entry point for resolving a contact id before getContact/updateContact/deleteContact.",
|
|
52
|
+
inputSchema,
|
|
53
|
+
outputSchema,
|
|
54
|
+
annotations: {
|
|
55
|
+
readOnlyHint: true,
|
|
56
|
+
destructiveHint: false,
|
|
57
|
+
idempotentHint: true,
|
|
58
|
+
openWorldHint: true,
|
|
59
|
+
},
|
|
60
|
+
connection: "microsoft-outlook",
|
|
61
|
+
run: async (input, ctx) => {
|
|
62
|
+
// `@odata.nextLink` is an opaque full URL — when paging, fetch it verbatim
|
|
63
|
+
// and skip rebuilding the path/query.
|
|
64
|
+
let url: string;
|
|
65
|
+
if (input.cursor !== undefined) {
|
|
66
|
+
url = input.cursor;
|
|
67
|
+
} else {
|
|
68
|
+
const query = buildListQuery({
|
|
69
|
+
limit: input.limit ?? 20,
|
|
70
|
+
filter: input.filter,
|
|
71
|
+
});
|
|
72
|
+
url = `${GRAPH_BASE}/me/contacts${query}`;
|
|
73
|
+
}
|
|
74
|
+
const res = await outlookFetch(ctx.fetch, "listContacts", url);
|
|
75
|
+
return toListResult(await res.json());
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export default definition;
|
|
80
|
+
|
|
81
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import {
|
|
7
|
+
buildListQuery,
|
|
8
|
+
calendarRoot,
|
|
9
|
+
GRAPH_BASE,
|
|
10
|
+
outlookFetch,
|
|
11
|
+
toListResult,
|
|
12
|
+
} from "../lib/graph.ts";
|
|
13
|
+
import { eventListItemSchema } from "../lib/schemas.ts";
|
|
14
|
+
|
|
15
|
+
const inputSchema = z
|
|
16
|
+
.object({
|
|
17
|
+
filter: z
|
|
18
|
+
.string()
|
|
19
|
+
.describe(
|
|
20
|
+
"OData $filter predicate for exact matches, e.g. \"subject eq 'Standup'\" or \"showAs eq 'busy'\". Omit to list all events.",
|
|
21
|
+
)
|
|
22
|
+
.optional(),
|
|
23
|
+
mailbox: z
|
|
24
|
+
.string()
|
|
25
|
+
.describe(
|
|
26
|
+
"Shared-mailbox address (UPN/email) to read instead of your own, e.g. team@contoso.com. Requires shared-mailbox delegation. Omit for your own mailbox.",
|
|
27
|
+
)
|
|
28
|
+
.optional(),
|
|
29
|
+
calendarId: z
|
|
30
|
+
.string()
|
|
31
|
+
.describe(
|
|
32
|
+
"Target a specific calendar (id from listCalendars). Omit to use the default calendar.",
|
|
33
|
+
)
|
|
34
|
+
.optional(),
|
|
35
|
+
limit: z
|
|
36
|
+
.number()
|
|
37
|
+
.int()
|
|
38
|
+
.gte(1)
|
|
39
|
+
.describe(
|
|
40
|
+
"Events per page. Defaults to 20 when omitted; pass a value when you need a specific number of results.",
|
|
41
|
+
)
|
|
42
|
+
.optional(),
|
|
43
|
+
cursor: z
|
|
44
|
+
.string()
|
|
45
|
+
.describe(
|
|
46
|
+
"Pagination cursor from a previous response's next_cursor. Omit for the first page.",
|
|
47
|
+
)
|
|
48
|
+
.optional(),
|
|
49
|
+
})
|
|
50
|
+
.strict();
|
|
51
|
+
|
|
52
|
+
const outputSchema = z.object({
|
|
53
|
+
items: z.array(eventListItemSchema),
|
|
54
|
+
next_cursor: z
|
|
55
|
+
.string()
|
|
56
|
+
.describe("Pass as cursor to fetch the next page. Absent on the last page.")
|
|
57
|
+
.optional(),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const definition = defineTool({
|
|
61
|
+
name: "listEvents",
|
|
62
|
+
title: "List Events",
|
|
63
|
+
description:
|
|
64
|
+
"List a calendar's events: single events plus recurring SERIES MASTERS (the recurrence definition, not expanded occurrences). Use filter for exact predicates. To see what actually occurs within a date range — including each occurrence of a recurring series — use listCalendarView instead.",
|
|
65
|
+
inputSchema,
|
|
66
|
+
outputSchema,
|
|
67
|
+
annotations: {
|
|
68
|
+
readOnlyHint: true,
|
|
69
|
+
destructiveHint: false,
|
|
70
|
+
idempotentHint: true,
|
|
71
|
+
openWorldHint: true,
|
|
72
|
+
},
|
|
73
|
+
connection: "microsoft-outlook",
|
|
74
|
+
run: async (input, ctx) => {
|
|
75
|
+
// `@odata.nextLink` is an opaque full URL — when paging, fetch it verbatim
|
|
76
|
+
// and skip rebuilding the path/query.
|
|
77
|
+
let url: string;
|
|
78
|
+
if (input.cursor !== undefined) {
|
|
79
|
+
url = input.cursor;
|
|
80
|
+
} else {
|
|
81
|
+
const query = buildListQuery({
|
|
82
|
+
limit: input.limit ?? 20,
|
|
83
|
+
filter: input.filter,
|
|
84
|
+
});
|
|
85
|
+
url = `${GRAPH_BASE}${calendarRoot(input.mailbox, input.calendarId)}/events${query}`;
|
|
86
|
+
}
|
|
87
|
+
const res = await outlookFetch(ctx.fetch, "listEvents", url);
|
|
88
|
+
return toListResult(await res.json());
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export default definition;
|
|
93
|
+
|
|
94
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|