diff --git a/.vscode/launch.json b/.vscode/launch.json index dcbf59852..9b917958b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -37,7 +37,7 @@ "args": [ "--verbose", "--logging", - "Error", + "verbose", "--record", "write" ], diff --git a/debug/launch/graph.ts b/debug/launch/graph.ts index f2646a551..ee86b8863 100644 --- a/debug/launch/graph.ts +++ b/debug/launch/graph.ts @@ -1,6 +1,9 @@ import { Logger, LogLevel } from "@pnp/logging"; import { graphSetup } from "./setup.js"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; import "@pnp/graph/users"; +import "@pnp/graph/files"; +import { IDriveItemAdd, IDriveItemAddFolder, IFileUploadOptions, IItemOptions, IBundleDef } from "@pnp/graph/files"; declare var process: { exit(code?: number): void }; @@ -8,10 +11,42 @@ export async function Example(settings: any) { const graph = graphSetup(settings); - const users = await graph.users(); + const fileOptions: IFileUploadOptions = { + content: "This is some test content", + filePathName: "pnpTest.txt", + contentType: "text/plain;charset=utf-8", + }; + + const testUserName = settings.testing.testUser.substring(settings.testing.testUser.lastIndexOf("|") + 1); + const drives = await graph.users.getById(testUserName).drives(); + let driveId = ""; + if (drives.length > 0) { + driveId = drives[0].id; + } + + // Create sample files + let folderId = ""; + let child1Id = ""; + let child2Id = ""; + const testFolderName = `TestFolder_${getRandomString(4)}`; + const driveItemAdd: IDriveItemAddFolder = { + name: testFolderName, + }; + const folder = await graph.users.getById(testUserName).drives.getById(driveId).root.children.addFolder(driveItemAdd); + if (folder != null) { + folderId = folder.id; + const testFileName = `TestFile_${getRandomString(4)}.json`; + const fo = JSON.parse(JSON.stringify(fileOptions)); + fo.filePathName = testFileName; + const child1 = await graph.users.getById(testUserName).drives.getById(driveId).getItemById(folderId).upload(fo); + child1Id = child1.id; + fo.filePathName = `TestFile_${getRandomString(4)}.json`; + const child2 = await graph.users.getById(testUserName).drives.getById(driveId).getItemById(folderId).upload(fo); + child2Id = child2.id; + } Logger.log({ - data: users, + data: folder, level: LogLevel.Info, message: "List of Users Data", }); diff --git a/docs/graph/files.md b/docs/graph/files.md index 9e4ce0a63..7448f8436 100644 --- a/docs/graph/files.md +++ b/docs/graph/files.md @@ -129,7 +129,7 @@ const shared = await graph.me.drives.getById({drive id}).sharedWithMe(options); ``` -## Get the following drive item +## Get the drive item being followed List the items that have been followed by the signed in user. @@ -208,9 +208,9 @@ const rootChildren = await graph.users.getById({user id}).drives.getById({drive const rootChildren = await graph.me.drives.getById({drive id}).root.children(); -const itemChildren = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").children(); +const itemChildren = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").children(); -const itemChildren = await graph.me.drives.getById({drive id}).root.items.getById("{item id}").children(); +const itemChildren = await graph.me.drives.getById({drive id}).root.getItemById("{item id}").children(); ``` @@ -368,9 +368,9 @@ import "@pnp/graph/files"; const graph = graphfi(...); -const item = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}")(); +const item = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}")(); -const item = await graph.me.drives.getById({drive id}).items.getById("{item id}")(); +const item = await graph.me.drives.getById({drive id}).getItemById("{item id}")(); ``` @@ -462,9 +462,9 @@ import "@pnp/graph/files"; const graph = graphfi(...); -const thumbs = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").thumbnails(); +const thumbs = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").thumbnails(); -const thumbs = await graph.me.drives.getById({drive id}).items.getById("{item id}").thumbnails(); +const thumbs = await graph.me.drives.getById({drive id}).getItemById("{item id}").thumbnails(); ``` @@ -479,10 +479,10 @@ import "@pnp/graph/files"; const graph = graphfi(...); -await graph.me.drives.getById({drive id}).items.getById({item id}).delete(); -await graph.me.drives.getById({drive id}).items.getById({item id}).permanentDelete(); -await graph.users.getById({user id}).drives.getById({drive id}).items.getById({item id}).delete(); -await graph.users.getById({user id}).drives.getById({drive id}).items.getById({item id}).permanentDelete(); +await graph.me.drives.getById({drive id}).getItemById({item id}).delete(); +await graph.me.drives.getById({drive id}).getItemById({item id}).permanentDelete(); +await graph.users.getById({user id}).drives.getById({drive id}).getItemById({item id}).delete(); +await graph.users.getById({user id}).drives.getById({drive id}).getItemById({item id}).permanentDelete(); ``` ## Update drive item metadata @@ -496,9 +496,9 @@ import "@pnp/graph/files"; const graph = graphfi(...); -const update = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").update({name: "New Name"}); +const update = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").update({name: "New Name"}); -const update = await graph.me.drives.getById({drive id}).items.getById("{item id}").update({name: "New Name"}); +const update = await graph.me.drives.getById({drive id}).getItemById("{item id}").update({name: "New Name"}); ``` @@ -522,9 +522,9 @@ const moveOptions: IItemOptions = { name?: {newName}; }; -const move = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").move(moveOptions); +const move = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").move(moveOptions); -const move = await graph.me.drives.getById({drive id}).items.getById("{item id}").move(moveOptions); +const move = await graph.me.drives.getById({drive id}).getItemById("{item id}").move(moveOptions); ``` @@ -548,9 +548,9 @@ const copyOptions: IItemOptions = { name?: {newName}; }; -const copy = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").copy(copyOptions); +const copy = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").copy(copyOptions); -const copy = await graph.me.drives.getById({drive id}).items.getById("{item id}").copy(copyOptions); +const copy = await graph.me.drives.getById({drive id}).getItemById("{item id}").copy(copyOptions); ``` @@ -590,16 +590,16 @@ import { ItemPreviewInfo } from "@microsoft/microsoft-graph-types" const graph = graphfi(...); -const preview: ItemPreviewInfo = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").preview(); +const preview: ItemPreviewInfo = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").preview(); -const preview: ItemPreviewInfo = await graph.me.drives.getById({drive id}).items.getById("{item id}").preview(); +const preview: ItemPreviewInfo = await graph.me.drives.getById({drive id}).getItemById("{item id}").preview(); const previewOptions: IPreviewOptions = { page: 1, zoom: 90 } -const preview2: ItemPreviewInfo = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").preview(previewOptions); +const preview2: ItemPreviewInfo = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").preview(previewOptions); ``` @@ -640,16 +640,57 @@ import { IAnalyticsOptions } from "@pnp/graph/files"; const graph = graphfi(...); // Defaults to lastSevenDays -const analytics = await graph.users.getById({user id}).drives.getById({drive id}).items.getById("{item id}").analytics()(); +const analytics = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").analytics()(); -const analytics = await graph.me.drives.getById({drive id}).items.getById("{item id}").analytics()(); +const analytics = await graph.me.drives.getById({drive id}).getItemById("{item id}").analytics()(); const analyticOptions: IAnalyticsOptions = { timeRange: "allTime" }; -const analyticsAllTime = await graph.me.drives.getById({drive id}).items.getById("{item id}").analytics(analyticOptions)(); +const analyticsAllTime = await graph.me.drives.getById({drive id}).getItemById("{item id}").analytics(analyticOptions)(); ``` For more information on: [Sensitivity and Retention Labels (Premium Endpoint)](./files-labels.md) + +## Permissions + +### List/Get/Add/Update/Delete Drive Item Permissions + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/files"; +import "@pnp/graph/permissions/drive-item"; +import {IPermissionsInviteInfo} from "@pnp/graph/permissions/drive-item"; + +const graph = graphfi(...); + +const newPermissions: IPermissionsInviteInfo = { + recipients: [{email: "user@contoso.com"}], + requireSignIn: true, + sendInvitation: true, + roles: ["read"] +}; + +// List permissions +const permissions = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").permissions(); + +// Add permissions +const permissions = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").addPermissions(newPermissions); + +// Get permissions +const itemPermissions = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").permissions.getById(permissions.id)(); + +// Update permissions +const updatedPermissions = await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").permissions.getById(permissions.id).update({roles: ["write"]}); + +// Delete permissions +await graph.users.getById({user id}).drives.getById({drive id}).getItemById("{item id}").permissions.getById(permissions.id).delete(); + +``` + +## Sharing + +[Shares](./shares.md) diff --git a/docs/graph/permissions.md b/docs/graph/permissions.md index ade06dc57..f3a7543e6 100644 --- a/docs/graph/permissions.md +++ b/docs/graph/permissions.md @@ -46,8 +46,10 @@ const graph = graphfi(...); const permissions = await graph.sites.getById("{site id}").permissions.add({ roles: ["fullcontrol"], grantedToIdentities: [{ - id: "89ea5c94-7736-4e25-95ad-3fa95f62b66e", - displayName: "Contoso Time Manager App", + application: { + id: "89ea5c94-7736-4e25-95ad-3fa95f62b66e", + displayName: "Contoso Time Manager App", + } }], }); ``` diff --git a/docs/graph/shares.md b/docs/graph/shares.md index 40f7703b8..30ceafdc2 100644 --- a/docs/graph/shares.md +++ b/docs/graph/shares.md @@ -46,3 +46,74 @@ const graph = graphfi(...); const driveItemInfo = await graph.shares.getById("{shareId}").driveItem(); ``` + +## Convert sharing URL to a sharing token + +To use a sharing URL with this API, your app needs to transform the URL into a sharing token. + +```TS +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/shares"; +import {IShareLinkInfo} from "@pnp/graph/shares"; + +const graph = graphfi(...); + +// Use ShareId +const shareLinkInfo: IShareLinkInfo = { + shareId: shareId, + redeemSharingLink: false, +}; +const sharedDriveItem = await graph.shares.useSharingLink(shareLinkInfo); + +// Use Encoded Sharing Link +const shareLink: string = graph.shares.encodeSharingLink("https://{tenant}.sharepoint.com/sites/dev/Shared%20Documents/new.pptx"); +const shareLinkInfo = { + encodedSharingUrl: shareLink, + redeemSharingLink: false +}; +const sharedDriveItem = await graph.shares.useSharingLink(shareLinkInfo); +``` + +## Create Sharing Link + +You can use createLink action to share a DriveItem via a sharing link. + +The createLink action will create a new sharing link if the specified link type doesn't already exist for the calling application. If a sharing link of the specified type already exists for the app, the existing sharing link will be returned. + +```TS +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/shares"; +import "@pnp/graph/users"; +import "@pnp/graph/files"; + +const graph = graphfi(...); + +const sharingLinkInfo: ICreateShareLinkInfo = { + type: "view", + scope: "anonymous", +}; +const sharingLink = await graph.users.getById({userId}).drives.getById({driveId}).getItemById({itemId}).createSharingLink(sharingLinkInfo); + +``` + +## Grant Sharing Link Access + +Grant users access to a link represented by a permission. + +```TS +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/shares"; + +const graph = graphfi(...); + +const shareLink: string = graph.shares.encodeSharingLink("https://{tenant}.sharepoint.com/sites/dev/Shared%20Documents/new.pptx"); +const sharingLinkAccess = { + encodedSharingUrl: shareLink, + recipients: [{email: "user@contoso.com"}], + roles: ["read"] +}; + +// +const permissions = await graph.shares.grantSharingLinkAccess(sharingLinkAccess); + +``` diff --git a/package-lock.json b/package-lock.json index 76e50ea57..2dd746037 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@types/core-js": "2.5.8", "@types/findup-sync": "4.0.4", "@types/mocha": "10.0.6", - "@types/node": "16.11.7", + "@types/node": "18.11.9", "@types/webpack": "5.28.5", "@types/yargs": "17.0.32", "@typescript-eslint/eslint-plugin": "5.62.0", @@ -68,65 +68,65 @@ } }, "node_modules/@azure/core-auth": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.6.0.tgz", - "integrity": "sha512-3X9wzaaGgRaBCwhLQZDtFp5uLIXCPrGbwJNWPPugvL4xbIGgScv77YzzxToKGLAKvG9amDoofMoP+9hsH1vs1w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.0.tgz", + "integrity": "sha512-OuDVn9z2LjyYbpu6e7crEwSipa62jX7/ObV/pmXQfnOG8cHwm363jYtg3FSX3GB1V7jsIKri1zgq7mfXkFk/qw==", "dev": true, "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", - "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.0.tgz", + "integrity": "sha512-SYtcG13aiV7znycu6plCClWUzD9BBtfnsbIxT89nkkRvQRB4n0kuZyJJvJ7hqdKOn7x7YoGKZ9lVStLJpLnOFw==", "dev": true, "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-client": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.8.0.tgz", - "integrity": "sha512-+gHS3gEzPlhyQBMoqVPOTeNH031R5DM/xpCvz72y38C09rg4Hui/1sJS/ujoisDZbbSHyuRLVWdFlwL0pIFwbg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.0.tgz", + "integrity": "sha512-x50SSD7bbG5wen3tMDI2oWVSAjt1K1xw6JZSnc6239RmBwqLJF9dPsKsh9w0Rzh5+mGpsu9FDu3DlsT0lo1+Uw==", "dev": true, "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-rest-pipeline": "^1.9.1", "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", + "@azure/core-util": "^1.6.1", "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", - "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.0.tgz", + "integrity": "sha512-SYtcG13aiV7znycu6plCClWUzD9BBtfnsbIxT89nkkRvQRB4n0kuZyJJvJ7hqdKOn7x7YoGKZ9lVStLJpLnOFw==", "dev": true, "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.14.0.tgz", - "integrity": "sha512-Tp4M6NsjCmn9L5p7HsW98eSOS7A0ibl3e5ntZglozT0XuD/0y6i36iW829ZbBq0qihlGgfaeFpkLjZ418KDm1Q==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.15.0.tgz", + "integrity": "sha512-6kBQwE75ZVlOjBbp0/PX0fgNLHxoMDxHe3aIPV/RLVwrIDidxTbsHtkSbPNTkheMset3v9s1Z08XuMNpWRK/7w==", "dev": true, "dependencies": { "@azure/abort-controller": "^2.0.0", @@ -134,58 +134,58 @@ "@azure/core-tracing": "^1.0.1", "@azure/core-util": "^1.3.0", "@azure/logger": "^1.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", - "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.0.tgz", + "integrity": "sha512-SYtcG13aiV7znycu6plCClWUzD9BBtfnsbIxT89nkkRvQRB4n0kuZyJJvJ7hqdKOn7x7YoGKZ9lVStLJpLnOFw==", "dev": true, "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.0.tgz", + "integrity": "sha512-MVeJvGHB4jmF7PeHhyr72vYJsBJ3ff1piHikMgRaabPAC4P3rxhf9fm42I+DixLysBunskJWhsDQD2A+O+plkQ==", "dev": true, "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-util": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.7.0.tgz", - "integrity": "sha512-Zq2i3QO6k9DA8vnm29mYM4G8IE9u1mhF1GUabVEqPNX8Lj833gdxQ2NAFxt2BZsfAL+e9cT8SyVN7dFVJ/Hf0g==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.8.0.tgz", + "integrity": "sha512-w8NrGnrlGDF7fj36PBnJhGXDK2Y3kpTOgL7Ksb5snEHXq/3EAbKYOp1yqme0yWCUlSDq5rjqvxSBAJmsqYac3w==", "dev": true, "dependencies": { "@azure/abort-controller": "^2.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", - "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.0.tgz", + "integrity": "sha512-SYtcG13aiV7znycu6plCClWUzD9BBtfnsbIxT89nkkRvQRB4n0kuZyJJvJ7hqdKOn7x7YoGKZ9lVStLJpLnOFw==", "dev": true, "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" @@ -240,15 +240,15 @@ } }, "node_modules/@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.0.tgz", + "integrity": "sha512-BnfkfzVEsrgbVCtqq0RYRMePSH2lL/cgUUR5sYRF4yNN10zJZq/cODz0r89k3ykY83MqeM3twR292a3YBNgC3w==", "dev": true, "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/msal-browser": { @@ -573,14 +573,14 @@ "dev": true }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", - "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -596,22 +596,22 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { @@ -621,9 +621,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", - "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -701,9 +701,9 @@ } }, "node_modules/@pnp/core": { - "version": "4.0.0-alpha0-v4nightly.20240226", - "resolved": "https://registry.npmjs.org/@pnp/core/-/core-4.0.0-alpha0-v4nightly.20240226.tgz", - "integrity": "sha512-C668f3AsirPvv6KNhoOyR40VRiCyqCy0HtaMJ2NwX/6/1T7Tw2M6PeV9rS63oz4Tc8tI7EK6TF93flgVmiTAdA==", + "version": "4.0.0-alpha0-v4nightly.20240318", + "resolved": "https://registry.npmjs.org/@pnp/core/-/core-4.0.0-alpha0-v4nightly.20240318.tgz", + "integrity": "sha512-pUmvt7vjEO5Pqo7c05WPMA+IflKEGuX16aLLWErEG55ivDmtf8NKayl+j4GHbPv+xHnPK621B6mvKzHjU6BV8A==", "dev": true, "dependencies": { "tslib": "2.4.1" @@ -723,9 +723,9 @@ "dev": true }, "node_modules/@pnp/logging": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-3.23.0.tgz", - "integrity": "sha512-QuWUiBgf7csR2/zgfk3Y4EkBBIimfJhdr+8AotfargBBvDzwiOEk0Fb7mwH6saaGeMZJFh9ks0BlLpRSek8/Dg==", + "version": "3.24.0", + "resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-3.24.0.tgz", + "integrity": "sha512-Fw9ej0WIkKxFmG2mQx6BD2TJBOPbmQHbx3y5dASFongg8mZSg/X/pbvxKwMi4CWhfVkSCgt1vw1eH6tEHuT8Bg==", "dev": true, "dependencies": { "tslib": "2.4.1" @@ -756,15 +756,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -831,9 +822,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.56.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.3.tgz", - "integrity": "sha512-PvSf1wfv2wJpVIFUMSb+i4PvqNYkB9Rkp9ZDO3oaWzq4SKhsQk4mrMBr3ZH06I0hKrVGLBacmgl8JM4WVjb9dg==", + "version": "8.56.5", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.5.tgz", + "integrity": "sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -938,9 +929,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.11.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", - "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", + "version": "18.11.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", + "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", "dev": true }, "node_modules/@types/node-forge": { @@ -959,9 +950,9 @@ "dev": true }, "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "version": "6.9.12", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.12.tgz", + "integrity": "sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==", "dev": true }, "node_modules/@types/range-parser": { @@ -1280,9 +1271,9 @@ "dev": true }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", @@ -1302,9 +1293,9 @@ "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { @@ -1325,15 +1316,15 @@ "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { @@ -1361,28 +1352,28 @@ "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/leb128": "1.11.6", @@ -1390,24 +1381,24 @@ } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", @@ -1416,12 +1407,12 @@ } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -1525,15 +1516,15 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "dev": true, "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/aggregate-error": { @@ -1753,22 +1744,25 @@ } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -1776,7 +1770,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -1971,9 +1965,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001589", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", - "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", + "version": "1.0.30001599", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz", + "integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==", "dev": true, "funding": [ { @@ -2049,10 +2043,16 @@ } }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2065,9 +2065,6 @@ "engines": { "node": ">= 8.10.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -2614,9 +2611,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.681", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.681.tgz", - "integrity": "sha512-1PpuqJUFWoXZ1E54m8bsLPVYwIVCRzvaL+n5cjigGga4z854abDnFRc+cTa2th4S79kyGqya/1xoR7h+Y5G5lg==", + "version": "1.4.708", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.708.tgz", + "integrity": "sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA==", "dev": true }, "node_modules/emoji-regex": { @@ -2644,9 +2641,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -2982,14 +2979,14 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -3286,9 +3283,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -3652,9 +3649,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { "function-bind": "^1.1.2" @@ -3739,9 +3736,9 @@ } }, "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", "dev": true, "funding": [ { @@ -3797,17 +3794,16 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/http-proxy-middleware": { @@ -3847,16 +3843,16 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "dev": true, "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -4826,33 +4822,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/mocha/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -4864,18 +4833,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/mocha/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", @@ -5633,9 +5590,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -6136,17 +6093,17 @@ } }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6201,12 +6158,12 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -6465,9 +6422,9 @@ } }, "node_modules/terser": { - "version": "5.28.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz", - "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==", + "version": "5.29.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", + "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -6769,9 +6726,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", diff --git a/package.json b/package.json index b6e017621..6afa371fe 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@types/core-js": "2.5.8", "@types/findup-sync": "4.0.4", "@types/mocha": "10.0.6", - "@types/node": "16.11.7", + "@types/node": "18.11.9", "@types/webpack": "5.28.5", "@types/yargs": "17.0.32", "@typescript-eslint/eslint-plugin": "5.62.0", diff --git a/packages/graph/files/bundles.ts b/packages/graph/files/bundles.ts new file mode 100644 index 000000000..ab7ad5f23 --- /dev/null +++ b/packages/graph/files/bundles.ts @@ -0,0 +1,72 @@ +import { + _GraphInstance, + _GraphCollection, + graphInvokableFactory, + GraphQueryable, + graphPost, + graphDelete, +} from "../graphqueryable.js"; +import { + Bundle as IBundleType, + DriveItem as IDriveItemType, +} from "@microsoft/microsoft-graph-types"; +import { defaultPath, getById, IGetById, deleteable, IDeleteable, updateable, IUpdateable } from "../decorators.js"; +import { body } from "@pnp/queryable"; + + +/** + * Describes a Bundle instance + * ONLY SUPPORTED IN PERSONAL ONEDRIVE + */ +@deleteable() +@updateable() +export class _Bundle extends _GraphInstance { + + /** + * Method for adding a drive item to a bundle. + * @param id - The Id of a DriveItem object to add to the bundle + * @returns void - 204 if successful + */ + public async addItem(id: string): Promise { + return graphPost(this, body({ id })); + } + + /** + * Method for removing a drive item from a bundle. + * @param id - The Id of a DriveItem object to remove from the bundle + * @returns void - 204 if successful + */ + public async removeItem(id: string): Promise { + return graphDelete(GraphQueryable(this,`/children/${id}`)); + } +} + +export interface IBundle extends _Bundle, IDeleteable, IUpdateable { } +export const Bundle = graphInvokableFactory(_Bundle); + +/** + * Describes a collection of Bundle objects + * ONLY SUPPORTED IN PERSONAL ONEDRIVE + */ +@defaultPath("bundles") +@getById(Bundle) +export class _Bundles extends _GraphCollection { + + /** + * Method for creating a new bundle. + * @param bundleDef - IBundleDef object + * @returns Microsoft Graph - DriveItem + */ + public async create(bundleDef: IBundleDef): Promise { + return graphPost(this, body(bundleDef)); + } +} +export interface IBundles extends _Bundles, IGetById { } +export const Bundles = graphInvokableFactory(_Bundles); + +export interface IBundleDef { + name: string; + "@microsoft.graph.conflictBehavior": "rename"; + bundle: IBundleType; + children: {id: string}[]; +} diff --git a/packages/graph/files/index.ts b/packages/graph/files/index.ts index 0fd2f4a8d..028c3579a 100644 --- a/packages/graph/files/index.ts +++ b/packages/graph/files/index.ts @@ -19,6 +19,14 @@ export { IResumableUploadOptions, } from "./resumableUpload.js"; +export { + Bundle, + IBundle, + Bundles, + IBundles, + IBundleDef, +} from "./bundles.js"; + export { Drive, DriveItem, @@ -52,3 +60,4 @@ Reflect.defineProperty(GraphFI.prototype, "drives", { return this.create(Drives); }, }); + diff --git a/packages/graph/files/types.ts b/packages/graph/files/types.ts index d65f79aeb..9c06d1d01 100644 --- a/packages/graph/files/types.ts +++ b/packages/graph/files/types.ts @@ -438,6 +438,7 @@ export class _DriveItems extends _GraphCollection { export interface IDriveItems extends _DriveItems, IGetById { } export const DriveItems = graphInvokableFactory(_DriveItems); + /** * IDriveItemAdd - for adding a drive item and the corresponding contents * @param filename - string - file name. diff --git a/packages/graph/files/users.ts b/packages/graph/files/users.ts index 1f7d71fb4..fbc6febc7 100644 --- a/packages/graph/files/users.ts +++ b/packages/graph/files/users.ts @@ -16,16 +16,13 @@ declare module "../users/types" { addProp(_User, "drive", Drive); addProp(_User, "drives", Drives); -addProp(_Drive, "bundles", DriveItems); addProp(_Drive, "following", DriveItems); declare module "./types" { interface _Drive { - bundles: IDriveItems; special(specialFolder: SpecialFolder): IDriveItem; } interface IDrive { - bundles: IDriveItems; special(specialFolder: SpecialFolder): IDriveItem; } interface _DriveItem { diff --git a/packages/graph/permissions/drive-item.ts b/packages/graph/permissions/drive-item.ts new file mode 100644 index 000000000..2123fa66a --- /dev/null +++ b/packages/graph/permissions/drive-item.ts @@ -0,0 +1,52 @@ +import { addProp, body } from "@pnp/queryable"; +import { graphPost } from "../graphqueryable.js"; +import { _DriveItem, DriveItem } from "../files/types.js"; +import { IPermissions, Permissions } from "./types.js"; +import { Permission as IPermissionType, DriveRecipient as IDriveRecipientType } from "@microsoft/microsoft-graph-types"; + +declare module "../files/types" { + interface _DriveItem { + readonly permissions: IPermissions; + addPermissions(permissionsInviteInfo: IPermissionsInviteInfo): Promise; + } + interface IDriveItem { + readonly permissions: IPermissions; + addPermissions(permissionsInviteInfo: IPermissionsInviteInfo): Promise; + } +} + +addProp(_DriveItem, "permissions", Permissions); + +/** + * Method for adding permissions to the drive item. + * @param permissionsInviteInfo: IPermissionsInviteInfo + * @returns Microsoft Graph - Permission[] + */ +_DriveItem.prototype.addPermissions = async function addPermissions(permissionsInviteInfo: IPermissionsInviteInfo): Promise { + return graphPost(DriveItem(this, "invite"), body(permissionsInviteInfo)); +}; + +/* +* IPermissionsInviteInfo - for adding permissions to a drive item +* @param recipients - IDriveRecipientType[] - A collection of recipients who will receive access and the sharing invitation. +* @param message - string - A plain text formatted message that is included in the sharing invitation. Maximum length 2000 characters. +* @param requireSignIn - boolean - Specifies whether the recipient of the invitation is required to sign-in to view the shared item. +* @param sendInvitation - boolean - If true, a sharing link is sent to the recipient. Otherwise, a permission is granted directly without sending a notification. +* @param roles - "read" | "write" | "owner"[] - Specifies the roles that are to be granted to the recipients of the sharing invitation. +* @param expirationDateTime - string - (Optional) A String with format of yyyy-MM-ddTHH:mm:ssZ of DateTime indicates the expiration time of the permission. +* For OneDrive for Business and SharePoint, expirationDateTime is only applicable for sharingLink permissions. Available on OneDrive for Business, SharePoint, +* and premium personal OneDrive accounts. +* @param password - string (Optional) - The password set on the invite by the creator. Optional and OneDrive Personal only. +* @param retainInheritedPermissions - boolean (Optional) - If true (default), any existing inherited permissions are retained on the shared item when sharing +* this item for the first time. If false, all existing permissions are removed when sharing for the first time. +} +*/ +export interface IPermissionsInviteInfo { + recipients: IDriveRecipientType[]; + requireSignIn: boolean; + sendInvitation: boolean; + roles: ["read" | "write" | "owner"]; + expirationDateTime?: string; + password?: string; + retainInheritedPermissions?: boolean; +} diff --git a/packages/graph/permissions/index.ts b/packages/graph/permissions/index.ts index 44f0a05ee..6b0b80bf2 100644 --- a/packages/graph/permissions/index.ts +++ b/packages/graph/permissions/index.ts @@ -1,4 +1,5 @@ import "./site.js"; +import "./drive-item.js"; export { IPermission, @@ -6,3 +7,7 @@ export { Permission, Permissions, } from "./types.js"; + +export { + IPermissionsInviteInfo, +} from "./drive-item.js"; diff --git a/packages/graph/permissions/site.ts b/packages/graph/permissions/site.ts index a293c6e24..7e11d3c28 100644 --- a/packages/graph/permissions/site.ts +++ b/packages/graph/permissions/site.ts @@ -1,14 +1,32 @@ -import { addProp } from "@pnp/queryable"; +import { addProp, body } from "@pnp/queryable"; +import { graphPost } from "../graphqueryable.js"; +import { Permission as IPermissionType } from "@microsoft/microsoft-graph-types"; import { _Site } from "../sites/types.js"; -import { IPermissions, Permissions } from "./types.js"; +import { IPermissions, Permissions, _Permissions } from "./types.js"; declare module "../sites/types" { interface _Site { readonly permissions: IPermissions; + add(permissions: Pick): Promise; } interface ISite { readonly permissions: IPermissions; + add(permissions: Pick): Promise; } } addProp(_Site, "permissions", Permissions); + +declare module "./types" { + interface _Permissions { + add(permissions: Pick): Promise; + } + interface IPermissions { + add(permissions: Pick): Promise; + } +} + +_Permissions.prototype.add = async function addPermissions(permissions: Pick): Promise { + return graphPost(this, body(permissions)); +}; + diff --git a/packages/graph/permissions/types.ts b/packages/graph/permissions/types.ts index ca5cddb95..cd04d5b92 100644 --- a/packages/graph/permissions/types.ts +++ b/packages/graph/permissions/types.ts @@ -1,6 +1,6 @@ -import { body } from "@pnp/queryable"; + import { IDeleteable, IGetById, IUpdateable, defaultPath, deleteable, getById, updateable } from "../decorators.js"; -import { graphInvokableFactory, _GraphCollection, _GraphInstance, graphPost } from "../graphqueryable.js"; +import { graphInvokableFactory, _GraphCollection, _GraphInstance } from "../graphqueryable.js"; import { Permission as IPermissionType } from "@microsoft/microsoft-graph-types"; /** @@ -17,12 +17,6 @@ export const Permission = graphInvokableFactory(_Permission); */ @defaultPath("permissions") @getById(Permission) -export class _Permissions extends _GraphCollection { - - public add(permissions: Pick): Promise { - - return graphPost(this, body(permissions)); - } -} +export class _Permissions extends _GraphCollection {} export interface IPermissions extends _Permissions, IGetById { } export const Permissions = graphInvokableFactory(_Permissions); diff --git a/packages/graph/shares/drive-item.ts b/packages/graph/shares/drive-item.ts new file mode 100644 index 000000000..84358a116 --- /dev/null +++ b/packages/graph/shares/drive-item.ts @@ -0,0 +1,39 @@ +import { body } from "@pnp/queryable"; +import { graphPost } from "../graphqueryable.js"; +import { _DriveItem, DriveItem } from "../files/types.js"; +import { SharingLink as ISharingLinkType } from "@microsoft/microsoft-graph-types"; + +declare module "../files/types" { + interface _DriveItem { + createSharingLink(sharingLinkInfo: ICreateShareLinkInfo): Promise; + } + interface IDriveItem { + createSharingLink(sharingLinkInfo: ICreateShareLinkInfo): Promise; + } +} + +/** + * Method for creating a sharing link for the drive item. + * @param sharingLinkInfo - ISharingLinkInfo + * @returns Microsoft Graph - SharingLink + */ +_DriveItem.prototype.createSharingLink = async function createSharingLink(sharingLinkInfo: ICreateShareLinkInfo): Promise { + return graphPost(DriveItem(this, "createLink"), body(sharingLinkInfo)); +}; + +/** + * ISharingLinkInfo - for creating a sharing link + * @param type - "view" | "edit" | "embed" - The type of sharing link to create. + * @param scope - "anonymous" | "organization" | "users" - The scope of link to create. + * @param expirationDateTime - string - (Optional) A String with format of yyyy-MM-ddTHH:mm:ssZ of DateTime indicates the expiration time of the permission. + * @param password - string (Optional) - password for the link + * @param retainInheritedPermissions - boolean (Optional) - If true (default), any existing inherited permissions are retained on the shared + * item when sharing this item for the first time. If false, all existing permissions are removed when sharing for the first time. + */ +export interface ICreateShareLinkInfo { + type: "view" | "edit" | "embed"; + scope: "anonymous" | "organization" | "users"; + expirationDateTime?: string; + password?: string; + retainInheritedPermissions?: boolean; +} diff --git a/packages/graph/shares/index.ts b/packages/graph/shares/index.ts index 32dd826a6..b3529a5b7 100644 --- a/packages/graph/shares/index.ts +++ b/packages/graph/shares/index.ts @@ -1,13 +1,20 @@ import { GraphFI } from "../fi.js"; import { Shares, IShares } from "./types.js"; +import "./drive-item.js"; export { IShare, IShares, Share, Shares, + IShareLinkInfo, + IShareLinkAccessInfo, } from "./types.js"; +export { + ICreateShareLinkInfo, +} from "./drive-item.js"; + declare module "../fi" { interface GraphFI { readonly shares: IShares; diff --git a/packages/graph/shares/types.ts b/packages/graph/shares/types.ts index 10083be78..a2e2aa590 100644 --- a/packages/graph/shares/types.ts +++ b/packages/graph/shares/types.ts @@ -1,23 +1,36 @@ -import { defaultPath } from "../decorators.js"; -import { graphInvokableFactory, _GraphCollection, _GraphInstance } from "../graphqueryable.js"; -import { SharedDriveItem as ISharedDriveItem } from "@microsoft/microsoft-graph-types"; +import { defaultPath, getById, IGetById } from "../decorators.js"; +import { body, InjectHeaders } from "@pnp/queryable"; +import { combine } from "@pnp/core"; +import { graphInvokableFactory, _GraphCollection, _GraphInstance, graphPost, graphGet } from "../graphqueryable.js"; import { DriveItem, IDriveItem } from "../files/types.js"; +import { + Permission as IPermissionType, + SharedDriveItem as ISharedDriveItemType, + DriveRecipient as IDriveRecipientType, +} from "@microsoft/microsoft-graph-types"; /** - * Shares + * Describes a Share object */ -@defaultPath("shares") -export class _Shares extends _GraphCollection { +export class _Share extends _GraphInstance { /** - * Gets a share by share id or encoded url - * @param id The share id - * @returns An IShare instance + * Access the driveItem associated with this shared file */ - public getById(id: string): IShare { - return Share(this, id); + public get driveItem(): IDriveItem { + return DriveItem(this, "driveitem"); } +} +export interface IShare extends _Share { } +export const Share = graphInvokableFactory(_Share); +/** + * Describes a collection of Share objects + * + */ +@defaultPath("shares") +@getById(Share) +export class _Shares extends _GraphCollection { /** * Creates a sharing link (id) from a given absolute url to a file * @param url Absolute file url such as "https://{tenant}.sharepoint.com/sites/dev/Shared%20Documents/new.pptx" @@ -26,22 +39,51 @@ export class _Shares extends _GraphCollection { public encodeSharingLink(url: string): string { return (`u!${Buffer.from(url).toString("base64").replace(/=$/, "").replace("/", "_").replace("+", "-")}`); } + + /** + * Method for using a sharing link. + * @param share: string - Share Id or Encoded Sharing Url + * @returns Microsoft Graph - SharingLink + */ + public async useSharingLink(shareLink: IShareLinkInfo): Promise { + const q = Shares(this, shareLink.shareId || shareLink.encodedSharingUrl); + if (shareLink.redeemSharingLink) { + q.using(InjectHeaders({ + "Prefer": (shareLink.redeemSharingLink) ? "redeemSharingLink" : "redeemSharingLinkIfNecessary", + })); + } + return graphGet(q); + } + + public async grantSharingLinkAccess(shareLinkAccess: IShareLinkAccessInfo): Promise { + const q = Shares(this, combine(shareLinkAccess.encodedSharingUrl, "permission", "grant")); + return graphPost(q, body(shareLinkAccess)); + } } -export interface IShares extends _Shares { } +export interface IShares extends _Shares, IGetById { } export const Shares = graphInvokableFactory(_Shares); + /** - * Share + * IShareLinkInfo - for using a sharing link - either ShareId or EncodedSharingUrl must be included. + * @param shareId: string - Optional - Share Id + * @param encodedSharingUrl: string - Optional - Encoded Sharing Url + * @param redeemSharingLink: boolean - Optional - True to Redeem the sharing link; False to redeem the sharing link if necessary */ -export class _Share extends _GraphInstance { - - /** - * Access the driveItem associated with this shared file - */ - public get driveItem(): IDriveItem { - return DriveItem(this, "driveitem"); - } +export interface IShareLinkInfo { + shareId?: string; + encodedSharingUrl?: string; + redeemSharingLink?: boolean; } -export interface IShare extends _Share { } -export const Share = graphInvokableFactory(_Share); +/** + * IShareLinkAccessInfo - update Sharing permissions. + * @param encodedSharingUrl: string - Encoded Sharing Url + * @param recipients: IDriveRecipientType[] - Array of recipients + * @param roles: ["read" | "write" | "owner"] - Array of roles + */ +export interface IShareLinkAccessInfo { + encodedSharingUrl: string; + recipients: IDriveRecipientType[]; + roles: ["read" | "write" | "owner"]; +} diff --git a/test/graph/files.ts b/test/graph/files.ts index 692607ae7..9e3a40c79 100644 --- a/test/graph/files.ts +++ b/test/graph/files.ts @@ -4,9 +4,8 @@ import * as fs from "fs"; import findupSync from "findup-sync"; import "@pnp/graph/users"; import "@pnp/graph/files"; -import "@pnp/graph/files/sites"; import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; -import { IDriveItemAdd, IDriveItemAddFolder, IFileUploadOptions, IItemOptions } from "@pnp/graph/files/types"; +import { IDriveItemAdd, IDriveItemAddFolder, IFileUploadOptions, IItemOptions } from "@pnp/graph/files"; // give ourselves a single reference to the projectRoot const projectRoot = path.resolve(path.dirname(findupSync("package.json"))); @@ -66,6 +65,7 @@ describe("Drive", function () { }); + // TODO: Failing with Timeout it("Get Recent Drive Items", async function () { if (stringIsNullOrEmpty(driveId)) { this.skip(); @@ -200,7 +200,7 @@ describe("Drive", function () { } let driveItems; const testFolderName = `TestFolder_${getRandomString(4)}`; - const folder = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.children.addFolder({name: testFolderName}); + const folder = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.children.addFolder({ name: testFolderName }); if (folder != null) { const testFileName = `${getRandomString(4)}.txt`; const children = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(folder.id) @@ -326,11 +326,11 @@ describe("Drive", function () { } const testFileName = `${getRandomString(4)}.txt`; const testFileName2 = `${getRandomString(4)}.txt`; - const children = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.children.add({filename: testFileName, content: "My File Content String"}); + const children = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.children.add({ filename: testFileName, content: "My File Content String" }); let driveItemUpdate; if (children != null) { const testFolderName = `TestFolder_${getRandomString(4)}`; - const folder = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.children.addFolder({name: testFolderName}); + const folder = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.children.addFolder({ name: testFolderName }); if (folder != null) { const moveOptions: IItemOptions = { parentReference: { driveId: folder.parentReference.driveId, id: folder.id }, @@ -349,6 +349,7 @@ describe("Drive", function () { return expect(driveItemUpdate.name).to.eq(testFileName2); }); + // TODO: Failing timeout it("Convert Drive Item", async function () { if (stringIsNullOrEmpty(driveId)) { this.skip(); @@ -419,10 +420,10 @@ describe("Drive", function () { if (children != null) { // Set up test file await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(children.id).follow(); - try{ + try { await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(children.id).unfollow(); unfollowDriveItem = true; - }catch(err){ + } catch (err) { unfollowDriveItem = false; } // Clean up test file @@ -430,4 +431,35 @@ describe("Drive", function () { } return expect(unfollowDriveItem).to.be.true; }); + + // it("Create Sharing Link", async function () { + // if (stringIsNullOrEmpty(driveId)) { + // this.skip(); + // } + // const testFileName = `TestFile_${getRandomString(4)}.json`; + // const fo = JSON.parse(JSON.stringify(fileOptions)); + // fo.filePathName = testFileName; + // const driveItemAdd: IDriveItemAdd = { + // filename: testFileName, + // content: fileOptions.content, + // contentType: fileOptions.contentType, + // }; + // const children = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.children.add(driveItemAdd); + // let sharingLink = null; + // if (children != null) { + // // Create Sharing Link + // const sharingLinkInfo: ISharingLinkInfo = { + // type: "view", + // scope: "anonymous", + // }; + // sharingLink = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(children.id).createSharingLink(sharingLinkInfo); + // // Clean up test file + // await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(children.id).delete(); + // } + // return expect(sharingLink).to.haveOwnProperty("id"); + // }); + + /* Testing for Bundles is not possible as it is only supported in Personal OneDrive */ + // describe.skip("Bundles", function () {}); }); + diff --git a/test/graph/list-items.ts b/test/graph/list-items.ts index 5b5aaaeb5..562e0042f 100644 --- a/test/graph/list-items.ts +++ b/test/graph/list-items.ts @@ -84,6 +84,7 @@ describe("List-Items", function () { await itemDelete.delete(); let passed = false; try{ + // eslint-disable-next-line @typescript-eslint/no-unused-vars const r = await list.items.getById(itemDeleteId)(); }catch(err){ passed = true; diff --git a/test/graph/permissions.ts b/test/graph/permissions.ts new file mode 100644 index 000000000..33c925edf --- /dev/null +++ b/test/graph/permissions.ts @@ -0,0 +1,131 @@ +import { expect } from "chai"; +import "@pnp/graph/users"; +import "@pnp/graph/files"; +import "@pnp/graph/permissions/drive-item"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import { IFileUploadOptions } from "@pnp/graph/files"; +import { IPermissionsInviteInfo } from "@pnp/graph/permissions/drive-item"; + +describe("Permissions", function () { + let testUserName = ""; + let driveId = null; + let fileId = null; + let fileId2 = null; + let permissionsId = null; + + const newPermissions: IPermissionsInviteInfo = { + recipients: [{email: testUserName}], + requireSignIn: true, + sendInvitation: true, + roles: ["read"], + }; + + // Ensure we have the data to test against + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + // Get a sample user + try { + testUserName = this.pnp.settings.testUser.substring(this.pnp.settings.testUser.lastIndexOf("|") + 1); + newPermissions.recipients[0].email = testUserName; + const drives = await this.pnp.graph.users.getById(testUserName).drives(); + if (drives.length > 0) { + driveId = drives[0].id; + + // upload a file + const fileOptions: IFileUploadOptions = { + content: "This is some test content", + filePathName: `TestFile_${getRandomString(4)}.json`, + contentType: "text/plain;charset=utf-8", + }; + const children = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.upload(fileOptions); + if (children != null) { + fileId = children.id; + const perms = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).permissions(); + if(perms != null && perms.length > 0){ + permissionsId = perms[0].id; + } + } + } + } catch (err) { + console.log("Could not retrieve user's drives"); + } + }); + + after(async function () { + if (fileId) { + await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).delete(); + } + if(fileId2){ + await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId2).delete(); + } + }); + + describe("DriveItem", function () { + it("List Permissions", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + + const permissions = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).permissions(); + expect(permissions).to.be.instanceOf(Array); + }); + + it("Add Permissions", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + + const permissions = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).addPermissions(newPermissions); + expect(permissions).to.be.instanceOf(Array); + }); + + it("Get Permissions", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + + const permissions = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).permissions.getById(permissionsId)(); + expect(permissions).to.haveOwnProperty("id"); + }); + + it("Update Permissions", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + + const permissionUpdate = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId) + .permissions.getById(permissionsId).update({roles: ["write"]}); + expect(permissionUpdate).to.haveOwnProperty("id"); + }); + + it("Delete Permissions", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + const fileOptions: IFileUploadOptions = { + content: "This is some test content", + filePathName: `TestFile_${getRandomString(4)}.json`, + contentType: "text/plain;charset=utf-8", + }; + const newFile = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.upload(fileOptions); + let success = false; + if(newFile != null){ + fileId2 = newFile.id; + const permissions = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).addPermissions(newPermissions); + if(permissions != null){ + try{ + await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).permissions.getById(permissions[0].id).delete(); + success = true; + }catch(err){ + // ignore + } + } + } + expect(success).to.equal(true); + }); + }); +}); diff --git a/test/graph/shares.ts b/test/graph/shares.ts index 78a2482fc..1e077374f 100644 --- a/test/graph/shares.ts +++ b/test/graph/shares.ts @@ -1,5 +1,11 @@ import { expect } from "chai"; import "@pnp/graph/shares"; +import "@pnp/graph/users"; +import "@pnp/graph/files"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import { IFileUploadOptions } from "@pnp/graph/files"; +import { ICreateShareLinkInfo, IShareLinkAccessInfo } from "@pnp/graph/shares"; +import { DriveItem } from "@microsoft/microsoft-graph-types"; describe("Shares", function () { @@ -23,4 +29,90 @@ describe("Shares", function () { return expect(link).to.eq("u!aHR0cHM6Ly9zb21ldGhpbmcuc2hhcmVwb2ludC5jb20vc2l0ZXMvc2l0ZS9zaGFyZWQlMjBkb2N1bWVudHMvc29tZXRoaW5nLmRvY3g"); }); + + describe("Drive Item", function () { + let testUserName = ""; + let driveId = null; + let fileId = null; + + // Ensure we have the data to test against + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + // Get a sample user + try { + testUserName = this.pnp.settings.testUser.substring(this.pnp.settings.testUser.lastIndexOf("|") + 1); + const drives = await this.pnp.graph.users.getById(testUserName).drives(); + if (drives.length > 0) { + driveId = drives[0].id; + + // upload a file + const fileOptions: IFileUploadOptions = { + content: "This is some test content", + filePathName: `TestFile_${getRandomString(4)}.json`, + contentType: "text/plain;charset=utf-8", + }; + const children = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).root.upload(fileOptions); + if (children != null) { + fileId = children.id; + } + } + } catch (err) { + console.log("Could not retrieve user's drives"); + } + }); + + after(async function () { + if (fileId) { + await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).delete(); + } + }); + + it("Create Sharing Link", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + + const sharingLinkInfo: ICreateShareLinkInfo = { + type: "view", + scope: "anonymous", + }; + const sharingLink = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId).createSharingLink(sharingLinkInfo); + expect(sharingLink).to.haveOwnProperty("id"); + }); + + it("Grant Sharing Link Access", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + + const driveItem: DriveItem = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId)(); + const shareLink: string = this.pnp.graph.shares.encodeSharingLink(driveItem.webUrl); + const sharingLinkAccess: IShareLinkAccessInfo = { + encodedSharingUrl: shareLink, + recipients: [{email: testUserName}], + roles: ["read"], + }; + const permissions = await this.pnp.graph.shares.grantSharingLinkAccess(sharingLinkAccess); + expect(permissions).to.be.instanceOf(Array); + }); + + it("Use Sharing Link", async function () { + if (stringIsNullOrEmpty(fileId)) { + this.skip(); + } + + const driveItem: DriveItem = await this.pnp.graph.users.getById(testUserName).drives.getById(driveId).getItemById(fileId)(); + const shareLink: string = this.pnp.graph.shares.encodeSharingLink(driveItem.webUrl); + const shareLinkInfo = { + encodedSharingUrl: shareLink, + redeemSharingLink: false, + }; + const sharedDriveItem = await this.pnp.graph.shares.useSharingLink(shareLinkInfo); + expect(sharedDriveItem).to.haveOwnProperty("id"); + }); + }); }); diff --git a/test/sp/files.ts b/test/sp/files.ts index 7df1b9247..6ad66cb97 100644 --- a/test/sp/files.ts +++ b/test/sp/files.ts @@ -95,7 +95,7 @@ describe("Files", function () { const name = `Testing Chunked - ${getRandomString(4)}.jpg`; const content = readFileSync(resolve(projectRoot, "./test/sp/assets/sample_file.jpg")); - const far = await files.addChunked(name, content, null, true, 1000000); + const far = await files.addChunked(name, content, null); // eslint-disable-next-line @typescript-eslint/no-unused-expressions expect(far).to.not.be.null; return expect(far.file()).to.eventually.be.fulfilled; diff --git a/test/sp/sites.ts b/test/sp/sites.ts index 555e79161..672eed56c 100644 --- a/test/sp/sites.ts +++ b/test/sp/sites.ts @@ -86,7 +86,7 @@ describe("Sites", function () { const files: IFiles = this.pnp.sp.web.defaultDocumentLibrary.rootFolder.files; const name = `Testing Chunked - ${getRandomString(4)}.jpg`; const content = readFileSync(resolve(projectRoot, "./test/sp/assets/sample_file.jpg")); - const far = await files.addChunked(name, content, null, true, 1000000); + const far = await files.addChunked(name, content, null); const path = far.data.ServerRelativeUrl; const logoProperties: ISiteLogoProperties = {relativeLogoUrl: path, aspect: SiteLogoAspect.Square, type: SiteLogoType.WebLogo}; await this.pnp.sp.site.setSiteLogo(logoProperties);