UNPKG

spx-com

Version:

Sharepoint 2013 Client Object Model Library

1,366 lines (1,256 loc) 179 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('crypto-js'), require('axios')) : typeof define === 'function' && define.amd ? define(['crypto-js', 'axios'], factory) : (global = global || self, global.spx = factory(global.CryptoJS, global.axios)); }(this, function (cryptoJs, axios) { 'use strict'; axios = axios && axios.hasOwnProperty('default') ? axios['default'] : axios; /* eslint-disable no-restricted-syntax */ // ================================================================================================ // ======= ==== === ======= == == ==== ==== ======= = == ====== // ====== === == == == ====== = ==== ==== ====== === ====== ==== ==== ==== ===== // ===== ======= ==== = ===== = ==== ==== ===== == == ===== ==== ==== ==== ===== // ===== ======= ==== = == === == ========= ==== ==== = == === ==== ===== ========== // ===== ======= ==== = === == ==== ======= ==== ==== = === == ==== ======= ======== // ===== ======= ==== = ==== = ====== ===== ==== = ==== = ==== ========= ====== // ===== ======= ==== = ===== = ==== ==== ==== ==== = ===== ==== ==== ==== ===== // ====== === == == == ====== = ==== ==== ==== ==== = ====== ==== ==== ==== ===== // ======= ==== === ======= == ===== ==== ==== = ======= ==== ===== ====== // ================================================================================================ const REQUEST_TIMEOUT = 3600000; const MAX_ITEMS_LIMIT = 100000; const REQUEST_BUNDLE_MAX_SIZE = 252; const REQUEST_LIST_FOLDER_UPDATE_BUNDLE_MAX_SIZE = 82; const REQUEST_LIST_FOLDER_DELETE_BUNDLE_MAX_SIZE = 240; const ACTION_TYPES = { create: 'created', update: 'updated', delete: 'deleted', recycle: 'recycled', get: 'get', copy: 'copied', move: 'moved', restore: 'restored', clear: 'cleared', erase: 'erased', send: 'sent' }; const FILE_LIST_TEMPLATES = { 101: true, 109: true, 110: true, 113: true, 114: true, 116: true, 119: true, 121: true, 122: true, 123: true, 175: true, 851: true, 10102: true }; const LIBRARY_STANDART_COLUMN_NAMES = { AppAuthor: true, AppEditor: true, Author: true, CheckedOutTitle: true, CheckedOutUserId: true, CheckoutUser: true, ContentTypeId: true, Created: true, Created_x0020_By: true, Created_x0020_Date: true, DocConcurrencyNumber: true, Editor: true, FSObjType: true, FileDirRef: true, FileLeafRef: true, FileRef: true, File_x0020_Size: true, File_x0020_Type: true, FolderChildCount: true, GUID: true, HTML_x0020_File_x0020_Type: true, ID: true, InstanceID: true, IsCheckedoutToLocal: true, ItemChildCount: true, Last_x0020_Modified: true, MetaInfo: true, Modified: true, Modified_x0020_By: true, Order: true, ParentLeafName: true, ParentVersionString: true, ProgId: true, ScopeId: true, SortBehavior: true, SyncClientId: true, TemplateUrl: true, UniqueId: true, VirusStatus: true, WorkflowInstanceID: true, WorkflowVersion: true, owshiddenversion: true, xd_ProgID: true, xd_Signature: true, _CheckinComment: true, _CopySource: true, _HasCopyDestinations: true, _IsCurrentVersion: true, _Level: true, _ModerationComments: true, _ModerationStatus: true, _SharedFileIndex: true, _SourceUrl: true, _UIVersion: true, _UIVersionString: true, ImageHeight: true, ImageWidth: true, PreviewExists: true, ThumbnailExists: true }; // ============================================= // ===== = ==== = == ===== // ======== ==== == = ==== = =========== // ======== ===== == == ==== = =========== // ======== ===== == == ==== = =========== // ======== ====== === == ======= // ======== ======= ==== ======= =========== // ======== ======= ==== ======= =========== // ======== ======= ==== ======= =========== // ======== ======= ==== ======= ===== // ============================================= const typeOf = (variable) => Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); // =================================================================================================== // ======= ==== === ===== = === = ======= ==== ==== === === ====== // ====== === == == == === = === === == ====== === ====== ===== == == ==== ===== // ===== ======= ==== = = = = ==== == == ===== == == ===== ==== ==== = ==== ===== // ===== ======= ==== = == == = === === == == === = ==== ==== ==== ==== = === ===== // ===== ======= ==== = ===== = ==== == === == = ==== ==== ==== ==== = ======= // ===== ======= ==== = ===== = === === == ==== = = ==== ==== ==== = ==== ===== // ===== ======= ==== = ===== = ==== == == ===== = ==== ==== ==== ==== = ==== ===== // ====== === == == == ===== = === === == ====== = ==== ==== ===== == == ==== ===== // ======= ==== === ===== = === = ======= = ==== ==== ====== === ==== ===== // =================================================================================================== const COMBINATOR = { /** * I :: a → a * * identity * * @param {*} a * @returns {*} a */ I: x => x, /** * K :: a → b → a * * constant * * @param {*} a * @returns {*} a */ K: x => () => x, /** * A :: (a → b) → a → b * * apply * @param {Function} f * @returns {Function} f */ A: f => x => f(x), /** * U :: (a → a) → a * * universal * @param {Function} f * @returns {Function} f */ U: f => f(f), /** * Y :: (a → a) → a * * fixed-point * @param {Function} f * @returns {Function} f */ Y: f => COMBINATOR.U(g => f((x) => g(g)(x))), /** * C :: (a → b → c) → b → a → c * * flip * @param {Function} f * @returns {Function} f */ C: f => x => y => f(y)(x), /** * S :: (a → b → c) → (a → b) → a → c * * substitution * @param {Function} f * @returns {Function} f */ S: f => g => x => f(x)(g(x)), /** * SI :: (a → b) → (a → b → c) → a → c * * inverted S * @param {Function} f * @returns {Function} f */ SI: f => g => x => g(x)(f(x)), /** * SA :: (a → b) → (a → b → c) → a → c * * async S * @param {Function} f * @returns {Function} f */ SA: f => g => async x => f(x)(await g(x)), /** * SIA :: (a → b) → (a → b → c) → a → c * * async SI * @param {Function} f * @returns {Function} f */ SIA: f => g => async x => g(x)(await f(x)) }; const identity = COMBINATOR.I; const constant = COMBINATOR.K; const fix = COMBINATOR.Y; const flip = COMBINATOR.C; const overstep = f => x => { f(x); return x }; const functionSum = f => x => y => x + f(y); // ====================================================== // ======= == ==== = == == ==== ===== // ====== === = ==== = ==== = ==== = == ===== // ===== ======= ==== = ==== = ==== == == ====== // ===== ======= ==== = === = === == == ====== // ===== ======= ==== = === ===== ======= // ===== ======= ==== = ==== = ==== ==== ======== // ===== ======= ==== = ==== = ==== ==== ======== // ====== === = == = ==== = ==== ==== ======== // ======= === == ==== = ==== ==== ======== // ====================================================== /** * curry2 :: f → g * * 2-args currying * * @param {Function} f * @returns {Function} */ const curry2 = (f) => (x, y) => f(x)(y); // ======================================================================================== // ======= ==== === ======= = == = = === === ======= ===== // ====== === == == == ====== = ==== == ===== ===== === == == ====== ===== // ===== ======= ==== = ===== = ==== == ===== ===== == ==== = ===== ===== // ===== ======= ==== = == === = ==== == ===== ===== == ==== = == === ===== // ===== ======= ==== = === == = ==== == ===== ===== == ==== = === == ===== // ===== ======= ==== = ==== = = ==== == ===== ===== == ==== = ==== = ===== // ===== ======= ==== = ===== = ==== == ===== ===== == ==== = ===== ===== // ====== === == == == ====== = ==== == ===== ===== === == == ====== ===== // ======= ==== === ======= = == ==== ==== === === ======= ===== // ======================================================================================== const ifThen = (predicate) => ([onTrue, onFalse]) => (x) => predicate(x) ? onTrue(x) : (onFalse) ? onFalse(x) : x; const switchCase = (condition) => (cases) => (x) => { const caseF = cases[condition(x)]; return caseF ? caseF(x) : cases.default ? cases.default(x) : undefined }; const switchType = switchCase(typeOf); // =================================================================== // ===== ======= = ==== = ===== = === = ====== // ===== ====== = ==== = === = === == ======= ==== ===== // ===== ===== = ==== = = = = ==== = ======= ==== ===== // ===== == === = ==== = == == = === == ======= === ===== // ===== === == = ==== = ===== = === === ======= // ===== ==== = = ==== = ===== = === == ======= ==== ===== // ===== ===== = ==== = ===== = ==== = ======= ==== ===== // ===== ====== = == = ===== = === == ======= ==== ===== // ===== ======= == == ===== = === = ==== ===== // =================================================================== const sum = (x) => (y) => x + y; const gt = (x) => (y) => x < y; // ============================================================== // ====== == = == = ======= == ====== // ===== ==== ==== ==== ==== == == ====== = == ===== // ===== ==== ==== ==== ==== == == ===== = ==== ===== // ====== ========= ==== === == == == === = =========== // ======== ======= ==== ==== == === == = =========== // ========== ===== ==== ==== == == ==== = = === ===== // ===== ==== ==== ==== ==== == == ===== = ==== ===== // ===== ==== ==== ==== ==== == == ====== = == ===== // ====== ===== ==== ==== = = ======= == ====== // ============================================================== const stringTest = (re) => (str) => re.test(str); const stringReplace = (re) => (to) => (str) => str.replace(re, to); const stringMatch = (re) => (str) => str.match(re) || []; const stringCut = (re) => stringReplace(re)(''); const stringSplit = (re) => (str) => str.split(re); const stringTrim = (str) => str.trim(); // ====================================================== // ======== ==== == ===== ==== ==== ===== // ======= === ==== = ==== === === == ===== // ====== == == ==== = ==== == == === == ====== // ===== ==== = === = === = ==== == == ====== // ===== ==== = === === ==== === ======= // ===== = ==== = ==== = ==== ======== // ===== ==== = ==== = ==== = ==== ==== ======== // ===== ==== = ==== = ==== = ==== ==== ======== // ===== ==== = ==== = ==== = ==== ==== ======== // ====================================================== const getArray = (x) => (typeOf(x) === 'array' ? x : x ? [x] : []); const map = (f) => (xs) => xs.map(f); const filter = (f) => (xs) => xs.filter(f); const slice = (from, to) => (xs) => xs.slice(from, to); const join = (delim) => (xs) => xs.join(delim); const removeUndefineds = filter((x) => x !== undefined); const concat = (array) => (x) => array.concat(x); const reduce = (f) => (init) => (xs) => xs.reduce( curry2(f), switchType({ object: constant({}), array: constant([]), default: identity })(init) ); const reduceDirty = (f) => (init) => (xs) => getArray(xs).reduce(curry2(flip(f)), getArray(init)); const flatten = reduce((acc) => pipe([ifThen(isArray)([flatten, identity]), concat(acc)]))([]); const arrayHead = (xs) => xs[0]; const arrayTail = ([, ...t]) => t; const arrayLast = (xs) => xs[xs.length - 1]; const arrayInit = slice(0, -1); const EMPTY_ARRAY = () => []; const chunkArrayFrom = (start = 0) => (size) => (value) => { let i = start; return reduce((acc) => (x) => { if (acc[i] === undefined) acc[i] = []; const chunk = acc[i]; chunk.push(x); if (chunk.length === size) i += 1; return acc })([])(value) }; const chunkArray = chunkArrayFrom(); const removeEmptiesByProp = property => filter((x) => !!x[property]); const removeDuplicatedProp = property => pipe([reduce((acc) => (x) => { acc[x[property]] = x; return acc })({}), Object.values]); const methodEmpty = (m) => (o) => (o[m] ? o[m]() : o); const method = (m) => (arg) => (o) => (o[m] ? o[m](arg) : o); const methodI = (m) => (o) => (arg) => (o[m] ? o[m](arg) : o); const apply = (m) => (o) => (args) => o[m](...args); const prop = (name) => (o) => o[name]; const keys = (o) => Object.keys(o); const getInstance = (constructor) => (...args) => new constructor(...args); const getInstanceEmpty = (constructor) => new constructor(); const switchProp = (o) => (x) => { const props = Reflect.ownKeys(o); for (let i = 0; i < props.length; i += 1) { const property = props[i]; if (x[property]) return o[property](x) if (x.default) return x.default(x) } return undefined }; const NULL = () => null; const climb = f => fix(fr => ([h, ...t]) => o => t.length ? fr(t)(f(h)(o)) : f(h)(o)); // ========================================================================= // ======= ==== === ===== = ==== ==== == ===== // ====== === == == == === = ==== == == == ==== = =========== // ===== ======= ==== = = = = ==== = ==== = ==== = =========== // ===== ======= ==== = == == = ==== = ==== == ====== =========== // ===== ======= ==== = ===== = == ==== ==== ==== ======= // ===== ======= ==== = ===== = ======= ==== ====== == =========== // ===== ======= ==== = ===== = ======= ==== = ==== = =========== // ====== === == == == ===== = ======== == == ==== = =========== // ======= ==== === ===== = ========= ==== == ===== // ========================================================================= const pipe = reduce((acc) => (f) => (x) => f(acc(x)))(identity); // ================================================== // ===== ========= ==== == === ====== // ===== ======== == == == == === === ===== // ===== ======= ==== = ==== == == =========== // ===== ======= ==== = ======== == =========== // ===== ======= ==== = ======== == =========== // ===== ======= ==== = === == == =========== // ===== ======= ==== = ==== == == =========== // ===== ======== == == == == === === ===== // ===== === ==== == === ====== // ================================================== const toBoolean = (x) => !!x; const not = (x) => !x; const and = (x) => (y) => toBoolean(x && y); const TRUE = () => true; const FALSE = () => false; const isEqual = (sample) => (x) => x === sample; const isNotEqual = pipe([isEqual, not]); const isNumber = (x) => typeOf(x) === 'number'; const isString = (x) => typeOf(x) === 'string'; const isArray = (x) => typeOf(x) === 'array'; const isObject = (x) => typeOf(x) === 'object'; const isBlob = (x) => { const type = typeOf(x); return type === 'blob' || type === 'file' }; const isGUID = stringTest(/^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/); // ========================================================================================= // ===== = == = == == ==== ==== ======= === == ===== // ===== ======== == === == ==== ==== ====== === ====== == === = =========== // ===== ======== == === == ==== ==== ===== == == ===== = ======= =========== // ===== ========= ==== === ========= ==== ==== = == === = ======= =========== // ===== ====== ===== ===== ======= ==== ==== = === == = ======= ======= // ===== ========= ==== ======= ===== ==== = ==== = = ======= =========== // ===== ======== == === == ==== ==== ==== ==== = ===== = ======= =========== // ===== ======== == === == ==== ==== ==== ==== = ====== == === = =========== // ===== = ==== = == ===== ==== ==== = ======= === == ===== // ========================================================================================= const isNull = (x) => x === null; const isNotNull = pipe([isNull, not]); const isUndefined = (x) => x === undefined; const isDefined = pipe([isUndefined, not]); const isZero = (x) => x === 0; const isNotZero = pipe([isZero, not]); const isNaN = (x) => typeOf(x) === 'number' && x.toString() === 'NaN'; const isNotNaN = pipe([isNaN, not]); const isNumberFilled = (x) => isNumber(x) && isNotZero(x) && isNotNaN(x); const isStringEmpty = (x) => x === ''; const isStringFilled = pipe([isStringEmpty, not]); const isArrayFilled = pipe([filter(isDefined), prop('length'), toBoolean]); const isArrayEmpty = pipe([isArrayFilled, not]); const isObjectFilled = ifThen(isObject)([pipe([keys, isArrayFilled]), FALSE]); const isObjectEmpty = pipe([keys, isArrayEmpty]); const isNotError = x => typeOf(x) !== 'error'; const isExists = (x) => isDefined(x) && isNotNull(x); const isNotExists = pipe([isExists, not]); const isFilled = ifThen(isExists)([ switchType({ number: isNumberFilled, string: isStringFilled, array: isArrayFilled, object: isObjectFilled, null: FALSE, default: TRUE }), toBoolean ]); const isNotFilled = pipe([isFilled, not]); const hasProp = (name) => (o) => o[name]; const isPropExists = (name) => pipe([prop(name), isExists]); const isPropFilled = (name) => pipe([prop(name), isFilled]); // ==================================== // ===== = == ==== ===== // ======== ==== ==== = == ===== // ======== ==== ==== == == ====== // ======== ==== === == == ====== // ======== ==== ===== ======= // ======== ==== ==== ==== ======== // ======== ==== ==== ==== ======== // ======== ==== ==== ==== ======== // ======== ==== ==== ==== ======== // ==================================== const tryCatch = (tryer) => (catcher) => (data) => { try { return tryer(data) } catch (err) { return catcher(err)(data) } }; const throwError = (msg) => { throw new Error(msg) }; const report = (msg, opts = {}) => { if (!opts.silent && !opts.silentInfo) console.log(msg); }; const rootReport = (actionType, opts = {}) => { const { box, name, detailed } = opts; const count = box.getCount(); report( `${ACTION_TYPES[actionType]} ${count} ${name}${count > 1 ? 's' : ''}${detailed ? `: ${box.join()}` : ''} `, opts ); }; const webReport = (actionType, opts = {}) => { const { box, name, detailed, contextUrl } = opts; const count = box.getCount(actionType); report( `${ACTION_TYPES[actionType] } ${count } ${name}${count > 1 ? 's' : ''} at ${contextUrl || '/' }${detailed ? `: ${box.join()}` : ''}`, opts ); }; const listReport = (actionType, opts = {}) => { const { box, name, detailed, contextUrl, listUrl } = opts; const count = box.getCount(actionType); report( `${ACTION_TYPES[actionType] } ${count } ${name}${count > 1 ? 's' : ''} in ${listUrl } at ${contextUrl || '/' }${detailed ? `: ${box.join()}` : ''}`, opts ); }; // ======================================================================== // ====== == ==== === ==== = == = ====== // ===== == = ==== == == == ==== = ==== = ======= ==== ===== // ===== ==== = ==== = ==== = ==== = ==== = ======= ==== ===== // ===== ======= === = ==== = ==== = ==== = ======= === ===== // ===== ======= === ==== = ==== = == === ======= // ===== === = ==== = ==== = ==== = ======= ======= ==== ===== // ===== ==== = ==== = ==== = ==== = ======= ======= ==== ===== // ===== == = ==== == == == == = ======= ======= ==== ===== // ====== == ==== === ==== == ======= = ==== ===== // ======================================================================== const groupSimple = (by) => reduce((acc) => (el) => { const elValue = el[by]; const trueValue = isExists(elValue) && elValue.get_lookupId ? elValue.get_lookupId() : elValue; const groupValue = acc[trueValue]; acc[trueValue] = isUndefined(groupValue) ? [el] : isArray(groupValue) ? concat(groupValue)(el) : [groupValue, el]; return acc })({}); const groupMapper = (f) => fix((fR) => (acc) => switchType({ array: f, object: (el) => { const props = Reflect.ownKeys(el); for (let i = 0; i < props.length; i += 1) { const property = props[i]; const childEl = el[property]; acc[property] = isArray(childEl) ? f(childEl) : fR({})(childEl); } return acc }, default: identity }))({}); // const grouper = pipe([getArray, flip(pipe([getArray, reduceDirty(pipe([groupSimple, groupMapper]))]))]); const grouper = flip(reduceDirty(pipe([groupSimple, groupMapper]))); const mapper = (by) => (xs) => reduce((acc) => (el) => { const elValue = el[by]; acc[isExists(elValue) && elValue.get_lookupId ? elValue.get_lookupId() : elValue] = el; return acc })({})(getArray(xs)); // ==================================== // ===== ==== = == =========== // ===== ==== = ==== = =========== // ===== ==== = ==== = =========== // ===== ==== = === = =========== // ===== ==== = === =========== // ===== ==== = ==== = =========== // ===== ==== = ==== = =========== // ===== == = ==== = =========== // ====== == ==== = ===== // ==================================== const hasUrlTailSlash = stringTest(/\/$/); const hasUrlFilename = stringTest(/\.[^/]+$/); const removeEmptyUrls = removeEmptiesByProp('Url'); const removeEmptyIDs = filter(pipe([prop('ID'), isNumberFilled])); const removeEmptyFilenames = filter((x) => x.Url && hasUrlFilename(x.Url)); const removeDuplicatedUrls = removeDuplicatedProp('Url'); const prependSlash = ifThen(stringTest(/^\//))([identity, sum('/')]); const popSlash = stringCut(/\/$/); const shiftSlash = stringCut(/^\//); const mergeSlashes = stringReplace(/\/\/+/g)('/'); const urlSplit = stringSplit('/'); const getTitleFromUrl = pipe([popSlash, urlSplit, arrayLast]); const urlJoin = join('/'); const getParentUrl = pipe([popSlash, urlSplit, arrayInit, urlJoin]); const getFolderFromUrl = ifThen(stringTest(/\./))([getParentUrl, popSlash]); const getFilenameFromUrl = ifThen(stringTest(/\./))([getTitleFromUrl, NULL]); const isStrictUrl = (url) => isStringFilled(url) && !hasUrlTailSlash(url); const getListRelativeUrl = webUrl => listUrl => (element = {}) => { const { Url, Folder } = element; if (Folder) { const folder = shiftSlash(Folder); return Url ? `${folder}/${getTitleFromUrl(Url)}` : folder } return Url && stringTest(/\//)(Url) ? Url === '/' ? '/' : shiftSlash( arrayLast( stringSplit('@list@')( stringReplace(listUrl)('@list@')(stringReplace(shiftSlash(webUrl))('@web@')(Url)) ) ) ) : Url }; const getWebRelativeUrl = (webUrl) => (element = {}) => { const { Url, Folder } = element; if (Folder) { const folder = shiftSlash(Folder); return Url ? `${folder}/${getTitleFromUrl(Url)}` : folder } return Url && stringTest(/\//)(Url) ? Url === '/' ? '/' : shiftSlash(arrayLast(stringSplit('@web@')(stringReplace(shiftSlash(webUrl))('@web@')(Url)))) : Url }; class AbstractBox { constructor(value, lifter, arrayValidator = identity) { this.prop = 'Url'; this.joinProp = 'Url'; this.value = isArray(value) ? ifThen(isArrayFilled)([ pipe([ map(lifter), arrayValidator ]), constant([lifter()]) ])(value) : lifter(value); } reduce(f, init = []) { return isArray(this.value) ? reduce(f)(init)(this.value) : f(init)(this.value) } some(f) { return isArray(this.value) ? this.value.some(f) : f(this.value) } chain(f) { return isArray(this.value) ? Promise.all(map(f)(this.value)) : f(this.value) } join() { return isArray(this.value) ? join(', ')(map(prop(this.joinProp))(this.value)) : this.value[this.joinProp] } getCount() { return isArray(this.value) ? this.value.filter(el => isDefined(el[this.prop])).length : isDefined(this.value[this.prop]) ? 1 : 0 } getHead() { return isArray(this.value) ? this.value[0] : this.value } getHeadPropValue() { return isArray(this.value) ? (this.value[0] ? this.value[0][this.prop] : undefined) : this.value[this.prop] } getIterable() { return isArray(this.value) ? this.value : [this.value] } isArray() { return isArray(this.value) } } // ============================================================================= // ===== = = = ===== ==== === === ====== // ====== ===== ==== ======= ==== === ====== ===== == == ==== ===== // ====== ===== ==== ======= ==== == == ===== ==== ==== = ==== ===== // ====== ===== ==== ======= === = ==== ==== ==== ==== = === ===== // ====== ===== ==== === === ==== ==== ==== ==== = ======= // ====== ===== ==== ======= ==== = ==== ==== ==== = ==== ===== // ====== ===== ==== ======= ==== = ==== ==== ==== ==== = ==== ===== // ====== ===== ==== ======= ==== = ==== ==== ===== == == ==== ===== // ===== ==== ==== = ==== = ==== ==== ====== === ==== ===== // ============================================================================= const deep1Iterator = ({ contextUrl = '/', elementBox, bundleSize = REQUEST_BUNDLE_MAX_SIZE }) => async (f) => { let totalElements = 0; let clientContext = getClientContext(contextUrl); const clientContexts = [clientContext]; const result = await elementBox.chain((element) => { totalElements += 1; if (totalElements >= bundleSize) { clientContext = getClientContext(contextUrl); clientContexts.push(clientContext); totalElements = 0; } return f({ clientContext, element }) }); return { clientContexts, result } }; const deep1IteratorREST = ({ elementBox }) => (f) => elementBox.chain(async (element) => f({ element })); // =========================================================================== // ======= ==== === ======= = = = == = ===== // ====== === == == == ====== ==== ==== ======== == ===== ======== // ===== ======= ==== = ===== ==== ==== ======== == ===== ======== // ===== ======= ==== = == === ==== ==== ========= ====== ======== // ===== ======= ==== = === == ==== ==== ====== ======= ======== // ===== ======= ==== = ==== = ==== ==== ========= ====== ======== // ===== ======= ==== = ===== ==== ==== ======== == ===== ======== // ====== === == == == ====== ==== ==== ======== == ===== ======== // ======= ==== === ======= ==== ==== = ==== ==== ======== // =========================================================================== const newClientContext = getInstance(SP.ClientContext); const getClientContext = url => { let normalizedUrl = url; if (!/^https?:/.test(url) && !/^\//.test(url)) { normalizedUrl = prependSlash(url); } if (/\.\/$/.test(normalizedUrl)) { normalizedUrl = popSlash(normalizedUrl); } const clientContext = newClientContext(normalizedUrl); clientContext.set_requestTimeout(REQUEST_TIMEOUT); return clientContext }; // ==================================================================================== // ===== == == == ==== === ======= == == ===== // ===== ==== = ======= ==== = ==== == == == ====== = ==== = =========== // ===== ==== = ======= ==== = ==== = ==== = ===== = ==== = =========== // ===== === = ======== ====== ==== = ==== = == === == ====== =========== // ===== === ====== ==== == ==== = === == ==== ==== ======= // ===== ==== = ============ == ======= ==== = ==== = ====== == =========== // ===== ==== = ======= ==== = ======= ==== = ===== = ==== = =========== // ===== ==== = ======= ==== = ======== == == ====== = ==== = =========== // ===== ==== = == == ========= === ======= == == ===== // ==================================================================================== const getSPObjectValues = asItem => ifThen(isExists)([ pipe([ ifThen(constant(asItem))([methodEmpty('get_listItemAllFields')]), ifThen(isObject)([ switchProp({ get_fieldValues: methodEmpty('get_fieldValues'), get_objectData: pipe([methodEmpty('get_objectData'), methodEmpty('get_properties')]), default: tryCatch(pipe([JSON.stringify, sum('Wrong spObject: '), throwError]))(throwError) }) ]) ]) ]); const getRESTValues = pipe([ ifThen(hasProp('body'))([pipe([prop('body'), ifThen(isString)([JSON.parse])]), prop('data')]), ifThen(hasProp('d'))([pipe([prop('d'), ifThen(hasProp('results'))([prop('results')])])]) ]); const prepareResponseJSOM = (results, opts = {}) => ifThen(isArray)([ pipe([ flatten, removeUndefineds, ifThen(constant(opts.expanded))([ identity, pipe([ map(getSPObjectValues(opts.asItem)), ifThen(constant(opts.groupBy))([ grouper(opts.groupBy), ifThen(constant(opts.mapBy))([mapper(opts.mapBy)]) ]) ]) ]) ]), ifThen(constant(opts.expanded))([identity, getSPObjectValues(opts.asItem)]) ])(results); const prepareResponseREST = (results, opts = {}) => ifThen(isArray)([ pipe([ flatten, pipe([ ifThen(constant(opts.expanded))([identity]), map(getRESTValues), ifThen(constant(opts.groupBy))([ grouper(opts.groupBy), ifThen(constant(opts.mapBy))([mapper(opts.mapBy)]) ]) ]) ]), getRESTValues ])(results); // ============================================= // ===== ========= ====== ==== ====== // ===== ======== == ==== === ==== ===== // ===== ======= ==== == == == ==== ===== // ===== ======= ==== = ==== = ==== ===== // ===== ======= ==== = ==== = ==== ===== // ===== ======= ==== = = ==== ===== // ===== ======= ==== = ==== = ==== ===== // ===== ======== == == ==== = ==== ===== // ===== === === ==== = ====== // ============================================= const getViewOption = ifThen(isObjectFilled)([ ifThen(isPropFilled('view'))([ ifThen(isPropFilled('groupBy'))([ (opts) => concat(getArray(opts.view))(getArray(opts.groupBy)), pipe([prop('view'), getArray]) ]), EMPTY_ARRAY ]), EMPTY_ARRAY ]); const load = (clientContext, spObject, opts = {}) => ifThen(hasProp('getEnumerator'))([ pipe([ (data) => pipe([ constant(getViewOption(opts)), ifThen(isArrayFilled)([(view) => [data, `Include(${view})`], constant([data])]) ])(data), apply('loadQuery')(clientContext) ]), overstep( pipe([ (data) => pipe([ constant(getViewOption(opts)), ifThen(isArrayFilled)([(view) => [data, view], constant([data])]) ])(data), apply('load')(clientContext) ]) ) ])(spObject); // ================================================================================= // ===== = == = === == ==== = === === ====== // ===== ======== == == ======== === = ==== ==== ===== == == ==== ===== // ===== ======== == == ======= ======= ==== ==== ==== ==== = ==== ===== // ===== ========= === ======= ======= ==== ==== ==== ==== = === ===== // ===== ====== ==== === ======= ==== ==== ==== ==== = ======= // ===== ========= === ======= ======= ==== ==== ==== ==== = ==== ===== // ===== ======== == == ======= ======= ==== ==== ==== ==== = ==== ===== // ===== ======== == == ======== === = == ==== ===== == == ==== ===== // ===== = ==== = === === ===== ====== === ==== ===== // ================================================================================= const executorJSOM = async (clientContext) => new Promise((resolve, reject) => { clientContext.executeQueryAsync( resolve, (sender, args) => { const cid = args.get_errorTraceCorrelationId(); reject(new Error( `\nMessage: ${args .get_message() .replace( /\n{1,}/g, ' ' )}\nValue: ${args.get_errorValue()}\nType: ${args.get_errorTypeName()}\nId: ${cid}` )); } ); }); const executeJSOM = async (clientContext, spObject, opts) => { const spObjects = load(clientContext, spObject, opts); await executorJSOM(clientContext); return spObjects }; const executorREST = async (contextUrl, opts = {}) => pipe([ mergeSlashes, popSlash, prependSlash, getInstance(SP.RequestExecutor), (executor) => new Promise((resolve, reject) => executor.executeAsync({ ...opts, method: pipe([ prop('method'), ifThen(stringTest(/post/i))([constant('POST'), constant('GET')]) ])(opts), success: resolve, error: (res) => { const { silent, silentErrors } = opts; if (!silent && !silentErrors) { const { body } = res; let msg = body; if (typeOf(res.body) === 'string') { try { msg = JSON.parse(res.body).error.message.value; } catch (err) { // err } } console.error(`\nMessage: ${res.statusText}\nCode: ${res.statusCode}\nValue: ${msg}`); } reject(res); } })) ])(contextUrl); // ================================================================= // ===== ====== ===== == == ======= ======= // ===== === ==== === ==== = ======= ===== ===== ======= // ===== ==== == == == ==== = ======= =========== ======= // ===== === == ==== == ====== ======= ===== = ======= // ===== === ==== ==== ==== === === === == ======= // ===== === == ====== == ======= ===== = === ======= // ===== ==== = ==== = ==== = ======= ===== = ===== // ===== === == ==== = ==== = ======== === ====== ======= // ===== === ==== == == === ======== ======= // ================================================================= const convertFileContent = switchType({ arraybuffer: pipe([getInstance(Uint8Array), reduce(functionSum(String.fromCharCode))(''), btoa]), default: tryCatch(btoa)(() => identity) }); // ================================================================================= // ====== == ==== === ======= = === == ===== // ===== ==== = ==== == == == === ======= == ======== === ==== ======== // ===== ==== = ==== = ==== = ==== ====== == ======= ========== ======== // ====== ====== ==== = ==== = === ======= == ======= ========== ======== // ======== ==== == ==== = ======== == === ========== ======== // ========== == ======= ==== = === ======= == ======= ========== ======== // ===== ==== = ======= ==== = ==== = === == ======= ========== ======== // ===== ==== = ======== == == === == === == ======== === ==== ======== // ====== == ========= === ==== === === ===== ======== // ================================================================================= const setItemSP = (name) => (item) => (value) => item.set_item(name, value); const getSPFolderByUrl = (initUrl) => ifThen(constant(initUrl))([ climb((url) => pipe([methodEmpty('get_folders'), method('getByUrl')(url)]))( pipe([stringReplace(/\/\/+/)('/'), stringSplit('/')])(initUrl) ), identity ]); const setItem = (fieldsInfo) => (fields) => (spObject) => { const props = Reflect.ownKeys(fields); for (let i = 0; i < props.length; i += 1) { const property = props[i]; const fieldInfo = fieldsInfo[property]; const fieldValues = fields[property]; if (fieldInfo) { const set = setItemSP(fieldInfo.InternalName)(spObject); const setLookupAndUser = (f) => (constructor) => pipe([f(constructor), set]); switch (fieldInfo.TypeAsString) { case 'Lookup': setLookupAndUser(setLookup)(SP.FieldLookupValue)(fieldValues); break case 'LookupMulti': setLookupAndUser(setLookupMulti)(SP.FieldLookupValue)(getArray(fieldValues)); break case 'User': setLookupAndUser(setLookup)(SP.FieldUserValue)(fieldValues); break case 'UserMulti': setLookupAndUser(setLookupMulti)(SP.FieldUserValue)(getArray(fieldValues)); break case 'TaxonomyFieldType': set(`-1;#${fieldValues.get_label()}|${fieldValues.get_termGuid()}`); break case 'TaxonomyFieldTypeMulti': switchType({ object: pipe([ prop('$2_1'), pipe([ reduce((acc) => (el) => acc.concat(`-1;#${el.get_label()}|${el.get_termGuid()}`))([]), join(';#'), set ]) ]), array: pipe([join(';'), setItemSP('TaxKeywordTaxHTField')(spObject)]), string: setItemSP('TaxKeywordTaxHTField')(spObject) })(fieldValues); break default: set(fieldValues); } } else { setItemSP(property)(spObject)(fieldValues); } } spObject.update(); return spObject }; const setLookupMulti = (constructor) => pipe([ reduce((acc) => ifThen(isExists)([pipe([setLookup(constructor), concat(acc)])]))([]), ifThen(isArrayFilled)([identity, NULL]) ]); const setLookupValue = (constructor) => (value) => pipe([ getInstanceEmpty, overstep(method('set_lookupId')(value)) ])(constructor); const setLookup = (constructor) => pipe([ ifThen(isNull)([ NULL, ifThen(hasProp('get_lookupId'))([ pipe([methodEmpty('get_lookupId'), setLookupValue(constructor)]), pipe([parseInt, ifThen(constant(and(isNumber)(gt(0))))([setLookupValue(constructor), NULL])]) ]) ]) ]); const setFields = (source) => (target) => { const props = Reflect.ownKeys(source); for (let i = 0; i < props.length; i += 1) { const property = props[i]; const value = source[property]; if (value !== undefined && target[property]) target[property](value); } return target }; // ============================================================ // ======== ==== == ==== == == ======= // ======= == ====== ===== ==== == ======== ==== ====== // ====== ==== ===== ===== ==== == ======== ==== ====== // ====== ==== ===== ===== ==== == ======== === ====== // ====== ==== ===== ===== == ==== ======== // ====== ==== ===== ===== ==== == ======== ==== ====== // ====== ==== ===== ===== ==== == ======== ==== ====== // ======= == ====== ===== ==== == ======== ==== ====== // ======== ======= ===== ==== == == ==== ====== // ============================================================ const getRequestDigest = contextUrl => axios({ url: `${prependSlash(contextUrl)}/_api/contextinfo`, headers: { Accept: 'application/json; odata=verbose' }, method: 'POST' }).then(res => res.data.d.GetContextWebInformation.FormDigestValue); const getPermissionMasks = () => getPermissionMasks.cache || (() => { const permissionKind = SP.PermissionKind; getPermissionMasks.cache = Object.keys(permissionKind).reduce((acc, el) => { const kind = permissionKind[el]; if (isNumber(kind)) acc[el] = kind; return acc }, {}); return getPermissionMasks.cache })(); const KEY_PROP = 'Query'; const lifter = switchType({ object: query => Object.assign({}, query), string: (query = '') => ({ [KEY_PROP]: query, }), default: () => ({ [KEY_PROP]: '' }) }); class Search { constructor(parent, query) { this.name = 'search'; this.parent = parent; this.element = lifter(query); this.contextUrl = parent.box.getHeadPropValue(); this.rowsPerPage = this.element.RowsPerPage || 10; if (this.element.StartRow === undefined) this.element.StartRow = 0; } async get(opts) { const clientContext = getClientContext(this.contextUrl || '/'); const { element } = this; const searchExecutor = new Microsoft.SharePoint.Client.Search.Query.SearchExecutor(clientContext); const keywordQuery = new Microsoft.SharePoint.Client.Search.Query.KeywordQuery(clientContext); setFields({ set_queryText: element[KEY_PROP], set_clientType: element.ClientType || 'AllResultsQuery', set_queryTemplate: element.QueryTemplate ? element.QueryTemplate.join(' ') : undefined, set_refiners: element.Refiners, set_rowsPerPage: element.RowsPerPage || this.rowsPerPage, set_totalRowsExactMinimum: element.TotalRowsExactMinimum || 11, set_blockDedupeMode: element.BlockDedupeMode, set_bypassResultTypes: element.BypassResultTypes, set_collapseSpecification: element.CollapseSpecification, set_culture: element.Culture || 1033, set_desiredSnippetLength: element.DesiredSnippetLength, set_enableInterleaving: element.EnableInterleaving, set_enableNicknames: element.EnableNicknames, set_enableOrderHitHighlightedProperty: element.EnableOrderHitHighlightedProperty, set_enablePhonetic: element.EnablePhonetic, set_enableQueryRules: element.EnableQueryRules, set_enableSorting: element.EnableSorting, set_enableStemming: element.EnableStemming, set_generateBlockRankLog: element.GenerateBlockRankLog, set_hiddenConstrains: element.HiddenConstrains, set_hitHighlightedMultivaluePropertyLimit: element.HitHighlightedMultivaluePropertyLimit, set_impressionID: element.ImpressionID, set_maxSnippetLength: element.MaxSnippetLength, set_personalizationData: element.PersonalizationData, set_processBestBets: element.ProcessBestBets, set_processPersonalFavorites: element.ProcessPersonalFavorites, set_queryTag: element.QueryTag, set_rankingModelId: element.RankingModelId, set_refinementFilters: element.RefinementFilters, set_reorderingRules: element.ReorderingRules, set_resultsUrl: element.ResultsUrl, set_rowLimit: element.RowLimit || 10, set_startRow: element.StartRow, set_showPeopleNameSuggestions: element.ShowPeopleNameSuggestions || false, set_summaryLength: element.SummaryLength, set_timeZoneId: element.TimeZoneId, set_timeout: element.Timeout, set_trimDuplicates: element.TrimDuplicates, set_trimDuplicatesIncludeId: element.TrimDuplicatesIncludeId, set_uiLanguage: element.UiLanguage || 1033 })(keywordQuery); load(clientContext, keywordQuery, opts); const result = searchExecutor.executeQuery(keywordQuery); await executorJSOM(clientContext); return result.get_value() } async next(opts) { const res = await this.get(opts); this.element.StartRow += this.rowsPerPage; return res } async previous(opts) { const res = await this.get(opts); this.element.StartRow -= this.rowsPerPage; return res } async move(opts = {}) { const { page } = opts; this.element.StartRow = page * this.rowsPerPage; return this.get(opts) } } var search = getInstance(Search); /* eslint class-methods-use-this:0 */ const KEY_PROP$1 = 'Title'; const addFieldAsXml = spParentObject => schema => spParentObject.addFieldAsXml( schema, true, SP.AddFieldOptions.defaultValue ); const arrayValidator = pipe([removeEmptiesByProp(KEY_PROP$1), removeDuplicatedProp(KEY_PROP$1)]); const lifter$1 = switchType({ object: column => { const newColumn = Object.assign({}, column); if (column[KEY_PROP$1] !== '/') newColumn[KEY_PROP$1] = shiftSlash(newColumn[KEY_PROP$1]); if (!column[KEY_PROP$1]) { newColumn[KEY_PROP$1] = column.EntityPropertyName || column.InternalName || column.StaticName; } if (!column.Type) newColumn.Type = 'Text'; return newColumn }, string: column => ({ [KEY_PROP$1]: column === '/' ? '/' : shiftSlash(mergeSlashes(column)), Type: 'Text' }), default: () => ({ [KEY_PROP$1]: undefined, Type: 'Text' }) }); class Box extends AbstractBox { constructor(value = '') { super(value, lifter$1, arrayValidator); this.prop = KEY_PROP$1; this.joinProp = KEY_PROP$1; } } class Column { constructor(parent, columns) { this.name = 'column'; this.parent = parent; this.box = getInstance(Box)(columns); this.contextUrl = parent.parent.box.getHeadPropValue(); this.listUrl = parent.box.getHeadPropValue(); this.iterator = deep1Iterator({ contextUrl: this.contextUrl, elementBox: this.box, }); } async get(opts) { const { clientContexts, result } = await this.iterator(({ clientContext, element }) => { const elementTitle = element[KEY_PROP$1]; const isCollection = isStringEmpty(elementTitle) || hasUrlTailSlash(elementTitle); const spObject = isCollection ? this.getSPObjectCollection(clientContext) : this.getSPObject(elementTitle, clientContext); return load(clientContext, spObject, opts) }); await Promise.all(clientContexts.map(executorJSOM)); return prepareResponseJSOM(result, opts) } async create(opts) { const { clientContexts, result } = await this.iterator(({ clientContext, element }) => { const title = element[KEY_PROP$1]; if (!isStrictUrl(title)) return undefined const { Title = title, Type = element.TypeAsString || 'Text', AllowMultipleValues, LookupWebId, LookupList, LookupField = 'Title', MaxLength, RichText, SchemaXml } = element; const castTo = value => spFieldObject => clientContext.castTo(spFieldObject, value); const spObject = pipe([ ifThen(isFilled)([ ifThen(constant(MaxLength))([stringReplace(/MaxLength="\d+"/)(`MaxLength="${MaxLength}"`)]), ifThen(constant(MaxLength && Type === 'Text'))([ constant(`<Field Type="${Type}" DisplayName="${Title}" MaxLength="${MaxLength}"/>`), constant(`<Field Type="${Type}" DisplayName="${Title}"/>`) ]) ]), addFieldAsXml(this.getSPObjectCollection(clientContext)), overstep( setFields({ set_defaultValue: element.DefaultValue, set_description: element.Description, set_direction: element.Direction, set_enforceUniqueValues: element.EnforceUniqueValues, set_fieldTypeKind: element.FieldTypeKind, set_group: element.Group, set_hidden: element.Hidden || undefined, set_indexed: element.Indexed, set_jsLink: element.JsLink, set_objectVersion: element.ObjectVersion, set_readOnlyField: element.ReadOnlyField, set_required: element.Required, set_schemaXml: element.SchemaXml ? element.SchemaXml.replace(/\sID="{[^}]+}"/, '') : undefined, set_staticName: element.StaticName, set_title: element[KEY_PROP$1], set_typeAsString: element.TypeAsString, set_validationFormula: element.ValidationFormula || undefined, set_validationMessage: element.ValidationMessage || undefined }) ), switchCase(constant(Type))({ Text: castTo(SP.FieldText), Note: pipe([ castTo(SP.FieldMultiLineText), overstep(ifThen(constant(RichText))([method('set_richText')(true)])) ]), Likes: castTo(SP.FieldNumber), Number: castTo(SP.FieldNumber), Boolean: castTo(SP.Field), Choice: castTo(AllowMultipleValues ? SP.FieldMultiChoice : SP.FieldChoice), DateTime: castTo(SP.FieldDateTime), URL: castTo(SP.FieldUrl), RatingCount: castTo(SP.FieldRatingScale), AverageRating: castTo(SP.FieldRatingScale), Lookup: pipe([ castTo(SP.FieldLookup), overstep( pipe([ method('set_lookupWebId')(LookupWebId), method('set_lookupList')(LookupList), method('set_lookupField')(LookupField), ifThen(constant(AllowMultipleValues))([method('set_allowMultipleValues')(true)]) ]) ) ]), LookupMulti: pipe([ castTo(SP.FieldLookup), overstep( pipe([ method('set_lookupWebId')(LookupWebId), method('set_lookupList')(LookupList), method('set_lookupField')(LookupField), method('set_allowMultipleValues')(true) ]) ) ]), User: pipe([ ca