Skip to content

Instantly share code, notes, and snippets.

@sancarn
Created November 29, 2022 20:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sancarn/00ab6727a16c50e2bcd42b617f65a798 to your computer and use it in GitHub Desktop.
Save sancarn/00ab6727a16c50e2bcd42b617f65a798 to your computer and use it in GitHub Desktop.
Simple script to update sharepoint using the REST API
//Note: When porting `Authorization: "Bearer " + accessToken` will also be required in all headers!
/*
* Get all fields of a list
* @param {string} site - Url of site
* @param {string} list - Title of list
* @example await getListFields("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name")
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-lists-and-list-items-with-rest
*/
async function getListFields(site, list){
const f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')/Fields`, {method: "GET", headers:{Accept: "application/json;odata=verbose"}})
return (await f.json()).d
}
/*
* Get all fields of a list
* @param {string} site - Url of site
* @param {string} list - Title of list
* @example await getListFields("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name")
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-lists-and-list-items-with-rest
*/
async function getFieldNameFromDisplayName(site, list, displayName, fields=null){
if (fields==null) fields = await getListFields(site, list)
let field = fields.results.find(e=>e.Title == displayName)
if(field){
return field.StaticName
} else {
throw `Field '${displayName}' doesn't exist on list '${list}'.`
}
}
/*
* Get all list items
* @param {string} site - Url of site
* @param {string} list - Title of list
* @example getListItems("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name")
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-lists-and-list-items-with-rest
*/
async function getListItems(site, list){
var f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')/items`, {method: "GET", headers:{Accept: "application/json;odata=verbose"}});
var data = (await f.json()).d;
var results = data.results;
while(!!data.__next){
f = await fetch(data.__next, {method: "GET", headers:{Accept: "application/json;odata=verbose"}});
data = (await f.json()).d;
results = results.concat(data.results);
}
return results;
}
/*
* Get a list item by its ID
* @param {string} site - Url of site
* @param {string} list - Title of list
* @param {string} itemID - ID of item to retrieve
* @example getListItem("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name", 1)
*/
async function getListItem(site, list, itemID){
const f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')/items(${itemID})`, {method: "GET", headers:{Accept: "application/json;odata=verbose"}})
return (await f.json()).d
}
/*
* Obtain list item type, used in creation of items.
* @param {string} site - Url of site
* @param {string} list - Title of list
* @example getListItemType("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name")
*/
async function getListItemType(site,list){
const f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')?$select=ListItemEntityTypeFullName`, {method: "GET", headers:{Accept: "application/json;odata=verbose"}})
let data = await f.json()
return data.d.ListItemEntityTypeFullName
}
/*
* Obtain list item type, used in creation of items.
* @param {string} site - Url of site
* @remark Request digest will timeout after 1800 seconds, so you can use this for a batch of creations however unlikely between batches.
* @example getRequestDigest("https://myServer.sharepoint.com/sites/my/sharepoint/site")
*/
async function getRequestDigest(site){
const f = await fetch(`${site}/_api/contextinfo`, {method: "POST", headers:{Accept: "application/json;odata=verbose"}})
let data = await f.json()
return data.d.GetContextWebInformation.FormDigestValue
}
/*
* Create a new list item
* @param {string} site - Url of site
* @param {string} list - Title of list
* @param {object} data - List item data
* @param {string|null} itemType - Obtained from getListItemType(). If null then item type will be obtained directly.
* @param {string|null} digest - Digest token which usually timeout after 1800 seconds. If Null then digest is automatically retrieved.
* @example await createListItem("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name", {"Title":"STORM-10001-Network Water"})
*/
async function createListItem(site, list, data, itemType=null, digest=null){
if(digest == null) digest = await getRequestDigest(site)
if(itemType == null) itemType = await getListItemType(site,list)
data["__metadata"] = {type: itemType}
console.log(data)
const f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')/items`, {
method: "POST",
headers:{
"Accept": "application/json;odata=verbose",
"Content-Type":"application/json;odata=verbose",
"Content-Length": JSON.stringify(data).length,
"X-RequestDigest": digest
},
body: JSON.stringify(data)
})
return await f.json()
}
/*
* Update a list item
* @param {string} site - Url of site
* @param {string} list - Title of list
* @param {string} itemID - ID of item to update
* @param {object} data - List item data
* @param {string|null} itemType - Obtained from getListItemType(). If null then item type will be obtained directly.
* @param {string|null} digest - Digest token which usually timeout after 1800 seconds. If Null then digest is automatically retrieved.
* @example await updateListItem("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name", 1, {"County":"Staffordshire"})
*/
async function updateListItem(site, list, itemID, data, itemType=null, digest=null){
if(digest == null) digest = await getRequestDigest(site)
if(itemType == null) itemType = await getListItemType(site,list)
data["__metadata"] = {type: itemType}
console.log(data)
const f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')/items(${itemID})`, {
method: "POST",
headers:{
"Accept": "application/json;odata=verbose",
"Content-Type":"application/json;odata=verbose",
"Content-Length": JSON.stringify(data).length,
"If-Match":"*",
"X-HTTP-Method": "MERGE",
"X-RequestDigest": digest
},
body: JSON.stringify(data)
})
return f.status == 204
}
/*
* Delete a list item
* @param {string} site - Url of site
* @param {string} list - Title of list
* @param {int} itemID - ID of item to delete
* @param {string} digest - The digest to use
* @example await deleteListItem("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name", 8545)
*/
async function deleteListItem(site, list, itemID, digest=null){
if(digest == null) digest = await getRequestDigest(site)
const f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')/items(${itemID})`, {
method: "POST",
headers:{
"Accept": "application/json;odata=verbose",
"Content-Type":"application/json",
"If-Match": "*",
"X-HTTP-Method": "DELETE",
"X-RequestDigest": digest
}
})
if(!f.status) console.error(f)
return f.status == 200
}
/*
* Find a list item
* @param {string} site - Url of site
* @param {string} list - Title of list
* @param {string} query - ODATA Query e.g. Column eq value
* @example await findListItem("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name", "Title eq 'STORM-10001-Network Water'")
*/
async function findListItem(site, list, query){
const f = await fetch(`${site}/_api/web/lists/GetByTitle('${list}')/items?&$filter=${query}`, {
method: "GET",
headers:{
"Accept": "application/json;odata=verbose",
}
})
return await f.json()
}
/*
* Check in a file
* @param {string} site - Url of site
* @param {string} relativePath -
* @param {string} versionComment -
* @param {string} checkInType -
* @param {string|null} digest - Digest token which usually timeout after 1800 seconds. If Null then digest is automatically retrieved.
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
*/
async function fileCheckIn(site, relativePath, versionComment, checkInType=0, digest=null){
if(digest == null) digest = await getRequestDigest(site)
const f = await fetch(`${site}/_api/web/GetFileByServerRelativeUrl('${relativePath}')/CheckIn(comment='${versionComment}', checkInType=${checkInType})`, {
method: "POST",
headers:{
"Accept": "application/json;odata=verbose",
"X-RequestDigest": digest
}
})
return await f.json()
}
/*
* Check out a file
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
*/
async function fileCheckOut(site, relativePath, digest=null){
if(digest == null) digest = await getRequestDigest(site)
const f = await fetch(`${site}/_api/web/GetFileByServerRelativeUrl('${relativePath}')/CheckOut()`, {
method: "POST",
headers:{
"Accept": "application/json;odata=verbose",
"X-RequestDigest": digest
}
})
return await f.json()
}
/*
* Create a folder
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
*/
async function folderCreate(site, relativePath){
var data;
if(digest == null) digest = await getRequestDigest(site)
const f = await fetch(`${site}/_api/web/folders`, {
method: "POST",
body: (data=JSON.stringify({
__metadata: {type: "SP.Folder"},
ServerRelativeUrl: relativePath
})),
headers: {
"Accept":"application/json;odata=verbose",
"Content-Type": "application/json",
"Content-Length": data.length,
"X-RequestDigest": digest
}
})
return await f.json()
}
/*
* Create a file
* @param {string} fileName - File name and extension e.g. "Notes.txt"
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
* @remark fileContent must be < 2GB
*/
async function fileCreate(site, dirPath, fileName, fileContent, overwrite=true, digest=null){
if(digest == null) digest = await getRequestDigest(site)
const f = await fetch(`${site}/_api/web/GetFolderByServerRelativeUrl('${dirPath}')/Files/add(url='${fileName}',overwrite=${overwrite ? "true" : "false"})`, {
method: "POST",
body: fileContent,
headers: {
"Content-Length": fileContent.length,
"X-RequestDigest": digest
}
})
return await f.json()
}
/*
* Update an existing file
* @docs https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
* @remark fileContent must be < 2GB
*/
async function fileUpdate(site, relativePath, fileContent, overwrite=true, digest=null){
if(digest == null) digest = await getRequestDigest(site)
const f = await fetch(`${site}/_api/web/GetFileByServerRelativeUrl('${relativePath}')/$value`, {
method: "POST",
body: fileContent,
headers: {
"Content-Length": fileContent.length,
"X-HTTP-Method": "PUT",
"X-RequestDigest": digest
}
})
return await f.json()
}
//TODO:
//fileDelete
//folderCreate()
//fileUpload()
//fileUpdate()
//folderChildren()
//folderDescendents()
/*
function* generateRange(start, end, step = 1) {
let current = start;
while (start < end ? current <= end : current >= end) {
yield current;
current = start < end ? current + step : current - step;
}
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
arr = []
digest = await getRequestDigest("https://myServer.sharepoint.com/sites/my/sharepoint/site");
for (let i of generateRange(8546,10428)) {
console.log("Deleting " + i)
try {
await deleteListItem("https://myServer.sharepoint.com/sites/my/sharepoint/site", "My list name", i, digest)
} catch(e) {
console.error(e)
}
await sleep(300)
}
====================================================================================================
Update single item in a list with link to SearchExistingRisks
====================================================================================================
const SERUrl = "https://someOtherServer/teamworks/executecf?modelID=1.aa463662-4a96-45c9-8f0a-bc89cb578d5a&snapshotID=2064.9c5d6b47-a468-45b8-b1a9-4887fb1817f1&tw.local.riskId="
const site = "https://myServer.sharepoint.com/sites/my/sharepoint/site"
const list = "My list name"
var item = await getListItem(site, list, 1)
var type = await getListItemType(site, list)
var digest = await getRequestDigest("https://myServer.sharepoint.com/sites/my/sharepoint/site");
await updateListItem(site, list, item.Id, {
SearchExistingRisk: {
Description: "Link",
Url: SERUrl + item.Title
}
}, type, digest)
====================================================================================================
Update all items in a list with link to SearchExistingRisks
====================================================================================================
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
const SERUrl = "https://someOtherServer/teamworks/executecf?modelID=1.aa463662-4a96-45c9-8f0a-bc89cb578d5a&snapshotID=2064.9c5d6b47-a468-45b8-b1a9-4887fb1817f1&tw.local.riskId="
const site = "https://myServer.sharepoint.com/sites/my/sharepoint/site"
const list = "My list name"
var items = await getListItems(site, list)
var type = await getListItemType(site, list)
var digest = await getRequestDigest(site);
var iUpdates=0;
for(item of items){
if(item.Id >= 3911){
console.log("Updatng " + item.Id)
let b = await updateListItem(site, list, item.Id, {
SearchExistingRisk: {
Description: "Link",
Url: SERUrl + item.Title
}
}, type, digest)
await sleep(100)
iUpdates = iUpdates + 1
if((iUpdates % 500) == 0){
digest = await getRequestDigest(site);
await sleep(100)
}
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment