From 642743c0bb9305134b6923ba335b905e0d444d10 Mon Sep 17 00:00:00 2001 From: Julie Turner Date: Thu, 21 Dec 2023 14:35:36 +0000 Subject: [PATCH 1/3] Graph Mail endpoints and related --- .vscode/settings.json | 4 + CHANGELOG.md | 1 + docs/graph/attachments.md | 38 ++ docs/graph/calendars.md | 4 + docs/graph/conversations.md | 294 ++++++++++ docs/graph/groups.md | 12 +- docs/graph/{outlook.md => mail-categories.md} | 4 +- docs/graph/mail-folders.md | 166 ++++++ docs/graph/mail-mailbox.md | 103 ++++ docs/graph/mail-messages.md | 208 +++++++ docs/graph/mail-rules.md | 103 ++++ docs/graph/messages.md | 20 - mkdocs.yml | 9 +- package-lock.json | 542 +++++++++--------- packages/graph/attachments/event.ts | 14 + packages/graph/attachments/index.ts | 2 + packages/graph/attachments/message.ts | 14 + packages/graph/attachments/types.ts | 10 +- packages/graph/behaviors/paged.ts | 10 +- packages/graph/graphqueryable.ts | 2 +- .../{outlook/types.ts => mail/categories.ts} | 26 +- packages/graph/mail/folders.ts | 108 ++++ packages/graph/mail/funcs.ts | 30 +- packages/graph/mail/groups.ts | 0 packages/graph/mail/index.ts | 39 +- packages/graph/mail/mailbox.ts | 104 ++++ packages/graph/mail/messages.ts | 178 ++++++ packages/graph/mail/types.ts | 0 packages/graph/mail/users.ts | 64 ++- packages/graph/messages/index.ts | 14 - packages/graph/messages/types.ts | 46 -- packages/graph/messages/users.ts | 27 - packages/graph/outlook/index.ts | 11 - packages/graph/outlook/users.ts | 14 - packages/graph/presets/all.ts | 4 +- test/graph/analytics.ts | 12 +- test/graph/appCatalogs.ts | 2 +- test/graph/attachments.ts | 78 +++ test/graph/group-conversations.ts | 126 ++++ test/graph/{outlook.ts => mail-categories.ts} | 14 +- test/graph/mail-folders.ts | 194 +++++++ test/graph/mail-mailbox.ts | 157 +++++ test/graph/mail-messages.ts | 232 ++++++++ test/graph/mail-rules.ts | 112 ++++ 44 files changed, 2671 insertions(+), 481 deletions(-) create mode 100644 docs/graph/attachments.md create mode 100644 docs/graph/conversations.md rename docs/graph/{outlook.md => mail-categories.md} (94%) create mode 100644 docs/graph/mail-folders.md create mode 100644 docs/graph/mail-mailbox.md create mode 100644 docs/graph/mail-messages.md create mode 100644 docs/graph/mail-rules.md delete mode 100644 docs/graph/messages.md create mode 100644 packages/graph/attachments/event.ts create mode 100644 packages/graph/attachments/message.ts rename packages/graph/{outlook/types.ts => mail/categories.ts} (68%) create mode 100644 packages/graph/mail/folders.ts delete mode 100644 packages/graph/mail/groups.ts create mode 100644 packages/graph/mail/mailbox.ts create mode 100644 packages/graph/mail/messages.ts delete mode 100644 packages/graph/mail/types.ts delete mode 100644 packages/graph/messages/index.ts delete mode 100644 packages/graph/messages/types.ts delete mode 100644 packages/graph/messages/users.ts delete mode 100644 packages/graph/outlook/index.ts delete mode 100644 packages/graph/outlook/users.ts create mode 100644 test/graph/attachments.ts create mode 100644 test/graph/group-conversations.ts rename test/graph/{outlook.ts => mail-categories.ts} (89%) create mode 100644 test/graph/mail-folders.ts create mode 100644 test/graph/mail-mailbox.ts create mode 100644 test/graph/mail-messages.ts create mode 100644 test/graph/mail-rules.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 629e5f75c..761d8a23e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,10 @@ "typescript.tsdk": "./node_modules/typescript/lib", "editor.tabSize": 4, "cSpell.words": [ + "deleteable", + "graphfi", + "graphqueryable", + "Invokable", "queryables" ], } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c1ced204..559f2627b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - All GraphQueryable*, _GraphQueryable*, and IGraphQueryable* have been renamed to remove "Queryable" (ex: GraphQueryableCollection is now GraphCollection) - @pnp/graph/onedrive renamed to @pnp/graph/files - ISites.getByUrl is now async + - mailCategory.add() returns Microsoft Graph types OutlookCategory vs object with data property. - sp - _Items and IItems now supports async iterator pattern diff --git a/docs/graph/attachments.md b/docs/graph/attachments.md new file mode 100644 index 000000000..d89fcfde0 --- /dev/null +++ b/docs/graph/attachments.md @@ -0,0 +1,38 @@ +# Graph Attachments + +More information can be found in the official Graph documentation: + +- [Attachments Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/attachment?view=graph-rest-1.0) + +Attachments work with [Calendar Events](./calendars.md), [Mail Message](./mail-messages.md), and [Conversation Thread Posts](./conversations.md). The samples below are generic on purpose. + +## IAttachment, IAttachments + +[![Invokable Banner](https://img.shields.io/badge/Invokable-informational.svg)](../concepts/invokable.md) [![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + +## Get Attachments + +```TypeScript +import { graphfi } from "@pnp/graph"; +// Imports required for the object you're obtaining attachments for. +import "@pnp/graph/attachments"; + +const graph = graphfi(...); + +const event_message_post = graph.xxx; +const a = await event_message_post.attachments(); +``` + +## Get Attachment By Id + +```TypeScript +import { graphfi } from "@pnp/graph"; +// Imports required for the object you're obtaining attachments for. +import "@pnp/graph/attachments"; + +const graph = graphfi(...); + +const event_message_post = graph.xxx; +const attachmentId = ""; +const a = await event_message_post.attachments.getById(attachmentId)(); +``` diff --git a/docs/graph/calendars.md b/docs/graph/calendars.md index b25ce0dbc..e773daa67 100644 --- a/docs/graph/calendars.md +++ b/docs/graph/calendars.md @@ -268,3 +268,7 @@ const instances2 = await event.instances("2020-01-01", "2020-03-01").select("sub // you can specify times along with the dates const instance3 = await event.instances("2020-01-01T19:00:00-08:00", "2020-03-01T19:00:00-08:00")(); ``` + +## Event Attachments + +See [Attachments](./attachments.md) \ No newline at end of file diff --git a/docs/graph/conversations.md b/docs/graph/conversations.md new file mode 100644 index 000000000..80c5c9787 --- /dev/null +++ b/docs/graph/conversations.md @@ -0,0 +1,294 @@ +# Graph Conversations + +More information can be found in the official Graph documentation: + +- [Conversation Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/conversation?view=graph-rest-1.0) +- [Conversation Thread Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/conversationthread?view=graph-rest-1.0) +- [Post Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/post?view=graph-rest-1.0) + +## IConversation, IConversations, IPost, IPostForwardInfo, IPosts, ISenders, IThread, IThreads + +[![Invokable Banner](https://img.shields.io/badge/Invokable-informational.svg)](../concepts/invokable.md) [![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + +## Get Group Accepted/Rejected Senders + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const accepted = await graph.groups.getById(groupId).acceptedSenders(); +const rejected = await graph.groups.getById(groupId).rejectedSenders(); +``` + +## Add Group Accepted/Rejected Senders + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const sender = "https://graph.microsoft.com/v1.0/users/user@contoso.com"; +await graph.groups.getById(groupId).acceptedSenders.add(sender); +await graph.groups.getById(groupId).rejectedSenders.add(sender); +``` + +## Delete Group Accepted/Rejected Senders + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const sender = "https://graph.microsoft.com/v1.0/users/user@contoso.com"; +await graph.groups.getById(groupId).acceptedSenders.remove(sender); +await graph.groups.getById(groupId).rejectedSenders.remove(sender); +``` + +## Get Group Conversations + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const c = await graph.groups.getById(groupId).conversations(); +``` + +## Get Group Conversation by Id + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const conversationId = ""; +const c = await graph.groups.getById(groupId).conversations.getById(conversationId)(); +``` + +## Add/Update/Delete a Group Conversation + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; +import { Conversation } from "@microsoft/microsoft-graph-types"; + +const graph = graphfi(...); + +const conversation: Conversation = { + topic: "My New Conversation", + ... +}; + +const c = await graph.groups.getById(groupId).conversations.add(conversation); + +const conversationId = ""; +const update = await graph.groups.getById(groupId).conversations.getById(conversationId) + .update({topic: "My Conversation"}); +await graph.groups.getById(groupId).conversations.getById(conversationId).delete(); +``` + +## Get Group Conversation Threads + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; +import { Conversation } from "@microsoft/microsoft-graph-types"; + +const graph = graphfi(...); + +const groupId = ""; +const conversationId = ""; +const t = await graph.groups.getById(groupId).conversations.getById(conversationId).threads(); +``` + +## Get Group Conversation Thread by Id + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const conversationId = ""; +const threadId = ""; +const c = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId)(); +``` + +## Create/Update/Delete a Group Conversation Thread + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; +import { ConversationThread } from "@microsoft/microsoft-graph-types"; + +const graph = graphfi(...); + +const conversationThread: ConversationThread = { + topic: "My New Conversation", + ... +}; + +const conversationId = ""; +const t = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.add(conversationThread); + +const threadId = ""; +const update = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId) + .update({topic: "My Conversation"}); +await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).delete(); +``` + +## Reply to a Group Conversation Thread + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; +import { Post } from "@microsoft/microsoft-graph-types"; + +const graph = graphfi(...); + +const post: Post = { + body: { content: "This is a post" }, + from: { + emailAddress: { + address: "", + name: "", + }, + }, +}; + +const conversationId = ""; +const threadId = ""; +const reply = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).reply(post); +``` + +## Get Group Conversation Thread Posts + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const groupId = ""; +const conversationId = ""; +const threadId = ""; +const p = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).posts(); +``` + +## Get Group Conversation Thread Post by Id + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const conversationId = ""; +const threadId = ""; +const postId = ""; +const p = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).posts.getById(postId)(); +``` + +## Create/Update/Delete a Group Conversation Thread Post + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; +import { Post } from "@microsoft/microsoft-graph-types"; + +const graph = graphfi(...); + +const post: Post = { + body: { content: "This is a post" }, + from: { + emailAddress: { + address: "", + name: "", + }, + }, +}; + +const conversationId = ""; +const threadId = ""; +const p = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).posts.add(post); + +const postId = ""; +const update = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).posts.getById(postId) + .update({body: {content: "New Post Content"}}); +await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).posts.getById(postId).delete(); +``` + +## Reply to a Group Conversation Thread Post + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; +import { Post } from "@microsoft/microsoft-graph-types"; + +const graph = graphfi(...); + +const post: Post = { + body: { content: "This is a post" }, + from: { + emailAddress: { + address: "", + name: "", + }, + }, +}; + +const conversationId = ""; +const threadId = ""; +const reply = await graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).posts.getById(postId).reply(post); +``` + +## Forward a Group Conversation Thread Post + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/conversations"; +import { IPostForwardInfo } from "@pnp/graph/conversations"; + +const graph = graphfi(...); + +const postForwardInfo: IPostForwardInfo = { + toRecipients: [ + { + emailAddress: { + address: "", + name: "", + }, + }, + ], +}; + +const conversationId = ""; +const threadId = ""; +const post = graph.groups.getById(groupId).conversations.getById(conversationId).threads.getById(threadId).posts.getById(postId); +await post.forward(postForwardInfo); +``` + +## Group Conversation Thread Post Attachments + +See [Attachments](./attachments.md) diff --git a/docs/graph/groups.md b/docs/graph/groups.md index fd55aa7f6..9451bfd35 100644 --- a/docs/graph/groups.md +++ b/docs/graph/groups.md @@ -132,10 +132,6 @@ const endDate = new Date("2020-03-01"); const events = graph.groups.getById("7d2b9355-0891-47d3-84c8-bf2cd9c62177").getCalendarView(startDate, endDate); ``` -## Group Photo Operations - -See [Photos](./photos.md) - ## Group Membership Get the members and/or owners of a group. @@ -162,3 +158,11 @@ const graph = graphfi(...); const teamSite = await graph.groups.getById("7d2b9355-0891-47d3-84c8-bf2cd9c62177").sites.root(); const url = teamSite.webUrl ``` + +## Group Photo Operations + +See [Photos](./photos.md) + +## Group Conversation Operations + +See [Conversations](./conversations.md) diff --git a/docs/graph/outlook.md b/docs/graph/mail-categories.md similarity index 94% rename from docs/graph/outlook.md rename to docs/graph/mail-categories.md index 535b6e57d..7295607bb 100644 --- a/docs/graph/outlook.md +++ b/docs/graph/mail-categories.md @@ -1,6 +1,4 @@ -# @pnp/graph/outlook - -Represents the Outlook services available to a user. Currently, only interacting with categories is supported. +# Graph Mail Categories You can learn more by reading the [Official Microsoft Graph Documentation](https://docs.microsoft.com/en-us/graph/api/resources/outlookuser?view=graph-rest-1.0). diff --git a/docs/graph/mail-folders.md b/docs/graph/mail-folders.md new file mode 100644 index 000000000..2aeb5f85f --- /dev/null +++ b/docs/graph/mail-folders.md @@ -0,0 +1,166 @@ +# Graph Mail Folders + +More information can be found in the official Graph documentation: + +- [Mail Folder Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/mailfolder?view=graph-rest-1.0) + +[![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + +## Get Mail folder listing + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +// This can be any folder id or Well-known folder names +const currentUserInbox = await graph.me.mailFolders.getById("inbox")(); + +// Get folders +const folders = await graph.me.mailFolders(); + +// Get folders and include hidden folders +const allFolders = await graph.me.mailFolders.includeHidden(); +``` + +## Get Specific Folder by Id or Well0know folder name + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +// Get folder by Well-known folder names +const currentUserInbox = await graph.me.mailFolders.getById("inbox")(); + +// Get folders +const folders = await graph.me.mailFolders(); +// Get folder by folder id +const currentUserFolder = await graph.me.mailFolders.getById(folders[0].id)(); +``` + +## Get Folders - Delta + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; +import {IMailFolderDelta} from "@pnp/graph/mail" + +const graph = graphfi(...); + +const currentUser = graph.me; +const folders = await currentUser.mailFolders.delta(); + +const deltatoken = folders.deltaLink.substring(folder.deltaLink.indexOf("deltatoken=") + 11); +const deltaParameters: IMailFolderDelta = { + "$skiptoken": null, + "$deltatoken": deltatoken, +} +const deltaFolders = await currentUser.mailFolders.delta(deltaParameters); +``` + +## Add Folder or Search Folder + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +// Add Mail Folder +const draftFolder: IMailFolder = { + displayName: "PnP Test Folder", + isHidden: false, +}; + +const folder = await graph.users.getById(testUserName).mailFolders.add(draftFolder); + +// Add Child Folder + +const childFolder = await graph.users.getById(testUserName).mailFolders.getById({mailFolderId}).childFolders.add(draftFolder); + +// Add Search Folder +const currentUserInbox = await graph.me.mailFolders.getById("inbox")(); + +const draftSearchFolder: IMailSearchFolder = { + displayName: "PnP Test Search Folder", + sourceFolderIds: [currentUserInbox.id], + filterQuery: "{Your Query Goes Here}" +}; + +const searchFolder = await graph.users.getById(testUserName).mailFolders.getById(currentUserInbox.id).childFolders.add(draftSearchFolder); +``` + +## Update Folder + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +const folder = await graph.users.getById(testUserName).mailFolders.update({displayName: "New Display Name"}); +``` + +## Delete Folder + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +await graph.users.getById(testUserName).mailFolders.getById({mailFolderId}).delete(); +``` + +## Copy/Move Folder + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +const destinationFolderId = "..."; +// Move folder to destination folder +await graph.users.getById(testUserName).mailFolders.getById({mailFolderId}).move(destinationFolderId); +// Copy folder to destination folder +await graph.users.getById(testUserName).mailFolders.getById({mailFolderId}).copy(destinationFolderId); +``` + +## Get Child Folders + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +await graph.users.getById(testUserName).mailFolders.getById({mailFolderId}).childFolders(); +``` + +## Get Folder's Messages + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +await graph.users.getById(testUserName).mailFolders.getById({mailFolderId}).messages(); +``` + +## Messages + +For more information on [Messages](./mail-messages.md) diff --git a/docs/graph/mail-mailbox.md b/docs/graph/mail-mailbox.md new file mode 100644 index 000000000..5d7a829ea --- /dev/null +++ b/docs/graph/mail-mailbox.md @@ -0,0 +1,103 @@ +# Graph Mailbox + +More information can be found in the official Graph documentation: + +- [Outlook Mailbox Settings Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/mailboxsettings?view=graph-rest-1.0) +- [Manage Focused Inbox](https://learn.microsoft.com/en-us/graph/api/resources/manage-focused-inbox?view=graph-rest-1.0) + +## IMailboxSettings + +[![Invokable Banner](https://img.shields.io/badge/Invokable-informational.svg)](../concepts/invokable.md) [![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + +## Get User's Mailbox Setting + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/mailbox"; + +const graph = graphfi(...); + +const currentUser = graph.me; +const mailboxSettings = await currentUser.mailboxSettings(); +const automaticRepliesSetting = await currentUser.mailboxSettings.automaticRepliesSetting(); +const dateFormat = await currentUser.mailboxSettings.dateFormat(); +const language = await currentUser.mailboxSettings.language(); +const timeFormat = await currentUser.mailboxSettings.timeFormat(); +const timeZone = await currentUser.mailboxSettings.timeZone(); +const workingHours = await currentUser.mailboxSettings.workingHours(); +const userPurpose = await currentUser.mailboxSettings.userPurpose(); +``` + +## Get User's Focused Inbox Overrides + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/mailbox"; + +const graph = graphfi(...); + +const currentUser = graph.me; +const fio = await currentUser.focusedInboxOverrides(); +``` + +## Get User's Focused Inbox Override by Id + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/mailbox"; + +const graph = graphfi(...); + +const currentUser = graph.me; +const fio = await currentUser.focusedInboxOverrides.getById({fio id}); +``` + +## Add Focused Inbox Override + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/mailbox"; + +const graph = graphfi(...); + +const override: InferenceClassificationOverride = { + classifyAs: "focused", + senderEmailAddress: { + name: "Mary Smith", + address: "msmith@contoso.com", + }, + }; + +const currentUser = graph.me; +const fio = await currentUser.focusedInboxOverrides.add(override); +``` + +## Update Focused Inbox Override + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/mailbox"; + +const graph = graphfi(...); + +const currentUser = graph.me; +const fio = await currentUser.focusedInboxOverrides.update({ senderEmailAddress: { name: "marysmith@contoso.com" }}); +``` + +## Delete Focused Inbox Override + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/mailbox"; + +const graph = graphfi(...); + +const currentUser = graph.me; +const fio = await currentUser.focusedInboxOverrides.getById({fio id}).delete(); +``` diff --git a/docs/graph/mail-messages.md b/docs/graph/mail-messages.md new file mode 100644 index 000000000..06d48f5fc --- /dev/null +++ b/docs/graph/mail-messages.md @@ -0,0 +1,208 @@ +# Graph Mail Messages + +More information can be found in the official Graph documentation: + +- [Message Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/message?view=graph-rest-1.0) + +## IMessage, IMessages + +[![Invokable Banner](https://img.shields.io/badge/Invokable-informational.svg)](../concepts/invokable.md) [![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + +## Get User's Messages + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const graph = graphfi(...); + +const currentUser = graph.me; +const messages = await currentUser.messages(); +``` + +## Get User's Messages - Delta + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; +import {IMessageDelta} from "@pnp/graph/mail" + +const graph = graphfi(...); + +const currentUser = graph.me; +const messages = await currentUser.messages.delta(); + +const deltatoken = messages.deltaLink.substring(folder.deltaLink.indexOf("deltatoken=") + 11); +const deltaParameters: IMessageDelta = { + "$skiptoken": null, + "$deltatoken": deltatoken, + changeType: "created" +} +const deltaMessages = await currentUser.messages.delta(deltaParameters); +``` + +## Create Draft Message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const draftMessage: Message = { + subject: "PnPjs Test Message", + importance: "low", + body: { + contentType: "html", + content: "This is a test message!", + }, + toRecipients: [ + { + emailAddress: { + address: "AdeleV@contoso.onmicrosoft.com", + }, + }, + ], +}; + + +const graph = graphfi(...); +const currentUser = graph.me; +const draft = await currentUser.messages.add(m); +``` + +## Update Draft Message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const graph = graphfi(...); +const currentUser = graph.me; +const update = await currentUser.messages.getById(draft.id).update({ subject: "New Subject" }); +``` + +## Delete a Message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const graph = graphfi(...); +const currentUser = graph.me; +await currentUser.messages.getById({id}).delete(); +``` + +## Copy a Message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const graph = graphfi(...); +const currentUser = graph.me; +const messageId = ""; +const messageCopy = await currentUser.messages.getById(messageId).copy({Destination Folder Id}); +``` + +## Move a Message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const graph = graphfi(...); +const currentUser = graph.me; +const messageId = ""; +const messageCopy = await currentUser.messages.getById(messageId).move({Destination Folder Id}); +``` + +## Send Draft Message/Reply/ReplyAll + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const graph = graphfi(...); +const currentUser = graph.me; +const update = await currentUser.messages.getById(draft.id).send(); +``` + +## Send Message + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; + +const draftMessage: Message = { + subject: "PnPjs Test Message", + importance: "low", + body: { + contentType: "html", + content: "This is a test message!", + }, + toRecipients: [ + { + emailAddress: { + address: "AdeleV@contoso.onmicrosoft.com", + }, + }, + ], +}; + + +const graph = graphfi(...); +const currentUser = graph.me; +const draft = await currentUser.sendMail(m); +``` + +## Create Draft Reply/ReplyAll/Forward for Message + +The payload for any of these methods take either no payload or one of the Options outlined in the example below. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail/messages"; +import {Message} from " + +//Option 1 +const draftMessage1: Message = { + subject: "PnPjs Test Message", + importance: "low", + body: { + contentType: "html", + content: "This is a test message!", + }, + toRecipients: [ + { + emailAddress: { + address: "AdeleV@contoso.onmicrosoft.com", + }, + }, + ], +}; + +//Option 2 +const draftMessage2 = { + comment: "This is my response" +} + +const graph = graphfi(...); +const messageId = ""; +const currentUser = graph.me; +const draftReply = await currentUser.messages.getById(messageId).createReply(draftMessage1); +const draftReplyAll = await currentUser.messages.getById(messageId).createReplyAll(draftMessage2); +const draftForward = await currentUser.messages.getById(messageId).createForward(); +``` + +## Message Attachments + +See [Attachments](./attachments.md) diff --git a/docs/graph/mail-rules.md b/docs/graph/mail-rules.md new file mode 100644 index 000000000..9d50095a9 --- /dev/null +++ b/docs/graph/mail-rules.md @@ -0,0 +1,103 @@ +# Graph Mail Rules + +More information can be found in the official Graph documentation: + +- [Rule Resource Type](https://learn.microsoft.com/en-us/graph/api/resources/messagerule?view=graph-rest-1.0) + +## IMessageRule, IMessageRules + +[![Invokable Banner](https://img.shields.io/badge/Invokable-informational.svg)](../concepts/invokable.md) [![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + +## Get User's Message Rules for their Inbox + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +// This can be any folder id or Well-known folder names +const currentUserInbox = graph.me.mailFolders.getById("inbox"); +const rules = await currentUserInbox.messageRules(); +``` + +## Get a Message Rules for a User + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +// This can be any folder id or Well-known folder names +const currentUserInbox = graph.me.mailFolders.getById("inbox"); +const rule = await currentUserInbox.messageRules.getById({ruleId})(); +``` + +## Add a Message Rule + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; +import { MessageRule as IMessageRuleType } from "@microsoft/microsoft-graph-types"; + +const graph = graphfi(...); + +const draftRule: IMessageRuleType = { + displayName: "PnPjs Test Rule", + sequence: 2, + isEnabled: true, + conditions: { + senderContains: [ + "adele", + ], + }, + actions: { + forwardTo: [ + { + emailAddress: { + name: "Alex Wilbur", + address: "AlexW@contoso.onmicrosoft.com", + }, + }, + ], + stopProcessingRules: true, + }, + }; + +// This can be any folder id or Well-known folder names +const currentUserInbox = graph.me.mailFolders.getById("inbox"); +const rule = await currentUserInbox.messageRules.add(draftRule); +``` + +## Update a Message Rule + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +// This can be any folder id or Well-known folder names +const currentUserInbox = graph.me.mailFolders.getById("inbox"); +const newRuleName = "My Mail Rule"; +const rule = await currentUserInbox.messageRules.getById({ruleId}).update({ displayName: newRuleName }); +``` + +## Delete a Message Rule + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; + +const graph = graphfi(...); + +// This can be any folder id or Well-known folder names +const currentUserInbox = graph.me.mailFolders.getById("inbox"); +const rule = await currentUserInbox.messageRules.getById({ruleId}).delete(); +``` diff --git a/docs/graph/messages.md b/docs/graph/messages.md deleted file mode 100644 index 2516fc416..000000000 --- a/docs/graph/messages.md +++ /dev/null @@ -1,20 +0,0 @@ -# Graph Messages (Mail) - -More information can be found in the official Graph documentation: - -- [Message Resource Type](https://docs.microsoft.com/en-us/graph/api/resources/message?view=graph-rest-1.0) - -[![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) - -## Get User's Messages - -```TypeScript -import { graphfi } from "@pnp/graph"; -import "@pnp/graph/users"; -import "@pnp/graph/messages"; - -const graph = graphfi(...); - -const currentUser = graph.me; -const messages = await currentUser.messages(); -``` diff --git a/mkdocs.yml b/mkdocs.yml index 9b00f5691..3b28d5e07 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -39,10 +39,12 @@ nav: - util: 'core/util.md' - graph: - graph: 'packages/#graph' + - attachments: 'graph/attachments.md' - behaviors: 'graph/behaviors.md' - bookings: 'graph/bookings.md' - columns: 'graph/columns.md' - 'content types': 'graph/content-types.md' + - conversations: 'graph/conversations.md' - groups: 'graph/groups.md' - insights: 'graph/insights.md' - contacts: 'graph/contacts.md' @@ -53,7 +55,12 @@ nav: - invitations: 'graph/invitations.md' - items: 'graph/items.md' - lists: 'graph/lists.md' - - messages: 'graph/messages.md' + - mail: + - 'categories': 'graph/mail-categories.md' + - 'folders': 'graph/mail-folders.md' + - 'mailbox': 'graph/mail-mailbox.md' + - 'messages': 'graph/mail-messages.md' + - 'rules': 'graph/mail-rules.md' - outlook: 'graph/outlook.md' - operations: 'graph/operations.md' - permissions: 'graph/permissions.md' diff --git a/package-lock.json b/package-lock.json index 16ae6bce0..9e4a09b90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,23 +100,22 @@ } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.13.0.tgz", + "integrity": "sha512-a62aP/wppgmnfIkJLfcB4ssPBcH94WzrzPVJ3tlJt050zX4lfmtnvy95D3igDo3f31StO+9BgPrzvkj4aOxnoA==", "dev": true, "dependencies": { - "@azure/abort-controller": "^1.0.0", + "@azure/abort-controller": "^1.1.0", "@azure/core-auth": "^1.4.0", "@azure/core-tracing": "^1.0.1", "@azure/core-util": "^1.3.0", "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "tslib": "^2.2.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-tracing": { @@ -132,22 +131,23 @@ } }, "node_modules/@azure/core-util": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.5.0.tgz", - "integrity": "sha512-GZBpVFDtQ/15hW1OgBcRdT4Bl7AEpcEZqLfbAvOtm1CQUncKWiYapFHVD588hmlV27NbOOtSm3cnLF3lvoHi4g==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.6.1.tgz", + "integrity": "sha512-h5taHeySlsV9qxuK64KZxy4iln1BtMYlNt5jbuEFN3UFSAd1EwKg/Gjl5a6tZ/W8t6li3xPnutOx7zbDyXnPmQ==", "dev": true, "dependencies": { "@azure/abort-controller": "^1.0.0", "tslib": "^2.2.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@azure/identity": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-3.3.0.tgz", "integrity": "sha512-gISa/dAAxrWt6F2WiDXZY0y2xY4MLlN2wkNW4cPuq5OgPQKLSkxLc4I2WR04puTfZyQZnpXbAapAMEj1b96fgg==", + "deprecated": "Please upgrade to the latest version of this package to get necessary fixes", "dev": true, "dependencies": { "@azure/abort-controller": "^1.0.0", @@ -184,21 +184,22 @@ } }, "node_modules/@azure/msal-browser": { - "version": "2.38.2", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.38.2.tgz", - "integrity": "sha512-71BeIn2we6LIgMplwCSaMq5zAwmalyJR3jFcVOZxNVfQ1saBRwOD+P77nLs5vrRCedVKTq8RMFhIOdpMLNno0A==", + "version": "2.38.3", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.38.3.tgz", + "integrity": "sha512-2WuLFnWWPR1IdvhhysT18cBbkXx1z0YIchVss5AwVA95g7CU5CpT3d+5BcgVGNXDXbUU7/5p0xYHV99V5z8C/A==", + "deprecated": "A newer major version of this library is available. Please upgrade to the latest available version.", "dev": true, "dependencies": { - "@azure/msal-common": "13.3.0" + "@azure/msal-common": "13.3.1" }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-common": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.3.0.tgz", - "integrity": "sha512-/VFWTicjcJbrGp3yQP7A24xU95NiDMe23vxIU1U6qdRPFsprMDNUohMudclnd+WSHE4/McqkZs/nUU3sAKkVjg==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.3.1.tgz", + "integrity": "sha512-Lrk1ozoAtaP/cp53May3v6HtcFSVxdFrg2Pa/1xu5oIvsIwhxW6zSPibKefCOVgd5osgykMi5jjcZHv8XkzZEQ==", "dev": true, "engines": { "node": ">=0.8.0" @@ -208,6 +209,7 @@ "version": "1.18.3", "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.18.3.tgz", "integrity": "sha512-lI1OsxNbS/gxRD4548Wyj22Dk8kS7eGMwD9GlBZvQmFV8FJUXoXySL1BiNzDsHUE96/DS/DHmA+F73p1Dkcktg==", + "deprecated": "A newer major version of this library is available. Please upgrade to the latest available version.", "dev": true, "dependencies": { "@azure/msal-common": "13.3.0", @@ -218,13 +220,22 @@ "node": "10 || 12 || 14 || 16 || 18" } }, + "node_modules/@azure/msal-node/node_modules/@azure/msal-common": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.3.0.tgz", + "integrity": "sha512-/VFWTicjcJbrGp3yQP7A24xU95NiDMe23vxIU1U6qdRPFsprMDNUohMudclnd+WSHE4/McqkZs/nUU3sAKkVjg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -312,9 +323,9 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -421,18 +432,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.0.tgz", - "integrity": "sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -462,12 +473,12 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -489,9 +500,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@jridgewell/gen-mapping": { @@ -543,9 +554,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -559,9 +570,9 @@ "dev": true }, "node_modules/@microsoft/microsoft-graph-types": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.38.0.tgz", - "integrity": "sha512-EXpTf/TFUb0EfBXiQ0rTmZf6fRgBn73lNfYdU2QKvqiMPQD/Cs2Gt+VmWVtK19F9Mf5Mt4bDTu5Ft0TGXOF8rA==", + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.40.0.tgz", + "integrity": "sha512-1fcPVrB/NkbNcGNfCy+Cgnvwxt6/sbIEEFgZHFBJ670zYLegENYJF8qMo7x3LqBjWX2/Eneq5BVVRCLTmlJN+g==", "dev": true }, "node_modules/@nodelib/fs.scandir": { @@ -801,9 +812,9 @@ } }, "node_modules/@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, "dependencies": { "@types/connect": "*", @@ -811,18 +822,18 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", - "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-U5tlMYa0U/2eFTmJgKcPWQOEICP173sJDa6OjHbj5Tv+NVaYcrq2xmdWpNXOwWYGwJu+jER/pfTLdoQ31q8PzA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.4.tgz", + "integrity": "sha512-0WR3b8eaISjEW7RpZnclONaLFDf7buaowRHdqLp4vLj54AsSAYWfh3DRbfiYJY9XDxMgx1B4sE1Afw2PGpuHOA==", "dev": true }, "node_modules/@types/chai": { @@ -841,18 +852,18 @@ } }, "node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", - "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", @@ -866,9 +877,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.44.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", - "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", + "version": "8.44.9", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.9.tgz", + "integrity": "sha512-6yBxcvwnnYoYT1Uk2d+jvIfsuP4mb2EdIxFnrPABj5a/838qe5bGkNLFOiipX4ULQ7XVQvTxOh7jO+BTAiqsEw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -876,9 +887,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz", - "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -886,9 +897,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/expect": { @@ -898,9 +909,9 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.18", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz", - "integrity": "sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -910,9 +921,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", "dev": true, "dependencies": { "@types/node": "*", @@ -931,9 +942,9 @@ } }, "node_modules/@types/glob-stream": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-8.0.0.tgz", - "integrity": "sha512-fxTWwdQmX9LWSHD7ZLlv3BHR992mKcVcDnT/2v+l/QZZo7TfDdyasqlSYVzOnMGWhRbrWeWkbj/mgezFjKynhw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-8.0.2.tgz", + "integrity": "sha512-kyuRfGE+yiSJWzSO3t74rXxdZNdYfLcllO0IUha4eX1fl40pm9L02Q/TEc3mykTLjoWz4STBNwYnUWdFu3I0DA==", "dev": true, "dependencies": { "@types/node": "*", @@ -953,45 +964,45 @@ } }, "node_modules/@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true }, "node_modules/@types/http-proxy": { - "version": "1.17.12", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", - "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/micromatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.3.tgz", - "integrity": "sha512-QX1czv7QoLU76Asb1NSVSlu5zTMx/TFNswUDtQSbH9hgvCg+JHvIEoVvVSzBf1WNCT8XsK515W+p3wFOCuvhCg==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.6.tgz", + "integrity": "sha512-2eulCHWqjEpk9/vyic4tBhI8a9qQEl6DaK2n/sF7TweX9YESlypgKyhXMDGt4DAOy/jhLPvVrZc8pTDAMsplJA==", "dev": true, "dependencies": { "@types/braces": "*" } }, "node_modules/@types/mime": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", - "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, "node_modules/@types/minimist": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.3.tgz", - "integrity": "sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true }, "node_modules/@types/mocha": { @@ -1006,28 +1017,37 @@ "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", "dev": true }, + "node_modules/@types/node-forge": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz", + "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/normalize-package-data": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, "node_modules/@types/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-Ejq9/KBsgfZZafGGdr9R7011EZhDzcAEMjoBl2W4eGNcZGhsUFMbUA0D+sHxjtAA1ldk3e6wapzXeyp0NSuM8Q==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.3.tgz", + "integrity": "sha512-Yll76ZHikRFCyz/pffKGjrCwe/le2CDwOP5F210KQo27kpRE46U2rDnzikNlVn6/ezH3Mhn46bJMTfeVTtcYMg==", "dev": true }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz", - "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, "node_modules/@types/retry": { @@ -1037,15 +1057,15 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", - "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -1053,18 +1073,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.2.tgz", - "integrity": "sha512-asaEIoc6J+DbBKXtO7p2shWUpKacZOoMBEGBgPG91P8xhO53ohzHWGCs4ScZo5pQMf5ukQzVT9fhX1WzpHihig==", + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", - "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -1073,27 +1093,27 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.34", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.34.tgz", - "integrity": "sha512-R+n7qBFnm/6jinlteC9DBL5dGiDGjWAvjo4viUanpnc/dG1y7uDoacXPIQ/PQEg1fI912SMHIa014ZjRpvDw4g==", + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/streamx": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/streamx/-/streamx-2.9.2.tgz", - "integrity": "sha512-HmO0hbPVLzr6HIcc86QQPjJRLpBDQmC+c/qd1jG3vpH1ZgGxl9R9xhofm19vh7Xm8wHUcKBek1Ef1OHrwipmiA==", + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/@types/streamx/-/streamx-2.9.5.tgz", + "integrity": "sha512-IHYsa6jYrck8VEdSwpY141FTTf6D7boPeMq9jy4qazNrFMA4VbRz/sw5LSsfR7jwdDcx0QKWkUexZvsWBC2eIQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/undertaker": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.9.tgz", - "integrity": "sha512-rOGGHtWFP4jsSKXvW2BJn+hYIAJ4cvsJi5wscbfbBHQ0yLQvTUXKvL+i72cv+8biktveFLEqbMpsKmJQxYVPQw==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.11.tgz", + "integrity": "sha512-j1Z0V2ByRHr8ZK7eOeGq0LGkkdthNFW0uAZGY22iRkNQNL9/vAV0yFPr1QN3FM/peY5bxs9P+1f0PYJTQVa5iA==", "dev": true, "dependencies": { "@types/node": "*", @@ -1102,15 +1122,15 @@ } }, "node_modules/@types/undertaker-registry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.2.tgz", - "integrity": "sha512-O9CqcXYnCsHUSd71+hohlhEaP57dThYQQ8/cDwskhTCJ1kA3E5CVaK1sbEnukP2eWlpSgae/8KqgJBw3w/DmoQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/undertaker-registry/-/undertaker-registry-1.0.4.tgz", + "integrity": "sha512-tW77pHh2TU4uebWXWeEM5laiw8BuJ7pyJYDh6xenOs75nhny2kVgwYbegJ4BoLMYsIrXaBpKYaPdYO3/udG+hg==", "dev": true }, "node_modules/@types/vinyl": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.8.tgz", - "integrity": "sha512-bls3EAsYVnVoPKoqgFC4Rtq7Kzte4MCk8xMA9UEPPVncJFsov9FJWYj0uxqJRwNEi9b4i4zX13FydaDrhadmHg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.11.tgz", + "integrity": "sha512-vPXzCLmRp74e9LsP8oltnWKTH+jBwt86WgRUb4Pc9Lf3pkMVGyvIo2gm9bODeGfCay2DBB/hAWDuvf07JcK4rw==", "dev": true, "dependencies": { "@types/expect": "^1.20.4", @@ -1118,9 +1138,9 @@ } }, "node_modules/@types/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-lh/EgJwJikII5ZvdcrwUcm1zoBOwVG8/Szo3Q4opb6HE8yYUPejiE5UDiDrhzgU2Zka8jKjEDPHblAvg8faMqw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-3.0.5.tgz", + "integrity": "sha512-ckYz9giHgV6U10RFuf9WsDQ3X86EFougapxHmmoxLK7e6ICQqO8CE+4V/3lBN148V5N1pb4nQMmMjyScleVsig==", "dev": true, "dependencies": { "@types/glob-stream": "*", @@ -1140,9 +1160,9 @@ } }, "node_modules/@types/ws": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.6.tgz", - "integrity": "sha512-8B5EO9jLVCy+B58PLHvLDuOD8DRVMgQzq8d55SjLCOn9kqGyqOvy27exVaTio1q1nX5zLu8/6N0n2ThSxOM6tg==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dev": true, "dependencies": { "@types/node": "*" @@ -1158,9 +1178,9 @@ } }, "node_modules/@types/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -1568,9 +1588,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1935,9 +1955,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz", - "integrity": "sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -1954,9 +1974,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001539", - "electron-to-chromium": "^1.4.530", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -1988,13 +2008,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2052,9 +2073,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001541", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz", - "integrity": "sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "dev": true, "funding": [ { @@ -2274,18 +2295,6 @@ "node": ">=0.1.90" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -2586,15 +2595,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2696,9 +2696,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.535", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.535.tgz", - "integrity": "sha512-4548PpR4S5X5dlvX8NUIw0njH7btQtBoJWcgzpq7n2F9NQ5gMXOPP/6p6iVx6+YT3FVioNhEGa14WJj1k+2SfA==", + "version": "1.4.615", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", + "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==", "dev": true }, "node_modules/emoji-regex": { @@ -2748,9 +2748,9 @@ } }, "node_modules/envinfo": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", - "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", "dev": true, "bin": { "envinfo": "dist/cli.js" @@ -2769,9 +2769,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "dev": true }, "node_modules/escalade": { @@ -3135,9 +3135,9 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3301,17 +3301,17 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -3361,20 +3361,6 @@ "node": ">=0.10.0" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -3432,10 +3418,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-caller-file": { "version": "2.0.5", @@ -3456,15 +3445,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3563,9 +3552,9 @@ } }, "node_modules/globals": { - "version": "13.22.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", - "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3633,18 +3622,6 @@ "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3866,9 +3843,9 @@ } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -3993,12 +3970,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4338,22 +4315,22 @@ } }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", "dev": true, "dependencies": { "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" + "shell-quote": "^1.8.1" } }, "node_modules/levn": { @@ -4497,12 +4474,12 @@ } }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "node_modules/lru-cache": { @@ -4901,6 +4878,7 @@ "version": "1.4.18", "resolved": "https://registry.npmjs.org/msal/-/msal-1.4.18.tgz", "integrity": "sha512-QyWMWrZqpwtK6LEqhwtbikxIWqA1EOcdMvDeIDjIXdGU29wM4orwq538sPe1+JfKDIgPmJj1Fgi5B7luaw/IyA==", + "deprecated": "This package is no longer supported. Please use @azure/msal-browser instead.", "dev": true, "dependencies": { "tslib": "^1.9.3" @@ -5008,9 +4986,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-package-data": { @@ -5050,9 +5028,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5523,9 +5501,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -5765,9 +5743,9 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -5932,11 +5910,12 @@ "dev": true }, "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "dependencies": { + "@types/node-forge": "^1.3.0", "node-forge": "^1" }, "engines": { @@ -6251,9 +6230,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz", - "integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", "dev": true }, "node_modules/spdy": { @@ -6449,9 +6428,9 @@ } }, "node_modules/terser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", - "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -7073,12 +7052,13 @@ } }, "node_modules/webpack-merge": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", - "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, "dependencies": { "clone-deep": "^4.0.1", + "flat": "^5.0.2", "wildcard": "^2.0.0" }, "engines": { @@ -7190,9 +7170,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.15.1.tgz", + "integrity": "sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/packages/graph/attachments/event.ts b/packages/graph/attachments/event.ts new file mode 100644 index 000000000..366ba0f0b --- /dev/null +++ b/packages/graph/attachments/event.ts @@ -0,0 +1,14 @@ +import { _Event } from "../calendars/types.js"; +import { addProp } from "@pnp/queryable"; +import { Attachments, IAttachments } from "./types.js"; + +declare module "../calendars/types" { + interface _Event { + readonly attachments: IAttachments; + } + interface IEvent { + readonly attachments: IAttachments; + } +} + +addProp(_Event, "attachments", Attachments); diff --git a/packages/graph/attachments/index.ts b/packages/graph/attachments/index.ts index eaa3e19b4..569d702c3 100644 --- a/packages/graph/attachments/index.ts +++ b/packages/graph/attachments/index.ts @@ -1,4 +1,6 @@ import "./conversations.js"; +import "./message.js"; +import "./event.js"; export { Attachment, diff --git a/packages/graph/attachments/message.ts b/packages/graph/attachments/message.ts new file mode 100644 index 000000000..6bc5c991d --- /dev/null +++ b/packages/graph/attachments/message.ts @@ -0,0 +1,14 @@ +import { _Message } from "../mail/messages.js"; +import { addProp } from "@pnp/queryable"; +import { Attachments, IAttachments } from "./types.js"; + +declare module "../mail/messages" { + interface _Message { + readonly attachments: IAttachments; + } + interface IMessage { + readonly attachments: IAttachments; + } +} + +addProp(_Message, "attachments", Attachments); diff --git a/packages/graph/attachments/types.ts b/packages/graph/attachments/types.ts index 2818fd31f..27c525e6b 100644 --- a/packages/graph/attachments/types.ts +++ b/packages/graph/attachments/types.ts @@ -1,14 +1,15 @@ import { Attachment as IAttachmentType } from "@microsoft/microsoft-graph-types"; import { body } from "@pnp/queryable"; -import { _GraphCollection, _GraphInstance, graphInvokableFactory, graphPost } from "../graphqueryable.js"; -import { defaultPath, getById, IGetById } from "../decorators.js"; +import { GraphInstance, _GraphCollection, _GraphInstance, graphInvokableFactory, graphPost } from "../graphqueryable.js"; +import { defaultPath, deleteable, getById, IDeleteable, IGetById } from "../decorators.js"; import { type } from "../utils/type.js"; /** * Attachment */ +@deleteable() export class _Attachment extends _GraphInstance { } -export interface IAttachment extends _Attachment { } +export interface IAttachment extends _Attachment, IDeleteable { } export const Attachment = graphInvokableFactory(_Attachment); /** @@ -18,6 +19,7 @@ export const Attachment = graphInvokableFactory(_Attachment); @getById(Attachment) export class _Attachments extends _GraphCollection { + // TODO: Adding attachments is not implemented correctly. I believe it requires updating the parent item but needs further investigation. /** * Add attachment to this collection * @@ -26,7 +28,7 @@ export class _Attachments extends _GraphCollection { */ public addFile(name: string, bytes: string | Blob): Promise { - return graphPost(this, body(type("#microsoft.graph.fileAttachment", { + return graphPost(GraphInstance(this), body(type("#microsoft.graph.fileAttachment", { contentBytes: bytes, name, }))); diff --git a/packages/graph/behaviors/paged.ts b/packages/graph/behaviors/paged.ts index 7cae1886b..3a06cf071 100644 --- a/packages/graph/behaviors/paged.ts +++ b/packages/graph/behaviors/paged.ts @@ -3,11 +3,12 @@ import { errorCheck, parseODataJSON } from "@pnp/queryable"; import { GraphCollection, IGraphQueryable, IGraphCollection } from "../graphqueryable.js"; import { ConsistencyLevel } from "./consistency-level.js"; -export interface IPagedResult { +export interface IPagedResult { count: number; - value: any | any[] | null; + value: T | T[] | null; hasNext: boolean; nextLink: string; + deltaLink: string; } /** @@ -23,7 +24,7 @@ export async function Count(col: IGraphCollection): Promise { q.query.set("$count", "true"); q.top(1); - const y: IPagedResult = await q(); + const y: IPagedResult = await q(); return y.count; } @@ -42,15 +43,18 @@ export function Paged(): TimelinePipe { const txt = await response.text(); const json = txt.replace(/\s/ig, "").length > 0 ? JSON.parse(txt) : {}; const nextLink = json["@odata.nextLink"]; + const deltaLink = json["@odata.deltaLink"]; const count = hOP(json, "@odata.count") ? parseInt(json["@odata.count"], 10) : -1; const hasNext = !stringIsNullOrEmpty(nextLink); + const hasDelta = !stringIsNullOrEmpty(deltaLink); result = { count, hasNext, nextLink: hasNext ? nextLink : null, + deltaLink: hasDelta ? deltaLink : null, value: parseODataJSON(json), }; diff --git a/packages/graph/graphqueryable.ts b/packages/graph/graphqueryable.ts index f2e221d42..c1c6f039a 100644 --- a/packages/graph/graphqueryable.ts +++ b/packages/graph/graphqueryable.ts @@ -194,7 +194,7 @@ export class _GraphCollection extends _GraphQueryable return { done: true, value: undefined }; } - const result: IPagedResult = await this._next(); + const result: IPagedResult = await this._next(); if (result.hasNext) { this._next = GraphCollection([this._next, result.nextLink]); diff --git a/packages/graph/outlook/types.ts b/packages/graph/mail/categories.ts similarity index 68% rename from packages/graph/outlook/types.ts rename to packages/graph/mail/categories.ts index 606524491..0d50b1ca8 100644 --- a/packages/graph/outlook/types.ts +++ b/packages/graph/mail/categories.ts @@ -1,8 +1,8 @@ import { _GraphCollection, _GraphInstance, graphInvokableFactory } from "../graphqueryable.js"; import { OutlookUser as IOutlookType, OutlookCategory as IOutlookCategoryType } from "@microsoft/microsoft-graph-types"; -import { defaultPath, deleteable, getById, IDeleteable, IGetById, IUpdateable, updateable } from "../decorators.js"; -import { graphPost } from "@pnp/graph"; -import { body } from "@pnp/queryable"; +import { addable, defaultPath, deleteable, getById, IAddable, IDeleteable, IGetById, IUpdateable, updateable } from "../decorators.js"; +// import { graphPost } from "@pnp/graph"; +// import { body } from "@pnp/queryable"; /** * Outlook @@ -31,23 +31,9 @@ export const OutlookCategory = graphInvokableFactory(_OutlookC */ @defaultPath("masterCategories") @getById(OutlookCategory) -export class _MasterCategories extends _GraphCollection { - - /** - * Adds a new event to the collection - * - * @param properties The set of properties used to create the event - */ - public async add(properties: IOutlookCategoryType): Promise { - - const data = await graphPost(this, body(properties)); - - return { - data, - }; - } -} -export interface IMasterCategories extends _MasterCategories, IGetById { } +@addable() +export class _MasterCategories extends _GraphCollection { } +export interface IMasterCategories extends _MasterCategories, IGetById, IAddable { } export const MasterCategories = graphInvokableFactory(_MasterCategories); /** diff --git a/packages/graph/mail/folders.ts b/packages/graph/mail/folders.ts new file mode 100644 index 000000000..d92ab32ce --- /dev/null +++ b/packages/graph/mail/folders.ts @@ -0,0 +1,108 @@ +import { + MailFolder as IMailFolderType, + MailSearchFolder as IMailSearchFolderType, +} from "@microsoft/microsoft-graph-types"; +import { _GraphInstance, _GraphCollection, graphInvokableFactory, graphGet, GraphQueryable, graphPost } from "../graphqueryable.js"; +import { defaultPath, getById, addable, IGetById, IAddable, updateable, IUpdateable, IDeleteable, deleteable } from "../decorators.js"; +import { body, InjectHeaders } from "@pnp/queryable/index.js"; +import { IMessageRules, IMessages, MessageRules, Messages } from "./messages.js"; +import { IPagedResult, Paged } from "../behaviors/paged.js"; + +/** + * Mail Folder or Mail Search Folder + */ +@updateable() +@deleteable() +export class _MailFolder extends _GraphInstance { + /** + * Gets the child folders in this mail folder + * + */ + public get childFolders(): IMailFolders { + return MailFolders(this, "childFolders"); + } + + /** + * Gets the messages in this mail folder + * + */ + public get messages(): IMessages { + return Messages(this); + } + + /** + * Gets the child folders in this mail folder + * + */ + public get messageRules(): IMessageRules { + return MessageRules(this); + } + + /** + * Copy the mail folder + * + * @param destinationFolderId The id of the destination folder to copy the message to + */ + public async copy(destinationFolderId: string): Promise { + return await graphPost(MailFolder(this, "copy"), body({ destinationId: destinationFolderId })); + } + + /** + * Move the mail folder + * + * @param destinationFolderId The id of the destination folder to copy the message to + */ + public async move(destinationFolderId: string): Promise { + return await graphPost(MailFolder(this, "move"), body({ destinationId: destinationFolderId })); + } +} +export interface IMailFolder extends _MailFolder, IUpdateable, IDeleteable { } +export const MailFolder = graphInvokableFactory(_MailFolder); + +/** + * Mail Folders or Mail Search Folders + */ +@defaultPath("mailFolders") +@getById(MailFolder) +@addable() +export class _MailFolders extends _GraphCollection { + public get includeHidden() { + const q = GraphQueryable(this); + q.query.set("includeHiddenFolders", "true"); + return q; + } + + /** + * Gets the delta for the current set of mail folders + * + * @param properties The set of properties used to retrieve specific types of messages + */ + public async delta(properties?: IMailFolderDelta, maxPageSize?: number): Promise> { + properties = properties || {}; + const querystring = Object.keys(properties)?.map(key => `${key}=${properties[key]}`).join("&") || ""; + const path = (querystring.length > 0) ? `delta?${querystring}` : "delta"; + const q = GraphQueryable(this, path); + if (maxPageSize) { + q.using(InjectHeaders({ + "Prefer": `odata.maxpagesize=${maxPageSize}`, + })); + } + return await graphGet(q.using(Paged())); + } + +} +export interface IMailFolders extends _MailFolders, IGetById, IAddable { } +export const MailFolders = graphInvokableFactory(_MailFolders); + +// export interface IDelta { +// nextLink: string; +// deltaLink: string; +// values: T[]; +// valuesCollection: IGraphQueryableCollection; +// } + + +export interface IMailFolderDelta { + "$skiptoken"?: string; + "$deltatoken"?: string; +} diff --git a/packages/graph/mail/funcs.ts b/packages/graph/mail/funcs.ts index 9e3fba5c8..3b306512f 100644 --- a/packages/graph/mail/funcs.ts +++ b/packages/graph/mail/funcs.ts @@ -1,15 +1,31 @@ -import { IGraphQueryable, GraphCollection, graphPost } from "../graphqueryable.js"; -import { body } from "@pnp/queryable"; +import { TimeZoneInformation, Message as IMessageType } from "@microsoft/microsoft-graph-types"; +import { graphPost, IGraphQueryable } from "../graphqueryable.js"; +import { InjectHeaders, body } from "@pnp/queryable/index.js"; +import { Message } from "./messages.js"; /** * Get the occurrences, exceptions, and single instances of events in a calendar view defined by a time range, * from the user's default calendar, or from some other calendar of the user's * * @param this IGraphQueryable instance - * @param message - should roughly match Message type in @microsoft/microsoft-graph-types. - * Am not typing the property because attaching a file require the property "@odata.type": "#microsoft.graph.fileAttachment" - * which is not included the typing and therefore will make the function unusable in that scenario. + * @param type "reply" | "replyAll" | "createReply" | "createReplyAll" | "forward" | "createForward" + * @param response The body of the response message + * If using JSON provide either comment: string or message: IMessageType. + * If using MIME format, provide the MIME content with the applicable Internet message headers, all encoded in base64 format. + * @param timeZone (optional) The time zone to use when creating the draft. + * Only use when providing a JSON message. */ -export function mailSend(this: IGraphQueryable, message: any): Promise { - return graphPost(GraphCollection(this, "mailSend"), body(message)); +export async function mailResponse( + gq: IGraphQueryable, + type: "reply" | "replyAll" | "createReply" | "createReplyAll" | "forward" | "createForward", + response: any, + timeZone: TimeZoneInformation = null): Promise { + + const header = (timeZone != null) ? { "Prefer: outlook.timezone": timeZone.alias } : null; + const postBody = response; + const q = Message(gq, type); + if (header != null) { + q.using(InjectHeaders(header)); + } + return await graphPost(q, body(postBody)); } diff --git a/packages/graph/mail/groups.ts b/packages/graph/mail/groups.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/graph/mail/index.ts b/packages/graph/mail/index.ts index b9f93edaa..88f9dcc8e 100644 --- a/packages/graph/mail/index.ts +++ b/packages/graph/mail/index.ts @@ -1,5 +1,40 @@ import "./users.js"; -// export { +export { + Outlook, + IOutlook, + IMasterCategories, + MasterCategories, + IMasterCategoryAddResult, + OutlookCategory, + IOutlookCategory, +} from "./categories.js"; + +export { + IMailboxSettings, + MailboxSettings, + FocusedInboxOverrides, + IFocusedInboxOverrides, +} from "./mailbox.js"; + +export { + IMessage, + IMessages, + IMessageRule, + IMessageRules, + IMessageDelta, + Message, + Messages, + MessageRule, + MessageRules, +} from "./messages.js"; + +export { + IMailFolder, + IMailFolders, + MailFolder, + MailFolders, + IMailFolderDelta, +} from "./folders.js"; + -// } from "./types.js"; diff --git a/packages/graph/mail/mailbox.ts b/packages/graph/mail/mailbox.ts new file mode 100644 index 000000000..f793342b8 --- /dev/null +++ b/packages/graph/mail/mailbox.ts @@ -0,0 +1,104 @@ +import { + MailboxSettings as IMailboxSettingsType, + AutomaticRepliesSetting as IAutomaticRepliesSetting, + LocaleInfo as ILocaleInfo, + WorkingHours as IWorkingHours, + UserPurpose as IUserPurpose, + InferenceClassificationOverride as IInterfaceClassificationOverride, +} from "@microsoft/microsoft-graph-types"; +import { _GraphInstance, _GraphCollection, graphInvokableFactory, graphGet, GraphQueryable } from "../graphqueryable.js"; +import { defaultPath, getById, IGetById, addable, IAddable, updateable, IUpdateable, IDeleteable, deleteable } from "../decorators.js"; + +/** + * MailboxSettings + */ +@defaultPath("mailboxSettings") +@updateable() +export class _MailboxSettings extends _GraphInstance { + /** + * Get the automatic replies setting + * + */ + public async automaticRepliesSetting(): Promise { + return graphGet(GraphQueryable(this, "automaticRepliesSetting")); + } + + /** + * Get the mailbox settings date format + * + */ + public async dateFormat(): Promise { + return graphGet(GraphQueryable(this, "dateFormat")); + } + + /** + * Get the delegateMeetingMessageDeliveryOptions settings + * + */ + // DOCUMENTED BUT NOT IMPLEMENTED + // public async delegateMeetingMessageDeliveryOptions(): Promise { + // return graphGet(GraphQueryable(this, "delegateMeetingMessageDeliveryOptions")); + // } + + /** + * Get the delegateMeetingMessageDeliveryOptions settings + * + */ + public async language(): Promise { + return graphGet(GraphQueryable(this, "language")); + } + + /** + * Get the mailbox settings time format + * + */ + public async timeFormat(): Promise { + return graphGet(GraphQueryable(this, "timeFormat")); + } + + /** + * Get the mailbox settings time format + * + */ + public async timeZone(): Promise { + return graphGet(GraphQueryable(this, "timeZone")); + } + + /** + * Get the mailbox settings working hours + * + */ + public async workingHours(): Promise { + return graphGet(GraphQueryable(this, "workingHours")); + } + + /** + * Get the mailbox settings user purpose + * + */ + public async userPurpose(): Promise { + return graphGet(GraphQueryable(this, "userPurpose")); + } +} +export interface IMailboxSettings extends _MailboxSettings, IUpdateable { } +export const MailboxSettings = graphInvokableFactory(_MailboxSettings); + +/** + * Focused Inbox Override + */ +@defaultPath("inferenceClassification/overrides") +@updateable() +@deleteable() +export class _FocusedInboxOverride extends _GraphInstance {} +export interface IFocusedInboxOverride extends _FocusedInboxOverride, IUpdateable, IDeleteable { } +export const FocusedInboxOverride = graphInvokableFactory(_FocusedInboxOverride); + +/** + * Focused Inbox Overrides + */ +@defaultPath("inferenceClassification/overrides") +@getById(FocusedInboxOverride) +@addable() +export class _FocusedInboxOverrides extends _GraphCollection {} +export interface IFocusedInboxOverrides extends _FocusedInboxOverrides, IGetById, IAddable { } +export const FocusedInboxOverrides = graphInvokableFactory(_FocusedInboxOverrides); diff --git a/packages/graph/mail/messages.ts b/packages/graph/mail/messages.ts new file mode 100644 index 000000000..08373ad77 --- /dev/null +++ b/packages/graph/mail/messages.ts @@ -0,0 +1,178 @@ +import { + Message as IMessageType, + MessageRule as IMessageRuleType, + TimeZoneInformation, +} from "@microsoft/microsoft-graph-types"; +import { _GraphInstance, _GraphCollection, graphInvokableFactory, graphGet, GraphQueryable, graphPost } from "../graphqueryable.js"; +import { defaultPath, getById, addable, IGetById, IAddable, updateable, IUpdateable, IDeleteable, deleteable } from "../decorators.js"; +import { body, InjectHeaders } from "@pnp/queryable/index.js"; +import { mailResponse } from "./funcs.js"; +import { IPagedResult, Paged } from "../behaviors/paged.js"; + +/** + * Message + */ +@updateable() +@deleteable() +export class _Message extends _GraphInstance { + + /** + * Sends the message + * + */ + public async send(): Promise { + return await graphPost(Message(this, "send")); + } + + /** + * Copy the message + * + * @param destinationFolderId The id of the destination folder to copy the message to + */ + public async copy(destinationFolderId: string): Promise { + return await graphPost(Message(this, "copy"), body({ destinationId: destinationFolderId })); + } + + /** + * Move the message + * + * @param destinationFolderId The id of the destination folder to copy the message to + */ + public async move(destinationFolderId: string): Promise { + return await graphPost(Message(this, "move"), body({ destinationId: destinationFolderId })); + } + + /** + * Create a draft response + * + * @param response (optional) The body of the response message + * If using JSON provide either comment: string or message: IMessageType. + * If using MIME format, provide the MIME content with the applicable Internet message headers, all encoded in base64 format. + * @param timeZone (optional) The time zone to use when creating the draft. + * Only use when providing a JSON message. + */ + public async createReply(response?: any, timeZone?: TimeZoneInformation): Promise { + return (await mailResponse(this, "createReply", response, timeZone)) as IMessageType; + } + + /** + * Send a message response + * + * @param response (optional) The body of the response message + * If using JSON provide either comment: string or message: IMessageType. + * If using MIME format, provide the MIME content with the applicable Internet message headers, all encoded in base64 format. + * @param timeZone (optional) The time zone to use when creating the draft. + * Only use when providing a JSON message. + */ + public async reply(response?: any, timeZone?: TimeZoneInformation): Promise { + return (await mailResponse(this, "reply", response, timeZone)) as void; + } + + /** + * Create a draft response message to all + * + * @param response (optional) The body of the response message + * If using JSON provide either comment: string or message: IMessageType. + * If using MIME format, provide the MIME content with the applicable Internet message headers, all encoded in base64 format. + * @param timeZone (optional) The time zone to use when creating the draft. + * Only use when providing a JSON message. + */ + public async createReplyAll(response?: any, timeZone?: TimeZoneInformation): Promise { + return (await mailResponse(this, "createReplyAll", response, timeZone)) as IMessageType; + } + + /** + * Send a message response to all + * + * @param response (optional) The body of the response message + * If using JSON provide either comment: string or message: IMessageType. + * If using MIME format, provide the MIME content with the applicable Internet message headers, all encoded in base64 format. + * @param timeZone (optional) The time zone to use when creating the draft. + * Only use when providing a JSON message. + */ + public async replyAll(response?: any, timeZone?: TimeZoneInformation): Promise { + return (await mailResponse(this, "replyAll", response, timeZone)) as void; + } + + /** + * Create a draft forward message + * + * @param forward (optional) The body of the forward message + * If using JSON provide either comment: string or message: IMessageType. + * If using MIME format, provide the MIME content with the applicable Internet message headers, all encoded in base64 format. + * @param timeZone (optional) The time zone to use when creating the draft. + * Only use when providing a JSON message. + */ + public async createForward(forward?: any, timeZone?: TimeZoneInformation): Promise { + return (await mailResponse(this, "createForward", forward, timeZone)) as IMessageType; + } + + /** + * Forward a message + * + * @param forward (optional) The body of the forward message + * If using JSON provide either comment: string or message: IMessageType. + * If using MIME format, provide the MIME content with the applicable Internet message headers, all encoded in base64 format. + * @param timeZone (optional) The time zone to use when creating the draft. + * Only use when providing a JSON message. + */ + public async forward(forward?: any, timeZone?: TimeZoneInformation): Promise { + return (await mailResponse(this, "forward", forward, timeZone)) as void; + } +} +export interface IMessage extends _Message, IUpdateable, IDeleteable { } +export const Message = graphInvokableFactory(_Message); + +/** + * Messages + */ +@defaultPath("messages") +@getById(Message) +@addable() +export class _Messages extends _GraphCollection { + /** + * Gets the delta for the current set of messages + * + * @param properties The set of properties used to retrieve specific types of messages + */ + public async delta(properties?: IMessageDelta, maxPageSize?: number): Promise> { + properties = properties || {}; + const querystring = Object.keys(properties)?.map(key => `${key}=${properties[key]}`).join("&") || ""; + const path = (querystring.length > 0) ? `delta?${querystring}` : "delta"; + const q = GraphQueryable(this, path); + if (maxPageSize) { + q.using(InjectHeaders({ + "Prefer": `odata.maxpagesize=${maxPageSize}`, + })); + } + return await graphGet(q.using(Paged())); + } +} +export interface IMessages extends _Messages, IGetById, IAddable, IDeleteable { } +export const Messages = graphInvokableFactory(_Messages); + + +/** + * Message Rule + */ +@updateable() +@deleteable() +export class _MessageRule extends _GraphInstance {} +export interface IMessageRule extends _MessageRule, IUpdateable, IDeleteable { } +export const MessageRule = graphInvokableFactory(_MessageRule); + +/** + * Message Rules + */ +@defaultPath("messageRules") +@getById(MessageRule) +@addable() +export class _MessageRules extends _GraphCollection {} +export interface IMessageRules extends _MessageRules, IGetById, IAddable { } +export const MessageRules = graphInvokableFactory(_MessageRules); + +export interface IMessageDelta { + "$skiptoken"?: string; + "$deltatoken"?: string; + changeType?: string; +} diff --git a/packages/graph/mail/types.ts b/packages/graph/mail/types.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/graph/mail/users.ts b/packages/graph/mail/users.ts index 6349a3146..c452fcd7d 100644 --- a/packages/graph/mail/users.ts +++ b/packages/graph/mail/users.ts @@ -1,17 +1,65 @@ -import { _User } from "../users/types.js"; -import { mailSend } from "./funcs.js"; +import { _User, User } from "../users/types.js"; +import { IMessages, Messages, IMessage } from "./messages.js"; +import { IMailFolders, MailFolders } from "./folders.js"; +import { IOutlook, Outlook } from "./categories.js"; +import { FocusedInboxOverrides, IFocusedInboxOverrides, IMailboxSettings, MailboxSettings } from "./mailbox.js"; +import { addProp, body } from "@pnp/queryable"; +import { graphPost } from "../graphqueryable.js"; declare module "../users/types" { interface _User { - mailSend(message: any): void; + readonly messages: IMessages; + readonly mailboxSettings: IMailboxSettings; + readonly mailFolders: IMailFolders; + readonly outlook: IOutlook; + readonly focusedInboxOverrides: IFocusedInboxOverrides; + sendMail(message: IMessage): Promise; + translateExchangeIds(translateExchangeIds: ITranslateExchangeIds): Promise; } interface IUser { - mailSend(message: any): void; + readonly messages: IMessages; + readonly mailboxSettings: IMailboxSettings; + readonly mailFolders: IMailFolders; + readonly outlook: IOutlook; + readonly focusedInboxOverrides: IFocusedInboxOverrides; + sendMail(message: IMessage): Promise; + translateExchangeIds(translateExchangeIds: ITranslateExchangeIds): Promise; } } -// addProp(_User, "calendar", Calendar); -// addProp(_User, "calendars", Calendars); -// addProp(_User, "events", Events); +addProp(_User, "messages", Messages); +addProp(_User, "mailboxSettings", MailboxSettings); +addProp(_User, "mailFolders", MailFolders); +addProp(_User, "outlook", Outlook); +addProp(_User, "focusedInboxOverrides", FocusedInboxOverrides, "inferenceClassification/overrides"); -_User.prototype.mailSend = mailSend; +_User.prototype.sendMail = function (this: _User, message: IMessage): Promise { + return graphPost(User(this, "sendMail"), body(message)); +}; + +/** + * Translate identifiers of Outlook-related resources between formats. + * + */ +_User.prototype.translateExchangeIds = function (this: _User, translateExchangeIds: ITranslateExchangeIds): Promise { + return graphPost(User(this, "translateExchangeIds"), body(translateExchangeIds)); +}; + +export interface IExchangeIdFormat { + entryId: string; + ewsId: string; + immutableEntryId: string; + restId: string; + restImmutableEntryId: string; +} + +export interface ITranslateExchangeIds { + inputIds: string[]; + sourceIdType: IExchangeIdFormat; + targetIdType: IExchangeIdFormat; +} + +export interface ITranslateExchangeIdsResponse { + sourceId: string; + targetId: string; +} diff --git a/packages/graph/messages/index.ts b/packages/graph/messages/index.ts deleted file mode 100644 index 051dbe593..000000000 --- a/packages/graph/messages/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import "./users.js"; - -export { - IMailFolder, - IMessage, - IMailFolders, - IMailboxSettings, - IMessages, - MailFolder, - MailFolders, - MailboxSettings, - Message, - Messages, -} from "./types.js"; diff --git a/packages/graph/messages/types.ts b/packages/graph/messages/types.ts deleted file mode 100644 index 342e544ce..000000000 --- a/packages/graph/messages/types.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Message as IMessageType, MailFolder as IMailFolderType, MailboxSettings as IMailboxSettingsType } from "@microsoft/microsoft-graph-types"; -import { _GraphInstance, _GraphCollection, graphInvokableFactory } from "../graphqueryable.js"; -import { defaultPath, getById, addable, IGetById, IAddable, updateable, IUpdateable } from "../decorators.js"; - -/** - * Message - */ -export class _Message extends _GraphInstance { } -export interface IMessage extends _Message { } -export const Message = graphInvokableFactory(_Message); - -/** - * Messages - */ -@defaultPath("messages") -@getById(Message) -@addable() -export class _Messages extends _GraphCollection { } -export interface IMessages extends _Messages, IGetById, IAddable { } -export const Messages = graphInvokableFactory(_Messages); - -/** - * MailFolder - */ -export class _MailFolder extends _GraphInstance { } -export interface IMailFolder extends _MailFolder { } -export const MailFolder = graphInvokableFactory(_MailFolder); - -/** - * MailFolders - */ -@defaultPath("mailFolders") -@getById(MailFolder) -@addable() -export class _MailFolders extends _GraphCollection { } -export interface IMailFolders extends _MailFolders, IGetById, IAddable { } -export const MailFolders = graphInvokableFactory(_MailFolders); - -/** - * MailboxSettings - */ -@defaultPath("mailboxSettings") -@updateable() -export class _MailboxSettings extends _GraphInstance { } -export interface IMailboxSettings extends _MailboxSettings, IUpdateable { } -export const MailboxSettings = graphInvokableFactory(_MailboxSettings); diff --git a/packages/graph/messages/users.ts b/packages/graph/messages/users.ts deleted file mode 100644 index 281280c35..000000000 --- a/packages/graph/messages/users.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { addProp, body } from "@pnp/queryable"; -import { _User, User } from "../users/types.js"; -import { IMessages, Messages, IMailboxSettings, MailboxSettings, IMailFolders, MailFolders, IMessage } from "./types.js"; -import { graphPost } from "../graphqueryable.js"; - -declare module "../users/types" { - interface _User { - readonly messages: IMessages; - readonly mailboxSettings: IMailboxSettings; - readonly mailFolders: IMailFolders; - sendMail(message: IMessage): Promise; - } - interface IUser { - readonly messages: IMessages; - readonly mailboxSettings: IMailboxSettings; - readonly mailFolders: IMailFolders; - sendMail(message: IMessage): Promise; - } -} - -addProp(_User, "messages", Messages); -addProp(_User, "mailboxSettings", MailboxSettings); -addProp(_User, "mailFolders", MailFolders); - -_User.prototype.sendMail = function (this: _User, message: IMessage): Promise { - return graphPost(User(this, "sendMail"), body(message)); -}; diff --git a/packages/graph/outlook/index.ts b/packages/graph/outlook/index.ts deleted file mode 100644 index 8e9ee1f97..000000000 --- a/packages/graph/outlook/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import "./users.js"; - -export { - Outlook, - IOutlook, - IMasterCategories, - MasterCategories, - IMasterCategoryAddResult, - OutlookCategory, - IOutlookCategory, -} from "./types.js"; diff --git a/packages/graph/outlook/users.ts b/packages/graph/outlook/users.ts deleted file mode 100644 index ccf2de521..000000000 --- a/packages/graph/outlook/users.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { addProp } from "@pnp/queryable"; -import { _User } from "../users/types.js"; -import { Outlook, IOutlook } from "./types.js"; - -declare module "../users/types" { - interface _User { - readonly outlook: IOutlook; - } - interface IUser { - readonly outlook: IOutlook; - } -} - -addProp(_User, "outlook", Outlook); diff --git a/packages/graph/presets/all.ts b/packages/graph/presets/all.ts index 2edcc11ad..e7b213db4 100644 --- a/packages/graph/presets/all.ts +++ b/packages/graph/presets/all.ts @@ -9,7 +9,7 @@ import "../groups/index.js"; import "../insights/index.js"; import "../invitations/index.js"; import "../members/index.js"; -import "../messages/index.js"; +import "../mail/index.js"; import "../files/index.js"; import "../onenote/index.js"; import "../operations/index.js"; @@ -32,7 +32,7 @@ export * from "../groups/index.js"; export * from "../insights/index.js"; export * from "../invitations/index.js"; export * from "../members/index.js"; -export * from "../messages/index.js"; +export * from "../mail/index.js"; export * from "../files/index.js"; export * from "../onenote/index.js"; export * from "../operations/index.js"; diff --git a/test/graph/analytics.ts b/test/graph/analytics.ts index 24998a917..855c11fac 100644 --- a/test/graph/analytics.ts +++ b/test/graph/analytics.ts @@ -9,6 +9,7 @@ import { List } from "@microsoft/microsoft-graph-types"; import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; import { IAnalyticsOptions } from "@pnp/graph/analytics"; import getTestingGraphSPSite from "./utilities/getTestingGraphSPSite.js"; +import { ListItem } from "@pnp/graph/list-item"; describe("Analytics", function () { let testUserName = ""; @@ -40,9 +41,7 @@ describe("Analytics", function () { const listResult = await site.lists.add(sampleList); listResultId = listResult.data.id; const listItemProps: any = { - fields: { - title: "Test Item", - }, + title: "Test Item", }; const listItem = await site.lists.getById(listResultId).items.add(listItemProps); listItemId = listItem.data.id; @@ -73,7 +72,8 @@ describe("Analytics", function () { return expect(analytics).to.haveOwnProperty("@odata.context").eq("https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.itemActivityStat"); }); - it("Get List Item Analytics - Last Seven Days", async function () { + // Analytics is not working on list items, returning item not found error. + it.skip("Get List Item Analytics - Last Seven Days", async function () { if (stringIsNullOrEmpty(listItemId)) { this.skip(); } @@ -103,11 +103,13 @@ describe("Analytics", function () { return expect(analytics).to.haveOwnProperty("@odata.context").eq("https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.itemActivityStat"); }); - it("Get List Item Analytics - All Time", async function () { + // Analytics is not working on list items, returning item not found error. + it.skip("Get List Item Analytics - All Time", async function () { if (stringIsNullOrEmpty(listItemId)) { this.skip(); } const options: IAnalyticsOptions = { timeRange: "allTime" }; + const item: ListItem = await site.lists.getById(listResultId).items.getById(listItemId)(); const analytics = await site.lists.getById(listResultId).items.getById(listItemId).analytics(options); return expect(analytics).to.haveOwnProperty("@odata.context").eq("https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.itemActivityStat"); }); diff --git a/test/graph/appCatalogs.ts b/test/graph/appCatalogs.ts index 39aa54dc7..10db8f088 100644 --- a/test/graph/appCatalogs.ts +++ b/test/graph/appCatalogs.ts @@ -3,7 +3,7 @@ import "@pnp/graph/teams"; import "@pnp/graph/appCatalog"; import { pnpTest } from "../pnp-test.js"; -describe.only("AppCatalog", function () { +describe("AppCatalog", function () { before(async function () { diff --git a/test/graph/attachments.ts b/test/graph/attachments.ts new file mode 100644 index 000000000..66dca8fc6 --- /dev/null +++ b/test/graph/attachments.ts @@ -0,0 +1,78 @@ +import { expect } from "chai"; +import getValidUser from "./utilities/getValidUser.js"; +import "@pnp/graph/users"; +import "@pnp/graph/teams"; +import "@pnp/graph/conversations"; +import "@pnp/graph/attachments"; +import { getRandomString } from "@pnp/core"; +import { Message } from "@microsoft/microsoft-graph-types"; + +describe.skip("Attachments", function () { + let testUserName = ""; + let groupId = ""; + let inboxFolder = null; + + const draftMessage: Message = { + subject: "PnPjs Test Message", + importance: "low", + body: { + contentType: "html", + content: "This is a test message!", + }, + toRecipients: [ + { + emailAddress: { + address: "AdeleV@contoso.onmicrosoft.com", + }, + }, + ], + }; + + before(async function () { + + if (!this.pnp.settings.enableWebTests) { + this.skip(); + } + const userInfo = await getValidUser.call(this); + testUserName = userInfo.userPrincipalName; + inboxFolder = this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox"); + const groups = await this.pnp.graph.users.getById(testUserName).joinedTeams(); + if (groups.length > 0) { + groupId = groups[0].id; + } else { + this.skip(); + } + }); + + describe.skip("Post", function () { + it("post getById", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const convThreads = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads(); + const threadPost = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads.getById(convThreads[0].id).posts(); + const post = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id) + .threads.getById(convThreads[0].id).posts.getById(threadPost[0].id)(); + return expect(post).to.have.property("id"); + }); + + // Remaining endpoints not supported by app permissions + }); + + describe.skip("Message", function () { + it("list", async function () { + const draft = await inboxFolder.messages.add(draftMessage); + const fileName = getRandomString(8) + ".txt"; + await inboxFolder.messages.getById(draft.id).attachments.addFile(fileName, "VGhpcyBpcyBhIGZpbGUgdG8gYmUgYXR0YWNoZWQu"); + const attachments = await inboxFolder.messages.getById(draft.id).attachments(); + return expect(attachments).to.have.length.greaterThan(0); + }); + + it("getById", async function () { + const draft = await inboxFolder.messages.add(draftMessage); + const fileName = getRandomString(8) + ".txt"; + const attachment = await inboxFolder.messages.getById(draft.id).attachments.addFile(fileName, "This is a test attachment"); + return expect(attachment).to.have.property("id"); + }); + + // Remaining endpoints not supported by app permissions + }); +}); diff --git a/test/graph/group-conversations.ts b/test/graph/group-conversations.ts new file mode 100644 index 000000000..f343b2206 --- /dev/null +++ b/test/graph/group-conversations.ts @@ -0,0 +1,126 @@ +import { expect } from "chai"; +import getValidUser from "./utilities/getValidUser.js"; +import "@pnp/graph/users"; +import "@pnp/graph/teams"; +import "@pnp/graph/conversations"; +import { IPostForwardInfo } from "@pnp/graph/conversations"; +import { + Post as IPostType, +} from "@microsoft/microsoft-graph-types"; +import { getRandomString } from "@pnp/core"; + +describe("Group Conversations", function () { + let testUserName = ""; + let groupId = ""; + + const draftPost: IPostType = { + body: { content: "This is a post" }, + from: { + emailAddress: { + address: "", + name: "", + }, + }, + }; + + const postForwardInfo: IPostForwardInfo = { + toRecipients: [ + { + emailAddress: { + address: "", + name: "", + }, + }, + ], + }; + + before(async function () { + + if (!this.pnp.settings.enableWebTests) { + this.skip(); + } + const userInfo = await getValidUser.call(this); + testUserName = userInfo.userPrincipalName; + draftPost.from.emailAddress.address = userInfo.userPrincipalName; + draftPost.from.emailAddress.name = userInfo.displayName; + postForwardInfo.toRecipients[0].emailAddress.address = userInfo.userPrincipalName; + postForwardInfo.toRecipients[0].emailAddress.name = userInfo.displayName; + const groups = await this.pnp.graph.users.getById(testUserName).joinedTeams(); + if (groups.length > 0) { + groupId = groups[0].id; + } else { + this.skip(); + } + }); + + describe("Group Conversations", function () { + it("list conversations", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + return expect(conversations.length).to.be.greaterThan(0); + }); + + it("conversation getById", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const conversation = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id)(); + return expect(conversation).to.have.property("id"); + }); + + it("list threads", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const convThreads = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads(); + return expect(convThreads).is.not.null; + }); + + it("thread getById", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const convThreads = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads(); + const thread = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads.getById(convThreads[0].id)(); + return expect(thread).to.have.property("id"); + }); + + it("list posts", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const convThreads = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads(); + let threadPost = null; + if (convThreads.length > 0) { + threadPost = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads.getById(convThreads[0].id).posts(); + } + return expect(threadPost).is.not.null; + }); + + it("post getById", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const convThreads = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads(); + const threadPost = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads.getById(convThreads[0].id).posts(); + const post = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id) + .threads.getById(convThreads[0].id).posts.getById(threadPost[0].id)(); + return expect(post).to.have.property("id"); + }); + + it("post reply", async function () { + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const convThreads = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads(); + const threadPost = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads.getById(convThreads[0].id).posts(); + const post = this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id) + .threads.getById(convThreads[0].id).posts.getById(threadPost[0].id); + const p = JSON.parse(JSON.stringify(draftPost)); + p.body.content = `Test Reply ${getRandomString(4)}`; + const reply = await post.reply(p); + return expect(reply).to.have.property("id"); + }); + + it("post forward", async function () { + let success = false; + const conversations = await this.pnp.graph.groups.getById(groupId).conversations(); + const convThreads = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads(); + const threadPost = await this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id).threads.getById(convThreads[0].id).posts(); + const post = this.pnp.graph.groups.getById(groupId).conversations.getById(conversations[0].id) + .threads.getById(convThreads[0].id).posts.getById(threadPost[0].id); + await post.forward(postForwardInfo); + success = true; + return expect(success).to.be.true; + }); + + // Remaining endpoints not supported by app permissions + }); +}); diff --git a/test/graph/outlook.ts b/test/graph/mail-categories.ts similarity index 89% rename from test/graph/outlook.ts rename to test/graph/mail-categories.ts index 98635c397..468c041f4 100644 --- a/test/graph/outlook.ts +++ b/test/graph/mail-categories.ts @@ -1,11 +1,11 @@ import { expect } from "chai"; import "@pnp/graph/users"; -import "@pnp/graph/outlook"; +import "@pnp/graph/mail"; import { OutlookCategory } from "@microsoft/microsoft-graph-types"; import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; import getValidUser from "./utilities/getValidUser.js"; -describe("Outlook", function () { +describe("Mail: Categories", function () { let testUserName = ""; const testCategoryList: string[] = []; @@ -37,7 +37,7 @@ describe("Outlook", function () { return; }); - it("outlook", async function () { + it("Mail: Categories", async function () { const outlookUser = await this.pnp.graph.users.getById(testUserName).outlook(); return expect(outlookUser).is.not.null; }); @@ -56,7 +56,7 @@ describe("Outlook", function () { }; const addedCategory = await this.pnp.graph.users.getById(testUserName).outlook.masterCategories.add(testCategory); - testCategoryList.push(addedCategory.data.id); + testCategoryList.push(addedCategory.id); return expect(addedCategory).is.not.null; }); @@ -68,13 +68,13 @@ describe("Outlook", function () { }; const addedCategory = await this.pnp.graph.users.getById(testUserName).outlook.masterCategories.add(testCategory); - testCategoryList.push(addedCategory.data.id); + testCategoryList.push(addedCategory.id); const updateCategory: OutlookCategory = { color: "preset3", }; - const updatedCategory = this.pnp.graph.users.getById(testUserName).outlook.masterCategories.getById(addedCategory.data.id).update(updateCategory); + const updatedCategory = this.pnp.graph.users.getById(testUserName).outlook.masterCategories.getById(addedCategory.id).update(updateCategory); return expect(updatedCategory).to.eventually.be.fulfilled; }); @@ -87,7 +87,7 @@ describe("Outlook", function () { const addedCategory = await this.pnp.graph.users.getById(testUserName).outlook.masterCategories.add(testCategory); - const deleteCategory = this.pnp.graph.users.getById(testUserName).outlook.masterCategories.getById(addedCategory.data.id).delete(); + const deleteCategory = this.pnp.graph.users.getById(testUserName).outlook.masterCategories.getById(addedCategory.id).delete(); return expect(deleteCategory).to.eventually.be.fulfilled; }); diff --git a/test/graph/mail-folders.ts b/test/graph/mail-folders.ts new file mode 100644 index 000000000..0dce3e0d1 --- /dev/null +++ b/test/graph/mail-folders.ts @@ -0,0 +1,194 @@ +import { expect } from "chai"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import getValidUser from "./utilities/getValidUser.js"; +import { MailFolder as IMailFolder, MailSearchFolder as IMailSearchFolder } from "@microsoft/microsoft-graph-types"; + +describe("Mail: Folders", function () { + const testFolderName = "PnP Test Folder"; + let testUserName = ""; + let inboxFolder = null; + + const draftFolder: IMailFolder = { + displayName: testFolderName, + isHidden: false, + }; + + const draftSearchFolder: IMailSearchFolder = { + displayName: `${testFolderName} Search`, + sourceFolderIds: [], + }; + + // Ensure we have the data to test against + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + const userInfo = await getValidUser.call(this); + testUserName = userInfo.userPrincipalName; + inboxFolder = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox")(); + draftSearchFolder.sourceFolderIds.push(inboxFolder.id); + }); + + // Clean up testing folders + after(async function () { + if (!stringIsNullOrEmpty(testUserName)) { + const folders: IMailFolder[] = await this.pnp.graph.users.getById(testUserName).mailFolders(); + for(let i=0; i < folders.length; i++){ + if(folders[i].displayName.startsWith(testFolderName)){ + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folders[i].id).delete(); + } + } + } + return; + }); + + it("Mail: Folder List", async function () { + const folders = await this.pnp.graph.users.getById(testUserName).mailFolders(); + return expect(folders).is.not.null; + }); + + it("Mail: Folder List - Include Hidden", async function () { + const folders = await this.pnp.graph.users.getById(testUserName).mailFolders.includeHidden(); + return expect(folders).is.not.null; + }); + + it("Mail: Folder List - Delta", async function () { + const folders = await this.pnp.graph.users.getById(testUserName).mailFolders.delta(); + return expect(folders).has.property("deltaLink"); + }); + + it("Mail: Get Folder by Id (Add/Delete)", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.add(f); + let success = false; + if (folder !== null) { + const getFolder = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id)(); + if(getFolder !== null) { + success = (getFolder.displayName === f.displayName); + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Folder Add", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.add(f); + const success = (folder !== null); + if (success) { + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).delete(); + } + return expect(success).to.be.true; + }); + + it("Mail: Search Folder Add", async function () { + const f: IMailSearchFolder = JSON.parse(JSON.stringify(draftSearchFolder)); + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(inboxFolder.id).childFolders.add(f); + const success = (folder !== null); + if (success) { + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).delete(); + } + return expect(success).to.be.true; + }); + + it("Mail: Folder Update", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + const newDisplayName = `${testFolderName} ${getRandomString(8)}`; + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.add(f); + let success = false; + if (folder !== null) { + const update = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).update({ displayName: newDisplayName }); + if (update !== null) { + success = (update.displayName === newDisplayName); + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(update.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Folder Delete", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.add(f); + let success = false; + if (folder !== null) { + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).delete(); + try { + const found = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id)(); + if (found?.id === null) { + success = true; + } + } catch (e) { + success = true; + } + } + return expect(success).to.be.true; + }); + + it("Mail: Folder Copy", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.add(f); + let success = false; + if (folder !== null) { + const folderCopy = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).copy(inboxFolder.id); + if (folderCopy !== null) { + success = true; + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folderCopy.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Folder Move", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder: IMailFolder = await this.pnp.graph.users.getById(testUserName).mailFolders.add(f); + let success = false; + if (folder !== null) { + const folderMove = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).move("drafts"); + if (folderMove !== null) { + success = (folderMove.displayName === folder.displayName); + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folderMove.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Child Folder List", async function () { + const folders = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").childFolders(); + return expect(folders).is.not.null; + }); + + it("Mail: Child Folder Add", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").childFolders.add(f); + const success = (folder !== null); + if (success) { + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).delete(); + } + return expect(success).to.be.true; + }); + + it("Mail: Child Folder Messages List", async function () { + const f: IMailFolder = JSON.parse(JSON.stringify(draftFolder)); + f.displayName = `${testFolderName} ${getRandomString(8)}`; + const folder = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").childFolders.add(f); + let success = false; + if (folder !== null) { + const messages = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).messages(); + success = (messages !== null); + await this.pnp.graph.users.getById(testUserName).mailFolders.getById(folder.id).delete(); + } + return expect(success).to.be.true; + }); +}); + diff --git a/test/graph/mail-mailbox.ts b/test/graph/mail-mailbox.ts new file mode 100644 index 000000000..e8229d37e --- /dev/null +++ b/test/graph/mail-mailbox.ts @@ -0,0 +1,157 @@ +import { expect } from "chai"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import getValidUser from "./utilities/getValidUser.js"; +import { InferenceClassificationOverride } from "@microsoft/microsoft-graph-types"; + +describe("Mail: Mailbox", function () { + const testName = "PnP Test Override"; + const testEmail = "!@contoso.onmicrosoft.com"; + let testUserName = ""; + + const override: InferenceClassificationOverride = { + classifyAs: "focused", + senderEmailAddress: { + name: testName, + address: testEmail, + }, + }; + + // Ensure we have the data to test against + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + const userInfo = await getValidUser.call(this); + testUserName = userInfo.userPrincipalName; + }); + + // Clean up testing folders + after(async function () { + if (!stringIsNullOrEmpty(testUserName)) { + // TBD + } + return; + }); + + it("Mailbox: Settings", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings(); + return expect(settings).is.not.null; + }); + + it("Mailbox: AutomaticRepliesSetting", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.automaticRepliesSetting(); + return expect(settings).is.not.null; + }); + + it("Mailbox: dateFormat setting", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.dateFormat(); + return expect(settings).is.not.null; + }); + + // DOCUMENTED BUT NOT IMPLEMENTED + it.skip("Mailbox: delegateMeetingMessageDeliveryOptions setting", async function () { + // const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.delegateMeetingMessageDeliveryOptions(); + // return expect(settings).is.not.null; + }); + + it("Mailbox: language setting", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.language(); + return expect(settings).is.not.null; + }); + + it("Mailbox: timeFormat setting", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.timeFormat(); + return expect(settings).is.not.null; + }); + + it("Mailbox: timeZone setting", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.timeZone(); + return expect(settings).is.not.null; + }); + + it("Mailbox: workingHours setting", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.workingHours(); + return expect(settings).is.not.null; + }); + + it("Mailbox: userPurpose setting", async function () { + const settings = await this.pnp.graph.users.getById(testUserName).mailboxSettings.userPurpose(); + return expect(settings).is.not.null; + }); + + it("Mailbox: Focused Inbox Overrides", async function () { + const fio = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides(); + return expect(fio).is.not.null; + }); + + it("Mailbox: Get Focused Inbox Override", async function () { + const f: InferenceClassificationOverride = JSON.parse(JSON.stringify(override)); + f.senderEmailAddress.name = `${testName} ${getRandomString(8)}`; + f.senderEmailAddress.address = testEmail.replace("!",getRandomString(8)); + const fio = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.add(f); + let success = false; + if (fio !== null) { + const getFIO = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.getById(fio.id)(); + if(getFIO !== null) { + success = (getFIO.senderEmailAddress.name === f.senderEmailAddress.name); + await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.getById(fio.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mailbox: Add Focused Inbox Override", async function () { + const f: InferenceClassificationOverride = JSON.parse(JSON.stringify(override)); + f.senderEmailAddress.name = `${testName} ${getRandomString(8)}`; + f.senderEmailAddress.address = testEmail.replace("!",getRandomString(8)); + const fio = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.add(f); + const success = (fio !== null); + if (success) { + await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.getById(fio.id).delete(); + } + return expect(success).to.be.true; + }); + + it("Mailbox: Update Focused Inbox Override", async function () { + const f: InferenceClassificationOverride = JSON.parse(JSON.stringify(override)); + f.senderEmailAddress.name = `${testName} ${getRandomString(8)}`; + f.senderEmailAddress.address = testEmail.replace("!",getRandomString(8)); + const fio = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.add(f); + const newName = `${testName} ${getRandomString(8)}`; + let success = false; + if (fio !== null) { + const update = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.getById(fio.id) + .update({ senderEmailAddress: { name: newName }}); + if (update !== null) { + success = (update.senderEmailAddress.name === newName); + await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.getById(update.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mailbox: Delete Focused Inbox Override", async function () { + const f: InferenceClassificationOverride = JSON.parse(JSON.stringify(override)); + f.senderEmailAddress.name = `${testName} ${getRandomString(8)}`; + f.senderEmailAddress.address = testEmail.replace("!",getRandomString(8)); + const fio = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.add(f); + let success = false; + if (fio !== null) { + await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.getById(fio.id).delete(); + try { + const found = await this.pnp.graph.users.getById(testUserName).focusedInboxOverrides.getById(fio.id)(); + if (found?.id === null) { + success = true; + } + } catch (e) { + success = true; + } + } + return expect(success).to.be.true; + }); +}); + diff --git a/test/graph/mail-messages.ts b/test/graph/mail-messages.ts new file mode 100644 index 000000000..47b9fe36f --- /dev/null +++ b/test/graph/mail-messages.ts @@ -0,0 +1,232 @@ +import { expect } from "chai"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import getValidUser from "./utilities/getValidUser.js"; +import { Message, MailFolder as IMailFolderType } from "@microsoft/microsoft-graph-types"; + +describe("Mail: Messages", function () { + let testUserName = ""; + let inboxFolder = null; + let draftFolder = null; + + const draftMessage: Message = { + subject: "PnPjs Test Message", + importance: "low", + body: { + contentType: "html", + content: "This is a test message!", + }, + toRecipients: [ + { + emailAddress: { + address: "AdeleV@contoso.onmicrosoft.com", + }, + }, + ], + }; + + // Ensure we have the data to test against + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + const userInfo = await getValidUser.call(this); + testUserName = userInfo.userPrincipalName; + draftMessage.toRecipients[0].emailAddress.address = testUserName; + const mailFolders: IMailFolderType[] = await this.pnp.graph.users.getById(testUserName).mailFolders(); + if (mailFolders.length >= 0) { + const inbox = mailFolders.find((f) => f.displayName === "Inbox"); + inboxFolder = inbox?.id || mailFolders[0].id; + const draft = mailFolders.find((f) => f.displayName === "Draft"); + draftFolder = draft?.id || mailFolders[0].id; + } + + if (inboxFolder === null || draftFolder === null) { + this.skip(); + } + }); + + // Clean up testing categories + after(async function () { + if (!stringIsNullOrEmpty(testUserName)) { + // TBD + } + return; + }); + + it("Mail: Message List", async function () { + const messages = await this.pnp.graph.users.getById(testUserName).messages(); + return expect(messages).is.not.null; + }); + + it("Mail: Message List (Delta)", async function () { + const messagesDelta = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(inboxFolder).messages.delta(); + return expect(messagesDelta).has.property("deltaLink"); + }); + + it("Mail: Create Draft Message", async function () { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + const draft = await this.pnp.graph.users.getById(testUserName).messages.add(m); + const success = (draft !== null); + if (success) { + await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).delete(); + } + return expect(success).to.be.true; + }); + + it("Mail: Update Message", async function () { + const m = JSON.parse(JSON.stringify(draftMessage)); + const newSubject = `PnPjs Test Message ${getRandomString(8)}`; + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + const draft = await this.pnp.graph.users.getById(testUserName).messages.add(m); + let success = false; + if (draft !== null) { + const update = await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).update({ subject: newSubject }); + if (update !== null) { + success = (update.subject === newSubject); + await this.pnp.graph.users.getById(testUserName).messages.getById(update.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Delete Message", async function () { + const m = JSON.parse(JSON.stringify(draftMessage)); + const draft = await this.pnp.graph.users.getById(testUserName).messages.add(m); + let success = false; + if (draft !== null) { + await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).delete(); + try { + const found = await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id)(); + if (found?.id === null) { + success = true; + } + } catch (e) { + success = true; + } + } + return expect(success).to.be.true; + }); + + it("Mail: Copy Message", async function () { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + const draft = await this.pnp.graph.users.getById(testUserName).messages.add(m); + let success = false; + if (draft !== null) { + const messageCopy = await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).copy(inboxFolder); + if (messageCopy !== null) { + success = true; + await this.pnp.graph.users.getById(testUserName).messages.getById(messageCopy.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Move Message", async function () { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + const draft: Message = await this.pnp.graph.users.getById(testUserName).messages.add(m); + let success = false; + if (draft !== null) { + const messageMove = await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).move(inboxFolder); + if (messageMove !== null) { + success = (messageMove.subject === draft.subject); + await this.pnp.graph.users.getById(testUserName).messages.getById(messageMove.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Send Draft Message", async function () { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + const draft = await this.pnp.graph.users.getById(testUserName).messages.add(m); + if (draft !== null) { + await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).send(); + return true; + } else { + return false; + } + }); + + it("Mail: Send Message", async function () { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + let success = false; + try{ + await this.pnp.graph.users.getById(testUserName).sendMail(m); + success = true; + }catch(err){ + // do nothing + } + return success; + }); + + it("Mail: Create Draft Reply Message", async function () { + const inboxMessage = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(inboxFolder).messages.top(1)(); + if (inboxMessage.length === 1) { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + let success = false; + const draft = await this.pnp.graph.users.getById(testUserName).messages.getById(inboxMessage[0].id).createReply(m); + if (draft !== null) { + success = true; + await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).delete(); + } + return success; + } else { + return false; + } + }); + + it.skip("Mail: Send Reply Message", async function () { + // Skipping because it would possibly send an email to someone who didn't expect it + }); + + it("Mail: Create Draft Reply-All Message", async function () { + const inboxMessage = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(inboxFolder).messages.top(1)(); + if (inboxMessage.length === 1) { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + let success = false; + const draft = await this.pnp.graph.users.getById(testUserName).messages.getById(inboxMessage[0].id).createReplyAll(m); + if (draft !== null) { + success = true; + await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).delete(); + } + return success; + } else { + return false; + } + }); + + it.skip("Mail: Send Reply-All Message", async function () { + // Skipping because it would possibly send an email to someone who didn't expect it + }); + + it("Mail: Create Draft Forward Message", async function () { + const inboxMessage = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(inboxFolder).messages.top(1)(); + if (inboxMessage.length === 1) { + const m = JSON.parse(JSON.stringify(draftMessage)); + m.subject = `PnPjs Test Message ${getRandomString(8)}`; + let success = false; + const draft = await this.pnp.graph.users.getById(testUserName).messages.getById(inboxMessage[0].id).createForward(m); + if (draft !== null) { + success = true; + await this.pnp.graph.users.getById(testUserName).messages.getById(draft.id).delete(); + } + return success; + } else { + return false; + } + }); + + it.skip("Mail: Forward Message", async function () { + // Skipping because it would possibly send an email to someone who didn't expect it + }); +}); diff --git a/test/graph/mail-rules.ts b/test/graph/mail-rules.ts new file mode 100644 index 000000000..aa98a6003 --- /dev/null +++ b/test/graph/mail-rules.ts @@ -0,0 +1,112 @@ +import { expect } from "chai"; +import "@pnp/graph/users"; +import "@pnp/graph/mail"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import getValidUser from "./utilities/getValidUser.js"; +import { MessageRule as IMessageRuleType } from "@microsoft/microsoft-graph-types"; + +describe("Mail: Rules", function () { + let testUserName = ""; + + const draftRule: IMessageRuleType = { + displayName: "PnPjs Test Rule", + sequence: 2, + isEnabled: true, + conditions: { + senderContains: [ + "adele", + ], + }, + actions: { + forwardTo: [ + { + emailAddress: { + name: "Alex Wilbur", + address: "AlexW@contoso.onmicrosoft.com", + }, + }, + ], + stopProcessingRules: true, + }, + }; + + // Ensure we have the data to test against + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + const userInfo = await getValidUser.call(this); + testUserName = userInfo.userPrincipalName; + }); + + it("Mail: Rules List", async function () { + const rules = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules(); + return expect(rules).is.not.null; + }); + + it("Mail: Rule Get", async function () { + const r = JSON.parse(JSON.stringify(draftRule)); + r.displayName = `PnPjs Test Rule ${getRandomString(8)}`; + const rule = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.add(r); + let success = false; + if (rule !== null) { + const getRule = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.getById(rule.id)(); + if(getRule !== null) { + success = (getRule.displayName === r.displayName); + await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.getById(rule.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Rule Add", async function () { + const r = JSON.parse(JSON.stringify(draftRule)); + r.displayName = `PnPjs Test Rule ${getRandomString(8)}`; + const rule = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.add(r); + const success = (rule !== null); + if (success) { + await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.getById(rule.id).delete(); + } + return expect(success).to.be.true; + }); + + it("Mail: Rule Update", async function () { + const r = JSON.parse(JSON.stringify(draftRule)); + r.displayName = `PnPjs Test Rule ${getRandomString(8)}`; + const rule = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.add(r); + const newRuleName = `PnPjs Test Rule ${getRandomString(8)}`; + let success = false; + if (rule !== null) { + const update = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox") + .messageRules.getById(rule.id).update({ displayName: newRuleName }); + if (update !== null) { + success = (update.displayName === newRuleName); + await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.getById(rule.id).delete(); + } + } + return expect(success).to.be.true; + }); + + it("Mail: Rule Delete", async function () { + const r = JSON.parse(JSON.stringify(draftRule)); + r.displayName = `PnPjs Test Rule ${getRandomString(8)}`; + const rule = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.add(r); + let success = false; + if (rule !== null) { + await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.getById(rule.id).delete(); + try { + const found = await this.pnp.graph.users.getById(testUserName).mailFolders.getById("inbox").messageRules.getById(rule.id)(); + if (found?.id === null) { + success = true; + } + } catch (e) { + success = true; + } + } + return expect(success).to.be.true; + }); + +}); + From 239ddee2351272f2c6b2701acdfbc14232f054d2 Mon Sep 17 00:00:00 2001 From: Julie Turner Date: Thu, 21 Dec 2023 15:35:11 +0000 Subject: [PATCH 2/3] Updates for tests and merge conflicts --- package-lock.json | 367 +++++++++++++++++++--------------- package.json | 2 +- packages/graph/package.json | 2 +- packages/logging/index.js | 97 +++++++++ packages/logging/listeners.js | 101 ++++++++++ test/graph/mail-messages.ts | 10 +- 6 files changed, 406 insertions(+), 173 deletions(-) create mode 100644 packages/logging/index.js create mode 100644 packages/logging/listeners.js diff --git a/package-lock.json b/package-lock.json index 9e4a09b90..15a1f12d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@azure/identity": "3.3.0", "@azure/msal-node": "1.18.3", - "@microsoft/microsoft-graph-types": "2.38.0", + "@microsoft/microsoft-graph-types": "2.40.0", "@pnp/buildsystem": "^4.0.0-beta5", "@pnp/logging": "^3.21.0", "@types/chai": "4.3.6", @@ -655,50 +655,6 @@ "node": ">=4.0" } }, - "node_modules/@pnp/buildsystem/node_modules/globby": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", - "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^1.0.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@pnp/buildsystem/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@pnp/buildsystem/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@pnp/buildsystem/node_modules/webpack": { "version": "5.89.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", @@ -877,9 +833,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.44.9", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.9.tgz", - "integrity": "sha512-6yBxcvwnnYoYT1Uk2d+jvIfsuP4mb2EdIxFnrPABj5a/838qe5bGkNLFOiipX4ULQ7XVQvTxOh7jO+BTAiqsEw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg==", "dev": true, "dependencies": { "@types/estree": "*", @@ -1330,6 +1286,35 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/@typescript-eslint/utils": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz", @@ -1709,6 +1694,15 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -1830,12 +1824,6 @@ "node": ">= 0.10" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2253,15 +2241,6 @@ "node": ">=0.10.0" } }, - "node_modules/clone-deep/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2525,6 +2504,20 @@ "node": ">= 10" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -2650,6 +2643,15 @@ "node": ">=8" } }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -3567,32 +3569,47 @@ } }, "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", + "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "@sindresorhus/merge-streams": "^1.0.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/graceful-fs": { @@ -3631,6 +3648,18 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", @@ -3655,6 +3684,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -3700,6 +3741,36 @@ "wbuf": "^1.1.0" } }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/html-entities": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", @@ -3929,6 +4000,15 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/ipaddr.js": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", @@ -4323,6 +4403,15 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/launch-editor": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", @@ -4506,15 +4595,6 @@ "node": ">=0.10.0" } }, - "node_modules/make-iterator/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -4730,15 +4810,6 @@ "node": ">= 6" } }, - "node_modules/minimist-options/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/mocha": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", @@ -4779,15 +4850,6 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/mocha/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -5351,12 +5413,15 @@ "dev": true }, "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/pathval": { @@ -5658,26 +5723,19 @@ } }, "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6084,6 +6142,21 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -6102,15 +6175,6 @@ "node": ">=8" } }, - "node_modules/shallow-clone/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6265,20 +6329,6 @@ "wbuf": "^1.7.3" } }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -6305,20 +6355,14 @@ "dev": true }, "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/string-replace-loader": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-replace-loader/-/string-replace-loader-3.1.0.tgz", @@ -6854,15 +6898,6 @@ "node": ">=14" } }, - "node_modules/webpack-cli/node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/webpack-dev-middleware": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", diff --git a/package.json b/package.json index 06209e047..c59875581 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "devDependencies": { "@azure/identity": "3.3.0", "@azure/msal-node": "1.18.3", - "@microsoft/microsoft-graph-types": "2.38.0", + "@microsoft/microsoft-graph-types": "2.40.0", "@pnp/buildsystem": "^4.0.0-beta5", "@pnp/logging": "^3.21.0", "@types/chai": "4.3.6", diff --git a/packages/graph/package.json b/packages/graph/package.json index 7c9730e62..e7f0fc6b2 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -8,7 +8,7 @@ "postinstall": "node ./post-install.cjs" }, "dependencies": { - "@microsoft/microsoft-graph-types": "2.38.0", + "@microsoft/microsoft-graph-types": "2.40.0", "tslib": "2.6.2", "@pnp/core": "0.0.0-PLACEHOLDER", "@pnp/queryable": "0.0.0-PLACEHOLDER" diff --git a/packages/logging/index.js b/packages/logging/index.js new file mode 100644 index 000000000..84c854091 --- /dev/null +++ b/packages/logging/index.js @@ -0,0 +1,97 @@ +export * from "./listeners.js"; +/** + * A set of logging levels + */ +export var LogLevel; +(function (LogLevel) { + LogLevel[LogLevel["Verbose"] = 0] = "Verbose"; + LogLevel[LogLevel["Info"] = 1] = "Info"; + LogLevel[LogLevel["Warning"] = 2] = "Warning"; + LogLevel[LogLevel["Error"] = 3] = "Error"; + LogLevel[LogLevel["Off"] = 99] = "Off"; +})(LogLevel || (LogLevel = {})); +const _subscribers = []; +let _activeLogLevel = 2 /* Warning */; +/** + * Class used to subscribe ILogListener and log messages throughout an application + * + */ +export class Logger { + /** + * Gets or sets the active log level to apply for log filtering + */ + static get activeLogLevel() { + return _activeLogLevel; + } + static set activeLogLevel(value) { + _activeLogLevel = value; + } + /** + * Adds ILogListener instances to the set of subscribed listeners + * + * @param listeners One or more listeners to subscribe to this log + */ + static subscribe(...listeners) { + _subscribers.push(...listeners); + } + /** + * Clears the subscribers collection, returning the collection before modification + */ + static clearSubscribers() { + const s = _subscribers.slice(0); + _subscribers.length = 0; + return s; + } + /** + * Gets the current subscriber count + */ + static get count() { + return _subscribers.length; + } + /** + * Writes the supplied string to the subscribed listeners + * + * @param message The message to write + * @param level [Optional] if supplied will be used as the level of the entry (Default: LogLevel.Info) + */ + static write(message, level = 1 /* Info */) { + Logger.log({ level: level, message: message }); + } + /** + * Writes the supplied string to the subscribed listeners + * + * @param json The json object to stringify and write + * @param level [Optional] if supplied will be used as the level of the entry (Default: LogLevel.Info) + */ + static writeJSON(json, level = 1 /* Info */) { + Logger.write(JSON.stringify(json), level); + } + /** + * Logs the supplied entry to the subscribed listeners + * + * @param entry The message to log + */ + static log(entry) { + if (entry !== undefined && Logger.activeLogLevel <= entry.level) { + _subscribers.map(subscriber => subscriber.log(entry)); + } + } + /** + * Logs an error object to the subscribed listeners + * + * @param err The error object + */ + static error(err) { + Logger.log({ data: err, level: 3 /* Error */, message: err.message }); + } +} +export function PnPLogging(activeLevel) { + return (instance) => { + instance.on.log(function (message, level) { + if (activeLevel <= level) { + _subscribers.map(subscriber => subscriber.log({ level, message })); + } + }); + return instance; + }; +} diff --git a/packages/logging/listeners.js b/packages/logging/listeners.js new file mode 100644 index 000000000..fdc636b47 --- /dev/null +++ b/packages/logging/listeners.js @@ -0,0 +1,101 @@ +export function ConsoleListener(prefix, colors) { + return new _ConsoleListener(prefix, colors); +} +function withColor(msg, color, logMethod) { + if (typeof color === "undefined") { + logMethod(msg); + } + else { + logMethod(`%c${msg}`, `color:${color}`); + } +} +/** + * Formats the message + * + * @param entry The information to format into a string + */ +function entryToString(entry, prefix) { + const msg = []; + if (prefix.length > 0) { + msg.push(`${prefix} -`); + } + msg.push(entry.message); + if (entry.data !== undefined) { + try { + msg.push("Data: " + JSON.stringify(entry.data)); + } + catch (e) { + msg.push(`Data: Error in stringify of supplied data ${e}`); + } + } + return msg.join(" "); +} +// index order matters, this is a lookup table based on the corresponding LogLevel value +const colorProps = ["verbose", "info", "warning", "error"]; +/** + * Implementation of LogListener which logs to the console + * + */ +class _ConsoleListener { + /** + * Makes a new one + * + * @param prefix Optional text to include at the start of all messages (useful for filtering) + * @param colors Optional text color settings + */ + constructor(_prefix = "", _colors = {}) { + this._prefix = _prefix; + this._colors = _colors; + } + /** + * Any associated data that a given logging listener may choose to log or ignore + * + * @param entry The information to be logged + */ + log(entry) { + let logMethod = console.log; + switch (entry.level) { + case 3 /* Error */: + logMethod = console.error; + break; + case 2 /* Warning */: + logMethod = console.warn; + break; + case 0 /* Verbose */: + logMethod = console.debug; + break; + case 1 /* Info */: + logMethod = console.info; + break; + default: + logMethod = console.log; + } + withColor(entryToString(entry, this._prefix), this._colors[colorProps[entry.level]], logMethod); + } +} +export function FunctionListener(impl) { + return new _FunctionListener(impl); +} +/** + * Implementation of LogListener which logs to the supplied function + * + */ +class _FunctionListener { + /** + * Creates a new instance of the FunctionListener class + * + * @constructor + * @param method The method to which any logging data will be passed + */ + constructor(method) { + this.method = method; + } + /** + * Any associated data that a given logging listener may choose to log or ignore + * + * @param entry The information to be logged + */ + log(entry) { + this.method(entry); + } +} diff --git a/test/graph/mail-messages.ts b/test/graph/mail-messages.ts index 47b9fe36f..8ffd8fd8d 100644 --- a/test/graph/mail-messages.ts +++ b/test/graph/mail-messages.ts @@ -154,7 +154,7 @@ describe("Mail: Messages", function () { } }); - it("Mail: Send Message", async function () { + it.only("Mail: Send Message", async function () { const m = JSON.parse(JSON.stringify(draftMessage)); m.subject = `PnPjs Test Message ${getRandomString(8)}`; let success = false; @@ -167,7 +167,7 @@ describe("Mail: Messages", function () { return success; }); - it("Mail: Create Draft Reply Message", async function () { + it.only("Mail: Create Draft Reply Message", async function () { const inboxMessage = await this.pnp.graph.users.getById(testUserName).mailFolders.getById(inboxFolder).messages.top(1)(); if (inboxMessage.length === 1) { const m = JSON.parse(JSON.stringify(draftMessage)); @@ -180,7 +180,7 @@ describe("Mail: Messages", function () { } return success; } else { - return false; + this.skip(); } }); @@ -201,7 +201,7 @@ describe("Mail: Messages", function () { } return success; } else { - return false; + this.skip(); } }); @@ -222,7 +222,7 @@ describe("Mail: Messages", function () { } return success; } else { - return false; + this.skip(); } }); From 788de5227fbfb938ac4ad6dee02a6999e5d44c46 Mon Sep 17 00:00:00 2001 From: Julie Turner Date: Fri, 22 Dec 2023 17:19:25 +0000 Subject: [PATCH 3/3] Clarify format for getByLoginName --- CHANGELOG.md | 1 + docs/sp/site-users.md | 2 +- packages/sp/site-users/types.ts | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 559f2627b..52b1e9ac4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - All GraphQueryable*, _GraphQueryable*, and IGraphQueryable* have been renamed to remove "Queryable" (ex: GraphQueryableCollection is now GraphCollection) - @pnp/graph/onedrive renamed to @pnp/graph/files - ISites.getByUrl is now async + - @pnp/graph/outlook is not in @pnp/graph/mail, included all mail endpoints - mailCategory.add() returns Microsoft Graph types OutlookCategory vs object with data property. - sp diff --git a/docs/sp/site-users.md b/docs/sp/site-users.md index 9403417f9..ae7b2c63a 100644 --- a/docs/sp/site-users.md +++ b/docs/sp/site-users.md @@ -93,7 +93,7 @@ const users = await sp.web.siteUsers; await users.add(user.data.LoginName); ``` -### Get user +### Get user by Id, Email, or LoginName ```TypeScript import { spfi } from "@pnp/sp"; diff --git a/packages/sp/site-users/types.ts b/packages/sp/site-users/types.ts index a30e3f451..283b313f7 100644 --- a/packages/sp/site-users/types.ts +++ b/packages/sp/site-users/types.ts @@ -37,6 +37,7 @@ export class _SiteUsers extends _SPCollection { * Gets a user from the collection by login name * * @param loginName The login name of the user to retrieve + * e.g. SharePoint Online: 'i:0#.f|membership|user@domain' */ public getByLoginName(loginName: string): ISiteUser { return SiteUser(this).concat(`('!@v::${loginName}')`);