@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.
Files changed (310) hide show
  1. package/LICENSE +21 -0
  2. package/dist/_dependencies.d.ts +1 -0
  3. package/dist/_dependencies.js +8 -0
  4. package/dist/_dependencies.js.map +1 -0
  5. package/dist/helpers/Guid.d.ts +119 -0
  6. package/dist/helpers/Guid.js +183 -0
  7. package/dist/helpers/Guid.js.map +1 -0
  8. package/dist/helpers/_dependencies.d.ts +2 -0
  9. package/dist/helpers/_dependencies.js +21 -0
  10. package/dist/helpers/_dependencies.js.map +1 -0
  11. package/dist/helpers/base64.d.ts +8 -0
  12. package/dist/helpers/base64.js +178 -0
  13. package/dist/helpers/base64.js.map +1 -0
  14. package/dist/helpers/browser.d.ts +144 -0
  15. package/dist/helpers/browser.js +1200 -0
  16. package/dist/helpers/browser.js.map +1 -0
  17. package/dist/helpers/browserinfo.d.ts +23 -0
  18. package/dist/helpers/browserinfo.js +215 -0
  19. package/dist/helpers/browserinfo.js.map +1 -0
  20. package/dist/helpers/collections.base.d.ts +128 -0
  21. package/dist/helpers/collections.base.js +430 -0
  22. package/dist/helpers/collections.base.js.map +1 -0
  23. package/dist/helpers/collections.d.ts +18 -0
  24. package/dist/helpers/collections.js +99 -0
  25. package/dist/helpers/collections.js.map +1 -0
  26. package/dist/helpers/color.d.ts +11 -0
  27. package/dist/helpers/color.js +57 -0
  28. package/dist/helpers/color.js.map +1 -0
  29. package/dist/helpers/cookies.d.ts +6 -0
  30. package/dist/helpers/cookies.js +56 -0
  31. package/dist/helpers/cookies.js.map +1 -0
  32. package/dist/helpers/date.d.ts +43 -0
  33. package/dist/helpers/date.js +158 -0
  34. package/dist/helpers/date.js.map +1 -0
  35. package/dist/helpers/debug.d.ts +33 -0
  36. package/dist/helpers/debug.js +177 -0
  37. package/dist/helpers/debug.js.map +1 -0
  38. package/dist/helpers/emails.d.ts +2 -0
  39. package/dist/helpers/emails.js +10 -0
  40. package/dist/helpers/emails.js.map +1 -0
  41. package/dist/helpers/eval.d.ts +1 -0
  42. package/dist/helpers/eval.js +10 -0
  43. package/dist/helpers/eval.js.map +1 -0
  44. package/dist/helpers/file.d.ts +11 -0
  45. package/dist/helpers/file.js +55 -0
  46. package/dist/helpers/file.js.map +1 -0
  47. package/dist/helpers/flatted.d.ts +20 -0
  48. package/dist/helpers/flatted.js +135 -0
  49. package/dist/helpers/flatted.js.map +1 -0
  50. package/dist/helpers/functions.d.ts +4 -0
  51. package/dist/helpers/functions.js +17 -0
  52. package/dist/helpers/functions.js.map +1 -0
  53. package/dist/helpers/graph/calendar.types.d.ts +3 -0
  54. package/dist/helpers/graph/calendar.types.js +15 -0
  55. package/dist/helpers/graph/calendar.types.js.map +1 -0
  56. package/dist/helpers/http.d.ts +25 -0
  57. package/dist/helpers/http.js +70 -0
  58. package/dist/helpers/http.js.map +1 -0
  59. package/dist/helpers/images.d.ts +16 -0
  60. package/dist/helpers/images.js +21 -0
  61. package/dist/helpers/images.js.map +1 -0
  62. package/dist/helpers/index.d.ts +29 -0
  63. package/dist/helpers/index.js +46 -0
  64. package/dist/helpers/index.js.map +1 -0
  65. package/dist/helpers/json.d.ts +3 -0
  66. package/dist/helpers/json.js +44 -0
  67. package/dist/helpers/json.js.map +1 -0
  68. package/dist/helpers/md5.d.ts +5 -0
  69. package/dist/helpers/md5.js +172 -0
  70. package/dist/helpers/md5.js.map +1 -0
  71. package/dist/helpers/objects.d.ts +49 -0
  72. package/dist/helpers/objects.js +271 -0
  73. package/dist/helpers/objects.js.map +1 -0
  74. package/dist/helpers/promises.d.ts +14 -0
  75. package/dist/helpers/promises.js +112 -0
  76. package/dist/helpers/promises.js.map +1 -0
  77. package/dist/helpers/random.d.ts +2 -0
  78. package/dist/helpers/random.js +32 -0
  79. package/dist/helpers/random.js.map +1 -0
  80. package/dist/helpers/scheduler/scheduler.d.ts +39 -0
  81. package/dist/helpers/scheduler/scheduler.js +109 -0
  82. package/dist/helpers/scheduler/scheduler.js.map +1 -0
  83. package/dist/helpers/sharepoint.d.ts +112 -0
  84. package/dist/helpers/sharepoint.js +629 -0
  85. package/dist/helpers/sharepoint.js.map +1 -0
  86. package/dist/helpers/strings.d.ts +56 -0
  87. package/dist/helpers/strings.js +282 -0
  88. package/dist/helpers/strings.js.map +1 -0
  89. package/dist/helpers/typecheckers.d.ts +56 -0
  90. package/dist/helpers/typecheckers.js +274 -0
  91. package/dist/helpers/typecheckers.js.map +1 -0
  92. package/dist/helpers/url.d.ts +46 -0
  93. package/dist/helpers/url.js +199 -0
  94. package/dist/helpers/url.js.map +1 -0
  95. package/dist/helpers/urlhelper.d.ts +16 -0
  96. package/dist/helpers/urlhelper.js +96 -0
  97. package/dist/helpers/urlhelper.js.map +1 -0
  98. package/dist/index.d.ts +15 -0
  99. package/dist/index.js +37 -0
  100. package/dist/index.js.map +1 -0
  101. package/dist/types/common.types.d.ts +19 -0
  102. package/dist/types/common.types.js +4 -0
  103. package/dist/types/common.types.js.map +1 -0
  104. package/dist/types/flatted.types.d.ts +49 -0
  105. package/dist/types/flatted.types.js +3 -0
  106. package/dist/types/flatted.types.js.map +1 -0
  107. package/dist/types/globals.types.d.ts +6 -0
  108. package/dist/types/globals.types.js +3 -0
  109. package/dist/types/globals.types.js.map +1 -0
  110. package/dist/types/graph/calendar.types.d.ts +79 -0
  111. package/dist/types/graph/calendar.types.js +3 -0
  112. package/dist/types/graph/calendar.types.js.map +1 -0
  113. package/dist/types/graph/index.d.ts +1 -0
  114. package/dist/types/graph/index.js +18 -0
  115. package/dist/types/graph/index.js.map +1 -0
  116. package/dist/types/index.d.ts +11 -0
  117. package/dist/types/index.js +28 -0
  118. package/dist/types/index.js.map +1 -0
  119. package/dist/types/knownscript.types.d.ts +22 -0
  120. package/dist/types/knownscript.types.js +3 -0
  121. package/dist/types/knownscript.types.js.map +1 -0
  122. package/dist/types/libs/datajs.types.d.ts +29 -0
  123. package/dist/types/libs/datajs.types.js +3 -0
  124. package/dist/types/libs/datajs.types.js.map +1 -0
  125. package/dist/types/libs/ics.types.d.ts +29 -0
  126. package/dist/types/libs/ics.types.js +3 -0
  127. package/dist/types/libs/ics.types.js.map +1 -0
  128. package/dist/types/libs/index.d.ts +3 -0
  129. package/dist/types/libs/index.js +20 -0
  130. package/dist/types/libs/index.js.map +1 -0
  131. package/dist/types/libs/msal.types.d.ts +33 -0
  132. package/dist/types/libs/msal.types.js +63 -0
  133. package/dist/types/libs/msal.types.js.map +1 -0
  134. package/dist/types/locales.d.ts +122 -0
  135. package/dist/types/locales.js +1 -0
  136. package/dist/types/locales.js.map +1 -0
  137. package/dist/types/localstoragecache.types.d.ts +8 -0
  138. package/dist/types/localstoragecache.types.js +3 -0
  139. package/dist/types/localstoragecache.types.js.map +1 -0
  140. package/dist/types/moment.d.ts +6 -0
  141. package/dist/types/moment.js +1 -0
  142. package/dist/types/moment.js.map +1 -0
  143. package/dist/types/regex.types.d.ts +14 -0
  144. package/dist/types/regex.types.js +3 -0
  145. package/dist/types/regex.types.js.map +1 -0
  146. package/dist/types/rest.types.d.ts +81 -0
  147. package/dist/types/rest.types.js +24 -0
  148. package/dist/types/rest.types.js.map +1 -0
  149. package/dist/types/sharepoint.types.d.ts +1432 -0
  150. package/dist/types/sharepoint.types.js +629 -0
  151. package/dist/types/sharepoint.types.js.map +1 -0
  152. package/dist/types/sharepoint.utils.types.d.ts +246 -0
  153. package/dist/types/sharepoint.utils.types.js +26 -0
  154. package/dist/types/sharepoint.utils.types.js.map +1 -0
  155. package/dist/utils/_dependencies.d.ts +3 -0
  156. package/dist/utils/_dependencies.js +24 -0
  157. package/dist/utils/_dependencies.js.map +1 -0
  158. package/dist/utils/base64.d.ts +2 -0
  159. package/dist/utils/base64.js +41 -0
  160. package/dist/utils/base64.js.map +1 -0
  161. package/dist/utils/consolelogger.d.ts +73 -0
  162. package/dist/utils/consolelogger.js +281 -0
  163. package/dist/utils/consolelogger.js.map +1 -0
  164. package/dist/utils/date.d.ts +10 -0
  165. package/dist/utils/date.js +30 -0
  166. package/dist/utils/date.js.map +1 -0
  167. package/dist/utils/emails.d.ts +2 -0
  168. package/dist/utils/emails.js +24 -0
  169. package/dist/utils/emails.js.map +1 -0
  170. package/dist/utils/index.d.ts +13 -0
  171. package/dist/utils/index.js +31 -0
  172. package/dist/utils/index.js.map +1 -0
  173. package/dist/utils/knownscript.d.ts +99 -0
  174. package/dist/utils/knownscript.js +261 -0
  175. package/dist/utils/knownscript.js.map +1 -0
  176. package/dist/utils/localstoragecache.d.ts +19 -0
  177. package/dist/utils/localstoragecache.js +372 -0
  178. package/dist/utils/localstoragecache.js.map +1 -0
  179. package/dist/utils/rest.d.ts +17 -0
  180. package/dist/utils/rest.js +402 -0
  181. package/dist/utils/rest.js.map +1 -0
  182. package/dist/utils/script.d.ts +33 -0
  183. package/dist/utils/script.js +169 -0
  184. package/dist/utils/script.js.map +1 -0
  185. package/dist/utils/sharepoint.rest/common.d.ts +32 -0
  186. package/dist/utils/sharepoint.rest/common.js +146 -0
  187. package/dist/utils/sharepoint.rest/common.js.map +1 -0
  188. package/dist/utils/sharepoint.rest/date.d.ts +2 -0
  189. package/dist/utils/sharepoint.rest/date.js +57 -0
  190. package/dist/utils/sharepoint.rest/date.js.map +1 -0
  191. package/dist/utils/sharepoint.rest/file.folder.d.ts +58 -0
  192. package/dist/utils/sharepoint.rest/file.folder.js +305 -0
  193. package/dist/utils/sharepoint.rest/file.folder.js.map +1 -0
  194. package/dist/utils/sharepoint.rest/index.d.ts +11 -0
  195. package/dist/utils/sharepoint.rest/index.js +28 -0
  196. package/dist/utils/sharepoint.rest/index.js.map +1 -0
  197. package/dist/utils/sharepoint.rest/item.d.ts +81 -0
  198. package/dist/utils/sharepoint.rest/item.js +444 -0
  199. package/dist/utils/sharepoint.rest/item.js.map +1 -0
  200. package/dist/utils/sharepoint.rest/list.d.ts +228 -0
  201. package/dist/utils/sharepoint.rest/list.js +868 -0
  202. package/dist/utils/sharepoint.rest/list.js.map +1 -0
  203. package/dist/utils/sharepoint.rest/listutils/GetListItemsByCaml.d.ts +19 -0
  204. package/dist/utils/sharepoint.rest/listutils/GetListItemsByCaml.js +629 -0
  205. package/dist/utils/sharepoint.rest/listutils/GetListItemsByCaml.js.map +1 -0
  206. package/dist/utils/sharepoint.rest/listutils/GetListItemsById.d.ts +14 -0
  207. package/dist/utils/sharepoint.rest/listutils/GetListItemsById.js +222 -0
  208. package/dist/utils/sharepoint.rest/listutils/GetListItemsById.js.map +1 -0
  209. package/dist/utils/sharepoint.rest/listutils/common.d.ts +3 -0
  210. package/dist/utils/sharepoint.rest/listutils/common.js +198 -0
  211. package/dist/utils/sharepoint.rest/listutils/common.js.map +1 -0
  212. package/dist/utils/sharepoint.rest/user-search.d.ts +76 -0
  213. package/dist/utils/sharepoint.rest/user-search.js +239 -0
  214. package/dist/utils/sharepoint.rest/user-search.js.map +1 -0
  215. package/dist/utils/sharepoint.rest/user.d.ts +71 -0
  216. package/dist/utils/sharepoint.rest/user.js +404 -0
  217. package/dist/utils/sharepoint.rest/user.js.map +1 -0
  218. package/dist/utils/sharepoint.rest/web.d.ts +107 -0
  219. package/dist/utils/sharepoint.rest/web.js +929 -0
  220. package/dist/utils/sharepoint.rest/web.js.map +1 -0
  221. package/dist/utils/sod.d.ts +29 -0
  222. package/dist/utils/sod.js +177 -0
  223. package/dist/utils/sod.js.map +1 -0
  224. package/package.json +60 -0
  225. package/readme.md +13 -0
  226. package/src/_dependencies.ts +2 -0
  227. package/src/helpers/Guid.ts +182 -0
  228. package/src/helpers/_dependencies.ts +3 -0
  229. package/src/helpers/base64.ts +174 -0
  230. package/src/helpers/browser.test.js +9 -0
  231. package/src/helpers/browser.ts +1299 -0
  232. package/src/helpers/browserinfo.ts +293 -0
  233. package/src/helpers/collections.base.test.js +26 -0
  234. package/src/helpers/collections.base.ts +439 -0
  235. package/src/helpers/collections.ts +108 -0
  236. package/src/helpers/color.ts +55 -0
  237. package/src/helpers/cookies.ts +55 -0
  238. package/src/helpers/date.test.js +97 -0
  239. package/src/helpers/date.ts +163 -0
  240. package/src/helpers/debug.ts +187 -0
  241. package/src/helpers/emails.ts +7 -0
  242. package/src/helpers/eval.ts +5 -0
  243. package/src/helpers/file.test.js +51 -0
  244. package/src/helpers/file.ts +59 -0
  245. package/src/helpers/flatted.ts +150 -0
  246. package/src/helpers/functions.ts +17 -0
  247. package/src/helpers/graph/calendar.types.ts +11 -0
  248. package/src/helpers/http.ts +70 -0
  249. package/src/helpers/images.ts +23 -0
  250. package/src/helpers/index.ts +29 -0
  251. package/src/helpers/json.ts +39 -0
  252. package/src/helpers/md5.ts +190 -0
  253. package/src/helpers/objects.test.js +27 -0
  254. package/src/helpers/objects.ts +256 -0
  255. package/src/helpers/promises.test.js +18 -0
  256. package/src/helpers/promises.ts +102 -0
  257. package/src/helpers/random.ts +27 -0
  258. package/src/helpers/scheduler/scheduler.test.js +104 -0
  259. package/src/helpers/scheduler/scheduler.ts +132 -0
  260. package/src/helpers/sharepoint.ts +681 -0
  261. package/src/helpers/strings.test.js +43 -0
  262. package/src/helpers/strings.ts +288 -0
  263. package/src/helpers/typecheckers.test.js +35 -0
  264. package/src/helpers/typecheckers.ts +263 -0
  265. package/src/helpers/url.test.js +18 -0
  266. package/src/helpers/url.ts +202 -0
  267. package/src/helpers/urlhelper.ts +104 -0
  268. package/src/index.ts +24 -0
  269. package/src/types/common.types.ts +16 -0
  270. package/src/types/flatted.types.ts +60 -0
  271. package/src/types/globals.types.ts +7 -0
  272. package/src/types/graph/calendar.types.ts +81 -0
  273. package/src/types/graph/index.ts +1 -0
  274. package/src/types/index.ts +12 -0
  275. package/src/types/knownscript.types.ts +19 -0
  276. package/src/types/libs/datajs.types.ts +29 -0
  277. package/src/types/libs/ics.types.ts +31 -0
  278. package/src/types/libs/index.ts +4 -0
  279. package/src/types/libs/msal.types.ts +79 -0
  280. package/src/types/locales.ts +125 -0
  281. package/src/types/localstoragecache.types.ts +9 -0
  282. package/src/types/moment.ts +7 -0
  283. package/src/types/regex.types.ts +17 -0
  284. package/src/types/rest.types.ts +94 -0
  285. package/src/types/sharepoint.types.ts +1413 -0
  286. package/src/types/sharepoint.utils.types.ts +246 -0
  287. package/src/utils/_dependencies.ts +4 -0
  288. package/src/utils/base64.ts +27 -0
  289. package/src/utils/consolelogger.ts +315 -0
  290. package/src/utils/date.ts +36 -0
  291. package/src/utils/emails.ts +25 -0
  292. package/src/utils/index.ts +13 -0
  293. package/src/utils/knownscript.ts +280 -0
  294. package/src/utils/localstoragecache.ts +419 -0
  295. package/src/utils/rest.ts +465 -0
  296. package/src/utils/script.ts +168 -0
  297. package/src/utils/sharepoint.rest/common.ts +149 -0
  298. package/src/utils/sharepoint.rest/date.ts +61 -0
  299. package/src/utils/sharepoint.rest/file.folder.ts +368 -0
  300. package/src/utils/sharepoint.rest/index.ts +11 -0
  301. package/src/utils/sharepoint.rest/item.ts +456 -0
  302. package/src/utils/sharepoint.rest/list.ts +1144 -0
  303. package/src/utils/sharepoint.rest/listutils/GetListItemsByCaml.ts +750 -0
  304. package/src/utils/sharepoint.rest/listutils/GetListItemsById.ts +265 -0
  305. package/src/utils/sharepoint.rest/listutils/common.ts +202 -0
  306. package/src/utils/sharepoint.rest/user-search.ts +254 -0
  307. package/src/utils/sharepoint.rest/user.ts +447 -0
  308. package/src/utils/sharepoint.rest/web.ts +1031 -0
  309. package/src/utils/sod.ts +193 -0
  310. 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>: "&lt;View Scope='RecursiveAll'>&lt;Query>&lt;/Query>&lt;RowLimit>1000&lt;/RowLimit>&lt;/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
+ }