@kwiz/common 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/_dependencies.d.ts +1 -0
- package/dist/_dependencies.js +8 -0
- package/dist/_dependencies.js.map +1 -0
- package/dist/helpers/Guid.d.ts +119 -0
- package/dist/helpers/Guid.js +183 -0
- package/dist/helpers/Guid.js.map +1 -0
- package/dist/helpers/_dependencies.d.ts +2 -0
- package/dist/helpers/_dependencies.js +21 -0
- package/dist/helpers/_dependencies.js.map +1 -0
- package/dist/helpers/base64.d.ts +8 -0
- package/dist/helpers/base64.js +178 -0
- package/dist/helpers/base64.js.map +1 -0
- package/dist/helpers/browser.d.ts +144 -0
- package/dist/helpers/browser.js +1200 -0
- package/dist/helpers/browser.js.map +1 -0
- package/dist/helpers/browserinfo.d.ts +23 -0
- package/dist/helpers/browserinfo.js +215 -0
- package/dist/helpers/browserinfo.js.map +1 -0
- package/dist/helpers/collections.base.d.ts +128 -0
- package/dist/helpers/collections.base.js +430 -0
- package/dist/helpers/collections.base.js.map +1 -0
- package/dist/helpers/collections.d.ts +18 -0
- package/dist/helpers/collections.js +99 -0
- package/dist/helpers/collections.js.map +1 -0
- package/dist/helpers/color.d.ts +11 -0
- package/dist/helpers/color.js +57 -0
- package/dist/helpers/color.js.map +1 -0
- package/dist/helpers/cookies.d.ts +6 -0
- package/dist/helpers/cookies.js +56 -0
- package/dist/helpers/cookies.js.map +1 -0
- package/dist/helpers/date.d.ts +43 -0
- package/dist/helpers/date.js +158 -0
- package/dist/helpers/date.js.map +1 -0
- package/dist/helpers/debug.d.ts +33 -0
- package/dist/helpers/debug.js +177 -0
- package/dist/helpers/debug.js.map +1 -0
- package/dist/helpers/emails.d.ts +2 -0
- package/dist/helpers/emails.js +10 -0
- package/dist/helpers/emails.js.map +1 -0
- package/dist/helpers/eval.d.ts +1 -0
- package/dist/helpers/eval.js +10 -0
- package/dist/helpers/eval.js.map +1 -0
- package/dist/helpers/file.d.ts +11 -0
- package/dist/helpers/file.js +55 -0
- package/dist/helpers/file.js.map +1 -0
- package/dist/helpers/flatted.d.ts +20 -0
- package/dist/helpers/flatted.js +135 -0
- package/dist/helpers/flatted.js.map +1 -0
- package/dist/helpers/functions.d.ts +4 -0
- package/dist/helpers/functions.js +17 -0
- package/dist/helpers/functions.js.map +1 -0
- package/dist/helpers/graph/calendar.types.d.ts +3 -0
- package/dist/helpers/graph/calendar.types.js +15 -0
- package/dist/helpers/graph/calendar.types.js.map +1 -0
- package/dist/helpers/http.d.ts +25 -0
- package/dist/helpers/http.js +70 -0
- package/dist/helpers/http.js.map +1 -0
- package/dist/helpers/images.d.ts +16 -0
- package/dist/helpers/images.js +21 -0
- package/dist/helpers/images.js.map +1 -0
- package/dist/helpers/index.d.ts +29 -0
- package/dist/helpers/index.js +46 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/json.d.ts +3 -0
- package/dist/helpers/json.js +44 -0
- package/dist/helpers/json.js.map +1 -0
- package/dist/helpers/md5.d.ts +5 -0
- package/dist/helpers/md5.js +172 -0
- package/dist/helpers/md5.js.map +1 -0
- package/dist/helpers/objects.d.ts +49 -0
- package/dist/helpers/objects.js +271 -0
- package/dist/helpers/objects.js.map +1 -0
- package/dist/helpers/promises.d.ts +14 -0
- package/dist/helpers/promises.js +112 -0
- package/dist/helpers/promises.js.map +1 -0
- package/dist/helpers/random.d.ts +2 -0
- package/dist/helpers/random.js +32 -0
- package/dist/helpers/random.js.map +1 -0
- package/dist/helpers/scheduler/scheduler.d.ts +39 -0
- package/dist/helpers/scheduler/scheduler.js +109 -0
- package/dist/helpers/scheduler/scheduler.js.map +1 -0
- package/dist/helpers/sharepoint.d.ts +112 -0
- package/dist/helpers/sharepoint.js +629 -0
- package/dist/helpers/sharepoint.js.map +1 -0
- package/dist/helpers/strings.d.ts +56 -0
- package/dist/helpers/strings.js +282 -0
- package/dist/helpers/strings.js.map +1 -0
- package/dist/helpers/typecheckers.d.ts +56 -0
- package/dist/helpers/typecheckers.js +274 -0
- package/dist/helpers/typecheckers.js.map +1 -0
- package/dist/helpers/url.d.ts +46 -0
- package/dist/helpers/url.js +199 -0
- package/dist/helpers/url.js.map +1 -0
- package/dist/helpers/urlhelper.d.ts +16 -0
- package/dist/helpers/urlhelper.js +96 -0
- package/dist/helpers/urlhelper.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/types/common.types.d.ts +19 -0
- package/dist/types/common.types.js +4 -0
- package/dist/types/common.types.js.map +1 -0
- package/dist/types/flatted.types.d.ts +49 -0
- package/dist/types/flatted.types.js +3 -0
- package/dist/types/flatted.types.js.map +1 -0
- package/dist/types/globals.types.d.ts +6 -0
- package/dist/types/globals.types.js +3 -0
- package/dist/types/globals.types.js.map +1 -0
- package/dist/types/graph/calendar.types.d.ts +79 -0
- package/dist/types/graph/calendar.types.js +3 -0
- package/dist/types/graph/calendar.types.js.map +1 -0
- package/dist/types/graph/index.d.ts +1 -0
- package/dist/types/graph/index.js +18 -0
- package/dist/types/graph/index.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.js +28 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/knownscript.types.d.ts +22 -0
- package/dist/types/knownscript.types.js +3 -0
- package/dist/types/knownscript.types.js.map +1 -0
- package/dist/types/libs/datajs.types.d.ts +29 -0
- package/dist/types/libs/datajs.types.js +3 -0
- package/dist/types/libs/datajs.types.js.map +1 -0
- package/dist/types/libs/ics.types.d.ts +29 -0
- package/dist/types/libs/ics.types.js +3 -0
- package/dist/types/libs/ics.types.js.map +1 -0
- package/dist/types/libs/index.d.ts +3 -0
- package/dist/types/libs/index.js +20 -0
- package/dist/types/libs/index.js.map +1 -0
- package/dist/types/libs/msal.types.d.ts +33 -0
- package/dist/types/libs/msal.types.js +63 -0
- package/dist/types/libs/msal.types.js.map +1 -0
- package/dist/types/locales.d.ts +122 -0
- package/dist/types/locales.js +1 -0
- package/dist/types/locales.js.map +1 -0
- package/dist/types/localstoragecache.types.d.ts +8 -0
- package/dist/types/localstoragecache.types.js +3 -0
- package/dist/types/localstoragecache.types.js.map +1 -0
- package/dist/types/moment.d.ts +6 -0
- package/dist/types/moment.js +1 -0
- package/dist/types/moment.js.map +1 -0
- package/dist/types/regex.types.d.ts +14 -0
- package/dist/types/regex.types.js +3 -0
- package/dist/types/regex.types.js.map +1 -0
- package/dist/types/rest.types.d.ts +81 -0
- package/dist/types/rest.types.js +24 -0
- package/dist/types/rest.types.js.map +1 -0
- package/dist/types/sharepoint.types.d.ts +1432 -0
- package/dist/types/sharepoint.types.js +629 -0
- package/dist/types/sharepoint.types.js.map +1 -0
- package/dist/types/sharepoint.utils.types.d.ts +246 -0
- package/dist/types/sharepoint.utils.types.js +26 -0
- package/dist/types/sharepoint.utils.types.js.map +1 -0
- package/dist/utils/_dependencies.d.ts +3 -0
- package/dist/utils/_dependencies.js +24 -0
- package/dist/utils/_dependencies.js.map +1 -0
- package/dist/utils/base64.d.ts +2 -0
- package/dist/utils/base64.js +41 -0
- package/dist/utils/base64.js.map +1 -0
- package/dist/utils/consolelogger.d.ts +73 -0
- package/dist/utils/consolelogger.js +281 -0
- package/dist/utils/consolelogger.js.map +1 -0
- package/dist/utils/date.d.ts +10 -0
- package/dist/utils/date.js +30 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/emails.d.ts +2 -0
- package/dist/utils/emails.js +24 -0
- package/dist/utils/emails.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.js +31 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/knownscript.d.ts +99 -0
- package/dist/utils/knownscript.js +261 -0
- package/dist/utils/knownscript.js.map +1 -0
- package/dist/utils/localstoragecache.d.ts +19 -0
- package/dist/utils/localstoragecache.js +372 -0
- package/dist/utils/localstoragecache.js.map +1 -0
- package/dist/utils/rest.d.ts +17 -0
- package/dist/utils/rest.js +402 -0
- package/dist/utils/rest.js.map +1 -0
- package/dist/utils/script.d.ts +33 -0
- package/dist/utils/script.js +169 -0
- package/dist/utils/script.js.map +1 -0
- package/dist/utils/sharepoint.rest/common.d.ts +32 -0
- package/dist/utils/sharepoint.rest/common.js +146 -0
- package/dist/utils/sharepoint.rest/common.js.map +1 -0
- package/dist/utils/sharepoint.rest/date.d.ts +2 -0
- package/dist/utils/sharepoint.rest/date.js +57 -0
- package/dist/utils/sharepoint.rest/date.js.map +1 -0
- package/dist/utils/sharepoint.rest/file.folder.d.ts +58 -0
- package/dist/utils/sharepoint.rest/file.folder.js +305 -0
- package/dist/utils/sharepoint.rest/file.folder.js.map +1 -0
- package/dist/utils/sharepoint.rest/index.d.ts +11 -0
- package/dist/utils/sharepoint.rest/index.js +28 -0
- package/dist/utils/sharepoint.rest/index.js.map +1 -0
- package/dist/utils/sharepoint.rest/item.d.ts +81 -0
- package/dist/utils/sharepoint.rest/item.js +444 -0
- package/dist/utils/sharepoint.rest/item.js.map +1 -0
- package/dist/utils/sharepoint.rest/list.d.ts +228 -0
- package/dist/utils/sharepoint.rest/list.js +868 -0
- package/dist/utils/sharepoint.rest/list.js.map +1 -0
- package/dist/utils/sharepoint.rest/listutils/GetListItemsByCaml.d.ts +19 -0
- package/dist/utils/sharepoint.rest/listutils/GetListItemsByCaml.js +629 -0
- package/dist/utils/sharepoint.rest/listutils/GetListItemsByCaml.js.map +1 -0
- package/dist/utils/sharepoint.rest/listutils/GetListItemsById.d.ts +14 -0
- package/dist/utils/sharepoint.rest/listutils/GetListItemsById.js +222 -0
- package/dist/utils/sharepoint.rest/listutils/GetListItemsById.js.map +1 -0
- package/dist/utils/sharepoint.rest/listutils/common.d.ts +3 -0
- package/dist/utils/sharepoint.rest/listutils/common.js +198 -0
- package/dist/utils/sharepoint.rest/listutils/common.js.map +1 -0
- package/dist/utils/sharepoint.rest/user-search.d.ts +76 -0
- package/dist/utils/sharepoint.rest/user-search.js +239 -0
- package/dist/utils/sharepoint.rest/user-search.js.map +1 -0
- package/dist/utils/sharepoint.rest/user.d.ts +71 -0
- package/dist/utils/sharepoint.rest/user.js +404 -0
- package/dist/utils/sharepoint.rest/user.js.map +1 -0
- package/dist/utils/sharepoint.rest/web.d.ts +107 -0
- package/dist/utils/sharepoint.rest/web.js +929 -0
- package/dist/utils/sharepoint.rest/web.js.map +1 -0
- package/dist/utils/sod.d.ts +29 -0
- package/dist/utils/sod.js +177 -0
- package/dist/utils/sod.js.map +1 -0
- package/package.json +60 -0
- package/readme.md +13 -0
- package/src/_dependencies.ts +2 -0
- package/src/helpers/Guid.ts +182 -0
- package/src/helpers/_dependencies.ts +3 -0
- package/src/helpers/base64.ts +174 -0
- package/src/helpers/browser.test.js +9 -0
- package/src/helpers/browser.ts +1299 -0
- package/src/helpers/browserinfo.ts +293 -0
- package/src/helpers/collections.base.test.js +26 -0
- package/src/helpers/collections.base.ts +439 -0
- package/src/helpers/collections.ts +108 -0
- package/src/helpers/color.ts +55 -0
- package/src/helpers/cookies.ts +55 -0
- package/src/helpers/date.test.js +97 -0
- package/src/helpers/date.ts +163 -0
- package/src/helpers/debug.ts +187 -0
- package/src/helpers/emails.ts +7 -0
- package/src/helpers/eval.ts +5 -0
- package/src/helpers/file.test.js +51 -0
- package/src/helpers/file.ts +59 -0
- package/src/helpers/flatted.ts +150 -0
- package/src/helpers/functions.ts +17 -0
- package/src/helpers/graph/calendar.types.ts +11 -0
- package/src/helpers/http.ts +70 -0
- package/src/helpers/images.ts +23 -0
- package/src/helpers/index.ts +29 -0
- package/src/helpers/json.ts +39 -0
- package/src/helpers/md5.ts +190 -0
- package/src/helpers/objects.test.js +27 -0
- package/src/helpers/objects.ts +256 -0
- package/src/helpers/promises.test.js +18 -0
- package/src/helpers/promises.ts +102 -0
- package/src/helpers/random.ts +27 -0
- package/src/helpers/scheduler/scheduler.test.js +104 -0
- package/src/helpers/scheduler/scheduler.ts +132 -0
- package/src/helpers/sharepoint.ts +681 -0
- package/src/helpers/strings.test.js +43 -0
- package/src/helpers/strings.ts +288 -0
- package/src/helpers/typecheckers.test.js +35 -0
- package/src/helpers/typecheckers.ts +263 -0
- package/src/helpers/url.test.js +18 -0
- package/src/helpers/url.ts +202 -0
- package/src/helpers/urlhelper.ts +104 -0
- package/src/index.ts +24 -0
- package/src/types/common.types.ts +16 -0
- package/src/types/flatted.types.ts +60 -0
- package/src/types/globals.types.ts +7 -0
- package/src/types/graph/calendar.types.ts +81 -0
- package/src/types/graph/index.ts +1 -0
- package/src/types/index.ts +12 -0
- package/src/types/knownscript.types.ts +19 -0
- package/src/types/libs/datajs.types.ts +29 -0
- package/src/types/libs/ics.types.ts +31 -0
- package/src/types/libs/index.ts +4 -0
- package/src/types/libs/msal.types.ts +79 -0
- package/src/types/locales.ts +125 -0
- package/src/types/localstoragecache.types.ts +9 -0
- package/src/types/moment.ts +7 -0
- package/src/types/regex.types.ts +17 -0
- package/src/types/rest.types.ts +94 -0
- package/src/types/sharepoint.types.ts +1413 -0
- package/src/types/sharepoint.utils.types.ts +246 -0
- package/src/utils/_dependencies.ts +4 -0
- package/src/utils/base64.ts +27 -0
- package/src/utils/consolelogger.ts +315 -0
- package/src/utils/date.ts +36 -0
- package/src/utils/emails.ts +25 -0
- package/src/utils/index.ts +13 -0
- package/src/utils/knownscript.ts +280 -0
- package/src/utils/localstoragecache.ts +419 -0
- package/src/utils/rest.ts +465 -0
- package/src/utils/script.ts +168 -0
- package/src/utils/sharepoint.rest/common.ts +149 -0
- package/src/utils/sharepoint.rest/date.ts +61 -0
- package/src/utils/sharepoint.rest/file.folder.ts +368 -0
- package/src/utils/sharepoint.rest/index.ts +11 -0
- package/src/utils/sharepoint.rest/item.ts +456 -0
- package/src/utils/sharepoint.rest/list.ts +1144 -0
- package/src/utils/sharepoint.rest/listutils/GetListItemsByCaml.ts +750 -0
- package/src/utils/sharepoint.rest/listutils/GetListItemsById.ts +265 -0
- package/src/utils/sharepoint.rest/listutils/common.ts +202 -0
- package/src/utils/sharepoint.rest/user-search.ts +254 -0
- package/src/utils/sharepoint.rest/user.ts +447 -0
- package/src/utils/sharepoint.rest/web.ts +1031 -0
- package/src/utils/sod.ts +193 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
import { EnsureViewFields, GeListItemsFoldersBehaviour, GetOrderByFromCaml, IDictionary, IFieldInfoEX, IRestItem, IsLocalDev, RemoveOrderByFromCaml, chunkArray, encodeURIComponentEX, firstIndexOf, firstOrNull, getFieldOutputType, isDate, isNotEmptyArray, isNullOrEmptyArray, isNullOrEmptyString, isNullOrNaN, isNullOrUndefined, isNumeric, jsonTypes, makeUniqueArray, toHash } from "../../_dependencies";
|
|
2
|
+
import { ConsoleLogger } from "../../consolelogger";
|
|
3
|
+
import { GetJson } from "../../rest";
|
|
4
|
+
import { GetSiteUrl, __getSPRestErrorData } from "../common";
|
|
5
|
+
import { GetListFields, GetListRestUrl } from "../list";
|
|
6
|
+
import { SPServerLocalTimeToUTCSync } from "../web";
|
|
7
|
+
import { GetItemsById } from "./GetListItemsById";
|
|
8
|
+
import { SkipFields, __fixGetListItemsResults } from "./common";
|
|
9
|
+
|
|
10
|
+
const logger = ConsoleLogger.get("sharepoint.rest/list/GetListItemsByCaml");
|
|
11
|
+
|
|
12
|
+
interface ICamlOptions {
|
|
13
|
+
/** Optional, default: 1000. 0: get all items. */
|
|
14
|
+
rowLimit?: number;
|
|
15
|
+
/** Id, Title, Modified, FileLeafRef, FileDirRef, FileRef, FileSystemObjectType */
|
|
16
|
+
columns: string[];
|
|
17
|
+
foldersBehaviour?: GeListItemsFoldersBehaviour;
|
|
18
|
+
/** set query to get items from this folder only */
|
|
19
|
+
FolderServerRelativeUrl?: string;
|
|
20
|
+
refreshCache?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//Lookup threshold limit is 12 but we use a smaller number here to ensure there are no issues
|
|
24
|
+
const lookupOrUserFieldLimit = 11;
|
|
25
|
+
/** returns the items or NULL, never errors out since it is used in aggregator.
|
|
26
|
+
* set throwErrors = true if you want errors to be thrown instead of returning null.
|
|
27
|
+
* camlQuery: one of:
|
|
28
|
+
* - view.ViewQuery
|
|
29
|
+
* - wrapped view.ViewQuery in a <View>: "<View Scope='RecursiveAll'><Query></Query><RowLimit>1000</RowLimit></View>" or send rowLimit in options.
|
|
30
|
+
*/
|
|
31
|
+
export async function GetListItemsByCaml(siteUrl: string, listIdOrTitle: string, camlQuery: string, options: ICamlOptions): Promise<IRestItem[]> {
|
|
32
|
+
siteUrl = GetSiteUrl(siteUrl);
|
|
33
|
+
|
|
34
|
+
if (!camlQuery.toLowerCase().startsWith("<view")) {
|
|
35
|
+
camlQuery = `<View Scope='RecursiveAll'><Query>${camlQuery}</Query></View>`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let xmlParser = new DOMParser();
|
|
39
|
+
let xmlDoc = xmlParser.parseFromString(camlQuery, "text/xml");
|
|
40
|
+
let viewNode = xmlDoc.querySelector("View, view");
|
|
41
|
+
let queryNode = viewNode && viewNode.querySelector("Query, query");
|
|
42
|
+
let rowLimitNode = viewNode && viewNode.querySelector("RowLimit, rowlimit");
|
|
43
|
+
let viewFieldsNode = viewNode && viewNode.querySelector("ViewFields, viewfields");
|
|
44
|
+
|
|
45
|
+
let parseRowLimitNodeResult = _parseRowLimitNode(rowLimitNode, viewNode, options.rowLimit);
|
|
46
|
+
if (!isNullOrUndefined(parseRowLimitNodeResult)) {
|
|
47
|
+
options.rowLimit = parseRowLimitNodeResult.rowLimit;
|
|
48
|
+
camlQuery = parseRowLimitNodeResult.camlQuery;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let removeSingleAndConditionsResult = _removeSingleAndConditions(viewNode, queryNode);
|
|
52
|
+
if (!isNullOrUndefined(removeSingleAndConditionsResult)) {
|
|
53
|
+
camlQuery = removeSingleAndConditionsResult.camlQuery;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let getAllItems = isNullOrEmptyString(options.rowLimit) || options.rowLimit < 1;
|
|
57
|
+
let totalItemsInList = 99999;
|
|
58
|
+
|
|
59
|
+
let maxBatchSize = 5000;
|
|
60
|
+
let batchSize = options.rowLimit > 0 && options.rowLimit < maxBatchSize ? options.rowLimit : maxBatchSize;
|
|
61
|
+
let totalNumberOfItemsToGet = getAllItems ? totalItemsInList : options.rowLimit > maxBatchSize ? options.rowLimit : batchSize;
|
|
62
|
+
|
|
63
|
+
let requestUrl = `${GetListRestUrl(siteUrl, listIdOrTitle)}/GetItems?$expand=FieldValuesAsText`;
|
|
64
|
+
|
|
65
|
+
let allListFieldsHash = toHash(await GetListFields(siteUrl, listIdOrTitle), f => f.InternalName);
|
|
66
|
+
|
|
67
|
+
let expandFields: string[] = [];
|
|
68
|
+
|
|
69
|
+
let orderByStatement = GetOrderByFromCaml(camlQuery);
|
|
70
|
+
|
|
71
|
+
if (isNullOrUndefined(options.columns)) {
|
|
72
|
+
options.columns = [];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let columns = options.columns;
|
|
76
|
+
columns = _ensureOrderByColumns(orderByStatement, columns);
|
|
77
|
+
columns = _ensureViewFields(viewFieldsNode, columns, allListFieldsHash);
|
|
78
|
+
columns = _normalizeColumns(columns, allListFieldsHash);
|
|
79
|
+
|
|
80
|
+
if (columns.length > options.columns.length) {
|
|
81
|
+
logger.warn(`added ${columns.length - options.columns.length} to query`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
options.columns = columns;
|
|
85
|
+
|
|
86
|
+
// Store the result of processing the request
|
|
87
|
+
let rtrnProcessRequestResult: { items: IRestItem[]; postProcessOrderBy: boolean; needContentTypes: boolean };
|
|
88
|
+
|
|
89
|
+
let lookupOrUserFieldsInColumns = options.columns.filter((columnName) => {
|
|
90
|
+
let field = allListFieldsHash[columnName];
|
|
91
|
+
return _isLookupOrUserField(field);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
let isThrottled = lookupOrUserFieldsInColumns.length >= lookupOrUserFieldLimit;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
if (isThrottled) {
|
|
98
|
+
//ISSUE: 1565
|
|
99
|
+
rtrnProcessRequestResult = await _processLookupThresholdCamlRequest(
|
|
100
|
+
orderByStatement,
|
|
101
|
+
allListFieldsHash,
|
|
102
|
+
options,
|
|
103
|
+
camlQuery,
|
|
104
|
+
requestUrl,
|
|
105
|
+
expandFields,
|
|
106
|
+
siteUrl,
|
|
107
|
+
totalNumberOfItemsToGet,
|
|
108
|
+
batchSize);
|
|
109
|
+
} else {
|
|
110
|
+
rtrnProcessRequestResult = await _processNormalCamlRequest(
|
|
111
|
+
orderByStatement,
|
|
112
|
+
allListFieldsHash,
|
|
113
|
+
options,
|
|
114
|
+
camlQuery,
|
|
115
|
+
requestUrl,
|
|
116
|
+
expandFields,
|
|
117
|
+
siteUrl,
|
|
118
|
+
totalNumberOfItemsToGet,
|
|
119
|
+
batchSize);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const { items, needContentTypes, postProcessOrderBy } = rtrnProcessRequestResult
|
|
123
|
+
|
|
124
|
+
let itemsResult = __fixGetListItemsResults(siteUrl, listIdOrTitle, items, options.foldersBehaviour);
|
|
125
|
+
|
|
126
|
+
let itemsWithOutContentType: number[] = [];
|
|
127
|
+
if (needContentTypes) {
|
|
128
|
+
itemsResult.forEach((item) => {
|
|
129
|
+
if (isNullOrUndefined(item["ContentType"])) {
|
|
130
|
+
itemsWithOutContentType.push(item.Id);
|
|
131
|
+
} else if (!isNullOrUndefined(item["ContentType"].Name)) {
|
|
132
|
+
item["ContentType"] = item["ContentType"].Name;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (itemsWithOutContentType.length > 0) {
|
|
138
|
+
logger.time("Getting content types");
|
|
139
|
+
//Issue 1465 content types no longer come back from get items request...
|
|
140
|
+
//Make a separate request to get this info
|
|
141
|
+
let ctypes = (await GetItemsById(siteUrl, listIdOrTitle, itemsWithOutContentType, {
|
|
142
|
+
expand: ['ContentType/Name'],
|
|
143
|
+
select: ['ContentType/Name', 'Id'],
|
|
144
|
+
jsonMetadata: jsonTypes.nometadata
|
|
145
|
+
})) as any as { Id: string, ContentType: { Name: string } }[];
|
|
146
|
+
|
|
147
|
+
itemsResult.forEach(item => {
|
|
148
|
+
if (!isNullOrUndefined(ctypes[item.Id])) {
|
|
149
|
+
item["ContentType"] = ctypes[item.Id].ContentType.Name
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
logger.timeEnd("Getting content types");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (postProcessOrderBy) {
|
|
156
|
+
//re-apply sort
|
|
157
|
+
if (IsLocalDev) {
|
|
158
|
+
logger.table(itemsResult.map(i => {
|
|
159
|
+
let row = {
|
|
160
|
+
Id: i.Id,
|
|
161
|
+
Title: i.Title
|
|
162
|
+
};
|
|
163
|
+
orderByStatement.forEach(s => { row[`${s.Name} ${s.IsAscending ? 'asc' : 'desc'}`] = i[s.Name]; });
|
|
164
|
+
return row;
|
|
165
|
+
}), "before sort", true);
|
|
166
|
+
}
|
|
167
|
+
itemsResult.sort((a, b) => {
|
|
168
|
+
for (let i = 0; i < orderByStatement.length; i++) {
|
|
169
|
+
let ob = orderByStatement[i];
|
|
170
|
+
let v1 = a[ob.Name];
|
|
171
|
+
let v2 = b[ob.Name];
|
|
172
|
+
if (v1 === v2) {
|
|
173
|
+
//these are equal - continue to second sort statement
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
if (ob.IsAscending)
|
|
177
|
+
return (v1 > v2) ? 1 : -1;
|
|
178
|
+
else
|
|
179
|
+
return (v2 > v1) ? 1 : -1;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return 0;
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (IsLocalDev) {
|
|
186
|
+
logger.table(itemsResult.map(i => {
|
|
187
|
+
let row = {
|
|
188
|
+
Id: i.Id,
|
|
189
|
+
Title: i.Title
|
|
190
|
+
};
|
|
191
|
+
orderByStatement.forEach(s => { row[`${s.Name} ${s.IsAscending ? 'asc' : 'desc'}`] = i[s.Name]; });
|
|
192
|
+
return row;
|
|
193
|
+
}), "after sort", true);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return itemsResult;
|
|
199
|
+
} catch (ex) {
|
|
200
|
+
console.log(`isThrottled: ${isThrottled}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// (window as any).runtTest = true;
|
|
207
|
+
// window.setTimeout(() => {
|
|
208
|
+
// if ((window as any).runtTest == false) return;
|
|
209
|
+
// (window as any).runtTest = false;
|
|
210
|
+
// GetListItemsByCaml(null, "aec7756b-daa0-4da1-88ba-c66cb572e816", "", {
|
|
211
|
+
// columns: [],
|
|
212
|
+
// refreshCache: true
|
|
213
|
+
// }).then((r) => {
|
|
214
|
+
|
|
215
|
+
// });
|
|
216
|
+
// }, 500);
|
|
217
|
+
|
|
218
|
+
//ISSUE: 1565
|
|
219
|
+
async function _processLookupThresholdCamlRequest(
|
|
220
|
+
orderByStatement: { Name: string; IsAscending: boolean; }[],
|
|
221
|
+
allListFieldsHash: IDictionary<IFieldInfoEX>,
|
|
222
|
+
options: ICamlOptions,
|
|
223
|
+
camlQuery: string,
|
|
224
|
+
requestUrl: string,
|
|
225
|
+
expandFields: string[],
|
|
226
|
+
siteUrl: string,
|
|
227
|
+
totalNumberOfItemsToGet: number,
|
|
228
|
+
batchSize: number) {
|
|
229
|
+
let rtrnProcessRequestResult = {
|
|
230
|
+
items: [],
|
|
231
|
+
postProcessOrderBy: false,
|
|
232
|
+
needContentTypes: false
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
let orderByFields = orderByStatement.map((orderByField) => {
|
|
236
|
+
let field = allListFieldsHash[orderByField.Name];
|
|
237
|
+
return field;
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
let lookupOrUserFieldsInOrderBy = orderByFields.filter((orderByField) => {
|
|
241
|
+
return _isLookupOrUserField(orderByField);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
let lookupOrUserFieldsToChunk = options.columns.filter((columnName) => {
|
|
245
|
+
let field = allListFieldsHash[columnName];
|
|
246
|
+
if (_isLookupOrUserField(field)) {
|
|
247
|
+
let col = firstOrNull(lookupOrUserFieldsInOrderBy, (orderByField) => {
|
|
248
|
+
return field.InternalName !== orderByField.InternalName;
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return col === null;
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
let otherFieldNames = options.columns.filter((columnName) => {
|
|
257
|
+
let field = allListFieldsHash[columnName];
|
|
258
|
+
let exists = !isNullOrUndefined(field);
|
|
259
|
+
let isLookupField = exists && _isLookupOrUserField(field);
|
|
260
|
+
let isInOrderBy = exists && firstOrNull(orderByFields, (orderByField) => orderByField.InternalName === field.InternalName) !== null
|
|
261
|
+
return exists && !isLookupField && !isInOrderBy;
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
//Split the requests into equally chunked arrays based on the lookup field count
|
|
265
|
+
//add lookup fields in chunk but leave room to add lookup fields from the order by statement
|
|
266
|
+
//since they are mandatory
|
|
267
|
+
let requestChunks = chunkArray(lookupOrUserFieldsToChunk, lookupOrUserFieldLimit - lookupOrUserFieldsInOrderBy.length);
|
|
268
|
+
let otherFieldsChunkSize = Math.ceil(otherFieldNames.length / requestChunks.length);
|
|
269
|
+
let otherFieldsChunks = chunkArray(otherFieldNames, otherFieldsChunkSize);
|
|
270
|
+
|
|
271
|
+
requestChunks.forEach((chunk, index) => {
|
|
272
|
+
//Add all order by fields to each request, this will include the lookup
|
|
273
|
+
//fields from the order by statement that we left room for previously
|
|
274
|
+
requestChunks[index] = chunk.concat(orderByFields.map((orderByField) => {
|
|
275
|
+
return orderByField.InternalName;
|
|
276
|
+
}));
|
|
277
|
+
|
|
278
|
+
//Add the other fields but split them across the requests so we don't request duplicate data
|
|
279
|
+
if (otherFieldsChunks[index]) {
|
|
280
|
+
requestChunks[index] = chunk.concat(otherFieldsChunks[index]);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
//requestChunks should now have about the same number of fields in each chunk and each
|
|
285
|
+
//chunk will have all the order by fields.
|
|
286
|
+
let queries = requestChunks.map((requestChunk) => {
|
|
287
|
+
let camlQueryClone = camlQuery;
|
|
288
|
+
|
|
289
|
+
let processColumnsResult = _processColumns(requestChunk, expandFields, allListFieldsHash);
|
|
290
|
+
|
|
291
|
+
//Id field must be included in oder to merge the items correctly
|
|
292
|
+
let viewFields = processColumnsResult.viewFields;
|
|
293
|
+
if (viewFields.length && !viewFields.includes("Id")) {
|
|
294
|
+
viewFields.push("Id");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
let selectFields = processColumnsResult.selectFields
|
|
298
|
+
if (selectFields.length && !selectFields.includes("Id")) {
|
|
299
|
+
selectFields.push("Id");
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
rtrnProcessRequestResult.needContentTypes = rtrnProcessRequestResult.needContentTypes || processColumnsResult.needContentTypes;
|
|
303
|
+
|
|
304
|
+
expandFields = processColumnsResult.expandFields;
|
|
305
|
+
|
|
306
|
+
if (isNotEmptyArray(viewFields)) {
|
|
307
|
+
camlQueryClone = EnsureViewFields(camlQueryClone, viewFields, true);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// if (isDebug()) {
|
|
311
|
+
// let lfields = viewFields.filter((fieldName) => {
|
|
312
|
+
// let field = allListFieldsHash[fieldName];
|
|
313
|
+
// return _isLookupOrUserField(field);
|
|
314
|
+
// });
|
|
315
|
+
|
|
316
|
+
// let xmlDoc = new DOMParser().parseFromString(camlQueryClone, "text/xml");
|
|
317
|
+
// let viewNode = xmlDoc.querySelector("View, view");
|
|
318
|
+
// let viewFieldsNode = viewNode && viewNode.querySelector("ViewFields, viewfields");
|
|
319
|
+
|
|
320
|
+
// let viewFields2 = Array.from(viewFieldsNode.children).map((viewFieldNode) => {
|
|
321
|
+
// let name = viewFieldNode.getAttribute("Name") || viewFieldNode.getAttribute("name");
|
|
322
|
+
// return name;
|
|
323
|
+
// });
|
|
324
|
+
|
|
325
|
+
// let lfields2 = viewFields2.filter((fieldName) => {
|
|
326
|
+
// let field = allListFieldsHash[fieldName];
|
|
327
|
+
// return _isLookupOrUserField(field);
|
|
328
|
+
// });
|
|
329
|
+
|
|
330
|
+
// if (lfields2.length !== lfields.length) {
|
|
331
|
+
// logger.warn("Lookup fields in caml query do not match look up fields in view fields.");
|
|
332
|
+
// logger.warn(`Lookup fields in caml query: ${lfields2}`)
|
|
333
|
+
// logger.warn(`Lookup fields in in view fields: ${lfields}`)
|
|
334
|
+
// }
|
|
335
|
+
// }
|
|
336
|
+
|
|
337
|
+
// Prepare the REST URL with select fields
|
|
338
|
+
let restUrlWithSelect = requestUrl;
|
|
339
|
+
if (expandFields.length > 0) {
|
|
340
|
+
restUrlWithSelect += ',' + expandFields.join(',');
|
|
341
|
+
}
|
|
342
|
+
// Include the lookup user select fields with the other select fields
|
|
343
|
+
restUrlWithSelect += '&$select=' + selectFields.join(',');
|
|
344
|
+
return { camlQueryClone, restUrlWithSelect, viewFields };
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
let mergedItems: IRestItem[] = null;
|
|
348
|
+
for (let i = 0; i < queries.length; i++) {
|
|
349
|
+
const { camlQueryClone, restUrlWithSelect, viewFields } = queries[i];
|
|
350
|
+
|
|
351
|
+
let loopResult = await processRequestResult(requestUrl,
|
|
352
|
+
restUrlWithSelect,
|
|
353
|
+
camlQueryClone,
|
|
354
|
+
{ ...options, columns: viewFields },
|
|
355
|
+
siteUrl,
|
|
356
|
+
totalNumberOfItemsToGet,
|
|
357
|
+
batchSize,
|
|
358
|
+
orderByStatement);
|
|
359
|
+
|
|
360
|
+
if (isNullOrUndefined(mergedItems)) {
|
|
361
|
+
mergedItems = loopResult.items;
|
|
362
|
+
} else {
|
|
363
|
+
for (let restItemIndex = 0; restItemIndex < loopResult.items.length; restItemIndex++) {
|
|
364
|
+
//The item chunks (loopResult) should be in the same order as mergedItems because each request should have the
|
|
365
|
+
//same number of items returned in the same order. The only difference between requests is which fields are present.
|
|
366
|
+
//So request 1 will have the 1st set of fields, request 2 will have the 2nd set. etc.
|
|
367
|
+
//This means that the restItemIndex should be the same as existingItemIndex for each iteration. But, we do these extra
|
|
368
|
+
//checks just in case.
|
|
369
|
+
let restItem = loopResult.items[restItemIndex];
|
|
370
|
+
let existingItem = mergedItems[restItemIndex];
|
|
371
|
+
let existingItemIndex = restItemIndex;
|
|
372
|
+
if (isNullOrUndefined(existingItem) || existingItem.Id !== restItem.Id) {
|
|
373
|
+
existingItemIndex = firstIndexOf(mergedItems, (mergedItem) => {
|
|
374
|
+
return mergedItem.Id === restItem.Id;
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (existingItemIndex === -1) {
|
|
379
|
+
//We shouldn't get here. Each chunk should have the same items in the same order.
|
|
380
|
+
logger.warn("_processLookupThresholdCamlRequest results are out of sync");
|
|
381
|
+
mergedItems.push(restItem);
|
|
382
|
+
} else {
|
|
383
|
+
let existingItem = mergedItems[existingItemIndex];
|
|
384
|
+
let FieldValuesAsText = {
|
|
385
|
+
...(existingItem.FieldValuesAsText || {}),
|
|
386
|
+
...(restItem.FieldValuesAsText || {})
|
|
387
|
+
};
|
|
388
|
+
let FieldValuesForEdit = {
|
|
389
|
+
...(existingItem.FieldValuesForEdit || {}),
|
|
390
|
+
...(restItem.FieldValuesForEdit || {})
|
|
391
|
+
};
|
|
392
|
+
existingItem = { ...existingItem, ...restItem };
|
|
393
|
+
existingItem.FieldValuesAsText = FieldValuesAsText;
|
|
394
|
+
existingItem.FieldValuesForEdit = FieldValuesForEdit;
|
|
395
|
+
mergedItems[existingItemIndex] = existingItem;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// only need to put this true if it happens once
|
|
401
|
+
if (loopResult.postProcessOrderBy) {
|
|
402
|
+
rtrnProcessRequestResult.postProcessOrderBy = true;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
rtrnProcessRequestResult.items = mergedItems;
|
|
407
|
+
|
|
408
|
+
return rtrnProcessRequestResult;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async function _processNormalCamlRequest(orderByStatement: { Name: string; IsAscending: boolean; }[],
|
|
412
|
+
allListFieldsHash: IDictionary<IFieldInfoEX>,
|
|
413
|
+
options: ICamlOptions,
|
|
414
|
+
camlQuery: string,
|
|
415
|
+
requestUrl: string,
|
|
416
|
+
expandFields: string[],
|
|
417
|
+
siteUrl: string,
|
|
418
|
+
totalNumberOfItemsToGet: number,
|
|
419
|
+
batchSize: number) {
|
|
420
|
+
let processColumnsResult = _processColumns(options.columns, expandFields, allListFieldsHash);
|
|
421
|
+
let viewFields = processColumnsResult.viewFields;
|
|
422
|
+
let selectFields = processColumnsResult.selectFields;
|
|
423
|
+
expandFields = processColumnsResult.expandFields;
|
|
424
|
+
let needContentTypes = processColumnsResult.needContentTypes;
|
|
425
|
+
|
|
426
|
+
if (isNotEmptyArray(viewFields)) {
|
|
427
|
+
camlQuery = EnsureViewFields(camlQuery, viewFields, true);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Prepare the REST URL with select fields
|
|
431
|
+
let restUrlWithSelect = requestUrl;
|
|
432
|
+
if (expandFields.length > 0) {
|
|
433
|
+
restUrlWithSelect += ',' + expandFields.join(',');
|
|
434
|
+
}
|
|
435
|
+
// Include the lookup user select fields with the other select fields
|
|
436
|
+
restUrlWithSelect += '&$select=' + selectFields.join(',');
|
|
437
|
+
|
|
438
|
+
// Process the request and get the result
|
|
439
|
+
let result = await processRequestResult(requestUrl, restUrlWithSelect, camlQuery, options, siteUrl, totalNumberOfItemsToGet, batchSize, orderByStatement);
|
|
440
|
+
|
|
441
|
+
return {
|
|
442
|
+
...result,
|
|
443
|
+
needContentTypes
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function _ensureViewFields(viewFieldsNode: Element, columns: string[], allListFieldsHash: IDictionary<IFieldInfoEX>) {
|
|
448
|
+
//ISSUE: 1565
|
|
449
|
+
//Cases
|
|
450
|
+
//1. Empty view fields element so ALL columns will be requested. We must include all list fields in
|
|
451
|
+
//columns parsing so that we get an accurate count of how many lookup/user fields there are
|
|
452
|
+
//2. View fields element with a some field names that must also be included in the column parsing so we add them here.
|
|
453
|
+
if (isNullOrUndefined(viewFieldsNode) && isNullOrEmptyArray(columns)) {
|
|
454
|
+
Object.keys(allListFieldsHash).forEach((fieldName) => {
|
|
455
|
+
let field = allListFieldsHash[fieldName];
|
|
456
|
+
if (!isNullOrUndefined(field)
|
|
457
|
+
&& !field.Hidden
|
|
458
|
+
&& !SkipFields.includes(fieldName.toLowerCase())) {
|
|
459
|
+
columns.push(field.InternalName);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
} else if (!isNullOrUndefined(viewFieldsNode)) {
|
|
463
|
+
let fieldRefNodes = Array.from(viewFieldsNode.querySelectorAll("FieldRef"));
|
|
464
|
+
if (isNotEmptyArray(fieldRefNodes)) {
|
|
465
|
+
fieldRefNodes.forEach((fieldRefNode) => {
|
|
466
|
+
let name = fieldRefNode.getAttribute("Name") || fieldRefNode.getAttribute("name");
|
|
467
|
+
if (!isNullOrEmptyString(name)) {
|
|
468
|
+
columns.push(name);
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return columns;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function _ensureOrderByColumns(orderByStatement: { Name: string; IsAscending: boolean; }[], columns: string[]) {
|
|
478
|
+
//Issue 548: Ensure that the order by field is in the view fields and columns collection so
|
|
479
|
+
//that paging works correctly when there is an order by clause
|
|
480
|
+
if (orderByStatement.length > 0 && !isNullOrEmptyString(orderByStatement[0].Name)) {
|
|
481
|
+
// just add them to columns, and we will add them to view fields below.
|
|
482
|
+
// camlQuery = EnsureViewFields(camlQuery, orderByStatement.orderBy.map(o => o.Name), false);
|
|
483
|
+
orderByStatement.forEach(o => {
|
|
484
|
+
if (columns.indexOf(o.Name) === -1) {
|
|
485
|
+
columns.push(o.Name);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return columns;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function _normalizeColumns(columns: string[], allListFieldsHash: IDictionary<IFieldInfoEX>) {
|
|
494
|
+
return makeUniqueArray(columns.map((column) => {
|
|
495
|
+
//some columns will come in lower case (from dvp), normalize them so that we can remove duplicates
|
|
496
|
+
let name = Object.keys(allListFieldsHash).filter((fieldName) => {
|
|
497
|
+
return fieldName.toLowerCase() === column.toLowerCase();
|
|
498
|
+
})[0];
|
|
499
|
+
if (!isNullOrEmptyString(name)) {
|
|
500
|
+
let field = allListFieldsHash[name];
|
|
501
|
+
return field;
|
|
502
|
+
}
|
|
503
|
+
return null;
|
|
504
|
+
}).filter((field) => {
|
|
505
|
+
return !isNullOrUndefined(field);
|
|
506
|
+
}).map((field) => {
|
|
507
|
+
return field.InternalName;
|
|
508
|
+
}).concat(['Title', 'Id', 'FileLeafRef', 'FileDirRef', 'FileRef', 'FileSystemObjectType']));
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function _removeSingleAndConditions(viewNode: Element, queryNode: Element) {
|
|
512
|
+
if (!isNullOrUndefined(viewNode.querySelector("And, and"))) {
|
|
513
|
+
try {
|
|
514
|
+
//Issue 8063: calendar list, will wrongly add a wrapping <and> statement for a single condition
|
|
515
|
+
//will result in error 500
|
|
516
|
+
//ie: <View Scope='RecursiveAll'><Query><Where><And><Eq><FieldRef Name=\"Title\" /><Value Type=\"Text\">Holiday</Value></Eq></And></Where>
|
|
517
|
+
//</Query><RowLimit>5000</RowLimit></View>
|
|
518
|
+
let whereNode = queryNode && queryNode.querySelector("Where, where");
|
|
519
|
+
|
|
520
|
+
if (!isNullOrUndefined(whereNode)) {
|
|
521
|
+
let firstCondition = whereNode.firstElementChild;
|
|
522
|
+
if (firstCondition.tagName.toLowerCase() === "and" && firstCondition.children.length < 2) {
|
|
523
|
+
//this is the bug, <and> tag must have 2 conditions - get rid of it!
|
|
524
|
+
whereNode.innerHTML = firstCondition.innerHTML;
|
|
525
|
+
return {
|
|
526
|
+
camlQuery: viewNode.outerHTML
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
} catch (e) { }
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function _parseRowLimitNode(rowLimitNode: Element, viewNode: Element, rowLimit: number) {
|
|
537
|
+
if (!isNullOrUndefined(rowLimitNode)) {
|
|
538
|
+
let value = rowLimitNode.textContent;
|
|
539
|
+
//if not provided by options - use it
|
|
540
|
+
if (isNullOrNaN(rowLimit) && isNumeric(value) && Number(value) > 0) {
|
|
541
|
+
rowLimit = Number(value);
|
|
542
|
+
}
|
|
543
|
+
//remove it
|
|
544
|
+
viewNode.removeChild(rowLimitNode);
|
|
545
|
+
return {
|
|
546
|
+
camlQuery: viewNode.outerHTML,
|
|
547
|
+
rowLimit: rowLimit
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function _processColumns(columns: string[], expandFields: string[], allListFieldsHash: IDictionary<IFieldInfoEX>) {
|
|
554
|
+
let thresholdLimitLookupCount = 0;
|
|
555
|
+
let thresholdLimitLookupHit = false;
|
|
556
|
+
let selectFields: string[] = [];
|
|
557
|
+
let viewFields: string[] = [];
|
|
558
|
+
let needContentTypes = false;
|
|
559
|
+
|
|
560
|
+
//column parsing
|
|
561
|
+
columns.forEach(viewField => {
|
|
562
|
+
if (viewField.toLowerCase() === 'contenttype' || viewField.toLowerCase() === 'contenttypeid') {
|
|
563
|
+
needContentTypes = true;
|
|
564
|
+
}
|
|
565
|
+
else if (viewField.toLowerCase() === '_moderationstatus') {
|
|
566
|
+
selectFields.push(`FieldValuesAsText/${viewField}`);
|
|
567
|
+
viewFields.push('_moderationstatus');
|
|
568
|
+
}
|
|
569
|
+
else if (viewField.toLowerCase() === '_moderationcomments') {
|
|
570
|
+
selectFields.push('OData_' + viewField);
|
|
571
|
+
viewFields.push('_moderationcomments');
|
|
572
|
+
}
|
|
573
|
+
else if (viewField.toLowerCase() === "filesystemobjecttype") {
|
|
574
|
+
selectFields.push("FileSystemObjectType");
|
|
575
|
+
}
|
|
576
|
+
else if (viewField.toLowerCase() === "fileref" || viewField.toLowerCase() === "filedirref") {
|
|
577
|
+
//treat them similar to lookup fields
|
|
578
|
+
selectFields.push(viewField);
|
|
579
|
+
selectFields.push(`FieldValuesAsText/${viewField}`);
|
|
580
|
+
viewFields.push(`${viewField}`);
|
|
581
|
+
viewFields.push(`${viewField}Id`);
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
//prefer to get columns not from FieldValuesAsText, unless special data type requires it (date, lookup, boolean, etc...)
|
|
585
|
+
//make the select url shorter
|
|
586
|
+
let foundField = allListFieldsHash[viewField];
|
|
587
|
+
if (foundField) {
|
|
588
|
+
let foundFieldInternalName = foundField.InternalName;
|
|
589
|
+
viewFields.push(foundFieldInternalName);
|
|
590
|
+
|
|
591
|
+
//Issue 828, 336
|
|
592
|
+
if (foundFieldInternalName.startsWith("_")) {
|
|
593
|
+
foundFieldInternalName = `OData_${foundFieldInternalName}`;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
let outputType = getFieldOutputType(foundField);
|
|
597
|
+
|
|
598
|
+
switch (outputType) {
|
|
599
|
+
case "Lookup":
|
|
600
|
+
case "LookupMulti":
|
|
601
|
+
case "User":
|
|
602
|
+
case "UserMulti":
|
|
603
|
+
thresholdLimitLookupCount += 1;
|
|
604
|
+
if (thresholdLimitLookupCount >= lookupOrUserFieldLimit) {
|
|
605
|
+
thresholdLimitLookupHit = true;
|
|
606
|
+
}
|
|
607
|
+
//lookup raw values comes with Id appended
|
|
608
|
+
selectFields.push(`FieldValuesAsText/${foundFieldInternalName}`);
|
|
609
|
+
selectFields.push(`${foundFieldInternalName}Id`);
|
|
610
|
+
break;
|
|
611
|
+
case "Boolean":
|
|
612
|
+
case "Attachments":
|
|
613
|
+
case "AllDayEvent":
|
|
614
|
+
case "Recurrence":
|
|
615
|
+
selectFields.push(`FieldValuesAsText/${foundFieldInternalName}`);
|
|
616
|
+
selectFields.push(foundFieldInternalName);
|
|
617
|
+
break;
|
|
618
|
+
default:
|
|
619
|
+
selectFields.push(foundFieldInternalName);
|
|
620
|
+
break;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
selectFields.push(viewField);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
if (needContentTypes) {
|
|
630
|
+
expandFields.push("ContentType");
|
|
631
|
+
selectFields.push("ContentType/Name");
|
|
632
|
+
selectFields.push("ContentTypeId");
|
|
633
|
+
viewFields.push("ContentTypeId");
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return {
|
|
637
|
+
thresholdLimitLookupHit,
|
|
638
|
+
viewFields: makeUniqueArray(viewFields),
|
|
639
|
+
selectFields: makeUniqueArray(selectFields),
|
|
640
|
+
expandFields: makeUniqueArray(expandFields),
|
|
641
|
+
needContentTypes
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function _isLookupOrUserField(field: IFieldInfoEX) {
|
|
646
|
+
if (isNullOrUndefined(field)) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
let outputType = getFieldOutputType(field);
|
|
650
|
+
|
|
651
|
+
switch (outputType) {
|
|
652
|
+
case "Lookup":
|
|
653
|
+
case "LookupMulti":
|
|
654
|
+
case "User":
|
|
655
|
+
case "UserMulti":
|
|
656
|
+
return true;
|
|
657
|
+
default:
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
async function processRequestResult(requestUrl: string, restUrlWithSelect: string, camlQuery: string, options: ICamlOptions, siteUrl: string, totalNumberOfItemsToGet: number, batchSize: number, orderByStatement): Promise<{ items: IRestItem[]; postProcessOrderBy: boolean; }> {
|
|
663
|
+
//issue 6150: if there are too many fields, url will be too long. just get all columns without adding a $select
|
|
664
|
+
if (restUrlWithSelect.length < 2000)
|
|
665
|
+
requestUrl = restUrlWithSelect;
|
|
666
|
+
|
|
667
|
+
let query: any = { ViewXml: camlQuery.replace("</View>", `<RowLimit>${batchSize}</RowLimit></View>`) };
|
|
668
|
+
|
|
669
|
+
if (!isNullOrEmptyString(options.FolderServerRelativeUrl))
|
|
670
|
+
query.FolderServerRelativeUrl = options.FolderServerRelativeUrl;
|
|
671
|
+
|
|
672
|
+
let data = { query: query };
|
|
673
|
+
|
|
674
|
+
let items: IRestItem[] = [];
|
|
675
|
+
//let triedWithoutViewFields = false;
|
|
676
|
+
let postProcessOrderBy = false;
|
|
677
|
+
do {
|
|
678
|
+
try {
|
|
679
|
+
let requestResult = await GetJson<{ value: IRestItem[]; }>(requestUrl, JSON.stringify(data),
|
|
680
|
+
{
|
|
681
|
+
allowCache: options.refreshCache !== true,
|
|
682
|
+
postCacheKey: JSON.stringify(data.query),
|
|
683
|
+
jsonMetadata: jsonTypes.nometadata,
|
|
684
|
+
spWebUrl: siteUrl
|
|
685
|
+
});
|
|
686
|
+
if (requestResult && requestResult.value)
|
|
687
|
+
items.push(...requestResult.value);
|
|
688
|
+
|
|
689
|
+
let itemsLeftToGet = totalNumberOfItemsToGet - items.length;
|
|
690
|
+
if (itemsLeftToGet > 0 &&//we need more items
|
|
691
|
+
requestResult.value.length === batchSize//we might have more on server since we got the full batch size we asked for
|
|
692
|
+
) {
|
|
693
|
+
let lastItem = items[items.length - 1];
|
|
694
|
+
let lastItemId = lastItem.Id;
|
|
695
|
+
let pagingInfoSort = "";
|
|
696
|
+
//Issue 7542 need to add order by value to the paging info if it is in the query
|
|
697
|
+
if (!postProcessOrderBy && orderByStatement && orderByStatement.length) {
|
|
698
|
+
let orderFieldName = orderByStatement[0].Name;
|
|
699
|
+
let orderFieldValue = lastItem[orderFieldName];
|
|
700
|
+
|
|
701
|
+
//if field is ID - do not do it.
|
|
702
|
+
if (orderFieldName.toLowerCase() !== "id" && !isNullOrUndefined(orderFieldValue)) {
|
|
703
|
+
//if value is date - we need it in ISO and in this format: yyyyMMdd HH:mm:ss
|
|
704
|
+
try {
|
|
705
|
+
//Numbers cast to date properly but they are not dates. ignore number values.
|
|
706
|
+
let orderFieldValueAsDate = isNumeric(orderFieldValue) ? null : new Date(orderFieldValue);
|
|
707
|
+
if (isDate(orderFieldValueAsDate)) {
|
|
708
|
+
try {
|
|
709
|
+
//issue 7599 date only field on different time zone...
|
|
710
|
+
orderFieldValue = SPServerLocalTimeToUTCSync(siteUrl, orderFieldValueAsDate).replace(/T/i, " ").replace(/Z/i, " ");
|
|
711
|
+
} catch (e) { }
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
} catch (e) { }
|
|
715
|
+
pagingInfoSort = `&p_${orderFieldName}=${encodeURIComponentEX(orderFieldValue)}`;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
data.query.ListItemCollectionPosition = {
|
|
719
|
+
"PagingInfo": `Paged=TRUE${pagingInfoSort}&p_ID=${lastItemId}`
|
|
720
|
+
};
|
|
721
|
+
if (itemsLeftToGet < batchSize)//the last batch should be smaller, update the row limit
|
|
722
|
+
data.query.ViewXml = camlQuery.replace("</View>", `<RowLimit>${itemsLeftToGet}</RowLimit></View>`);
|
|
723
|
+
}
|
|
724
|
+
else
|
|
725
|
+
data = null;
|
|
726
|
+
} catch (e) {
|
|
727
|
+
if (__getSPRestErrorData(e).code.indexOf('SPQueryThrottledException')) {
|
|
728
|
+
//test again - on awaiting score view, this will work but will ONLY return the order by fields...
|
|
729
|
+
// if (!triedWithoutViewFields) {
|
|
730
|
+
// //Our own issues list had too many lookup fields.
|
|
731
|
+
// logger.info("Query throttled, trying again without view fields... some fields might be missing from results.");
|
|
732
|
+
// triedWithoutViewFields = true;
|
|
733
|
+
// camlQuery = EnsureViewFields(camlQuery, orderByStatement.map(o => o.Name), false, true);
|
|
734
|
+
// data.query.ViewXml = camlQuery.replace("</View>", `<RowLimit>${batchSize}</RowLimit></View>`);
|
|
735
|
+
// }
|
|
736
|
+
// else
|
|
737
|
+
if (!postProcessOrderBy && orderByStatement.length > 0) {
|
|
738
|
+
logger.warn("Query throttled, trying again without order by...");
|
|
739
|
+
postProcessOrderBy = true;
|
|
740
|
+
camlQuery = RemoveOrderByFromCaml(camlQuery);
|
|
741
|
+
camlQuery = EnsureViewFields(camlQuery, [], false, true);
|
|
742
|
+
data.query.ViewXml = camlQuery.replace("</View>", `<RowLimit>${batchSize}</RowLimit></View>`);
|
|
743
|
+
}
|
|
744
|
+
else throw e;//still throttled? might be due to filter query
|
|
745
|
+
}
|
|
746
|
+
else throw e;//different error
|
|
747
|
+
}
|
|
748
|
+
} while (!isNullOrEmptyString(data));
|
|
749
|
+
return { items: items, postProcessOrderBy: postProcessOrderBy };
|
|
750
|
+
}
|