spx-com
Version:
Sharepoint 2013 Client Object Model Library
1,366 lines (1,256 loc) • 179 kB
JavaScript
(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