@jbctechsolutions/mcp-office365 2.5.1
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 +21 -0
- package/README.md +667 -0
- package/dist/applescript/account-repository.d.ts +30 -0
- package/dist/applescript/account-repository.d.ts.map +1 -0
- package/dist/applescript/account-repository.js +38 -0
- package/dist/applescript/account-repository.js.map +1 -0
- package/dist/applescript/account-scripts.d.ts +21 -0
- package/dist/applescript/account-scripts.d.ts.map +1 -0
- package/dist/applescript/account-scripts.js +180 -0
- package/dist/applescript/account-scripts.js.map +1 -0
- package/dist/applescript/calendar-manager.d.ts +44 -0
- package/dist/applescript/calendar-manager.d.ts.map +1 -0
- package/dist/applescript/calendar-manager.js +92 -0
- package/dist/applescript/calendar-manager.js.map +1 -0
- package/dist/applescript/calendar-writer.d.ts +36 -0
- package/dist/applescript/calendar-writer.d.ts.map +1 -0
- package/dist/applescript/calendar-writer.js +94 -0
- package/dist/applescript/calendar-writer.js.map +1 -0
- package/dist/applescript/content-readers.d.ts +114 -0
- package/dist/applescript/content-readers.d.ts.map +1 -0
- package/dist/applescript/content-readers.js +328 -0
- package/dist/applescript/content-readers.js.map +1 -0
- package/dist/applescript/executor.d.ts +60 -0
- package/dist/applescript/executor.d.ts.map +1 -0
- package/dist/applescript/executor.js +173 -0
- package/dist/applescript/executor.js.map +1 -0
- package/dist/applescript/index.d.ts +20 -0
- package/dist/applescript/index.d.ts.map +1 -0
- package/dist/applescript/index.js +29 -0
- package/dist/applescript/index.js.map +1 -0
- package/dist/applescript/mail-sender.d.ts +38 -0
- package/dist/applescript/mail-sender.d.ts.map +1 -0
- package/dist/applescript/mail-sender.js +67 -0
- package/dist/applescript/mail-sender.js.map +1 -0
- package/dist/applescript/parser.d.ts +235 -0
- package/dist/applescript/parser.d.ts.map +1 -0
- package/dist/applescript/parser.js +496 -0
- package/dist/applescript/parser.js.map +1 -0
- package/dist/applescript/repository.d.ts +64 -0
- package/dist/applescript/repository.d.ts.map +1 -0
- package/dist/applescript/repository.js +444 -0
- package/dist/applescript/repository.js.map +1 -0
- package/dist/applescript/scripts.d.ts +265 -0
- package/dist/applescript/scripts.d.ts.map +1 -0
- package/dist/applescript/scripts.js +1483 -0
- package/dist/applescript/scripts.js.map +1 -0
- package/dist/approval/hash.d.ts +87 -0
- package/dist/approval/hash.d.ts.map +1 -0
- package/dist/approval/hash.js +102 -0
- package/dist/approval/hash.js.map +1 -0
- package/dist/approval/index.d.ts +13 -0
- package/dist/approval/index.d.ts.map +1 -0
- package/dist/approval/index.js +7 -0
- package/dist/approval/index.js.map +1 -0
- package/dist/approval/token-manager.d.ts +51 -0
- package/dist/approval/token-manager.d.ts.map +1 -0
- package/dist/approval/token-manager.js +111 -0
- package/dist/approval/token-manager.js.map +1 -0
- package/dist/approval/types.d.ts +44 -0
- package/dist/approval/types.d.ts.map +1 -0
- package/dist/approval/types.js +6 -0
- package/dist/approval/types.js.map +1 -0
- package/dist/cli.d.ts +30 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +143 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +42 -0
- package/dist/config.js.map +1 -0
- package/dist/database/connection.d.ts +77 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +130 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/database/index.d.ts +11 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +11 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/queries.d.ts +93 -0
- package/dist/database/queries.d.ts.map +1 -0
- package/dist/database/queries.js +430 -0
- package/dist/database/queries.js.map +1 -0
- package/dist/database/repository.d.ts +198 -0
- package/dist/database/repository.d.ts.map +1 -0
- package/dist/database/repository.js +199 -0
- package/dist/database/repository.js.map +1 -0
- package/dist/graph/attachments.d.ts +72 -0
- package/dist/graph/attachments.d.ts.map +1 -0
- package/dist/graph/attachments.js +207 -0
- package/dist/graph/attachments.js.map +1 -0
- package/dist/graph/auth/config.d.ts +34 -0
- package/dist/graph/auth/config.d.ts.map +1 -0
- package/dist/graph/auth/config.js +78 -0
- package/dist/graph/auth/config.js.map +1 -0
- package/dist/graph/auth/device-code-flow.d.ts +55 -0
- package/dist/graph/auth/device-code-flow.d.ts.map +1 -0
- package/dist/graph/auth/device-code-flow.js +180 -0
- package/dist/graph/auth/device-code-flow.js.map +1 -0
- package/dist/graph/auth/index.d.ts +13 -0
- package/dist/graph/auth/index.d.ts.map +1 -0
- package/dist/graph/auth/index.js +13 -0
- package/dist/graph/auth/index.js.map +1 -0
- package/dist/graph/auth/token-cache.d.ts +41 -0
- package/dist/graph/auth/token-cache.d.ts.map +1 -0
- package/dist/graph/auth/token-cache.js +105 -0
- package/dist/graph/auth/token-cache.js.map +1 -0
- package/dist/graph/client/batch.d.ts +38 -0
- package/dist/graph/client/batch.d.ts.map +1 -0
- package/dist/graph/client/batch.js +33 -0
- package/dist/graph/client/batch.js.map +1 -0
- package/dist/graph/client/cache.d.ts +64 -0
- package/dist/graph/client/cache.d.ts.map +1 -0
- package/dist/graph/client/cache.js +108 -0
- package/dist/graph/client/cache.js.map +1 -0
- package/dist/graph/client/graph-client.d.ts +630 -0
- package/dist/graph/client/graph-client.d.ts.map +1 -0
- package/dist/graph/client/graph-client.js +1771 -0
- package/dist/graph/client/graph-client.js.map +1 -0
- package/dist/graph/client/index.d.ts +12 -0
- package/dist/graph/client/index.d.ts.map +1 -0
- package/dist/graph/client/index.js +12 -0
- package/dist/graph/client/index.js.map +1 -0
- package/dist/graph/content-readers.d.ts +106 -0
- package/dist/graph/content-readers.d.ts.map +1 -0
- package/dist/graph/content-readers.js +321 -0
- package/dist/graph/content-readers.js.map +1 -0
- package/dist/graph/index.d.ts +18 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +23 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/mailbox-adapter.d.ts +30 -0
- package/dist/graph/mailbox-adapter.d.ts.map +1 -0
- package/dist/graph/mailbox-adapter.js +59 -0
- package/dist/graph/mailbox-adapter.js.map +1 -0
- package/dist/graph/mappers/contact-mapper.d.ts +14 -0
- package/dist/graph/mappers/contact-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/contact-mapper.js +20 -0
- package/dist/graph/mappers/contact-mapper.js.map +1 -0
- package/dist/graph/mappers/email-mapper.d.ts +14 -0
- package/dist/graph/mappers/email-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/email-mapper.js +44 -0
- package/dist/graph/mappers/email-mapper.js.map +1 -0
- package/dist/graph/mappers/event-mapper.d.ts +14 -0
- package/dist/graph/mappers/event-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/event-mapper.js +31 -0
- package/dist/graph/mappers/event-mapper.js.map +1 -0
- package/dist/graph/mappers/folder-mapper.d.ts +22 -0
- package/dist/graph/mappers/folder-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/folder-mapper.js +51 -0
- package/dist/graph/mappers/folder-mapper.js.map +1 -0
- package/dist/graph/mappers/index.d.ts +16 -0
- package/dist/graph/mappers/index.d.ts.map +1 -0
- package/dist/graph/mappers/index.js +16 -0
- package/dist/graph/mappers/index.js.map +1 -0
- package/dist/graph/mappers/task-mapper.d.ts +20 -0
- package/dist/graph/mappers/task-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/task-mapper.js +27 -0
- package/dist/graph/mappers/task-mapper.js.map +1 -0
- package/dist/graph/mappers/utils.d.ts +97 -0
- package/dist/graph/mappers/utils.d.ts.map +1 -0
- package/dist/graph/mappers/utils.js +186 -0
- package/dist/graph/mappers/utils.js.map +1 -0
- package/dist/graph/repository.d.ts +1104 -0
- package/dist/graph/repository.d.ts.map +1 -0
- package/dist/graph/repository.js +2999 -0
- package/dist/graph/repository.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6052 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/html-stripper.d.ts +41 -0
- package/dist/parsers/html-stripper.d.ts.map +1 -0
- package/dist/parsers/html-stripper.js +179 -0
- package/dist/parsers/html-stripper.js.map +1 -0
- package/dist/parsers/index.d.ts +12 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +12 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/olk15.d.ts +87 -0
- package/dist/parsers/olk15.d.ts.map +1 -0
- package/dist/parsers/olk15.js +368 -0
- package/dist/parsers/olk15.js.map +1 -0
- package/dist/signature.d.ts +22 -0
- package/dist/signature.d.ts.map +1 -0
- package/dist/signature.js +89 -0
- package/dist/signature.js.map +1 -0
- package/dist/tools/calendar-permissions.d.ts +79 -0
- package/dist/tools/calendar-permissions.d.ts.map +1 -0
- package/dist/tools/calendar-permissions.js +121 -0
- package/dist/tools/calendar-permissions.js.map +1 -0
- package/dist/tools/calendar.d.ts +208 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/calendar.js +247 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/categories.d.ts +94 -0
- package/dist/tools/categories.d.ts.map +1 -0
- package/dist/tools/categories.js +117 -0
- package/dist/tools/categories.js.map +1 -0
- package/dist/tools/checklist-items.d.ts +89 -0
- package/dist/tools/checklist-items.d.ts.map +1 -0
- package/dist/tools/checklist-items.js +140 -0
- package/dist/tools/checklist-items.js.map +1 -0
- package/dist/tools/contacts.d.ts +94 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +134 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/excel.d.ts +96 -0
- package/dist/tools/excel.d.ts.map +1 -0
- package/dist/tools/excel.js +165 -0
- package/dist/tools/excel.js.map +1 -0
- package/dist/tools/focused-overrides.d.ts +70 -0
- package/dist/tools/focused-overrides.d.ts.map +1 -0
- package/dist/tools/focused-overrides.js +117 -0
- package/dist/tools/focused-overrides.js.map +1 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/linked-resources.d.ts +74 -0
- package/dist/tools/linked-resources.d.ts.map +1 -0
- package/dist/tools/linked-resources.js +122 -0
- package/dist/tools/linked-resources.js.map +1 -0
- package/dist/tools/mail-rules.d.ts +98 -0
- package/dist/tools/mail-rules.d.ts.map +1 -0
- package/dist/tools/mail-rules.js +169 -0
- package/dist/tools/mail-rules.js.map +1 -0
- package/dist/tools/mail-send.d.ts +314 -0
- package/dist/tools/mail-send.d.ts.map +1 -0
- package/dist/tools/mail-send.js +555 -0
- package/dist/tools/mail-send.js.map +1 -0
- package/dist/tools/mail.d.ts +127 -0
- package/dist/tools/mail.d.ts.map +1 -0
- package/dist/tools/mail.js +311 -0
- package/dist/tools/mail.js.map +1 -0
- package/dist/tools/mailbox-organization.d.ts +301 -0
- package/dist/tools/mailbox-organization.d.ts.map +1 -0
- package/dist/tools/mailbox-organization.js +541 -0
- package/dist/tools/mailbox-organization.js.map +1 -0
- package/dist/tools/meetings.d.ts +114 -0
- package/dist/tools/meetings.d.ts.map +1 -0
- package/dist/tools/meetings.js +110 -0
- package/dist/tools/meetings.js.map +1 -0
- package/dist/tools/notes.d.ts +74 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +136 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/onedrive.d.ts +194 -0
- package/dist/tools/onedrive.d.ts.map +1 -0
- package/dist/tools/onedrive.js +257 -0
- package/dist/tools/onedrive.js.map +1 -0
- package/dist/tools/people.d.ts +129 -0
- package/dist/tools/people.d.ts.map +1 -0
- package/dist/tools/people.js +195 -0
- package/dist/tools/people.js.map +1 -0
- package/dist/tools/planner-visualization.d.ts +91 -0
- package/dist/tools/planner-visualization.d.ts.map +1 -0
- package/dist/tools/planner-visualization.js +192 -0
- package/dist/tools/planner-visualization.js.map +1 -0
- package/dist/tools/planner.d.ts +288 -0
- package/dist/tools/planner.d.ts.map +1 -0
- package/dist/tools/planner.js +368 -0
- package/dist/tools/planner.js.map +1 -0
- package/dist/tools/scheduling.d.ts +49 -0
- package/dist/tools/scheduling.d.ts.map +1 -0
- package/dist/tools/scheduling.js +115 -0
- package/dist/tools/scheduling.js.map +1 -0
- package/dist/tools/sharepoint.d.ts +115 -0
- package/dist/tools/sharepoint.d.ts.map +1 -0
- package/dist/tools/sharepoint.js +99 -0
- package/dist/tools/sharepoint.js.map +1 -0
- package/dist/tools/task-attachments.d.ts +74 -0
- package/dist/tools/task-attachments.d.ts.map +1 -0
- package/dist/tools/task-attachments.js +122 -0
- package/dist/tools/task-attachments.js.map +1 -0
- package/dist/tools/tasks.d.ts +74 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +126 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/teams.d.ts +389 -0
- package/dist/tools/teams.d.ts.map +1 -0
- package/dist/tools/teams.js +546 -0
- package/dist/tools/teams.js.map +1 -0
- package/dist/types/calendar.d.ts +60 -0
- package/dist/types/calendar.d.ts.map +1 -0
- package/dist/types/calendar.js +15 -0
- package/dist/types/calendar.js.map +1 -0
- package/dist/types/contacts.d.ts +96 -0
- package/dist/types/contacts.d.ts.map +1 -0
- package/dist/types/contacts.js +41 -0
- package/dist/types/contacts.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mail.d.ts +108 -0
- package/dist/types/mail.d.ts.map +1 -0
- package/dist/types/mail.js +40 -0
- package/dist/types/mail.js.map +1 -0
- package/dist/types/notes.d.ts +26 -0
- package/dist/types/notes.d.ts.map +1 -0
- package/dist/types/notes.js +6 -0
- package/dist/types/notes.js.map +1 -0
- package/dist/types/tasks.d.ts +31 -0
- package/dist/types/tasks.d.ts.map +1 -0
- package/dist/types/tasks.js +6 -0
- package/dist/types/tasks.js.map +1 -0
- package/dist/utils/dates.d.ts +66 -0
- package/dist/utils/dates.d.ts.map +1 -0
- package/dist/utils/dates.js +94 -0
- package/dist/utils/dates.js.map +1 -0
- package/dist/utils/errors.d.ts +218 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +306 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/visualization/html.d.ts +26 -0
- package/dist/visualization/html.d.ts.map +1 -0
- package/dist/visualization/html.js +306 -0
- package/dist/visualization/html.js.map +1 -0
- package/dist/visualization/markdown.d.ts +25 -0
- package/dist/visualization/markdown.d.ts.map +1 -0
- package/dist/visualization/markdown.js +186 -0
- package/dist/visualization/markdown.js.map +1 -0
- package/dist/visualization/mermaid.d.ts +25 -0
- package/dist/visualization/mermaid.d.ts.map +1 -0
- package/dist/visualization/mermaid.js +158 -0
- package/dist/visualization/mermaid.js.map +1 -0
- package/dist/visualization/svg.d.ts +25 -0
- package/dist/visualization/svg.d.ts.map +1 -0
- package/dist/visualization/svg.js +282 -0
- package/dist/visualization/svg.js.map +1 -0
- package/dist/visualization/types.d.ts +43 -0
- package/dist/visualization/types.d.ts.map +1 -0
- package/dist/visualization/types.js +34 -0
- package/dist/visualization/types.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,1771 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 JBC Tech Solutions, LLC
|
|
3
|
+
* Licensed under the MIT License. See LICENSE file in the project root.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Microsoft Graph API client wrapper.
|
|
7
|
+
*
|
|
8
|
+
* Provides a typed interface to the Graph API with:
|
|
9
|
+
* - Automatic token management
|
|
10
|
+
* - Response caching
|
|
11
|
+
* - Pagination support
|
|
12
|
+
* - Error handling
|
|
13
|
+
*/
|
|
14
|
+
import 'isomorphic-fetch';
|
|
15
|
+
import { Client } from '@microsoft/microsoft-graph-client';
|
|
16
|
+
import { getAccessToken } from '../auth/index.js';
|
|
17
|
+
import { buildBatchPayload, splitIntoBatches, parseBatchResponse } from './batch.js';
|
|
18
|
+
import { ResponseCache, CacheTTL, createCacheKey } from './cache.js';
|
|
19
|
+
/**
|
|
20
|
+
* Graph client wrapper with caching and token management.
|
|
21
|
+
*/
|
|
22
|
+
export class GraphClient {
|
|
23
|
+
client = null;
|
|
24
|
+
cache = new ResponseCache();
|
|
25
|
+
deviceCodeCallback;
|
|
26
|
+
constructor(deviceCodeCallback) {
|
|
27
|
+
this.deviceCodeCallback = deviceCodeCallback;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Gets or creates the Graph client instance.
|
|
31
|
+
*/
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
33
|
+
async getClient() {
|
|
34
|
+
if (this.client == null) {
|
|
35
|
+
this.client = Client.init({
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
37
|
+
authProvider: async (done) => {
|
|
38
|
+
try {
|
|
39
|
+
const token = await getAccessToken(this.deviceCodeCallback);
|
|
40
|
+
done(null, token);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
done(error, null);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return this.client;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Clears the response cache.
|
|
52
|
+
*/
|
|
53
|
+
clearCache() {
|
|
54
|
+
this.cache.clear();
|
|
55
|
+
}
|
|
56
|
+
// ===========================================================================
|
|
57
|
+
// Mail Folders
|
|
58
|
+
// ===========================================================================
|
|
59
|
+
/**
|
|
60
|
+
* Lists all mail folders.
|
|
61
|
+
*/
|
|
62
|
+
async listMailFolders() {
|
|
63
|
+
const cacheKey = createCacheKey('listMailFolders');
|
|
64
|
+
const cached = this.cache.get(cacheKey);
|
|
65
|
+
if (cached != null) {
|
|
66
|
+
return cached;
|
|
67
|
+
}
|
|
68
|
+
const client = await this.getClient();
|
|
69
|
+
const result = [];
|
|
70
|
+
// Get top-level folders with pagination
|
|
71
|
+
let response = await client
|
|
72
|
+
.api('/me/mailFolders')
|
|
73
|
+
.select('id,displayName,parentFolderId,totalItemCount,unreadItemCount')
|
|
74
|
+
.top(100)
|
|
75
|
+
.get();
|
|
76
|
+
result.push(...response.value);
|
|
77
|
+
// Handle pagination
|
|
78
|
+
while (response['@odata.nextLink'] != null) {
|
|
79
|
+
response = await client.api(response['@odata.nextLink']).get();
|
|
80
|
+
result.push(...response.value);
|
|
81
|
+
}
|
|
82
|
+
// Also get child folders (one level deep)
|
|
83
|
+
for (const folder of [...result]) {
|
|
84
|
+
try {
|
|
85
|
+
const children = await client
|
|
86
|
+
.api(`/me/mailFolders/${folder.id}/childFolders`)
|
|
87
|
+
.select('id,displayName,parentFolderId,totalItemCount,unreadItemCount')
|
|
88
|
+
.get();
|
|
89
|
+
result.push(...children.value);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Some folders may not have children or may not be accessible
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
this.cache.set(cacheKey, result, CacheTTL.FOLDERS);
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Gets a specific mail folder by ID.
|
|
100
|
+
*/
|
|
101
|
+
async getMailFolder(folderId) {
|
|
102
|
+
const client = await this.getClient();
|
|
103
|
+
try {
|
|
104
|
+
return await client
|
|
105
|
+
.api(`/me/mailFolders/${folderId}`)
|
|
106
|
+
.select('id,displayName,parentFolderId,totalItemCount,unreadItemCount')
|
|
107
|
+
.get();
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// ===========================================================================
|
|
114
|
+
// Messages (Emails)
|
|
115
|
+
// ===========================================================================
|
|
116
|
+
/**
|
|
117
|
+
* Lists messages in a folder with pagination.
|
|
118
|
+
*/
|
|
119
|
+
async listMessages(folderId, limit = 50, skip = 0) {
|
|
120
|
+
const cacheKey = createCacheKey('listMessages', folderId, limit, skip);
|
|
121
|
+
const cached = this.cache.get(cacheKey);
|
|
122
|
+
if (cached != null) {
|
|
123
|
+
return cached;
|
|
124
|
+
}
|
|
125
|
+
const client = await this.getClient();
|
|
126
|
+
const response = await client
|
|
127
|
+
.api(`/me/mailFolders/${folderId}/messages`)
|
|
128
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId')
|
|
129
|
+
.orderby('receivedDateTime desc')
|
|
130
|
+
.top(limit)
|
|
131
|
+
.skip(skip)
|
|
132
|
+
.get();
|
|
133
|
+
const result = response.value;
|
|
134
|
+
this.cache.set(cacheKey, result, CacheTTL.EMAILS);
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Lists unread messages in a folder.
|
|
139
|
+
*/
|
|
140
|
+
async listUnreadMessages(folderId, limit = 50, skip = 0) {
|
|
141
|
+
const client = await this.getClient();
|
|
142
|
+
const response = await client
|
|
143
|
+
.api(`/me/mailFolders/${folderId}/messages`)
|
|
144
|
+
.filter('isRead eq false')
|
|
145
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId')
|
|
146
|
+
.orderby('receivedDateTime desc')
|
|
147
|
+
.top(limit)
|
|
148
|
+
.skip(skip)
|
|
149
|
+
.get();
|
|
150
|
+
return response.value;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Searches messages across all folders.
|
|
154
|
+
*/
|
|
155
|
+
async searchMessages(query, limit = 50) {
|
|
156
|
+
const client = await this.getClient();
|
|
157
|
+
const response = await client
|
|
158
|
+
.api('/me/messages')
|
|
159
|
+
.search(`"${query}"`)
|
|
160
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId,parentFolderId')
|
|
161
|
+
.top(limit)
|
|
162
|
+
.get();
|
|
163
|
+
return response.value;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Searches messages in a specific folder.
|
|
167
|
+
*/
|
|
168
|
+
async searchMessagesInFolder(folderId, query, limit = 50) {
|
|
169
|
+
const client = await this.getClient();
|
|
170
|
+
const response = await client
|
|
171
|
+
.api(`/me/mailFolders/${folderId}/messages`)
|
|
172
|
+
.search(`"${query}"`)
|
|
173
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId')
|
|
174
|
+
.top(limit)
|
|
175
|
+
.get();
|
|
176
|
+
return response.value;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Searches messages using raw KQL (Keyword Query Language).
|
|
180
|
+
* Unlike searchMessages, the query is passed directly without quote-wrapping,
|
|
181
|
+
* enabling KQL operators like from:, subject:, hasAttachments:, received>=, AND, OR.
|
|
182
|
+
*/
|
|
183
|
+
async searchMessagesKql(query, limit = 50) {
|
|
184
|
+
const client = await this.getClient();
|
|
185
|
+
const response = await client
|
|
186
|
+
.api('/me/messages')
|
|
187
|
+
.search(query)
|
|
188
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId,parentFolderId')
|
|
189
|
+
.top(limit)
|
|
190
|
+
.get();
|
|
191
|
+
return response.value;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Searches messages in a specific folder using raw KQL.
|
|
195
|
+
*/
|
|
196
|
+
async searchMessagesKqlInFolder(folderId, query, limit = 50) {
|
|
197
|
+
const client = await this.getClient();
|
|
198
|
+
const response = await client
|
|
199
|
+
.api(`/me/mailFolders/${folderId}/messages`)
|
|
200
|
+
.search(query)
|
|
201
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId,parentFolderId')
|
|
202
|
+
.top(limit)
|
|
203
|
+
.get();
|
|
204
|
+
return response.value;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Lists messages in a conversation by conversationId.
|
|
208
|
+
*/
|
|
209
|
+
async listConversationMessages(conversationId, limit = 50) {
|
|
210
|
+
const client = await this.getClient();
|
|
211
|
+
const response = await client
|
|
212
|
+
.api('/me/messages')
|
|
213
|
+
.filter(`conversationId eq '${conversationId}'`)
|
|
214
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId,parentFolderId')
|
|
215
|
+
.orderby('receivedDateTime asc')
|
|
216
|
+
.top(limit)
|
|
217
|
+
.get();
|
|
218
|
+
return response.value;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Gets a specific message with full body.
|
|
222
|
+
*/
|
|
223
|
+
async getMessage(messageId) {
|
|
224
|
+
const client = await this.getClient();
|
|
225
|
+
try {
|
|
226
|
+
return await client
|
|
227
|
+
.api(`/me/messages/${messageId}`)
|
|
228
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,body,bodyPreview,conversationId,internetMessageId,parentFolderId')
|
|
229
|
+
.get();
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Gets message delta for incremental sync.
|
|
237
|
+
*/
|
|
238
|
+
async getMessagesDelta(folderId, deltaLink) {
|
|
239
|
+
const client = await this.getClient();
|
|
240
|
+
let response;
|
|
241
|
+
if (deltaLink != null) {
|
|
242
|
+
response = await client.api(deltaLink).get();
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
response = await client
|
|
246
|
+
.api(`/me/mailFolders/${folderId}/messages/delta`)
|
|
247
|
+
.select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag,bodyPreview,conversationId,internetMessageId,parentFolderId')
|
|
248
|
+
.top(50)
|
|
249
|
+
.get();
|
|
250
|
+
}
|
|
251
|
+
const messages = [...(response.value ?? [])];
|
|
252
|
+
let nextLink = response['@odata.nextLink'];
|
|
253
|
+
while (nextLink != null) {
|
|
254
|
+
const nextPage = await client.api(nextLink).get();
|
|
255
|
+
messages.push(...(nextPage.value ?? []));
|
|
256
|
+
nextLink = nextPage['@odata.nextLink'];
|
|
257
|
+
}
|
|
258
|
+
const newDeltaLink = response['@odata.deltaLink'] ?? '';
|
|
259
|
+
return { messages, deltaLink: newDeltaLink };
|
|
260
|
+
}
|
|
261
|
+
// ===========================================================================
|
|
262
|
+
// Mail Rules
|
|
263
|
+
// ===========================================================================
|
|
264
|
+
/**
|
|
265
|
+
* Lists all inbox mail rules.
|
|
266
|
+
*/
|
|
267
|
+
async listMailRules() {
|
|
268
|
+
const client = await this.getClient();
|
|
269
|
+
const response = await client
|
|
270
|
+
.api('/me/mailFolders/inbox/messageRules')
|
|
271
|
+
.get();
|
|
272
|
+
return response.value;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Creates a new inbox mail rule.
|
|
276
|
+
*/
|
|
277
|
+
async createMailRule(rule) {
|
|
278
|
+
const client = await this.getClient();
|
|
279
|
+
const result = await client
|
|
280
|
+
.api('/me/mailFolders/inbox/messageRules')
|
|
281
|
+
.post(rule);
|
|
282
|
+
this.cache.clear();
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Deletes an inbox mail rule.
|
|
287
|
+
*/
|
|
288
|
+
async deleteMailRule(ruleId) {
|
|
289
|
+
const client = await this.getClient();
|
|
290
|
+
await client
|
|
291
|
+
.api(`/me/mailFolders/inbox/messageRules/${ruleId}`)
|
|
292
|
+
.delete();
|
|
293
|
+
this.cache.clear();
|
|
294
|
+
}
|
|
295
|
+
// ===========================================================================
|
|
296
|
+
// Automatic Replies (Out of Office)
|
|
297
|
+
// ===========================================================================
|
|
298
|
+
/**
|
|
299
|
+
* Gets the automatic replies (OOF) settings.
|
|
300
|
+
*/
|
|
301
|
+
async getAutomaticReplies() {
|
|
302
|
+
const client = await this.getClient();
|
|
303
|
+
return await client.api('/me/mailboxSettings/automaticRepliesSetting').get();
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Sets the automatic replies (OOF) settings.
|
|
307
|
+
*/
|
|
308
|
+
async setAutomaticReplies(settings) {
|
|
309
|
+
const client = await this.getClient();
|
|
310
|
+
await client.api('/me/mailboxSettings').patch({ automaticRepliesSetting: settings });
|
|
311
|
+
}
|
|
312
|
+
// ===========================================================================
|
|
313
|
+
// Mailbox Settings
|
|
314
|
+
// ===========================================================================
|
|
315
|
+
/**
|
|
316
|
+
* Gets the full mailbox settings for the current user.
|
|
317
|
+
*/
|
|
318
|
+
async getMailboxSettings() {
|
|
319
|
+
const client = await this.getClient();
|
|
320
|
+
return await client.api('/me/mailboxSettings').get();
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Updates mailbox settings for the current user.
|
|
324
|
+
*/
|
|
325
|
+
async updateMailboxSettings(settings) {
|
|
326
|
+
const client = await this.getClient();
|
|
327
|
+
await client.api('/me/mailboxSettings').patch(settings);
|
|
328
|
+
}
|
|
329
|
+
// ===========================================================================
|
|
330
|
+
// Calendars
|
|
331
|
+
// ===========================================================================
|
|
332
|
+
/**
|
|
333
|
+
* Lists all calendars.
|
|
334
|
+
*/
|
|
335
|
+
async listCalendars() {
|
|
336
|
+
const cacheKey = createCacheKey('listCalendars');
|
|
337
|
+
const cached = this.cache.get(cacheKey);
|
|
338
|
+
if (cached != null) {
|
|
339
|
+
return cached;
|
|
340
|
+
}
|
|
341
|
+
const client = await this.getClient();
|
|
342
|
+
const response = await client
|
|
343
|
+
.api('/me/calendars')
|
|
344
|
+
.select('id,name,color,isDefaultCalendar,canEdit')
|
|
345
|
+
.get();
|
|
346
|
+
const result = response.value;
|
|
347
|
+
this.cache.set(cacheKey, result, CacheTTL.FOLDERS);
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
// ===========================================================================
|
|
351
|
+
// Events
|
|
352
|
+
// ===========================================================================
|
|
353
|
+
/**
|
|
354
|
+
* Lists events with optional date range.
|
|
355
|
+
*/
|
|
356
|
+
async listEvents(limit = 50, calendarId, startDate, endDate) {
|
|
357
|
+
const client = await this.getClient();
|
|
358
|
+
// If date range provided, use calendarView
|
|
359
|
+
if (startDate != null && endDate != null) {
|
|
360
|
+
const baseUrl = calendarId != null
|
|
361
|
+
? `/me/calendars/${calendarId}/calendarView`
|
|
362
|
+
: '/me/calendarView';
|
|
363
|
+
const response = await client
|
|
364
|
+
.api(baseUrl)
|
|
365
|
+
.query({
|
|
366
|
+
startDateTime: startDate.toISOString(),
|
|
367
|
+
endDateTime: endDate.toISOString(),
|
|
368
|
+
})
|
|
369
|
+
.select('id,subject,start,end,location,isAllDay,organizer,attendees,body,recurrence,iCalUId')
|
|
370
|
+
.orderby('start/dateTime')
|
|
371
|
+
.top(limit)
|
|
372
|
+
.get();
|
|
373
|
+
return response.value;
|
|
374
|
+
}
|
|
375
|
+
// Otherwise, get upcoming events
|
|
376
|
+
const baseUrl = calendarId != null
|
|
377
|
+
? `/me/calendars/${calendarId}/events`
|
|
378
|
+
: '/me/events';
|
|
379
|
+
const response = await client
|
|
380
|
+
.api(baseUrl)
|
|
381
|
+
.select('id,subject,start,end,location,isAllDay,organizer,attendees,body,recurrence,iCalUId')
|
|
382
|
+
.orderby('start/dateTime')
|
|
383
|
+
.top(limit)
|
|
384
|
+
.get();
|
|
385
|
+
return response.value;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Gets a specific event.
|
|
389
|
+
*/
|
|
390
|
+
async getEvent(eventId) {
|
|
391
|
+
const client = await this.getClient();
|
|
392
|
+
try {
|
|
393
|
+
return await client
|
|
394
|
+
.api(`/me/events/${eventId}`)
|
|
395
|
+
.select('id,subject,start,end,location,isAllDay,organizer,attendees,body,recurrence,iCalUId')
|
|
396
|
+
.get();
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Lists instances of a recurring event within a date range.
|
|
404
|
+
*/
|
|
405
|
+
async listEventInstances(eventId, startDateTime, endDateTime) {
|
|
406
|
+
const client = await this.getClient();
|
|
407
|
+
const response = await client
|
|
408
|
+
.api(`/me/events/${eventId}/instances`)
|
|
409
|
+
.query({ startDateTime, endDateTime })
|
|
410
|
+
.select('id,subject,start,end,location,isAllDay,isCancelled,organizer,recurrence,bodyPreview')
|
|
411
|
+
.get();
|
|
412
|
+
return response.value;
|
|
413
|
+
}
|
|
414
|
+
// ===========================================================================
|
|
415
|
+
// Calendar Write Operations
|
|
416
|
+
// ===========================================================================
|
|
417
|
+
/**
|
|
418
|
+
* Creates a new calendar event.
|
|
419
|
+
*/
|
|
420
|
+
async createEvent(event, calendarId) {
|
|
421
|
+
const client = await this.getClient();
|
|
422
|
+
const url = calendarId != null
|
|
423
|
+
? `/me/calendars/${calendarId}/events`
|
|
424
|
+
: '/me/events';
|
|
425
|
+
const result = await client
|
|
426
|
+
.api(url)
|
|
427
|
+
.post(event);
|
|
428
|
+
this.cache.clear();
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Updates an existing calendar event.
|
|
433
|
+
*/
|
|
434
|
+
async updateEvent(eventId, updates) {
|
|
435
|
+
const client = await this.getClient();
|
|
436
|
+
await client
|
|
437
|
+
.api(`/me/events/${eventId}`)
|
|
438
|
+
.patch(updates);
|
|
439
|
+
this.cache.clear();
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Deletes a calendar event.
|
|
443
|
+
*/
|
|
444
|
+
async deleteEvent(eventId) {
|
|
445
|
+
const client = await this.getClient();
|
|
446
|
+
await client
|
|
447
|
+
.api(`/me/events/${eventId}`)
|
|
448
|
+
.delete();
|
|
449
|
+
this.cache.clear();
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Responds to a calendar event invitation.
|
|
453
|
+
*/
|
|
454
|
+
async respondToEvent(eventId, response, sendResponse, comment) {
|
|
455
|
+
const client = await this.getClient();
|
|
456
|
+
const actionMap = {
|
|
457
|
+
accept: 'accept',
|
|
458
|
+
decline: 'decline',
|
|
459
|
+
tentative: 'tentativelyAccept',
|
|
460
|
+
};
|
|
461
|
+
const action = actionMap[response];
|
|
462
|
+
await client
|
|
463
|
+
.api(`/me/events/${eventId}/${action}`)
|
|
464
|
+
.post({ sendResponse, comment: comment ?? '' });
|
|
465
|
+
this.cache.clear();
|
|
466
|
+
}
|
|
467
|
+
// ===========================================================================
|
|
468
|
+
// Contacts
|
|
469
|
+
// ===========================================================================
|
|
470
|
+
/**
|
|
471
|
+
* Lists contacts with pagination.
|
|
472
|
+
*/
|
|
473
|
+
async listContacts(limit = 50, skip = 0) {
|
|
474
|
+
const cacheKey = createCacheKey('listContacts', limit, skip);
|
|
475
|
+
const cached = this.cache.get(cacheKey);
|
|
476
|
+
if (cached != null) {
|
|
477
|
+
return cached;
|
|
478
|
+
}
|
|
479
|
+
const client = await this.getClient();
|
|
480
|
+
const response = await client
|
|
481
|
+
.api('/me/contacts')
|
|
482
|
+
.select('id,displayName,givenName,surname,middleName,nickName,companyName,jobTitle,department,emailAddresses,homePhones,businessPhones,mobilePhone,homeAddress,businessAddress,personalNotes')
|
|
483
|
+
.orderby('displayName')
|
|
484
|
+
.top(limit)
|
|
485
|
+
.skip(skip)
|
|
486
|
+
.get();
|
|
487
|
+
const result = response.value;
|
|
488
|
+
this.cache.set(cacheKey, result, CacheTTL.CONTACTS);
|
|
489
|
+
return result;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Searches contacts by display name.
|
|
493
|
+
*/
|
|
494
|
+
async searchContacts(query, limit = 50) {
|
|
495
|
+
const client = await this.getClient();
|
|
496
|
+
const response = await client
|
|
497
|
+
.api('/me/contacts')
|
|
498
|
+
.filter(`contains(displayName,'${query}')`)
|
|
499
|
+
.select('id,displayName,givenName,surname,middleName,nickName,companyName,jobTitle,department,emailAddresses,homePhones,businessPhones,mobilePhone,homeAddress,businessAddress,personalNotes')
|
|
500
|
+
.top(limit)
|
|
501
|
+
.get();
|
|
502
|
+
return response.value;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Gets a specific contact.
|
|
506
|
+
*/
|
|
507
|
+
async getContact(contactId) {
|
|
508
|
+
const client = await this.getClient();
|
|
509
|
+
try {
|
|
510
|
+
return await client
|
|
511
|
+
.api(`/me/contacts/${contactId}`)
|
|
512
|
+
.select('id,displayName,givenName,surname,middleName,nickName,companyName,jobTitle,department,emailAddresses,homePhones,businessPhones,mobilePhone,homeAddress,businessAddress,personalNotes')
|
|
513
|
+
.get();
|
|
514
|
+
}
|
|
515
|
+
catch {
|
|
516
|
+
return null;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
// ===========================================================================
|
|
520
|
+
// Contact Write Operations
|
|
521
|
+
// ===========================================================================
|
|
522
|
+
/**
|
|
523
|
+
* Creates a new contact.
|
|
524
|
+
*/
|
|
525
|
+
async createContact(contact) {
|
|
526
|
+
const client = await this.getClient();
|
|
527
|
+
const result = await client
|
|
528
|
+
.api('/me/contacts')
|
|
529
|
+
.post(contact);
|
|
530
|
+
this.cache.clear();
|
|
531
|
+
return result;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Updates an existing contact.
|
|
535
|
+
*/
|
|
536
|
+
async updateContact(contactId, updates) {
|
|
537
|
+
const client = await this.getClient();
|
|
538
|
+
await client
|
|
539
|
+
.api(`/me/contacts/${contactId}`)
|
|
540
|
+
.patch(updates);
|
|
541
|
+
this.cache.clear();
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Deletes a contact.
|
|
545
|
+
*/
|
|
546
|
+
async deleteContact(contactId) {
|
|
547
|
+
const client = await this.getClient();
|
|
548
|
+
await client
|
|
549
|
+
.api(`/me/contacts/${contactId}`)
|
|
550
|
+
.delete();
|
|
551
|
+
this.cache.clear();
|
|
552
|
+
}
|
|
553
|
+
// ===========================================================================
|
|
554
|
+
// Contact Photos
|
|
555
|
+
// ===========================================================================
|
|
556
|
+
/**
|
|
557
|
+
* Gets the photo for a contact as raw binary data.
|
|
558
|
+
*/
|
|
559
|
+
async getContactPhoto(contactId) {
|
|
560
|
+
const client = await this.getClient();
|
|
561
|
+
return await client
|
|
562
|
+
.api(`/me/contacts/${contactId}/photo/$value`)
|
|
563
|
+
.get();
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Sets or updates the photo for a contact.
|
|
567
|
+
*/
|
|
568
|
+
async setContactPhoto(contactId, photoData, contentType) {
|
|
569
|
+
const client = await this.getClient();
|
|
570
|
+
await client
|
|
571
|
+
.api(`/me/contacts/${contactId}/photo/$value`)
|
|
572
|
+
.header('Content-Type', contentType)
|
|
573
|
+
.put(photoData);
|
|
574
|
+
this.cache.clear();
|
|
575
|
+
}
|
|
576
|
+
// ===========================================================================
|
|
577
|
+
// Contact Folders
|
|
578
|
+
// ===========================================================================
|
|
579
|
+
/**
|
|
580
|
+
* Lists all contact folders.
|
|
581
|
+
*/
|
|
582
|
+
async listContactFolders() {
|
|
583
|
+
const client = await this.getClient();
|
|
584
|
+
const response = await client.api('/me/contactFolders').get();
|
|
585
|
+
return response.value;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Creates a new contact folder.
|
|
589
|
+
*/
|
|
590
|
+
async createContactFolder(displayName) {
|
|
591
|
+
const client = await this.getClient();
|
|
592
|
+
const result = await client.api('/me/contactFolders').post({ displayName });
|
|
593
|
+
this.cache.clear();
|
|
594
|
+
return result;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Deletes a contact folder.
|
|
598
|
+
*/
|
|
599
|
+
async deleteContactFolder(folderId) {
|
|
600
|
+
const client = await this.getClient();
|
|
601
|
+
await client.api(`/me/contactFolders/${folderId}`).delete();
|
|
602
|
+
this.cache.clear();
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Lists contacts in a specific contact folder.
|
|
606
|
+
*/
|
|
607
|
+
async listContactsInFolder(folderId, limit = 100) {
|
|
608
|
+
const client = await this.getClient();
|
|
609
|
+
const response = await client
|
|
610
|
+
.api(`/me/contactFolders/${folderId}/contacts`)
|
|
611
|
+
.select('id,displayName,givenName,surname,emailAddresses,businessPhones,mobilePhone,jobTitle,companyName')
|
|
612
|
+
.top(limit)
|
|
613
|
+
.get();
|
|
614
|
+
return response.value;
|
|
615
|
+
}
|
|
616
|
+
// ===========================================================================
|
|
617
|
+
// Tasks (Microsoft To Do)
|
|
618
|
+
// ===========================================================================
|
|
619
|
+
/**
|
|
620
|
+
* Lists task lists.
|
|
621
|
+
*/
|
|
622
|
+
async listTaskLists() {
|
|
623
|
+
const cacheKey = createCacheKey('listTaskLists');
|
|
624
|
+
const cached = this.cache.get(cacheKey);
|
|
625
|
+
if (cached != null) {
|
|
626
|
+
return cached;
|
|
627
|
+
}
|
|
628
|
+
const client = await this.getClient();
|
|
629
|
+
const response = await client
|
|
630
|
+
.api('/me/todo/lists')
|
|
631
|
+
.select('id,displayName,isOwner,isShared,wellknownListName')
|
|
632
|
+
.get();
|
|
633
|
+
const result = response.value;
|
|
634
|
+
this.cache.set(cacheKey, result, CacheTTL.FOLDERS);
|
|
635
|
+
return result;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Lists tasks in a task list.
|
|
639
|
+
*/
|
|
640
|
+
async listTasks(taskListId, limit = 50, skip = 0, includeCompleted = true) {
|
|
641
|
+
const client = await this.getClient();
|
|
642
|
+
let api = client
|
|
643
|
+
.api(`/me/todo/lists/${taskListId}/tasks`)
|
|
644
|
+
.select('id,title,status,importance,dueDateTime,completedDateTime,body,createdDateTime,lastModifiedDateTime,isReminderOn,reminderDateTime')
|
|
645
|
+
.top(limit)
|
|
646
|
+
.skip(skip);
|
|
647
|
+
if (!includeCompleted) {
|
|
648
|
+
api = api.filter("status ne 'completed'");
|
|
649
|
+
}
|
|
650
|
+
const response = await api.get();
|
|
651
|
+
return response.value;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Lists all tasks across all task lists.
|
|
655
|
+
*/
|
|
656
|
+
async listAllTasks(limit = 50, skip = 0, includeCompleted = true) {
|
|
657
|
+
const taskLists = await this.listTaskLists();
|
|
658
|
+
const allTasks = [];
|
|
659
|
+
for (const list of taskLists) {
|
|
660
|
+
if (list.id == null)
|
|
661
|
+
continue;
|
|
662
|
+
const tasks = await this.listTasks(list.id, 100, 0, includeCompleted);
|
|
663
|
+
for (const task of tasks) {
|
|
664
|
+
allTasks.push({ ...task, taskListId: list.id });
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
// Sort by due date, then slice for pagination
|
|
668
|
+
allTasks.sort((a, b) => {
|
|
669
|
+
if (a.dueDateTime == null && b.dueDateTime == null)
|
|
670
|
+
return 0;
|
|
671
|
+
if (a.dueDateTime == null)
|
|
672
|
+
return 1;
|
|
673
|
+
if (b.dueDateTime == null)
|
|
674
|
+
return -1;
|
|
675
|
+
return new Date(a.dueDateTime.dateTime ?? '').getTime() - new Date(b.dueDateTime.dateTime ?? '').getTime();
|
|
676
|
+
});
|
|
677
|
+
return allTasks.slice(skip, skip + limit);
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Gets a specific task.
|
|
681
|
+
*/
|
|
682
|
+
async getTask(taskListId, taskId) {
|
|
683
|
+
const client = await this.getClient();
|
|
684
|
+
try {
|
|
685
|
+
return await client
|
|
686
|
+
.api(`/me/todo/lists/${taskListId}/tasks/${taskId}`)
|
|
687
|
+
.select('id,title,status,importance,dueDateTime,completedDateTime,body,createdDateTime,lastModifiedDateTime,isReminderOn,reminderDateTime')
|
|
688
|
+
.get();
|
|
689
|
+
}
|
|
690
|
+
catch {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
// ===========================================================================
|
|
695
|
+
// Write Operations
|
|
696
|
+
// ===========================================================================
|
|
697
|
+
/**
|
|
698
|
+
* Moves a message to a different folder.
|
|
699
|
+
*/
|
|
700
|
+
async moveMessage(messageId, destinationFolderId) {
|
|
701
|
+
const client = await this.getClient();
|
|
702
|
+
await client
|
|
703
|
+
.api(`/me/messages/${messageId}/move`)
|
|
704
|
+
.post({ destinationId: destinationFolderId });
|
|
705
|
+
this.cache.clear(); // Invalidate cache after mutation
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Deletes a message (moves to Deleted Items).
|
|
709
|
+
*/
|
|
710
|
+
async deleteMessage(messageId) {
|
|
711
|
+
const client = await this.getClient();
|
|
712
|
+
// Move to deletedItems well-known folder
|
|
713
|
+
await client
|
|
714
|
+
.api(`/me/messages/${messageId}/move`)
|
|
715
|
+
.post({ destinationId: 'deleteditems' });
|
|
716
|
+
this.cache.clear();
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Archives a message (moves to Archive folder).
|
|
720
|
+
*/
|
|
721
|
+
async archiveMessage(messageId) {
|
|
722
|
+
const client = await this.getClient();
|
|
723
|
+
await client
|
|
724
|
+
.api(`/me/messages/${messageId}/move`)
|
|
725
|
+
.post({ destinationId: 'archive' });
|
|
726
|
+
this.cache.clear();
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Moves a message to the Junk folder.
|
|
730
|
+
*/
|
|
731
|
+
async junkMessage(messageId) {
|
|
732
|
+
const client = await this.getClient();
|
|
733
|
+
await client
|
|
734
|
+
.api(`/me/messages/${messageId}/move`)
|
|
735
|
+
.post({ destinationId: 'junkemail' });
|
|
736
|
+
this.cache.clear();
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Updates message properties (read status, flag, categories).
|
|
740
|
+
*/
|
|
741
|
+
async updateMessage(messageId, updates) {
|
|
742
|
+
const client = await this.getClient();
|
|
743
|
+
await client
|
|
744
|
+
.api(`/me/messages/${messageId}`)
|
|
745
|
+
.patch(updates);
|
|
746
|
+
this.cache.clear();
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Creates a new mail folder.
|
|
750
|
+
*/
|
|
751
|
+
async createMailFolder(displayName, parentFolderId) {
|
|
752
|
+
const client = await this.getClient();
|
|
753
|
+
const url = parentFolderId != null
|
|
754
|
+
? `/me/mailFolders/${parentFolderId}/childFolders`
|
|
755
|
+
: '/me/mailFolders';
|
|
756
|
+
const result = await client
|
|
757
|
+
.api(url)
|
|
758
|
+
.post({ displayName });
|
|
759
|
+
this.cache.clear();
|
|
760
|
+
return result;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Deletes a mail folder.
|
|
764
|
+
*/
|
|
765
|
+
async deleteMailFolder(folderId) {
|
|
766
|
+
const client = await this.getClient();
|
|
767
|
+
await client
|
|
768
|
+
.api(`/me/mailFolders/${folderId}`)
|
|
769
|
+
.delete();
|
|
770
|
+
this.cache.clear();
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Renames a mail folder.
|
|
774
|
+
*/
|
|
775
|
+
async renameMailFolder(folderId, newName) {
|
|
776
|
+
const client = await this.getClient();
|
|
777
|
+
await client
|
|
778
|
+
.api(`/me/mailFolders/${folderId}`)
|
|
779
|
+
.patch({ displayName: newName });
|
|
780
|
+
this.cache.clear();
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Moves a mail folder to a new parent.
|
|
784
|
+
*/
|
|
785
|
+
async moveMailFolder(folderId, destinationParentId) {
|
|
786
|
+
const client = await this.getClient();
|
|
787
|
+
await client
|
|
788
|
+
.api(`/me/mailFolders/${folderId}/move`)
|
|
789
|
+
.post({ destinationId: destinationParentId });
|
|
790
|
+
this.cache.clear();
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Deletes all messages in a folder.
|
|
794
|
+
*/
|
|
795
|
+
async emptyMailFolder(folderId) {
|
|
796
|
+
const client = await this.getClient();
|
|
797
|
+
// Get all messages in the folder
|
|
798
|
+
let response = await client
|
|
799
|
+
.api(`/me/mailFolders/${folderId}/messages`)
|
|
800
|
+
.select('id')
|
|
801
|
+
.top(100)
|
|
802
|
+
.get();
|
|
803
|
+
// Delete each message
|
|
804
|
+
for (const message of response.value) {
|
|
805
|
+
if (message.id != null) {
|
|
806
|
+
await client
|
|
807
|
+
.api(`/me/messages/${message.id}/move`)
|
|
808
|
+
.post({ destinationId: 'deleteditems' });
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
// Handle pagination
|
|
812
|
+
while (response['@odata.nextLink'] != null) {
|
|
813
|
+
response = await client.api(response['@odata.nextLink']).get();
|
|
814
|
+
for (const message of response.value) {
|
|
815
|
+
if (message.id != null) {
|
|
816
|
+
await client
|
|
817
|
+
.api(`/me/messages/${message.id}/move`)
|
|
818
|
+
.post({ destinationId: 'deleteditems' });
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
this.cache.clear();
|
|
823
|
+
}
|
|
824
|
+
// ===========================================================================
|
|
825
|
+
// Draft & Send Operations
|
|
826
|
+
// ===========================================================================
|
|
827
|
+
/**
|
|
828
|
+
* Creates a new draft message.
|
|
829
|
+
*/
|
|
830
|
+
async createDraft(message) {
|
|
831
|
+
const client = await this.getClient();
|
|
832
|
+
const result = await client
|
|
833
|
+
.api('/me/messages')
|
|
834
|
+
.post(message);
|
|
835
|
+
this.cache.clear();
|
|
836
|
+
return result;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Updates an existing draft message.
|
|
840
|
+
*/
|
|
841
|
+
async updateDraft(messageId, updates) {
|
|
842
|
+
const client = await this.getClient();
|
|
843
|
+
const result = await client
|
|
844
|
+
.api(`/me/messages/${messageId}`)
|
|
845
|
+
.patch(updates);
|
|
846
|
+
this.cache.clear();
|
|
847
|
+
return result;
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Sends an existing draft message.
|
|
851
|
+
*/
|
|
852
|
+
async sendDraft(messageId) {
|
|
853
|
+
const client = await this.getClient();
|
|
854
|
+
await client
|
|
855
|
+
.api(`/me/messages/${messageId}/send`)
|
|
856
|
+
.post(null);
|
|
857
|
+
this.cache.clear();
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Sends a new email directly without creating a draft.
|
|
861
|
+
*/
|
|
862
|
+
async sendMail(message) {
|
|
863
|
+
const client = await this.getClient();
|
|
864
|
+
await client
|
|
865
|
+
.api('/me/sendMail')
|
|
866
|
+
.post({ message });
|
|
867
|
+
this.cache.clear();
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Replies to a message, or replies to all recipients.
|
|
871
|
+
*/
|
|
872
|
+
async replyMessage(messageId, comment, replyAll) {
|
|
873
|
+
const client = await this.getClient();
|
|
874
|
+
const action = replyAll ? 'replyAll' : 'reply';
|
|
875
|
+
await client
|
|
876
|
+
.api(`/me/messages/${messageId}/${action}`)
|
|
877
|
+
.post({ comment });
|
|
878
|
+
this.cache.clear();
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Forwards a message to specified recipients.
|
|
882
|
+
*/
|
|
883
|
+
async forwardMessage(messageId, toRecipients, comment) {
|
|
884
|
+
const client = await this.getClient();
|
|
885
|
+
const body = { toRecipients };
|
|
886
|
+
if (comment != null) {
|
|
887
|
+
body.comment = comment;
|
|
888
|
+
}
|
|
889
|
+
await client
|
|
890
|
+
.api(`/me/messages/${messageId}/forward`)
|
|
891
|
+
.post(body);
|
|
892
|
+
this.cache.clear();
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Creates a reply draft for a message.
|
|
896
|
+
*/
|
|
897
|
+
async createReplyDraft(messageId) {
|
|
898
|
+
const client = await this.getClient();
|
|
899
|
+
const result = await client
|
|
900
|
+
.api(`/me/messages/${messageId}/createReply`)
|
|
901
|
+
.post(null);
|
|
902
|
+
this.cache.clear();
|
|
903
|
+
return result;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Creates a reply-all draft for a message.
|
|
907
|
+
*/
|
|
908
|
+
async createReplyAllDraft(messageId) {
|
|
909
|
+
const client = await this.getClient();
|
|
910
|
+
const result = await client
|
|
911
|
+
.api(`/me/messages/${messageId}/createReplyAll`)
|
|
912
|
+
.post(null);
|
|
913
|
+
this.cache.clear();
|
|
914
|
+
return result;
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Creates a forward draft for a message.
|
|
918
|
+
*/
|
|
919
|
+
async createForwardDraft(messageId) {
|
|
920
|
+
const client = await this.getClient();
|
|
921
|
+
const result = await client
|
|
922
|
+
.api(`/me/messages/${messageId}/createForward`)
|
|
923
|
+
.post(null);
|
|
924
|
+
this.cache.clear();
|
|
925
|
+
return result;
|
|
926
|
+
}
|
|
927
|
+
// ---------------------------------------------------------------------------
|
|
928
|
+
// Calendar Scheduling
|
|
929
|
+
// ---------------------------------------------------------------------------
|
|
930
|
+
/**
|
|
931
|
+
* Gets the free/busy schedule for one or more people.
|
|
932
|
+
* POST /me/calendar/getSchedule
|
|
933
|
+
*/
|
|
934
|
+
async getSchedule(params) {
|
|
935
|
+
const client = await this.getClient();
|
|
936
|
+
const response = await client.api('/me/calendar/getSchedule').post(params);
|
|
937
|
+
return response.value;
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Suggests meeting times for a set of attendees.
|
|
941
|
+
* POST /me/findMeetingTimes
|
|
942
|
+
*/
|
|
943
|
+
async findMeetingTimes(params) {
|
|
944
|
+
const client = await this.getClient();
|
|
945
|
+
return (await client.api('/me/findMeetingTimes').post(params));
|
|
946
|
+
}
|
|
947
|
+
// ===========================================================================
|
|
948
|
+
// Attachment Operations
|
|
949
|
+
// ===========================================================================
|
|
950
|
+
/**
|
|
951
|
+
* Lists attachments on a message.
|
|
952
|
+
*/
|
|
953
|
+
async listAttachments(messageId) {
|
|
954
|
+
const client = await this.getClient();
|
|
955
|
+
const response = await client
|
|
956
|
+
.api(`/me/messages/${messageId}/attachments`)
|
|
957
|
+
.select('id,name,size,contentType,isInline')
|
|
958
|
+
.get();
|
|
959
|
+
return response.value;
|
|
960
|
+
}
|
|
961
|
+
/**
|
|
962
|
+
* Gets a specific attachment with full content (including contentBytes).
|
|
963
|
+
*/
|
|
964
|
+
async getAttachment(messageId, attachmentId) {
|
|
965
|
+
const client = await this.getClient();
|
|
966
|
+
return await client
|
|
967
|
+
.api(`/me/messages/${messageId}/attachments/${attachmentId}`)
|
|
968
|
+
.get();
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* Adds an inline base64 attachment to a message (<= 3MB).
|
|
972
|
+
*/
|
|
973
|
+
async addAttachment(messageId, attachment) {
|
|
974
|
+
const client = await this.getClient();
|
|
975
|
+
const result = await client
|
|
976
|
+
.api(`/me/messages/${messageId}/attachments`)
|
|
977
|
+
.post(attachment);
|
|
978
|
+
this.cache.clear();
|
|
979
|
+
return result;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Creates an upload session for large file attachments (> 3MB).
|
|
983
|
+
*/
|
|
984
|
+
async createUploadSession(messageId, body) {
|
|
985
|
+
const client = await this.getClient();
|
|
986
|
+
return await client
|
|
987
|
+
.api(`/me/messages/${messageId}/attachments/createUploadSession`)
|
|
988
|
+
.post(body);
|
|
989
|
+
}
|
|
990
|
+
// ===========================================================================
|
|
991
|
+
// Tasks (Microsoft To Do) - continued
|
|
992
|
+
// ===========================================================================
|
|
993
|
+
/**
|
|
994
|
+
* Searches tasks by title.
|
|
995
|
+
*/
|
|
996
|
+
async searchTasks(query, limit = 50) {
|
|
997
|
+
const allTasks = await this.listAllTasks(1000, 0, true);
|
|
998
|
+
const queryLower = query.toLowerCase();
|
|
999
|
+
const matched = allTasks.filter((task) => task.title?.toLowerCase().includes(queryLower) ?? false);
|
|
1000
|
+
return matched.slice(0, limit);
|
|
1001
|
+
}
|
|
1002
|
+
// ===========================================================================
|
|
1003
|
+
// Task Write Operations
|
|
1004
|
+
// ===========================================================================
|
|
1005
|
+
/**
|
|
1006
|
+
* Creates a new task in a task list.
|
|
1007
|
+
*/
|
|
1008
|
+
async createTask(taskListId, task) {
|
|
1009
|
+
const client = await this.getClient();
|
|
1010
|
+
const result = await client
|
|
1011
|
+
.api(`/me/todo/lists/${taskListId}/tasks`)
|
|
1012
|
+
.post(task);
|
|
1013
|
+
this.cache.clear();
|
|
1014
|
+
return result;
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Updates an existing task.
|
|
1018
|
+
*/
|
|
1019
|
+
async updateTask(taskListId, taskId, updates) {
|
|
1020
|
+
const client = await this.getClient();
|
|
1021
|
+
const result = await client
|
|
1022
|
+
.api(`/me/todo/lists/${taskListId}/tasks/${taskId}`)
|
|
1023
|
+
.patch(updates);
|
|
1024
|
+
this.cache.clear();
|
|
1025
|
+
return result;
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Deletes a task.
|
|
1029
|
+
*/
|
|
1030
|
+
async deleteTask(taskListId, taskId) {
|
|
1031
|
+
const client = await this.getClient();
|
|
1032
|
+
await client
|
|
1033
|
+
.api(`/me/todo/lists/${taskListId}/tasks/${taskId}`)
|
|
1034
|
+
.delete();
|
|
1035
|
+
this.cache.clear();
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Creates a new task list.
|
|
1039
|
+
*/
|
|
1040
|
+
async createTaskList(displayName) {
|
|
1041
|
+
const client = await this.getClient();
|
|
1042
|
+
const result = await client
|
|
1043
|
+
.api('/me/todo/lists')
|
|
1044
|
+
.post({ displayName });
|
|
1045
|
+
this.cache.clear();
|
|
1046
|
+
return result;
|
|
1047
|
+
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Updates a task list (e.g. rename).
|
|
1050
|
+
*/
|
|
1051
|
+
async updateTaskList(listId, updates) {
|
|
1052
|
+
const client = await this.getClient();
|
|
1053
|
+
await client.api(`/me/todo/lists/${listId}`).patch(updates);
|
|
1054
|
+
this.cache.clear();
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Deletes a task list.
|
|
1058
|
+
*/
|
|
1059
|
+
async deleteTaskList(listId) {
|
|
1060
|
+
const client = await this.getClient();
|
|
1061
|
+
await client.api(`/me/todo/lists/${listId}`).delete();
|
|
1062
|
+
this.cache.clear();
|
|
1063
|
+
}
|
|
1064
|
+
// ===========================================================================
|
|
1065
|
+
// Master Categories
|
|
1066
|
+
// ===========================================================================
|
|
1067
|
+
/**
|
|
1068
|
+
* Lists all master categories.
|
|
1069
|
+
*/
|
|
1070
|
+
async listMasterCategories() {
|
|
1071
|
+
const client = await this.getClient();
|
|
1072
|
+
const response = await client.api('/me/outlook/masterCategories').get();
|
|
1073
|
+
return response.value;
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Creates a new master category.
|
|
1077
|
+
*/
|
|
1078
|
+
async createMasterCategory(displayName, color) {
|
|
1079
|
+
const client = await this.getClient();
|
|
1080
|
+
const result = await client.api('/me/outlook/masterCategories').post({ displayName, color });
|
|
1081
|
+
this.cache.clear();
|
|
1082
|
+
return result;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Deletes a master category.
|
|
1086
|
+
*/
|
|
1087
|
+
async deleteMasterCategory(categoryId) {
|
|
1088
|
+
const client = await this.getClient();
|
|
1089
|
+
await client.api(`/me/outlook/masterCategories/${categoryId}`).delete();
|
|
1090
|
+
this.cache.clear();
|
|
1091
|
+
}
|
|
1092
|
+
// ===========================================================================
|
|
1093
|
+
// Focused Inbox Overrides
|
|
1094
|
+
// ===========================================================================
|
|
1095
|
+
/**
|
|
1096
|
+
* Lists all focused inbox overrides.
|
|
1097
|
+
*/
|
|
1098
|
+
async listFocusedOverrides() {
|
|
1099
|
+
const client = await this.getClient();
|
|
1100
|
+
const response = await client.api('/me/inferenceClassification/overrides').get();
|
|
1101
|
+
return response.value;
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Creates a focused inbox override.
|
|
1105
|
+
*/
|
|
1106
|
+
async createFocusedOverride(senderAddress, classifyAs) {
|
|
1107
|
+
const client = await this.getClient();
|
|
1108
|
+
const result = await client.api('/me/inferenceClassification/overrides').post({
|
|
1109
|
+
classifyAs,
|
|
1110
|
+
senderEmailAddress: { address: senderAddress },
|
|
1111
|
+
});
|
|
1112
|
+
this.cache.clear();
|
|
1113
|
+
return result;
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Deletes a focused inbox override.
|
|
1117
|
+
*/
|
|
1118
|
+
async deleteFocusedOverride(overrideId) {
|
|
1119
|
+
const client = await this.getClient();
|
|
1120
|
+
await client.api(`/me/inferenceClassification/overrides/${overrideId}`).delete();
|
|
1121
|
+
this.cache.clear();
|
|
1122
|
+
}
|
|
1123
|
+
// ===========================================================================
|
|
1124
|
+
// Message Headers & MIME
|
|
1125
|
+
// ===========================================================================
|
|
1126
|
+
/**
|
|
1127
|
+
* Gets internet message headers for a message.
|
|
1128
|
+
*/
|
|
1129
|
+
async getMessageHeaders(messageId) {
|
|
1130
|
+
const client = await this.getClient();
|
|
1131
|
+
const message = await client
|
|
1132
|
+
.api(`/me/messages/${messageId}`)
|
|
1133
|
+
.select('internetMessageHeaders')
|
|
1134
|
+
.get();
|
|
1135
|
+
return (message.internetMessageHeaders ?? []);
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Gets the MIME content of a message.
|
|
1139
|
+
*/
|
|
1140
|
+
async getMessageMime(messageId) {
|
|
1141
|
+
const client = await this.getClient();
|
|
1142
|
+
return await client.api(`/me/messages/${messageId}/$value`).get();
|
|
1143
|
+
}
|
|
1144
|
+
// ===========================================================================
|
|
1145
|
+
// Calendar Groups
|
|
1146
|
+
// ===========================================================================
|
|
1147
|
+
/**
|
|
1148
|
+
* Lists all calendar groups.
|
|
1149
|
+
*/
|
|
1150
|
+
async listCalendarGroups() {
|
|
1151
|
+
const client = await this.getClient();
|
|
1152
|
+
const response = await client.api('/me/calendarGroups').get();
|
|
1153
|
+
return response.value;
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Creates a new calendar group.
|
|
1157
|
+
*/
|
|
1158
|
+
async createCalendarGroup(name) {
|
|
1159
|
+
const client = await this.getClient();
|
|
1160
|
+
const result = await client.api('/me/calendarGroups').post({ name });
|
|
1161
|
+
this.cache.clear();
|
|
1162
|
+
return result;
|
|
1163
|
+
}
|
|
1164
|
+
// ===========================================================================
|
|
1165
|
+
// Calendar Permissions
|
|
1166
|
+
// ===========================================================================
|
|
1167
|
+
/**
|
|
1168
|
+
* Lists all permissions for a calendar.
|
|
1169
|
+
*/
|
|
1170
|
+
async listCalendarPermissions(calendarId) {
|
|
1171
|
+
const client = await this.getClient();
|
|
1172
|
+
const response = await client.api(`/me/calendars/${calendarId}/calendarPermissions`).get();
|
|
1173
|
+
return response.value;
|
|
1174
|
+
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Creates a calendar permission (shares a calendar).
|
|
1177
|
+
*/
|
|
1178
|
+
async createCalendarPermission(calendarId, permission) {
|
|
1179
|
+
const client = await this.getClient();
|
|
1180
|
+
const result = await client.api(`/me/calendars/${calendarId}/calendarPermissions`).post(permission);
|
|
1181
|
+
this.cache.clear();
|
|
1182
|
+
return result;
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Deletes a calendar permission.
|
|
1186
|
+
*/
|
|
1187
|
+
async deleteCalendarPermission(calendarId, permissionId) {
|
|
1188
|
+
const client = await this.getClient();
|
|
1189
|
+
await client.api(`/me/calendars/${calendarId}/calendarPermissions/${permissionId}`).delete();
|
|
1190
|
+
this.cache.clear();
|
|
1191
|
+
}
|
|
1192
|
+
// ===========================================================================
|
|
1193
|
+
// Room Lists & Rooms
|
|
1194
|
+
// ===========================================================================
|
|
1195
|
+
/**
|
|
1196
|
+
* GET /me/findRoomLists
|
|
1197
|
+
*/
|
|
1198
|
+
async listRoomLists() {
|
|
1199
|
+
const client = await this.getClient();
|
|
1200
|
+
const response = await client.api('/me/findRoomLists').get();
|
|
1201
|
+
return response.value;
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* GET /me/findRooms or /me/findRooms(RoomList='...')
|
|
1205
|
+
*/
|
|
1206
|
+
async listRooms(roomListEmail) {
|
|
1207
|
+
const client = await this.getClient();
|
|
1208
|
+
const endpoint = roomListEmail != null
|
|
1209
|
+
? `/me/findRooms(RoomList='${roomListEmail}')`
|
|
1210
|
+
: '/me/findRooms';
|
|
1211
|
+
const response = await client.api(endpoint).get();
|
|
1212
|
+
return response.value;
|
|
1213
|
+
}
|
|
1214
|
+
// ===========================================================================
|
|
1215
|
+
// Mail Tips
|
|
1216
|
+
// ===========================================================================
|
|
1217
|
+
/**
|
|
1218
|
+
* Gets mail tips for the specified email addresses.
|
|
1219
|
+
*/
|
|
1220
|
+
async getMailTips(emailAddresses) {
|
|
1221
|
+
const client = await this.getClient();
|
|
1222
|
+
const response = await client.api('/me/getMailTips').post({
|
|
1223
|
+
emailAddresses,
|
|
1224
|
+
mailTipsOptions: 'automaticReplies,mailboxFullStatus,maxMessageSize,deliveryRestriction,externalMemberCount',
|
|
1225
|
+
});
|
|
1226
|
+
return response.value;
|
|
1227
|
+
}
|
|
1228
|
+
// ===========================================================================
|
|
1229
|
+
// Teams
|
|
1230
|
+
// ===========================================================================
|
|
1231
|
+
/**
|
|
1232
|
+
* Lists all teams the current user has joined.
|
|
1233
|
+
*/
|
|
1234
|
+
async listJoinedTeams() {
|
|
1235
|
+
const client = await this.getClient();
|
|
1236
|
+
const response = await client.api('/me/joinedTeams').get();
|
|
1237
|
+
return response.value;
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Lists all channels in a team.
|
|
1241
|
+
*/
|
|
1242
|
+
async listChannels(teamId) {
|
|
1243
|
+
const client = await this.getClient();
|
|
1244
|
+
const response = await client.api(`/teams/${teamId}/channels`).get();
|
|
1245
|
+
return response.value;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Gets a specific channel.
|
|
1249
|
+
*/
|
|
1250
|
+
async getChannel(teamId, channelId) {
|
|
1251
|
+
const client = await this.getClient();
|
|
1252
|
+
return await client.api(`/teams/${teamId}/channels/${channelId}`).get();
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Creates a new channel in a team.
|
|
1256
|
+
*/
|
|
1257
|
+
async createChannel(teamId, displayName, description) {
|
|
1258
|
+
const client = await this.getClient();
|
|
1259
|
+
const body = { displayName };
|
|
1260
|
+
if (description != null)
|
|
1261
|
+
body['description'] = description;
|
|
1262
|
+
return await client.api(`/teams/${teamId}/channels`).post(body);
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* Updates a channel's properties.
|
|
1266
|
+
*/
|
|
1267
|
+
async updateChannel(teamId, channelId, updates) {
|
|
1268
|
+
const client = await this.getClient();
|
|
1269
|
+
await client.api(`/teams/${teamId}/channels/${channelId}`).patch(updates);
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Deletes a channel.
|
|
1273
|
+
*/
|
|
1274
|
+
async deleteChannel(teamId, channelId) {
|
|
1275
|
+
const client = await this.getClient();
|
|
1276
|
+
await client.api(`/teams/${teamId}/channels/${channelId}`).delete();
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* Lists members of a team.
|
|
1280
|
+
*/
|
|
1281
|
+
async listTeamMembers(teamId) {
|
|
1282
|
+
const client = await this.getClient();
|
|
1283
|
+
const response = await client.api(`/teams/${teamId}/members`).get();
|
|
1284
|
+
return response.value;
|
|
1285
|
+
}
|
|
1286
|
+
// ===========================================================================
|
|
1287
|
+
// Channel Messages
|
|
1288
|
+
// ===========================================================================
|
|
1289
|
+
/**
|
|
1290
|
+
* Lists recent messages in a channel.
|
|
1291
|
+
*/
|
|
1292
|
+
async listChannelMessages(teamId, channelId, top = 25) {
|
|
1293
|
+
const client = await this.getClient();
|
|
1294
|
+
const response = await client.api(`/teams/${teamId}/channels/${channelId}/messages`).top(top).get();
|
|
1295
|
+
return response.value;
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Gets a specific channel message.
|
|
1299
|
+
*/
|
|
1300
|
+
async getChannelMessage(teamId, channelId, messageId) {
|
|
1301
|
+
const client = await this.getClient();
|
|
1302
|
+
return await client.api(`/teams/${teamId}/channels/${channelId}/messages/${messageId}`).get();
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Lists replies to a channel message.
|
|
1306
|
+
*/
|
|
1307
|
+
async listChannelMessageReplies(teamId, channelId, messageId) {
|
|
1308
|
+
const client = await this.getClient();
|
|
1309
|
+
const response = await client.api(`/teams/${teamId}/channels/${channelId}/messages/${messageId}/replies`).get();
|
|
1310
|
+
return response.value;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Sends a new message to a channel.
|
|
1314
|
+
*/
|
|
1315
|
+
async sendChannelMessage(teamId, channelId, body, contentType = 'html') {
|
|
1316
|
+
const client = await this.getClient();
|
|
1317
|
+
return await client.api(`/teams/${teamId}/channels/${channelId}/messages`).post({
|
|
1318
|
+
body: { contentType, content: body },
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Replies to a channel message.
|
|
1323
|
+
*/
|
|
1324
|
+
async replyToChannelMessage(teamId, channelId, messageId, body, contentType = 'html') {
|
|
1325
|
+
const client = await this.getClient();
|
|
1326
|
+
return await client.api(`/teams/${teamId}/channels/${channelId}/messages/${messageId}/replies`).post({
|
|
1327
|
+
body: { contentType, content: body },
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
// ===========================================================================
|
|
1331
|
+
// Chats
|
|
1332
|
+
// ===========================================================================
|
|
1333
|
+
async listChats(top = 25) {
|
|
1334
|
+
const client = await this.getClient();
|
|
1335
|
+
const response = await client.api('/me/chats')
|
|
1336
|
+
.top(top)
|
|
1337
|
+
.orderby('lastMessagePreview/createdDateTime desc')
|
|
1338
|
+
.expand('lastMessagePreview')
|
|
1339
|
+
.get();
|
|
1340
|
+
return response.value;
|
|
1341
|
+
}
|
|
1342
|
+
async getChat(chatId) {
|
|
1343
|
+
const client = await this.getClient();
|
|
1344
|
+
return await client.api(`/me/chats/${chatId}`).get();
|
|
1345
|
+
}
|
|
1346
|
+
async listChatMessages(chatId, top = 25) {
|
|
1347
|
+
const client = await this.getClient();
|
|
1348
|
+
const response = await client.api(`/me/chats/${chatId}/messages`).top(top).get();
|
|
1349
|
+
return response.value;
|
|
1350
|
+
}
|
|
1351
|
+
async sendChatMessage(chatId, body, contentType = 'html') {
|
|
1352
|
+
const client = await this.getClient();
|
|
1353
|
+
return await client.api(`/me/chats/${chatId}/messages`).post({
|
|
1354
|
+
body: { contentType, content: body },
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
async getChatMessage(chatId, messageId) {
|
|
1358
|
+
const client = await this.getClient();
|
|
1359
|
+
return await client.api(`/me/chats/${chatId}/messages/${messageId}`).get();
|
|
1360
|
+
}
|
|
1361
|
+
// Channel message reactions
|
|
1362
|
+
async setChannelMessageReaction(teamId, channelId, messageId, reactionType) {
|
|
1363
|
+
const client = await this.getClient();
|
|
1364
|
+
await client.api(`/teams/${teamId}/channels/${channelId}/messages/${messageId}/setReaction`)
|
|
1365
|
+
.post({ reactionType });
|
|
1366
|
+
}
|
|
1367
|
+
async unsetChannelMessageReaction(teamId, channelId, messageId, reactionType) {
|
|
1368
|
+
const client = await this.getClient();
|
|
1369
|
+
await client.api(`/teams/${teamId}/channels/${channelId}/messages/${messageId}/unsetReaction`)
|
|
1370
|
+
.post({ reactionType });
|
|
1371
|
+
}
|
|
1372
|
+
// Chat message reactions
|
|
1373
|
+
async setChatMessageReaction(chatId, messageId, reactionType) {
|
|
1374
|
+
const client = await this.getClient();
|
|
1375
|
+
await client.api(`/chats/${chatId}/messages/${messageId}/setReaction`)
|
|
1376
|
+
.post({ reactionType });
|
|
1377
|
+
}
|
|
1378
|
+
async unsetChatMessageReaction(chatId, messageId, reactionType) {
|
|
1379
|
+
const client = await this.getClient();
|
|
1380
|
+
await client.api(`/chats/${chatId}/messages/${messageId}/unsetReaction`)
|
|
1381
|
+
.post({ reactionType });
|
|
1382
|
+
}
|
|
1383
|
+
async listChatMembers(chatId) {
|
|
1384
|
+
const client = await this.getClient();
|
|
1385
|
+
const response = await client.api(`/me/chats/${chatId}/members`).get();
|
|
1386
|
+
return response.value;
|
|
1387
|
+
}
|
|
1388
|
+
// ===========================================================================
|
|
1389
|
+
// Checklist Items
|
|
1390
|
+
// ===========================================================================
|
|
1391
|
+
/**
|
|
1392
|
+
* Lists checklist items on a task.
|
|
1393
|
+
*/
|
|
1394
|
+
async listChecklistItems(taskListId, taskId) {
|
|
1395
|
+
const client = await this.getClient();
|
|
1396
|
+
const response = await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/checklistItems`).get();
|
|
1397
|
+
return response.value;
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* Creates a checklist item on a task.
|
|
1401
|
+
*/
|
|
1402
|
+
async createChecklistItem(taskListId, taskId, displayName, isChecked = false) {
|
|
1403
|
+
const client = await this.getClient();
|
|
1404
|
+
return await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/checklistItems`).post({
|
|
1405
|
+
displayName,
|
|
1406
|
+
isChecked,
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Updates a checklist item.
|
|
1411
|
+
*/
|
|
1412
|
+
async updateChecklistItem(taskListId, taskId, checklistItemId, updates) {
|
|
1413
|
+
const client = await this.getClient();
|
|
1414
|
+
await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/checklistItems/${checklistItemId}`).patch(updates);
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* Deletes a checklist item.
|
|
1418
|
+
*/
|
|
1419
|
+
async deleteChecklistItem(taskListId, taskId, checklistItemId) {
|
|
1420
|
+
const client = await this.getClient();
|
|
1421
|
+
await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/checklistItems/${checklistItemId}`).delete();
|
|
1422
|
+
}
|
|
1423
|
+
// ===========================================================================
|
|
1424
|
+
// Linked Resources
|
|
1425
|
+
// ===========================================================================
|
|
1426
|
+
async listLinkedResources(taskListId, taskId) {
|
|
1427
|
+
const client = await this.getClient();
|
|
1428
|
+
const response = await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/linkedResources`).get();
|
|
1429
|
+
return response.value;
|
|
1430
|
+
}
|
|
1431
|
+
async createLinkedResource(taskListId, taskId, webUrl, applicationName, displayName) {
|
|
1432
|
+
const client = await this.getClient();
|
|
1433
|
+
const body = { webUrl, applicationName };
|
|
1434
|
+
if (displayName != null)
|
|
1435
|
+
body['displayName'] = displayName;
|
|
1436
|
+
return await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/linkedResources`).post(body);
|
|
1437
|
+
}
|
|
1438
|
+
async deleteLinkedResource(taskListId, taskId, linkedResourceId) {
|
|
1439
|
+
const client = await this.getClient();
|
|
1440
|
+
await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/linkedResources/${linkedResourceId}`).delete();
|
|
1441
|
+
}
|
|
1442
|
+
// ===========================================================================
|
|
1443
|
+
// Task Attachments
|
|
1444
|
+
// ===========================================================================
|
|
1445
|
+
async listTaskAttachments(taskListId, taskId) {
|
|
1446
|
+
const client = await this.getClient();
|
|
1447
|
+
const response = await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/attachments`).get();
|
|
1448
|
+
return response.value;
|
|
1449
|
+
}
|
|
1450
|
+
async createTaskAttachment(taskListId, taskId, name, contentBytes, contentType = 'application/octet-stream') {
|
|
1451
|
+
const client = await this.getClient();
|
|
1452
|
+
return await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/attachments`).post({
|
|
1453
|
+
'@odata.type': '#microsoft.graph.taskFileAttachment',
|
|
1454
|
+
name,
|
|
1455
|
+
contentBytes,
|
|
1456
|
+
contentType,
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
async deleteTaskAttachment(taskListId, taskId, attachmentId) {
|
|
1460
|
+
const client = await this.getClient();
|
|
1461
|
+
await client.api(`/me/todo/lists/${taskListId}/tasks/${taskId}/attachments/${attachmentId}`).delete();
|
|
1462
|
+
}
|
|
1463
|
+
// ===========================================================================
|
|
1464
|
+
// Planner
|
|
1465
|
+
// ===========================================================================
|
|
1466
|
+
async listPlans() {
|
|
1467
|
+
const client = await this.getClient();
|
|
1468
|
+
const response = await client.api('/me/planner/plans').get();
|
|
1469
|
+
return response.value;
|
|
1470
|
+
}
|
|
1471
|
+
async getPlan(planId) {
|
|
1472
|
+
const client = await this.getClient();
|
|
1473
|
+
return await client.api(`/planner/plans/${planId}`).get();
|
|
1474
|
+
}
|
|
1475
|
+
async createPlan(title, groupId) {
|
|
1476
|
+
const client = await this.getClient();
|
|
1477
|
+
return await client.api('/planner/plans').post({
|
|
1478
|
+
title,
|
|
1479
|
+
owner: groupId,
|
|
1480
|
+
container: { url: `https://graph.microsoft.com/v1.0/groups/${groupId}`, type: 'group' },
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
async updatePlan(planId, updates, etag) {
|
|
1484
|
+
const client = await this.getClient();
|
|
1485
|
+
return await client.api(`/planner/plans/${planId}`).header('If-Match', etag).patch(updates);
|
|
1486
|
+
}
|
|
1487
|
+
async listBuckets(planId) {
|
|
1488
|
+
const client = await this.getClient();
|
|
1489
|
+
const response = await client.api(`/planner/plans/${planId}/buckets`).get();
|
|
1490
|
+
return response.value;
|
|
1491
|
+
}
|
|
1492
|
+
async createBucket(planId, name) {
|
|
1493
|
+
const client = await this.getClient();
|
|
1494
|
+
return await client.api('/planner/buckets').post({ planId, name });
|
|
1495
|
+
}
|
|
1496
|
+
async updateBucket(bucketId, updates, etag) {
|
|
1497
|
+
const client = await this.getClient();
|
|
1498
|
+
return await client.api(`/planner/buckets/${bucketId}`).header('If-Match', etag).patch(updates);
|
|
1499
|
+
}
|
|
1500
|
+
async deleteBucket(bucketId, etag) {
|
|
1501
|
+
const client = await this.getClient();
|
|
1502
|
+
await client.api(`/planner/buckets/${bucketId}`).header('If-Match', etag).delete();
|
|
1503
|
+
}
|
|
1504
|
+
// ===========================================================================
|
|
1505
|
+
// Planner Tasks
|
|
1506
|
+
// ===========================================================================
|
|
1507
|
+
async listPlannerTasks(planId) {
|
|
1508
|
+
const client = await this.getClient();
|
|
1509
|
+
const response = await client.api(`/planner/plans/${planId}/tasks`).get();
|
|
1510
|
+
return response.value;
|
|
1511
|
+
}
|
|
1512
|
+
async getPlannerTask(taskId) {
|
|
1513
|
+
const client = await this.getClient();
|
|
1514
|
+
return await client.api(`/planner/tasks/${taskId}`).get();
|
|
1515
|
+
}
|
|
1516
|
+
async createPlannerTask(task) {
|
|
1517
|
+
const client = await this.getClient();
|
|
1518
|
+
return await client.api('/planner/tasks').post(task);
|
|
1519
|
+
}
|
|
1520
|
+
async updatePlannerTask(taskId, updates, etag) {
|
|
1521
|
+
const client = await this.getClient();
|
|
1522
|
+
return await client.api(`/planner/tasks/${taskId}`).header('If-Match', etag).patch(updates);
|
|
1523
|
+
}
|
|
1524
|
+
async deletePlannerTask(taskId, etag) {
|
|
1525
|
+
const client = await this.getClient();
|
|
1526
|
+
await client.api(`/planner/tasks/${taskId}`).header('If-Match', etag).delete();
|
|
1527
|
+
}
|
|
1528
|
+
async getPlannerTaskDetails(taskId) {
|
|
1529
|
+
const client = await this.getClient();
|
|
1530
|
+
return await client.api(`/planner/tasks/${taskId}/details`).get();
|
|
1531
|
+
}
|
|
1532
|
+
async updatePlannerTaskDetails(taskId, updates, etag) {
|
|
1533
|
+
const client = await this.getClient();
|
|
1534
|
+
return await client.api(`/planner/tasks/${taskId}/details`).header('If-Match', etag).patch(updates);
|
|
1535
|
+
}
|
|
1536
|
+
// ===========================================================================
|
|
1537
|
+
// People & Presence
|
|
1538
|
+
// ===========================================================================
|
|
1539
|
+
async listRelevantPeople(top = 25) {
|
|
1540
|
+
const client = await this.getClient();
|
|
1541
|
+
const response = await client.api('/me/people').top(top).get();
|
|
1542
|
+
return response.value;
|
|
1543
|
+
}
|
|
1544
|
+
async searchPeople(query, top = 25) {
|
|
1545
|
+
const client = await this.getClient();
|
|
1546
|
+
const response = await client.api('/me/people').search('"' + query + '"').top(top).get();
|
|
1547
|
+
return response.value;
|
|
1548
|
+
}
|
|
1549
|
+
async getManager() {
|
|
1550
|
+
const client = await this.getClient();
|
|
1551
|
+
return await client.api('/me/manager').get();
|
|
1552
|
+
}
|
|
1553
|
+
async getDirectReports() {
|
|
1554
|
+
const client = await this.getClient();
|
|
1555
|
+
const response = await client.api('/me/directReports').get();
|
|
1556
|
+
return response.value;
|
|
1557
|
+
}
|
|
1558
|
+
async getUserProfile(identifier) {
|
|
1559
|
+
const client = await this.getClient();
|
|
1560
|
+
return await client.api(`/users/${identifier}`).get();
|
|
1561
|
+
}
|
|
1562
|
+
async getUserPhoto(identifier) {
|
|
1563
|
+
const client = await this.getClient();
|
|
1564
|
+
return await client.api(`/users/${identifier}/photo/$value`).get();
|
|
1565
|
+
}
|
|
1566
|
+
async getUserPresence(identifier) {
|
|
1567
|
+
const client = await this.getClient();
|
|
1568
|
+
return await client.api(`/users/${identifier}/presence`).get();
|
|
1569
|
+
}
|
|
1570
|
+
async getUsersPresence(userIds) {
|
|
1571
|
+
const client = await this.getClient();
|
|
1572
|
+
const response = await client.api('/communications/getPresencesByUserId').post({ ids: userIds });
|
|
1573
|
+
return response.value;
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Sends multiple requests in a single $batch call to the Graph API.
|
|
1577
|
+
* Automatically splits into multiple batches if there are more than 20 requests.
|
|
1578
|
+
*/
|
|
1579
|
+
async batchRequests(requests) {
|
|
1580
|
+
const client = await this.getClient();
|
|
1581
|
+
const batches = splitIntoBatches(requests);
|
|
1582
|
+
const allResults = new Map();
|
|
1583
|
+
for (const batch of batches) {
|
|
1584
|
+
const payload = buildBatchPayload(batch);
|
|
1585
|
+
const response = await client.api('/$batch').post(payload);
|
|
1586
|
+
const results = parseBatchResponse(response);
|
|
1587
|
+
for (const [id, result] of results) {
|
|
1588
|
+
allResults.set(id, result);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
return allResults;
|
|
1592
|
+
}
|
|
1593
|
+
// ===========================================================================
|
|
1594
|
+
// Online Meetings
|
|
1595
|
+
// ===========================================================================
|
|
1596
|
+
async listOnlineMeetings(limit = 20) {
|
|
1597
|
+
const client = await this.getClient();
|
|
1598
|
+
const response = await client.api('/me/onlineMeetings')
|
|
1599
|
+
.top(limit)
|
|
1600
|
+
.orderby('startDateTime desc')
|
|
1601
|
+
.get();
|
|
1602
|
+
return response.value;
|
|
1603
|
+
}
|
|
1604
|
+
async getOnlineMeeting(meetingId) {
|
|
1605
|
+
const client = await this.getClient();
|
|
1606
|
+
return await client.api(`/me/onlineMeetings/${meetingId}`).get();
|
|
1607
|
+
}
|
|
1608
|
+
async listMeetingRecordings(meetingId) {
|
|
1609
|
+
const client = await this.getClient();
|
|
1610
|
+
const response = await client.api(`/me/onlineMeetings/${meetingId}/recordings`).get();
|
|
1611
|
+
return response.value;
|
|
1612
|
+
}
|
|
1613
|
+
async getMeetingRecordingContent(meetingId, recordingId) {
|
|
1614
|
+
const client = await this.getClient();
|
|
1615
|
+
return await client.api(`/me/onlineMeetings/${meetingId}/recordings/${recordingId}/content`).get();
|
|
1616
|
+
}
|
|
1617
|
+
async listMeetingTranscripts(meetingId) {
|
|
1618
|
+
const client = await this.getClient();
|
|
1619
|
+
const response = await client.api(`/me/onlineMeetings/${meetingId}/transcripts`).get();
|
|
1620
|
+
return response.value;
|
|
1621
|
+
}
|
|
1622
|
+
async getMeetingTranscriptContent(meetingId, transcriptId, format = 'text/vtt') {
|
|
1623
|
+
const client = await this.getClient();
|
|
1624
|
+
return await client.api(`/me/onlineMeetings/${meetingId}/transcripts/${transcriptId}/content`)
|
|
1625
|
+
.header('Accept', format)
|
|
1626
|
+
.get();
|
|
1627
|
+
}
|
|
1628
|
+
// ===========================================================================
|
|
1629
|
+
// Excel Online (Workbook)
|
|
1630
|
+
// ===========================================================================
|
|
1631
|
+
/**
|
|
1632
|
+
* Lists worksheets in an Excel workbook.
|
|
1633
|
+
*/
|
|
1634
|
+
async listWorksheets(driveItemId) {
|
|
1635
|
+
const client = await this.getClient();
|
|
1636
|
+
const response = await client.api(`/me/drive/items/${driveItemId}/workbook/worksheets`).get();
|
|
1637
|
+
return response.value;
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Gets cell values for a specific range in a worksheet.
|
|
1641
|
+
*/
|
|
1642
|
+
async getWorksheetRange(driveItemId, worksheetName, range) {
|
|
1643
|
+
const client = await this.getClient();
|
|
1644
|
+
return await client.api(`/me/drive/items/${driveItemId}/workbook/worksheets/${encodeURIComponent(worksheetName)}/range(address='${encodeURIComponent(range)}')`).get();
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* Gets the used range (all data) for a worksheet.
|
|
1648
|
+
*/
|
|
1649
|
+
async getUsedRange(driveItemId, worksheetName) {
|
|
1650
|
+
const client = await this.getClient();
|
|
1651
|
+
return await client.api(`/me/drive/items/${driveItemId}/workbook/worksheets/${encodeURIComponent(worksheetName)}/usedRange`).get();
|
|
1652
|
+
}
|
|
1653
|
+
/**
|
|
1654
|
+
* Updates cell values for a specific range in a worksheet.
|
|
1655
|
+
*/
|
|
1656
|
+
async updateWorksheetRange(driveItemId, worksheetName, range, values) {
|
|
1657
|
+
const client = await this.getClient();
|
|
1658
|
+
return await client.api(`/me/drive/items/${driveItemId}/workbook/worksheets/${encodeURIComponent(worksheetName)}/range(address='${encodeURIComponent(range)}')`).patch({ values });
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Gets rows from a named table in an Excel workbook.
|
|
1662
|
+
*/
|
|
1663
|
+
async getTableData(driveItemId, tableName) {
|
|
1664
|
+
const client = await this.getClient();
|
|
1665
|
+
const response = await client.api(`/me/drive/items/${driveItemId}/workbook/tables/${encodeURIComponent(tableName)}/rows`).get();
|
|
1666
|
+
return response.value;
|
|
1667
|
+
}
|
|
1668
|
+
// ===========================================================================
|
|
1669
|
+
// OneDrive
|
|
1670
|
+
// ===========================================================================
|
|
1671
|
+
async listDriveItems(itemId) {
|
|
1672
|
+
const client = await this.getClient();
|
|
1673
|
+
const apiPath = itemId != null ? `/me/drive/items/${itemId}/children` : '/me/drive/root/children';
|
|
1674
|
+
const response = await client.api(apiPath).get();
|
|
1675
|
+
return response.value;
|
|
1676
|
+
}
|
|
1677
|
+
async searchDriveItems(query, limit = 25) {
|
|
1678
|
+
const client = await this.getClient();
|
|
1679
|
+
const response = await client.api(`/me/drive/root/search(q='${encodeURIComponent(query)}')`).top(limit).get();
|
|
1680
|
+
return response.value;
|
|
1681
|
+
}
|
|
1682
|
+
async getDriveItem(itemId) {
|
|
1683
|
+
const client = await this.getClient();
|
|
1684
|
+
return await client.api(`/me/drive/items/${itemId}`).get();
|
|
1685
|
+
}
|
|
1686
|
+
async downloadDriveItem(itemId) {
|
|
1687
|
+
const client = await this.getClient();
|
|
1688
|
+
return await client.api(`/me/drive/items/${itemId}/content`).get();
|
|
1689
|
+
}
|
|
1690
|
+
async uploadDriveItem(parentPath, fileName, content) {
|
|
1691
|
+
const client = await this.getClient();
|
|
1692
|
+
return await client.api(`/me/drive/root:/${parentPath}/${fileName}:/content`)
|
|
1693
|
+
.header('Content-Type', 'application/octet-stream')
|
|
1694
|
+
.put(content);
|
|
1695
|
+
}
|
|
1696
|
+
async listRecentDriveItems() {
|
|
1697
|
+
const client = await this.getClient();
|
|
1698
|
+
const response = await client.api('/me/drive/recent').get();
|
|
1699
|
+
return response.value;
|
|
1700
|
+
}
|
|
1701
|
+
async listSharedWithMe() {
|
|
1702
|
+
const client = await this.getClient();
|
|
1703
|
+
const response = await client.api('/me/drive/sharedWithMe').get();
|
|
1704
|
+
return response.value;
|
|
1705
|
+
}
|
|
1706
|
+
async createSharingLink(itemId, type, scope) {
|
|
1707
|
+
const client = await this.getClient();
|
|
1708
|
+
return await client.api(`/me/drive/items/${itemId}/createLink`).post({ type, scope });
|
|
1709
|
+
}
|
|
1710
|
+
async deleteDriveItem(itemId) {
|
|
1711
|
+
const client = await this.getClient();
|
|
1712
|
+
await client.api(`/me/drive/items/${itemId}`).delete();
|
|
1713
|
+
}
|
|
1714
|
+
// ===========================================================================
|
|
1715
|
+
// SharePoint Sites & Document Libraries
|
|
1716
|
+
// ===========================================================================
|
|
1717
|
+
/**
|
|
1718
|
+
* Lists sites the current user follows.
|
|
1719
|
+
*/
|
|
1720
|
+
async listFollowedSites() {
|
|
1721
|
+
const client = await this.getClient();
|
|
1722
|
+
const response = await client.api('/me/followedSites').get();
|
|
1723
|
+
return response.value;
|
|
1724
|
+
}
|
|
1725
|
+
/**
|
|
1726
|
+
* Searches for SharePoint sites by keyword.
|
|
1727
|
+
*/
|
|
1728
|
+
async searchSites(query) {
|
|
1729
|
+
const client = await this.getClient();
|
|
1730
|
+
const response = await client.api(`/sites?search=${encodeURIComponent(query)}`).get();
|
|
1731
|
+
return response.value;
|
|
1732
|
+
}
|
|
1733
|
+
/**
|
|
1734
|
+
* Gets a specific SharePoint site by ID.
|
|
1735
|
+
*/
|
|
1736
|
+
async getSite(siteId) {
|
|
1737
|
+
const client = await this.getClient();
|
|
1738
|
+
return await client.api(`/sites/${siteId}`).get();
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Lists document libraries (drives) for a SharePoint site.
|
|
1742
|
+
*/
|
|
1743
|
+
async listDocumentLibraries(siteId) {
|
|
1744
|
+
const client = await this.getClient();
|
|
1745
|
+
const response = await client.api(`/sites/${siteId}/drives`).get();
|
|
1746
|
+
return response.value;
|
|
1747
|
+
}
|
|
1748
|
+
/**
|
|
1749
|
+
* Lists items in a document library or folder.
|
|
1750
|
+
*/
|
|
1751
|
+
async listLibraryItems(driveId, itemId) {
|
|
1752
|
+
const client = await this.getClient();
|
|
1753
|
+
const apiPath = itemId != null ? `/drives/${driveId}/items/${itemId}/children` : `/drives/${driveId}/root/children`;
|
|
1754
|
+
const response = await client.api(apiPath).get();
|
|
1755
|
+
return response.value;
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Downloads a file from a document library.
|
|
1759
|
+
*/
|
|
1760
|
+
async downloadLibraryFile(driveId, itemId) {
|
|
1761
|
+
const client = await this.getClient();
|
|
1762
|
+
return await client.api(`/drives/${driveId}/items/${itemId}/content`).get();
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
/**
|
|
1766
|
+
* Creates a new Graph client instance.
|
|
1767
|
+
*/
|
|
1768
|
+
export function createGraphClient(deviceCodeCallback) {
|
|
1769
|
+
return new GraphClient(deviceCodeCallback);
|
|
1770
|
+
}
|
|
1771
|
+
//# sourceMappingURL=graph-client.js.map
|