From 6a6dc22cd1e2e1ded2276df3f019a833ce584dcb Mon Sep 17 00:00:00 2001 From: meenahoda Date: Wed, 19 Jun 2024 09:24:58 +0100 Subject: [PATCH 1/3] feat: Sharepoint package moveTo implementation [sc-25936] --- lib/index.js | 36 ++++++++++++++++++++++++++++++++++++ test/test.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/lib/index.js b/lib/index.js index deb7bdf..dcb7463 100644 --- a/lib/index.js +++ b/lib/index.js @@ -435,6 +435,42 @@ class Sharepoint { logAxiosError(this.debug, err, 'Unable to delete file') } } + + /** + * Moves the specified file + * @param options An object that must contain a 'fileName' (the name of the file), 'sourcePath' (the path to a folder in + * which the file is to be moved from) and 'targetPath' (the path to a folder which the file is to be moved to) properties. + * @returns {Promise} + */ + async moveFile (options) { + if (!options.fileName) { + throw new Error('You must provide a file name.') + } + + checkHeaders(this.accessToken) + + const sourcePath = encodeURIComponent(options.sourcePath) + const targetPath = encodeURIComponent(options.targetPath) + const fileName = encodeURIComponent(options.fileName) + + const formDigestValue = await getFormDigestValue(this.siteUrl, this.accessToken) + + const url = `${this.siteUrl}/_api/web/GetFileByServerRelativeUrl('${this.encodedBaseUrl}${sourcePath}/${fileName}')/moveto(newurl='${this.encodedBaseUrl}${targetPath}/${fileName}',flags=1)` + + try { + await axios({ + method: 'post', + url, + headers: { + Authorization: `Bearer ${this.accessToken}`, + 'X-RequestDigest': formDigestValue + } + }) + } catch (err) { + console.log(err) + logAxiosError(this.debug, err, 'Unable to move file') + } + } } // based on https://axios-http.com/docs/handling_errors diff --git a/test/test.js b/test/test.js index 0c1c1a1..4fee605 100644 --- a/test/test.js +++ b/test/test.js @@ -384,6 +384,39 @@ describe('tests', function () { expect(contents.map(i => i.Name).includes(FOLDER_NAME3)).to.eql(false) expect(contents.map(i => i.Name).includes(FOLDER_NAME4)).to.eql(false) }) + + it('create and move a file', async () => { + const sourceFolderPath = `${process.env.SHAREPOINT_TESTS_DIR_PATH}/Source` + const targetFolderPath = `${process.env.SHAREPOINT_TESTS_DIR_PATH}/Target` + const fileName = 'the-file-to-move.txt' + const data = 'This file will be moved!' + + await sharepoint.createFolder(sourceFolderPath) + await sharepoint.createFolder(targetFolderPath) + await sharepoint.createFile({ path: sourceFolderPath, fileName, data }) + + // Check contents before + const sourceFolderContentsBefore = await sharepoint.getContents(sourceFolderPath) + expect(sourceFolderContentsBefore.length).to.eql(1) + expect(sourceFolderContentsBefore[0].Name).to.eql(fileName) + + const targetFolderContentsBefore = await sharepoint.getContents(targetFolderPath) + expect(targetFolderContentsBefore.length).to.eql(0) + + // Move file + await sharepoint.moveFile({ sourcePath: sourceFolderPath, targetPath: targetFolderPath, fileName }) + + // Check contents after + const sourceFolderContentsAfter = await sharepoint.getContents(sourceFolderPath) + expect(sourceFolderContentsAfter.length).to.eql(0) + + const targetFolderContentsAfter = await sharepoint.getContents(targetFolderPath) + expect(targetFolderContentsAfter.length).to.eql(1) + expect(targetFolderContentsAfter[0].Name).to.eql(fileName) + + await sharepoint.deleteFolder(sourceFolderPath) + await sharepoint.deleteFolder(targetFolderPath) + }) }) }) From 8e9c65fb71f631763cc1bea289267724bbba1ff8 Mon Sep 17 00:00:00 2001 From: meenahoda Date: Wed, 19 Jun 2024 10:09:56 +0100 Subject: [PATCH 2/3] function to move folder contents --- lib/index.js | 32 ++++++++++++++++++++++++++++++++ test/test.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/lib/index.js b/lib/index.js index dcb7463..568ed6f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -471,6 +471,38 @@ class Sharepoint { logAxiosError(this.debug, err, 'Unable to move file') } } + + /** + * Moves the specified file + * @param options An object that must contain a 'sourcePath' (the path to a folder in + * which the file is to be moved from) and 'targetPath' (the path to a folder which the file is to be moved to) properties. + * @returns {Promise} + */ + async moveFolder (options) { + checkHeaders(this.accessToken) + + const filesToMove = [] + + async function collectFilesToMove (self, sourcePath, targetPath) { + const contents = await self.getContents(sourcePath) + for (const item of contents) { + if (item.__metadata.type === 'SP.File') { + filesToMove.push({ sourcePath, targetPath, fileName: item.Name }) + } else if (item.__metadata.type === 'SP.Folder') { + await collectFilesToMove(self, `${sourcePath}/${item.Name}`, `${targetPath}/${item.Name}`) + } + } + } + + await collectFilesToMove(this, options.sourcePath, options.targetPath) + + for (const { sourcePath, targetPath, fileName } of filesToMove) { + await this.createFolder(targetPath) + await this.moveFile({ sourcePath, targetPath, fileName }) + } + + await this.deleteFolder(options.sourcePath) + } } // based on https://axios-http.com/docs/handling_errors diff --git a/test/test.js b/test/test.js index 4fee605..94f46f0 100644 --- a/test/test.js +++ b/test/test.js @@ -417,6 +417,39 @@ describe('tests', function () { await sharepoint.deleteFolder(sourceFolderPath) await sharepoint.deleteFolder(targetFolderPath) }) + + it('create and move a folder', async () => { + const sourceFolderPath = `${process.env.SHAREPOINT_TESTS_DIR_PATH}/Source` + const targetFolderPath = `${process.env.SHAREPOINT_TESTS_DIR_PATH}/Target` + + await sharepoint.createFolder(sourceFolderPath) + await sharepoint.createFolder(targetFolderPath) + await sharepoint.createFile({ path: sourceFolderPath, fileName: 'file-1.txt', data: 'File 1' }) + await sharepoint.createFile({ path: sourceFolderPath, fileName: 'file-2.txt', data: 'File 2' }) + await sharepoint.createFile({ path: sourceFolderPath, fileName: 'file-3.txt', data: 'File 3' }) + await sharepoint.createFolder(`${sourceFolderPath}/Nested Folder`) + await sharepoint.createFile({ path: `${sourceFolderPath}/Nested Folder`, fileName: 'file-4.txt', data: 'File 4' }) + await sharepoint.createFile({ path: `${sourceFolderPath}/Nested Folder`, fileName: 'file-5.txt', data: 'File 5' }) + + // Check contents before + const sourceFolderContentsBefore = await sharepoint.getContents(sourceFolderPath) + expect(sourceFolderContentsBefore.length).to.eql(4) + + const targetFolderContentsBefore = await sharepoint.getContents(targetFolderPath) + expect(targetFolderContentsBefore.length).to.eql(0) + + await sharepoint.moveFolder({ sourcePath: sourceFolderPath, targetPath: targetFolderPath }) + + // Check contents after + const sourceFolderContentsAfter = await sharepoint.getContents(sourceFolderPath) + expect(sourceFolderContentsAfter.length).to.eql(0) + + const targetFolderContentsAfter = await sharepoint.getContents(targetFolderPath) + expect(targetFolderContentsAfter.length).to.eql(4) + + await sharepoint.deleteFolder(sourceFolderPath) + await sharepoint.deleteFolder(targetFolderPath) + }) }) }) From 14aba624dce4a69de69dcce05c2c9282a7d8bb38 Mon Sep 17 00:00:00 2001 From: meenahoda Date: Wed, 19 Jun 2024 10:51:07 +0100 Subject: [PATCH 3/3] rename to move folder contents --- lib/index.js | 2 +- test/test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index 568ed6f..0333906 100644 --- a/lib/index.js +++ b/lib/index.js @@ -478,7 +478,7 @@ class Sharepoint { * which the file is to be moved from) and 'targetPath' (the path to a folder which the file is to be moved to) properties. * @returns {Promise} */ - async moveFolder (options) { + async moveFolderContents (options) { checkHeaders(this.accessToken) const filesToMove = [] diff --git a/test/test.js b/test/test.js index 94f46f0..985e9be 100644 --- a/test/test.js +++ b/test/test.js @@ -438,7 +438,7 @@ describe('tests', function () { const targetFolderContentsBefore = await sharepoint.getContents(targetFolderPath) expect(targetFolderContentsBefore.length).to.eql(0) - await sharepoint.moveFolder({ sourcePath: sourceFolderPath, targetPath: targetFolderPath }) + await sharepoint.moveFolderContents({ sourcePath: sourceFolderPath, targetPath: targetFolderPath }) // Check contents after const sourceFolderContentsAfter = await sharepoint.getContents(sourceFolderPath)