@esri/hub-common 9.48.0 → 10.0.0-next.2

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 (248) hide show
  1. package/dist/es2017/core/traits/WithCatalog.js +1 -0
  2. package/dist/es2017/core/traits/WithCatalog.js.map +1 -0
  3. package/dist/es2017/index.js +1 -0
  4. package/dist/es2017/index.js.map +1 -1
  5. package/dist/es2017/projects/HubProjects.js.map +1 -1
  6. package/dist/es2017/search/Catalog.js +346 -0
  7. package/dist/es2017/search/Catalog.js.map +1 -0
  8. package/dist/es2017/search/Collection.js +38 -19
  9. package/dist/es2017/search/Collection.js.map +1 -1
  10. package/dist/es2017/search/_internal/{ipredicate-utils.js → expandPredicate.js} +1 -1
  11. package/dist/es2017/search/_internal/expandPredicate.js.map +1 -0
  12. package/dist/es2017/search/_internal/hubSearchItems.js +3 -137
  13. package/dist/es2017/search/_internal/hubSearchItems.js.map +1 -1
  14. package/dist/es2017/search/_internal/index.js +0 -1
  15. package/dist/es2017/search/_internal/index.js.map +1 -1
  16. package/dist/es2017/search/_internal/portalSearchGroups.js +1 -2
  17. package/dist/es2017/search/_internal/portalSearchGroups.js.map +1 -1
  18. package/dist/es2017/search/_internal/portalSearchItems.js +5 -30
  19. package/dist/es2017/search/_internal/portalSearchItems.js.map +1 -1
  20. package/dist/es2017/search/_internal/portalSearchUsers.js +1 -2
  21. package/dist/es2017/search/_internal/portalSearchUsers.js.map +1 -1
  22. package/dist/es2017/search/fetchCatalog.js +46 -0
  23. package/dist/es2017/search/fetchCatalog.js.map +1 -0
  24. package/dist/es2017/search/hubSearch.js +1 -1
  25. package/dist/es2017/search/hubSearch.js.map +1 -1
  26. package/dist/es2017/search/index.js +3 -9
  27. package/dist/es2017/search/index.js.map +1 -1
  28. package/dist/es2017/search/serializeQueryForPortal.js +1 -1
  29. package/dist/es2017/search/serializeQueryForPortal.js.map +1 -1
  30. package/dist/es2017/search/types/index.js +0 -5
  31. package/dist/es2017/search/types/index.js.map +1 -1
  32. package/dist/es2017/search/upgradeCatalogSchema.js +66 -0
  33. package/dist/es2017/search/upgradeCatalogSchema.js.map +1 -0
  34. package/dist/es2017/search/utils.js +1 -207
  35. package/dist/es2017/search/utils.js.map +1 -1
  36. package/dist/es2017/types/IMessage.js +1 -0
  37. package/dist/es2017/types/IMessage.js.map +1 -0
  38. package/dist/es2017/types/index.js +2 -0
  39. package/dist/es2017/types/index.js.map +1 -0
  40. package/dist/es2017/types.js.map +1 -1
  41. package/dist/esm/core/traits/WithCatalog.js +1 -0
  42. package/dist/esm/core/traits/WithCatalog.js.map +1 -0
  43. package/dist/esm/index.js +1 -0
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/projects/HubProjects.js.map +1 -1
  46. package/dist/esm/search/Catalog.js +404 -0
  47. package/dist/esm/search/Catalog.js.map +1 -0
  48. package/dist/esm/search/Collection.js +40 -24
  49. package/dist/esm/search/Collection.js.map +1 -1
  50. package/dist/esm/search/_internal/{ipredicate-utils.js → expandPredicate.js} +1 -1
  51. package/dist/esm/search/_internal/expandPredicate.js.map +1 -0
  52. package/dist/esm/search/_internal/hubSearchItems.js +4 -146
  53. package/dist/esm/search/_internal/hubSearchItems.js.map +1 -1
  54. package/dist/esm/search/_internal/index.js +0 -1
  55. package/dist/esm/search/_internal/index.js.map +1 -1
  56. package/dist/esm/search/_internal/portalSearchGroups.js +1 -2
  57. package/dist/esm/search/_internal/portalSearchGroups.js.map +1 -1
  58. package/dist/esm/search/_internal/portalSearchItems.js +6 -30
  59. package/dist/esm/search/_internal/portalSearchItems.js.map +1 -1
  60. package/dist/esm/search/_internal/portalSearchUsers.js +1 -2
  61. package/dist/esm/search/_internal/portalSearchUsers.js.map +1 -1
  62. package/dist/esm/search/fetchCatalog.js +59 -0
  63. package/dist/esm/search/fetchCatalog.js.map +1 -0
  64. package/dist/esm/search/hubSearch.js +1 -1
  65. package/dist/esm/search/hubSearch.js.map +1 -1
  66. package/dist/esm/search/index.js +3 -9
  67. package/dist/esm/search/index.js.map +1 -1
  68. package/dist/esm/search/serializeQueryForPortal.js +1 -1
  69. package/dist/esm/search/serializeQueryForPortal.js.map +1 -1
  70. package/dist/esm/search/types/index.js +0 -5
  71. package/dist/esm/search/types/index.js.map +1 -1
  72. package/dist/esm/search/upgradeCatalogSchema.js +66 -0
  73. package/dist/esm/search/upgradeCatalogSchema.js.map +1 -0
  74. package/dist/esm/search/utils.js +1 -204
  75. package/dist/esm/search/utils.js.map +1 -1
  76. package/dist/esm/types/IMessage.js +1 -0
  77. package/dist/esm/types/IMessage.js.map +1 -0
  78. package/dist/esm/types/index.js +2 -0
  79. package/dist/esm/types/index.js.map +1 -0
  80. package/dist/esm/types.js.map +1 -1
  81. package/dist/node/{search/types/ICollection.js → core/traits/WithCatalog.js} +1 -1
  82. package/dist/node/core/traits/WithCatalog.js.map +1 -0
  83. package/dist/node/index.js +1 -0
  84. package/dist/node/index.js.map +1 -1
  85. package/dist/node/projects/HubProjects.js.map +1 -1
  86. package/dist/node/search/Catalog.js +350 -0
  87. package/dist/node/search/Catalog.js.map +1 -0
  88. package/dist/node/search/Collection.js +37 -18
  89. package/dist/node/search/Collection.js.map +1 -1
  90. package/dist/node/search/_internal/{ipredicate-utils.js → expandPredicate.js} +1 -1
  91. package/dist/node/search/_internal/expandPredicate.js.map +1 -0
  92. package/dist/node/search/_internal/hubSearchItems.js +4 -139
  93. package/dist/node/search/_internal/hubSearchItems.js.map +1 -1
  94. package/dist/node/search/_internal/index.js +0 -1
  95. package/dist/node/search/_internal/index.js.map +1 -1
  96. package/dist/node/search/_internal/portalSearchGroups.js +2 -3
  97. package/dist/node/search/_internal/portalSearchGroups.js.map +1 -1
  98. package/dist/node/search/_internal/portalSearchItems.js +6 -31
  99. package/dist/node/search/_internal/portalSearchItems.js.map +1 -1
  100. package/dist/node/search/_internal/portalSearchUsers.js +2 -3
  101. package/dist/node/search/_internal/portalSearchUsers.js.map +1 -1
  102. package/dist/node/search/fetchCatalog.js +50 -0
  103. package/dist/node/search/fetchCatalog.js.map +1 -0
  104. package/dist/node/search/hubSearch.js +1 -1
  105. package/dist/node/search/hubSearch.js.map +1 -1
  106. package/dist/node/search/index.js +3 -9
  107. package/dist/node/search/index.js.map +1 -1
  108. package/dist/node/search/serializeQueryForPortal.js +2 -2
  109. package/dist/node/search/serializeQueryForPortal.js.map +1 -1
  110. package/dist/node/search/types/index.js +0 -5
  111. package/dist/node/search/types/index.js.map +1 -1
  112. package/dist/node/search/upgradeCatalogSchema.js +71 -0
  113. package/dist/node/search/upgradeCatalogSchema.js.map +1 -0
  114. package/dist/node/search/utils.js +1 -213
  115. package/dist/node/search/utils.js.map +1 -1
  116. package/dist/node/{search/types/ICatalog.js → types/IMessage.js} +1 -1
  117. package/dist/node/types/IMessage.js.map +1 -0
  118. package/dist/node/types/index.js +5 -0
  119. package/dist/node/types/index.js.map +1 -0
  120. package/dist/node/types.js.map +1 -1
  121. package/dist/types/core/traits/WithCatalog.d.ts +7 -0
  122. package/dist/types/index.d.ts +1 -0
  123. package/dist/types/search/Catalog.d.ts +143 -0
  124. package/dist/types/search/Collection.d.ts +23 -2
  125. package/dist/types/search/_internal/{ipredicate-utils.d.ts → expandPredicate.d.ts} +0 -0
  126. package/dist/types/search/_internal/hubSearchItems.d.ts +3 -4
  127. package/dist/types/search/_internal/index.d.ts +0 -1
  128. package/dist/types/search/_internal/portalSearchItems.d.ts +15 -15
  129. package/dist/types/search/fetchCatalog.d.ts +10 -0
  130. package/dist/types/search/index.d.ts +3 -9
  131. package/dist/types/search/types/IHubSearchOptions.d.ts +5 -1
  132. package/dist/types/search/types/IHubSearchResponse.d.ts +3 -3
  133. package/dist/types/search/types/index.d.ts +0 -5
  134. package/dist/types/search/types/types.d.ts +0 -206
  135. package/dist/types/search/upgradeCatalogSchema.d.ts +12 -0
  136. package/dist/types/search/utils.d.ts +2 -58
  137. package/dist/types/types/IMessage.d.ts +32 -0
  138. package/dist/types/types/index.d.ts +1 -0
  139. package/dist/types/types.d.ts +0 -2
  140. package/dist/umd/common.umd.js +1374 -2450
  141. package/dist/umd/common.umd.js.map +1 -1
  142. package/package.json +1 -1
  143. package/dist/es2017/search/_internal/ipredicate-utils.js.map +0 -1
  144. package/dist/es2017/search/_internal/state.js +0 -155
  145. package/dist/es2017/search/_internal/state.js.map +0 -1
  146. package/dist/es2017/search/_searchContent.js +0 -116
  147. package/dist/es2017/search/_searchContent.js.map +0 -1
  148. package/dist/es2017/search/_searchGroups.js +0 -88
  149. package/dist/es2017/search/_searchGroups.js.map +0 -1
  150. package/dist/es2017/search/_searchUsers.js +0 -89
  151. package/dist/es2017/search/_searchUsers.js.map +0 -1
  152. package/dist/es2017/search/collectionState.js +0 -60
  153. package/dist/es2017/search/collectionState.js.map +0 -1
  154. package/dist/es2017/search/content-utils.js +0 -455
  155. package/dist/es2017/search/content-utils.js.map +0 -1
  156. package/dist/es2017/search/convertCatalog.js +0 -33
  157. package/dist/es2017/search/convertCatalog.js.map +0 -1
  158. package/dist/es2017/search/filter-utils.js +0 -31
  159. package/dist/es2017/search/filter-utils.js.map +0 -1
  160. package/dist/es2017/search/group-utils.js +0 -142
  161. package/dist/es2017/search/group-utils.js.map +0 -1
  162. package/dist/es2017/search/types/ICatalog.js +0 -1
  163. package/dist/es2017/search/types/ICatalog.js.map +0 -1
  164. package/dist/es2017/search/types/ICollection.js +0 -1
  165. package/dist/es2017/search/types/ICollection.js.map +0 -1
  166. package/dist/es2017/search/types/IFacet.js +0 -1
  167. package/dist/es2017/search/types/IFacet.js.map +0 -1
  168. package/dist/es2017/search/types/IFacetOption.js +0 -1
  169. package/dist/es2017/search/types/IFacetOption.js.map +0 -1
  170. package/dist/es2017/search/types/IHubApiSearchRequest.js +0 -1
  171. package/dist/es2017/search/types/IHubApiSearchRequest.js.map +0 -1
  172. package/dist/es2017/search/user-utils.js +0 -139
  173. package/dist/es2017/search/user-utils.js.map +0 -1
  174. package/dist/esm/search/_internal/ipredicate-utils.js.map +0 -1
  175. package/dist/esm/search/_internal/state.js +0 -155
  176. package/dist/esm/search/_internal/state.js.map +0 -1
  177. package/dist/esm/search/_searchContent.js +0 -118
  178. package/dist/esm/search/_searchContent.js.map +0 -1
  179. package/dist/esm/search/_searchGroups.js +0 -91
  180. package/dist/esm/search/_searchGroups.js.map +0 -1
  181. package/dist/esm/search/_searchUsers.js +0 -92
  182. package/dist/esm/search/_searchUsers.js.map +0 -1
  183. package/dist/esm/search/collectionState.js +0 -61
  184. package/dist/esm/search/collectionState.js.map +0 -1
  185. package/dist/esm/search/content-utils.js +0 -462
  186. package/dist/esm/search/content-utils.js.map +0 -1
  187. package/dist/esm/search/convertCatalog.js +0 -33
  188. package/dist/esm/search/convertCatalog.js.map +0 -1
  189. package/dist/esm/search/filter-utils.js +0 -31
  190. package/dist/esm/search/filter-utils.js.map +0 -1
  191. package/dist/esm/search/group-utils.js +0 -146
  192. package/dist/esm/search/group-utils.js.map +0 -1
  193. package/dist/esm/search/types/ICatalog.js +0 -1
  194. package/dist/esm/search/types/ICatalog.js.map +0 -1
  195. package/dist/esm/search/types/ICollection.js +0 -1
  196. package/dist/esm/search/types/ICollection.js.map +0 -1
  197. package/dist/esm/search/types/IFacet.js +0 -1
  198. package/dist/esm/search/types/IFacet.js.map +0 -1
  199. package/dist/esm/search/types/IFacetOption.js +0 -1
  200. package/dist/esm/search/types/IFacetOption.js.map +0 -1
  201. package/dist/esm/search/types/IHubApiSearchRequest.js +0 -1
  202. package/dist/esm/search/types/IHubApiSearchRequest.js.map +0 -1
  203. package/dist/esm/search/user-utils.js +0 -143
  204. package/dist/esm/search/user-utils.js.map +0 -1
  205. package/dist/node/search/_internal/ipredicate-utils.js.map +0 -1
  206. package/dist/node/search/_internal/state.js +0 -166
  207. package/dist/node/search/_internal/state.js.map +0 -1
  208. package/dist/node/search/_searchContent.js +0 -120
  209. package/dist/node/search/_searchContent.js.map +0 -1
  210. package/dist/node/search/_searchGroups.js +0 -92
  211. package/dist/node/search/_searchGroups.js.map +0 -1
  212. package/dist/node/search/_searchUsers.js +0 -93
  213. package/dist/node/search/_searchUsers.js.map +0 -1
  214. package/dist/node/search/collectionState.js +0 -65
  215. package/dist/node/search/collectionState.js.map +0 -1
  216. package/dist/node/search/content-utils.js +0 -466
  217. package/dist/node/search/content-utils.js.map +0 -1
  218. package/dist/node/search/convertCatalog.js +0 -37
  219. package/dist/node/search/convertCatalog.js.map +0 -1
  220. package/dist/node/search/filter-utils.js +0 -36
  221. package/dist/node/search/filter-utils.js.map +0 -1
  222. package/dist/node/search/group-utils.js +0 -148
  223. package/dist/node/search/group-utils.js.map +0 -1
  224. package/dist/node/search/types/ICatalog.js.map +0 -1
  225. package/dist/node/search/types/ICollection.js.map +0 -1
  226. package/dist/node/search/types/IFacet.js +0 -3
  227. package/dist/node/search/types/IFacet.js.map +0 -1
  228. package/dist/node/search/types/IFacetOption.js +0 -3
  229. package/dist/node/search/types/IFacetOption.js.map +0 -1
  230. package/dist/node/search/types/IHubApiSearchRequest.js +0 -3
  231. package/dist/node/search/types/IHubApiSearchRequest.js.map +0 -1
  232. package/dist/node/search/user-utils.js +0 -145
  233. package/dist/node/search/user-utils.js.map +0 -1
  234. package/dist/types/search/_internal/state.d.ts +0 -70
  235. package/dist/types/search/_searchContent.d.ts +0 -9
  236. package/dist/types/search/_searchGroups.d.ts +0 -17
  237. package/dist/types/search/_searchUsers.d.ts +0 -31
  238. package/dist/types/search/collectionState.d.ts +0 -19
  239. package/dist/types/search/content-utils.d.ts +0 -83
  240. package/dist/types/search/convertCatalog.d.ts +0 -6
  241. package/dist/types/search/filter-utils.d.ts +0 -13
  242. package/dist/types/search/group-utils.d.ts +0 -36
  243. package/dist/types/search/types/ICatalog.d.ts +0 -87
  244. package/dist/types/search/types/ICollection.d.ts +0 -28
  245. package/dist/types/search/types/IFacet.d.ts +0 -62
  246. package/dist/types/search/types/IFacetOption.d.ts +0 -30
  247. package/dist/types/search/types/IHubApiSearchRequest.d.ts +0 -16
  248. package/dist/types/search/user-utils.d.ts +0 -35
@@ -1,5 +1,5 @@
1
1
  /* @preserve
2
- * @esri/hub-common - v9.47.0 - Wed Jul 20 2022 22:15:24 GMT+0000 (Coordinated Universal Time)
2
+ * @esri/hub-common - v10.0.0-next.1 - Fri Jul 22 2022 18:15:55 GMT+0000 (Coordinated Universal Time)
3
3
  * Copyright (c) 2022 Environmental Systems Research Institute, Inc.
4
4
  * Apache-2.0
5
5
  */
@@ -13431,76 +13431,6 @@
13431
13431
  return api;
13432
13432
  }
13433
13433
  }
13434
- /**
13435
- * @private
13436
- * Merge two date ranges by taking the longest span
13437
- * @param dr1
13438
- * @param dr2
13439
- * @returns
13440
- */
13441
- function mergeDateRange(dr1, dr2) {
13442
- // TODO: Remove with _searchContent
13443
- var result = cloneObject$1(dr1);
13444
- // feels like there is a more concise way to do this...
13445
- if (dr2.from < dr1.from) {
13446
- result.from = dr2.from;
13447
- }
13448
- if (dr2.to > dr1.to) {
13449
- result.to = dr2.to;
13450
- }
13451
- return result;
13452
- }
13453
- /**
13454
- * @private
13455
- * Merge two [`MatchOptions`](../MatchOptions)
13456
- *
13457
- * Currently a naieve implementation where the arrays are simply merged
13458
- *
13459
- * @param mo1
13460
- * @param mo2
13461
- * @returns
13462
- */
13463
- function mergeMatchOptions(mo1, mo2) {
13464
- // TODO: Remove with _searchContent
13465
- var result = {};
13466
- // None of these props are required, so we can't just
13467
- // use Object.keys/.entries
13468
- var props = ["any", "all", "not", "exact"];
13469
- props.forEach(function (prop) {
13470
- var key = prop;
13471
- var merged = __spreadArrays(getMatchValue(mo1, key), getMatchValue(mo2, key));
13472
- if (merged.length) {
13473
- // remove any dupes and set on the return
13474
- result[key] = merged.filter(unique);
13475
- }
13476
- });
13477
- return result;
13478
- }
13479
- /**
13480
- * Get the value of a property on an IMatchOptions
13481
- *
13482
- * This is complex b/c all the props are optional, and
13483
- * they could be a simple string, or an array of strings.
13484
- *
13485
- * This function normalizes all that and returns an array,
13486
- * which may or may not be empty
13487
- * @param option
13488
- * @param key
13489
- * @returns
13490
- */
13491
- function getMatchValue(option, key) {
13492
- var matchValue = [];
13493
- if (option[key]) {
13494
- var val = option[key];
13495
- if (Array.isArray(val)) {
13496
- matchValue = val;
13497
- }
13498
- else {
13499
- matchValue = [val];
13500
- }
13501
- }
13502
- return matchValue;
13503
- }
13504
13434
  /**
13505
13435
  * @private
13506
13436
  * Convert a field value into a MatchOptions if it's not already one
@@ -13569,137 +13499,6 @@
13569
13499
  }
13570
13500
  return result;
13571
13501
  }
13572
- /**
13573
- * @private
13574
- * As a final `ISearchOptions` object gets created, many such objects are created, and
13575
- * need to be systematically "merged" so as to return consistently structured `q` and `filter`
13576
- * values.
13577
- * @param so1
13578
- * @param so2
13579
- * @param join
13580
- * @returns
13581
- */
13582
- function mergeSearchOptions$1(so1, so2, join) {
13583
- // TODO: Remove with _searchContent
13584
- Logger.warn("DEPRECATION: mergeSearchOptions will be removed. Work with IFilterGroups<\"group\"> and hubSearch() instead");
13585
- var result = cloneObject$1(so1);
13586
- var q = so2.q, filter = so2.filter;
13587
- if (q) {
13588
- result.q = (result.q ? " (" + result.q + " " + join + " " + q + ")" : q).trim();
13589
- }
13590
- if (filter) {
13591
- result.filter = (result.filter ? "(" + result.filter + " " + join + " " + filter + ")" : filter).trim();
13592
- }
13593
- return result;
13594
- }
13595
- /**
13596
- * @private
13597
- * Serialize a `MatchOptions` into `q` or `filter` on an `ISearchOptions`
13598
- * DEPRECATED: Serialization should be handled in filter-utils.ts
13599
- * @param key
13600
- * @param opts
13601
- * @returns
13602
- */
13603
- function serializeMatchOptions$1(key, opts) {
13604
- var result = {
13605
- q: "",
13606
- filter: "",
13607
- };
13608
- if (opts.exact) {
13609
- // defined separately for refactoring later
13610
- var userFilterableFields = [
13611
- "username",
13612
- "firstname",
13613
- "lastname",
13614
- "fullname",
13615
- "email",
13616
- ];
13617
- var itemFilterableFields = [
13618
- "title",
13619
- "tags",
13620
- "typekeywords",
13621
- "type",
13622
- "name",
13623
- "owner",
13624
- ];
13625
- var groupFilterableFields = ["title", "typekeywords", "owner"];
13626
- var filterableFields = __spreadArrays(userFilterableFields, itemFilterableFields, groupFilterableFields);
13627
- if (filterableFields.includes(key)) {
13628
- result.filter = serializeStringOrArray$1("AND", key, opts.exact);
13629
- }
13630
- else {
13631
- // Treat it the same as .all
13632
- if (typeof opts.exact === "string") {
13633
- if (!opts.all) {
13634
- opts.all = [];
13635
- }
13636
- if (typeof opts.all === "string") {
13637
- opts.all = [opts.all];
13638
- }
13639
- opts.all.push(opts.exact);
13640
- }
13641
- if (Array.isArray(opts.exact)) {
13642
- if (!opts.all) {
13643
- opts.all = [];
13644
- }
13645
- if (typeof opts.all === "string") {
13646
- opts.all = [opts.all];
13647
- }
13648
- opts.all = opts.all.concat(opts.exact);
13649
- }
13650
- }
13651
- }
13652
- // Handle the other props
13653
- if (opts.any) {
13654
- result.q = serializeStringOrArray$1("OR", key, opts.any);
13655
- }
13656
- if (opts.all) {
13657
- result.q =
13658
- (result.q ? result.q + " AND " : "") +
13659
- serializeStringOrArray$1("AND", key, opts.all);
13660
- }
13661
- if (opts.not) {
13662
- // negate the entries if they are not
13663
- result.q =
13664
- (result.q ? result.q + " AND " : "") +
13665
- serializeStringOrArray$1("OR", "-" + key, opts.not);
13666
- }
13667
- return result;
13668
- }
13669
- /**
13670
- * @private
13671
- * Serialize a DateRange<number> into a Portal Query string
13672
- * @param key
13673
- * @param range
13674
- * @returns
13675
- */
13676
- function serializeDateRange$1(key, range) {
13677
- return {
13678
- q: key + ":[" + range.from + " TO " + range.to + "]",
13679
- filter: "",
13680
- };
13681
- }
13682
- /**
13683
- * @private
13684
- * Serialize a `string` or `string[]` into a string
13685
- * @param join
13686
- * @param key
13687
- * @param value
13688
- * @returns
13689
- */
13690
- function serializeStringOrArray$1(join, key, value) {
13691
- var q = "";
13692
- if (Array.isArray(value)) {
13693
- q = key + ":\"" + value.join("\" " + join + " " + key + ":\"") + "\"";
13694
- if (value.length > 1) {
13695
- q = "(" + q + ")";
13696
- }
13697
- }
13698
- else {
13699
- q = key + ":\"" + value + "\"";
13700
- }
13701
- return q;
13702
- }
13703
13502
  /**
13704
13503
  * Create a `.next()` function for a type
13705
13504
  * @param request
@@ -13764,2131 +13563,911 @@
13764
13563
  return thumbnailUrl;
13765
13564
  }
13766
13565
 
13767
- // TODO: Remove with _searchContent
13768
- // TODO: Implement $dataset
13769
- var ContentFilterExpansions = {
13770
- $apps: [
13771
- {
13772
- type: {
13773
- any: [
13774
- "Code Sample",
13775
- "Web Mapping Application",
13776
- "Mobile Application",
13777
- "Application",
13778
- "Desktop Application Template",
13779
- "Desktop Application",
13780
- "Operation View",
13781
- "Dashboard",
13782
- "Operations Dashboard Extension",
13783
- "Workforce Project",
13784
- "Insights Workbook",
13785
- "Insights Page",
13786
- "Insights Model",
13787
- "Hub Page",
13788
- "Hub Initiative",
13789
- "Hub Site Application",
13790
- "StoryMap",
13791
- "Web Experience",
13792
- "Web Experience Template",
13793
- "Form",
13794
- ],
13795
- not: [
13796
- "Code Attachment",
13797
- "Featured Items",
13798
- "Symbol Set",
13799
- "Color Set",
13800
- "Windows Viewer Add In",
13801
- "Windows Viewer Configuration",
13802
- "Map Area",
13803
- "Indoors Map Configuration",
13804
- ],
13805
- },
13806
- typekeywords: {
13807
- not: ["MapAreaPackage", "SMX"],
13808
- },
13809
- },
13810
- ],
13811
- $storymap: [
13812
- {
13813
- type: "StoryMap",
13814
- },
13815
- {
13816
- type: "Web Mapping Application",
13817
- typekeywords: ["Story Map"],
13818
- },
13819
- ],
13820
- $dashboard: [
13821
- {
13822
- type: "Dashboard",
13823
- typekeywords: {
13824
- any: ["Dashboard"],
13825
- not: ["ArcGIS Operation View", "Add In", "Extension"],
13826
- },
13827
- },
13828
- ],
13829
- $dataset: [],
13830
- $experience: [
13831
- {
13832
- type: {
13833
- any: ["Web Experience"],
13834
- not: ["Web Experience Template"],
13835
- },
13836
- },
13837
- ],
13838
- $site: [
13839
- {
13840
- type: ["Hub Site Application", "Site Application"],
13841
- },
13842
- {
13843
- type: ["Web Mapping Application"],
13844
- typekeywords: ["hubSite"],
13845
- },
13846
- ],
13847
- $initiative: [
13848
- {
13849
- type: {
13850
- any: "Hub Initiative",
13851
- not: "Hub Initiative Template",
13852
- },
13853
- },
13854
- ],
13855
- $document: [
13856
- {
13857
- typekeywords: {
13858
- any: "Document",
13859
- not: ["MapAreaPackage", "SMX"],
13860
- },
13861
- type: {
13862
- any: [
13863
- "Image",
13864
- "Layout",
13865
- "Desktop Style",
13866
- "Project Template",
13867
- "Report Template",
13868
- "Pro Report",
13869
- "Statistical Data Collection",
13870
- "360 VR Experience",
13871
- "netCDF",
13872
- "PDF",
13873
- "CSV",
13874
- "Administrative Report",
13875
- "Raster function template",
13876
- ],
13877
- not: [
13878
- "Image Service",
13879
- "Explorer Document",
13880
- "Explorer Map",
13881
- "Globe Document",
13882
- "Scene Document",
13883
- "Code Attachment",
13884
- "Featured Items",
13885
- "Symbol Set",
13886
- "ColorSet",
13887
- "Windows Viewer Add In",
13888
- "Windows Viewer Configuration",
13889
- "Map Area",
13890
- "Indoors Map Configuration",
13891
- ],
13892
- },
13893
- },
13894
- ],
13895
- };
13566
+ var CATALOG_SCHEMA_VERSION = 1.0;
13896
13567
  /**
13897
- * @private
13898
- * Convert portal search response to facets
13899
- * Note: Only applicable to an item search
13900
- * @param response
13568
+ * Apply schema upgrades to Catalog objects
13569
+ * @param catalog
13901
13570
  * @returns
13902
13571
  */
13903
- // TODO: Remove with _searchContent
13904
- function convertPortalResponseToFacets(response, operation) {
13905
- if (operation === void 0) { operation = "OR"; }
13906
- // delegate to a more future-friendly version
13907
- return convertPortalItemResponseToFacets(response, operation, "filter");
13572
+ function upgradeCatalogSchema(catalog) {
13573
+ var clone = cloneObject$1(catalog);
13574
+ if (getProp(clone, "schemaVersion") === CATALOG_SCHEMA_VERSION) {
13575
+ return clone;
13576
+ }
13577
+ else {
13578
+ // apply migrations in order
13579
+ clone = applyCatalogSchema(clone);
13580
+ return clone;
13581
+ }
13908
13582
  }
13909
13583
  /**
13910
- * @private
13911
- * Convert portal search response to facets
13912
- * Note: Only applicable to an item search
13913
- * @param response
13584
+ * Apply the Catalog schema to the original, unversioned
13585
+ * site catalog objects
13586
+ * @param original
13914
13587
  * @returns
13915
13588
  */
13916
- function convertPortalItemResponseToFacets(response, operation, optionProp // TODO: Remove with _searchContent and use `filters`
13917
- ) {
13918
- var _a;
13919
- if (operation === void 0) { operation = "OR"; }
13920
- if (optionProp === void 0) { optionProp = "filters"; }
13921
- // TODO: move into portalSearchItems
13922
- var result = [];
13923
- if ((_a = response.aggregations) === null || _a === void 0 ? void 0 : _a.counts) {
13924
- response.aggregations.counts.forEach(function (entry) {
13925
- var facet = {
13926
- label: entry.fieldName,
13927
- key: entry.fieldName,
13928
- aggField: entry.fieldName,
13929
- display: "multi-select",
13930
- };
13931
- var options = [];
13932
- entry.fieldValues.forEach(function (fv) {
13933
- var filter = {
13934
- filterType: "item",
13935
- };
13936
- // construct the filter based on the operation
13937
- var matchKey = operation === "OR" ? "any" : "all";
13938
- var filterMatchOption = {};
13939
- filterMatchOption[matchKey] = [fv.value];
13940
- filter[entry.fieldName] = filterMatchOption;
13941
- // construct the FacetOption
13942
- var fo = {
13943
- label: fv.value + " (" + fv.count + ")",
13944
- key: fv.value,
13945
- count: fv.count,
13946
- selected: false,
13947
- };
13948
- // Temporary to ensure the old fn can delegate to this
13949
- // but we can still return the correct structure
13950
- // TODO: Remove with _searchContent
13951
- /* istanbul ignore next */
13952
- if (optionProp === "filter") {
13953
- fo.filter = filter;
13954
- }
13955
- else {
13956
- fo.filters = [filter];
13957
- }
13958
- options.push(fo);
13589
+ function applyCatalogSchema(original) {
13590
+ if (getProp(original, "schemaVersion") > 1.0) {
13591
+ return original;
13592
+ }
13593
+ else {
13594
+ var catalog = {
13595
+ schemaVersion: 1,
13596
+ title: "Default Catalog",
13597
+ scopes: {
13598
+ item: {
13599
+ targetEntity: "item",
13600
+ filters: [],
13601
+ },
13602
+ },
13603
+ collections: [],
13604
+ };
13605
+ var rawGroups = getProp(original, "groups");
13606
+ var groups = [];
13607
+ if (Array.isArray(rawGroups) && rawGroups.length) {
13608
+ groups = rawGroups;
13609
+ }
13610
+ else if (typeof rawGroups === "string") {
13611
+ groups = [rawGroups];
13612
+ }
13613
+ if (groups.length) {
13614
+ catalog.scopes.item.filters.push({
13615
+ predicates: [{ group: groups }],
13959
13616
  });
13960
- facet.options = options;
13961
- result.push(facet);
13962
- });
13617
+ }
13618
+ return catalog;
13963
13619
  }
13964
- return result;
13965
13620
  }
13966
13621
  /**
13967
- * Merge `Filter<"content">` objects
13968
- *
13969
- * Useful in components which may get partial filters from a variety of
13970
- * sub-components, which are then combined into a single filter prior
13971
- * to executing the search.
13972
- * @param filters
13973
- * @returns
13622
+ * DEPRECATED: Use upgradeCatalogSchema(...)
13623
+ * @param original
13974
13624
  */
13975
- function mergeContentFilter(filters) {
13976
- Logger.warn("DEPRECATION: mergeContentFilter will be removed and filters should not longer be merged. Work with IFilterGroups instead");
13977
- // expand all the filters so all prop types are consistent
13978
- var expanded = filters.map(expandContentFilter);
13979
- // now we can merge based on fields
13980
- var dateFields = ["created", "modified"];
13981
- var specialFields = __spreadArrays(["filterType", "subFilters", "term"], dateFields);
13982
- var result = expanded.reduce(function (acc, entry) {
13983
- // process fields
13984
- Object.entries(entry).forEach(function (_a) {
13985
- var key = _a[0], value = _a[1];
13986
- if (acc.hasOwnProperty(key)) {
13987
- /* istanbul ignore else */
13988
- if (!specialFields.includes(key)) {
13989
- acc[key] = mergeMatchOptions(acc[key], value);
13990
- }
13991
- else if (dateFields.includes(key)) {
13992
- acc[key] = mergeDateRange(acc[key], value);
13993
- }
13994
- else if (key === "term") {
13995
- acc[key] = acc[key] + " " + value;
13996
- }
13997
- else if (key === "subFilters") {
13998
- acc[key] = mergeSubFilters(acc[key], value);
13999
- }
14000
- }
14001
- else {
14002
- acc[key] = cloneObject$1(value);
14003
- }
14004
- });
14005
- return acc;
14006
- }, {});
14007
- result.filterType = "content";
14008
- return result;
14009
- }
14010
- function mergeSubFilters(sf1, sf2) {
14011
- // Simplistic implementation: we just merge the arrays
14012
- // in the future we may try to de-dupe things as a safeguard
14013
- return __spreadArrays(sf1, sf2);
13625
+ /* istanbul ignore next */
13626
+ function convertCatalog(original) {
13627
+ return upgradeCatalogSchema(original);
14014
13628
  }
13629
+
14015
13630
  /**
14016
- * Prior to serialization into the query syntax for the backing APIs, we first expand [Filters](../Filter)
14017
- *
14018
- * Filter's can express their intent in a very terse form, but to ensure consistent structures
14019
- * we expand them into their more verbose form.
14020
- *
14021
- * i.e. `title: "Water"` expands into `title: { any: ["Water"]}`
14022
- *
14023
- * - "well known" type values are expanded
14024
- * - i.e. `type: "$storymap"` expands into two `subFilter` entries
14025
- * - Fields defined as `string | string[] | MatchOptions` will be converted to a `MatchOptions`
14026
- * - RelativeDate fields are converted to DateRange<number>
14027
- *
14028
- * @param filter
13631
+ * @private
13632
+ * Expand a predicate
13633
+ * @param predicate
14029
13634
  * @returns
14030
13635
  */
14031
- function expandContentFilter(filter) {
14032
- Logger.warn("DEPRECATION: expandContentFilter will be removed. Work with IFilterGroups<\"item\"> instead");
14033
- // Expand filter.type first
14034
- var expandedTypeFilter = expandTypeField(filter);
14035
- // Expand subfilters
14036
- // Guard - JS Clients could send in anything...
14037
- if (Array.isArray(filter.subFilters)) {
14038
- // Convert any strings into the coresponding ContentFilterDefinition
14039
- expandedTypeFilter.subFilters = expandedTypeFilter.subFilters.reduce(function (acc, entry) {
14040
- if (typeof entry === "string") {
14041
- // if the entry is not a key of ContentFilterExpansions
14042
- // we just skip over it
14043
- if (ContentFilterExpansions[entry]) {
14044
- acc = acc.concat(ContentFilterExpansions[entry]);
14045
- }
13636
+ function expandPredicate(predicate) {
13637
+ var result = {};
13638
+ var dateProps = ["created", "modified", "lastlogin"];
13639
+ var copyProps = [
13640
+ "filterType",
13641
+ "term",
13642
+ "searchUserAccess",
13643
+ "isopendata",
13644
+ "searchUserName",
13645
+ ];
13646
+ var nonMatchOptionsFields = __spreadArrays(dateProps, copyProps);
13647
+ // Do the conversion
13648
+ Object.entries(predicate).forEach(function (_a) {
13649
+ var key = _a[0], value = _a[1];
13650
+ // Handle MatchOptions fields
13651
+ if (!nonMatchOptionsFields.includes(key)) {
13652
+ setProp(key, valueToMatchOptions(value), result);
13653
+ }
13654
+ // Handle Date fields
13655
+ if (dateProps.includes(key)) {
13656
+ var dateFieldValue = cloneObject$1(getProp(predicate, key));
13657
+ if (getProp(predicate, key + ".type") === "relative-date") {
13658
+ setProp(key, relativeDateToDateRange(dateFieldValue), result);
14046
13659
  }
14047
13660
  else {
14048
- acc.push(entry); // should be a ContentFilterDefinition
13661
+ setProp(key, dateFieldValue, result);
14049
13662
  }
14050
- return acc;
14051
- }, []);
14052
- }
14053
- // Convert all props into MatchOptions/DateRanges
14054
- return convertContentDefinitionToFilter(expandedTypeFilter);
13663
+ }
13664
+ // Handle fields that are just copied forward
13665
+ if (copyProps.includes(key) && predicate.hasOwnProperty(key)) {
13666
+ setProp(key, value, result);
13667
+ }
13668
+ });
13669
+ return result;
14055
13670
  }
13671
+
14056
13672
  /**
14057
- * @private
14058
- * Expand from a well-known "type" into it's longer form
14059
- *
14060
- * i.e. `type: "$storymap"` expands into two subFilters entries
14061
- *
14062
- * @param filter
13673
+ * Serialize IQuery into ISearchOptions for ArcGIS Portal
13674
+ * @param query
14063
13675
  * @returns
14064
13676
  */
14065
- function expandTypeField(filter) {
14066
- var clone = cloneObject$1(filter);
14067
- // ensure subFilters is defined as an array
14068
- clone.subFilters = clone.subFilters || [];
14069
- if (clone.type) {
14070
- // if .type is an Array...
14071
- if (Array.isArray(clone.type)) {
14072
- // remove any well-known-keys and move their expansions into subfilters
14073
- clone.type = clone.type.reduce(function (acc, entry) {
14074
- if (isWellKnownType(entry)) {
14075
- // working with dynamic objects in typescript requires some assertions
14076
- var key = entry;
14077
- clone.subFilters = clone.subFilters.concat(lookupTypeFilters(key));
14078
- }
14079
- else {
14080
- acc.push(entry);
14081
- }
14082
- return acc;
14083
- }, []);
14084
- }
14085
- else if (isWellKnownType(clone.type)) {
14086
- var key = clone.type;
14087
- clone.subFilters = clone.subFilters.concat(lookupTypeFilters(key));
14088
- delete clone.type;
14089
- }
14090
- else ;
14091
- }
14092
- return clone;
14093
- }
14094
- /**
14095
- * Is the argument a well-known type "key"
14096
- *
14097
- * Accepts `string`, `string[]` or `IMatchOptions`
14098
- * but only string values can possibly be properties
14099
- * on `ContentFilterExpansions`
14100
- * @param key
14101
- * @returns
14102
- */
14103
- function isWellKnownType(key) {
14104
- var result = false;
14105
- if (typeof key === "string") {
14106
- result = key in ContentFilterExpansions;
14107
- }
13677
+ function serializeQueryForPortal(query) {
13678
+ var filterSearchOptions = query.filters.map(serializeFilter);
13679
+ // remove any empty entries
13680
+ var nonEmptyOptions = filterSearchOptions.filter(removeEmptyEntries);
13681
+ var result = mergeSearchOptions(nonEmptyOptions, "AND");
14108
13682
  return result;
14109
13683
  }
14110
- function lookupTypeFilters(key) {
14111
- return ContentFilterExpansions[key];
14112
- }
14113
13684
  /**
14114
- * @private
14115
- * Convert a `ContentFilterDefinition` to a `ContentFilter`
14116
- *
14117
- * ContentFilter is a narrower version of ContentFilterDefinition, without
14118
- * the union types. Using a ContentFilter makes working with the structure
14119
- * in typescript much easier.
14120
- *
14121
- * @param filter
13685
+ * Predicate to remove things from array
13686
+ * @param e
14122
13687
  * @returns
14123
13688
  */
14124
- function convertContentDefinitionToFilter(filter) {
14125
- // TODO: Remove with _searchContent
14126
- Logger.warn("DEPRECATION: convertContentDefinitionToFilter will be removed. Work with IFilterGroups<\"item\"> instead");
14127
- var result = {};
14128
- if (filter.term) {
14129
- result.term = filter.term;
14130
- }
14131
- var dateProps = ["created", "modified"];
14132
- // Some properties should not get converted to MatchOptions
14133
- var specialProps = __spreadArrays(["filterType", "subFilters", "term"], dateProps);
14134
- // Do the conversion
14135
- Object.entries(filter).forEach(function (_a) {
14136
- var key = _a[0], value = _a[1];
14137
- if (!specialProps.includes(key)) {
14138
- result[key] = valueToMatchOptions(value);
14139
- }
14140
- });
14141
- // Special Cases
14142
- // subFilters; Array of ContentFilterDefinitions
14143
- if (filter.subFilters && Array.isArray(filter.subFilters)) {
14144
- // downcast - would be nice to skip this or use some other constuct
14145
- var sf = filter.subFilters;
14146
- result.subFilters = sf.map(convertContentDefinitionToFilter);
14147
- }
14148
- // Dates; Ensure they are all DateRange<number>
14149
- dateProps.forEach(function (fld) {
14150
- if (filter[fld]) {
14151
- if (filter[fld].type === "relative-date") {
14152
- result[fld] = relativeDateToDateRange(filter[fld]);
13689
+ function removeEmptyEntries(e) {
13690
+ return !(typeof e === "undefined" || e === null || e === "");
13691
+ }
13692
+ function mergeSearchOptions(options, operation) {
13693
+ var result = options.reduce(function (acc, entry) {
13694
+ // walk the props
13695
+ Object.entries(entry).forEach(function (_a) {
13696
+ var key = _a[0], value = _a[1];
13697
+ // if prop exists and is not empty string
13698
+ if (acc[key] && value !== "") {
13699
+ // combine via operation
13700
+ acc[key] = acc[key] + " " + operation + " " + value;
14153
13701
  }
14154
13702
  else {
14155
- result[fld] = cloneObject$1(filter[fld]);
13703
+ // just copy the value if it's not empty string
13704
+ if (value !== "") {
13705
+ acc[key] = value;
13706
+ }
14156
13707
  }
14157
- }
14158
- });
13708
+ });
13709
+ return acc;
13710
+ }, { q: "" });
14159
13711
  return result;
14160
13712
  }
14161
13713
  /**
14162
- * @private
14163
- * Serialize a `ContentFilter` into an `ISearchOptions` for use with `searchItems`
13714
+ * Serialize the filters in a FitlerGroup into a Portal Query
14164
13715
  * @param filter
14165
13716
  * @returns
14166
13717
  */
14167
- function serializeContentFilterForPortal(filter) {
14168
- // TODO: Remove with _searchContent
14169
- Logger.warn("DEPRECATION: serializeContentFilterForPortal will be removed. Work with IFilterGroups<\"item\"> and hubSearch() instead");
14170
- var searchOptions = convertContentFilterToSearchOptions(filter);
14171
- if (filter.subFilters) {
14172
- var subFilterOptions = filter.subFilters.reduce(function (acc, entry) {
14173
- // Next guard is present b/c this can be used from javascript
14174
- // but our tests are written in typescript which prevents us
14175
- // from hitting the else
14176
- /* istanbul ignore else */
14177
- if (typeof entry === "object") {
14178
- acc = mergeSearchOptions$1(acc, convertContentFilterToSearchOptions(entry), "OR");
14179
- }
14180
- return acc;
14181
- }, { q: "", filter: "" });
14182
- // merge with searchOptions using AND
14183
- searchOptions = mergeSearchOptions$1(searchOptions, subFilterOptions, "AND");
14184
- }
14185
- // term is always last, and pre-pended on searchOptions.q
14186
- if (filter.term) {
14187
- searchOptions.q = (filter.term + " " + searchOptions.q).trim();
13718
+ function serializeFilter(filter) {
13719
+ var operation = filter.operation || "AND";
13720
+ var predicates = filter.predicates.map(expandPredicate);
13721
+ var predicateSearchOptions = predicates
13722
+ .map(serializePredicate)
13723
+ .filter(function (e) { return e !== undefined && e !== null; });
13724
+ // combine these searchOptions
13725
+ var searchOptions = mergeSearchOptions(predicateSearchOptions, operation);
13726
+ // wrap in parens if we have more than one predicate
13727
+ if (predicates.length > 1) {
13728
+ searchOptions.q = "(" + searchOptions.q + ")";
14188
13729
  }
14189
13730
  return searchOptions;
14190
13731
  }
14191
13732
  /**
14192
- * @private
14193
- * Convert a ContentFilter to a SearchOptions
14194
- *
14195
- * @param filter
13733
+ * Serialize a Filter into a Portal Query
13734
+ * @param predicate
14196
13735
  * @returns
14197
13736
  */
14198
- function convertContentFilterToSearchOptions(filter) {
14199
- // TODO: Remove with _searchContent
14200
- Logger.warn("DEPRECATION: convertContentFilterToSearchOptions will be removed. Work with IFilterGroups<\"item\"> and hubSearch() instead");
14201
- var result = {
14202
- q: "",
14203
- filter: "",
14204
- };
13737
+ function serializePredicate(predicate) {
14205
13738
  var dateProps = ["created", "modified"];
14206
- var specialProps = __spreadArrays(["filterType", "subFilters", "term"], dateProps);
14207
- Object.entries(filter).forEach(function (_a) {
13739
+ var boolProps = ["isopendata"];
13740
+ var passThroughProps = ["searchUserAccess", "searchUserName"];
13741
+ var specialProps = __spreadArrays([
13742
+ "filterType",
13743
+ "term"
13744
+ ], dateProps, boolProps, passThroughProps);
13745
+ var portalAllowList = [
13746
+ "access",
13747
+ "categories",
13748
+ "created",
13749
+ "description",
13750
+ "disabled",
13751
+ "email",
13752
+ "emailstatus",
13753
+ "firstname",
13754
+ "fullname",
13755
+ "group",
13756
+ "id",
13757
+ "isInvitationOnly",
13758
+ "isopendata",
13759
+ "joined",
13760
+ "lastlogin",
13761
+ "lastname",
13762
+ "memberType",
13763
+ "modified",
13764
+ "name",
13765
+ "orgid",
13766
+ "orgIds",
13767
+ "owner",
13768
+ "provider",
13769
+ "role",
13770
+ "searchUserAccess",
13771
+ "searchUserName",
13772
+ "snippet",
13773
+ "tags",
13774
+ "term",
13775
+ "title",
13776
+ "type",
13777
+ "typekeywords",
13778
+ "userlicensetype",
13779
+ "username",
13780
+ ];
13781
+ var qCount = 0;
13782
+ // TODO: Look at using reduce vs .map and remove the `.filter`
13783
+ var opts = Object.entries(predicate)
13784
+ .map(function (_a) {
14208
13785
  var key = _a[0], value = _a[1];
14209
- // MatchOptions may go into either q or filter
14210
- if (!specialProps.includes(key)) {
14211
- result = mergeSearchOptions$1(result, serializeMatchOptions$1(key, value), "AND");
13786
+ // When serializing for portal we limit predicate properties to
13787
+ // a list of known properties that the portal api accepts. This will
13788
+ // not attempt to ensure the properties are used in the correct combinations
13789
+ if (portalAllowList.includes(key)) {
13790
+ var so = { q: "" };
13791
+ if (!specialProps.includes(key) && key !== "term") {
13792
+ qCount++;
13793
+ so.q = serializeMatchOptions(key, value);
13794
+ }
13795
+ if (dateProps.includes(key)) {
13796
+ qCount++;
13797
+ so.q = serializeDateRange(key, value);
13798
+ }
13799
+ if (boolProps.includes(key)) {
13800
+ qCount++;
13801
+ so.q = key + ":" + value;
13802
+ }
13803
+ if (passThroughProps.includes(key)) {
13804
+ so[key] = value;
13805
+ }
13806
+ if (key === "term") {
13807
+ qCount++;
13808
+ so.q = value;
13809
+ }
13810
+ return so;
14212
13811
  }
14213
- // Dates only go into q
14214
- if (dateProps.includes(key)) {
14215
- result = mergeSearchOptions$1(result, serializeDateRange$1(key, value), "AND");
13812
+ })
13813
+ .filter(removeEmptyEntries);
13814
+ // merge up all the searchOptions
13815
+ if (opts.length) {
13816
+ var searchOptions = mergeSearchOptions(opts, "AND");
13817
+ if (qCount > 1) {
13818
+ searchOptions.q = "(" + searchOptions.q + ")";
14216
13819
  }
14217
- });
14218
- return result;
13820
+ return searchOptions;
13821
+ }
13822
+ else {
13823
+ return null;
13824
+ }
14219
13825
  }
14220
-
14221
- // TODO: Remove with _searchContent
14222
13826
  /**
14223
- *
14224
- * Merge `Filter<"group">` objects
14225
- *
14226
- * Useful in components which may get partial filters from a variety of
14227
- * sub-components, which are then combined into a single filter prior
14228
- * to executing the search.
14229
- * @param filters
13827
+ * Serialize MatchOptions into portal syntax
13828
+ * @param key
13829
+ * @param value
14230
13830
  * @returns
14231
13831
  */
14232
- function mergeGroupFilters(filters) {
14233
- // TODO: Remove with _searchContent
14234
- Logger.warn("DEPRECATION: mergeGroupFilters will be removed. Work with IFilterGroups<\"group\"> and hubSearch() instead");
14235
- // expand all the filters so all prop types are consistent
14236
- var expanded = filters.map(expandGroupFilter);
14237
- // now we can merge based on fields
14238
- var dateFields = ["created", "modified"];
14239
- var specialFields = __spreadArrays(["filterType", "term"], dateFields);
14240
- // acc is initialized as Filter<group> but also needs it
14241
- // in the function signature... for reasons?!
14242
- var result = expanded.reduce(function (acc, entry) {
14243
- // process fields
14244
- Object.entries(entry).forEach(function (_a) {
14245
- // Note: getProp/setProp are used to get around
14246
- // typescript issues with string indexing
14247
- var key = _a[0], value = _a[1];
14248
- if (acc.hasOwnProperty(key)) {
14249
- var existingValue = getProp(acc, key);
14250
- // if the key is not to a special field
14251
- if (!specialFields.includes(key)) {
14252
- // treat as an IMatchOptions
14253
- setProp(key, mergeMatchOptions(existingValue, value), acc);
14254
- }
14255
- else if (dateFields.includes(key)) {
14256
- // treat as IDateRange
14257
- setProp(key, mergeDateRange(existingValue, value), acc);
14258
- }
14259
- else if (key === "term") {
14260
- // append terms
14261
- acc[key] = acc[key] + " " + value;
14262
- }
14263
- }
14264
- else {
14265
- // Acc does not have an entry for this yet
14266
- // so just clone it
14267
- setProp(key, cloneObject$1(value), acc);
14268
- }
14269
- });
14270
- return acc;
14271
- }, {
14272
- filterType: "group",
14273
- });
13832
+ function serializeMatchOptions(key, value) {
13833
+ var result = "";
13834
+ if (value.any) {
13835
+ result = "" + serializeStringOrArray("OR", key, value.any);
13836
+ }
13837
+ if (value.all) {
13838
+ result =
13839
+ (result ? result + " AND " : "") +
13840
+ ("" + serializeStringOrArray("AND", key, value.all));
13841
+ }
13842
+ if (value.not) {
13843
+ // negate the entries if they are not
13844
+ result =
13845
+ (result ? result + " AND " : "") +
13846
+ ("" + serializeStringOrArray("OR", "-" + key, value.not));
13847
+ }
14274
13848
  return result;
14275
13849
  }
14276
13850
  /**
14277
- * Prior to serialization into the query syntax for the backing APIs, we first expand [Filters](../Filter)
14278
- *
14279
- * Filter's can express their intent in a very terse form, but to ensure consistent structures
14280
- * we expand them into their more verbose form.
14281
- *
14282
- * i.e. `title: "Water"` expands into `title: { any: ["Water"]}`
14283
- *
14284
- * - Fields defined as `string | string[] | MatchOptions` will be converted to a `MatchOptions`
14285
- * - RelativeDate fields are converted to DateRange<number>
14286
- *
14287
- * @param filter
13851
+ * Serialize a date-range into Portal syntax
13852
+ * @param key
13853
+ * @param range
14288
13854
  * @returns
14289
13855
  */
14290
- function expandGroupFilter(filter) {
14291
- // TODO: Remove with _searchContent
14292
- Logger.warn("DEPRECATION: expandGroupFilters will be removed. Work with IFilterGroups<\"group\"> and hubSearch() instead");
14293
- var result = {};
14294
- var dateProps = ["created", "modified"];
14295
- // Some properties should not get converted to MatchOptions
14296
- var specialProps = __spreadArrays(["term", "searchUserAccess"], dateProps);
14297
- // Do the conversion
14298
- Object.entries(filter).forEach(function (_a) {
14299
- var key = _a[0], value = _a[1];
14300
- // handle Matchish fields
14301
- if (!specialProps.includes(key)) {
14302
- // setProp side-steps typescript complaining
14303
- setProp(key, valueToMatchOptions(value), result);
14304
- }
14305
- // Handle date fields
14306
- if (dateProps.includes(key)) {
14307
- var dateFieldValue = cloneObject$1(getProp(filter, key));
14308
- if (getProp(filter, key + ".type") === "relative-date") {
14309
- setProp(key, relativeDateToDateRange(dateFieldValue), result);
14310
- }
14311
- else {
14312
- setProp(key, dateFieldValue, result);
14313
- }
14314
- }
14315
- });
14316
- // searchUserAccess is boolean, so we check if the prop exists
14317
- // vs checking if the value is truthy
14318
- if (filter.hasOwnProperty("searchUserAccess")) {
14319
- result.searchUserAccess = filter.searchUserAccess;
14320
- }
14321
- if (filter.term) {
14322
- result.term = filter.term;
14323
- }
14324
- return result;
13856
+ function serializeDateRange(key, range) {
13857
+ return key + ":[" + range.from + " TO " + range.to + "]";
14325
13858
  }
14326
13859
  /**
14327
- * @private
14328
- * Serialize an `IGroupFilterDefinition` into an `ISearchOptions` for use
14329
- * with `searchGroups`
14330
- * @param filter
13860
+ * Serialize a `string` or `string[]` into a string
13861
+ * @param join
13862
+ * @param key
13863
+ * @param value
14331
13864
  * @returns
14332
13865
  */
14333
- function serializeGroupFilterForPortal(filter) {
14334
- // TODO: Remove with _searchContent
14335
- Logger.warn("DEPRECATION: serializeGroupFilterForPortal will be removed. Work with IFilterGroups<\"group\"> and hubSearch() instead");
14336
- var result = {
14337
- q: "",
14338
- filter: "",
14339
- };
14340
- var dateProps = ["created", "modified"];
14341
- var specialProps = __spreadArrays(["term", "searchUserAccess", "filterType"], dateProps);
14342
- Object.entries(filter).forEach(function (_a) {
14343
- var key = _a[0], value = _a[1];
14344
- // MatchOptions fields
14345
- if (!specialProps.includes(key)) {
14346
- result = mergeSearchOptions$1(result, serializeMatchOptions$1(key, value), "AND");
14347
- }
14348
- // Dates only go into q
14349
- if (dateProps.includes(key)) {
14350
- result = mergeSearchOptions$1(result, serializeDateRange$1(key, value), "AND");
13866
+ function serializeStringOrArray(join, key, value) {
13867
+ var q = "";
13868
+ if (Array.isArray(value)) {
13869
+ q = key + ":\"" + value.join("\" " + join + " " + key + ":\"") + "\"";
13870
+ if (value.length > 1) {
13871
+ q = "(" + q + ")";
14351
13872
  }
14352
- });
14353
- // searchUserAccess is also a top-level property
14354
- if (filter.hasOwnProperty("searchUserAccess")) {
14355
- result.searchUserAccess = filter.searchUserAccess;
14356
13873
  }
14357
- // add the term
14358
- if (filter.term) {
14359
- result.q = (filter.term + " " + result.q).trim();
13874
+ else {
13875
+ q = key + ":\"" + value + "\"";
14360
13876
  }
14361
- return result;
13877
+ return q;
14362
13878
  }
14363
13879
 
14364
- // TODO: Remove with _searchContent
14365
13880
  /**
13881
+ * Generic Hub Error with an Error stack as well
13882
+ * as an optional serialized OperationStack.
14366
13883
  *
14367
- * Merge `Filter<"user">` objects
14368
- *
14369
- * Useful in components which may get partial filters from a variety of
14370
- * sub-components, which are then combined into a single filter prior
14371
- * to executing the search.
14372
- * @param filters
14373
- * @returns
13884
+ * Also accepts a `rootCause` Error object
14374
13885
  */
14375
- function mergeUserFilters(filters) {
14376
- // TODO: Remove with _searchContent
14377
- Logger.warn("DEPRECATION: mergeUserFilters will be removed. Work with IFilterGroups<\"user\"> and hubSearch() instead");
14378
- // expand all the filters so all prop types are consistent
14379
- var expanded = filters.map(expandUserFilter);
14380
- // now we can merge based on fields
14381
- var dateFields = ["created", "modified", "lastlogin"];
14382
- var specialFields = __spreadArrays(["disabled", "term", "filterType"], dateFields);
14383
- // acc is initialized as Filter<group> but also needs it
14384
- // in the function signature... for reasons?!
14385
- var result = expanded.reduce(function (acc, entry) {
14386
- // process fields
14387
- Object.entries(entry).forEach(function (_a) {
14388
- // Note: getProp/setProp are used to get around
14389
- // typescript issues with string indexing
14390
- var key = _a[0], value = _a[1];
14391
- if (acc.hasOwnProperty(key)) {
14392
- var existingValue = getProp(acc, key);
14393
- // if the key is not to a special field
14394
- if (!specialFields.includes(key)) {
14395
- // treat as an IMatchOptions
14396
- setProp(key, mergeMatchOptions(existingValue, value), acc);
14397
- }
14398
- else if (dateFields.includes(key)) {
14399
- // treat as IDateRange
14400
- setProp(key, mergeDateRange(existingValue, value), acc);
14401
- }
14402
- else if (key === "term") {
14403
- // append terms
14404
- acc[key] = acc[key] + " " + value;
14405
- }
14406
- }
14407
- else {
14408
- // Acc does not have an entry for this yet
14409
- // so just clone it
14410
- setProp(key, cloneObject$1(value), acc);
14411
- }
14412
- });
14413
- return acc;
14414
- }, {
14415
- filterType: "user",
14416
- });
14417
- return result;
14418
- }
14419
- /**
14420
- * Prior to serialization into the query syntax for the backing APIs, we first expand [Filters](../Filter)
14421
- *
14422
- * Filter's can express their intent in a very terse form, but to ensure consistent structures
14423
- * we expand them into their more verbose form.
14424
- *
14425
- * i.e. `firstname: "John"` expands into `firstname: { any: ["John"]}`
14426
- *
14427
- * - Fields defined as `string | string[] | MatchOptions` will be converted to a `MatchOptions`
14428
- * - RelativeDate fields are converted to DateRange<number>
14429
- * @param filter
14430
- * @returns
14431
- */
14432
- function expandUserFilter(filter) {
14433
- // TODO: Remove with _searchContent
14434
- Logger.warn("DEPRECATION: expandUserFilter will be removed. Work with IFilterGroups<\"user\"> and hubSearch() instead");
14435
- var result = {};
14436
- var dateProps = ["created", "modified", "lastlogin"];
14437
- var specialProps = __spreadArrays(["disabled", "term"], dateProps);
14438
- Object.entries(filter).forEach(function (_a) {
14439
- var key = _a[0], value = _a[1];
14440
- // handle Matchish fields
14441
- if (!specialProps.includes(key)) {
14442
- // setProp side-steps typescript complaining
14443
- setProp(key, valueToMatchOptions(value), result);
14444
- }
14445
- // Handle date fields
14446
- if (dateProps.includes(key)) {
14447
- var dateFieldValue = cloneObject$1(getProp(filter, key));
14448
- if (getProp(filter, key + ".type") === "relative-date") {
14449
- setProp(key, relativeDateToDateRange(dateFieldValue), result);
14450
- }
14451
- else {
14452
- setProp(key, dateFieldValue, result);
14453
- }
14454
- }
14455
- });
14456
- // disabled is boolean, so we check if the prop exists
14457
- // vs checking if the value is truthy
14458
- if (filter.hasOwnProperty("disabled")) {
14459
- result.disabled = filter.disabled;
14460
- }
14461
- if (filter.term) {
14462
- result.term = filter.term;
13886
+ var HubError = /** @class */ (function (_super) {
13887
+ __extends(HubError, _super);
13888
+ /**
13889
+ * Creates an instance of HubError.
13890
+ * @param {string} operation
13891
+ * @param {string} [message]
13892
+ * @param {Error} [rootCause]
13893
+ * @memberof HubError
13894
+ */
13895
+ function HubError(operation, message, rootCause) {
13896
+ var _this = this;
13897
+ message = message || "UNKNOWN_ERROR";
13898
+ // if the rootCause has a .rootCause, use that so we don't deeply nest
13899
+ rootCause = getWithDefault$1(rootCause, "rootCause", rootCause);
13900
+ /* Skip coverage on super(...) as per:
13901
+ https://github.com/Microsoft/TypeScript/issues/13029
13902
+ https://github.com/SitePen/remap-istanbul/issues/106
13903
+ */
13904
+ /* istanbul ignore next */
13905
+ _this = _super.call(this, operation, message, rootCause) || this;
13906
+ _this.name = "HubError";
13907
+ // if the original error has a stack use it, otherwise create a new
13908
+ // stack. Note: a new Stack will make it look like the error origninated
13909
+ // in the HubError constructor. This is only an issue in tests but
13910
+ // it can be confusing to debug
13911
+ _this.stack = getWithDefault$1(rootCause, "stack", new Error().stack);
13912
+ return _this;
14463
13913
  }
14464
- return result;
14465
- }
13914
+ return HubError;
13915
+ }(OperationError$1));
13916
+ var HubError$1 = HubError;
13917
+
14466
13918
  /**
14467
13919
  * @private
14468
- * Serialize an `IUserFilterDefinition` into an `ISearchOptions` for use
14469
- * with `searchUsers`
14470
- * @param filter
13920
+ * Convert a portal aggregation structure into the HubAggregations structure
13921
+ * @param searchResults
14471
13922
  * @returns
14472
13923
  */
14473
- function serializeUserFilterForPortal(filter) {
14474
- // TODO: Remove with _searchContent
14475
- Logger.warn("DEPRECATION: serializeUserFilterForPortal will be removed. Work with IFilterGroups<\"user\"> and hubSearch() instead");
14476
- var result = {
14477
- q: "",
14478
- filter: "",
14479
- };
14480
- var dateProps = ["created", "modified", "lastlogin"];
14481
- var specialProps = __spreadArrays(["term", "filterType"], dateProps);
14482
- Object.entries(filter).forEach(function (_a) {
14483
- var key = _a[0], value = _a[1];
14484
- // MatchOptions fields
14485
- if (!specialProps.includes(key)) {
14486
- result = mergeSearchOptions$1(result, serializeMatchOptions$1(key, value), "AND");
14487
- }
14488
- // Dates only go into q
14489
- if (dateProps.includes(key)) {
14490
- result = mergeSearchOptions$1(result, serializeDateRange$1(key, value), "AND");
14491
- }
14492
- });
14493
- // disabled is also a top-level property
14494
- if (filter.hasOwnProperty("disabled")) {
14495
- result.disabled = filter.disabled;
13924
+ function convertPortalAggregations(searchResults) {
13925
+ var _a;
13926
+ if ((_a = searchResults.aggregations) === null || _a === void 0 ? void 0 : _a.counts) {
13927
+ return searchResults.aggregations.counts.map(function (entry) {
13928
+ return {
13929
+ mode: "terms",
13930
+ field: entry.fieldName,
13931
+ values: entry.fieldValues,
13932
+ };
13933
+ });
14496
13934
  }
14497
- // add the term
14498
- if (filter.term) {
14499
- // Note: this is slightly different from other types
14500
- result.q = ("(" + filter.term + ") " + result.q).trim();
13935
+ else {
13936
+ return [];
14501
13937
  }
14502
- return result;
14503
13938
  }
14504
13939
 
14505
- // TODO: Remove with _searchContent
14506
13940
  /**
14507
13941
  * @private
14508
- * Search for content via the Portal or Hub API
14509
- * @param filter
13942
+ * Execute a search and convert to a specific entity
13943
+ * @param query
13944
+ * @param convertFn
14510
13945
  * @param options
14511
- */
14512
- function _searchContent(filter, options) {
14513
- var _a, _b;
14514
- return __awaiter(this, void 0, void 0, function () {
14515
- var expanded, api, searchPromise, so_1, props;
14516
- return __generator(this, function (_c) {
14517
- Logger.warn("DEPRECATION: _searchContent will be removed; switch to hubSearch(...)");
14518
- expanded = expandContentFilter(filter);
14519
- api = expandApi(options.api || "arcgis");
14520
- // Portal Search
14521
- if (api.type === "arcgis") {
14522
- so_1 = serializeContentFilterForPortal(expanded);
14523
- props = [
14524
- "authentication",
14525
- "num",
14526
- "sortField",
14527
- "sortOrder",
14528
- "site",
14529
- "start",
14530
- ];
14531
- // copy the props over
14532
- props.forEach(function (prop) {
14533
- if (options.hasOwnProperty(prop)) {
14534
- so_1[prop] = options[prop];
14535
- }
14536
- });
14537
- // If we don't have auth, ensure we have .portal
14538
- if (!so_1.authentication) {
14539
- so_1.portal = api.url + "/sharing/rest";
14540
- }
14541
- // DEPRECATION
14542
- if ((_a = options.aggregations) === null || _a === void 0 ? void 0 : _a.length) {
14543
- // tslint:disable-next-line:no-console
14544
- console.warn("IHubSearchOptions.aggregations is deprecated. Please use .aggFields instead.");
14545
- so_1.countFields = options.aggregations.join(",");
14546
- so_1.countSize = options.aggLimit || 10;
14547
- }
14548
- // Aggregations
14549
- if ((_b = options.aggFields) === null || _b === void 0 ? void 0 : _b.length) {
14550
- so_1.countFields = options.aggFields.join(",");
14551
- so_1.countSize = options.aggLimit || 10;
14552
- }
14553
- searchPromise = searchPortal$3(so_1);
14554
- }
14555
- else {
14556
- // Hub API Search
14557
- // TODO: Implement hub api content search
14558
- searchPromise = Promise.resolve({
14559
- total: 0,
14560
- results: [],
14561
- facets: [],
14562
- hasNext: false,
14563
- next: function () {
14564
- // tslint:disable-next-line
14565
- Promise.resolve(null);
14566
- },
14567
- });
14568
- }
14569
- return [2 /*return*/, searchPromise];
14570
- });
14571
- });
14572
- }
14573
- /**
14574
- * Internal portal search, which then converts items to Content, and
14575
- * if a Site was passed, also sets urls
14576
- *
14577
- * @param searchOptions
14578
- * @param site
14579
13946
  * @returns
14580
13947
  */
14581
- function searchPortal$3(searchOptions) {
13948
+ function searchEntities(query, convertFn, options) {
14582
13949
  var _a;
14583
- var portalUrl = ((_a = searchOptions.authentication) === null || _a === void 0 ? void 0 : _a.portal) || searchOptions.portal;
14584
- var token;
14585
- if (searchOptions.authentication) {
14586
- var us = searchOptions.authentication;
14587
- token = us.token;
14588
- }
14589
- var thumbnailify = function (content) {
14590
- content.thumbnailUrl = getItemThumbnailUrl(content, portalUrl, token);
14591
- return content;
14592
- };
14593
- return searchItems(searchOptions).then(function (resp) {
14594
- var hasNext = resp.nextStart > -1;
14595
- // convert items to IHubContent's
14596
- var content = resp.results.map(itemToContent);
14597
- // if we have a site, add those urls
14598
- if (searchOptions.site) {
14599
- content = content.map(function (entry) {
14600
- return setContentSiteUrls(entry, searchOptions.site);
14601
- });
13950
+ // serialize query to searchOptions
13951
+ var searchOptions = serializeQueryForPortal(query);
13952
+ // Aggregations
13953
+ if ((_a = options.aggFields) === null || _a === void 0 ? void 0 : _a.length) {
13954
+ searchOptions.countFields = options.aggFields.join(",");
13955
+ searchOptions.countSize = options.aggLimit || 10;
13956
+ }
13957
+ // properties to copy from IHubSearchOptions to the ISearchOptions
13958
+ var props = [
13959
+ "num",
13960
+ "sortField",
13961
+ "sortOrder",
13962
+ "start",
13963
+ "requestOptions",
13964
+ ];
13965
+ // Include "start" here
13966
+ // copy the props over
13967
+ props.forEach(function (prop) {
13968
+ if (options.hasOwnProperty(prop)) {
13969
+ searchOptions[prop] = options[prop];
14602
13970
  }
14603
- // add thumbnailUrl
14604
- content = content.map(thumbnailify);
14605
- // convert aggregations into facets
14606
- var facets = convertPortalResponseToFacets(resp);
14607
- return {
14608
- total: resp.total,
14609
- results: content,
14610
- facets: facets,
14611
- hasNext: hasNext,
14612
- next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$3),
14613
- };
14614
13971
  });
13972
+ // create the entitySearchFn
13973
+ var searchFn = createEntitySearchFn(convertFn);
13974
+ // Add ArcGIS API
13975
+ if (options.api && !options.authentication) {
13976
+ var expandedApi = expandApi(options.api);
13977
+ searchOptions.portal = expandedApi.url;
13978
+ }
13979
+ return searchFn(searchOptions);
14615
13980
  }
14616
-
14617
- // TODO: Remove with _searchContent
14618
13981
  /**
14619
13982
  * @private
14620
- * Search Groups using Filter<"group">
14621
- *
14622
- * Currently just returns ISearchResult<IGroup>
14623
- * @param filter
14624
- * @param options
13983
+ * @param convertFn
14625
13984
  * @returns
14626
13985
  */
14627
- function _searchGroups(filter, options) {
14628
- return __awaiter(this, void 0, void 0, function () {
14629
- var expanded, api, so_1, props;
14630
- return __generator(this, function (_a) {
14631
- Logger.warn("DEPRECATION: _searchGroups will be removed; switch to hubSearch(...)");
14632
- expanded = expandGroupFilter(filter);
14633
- api = expandApi(options.api || "arcgis");
14634
- if (api.type === "arcgis") {
14635
- so_1 = serializeGroupFilterForPortal(expanded);
14636
- props = [
14637
- "authentication",
14638
- "num",
14639
- "sortField",
14640
- "sortOrder",
14641
- "site",
14642
- "start",
14643
- ];
14644
- // copy the props over
14645
- props.forEach(function (prop) {
14646
- if (options.hasOwnProperty(prop)) {
14647
- so_1[prop] = options[prop];
14648
- }
14649
- });
14650
- // If we don't have auth, ensure we have .portal
14651
- if (!so_1.authentication) {
14652
- so_1.portal = api.url + "/sharing/rest";
13986
+ function createEntitySearchFn(convertFn) {
13987
+ // Return a function that does the search, with a closure over the
13988
+ // conversion function. Naming this function is important as it's
13989
+ // referenced in the `next` section below
13990
+ return function executeSearch(searchOptions) {
13991
+ return __awaiter(this, void 0, void 0, function () {
13992
+ var response, entities, aggregations;
13993
+ return __generator(this, function (_a) {
13994
+ switch (_a.label) {
13995
+ case 0: return [4 /*yield*/, searchItems(searchOptions)];
13996
+ case 1:
13997
+ response = _a.sent();
13998
+ return [4 /*yield*/, Promise.all(response.results.map(function (itm) {
13999
+ return convertFn(itm, searchOptions);
14000
+ }))];
14001
+ case 2:
14002
+ entities = _a.sent();
14003
+ aggregations = convertPortalAggregations(response);
14004
+ return [2 /*return*/, {
14005
+ total: response.total,
14006
+ results: entities,
14007
+ aggregations: aggregations,
14008
+ hasNext: response.nextStart > -1,
14009
+ next: getNextFunction(searchOptions, response.nextStart, response.total, executeSearch),
14010
+ }];
14653
14011
  }
14654
- return [2 /*return*/, searchPortalGroups(so_1)];
14655
- }
14656
- else {
14657
- throw new Error("_searchGroups is not implemented for non-arcgis apis");
14658
- }
14012
+ });
14659
14013
  });
14660
- });
14661
- }
14662
- /**
14663
- * Internal function that searches for groups using the ArcGIS Portal API
14664
- * @param searchOptions
14665
- * @returns
14666
- */
14667
- function searchPortalGroups(searchOptions) {
14668
- var _a;
14669
- var teamLinkify = function (group) {
14670
- group.siteTeamUrl = searchOptions.site.item.url + "/teams/" + group.id + "/about";
14671
- return group;
14672
14014
  };
14673
- var portalUrl = ((_a = searchOptions.authentication) === null || _a === void 0 ? void 0 : _a.portal) || searchOptions.portal;
14674
- var token;
14675
- if (searchOptions.authentication) {
14676
- var us = searchOptions.authentication;
14677
- token = us.token;
14678
- }
14679
- var thumbnailify = function (group) {
14680
- group.thumbnailUrl = getGroupThumbnailUrl(portalUrl, group, token);
14681
- return group;
14682
- };
14683
- // execute the search
14684
- return searchGroups(searchOptions).then(function (response) {
14685
- var _a, _b;
14686
- var hasNext = response.nextStart > -1;
14687
- // upgrade thumbnail url
14688
- var results = response.results.map(thumbnailify);
14689
- // generate the site team url if site url is provided
14690
- if ((_b = (_a = searchOptions.site) === null || _a === void 0 ? void 0 : _a.item) === null || _b === void 0 ? void 0 : _b.url) {
14691
- results = response.results.map(teamLinkify);
14692
- }
14693
- return {
14694
- hasNext: hasNext,
14695
- total: response.total,
14696
- results: results,
14697
- next: getNextFunction(searchOptions, response.nextStart, response.total, searchPortalGroups),
14698
- };
14699
- });
14700
14015
  }
14701
14016
 
14702
- // TODO: Remove with _searchContent
14703
14017
  /**
14704
- * @private
14705
- * Search for Users via the Portal API.
14706
- *
14707
- * **Note** Authentication is required
14708
- *
14709
- * Another trivial comment to force a release
14710
- *
14711
- * Note: in the future, there may be options to search via
14712
- * a Hub specific API
14713
- * @param filter
14714
- * @param options
14018
+ * Fetch Page specific Enrichments
14019
+ * @param item
14020
+ * @param include
14021
+ * @param requestOptions
14715
14022
  * @returns
14716
14023
  */
14717
- function _searchUsers(filter, options) {
14024
+ function enrichPageSearchResult(item, include, requestOptions) {
14718
14025
  return __awaiter(this, void 0, void 0, function () {
14719
- var expanded, api, searchOptions_1, props;
14026
+ var result, DEFAULTS, specs, enrichments, enriched;
14720
14027
  return __generator(this, function (_a) {
14721
- Logger.warn("DEPRECATION: _searchUsers will be removed; switch to hubSearch(...)");
14722
- // JS Clients may not pass in authentication
14723
- if (!options.authentication) {
14724
- throw new Error("Authentication required to search for users.");
14725
- }
14726
- expanded = expandUserFilter(filter);
14727
- api = expandApi(options.api || "arcgis");
14728
- if (api.type === "arcgis") {
14729
- searchOptions_1 = serializeUserFilterForPortal(expanded);
14730
- props = [
14731
- "authentication",
14732
- "num",
14733
- "sortField",
14734
- "sortOrder",
14735
- "site",
14736
- "start",
14737
- ];
14738
- // copy the props over
14739
- props.forEach(function (prop) {
14740
- if (options.hasOwnProperty(prop)) {
14741
- searchOptions_1[prop] = options[prop];
14742
- }
14743
- });
14744
- return [2 /*return*/, searchPortalUsers(searchOptions_1)];
14745
- }
14746
- else {
14747
- throw new Error("_searchUsers is not implemented for non-arcgis apis");
14028
+ switch (_a.label) {
14029
+ case 0:
14030
+ result = {
14031
+ access: item.access,
14032
+ id: item.id,
14033
+ type: item.type,
14034
+ name: item.title,
14035
+ owner: item.owner,
14036
+ summary: item.snippet || item.description,
14037
+ createdDate: new Date(item.created),
14038
+ createdDateSource: "item.created",
14039
+ updatedDate: new Date(item.modified),
14040
+ updatedDateSource: "item.modified",
14041
+ family: getFamily(item.type),
14042
+ links: {
14043
+ self: "not-implemented",
14044
+ siteRelative: "not-implemented",
14045
+ thumbnail: "not-implemented",
14046
+ },
14047
+ };
14048
+ DEFAULTS = [];
14049
+ // merge includes
14050
+ include = __spreadArrays(DEFAULTS, include).filter(unique);
14051
+ specs = include.map(parseInclude);
14052
+ enrichments = mapBy("enrichment", specs).filter(unique);
14053
+ enriched = {};
14054
+ if (!enrichments.length) return [3 /*break*/, 2];
14055
+ return [4 /*yield*/, fetchItemEnrichments(item, enrichments, requestOptions)];
14056
+ case 1:
14057
+ // TODO: Look into caching for the requests in fetchItemEnrichments
14058
+ enriched = _a.sent();
14059
+ _a.label = 2;
14060
+ case 2:
14061
+ // map the enriched props onto the result
14062
+ specs.forEach(function (spec) {
14063
+ result[spec.prop] = getProp(enriched, spec.path);
14064
+ });
14065
+ // Handle Links
14066
+ result.links.thumbnail = getItemThumbnailUrl(item, requestOptions);
14067
+ result.links.self = getItemHomeUrl(result.id, requestOptions);
14068
+ result.links.siteRelative = getHubRelativeUrl(result.type, result.id, item.typeKeywords);
14069
+ return [2 /*return*/, result];
14748
14070
  }
14749
14071
  });
14750
14072
  });
14751
14073
  }
14752
- /**
14753
- * Internal function that executes the user search along with
14754
- * some simple enrichments
14755
- * @param searchOptions
14756
- * @returns
14757
- */
14758
- function searchPortalUsers(searchOptions) {
14759
- var portalUrl = searchOptions.authentication.portal;
14760
- var token = searchOptions.authentication.token;
14761
- // Partially applied functions for mapping over the results
14762
- var userLinkify = function (user) {
14763
- user.profileUrl = searchOptions.site.item.url + "/people/" + user.username + "/profile";
14764
- return user;
14765
- };
14766
- var thumbnailify = function (user) {
14767
- if (user.thumbnail) {
14768
- user.thumbnailUrl = getUserThumbnailUrl(portalUrl, user, token);
14769
- }
14770
- return user;
14771
- };
14772
- return searchUsers(searchOptions).then(function (response) {
14773
- var _a, _b;
14774
- var hasNext = response.nextStart > -1;
14775
- // upgrade thumbnail url
14776
- var results = response.results.map(thumbnailify);
14777
- // generate the site team url if site url is provided
14778
- if ((_b = (_a = searchOptions.site) === null || _a === void 0 ? void 0 : _a.item) === null || _b === void 0 ? void 0 : _b.url) {
14779
- results = response.results.map(userLinkify);
14780
- }
14781
- return {
14782
- hasNext: hasNext,
14783
- total: response.total,
14784
- results: results,
14785
- next: getNextFunction(searchOptions, response.nextStart, response.total, searchPortalUsers),
14786
- };
14787
- });
14788
- }
14789
14074
 
14790
14075
  /**
14791
- * @private
14792
- * Apply the sortState to SortOptions
14793
- *
14794
- * @param sortOptions
14795
- * @param sortState
14796
- * @returns
14076
+ * Given a model, return a serialized clone that can be sent to
14077
+ * the items api
14078
+ * @param {Object} model Item model {item:{}, data:{}}
14797
14079
  */
14798
- function applySortState(sortOptions, sortState) {
14799
- var updated = cloneObject$1(sortOptions);
14800
- if (sortState) {
14801
- var _a = sortState.split("|"), label = _a[0], attribute = _a[1], order = _a[2];
14802
- updated.label = label;
14803
- updated.attribute = attribute;
14804
- updated.order = order;
14805
- }
14806
- return updated;
14080
+ function serializeModel(model) {
14081
+ var serialized = cloneObject$1(model.item);
14082
+ serialized.text = JSON.stringify(model.data);
14083
+ return serialized;
14807
14084
  }
14085
+
14808
14086
  /**
14809
- * @private
14810
- * Apply FacetState to a Facet
14811
- * @param facet
14812
- * @param state
14813
- * @returns
14087
+ * Gets the full item/data model for an item id
14088
+ * @param {string} id
14089
+ * @param {Object} requestOptions
14814
14090
  */
14815
- function applyFacetState(facet, state) {
14816
- var updated = cloneObject$1(facet);
14817
- switch (facet.display) {
14818
- case "single-select":
14819
- updated = applySingleSelectFacetState(facet, state);
14820
- break;
14821
- case "multi-select":
14822
- updated = applyMultiSelectFacetState(facet, state);
14823
- break;
14824
- }
14825
- return updated;
14091
+ function getModel(id, requestOptions) {
14092
+ return Promise.all([
14093
+ getItem(id, requestOptions),
14094
+ getItemData(id, requestOptions),
14095
+ ]).then(function (result) {
14096
+ // shape this into a model
14097
+ return {
14098
+ item: result[0],
14099
+ data: result[1],
14100
+ };
14101
+ });
14826
14102
  }
14827
14103
  /**
14828
- * @private
14829
- * Apply the Facet State onto a single-select facet
14104
+ * Get a model by it's slug
14105
+ *
14106
+ * This uses the [Filter](https://developers.arcgis.com/rest/users-groups-and-items/search-reference.htm) option of the
14107
+ * to search for an item that has a typekeyword of `slug|{slug-value}`
14108
+ *
14109
+ * This is useful for applications that want to use human-readable urls instead
14110
+ * of using item ids.
14830
14111
  *
14831
- * Intentionally mutates the facet.
14832
- * @param facet
14833
- * @param state
14112
+ * @param slug
14113
+ * @param requestOptions
14834
14114
  * @returns
14835
14115
  */
14836
- function applySingleSelectFacetState(facet, state) {
14837
- var updated = cloneObject$1(facet);
14838
- updated.options = updated.options.map(function (o) {
14839
- o.selected = o.key === state[facet.key];
14840
- return o;
14116
+ function getModelBySlug(slug, requestOptions) {
14117
+ return getItemBySlug(slug, requestOptions)
14118
+ .then(function (item) {
14119
+ var prms = [Promise.resolve(item)];
14120
+ if (item) {
14121
+ prms.push(getItemData(item.id, requestOptions));
14122
+ }
14123
+ else {
14124
+ prms.push(Promise.resolve(null));
14125
+ }
14126
+ return Promise.all(prms);
14127
+ })
14128
+ .then(function (result) {
14129
+ if (result[0]) {
14130
+ return {
14131
+ item: result[0],
14132
+ data: result[1],
14133
+ };
14134
+ }
14135
+ else {
14136
+ return null;
14137
+ }
14841
14138
  });
14842
- return updated;
14843
14139
  }
14844
14140
  /**
14845
- * @private
14846
- * Serialize single-select facet into IFacetState
14847
- * @param facet
14848
- * @returns
14141
+ * Create an item to back and IModel.
14142
+ *
14143
+ * @param {IModel}
14144
+ * @param {IRequestOptions} requestOptions
14145
+ * @returns {Promise<IModel>}
14849
14146
  */
14850
- function serializeSingleSelectFacetState(facet) {
14851
- var state = {};
14852
- var selected = facet.options.find(function (o) { return o.selected; });
14853
- if (selected) {
14854
- state[facet.key] = selected.key;
14855
- }
14856
- else {
14857
- state[facet.key] = null;
14858
- }
14859
- return state;
14147
+ function createModel(model, requestOptions) {
14148
+ var clone = cloneObject$1(model);
14149
+ var item = cloneObject$1(model.item);
14150
+ item.data = cloneObject$1(model.data);
14151
+ var opts = __assign({ item: item }, requestOptions);
14152
+ return createItem(opts).then(function (response) {
14153
+ clone.item.id = response.id;
14154
+ clone.item.created = new Date().getTime();
14155
+ clone.item.modified = clone.item.created;
14156
+ return clone;
14157
+ });
14860
14158
  }
14861
14159
  /**
14862
- * @private
14863
- * Apply the Facet State onto a multi-select Facet
14160
+ * Update an IModel. Generic function that will be used across all
14161
+ * type-specific update functions
14864
14162
  *
14865
- * Intentionally mutates the facet.
14866
- * @param facet
14867
- * @param state
14868
- * @returns
14163
+ * @export
14164
+ * @param {IModel} "model" object (i.e. `{item:{...}, data:{...}}`)
14165
+ * @param {IRequestOptions} requestOptions
14166
+ * @returns {Promise<IModel>}
14869
14167
  */
14870
- function applyMultiSelectFacetState(facet, state) {
14871
- var _a;
14872
- var updated = cloneObject$1(facet);
14873
- var selectedKeys = ((_a = state[facet.key]) === null || _a === void 0 ? void 0 : _a.split(",")) || [];
14874
- updated.options = updated.options.map(function (o) {
14875
- o.selected = selectedKeys.includes(o.key);
14876
- return o;
14168
+ function updateModel(model, requestOptions) {
14169
+ var clone = cloneObject$1(model);
14170
+ var item = cloneObject$1(model.item);
14171
+ item.data = cloneObject$1(model.data);
14172
+ var opts = __assign({ item: item }, requestOptions);
14173
+ return updateItem(opts).then(function () {
14174
+ // update the modified prop
14175
+ // this won't be exact, but it will be very close
14176
+ clone.item.modified = new Date().getTime();
14177
+ return clone;
14877
14178
  });
14878
- return updated;
14879
14179
  }
14880
14180
  /**
14881
- * @private
14882
- * Serialize multi-select facet into IFacetState
14883
- * @param facet
14181
+ * Given an Item, fetch the data json and return an IModel
14182
+ * @param item
14183
+ * @param requestOptions
14884
14184
  * @returns
14885
14185
  */
14886
- function serializeMultiSelectFacetState(facet) {
14887
- var state = {};
14888
- var selected = facet.options.filter(function (o) { return o.selected; });
14889
- var value = selected.map(function (o) { return o.key; }).join(",");
14890
- if (value.length) {
14891
- state[facet.key] = value;
14892
- }
14893
- else {
14894
- state[facet.key] = null;
14895
- }
14896
- return state;
14186
+ function fetchModelFromItem(item, requestOptions) {
14187
+ return __awaiter(this, void 0, void 0, function () {
14188
+ var data;
14189
+ return __generator(this, function (_a) {
14190
+ switch (_a.label) {
14191
+ case 0: return [4 /*yield*/, getItemData(item.id, requestOptions)];
14192
+ case 1:
14193
+ data = _a.sent();
14194
+ return [2 /*return*/, {
14195
+ item: item,
14196
+ data: data,
14197
+ }];
14198
+ }
14199
+ });
14200
+ });
14897
14201
  }
14202
+
14203
+ // TODO: work out how to unify content slug fns
14204
+ // https: github.com/Esri/hub.js/blob/master/packages/common/src/content/index.ts#L301-L348
14898
14205
  /**
14899
- * @private
14900
- * Serialize the state of the SortOption into a key/value pair
14206
+ * Create a slug, namespaced to an org
14207
+ * Typically used to lookup items by a human readable name in urls
14901
14208
  *
14902
- * Called from the Sort component
14903
- * @param sort
14209
+ * @param title
14210
+ * @param orgKey
14904
14211
  * @returns
14905
14212
  */
14906
- function serializeSortState(sort) {
14907
- return sort.label + "|" + sort.attribute + "|" + sort.order;
14213
+ function constructSlug(title, orgKey) {
14214
+ return orgKey.toLowerCase() + "-" + slugify(title);
14908
14215
  }
14909
14216
  /**
14910
- * @private
14911
- * Serialize the state of a facet into a key/value pair
14912
- *
14913
- * Called from the various facet components
14914
- * @param facet
14217
+ * Adds/Updates the slug typekeyword
14218
+ * Returns a new array of keywords
14219
+ * @param typeKeywords
14220
+ * @param slug
14915
14221
  * @returns
14916
14222
  */
14917
- function serializeFacetState(facet) {
14918
- var state = {};
14919
- switch (facet.display) {
14920
- case "single-select":
14921
- state = serializeSingleSelectFacetState(facet);
14922
- break;
14923
- case "multi-select":
14924
- state = serializeMultiSelectFacetState(facet);
14925
- break;
14926
- }
14927
- return state;
14223
+ function setSlugKeyword(typeKeywords, slug) {
14224
+ // remove slug entry from array
14225
+ var removed = typeKeywords.filter(function (entry) {
14226
+ return !entry.startsWith("slug|");
14227
+ });
14228
+ // now add it
14229
+ removed.push("slug|" + slug);
14230
+ return removed;
14928
14231
  }
14929
-
14930
14232
  /**
14931
- * Apply ICollectionState to an ICollection
14233
+ * Get an item by searching for items with a typeKeyword like `slug|{slug-value}`
14932
14234
  *
14933
- * Typically used in a Gallery or Catalog component to
14934
- * set the inital state, based on values deserialized
14935
- * from a query string
14936
- * @param collection
14937
- * @param state
14235
+ * For example, if you pass a slug `"snow-map"` into this function, it will
14236
+ * search for items with `slug|snow-map` in it's typeKeywords array,
14237
+ *
14238
+ * @param slug
14239
+ * @param requestOptions
14938
14240
  * @returns
14939
14241
  */
14940
- function applyCollectionState(collection, state) {
14941
- var updated = cloneObject$1(collection);
14942
- // Apply default query
14943
- if (state.query) {
14944
- updated.defaultQuery = state.query;
14945
- }
14946
- // Apply Sort State
14947
- updated.sortOption = applySortState(updated.sortOption, state.sort);
14948
- // Look for state props for the facets and apply them
14949
- updated.facets = updated.facets.map(function (facet) {
14950
- // see if there is a key for this facet on the state
14951
- if (Object.keys(state).includes(facet.key)) {
14952
- var facetState = {};
14953
- facetState[facet.key] = state[facet.key];
14954
- return applyFacetState(facet, facetState);
14242
+ function getItemBySlug(slug, requestOptions) {
14243
+ return findItemsBySlug({ slug: slug }, requestOptions).then(function (results) {
14244
+ if (results.length) {
14245
+ return results[0];
14955
14246
  }
14956
14247
  else {
14957
- // Ensure all options are not selected
14958
- // because they were not included in the state
14959
- facet.options.forEach(function (opt) {
14960
- opt.selected = false;
14961
- });
14962
- return facet;
14248
+ return null;
14963
14249
  }
14964
14250
  });
14965
- //
14966
- return updated;
14967
14251
  }
14968
14252
  /**
14969
- * Serialize the current state of a collection into a hash that
14970
- * can be converted into a query string
14971
- * @param collection
14253
+ * Find items by slug typeKeywords.
14254
+ *
14255
+ * Optional exclude parameter accepts the id of an item we expect to
14256
+ * have this particular slug. This is used during update calls
14257
+ * where we don't know if the slug specifically has been updated, but we
14258
+ * don't want a false-postive from the item we are updating
14259
+ *
14260
+ * @param slug
14261
+ * @param requestOptions
14972
14262
  * @returns
14973
14263
  */
14974
- function serializeCollectionState(collection) {
14975
- var state = {};
14976
- if (collection.defaultQuery) {
14977
- state.query = collection.defaultQuery;
14978
- }
14979
- if (collection.sortOption) {
14980
- state.sort = serializeSortState(collection.sortOption);
14981
- }
14982
- var facetState = (collection.facets || []).reduce(function (s, facet) {
14983
- return __assign(__assign({}, s), serializeFacetState(facet));
14984
- }, {});
14985
- return __assign(__assign({}, state), facetState);
14986
- }
14987
-
14988
- /**
14989
- * Convert the original site catalog structure into a formal ICatalog
14990
- * @param original
14991
- */
14992
- function convertCatalog(original) {
14993
- var catalog = {
14994
- schemaVersion: 1,
14995
- title: "Default Catalog",
14996
- scopes: {
14997
- item: {
14998
- targetEntity: "item",
14999
- filters: [],
15000
- },
15001
- },
15002
- collections: [],
14264
+ function findItemsBySlug(slugInfo, requestOptions) {
14265
+ var opts = {
14266
+ filter: "typekeywords:\"slug|" + slugInfo.slug + "\"",
15003
14267
  };
15004
- var rawGroups = getProp(original, "groups");
15005
- var groups = [];
15006
- if (Array.isArray(rawGroups) && rawGroups.length) {
15007
- groups = rawGroups;
14268
+ if (requestOptions.authentication) {
14269
+ opts.authentication = requestOptions.authentication;
15008
14270
  }
15009
- else if (typeof rawGroups === "string") {
15010
- groups = [rawGroups];
14271
+ else if (requestOptions.portal) {
14272
+ opts.portal = requestOptions.portal;
15011
14273
  }
15012
- if (groups.length) {
15013
- catalog.scopes.item.filters.push({
15014
- predicates: [{ group: groups }],
15015
- });
14274
+ // We need to check for other items w/ a slug during
14275
+ // the update calls. For those scenarios we are interested
14276
+ // in any _other_ items which may have a specific slug
14277
+ // but not one specific item
14278
+ if (slugInfo.exclude) {
14279
+ opts.q = "NOT id:" + slugInfo.exclude;
15016
14280
  }
15017
- return catalog;
14281
+ return searchItems(opts)
14282
+ .then(function (response) {
14283
+ return response.results;
14284
+ })
14285
+ .catch(function (e) {
14286
+ throw e;
14287
+ });
15018
14288
  }
15019
-
15020
14289
  /**
15021
- * Determine if a Filter is "empty"
15022
- * @param filter
14290
+ * Given a slug, search for items using that slug, incrementing the slug name until
14291
+ * a unique value is found
14292
+ *
14293
+ * For example, if a slug of `"snow-map"` into this function and some item exists
14294
+ * with that slug, it would return `"snow-map-1"`.
14295
+ *
14296
+ * @param slug
14297
+ * @param requestOptions
14298
+ * @param step
15023
14299
  * @returns
15024
14300
  */
15025
- function isEmptyFilter(filter) {
15026
- // if it has one property, filterType, it's empty
15027
- return (Object.keys(filter).length === 1 && filter.hasOwnProperty("filterType"));
14301
+ function getUniqueSlug(slugInfo, requestOptions, step) {
14302
+ if (step === void 0) { step = 0; }
14303
+ var combinedSlug = slugInfo.slug;
14304
+ if (step) {
14305
+ combinedSlug = slugInfo.slug + "-" + step;
14306
+ }
14307
+ return findItemsBySlug({ slug: combinedSlug, exclude: slugInfo.existingId }, requestOptions)
14308
+ .then(function (results) {
14309
+ if (results.length) {
14310
+ step++;
14311
+ return getUniqueSlug(slugInfo, requestOptions, step);
14312
+ }
14313
+ else {
14314
+ return combinedSlug;
14315
+ }
14316
+ })
14317
+ .catch(function (e) {
14318
+ throw Error("Error in getUniqueSlug " + e);
14319
+ });
15028
14320
  }
14321
+
15029
14322
  /**
15030
- * Determine if a filterGroup is "empty"
15031
- * @param filterGroup
15032
- * @returns
15033
- */
15034
- function isEmptyFilterGroup(filterGroup) {
15035
- // if filters array is empty
15036
- if (filterGroup.filters.length === 0) {
15037
- return true;
15038
- }
15039
- else {
15040
- // if all filters are empty
15041
- var result = filterGroup.filters.reduce(function (acc, entry) {
15042
- if (acc) {
15043
- acc = isEmptyFilter(entry);
15044
- }
15045
- return acc;
15046
- }, true);
15047
- return result;
14323
+ * Manage forward and backward property mappings to
14324
+ * streamline conversion between the Hub entities, and
14325
+ * the backing IModel
14326
+ */
14327
+ var PropertyMapper = /** @class */ (function () {
14328
+ /**
14329
+ * Pass in the mappings between the Entity and
14330
+ * it's backing structure (model or otherwise)
14331
+ * @param mappings
14332
+ */
14333
+ function PropertyMapper(mappings) {
14334
+ this.mappings = mappings;
15048
14335
  }
15049
- }
15050
-
14336
+ /**
14337
+ * Map properties from a model on to the entity object.
14338
+ *
14339
+ * Used when constructing an entity can from a fetched model,
14340
+ * in which case the entity should be an empty object (`{}`).
14341
+ *
14342
+ * Can also be used to apply changes to an entity from a model,
14343
+ * in which case an existing entity can be passed in.
14344
+ * @param model
14345
+ * @param object
14346
+ * @returns
14347
+ */
14348
+ PropertyMapper.prototype.modelToObject = function (model, object) {
14349
+ return mapModelToObject(model, object, this.mappings);
14350
+ };
14351
+ /**
14352
+ * Map properties from an entity object onto a model.
14353
+ *
14354
+ * Typically the model will already exist, and this
14355
+ * method is used to transfer changes to the model
14356
+ * prior to storage.
14357
+ * @param object
14358
+ * @param model
14359
+ * @returns
14360
+ */
14361
+ PropertyMapper.prototype.objectToModel = function (object, model) {
14362
+ return mapObjectToModel(object, model, this.mappings);
14363
+ };
14364
+ return PropertyMapper;
14365
+ }());
15051
14366
  /**
15052
- * @private
15053
- * Expand a predicate
15054
- * @param predicate
14367
+ * Generic function to apply properties from an Object
14368
+ * (i.e. IHubProject) onto a Model that can be persisted to an Item
14369
+ * @param object
14370
+ * @param model
14371
+ * @param mappings
15055
14372
  * @returns
15056
14373
  */
15057
- function expandPredicate(predicate) {
15058
- var result = {};
15059
- var dateProps = ["created", "modified", "lastlogin"];
15060
- var copyProps = [
15061
- "filterType",
15062
- "term",
15063
- "searchUserAccess",
15064
- "isopendata",
15065
- "searchUserName",
15066
- ];
15067
- var nonMatchOptionsFields = __spreadArrays(dateProps, copyProps);
15068
- // Do the conversion
15069
- Object.entries(predicate).forEach(function (_a) {
15070
- var key = _a[0], value = _a[1];
15071
- // Handle MatchOptions fields
15072
- if (!nonMatchOptionsFields.includes(key)) {
15073
- setProp(key, valueToMatchOptions(value), result);
15074
- }
15075
- // Handle Date fields
15076
- if (dateProps.includes(key)) {
15077
- var dateFieldValue = cloneObject$1(getProp(predicate, key));
15078
- if (getProp(predicate, key + ".type") === "relative-date") {
15079
- setProp(key, relativeDateToDateRange(dateFieldValue), result);
15080
- }
15081
- else {
15082
- setProp(key, dateFieldValue, result);
15083
- }
15084
- }
15085
- // Handle fields that are just copied forward
15086
- if (copyProps.includes(key) && predicate.hasOwnProperty(key)) {
15087
- setProp(key, value, result);
15088
- }
15089
- });
15090
- return result;
14374
+ function mapObjectToModel(object, model, mappings) {
14375
+ return mapProps(object, "objectKey", model, "modelKey", mappings);
15091
14376
  }
15092
-
15093
14377
  /**
15094
- * Serialize IQuery into ISearchOptions for ArcGIS Portal
15095
- * @param query
14378
+ * Generic function to apply properties from a Model
14379
+ * onto an Object (i.e. IHubProject etc)
14380
+ * @param model
14381
+ * @param object
14382
+ * @param mappings
15096
14383
  * @returns
15097
14384
  */
15098
- function serializeQueryForPortal(query) {
15099
- var filterSearchOptions = query.filters.map(serializeFilter);
15100
- // remove any empty entries
15101
- var nonEmptyOptions = filterSearchOptions.filter(removeEmptyEntries);
15102
- var result = mergeSearchOptions(nonEmptyOptions, "AND");
15103
- return result;
14385
+ function mapModelToObject(model, object, mappings) {
14386
+ return mapProps(model, "modelKey", object, "objectKey", mappings);
15104
14387
  }
15105
14388
  /**
15106
- * Predicate to remove things from array
15107
- * @param e
14389
+ * Internal function to map between objects
14390
+ * @param source
14391
+ * @param sourceKey
14392
+ * @param target
14393
+ * @param targetKey
14394
+ * @param mappings
15108
14395
  * @returns
15109
14396
  */
15110
- function removeEmptyEntries(e) {
15111
- return !(typeof e === "undefined" || e === null || e === "");
15112
- }
15113
- function mergeSearchOptions(options, operation) {
15114
- var result = options.reduce(function (acc, entry) {
15115
- // walk the props
15116
- Object.entries(entry).forEach(function (_a) {
15117
- var key = _a[0], value = _a[1];
15118
- // if prop exists and is not empty string
15119
- if (acc[key] && value !== "") {
15120
- // combine via operation
15121
- acc[key] = acc[key] + " " + operation + " " + value;
15122
- }
15123
- else {
15124
- // just copy the value if it's not empty string
15125
- if (value !== "") {
15126
- acc[key] = value;
15127
- }
15128
- }
15129
- });
15130
- return acc;
15131
- }, { q: "" });
15132
- return result;
14397
+ function mapProps(source, sourceKey, target, targetKey, mappings) {
14398
+ // clone the target
14399
+ var clone = cloneObject$1(target);
14400
+ // walk the property map array
14401
+ mappings.forEach(function (entry) {
14402
+ // Verbose b/c typescript hates the use of property indexing with generics
14403
+ // i.e. entry<T>[sourceKey] make typescript angry
14404
+ var sourcePath = getProp(entry, sourceKey);
14405
+ var targetPath = getProp(entry, targetKey);
14406
+ // get the value from the source
14407
+ var sourceVal = getProp(source, sourcePath);
14408
+ // if it's not null or undefined
14409
+ if (sourceVal !== null && sourceVal !== undefined) {
14410
+ // set it
14411
+ deepSet(clone, targetPath, sourceVal);
14412
+ }
14413
+ });
14414
+ return clone;
15133
14415
  }
14416
+
14417
+ var HUB_PROJECT_ITEM_TYPE = "Hub Project";
15134
14418
  /**
15135
- * Serialize the filters in a FitlerGroup into a Portal Query
15136
- * @param filter
15137
- * @returns
14419
+ * Default values of a IHubProject
15138
14420
  */
15139
- function serializeFilter(filter) {
15140
- var operation = filter.operation || "AND";
15141
- var predicates = filter.predicates.map(expandPredicate);
15142
- var predicateSearchOptions = predicates
15143
- .map(serializePredicate)
15144
- .filter(function (e) { return e !== undefined && e !== null; });
15145
- // combine these searchOptions
15146
- var searchOptions = mergeSearchOptions(predicateSearchOptions, operation);
15147
- // wrap in parens if we have more than one predicate
15148
- if (predicates.length > 1) {
15149
- searchOptions.q = "(" + searchOptions.q + ")";
15150
- }
15151
- return searchOptions;
15152
- }
14421
+ var DEFAULT_PROJECT = {
14422
+ name: "No title provided",
14423
+ tags: [],
14424
+ typeKeywords: ["Hub Project"],
14425
+ status: "inactive",
14426
+ };
15153
14427
  /**
15154
- * Serialize a Filter into a Portal Query
15155
- * @param predicate
14428
+ * Default values for a new HubProject Model
14429
+ */
14430
+ var DEFAULT_PROJECT_MODEL = {
14431
+ item: {
14432
+ type: HUB_PROJECT_ITEM_TYPE,
14433
+ title: "No Title Provided",
14434
+ description: "No Description Provided",
14435
+ snippet: "",
14436
+ tags: [],
14437
+ typeKeywords: ["Hub Project"],
14438
+ properties: {
14439
+ slug: "",
14440
+ },
14441
+ },
14442
+ data: {
14443
+ display: "about",
14444
+ timeline: {},
14445
+ status: "inactive",
14446
+ contacts: [],
14447
+ schemaVersion: 1,
14448
+ },
14449
+ };
14450
+ /**
14451
+ * Returns an Array of IPropertyMap objects
14452
+ * We could define these directly, but since the
14453
+ * properties of IHubProject map directly to properties
14454
+ * on item or data, it's slightly less verbose to
14455
+ * generate the structure.
15156
14456
  * @returns
15157
14457
  */
15158
- function serializePredicate(predicate) {
15159
- var dateProps = ["created", "modified"];
15160
- var boolProps = ["isopendata"];
15161
- var passThroughProps = ["searchUserAccess", "searchUserName"];
15162
- var specialProps = __spreadArrays([
15163
- "filterType",
15164
- "term"
15165
- ], dateProps, boolProps, passThroughProps);
15166
- var portalAllowList = [
15167
- "access",
15168
- "categories",
14458
+ function getProjectPropertyMap() {
14459
+ var itemProps = [
15169
14460
  "created",
14461
+ "culture",
15170
14462
  "description",
15171
- "disabled",
15172
- "email",
15173
- "emailstatus",
15174
- "firstname",
15175
- "fullname",
15176
- "group",
14463
+ "extent",
15177
14464
  "id",
15178
- "isInvitationOnly",
15179
- "isopendata",
15180
- "joined",
15181
- "lastlogin",
15182
- "lastname",
15183
- "memberType",
15184
14465
  "modified",
15185
- "name",
15186
- "orgid",
15187
- "orgIds",
15188
14466
  "owner",
15189
- "provider",
15190
- "role",
15191
- "searchUserAccess",
15192
- "searchUserName",
15193
14467
  "snippet",
15194
14468
  "tags",
15195
- "term",
15196
- "title",
15197
- "type",
15198
- "typekeywords",
15199
- "userlicensetype",
15200
- "username",
15201
- ];
15202
- var qCount = 0;
15203
- // TODO: Look at using reduce vs .map and remove the `.filter`
15204
- var opts = Object.entries(predicate)
15205
- .map(function (_a) {
15206
- var key = _a[0], value = _a[1];
15207
- // When serializing for portal we limit predicate properties to
15208
- // a list of known properties that the portal api accepts. This will
15209
- // not attempt to ensure the properties are used in the correct combinations
15210
- if (portalAllowList.includes(key)) {
15211
- var so = { q: "" };
15212
- if (!specialProps.includes(key) && key !== "term") {
15213
- qCount++;
15214
- so.q = serializeMatchOptions(key, value);
15215
- }
15216
- if (dateProps.includes(key)) {
15217
- qCount++;
15218
- so.q = serializeDateRange(key, value);
15219
- }
15220
- if (boolProps.includes(key)) {
15221
- qCount++;
15222
- so.q = key + ":" + value;
15223
- }
15224
- if (passThroughProps.includes(key)) {
15225
- so[key] = value;
15226
- }
15227
- if (key === "term") {
15228
- qCount++;
15229
- so.q = value;
15230
- }
15231
- return so;
15232
- }
15233
- })
15234
- .filter(removeEmptyEntries);
15235
- // merge up all the searchOptions
15236
- if (opts.length) {
15237
- var searchOptions = mergeSearchOptions(opts, "AND");
15238
- if (qCount > 1) {
15239
- searchOptions.q = "(" + searchOptions.q + ")";
15240
- }
15241
- return searchOptions;
15242
- }
15243
- else {
15244
- return null;
15245
- }
15246
- }
15247
- /**
15248
- * Serialize MatchOptions into portal syntax
15249
- * @param key
15250
- * @param value
15251
- * @returns
15252
- */
15253
- function serializeMatchOptions(key, value) {
15254
- var result = "";
15255
- if (value.any) {
15256
- result = "" + serializeStringOrArray("OR", key, value.any);
15257
- }
15258
- if (value.all) {
15259
- result =
15260
- (result ? result + " AND " : "") +
15261
- ("" + serializeStringOrArray("AND", key, value.all));
15262
- }
15263
- if (value.not) {
15264
- // negate the entries if they are not
15265
- result =
15266
- (result ? result + " AND " : "") +
15267
- ("" + serializeStringOrArray("OR", "-" + key, value.not));
15268
- }
15269
- return result;
15270
- }
15271
- /**
15272
- * Serialize a date-range into Portal syntax
15273
- * @param key
15274
- * @param range
15275
- * @returns
15276
- */
15277
- function serializeDateRange(key, range) {
15278
- return key + ":[" + range.from + " TO " + range.to + "]";
15279
- }
15280
- /**
15281
- * Serialize a `string` or `string[]` into a string
15282
- * @param join
15283
- * @param key
15284
- * @param value
15285
- * @returns
15286
- */
15287
- function serializeStringOrArray(join, key, value) {
15288
- var q = "";
15289
- if (Array.isArray(value)) {
15290
- q = key + ":\"" + value.join("\" " + join + " " + key + ":\"") + "\"";
15291
- if (value.length > 1) {
15292
- q = "(" + q + ")";
15293
- }
15294
- }
15295
- else {
15296
- q = key + ":\"" + value + "\"";
15297
- }
15298
- return q;
15299
- }
15300
-
15301
- /**
15302
- * Generic Hub Error with an Error stack as well
15303
- * as an optional serialized OperationStack.
15304
- *
15305
- * Also accepts a `rootCause` Error object
15306
- */
15307
- var HubError = /** @class */ (function (_super) {
15308
- __extends(HubError, _super);
15309
- /**
15310
- * Creates an instance of HubError.
15311
- * @param {string} operation
15312
- * @param {string} [message]
15313
- * @param {Error} [rootCause]
15314
- * @memberof HubError
15315
- */
15316
- function HubError(operation, message, rootCause) {
15317
- var _this = this;
15318
- message = message || "UNKNOWN_ERROR";
15319
- // if the rootCause has a .rootCause, use that so we don't deeply nest
15320
- rootCause = getWithDefault$1(rootCause, "rootCause", rootCause);
15321
- /* Skip coverage on super(...) as per:
15322
- https://github.com/Microsoft/TypeScript/issues/13029
15323
- https://github.com/SitePen/remap-istanbul/issues/106
15324
- */
15325
- /* istanbul ignore next */
15326
- _this = _super.call(this, operation, message, rootCause) || this;
15327
- _this.name = "HubError";
15328
- // if the original error has a stack use it, otherwise create a new
15329
- // stack. Note: a new Stack will make it look like the error origninated
15330
- // in the HubError constructor. This is only an issue in tests but
15331
- // it can be confusing to debug
15332
- _this.stack = getWithDefault$1(rootCause, "stack", new Error().stack);
15333
- return _this;
15334
- }
15335
- return HubError;
15336
- }(OperationError$1));
15337
- var HubError$1 = HubError;
15338
-
15339
- /**
15340
- * @private
15341
- * Convert a portal aggregation structure into the HubAggregations structure
15342
- * @param searchResults
15343
- * @returns
15344
- */
15345
- function convertPortalAggregations(searchResults) {
15346
- var _a;
15347
- if ((_a = searchResults.aggregations) === null || _a === void 0 ? void 0 : _a.counts) {
15348
- return searchResults.aggregations.counts.map(function (entry) {
15349
- return {
15350
- mode: "terms",
15351
- field: entry.fieldName,
15352
- values: entry.fieldValues,
15353
- };
15354
- });
15355
- }
15356
- else {
15357
- return [];
15358
- }
15359
- }
15360
-
15361
- /**
15362
- * @private
15363
- * Execute a search and convert to a specific entity
15364
- * @param query
15365
- * @param convertFn
15366
- * @param options
15367
- * @returns
15368
- */
15369
- function searchEntities(query, convertFn, options) {
15370
- var _a;
15371
- // serialize query to searchOptions
15372
- var searchOptions = serializeQueryForPortal(query);
15373
- // Aggregations
15374
- if ((_a = options.aggFields) === null || _a === void 0 ? void 0 : _a.length) {
15375
- searchOptions.countFields = options.aggFields.join(",");
15376
- searchOptions.countSize = options.aggLimit || 10;
15377
- }
15378
- // properties to copy from IHubSearchOptions to the ISearchOptions
15379
- var props = [
15380
- "num",
15381
- "sortField",
15382
- "sortOrder",
15383
- "start",
15384
- "requestOptions",
15385
- ];
15386
- // Include "start" here
15387
- // copy the props over
15388
- props.forEach(function (prop) {
15389
- if (options.hasOwnProperty(prop)) {
15390
- searchOptions[prop] = options[prop];
15391
- }
15392
- });
15393
- // create the entitySearchFn
15394
- var searchFn = createEntitySearchFn(convertFn);
15395
- // Add ArcGIS API
15396
- if (options.api && !options.authentication) {
15397
- var expandedApi = expandApi(options.api);
15398
- searchOptions.portal = expandedApi.url;
15399
- }
15400
- return searchFn(searchOptions);
15401
- }
15402
- /**
15403
- * @private
15404
- * @param convertFn
15405
- * @returns
15406
- */
15407
- function createEntitySearchFn(convertFn) {
15408
- // Return a function that does the search, with a closure over the
15409
- // conversion function. Naming this function is important as it's
15410
- // referenced in the `next` section below
15411
- return function executeSearch(searchOptions) {
15412
- return __awaiter(this, void 0, void 0, function () {
15413
- var response, entities, aggregations;
15414
- return __generator(this, function (_a) {
15415
- switch (_a.label) {
15416
- case 0: return [4 /*yield*/, searchItems(searchOptions)];
15417
- case 1:
15418
- response = _a.sent();
15419
- return [4 /*yield*/, Promise.all(response.results.map(function (itm) {
15420
- return convertFn(itm, searchOptions);
15421
- }))];
15422
- case 2:
15423
- entities = _a.sent();
15424
- aggregations = convertPortalAggregations(response);
15425
- return [2 /*return*/, {
15426
- total: response.total,
15427
- results: entities,
15428
- aggregations: aggregations,
15429
- hasNext: response.nextStart > -1,
15430
- next: getNextFunction(searchOptions, response.nextStart, response.total, executeSearch),
15431
- }];
15432
- }
15433
- });
15434
- });
15435
- };
15436
- }
15437
-
15438
- /**
15439
- * Fetch Page specific Enrichments
15440
- * @param item
15441
- * @param include
15442
- * @param requestOptions
15443
- * @returns
15444
- */
15445
- function enrichPageSearchResult(item, include, requestOptions) {
15446
- return __awaiter(this, void 0, void 0, function () {
15447
- var result, DEFAULTS, specs, enrichments, enriched;
15448
- return __generator(this, function (_a) {
15449
- switch (_a.label) {
15450
- case 0:
15451
- result = {
15452
- access: item.access,
15453
- id: item.id,
15454
- type: item.type,
15455
- name: item.title,
15456
- owner: item.owner,
15457
- summary: item.snippet || item.description,
15458
- createdDate: new Date(item.created),
15459
- createdDateSource: "item.created",
15460
- updatedDate: new Date(item.modified),
15461
- updatedDateSource: "item.modified",
15462
- family: getFamily(item.type),
15463
- links: {
15464
- self: "not-implemented",
15465
- siteRelative: "not-implemented",
15466
- thumbnail: "not-implemented",
15467
- },
15468
- };
15469
- DEFAULTS = [];
15470
- // merge includes
15471
- include = __spreadArrays(DEFAULTS, include).filter(unique);
15472
- specs = include.map(parseInclude);
15473
- enrichments = mapBy("enrichment", specs).filter(unique);
15474
- enriched = {};
15475
- if (!enrichments.length) return [3 /*break*/, 2];
15476
- return [4 /*yield*/, fetchItemEnrichments(item, enrichments, requestOptions)];
15477
- case 1:
15478
- // TODO: Look into caching for the requests in fetchItemEnrichments
15479
- enriched = _a.sent();
15480
- _a.label = 2;
15481
- case 2:
15482
- // map the enriched props onto the result
15483
- specs.forEach(function (spec) {
15484
- result[spec.prop] = getProp(enriched, spec.path);
15485
- });
15486
- // Handle Links
15487
- result.links.thumbnail = getItemThumbnailUrl(item, requestOptions);
15488
- result.links.self = getItemHomeUrl(result.id, requestOptions);
15489
- result.links.siteRelative = getHubRelativeUrl(result.type, result.id, item.typeKeywords);
15490
- return [2 /*return*/, result];
15491
- }
15492
- });
15493
- });
15494
- }
15495
-
15496
- /**
15497
- * Given a model, return a serialized clone that can be sent to
15498
- * the items api
15499
- * @param {Object} model Item model {item:{}, data:{}}
15500
- */
15501
- function serializeModel(model) {
15502
- var serialized = cloneObject$1(model.item);
15503
- serialized.text = JSON.stringify(model.data);
15504
- return serialized;
15505
- }
15506
-
15507
- /**
15508
- * Gets the full item/data model for an item id
15509
- * @param {string} id
15510
- * @param {Object} requestOptions
15511
- */
15512
- function getModel(id, requestOptions) {
15513
- return Promise.all([
15514
- getItem(id, requestOptions),
15515
- getItemData(id, requestOptions),
15516
- ]).then(function (result) {
15517
- // shape this into a model
15518
- return {
15519
- item: result[0],
15520
- data: result[1],
15521
- };
15522
- });
15523
- }
15524
- /**
15525
- * Get a model by it's slug
15526
- *
15527
- * This uses the [Filter](https://developers.arcgis.com/rest/users-groups-and-items/search-reference.htm) option of the
15528
- * to search for an item that has a typekeyword of `slug|{slug-value}`
15529
- *
15530
- * This is useful for applications that want to use human-readable urls instead
15531
- * of using item ids.
15532
- *
15533
- * @param slug
15534
- * @param requestOptions
15535
- * @returns
15536
- */
15537
- function getModelBySlug(slug, requestOptions) {
15538
- return getItemBySlug(slug, requestOptions)
15539
- .then(function (item) {
15540
- var prms = [Promise.resolve(item)];
15541
- if (item) {
15542
- prms.push(getItemData(item.id, requestOptions));
15543
- }
15544
- else {
15545
- prms.push(Promise.resolve(null));
15546
- }
15547
- return Promise.all(prms);
15548
- })
15549
- .then(function (result) {
15550
- if (result[0]) {
15551
- return {
15552
- item: result[0],
15553
- data: result[1],
15554
- };
15555
- }
15556
- else {
15557
- return null;
15558
- }
15559
- });
15560
- }
15561
- /**
15562
- * Create an item to back and IModel.
15563
- *
15564
- * @param {IModel}
15565
- * @param {IRequestOptions} requestOptions
15566
- * @returns {Promise<IModel>}
15567
- */
15568
- function createModel(model, requestOptions) {
15569
- var clone = cloneObject$1(model);
15570
- var item = cloneObject$1(model.item);
15571
- item.data = cloneObject$1(model.data);
15572
- var opts = __assign({ item: item }, requestOptions);
15573
- return createItem(opts).then(function (response) {
15574
- clone.item.id = response.id;
15575
- clone.item.created = new Date().getTime();
15576
- clone.item.modified = clone.item.created;
15577
- return clone;
15578
- });
15579
- }
15580
- /**
15581
- * Update an IModel. Generic function that will be used across all
15582
- * type-specific update functions
15583
- *
15584
- * @export
15585
- * @param {IModel} "model" object (i.e. `{item:{...}, data:{...}}`)
15586
- * @param {IRequestOptions} requestOptions
15587
- * @returns {Promise<IModel>}
15588
- */
15589
- function updateModel(model, requestOptions) {
15590
- var clone = cloneObject$1(model);
15591
- var item = cloneObject$1(model.item);
15592
- item.data = cloneObject$1(model.data);
15593
- var opts = __assign({ item: item }, requestOptions);
15594
- return updateItem(opts).then(function () {
15595
- // update the modified prop
15596
- // this won't be exact, but it will be very close
15597
- clone.item.modified = new Date().getTime();
15598
- return clone;
15599
- });
15600
- }
15601
- /**
15602
- * Given an Item, fetch the data json and return an IModel
15603
- * @param item
15604
- * @param requestOptions
15605
- * @returns
15606
- */
15607
- function fetchModelFromItem(item, requestOptions) {
15608
- return __awaiter(this, void 0, void 0, function () {
15609
- var data;
15610
- return __generator(this, function (_a) {
15611
- switch (_a.label) {
15612
- case 0: return [4 /*yield*/, getItemData(item.id, requestOptions)];
15613
- case 1:
15614
- data = _a.sent();
15615
- return [2 /*return*/, {
15616
- item: item,
15617
- data: data,
15618
- }];
15619
- }
15620
- });
15621
- });
15622
- }
15623
-
15624
- // TODO: work out how to unify content slug fns
15625
- // https: github.com/Esri/hub.js/blob/master/packages/common/src/content/index.ts#L301-L348
15626
- /**
15627
- * Create a slug, namespaced to an org
15628
- * Typically used to lookup items by a human readable name in urls
15629
- *
15630
- * @param title
15631
- * @param orgKey
15632
- * @returns
15633
- */
15634
- function constructSlug(title, orgKey) {
15635
- return orgKey.toLowerCase() + "-" + slugify(title);
15636
- }
15637
- /**
15638
- * Adds/Updates the slug typekeyword
15639
- * Returns a new array of keywords
15640
- * @param typeKeywords
15641
- * @param slug
15642
- * @returns
15643
- */
15644
- function setSlugKeyword(typeKeywords, slug) {
15645
- // remove slug entry from array
15646
- var removed = typeKeywords.filter(function (entry) {
15647
- return !entry.startsWith("slug|");
15648
- });
15649
- // now add it
15650
- removed.push("slug|" + slug);
15651
- return removed;
15652
- }
15653
- /**
15654
- * Get an item by searching for items with a typeKeyword like `slug|{slug-value}`
15655
- *
15656
- * For example, if you pass a slug `"snow-map"` into this function, it will
15657
- * search for items with `slug|snow-map` in it's typeKeywords array,
15658
- *
15659
- * @param slug
15660
- * @param requestOptions
15661
- * @returns
15662
- */
15663
- function getItemBySlug(slug, requestOptions) {
15664
- return findItemsBySlug({ slug: slug }, requestOptions).then(function (results) {
15665
- if (results.length) {
15666
- return results[0];
15667
- }
15668
- else {
15669
- return null;
15670
- }
15671
- });
15672
- }
15673
- /**
15674
- * Find items by slug typeKeywords.
15675
- *
15676
- * Optional exclude parameter accepts the id of an item we expect to
15677
- * have this particular slug. This is used during update calls
15678
- * where we don't know if the slug specifically has been updated, but we
15679
- * don't want a false-postive from the item we are updating
15680
- *
15681
- * @param slug
15682
- * @param requestOptions
15683
- * @returns
15684
- */
15685
- function findItemsBySlug(slugInfo, requestOptions) {
15686
- var opts = {
15687
- filter: "typekeywords:\"slug|" + slugInfo.slug + "\"",
15688
- };
15689
- if (requestOptions.authentication) {
15690
- opts.authentication = requestOptions.authentication;
15691
- }
15692
- else if (requestOptions.portal) {
15693
- opts.portal = requestOptions.portal;
15694
- }
15695
- // We need to check for other items w/ a slug during
15696
- // the update calls. For those scenarios we are interested
15697
- // in any _other_ items which may have a specific slug
15698
- // but not one specific item
15699
- if (slugInfo.exclude) {
15700
- opts.q = "NOT id:" + slugInfo.exclude;
15701
- }
15702
- return searchItems(opts)
15703
- .then(function (response) {
15704
- return response.results;
15705
- })
15706
- .catch(function (e) {
15707
- throw e;
15708
- });
15709
- }
15710
- /**
15711
- * Given a slug, search for items using that slug, incrementing the slug name until
15712
- * a unique value is found
15713
- *
15714
- * For example, if a slug of `"snow-map"` into this function and some item exists
15715
- * with that slug, it would return `"snow-map-1"`.
15716
- *
15717
- * @param slug
15718
- * @param requestOptions
15719
- * @param step
15720
- * @returns
15721
- */
15722
- function getUniqueSlug(slugInfo, requestOptions, step) {
15723
- if (step === void 0) { step = 0; }
15724
- var combinedSlug = slugInfo.slug;
15725
- if (step) {
15726
- combinedSlug = slugInfo.slug + "-" + step;
15727
- }
15728
- return findItemsBySlug({ slug: combinedSlug, exclude: slugInfo.existingId }, requestOptions)
15729
- .then(function (results) {
15730
- if (results.length) {
15731
- step++;
15732
- return getUniqueSlug(slugInfo, requestOptions, step);
15733
- }
15734
- else {
15735
- return combinedSlug;
15736
- }
15737
- })
15738
- .catch(function (e) {
15739
- throw Error("Error in getUniqueSlug " + e);
15740
- });
15741
- }
15742
-
15743
- /**
15744
- * Manage forward and backward property mappings to
15745
- * streamline conversion between the Hub entities, and
15746
- * the backing IModel
15747
- */
15748
- var PropertyMapper = /** @class */ (function () {
15749
- /**
15750
- * Pass in the mappings between the Entity and
15751
- * it's backing structure (model or otherwise)
15752
- * @param mappings
15753
- */
15754
- function PropertyMapper(mappings) {
15755
- this.mappings = mappings;
15756
- }
15757
- /**
15758
- * Map properties from a model on to the entity object.
15759
- *
15760
- * Used when constructing an entity can from a fetched model,
15761
- * in which case the entity should be an empty object (`{}`).
15762
- *
15763
- * Can also be used to apply changes to an entity from a model,
15764
- * in which case an existing entity can be passed in.
15765
- * @param model
15766
- * @param object
15767
- * @returns
15768
- */
15769
- PropertyMapper.prototype.modelToObject = function (model, object) {
15770
- return mapModelToObject(model, object, this.mappings);
15771
- };
15772
- /**
15773
- * Map properties from an entity object onto a model.
15774
- *
15775
- * Typically the model will already exist, and this
15776
- * method is used to transfer changes to the model
15777
- * prior to storage.
15778
- * @param object
15779
- * @param model
15780
- * @returns
15781
- */
15782
- PropertyMapper.prototype.objectToModel = function (object, model) {
15783
- return mapObjectToModel(object, model, this.mappings);
15784
- };
15785
- return PropertyMapper;
15786
- }());
15787
- /**
15788
- * Generic function to apply properties from an Object
15789
- * (i.e. IHubProject) onto a Model that can be persisted to an Item
15790
- * @param object
15791
- * @param model
15792
- * @param mappings
15793
- * @returns
15794
- */
15795
- function mapObjectToModel(object, model, mappings) {
15796
- return mapProps(object, "objectKey", model, "modelKey", mappings);
15797
- }
15798
- /**
15799
- * Generic function to apply properties from a Model
15800
- * onto an Object (i.e. IHubProject etc)
15801
- * @param model
15802
- * @param object
15803
- * @param mappings
15804
- * @returns
15805
- */
15806
- function mapModelToObject(model, object, mappings) {
15807
- return mapProps(model, "modelKey", object, "objectKey", mappings);
15808
- }
15809
- /**
15810
- * Internal function to map between objects
15811
- * @param source
15812
- * @param sourceKey
15813
- * @param target
15814
- * @param targetKey
15815
- * @param mappings
15816
- * @returns
15817
- */
15818
- function mapProps(source, sourceKey, target, targetKey, mappings) {
15819
- // clone the target
15820
- var clone = cloneObject$1(target);
15821
- // walk the property map array
15822
- mappings.forEach(function (entry) {
15823
- // Verbose b/c typescript hates the use of property indexing with generics
15824
- // i.e. entry<T>[sourceKey] make typescript angry
15825
- var sourcePath = getProp(entry, sourceKey);
15826
- var targetPath = getProp(entry, targetKey);
15827
- // get the value from the source
15828
- var sourceVal = getProp(source, sourcePath);
15829
- // if it's not null or undefined
15830
- if (sourceVal !== null && sourceVal !== undefined) {
15831
- // set it
15832
- deepSet(clone, targetPath, sourceVal);
15833
- }
15834
- });
15835
- return clone;
15836
- }
15837
-
15838
- var HUB_PROJECT_ITEM_TYPE = "Hub Project";
15839
- /**
15840
- * Default values of a IHubProject
15841
- */
15842
- var DEFAULT_PROJECT = {
15843
- name: "No title provided",
15844
- tags: [],
15845
- typeKeywords: ["Hub Project"],
15846
- status: "inactive",
15847
- };
15848
- /**
15849
- * Default values for a new HubProject Model
15850
- */
15851
- var DEFAULT_PROJECT_MODEL = {
15852
- item: {
15853
- type: HUB_PROJECT_ITEM_TYPE,
15854
- title: "No Title Provided",
15855
- description: "No Description Provided",
15856
- snippet: "",
15857
- tags: [],
15858
- typeKeywords: ["Hub Project"],
15859
- properties: {
15860
- slug: "",
15861
- },
15862
- },
15863
- data: {
15864
- display: "about",
15865
- timeline: {},
15866
- status: "inactive",
15867
- contacts: [],
15868
- schemaVersion: 1,
15869
- },
15870
- };
15871
- /**
15872
- * Returns an Array of IPropertyMap objects
15873
- * We could define these directly, but since the
15874
- * properties of IHubProject map directly to properties
15875
- * on item or data, it's slightly less verbose to
15876
- * generate the structure.
15877
- * @returns
15878
- */
15879
- function getProjectPropertyMap() {
15880
- var itemProps = [
15881
- "created",
15882
- "culture",
15883
- "description",
15884
- "extent",
15885
- "id",
15886
- "modified",
15887
- "owner",
15888
- "snippet",
15889
- "tags",
15890
- "typeKeywords",
15891
- "url",
14469
+ "typeKeywords",
14470
+ "url",
15892
14471
  "type",
15893
14472
  ];
15894
14473
  var dataProps = [
@@ -18053,7 +16632,7 @@
18053
16632
  */
18054
16633
  function searchPortal$2(searchOptions) {
18055
16634
  return __awaiter(this, void 0, void 0, function () {
18056
- var resp, fn, results, facets, aggregations;
16635
+ var resp, fn, results, aggregations;
18057
16636
  return __generator(this, function (_a) {
18058
16637
  switch (_a.label) {
18059
16638
  case 0: return [4 /*yield*/, searchItems(searchOptions)];
@@ -18065,13 +16644,11 @@
18065
16644
  return [4 /*yield*/, Promise.all(resp.results.map(fn))];
18066
16645
  case 2:
18067
16646
  results = _a.sent();
18068
- facets = convertPortalItemResponseToFacets(resp);
18069
16647
  aggregations = convertPortalAggregations(resp);
18070
16648
  // Construct the return
18071
16649
  return [2 /*return*/, {
18072
16650
  total: resp.total,
18073
16651
  results: results,
18074
- facets: facets,
18075
16652
  aggregations: aggregations,
18076
16653
  hasNext: resp.nextStart > -1,
18077
16654
  next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$2),
@@ -18111,10 +16688,9 @@
18111
16688
  });
18112
16689
  });
18113
16690
  }
18114
- var WellKnownItemFilters = {
16691
+ var WellKnownItemPredicates = {
18115
16692
  $application: [
18116
16693
  {
18117
- filterType: "item",
18118
16694
  type: {
18119
16695
  any: [
18120
16696
  "Web Mapping Application",
@@ -18129,14 +16705,12 @@
18129
16705
  },
18130
16706
  },
18131
16707
  {
18132
- filterType: "item",
18133
16708
  type: "Web Mapping Experience",
18134
16709
  typekeywords: "EXB Experience",
18135
16710
  },
18136
16711
  ],
18137
16712
  $dashboard: [
18138
16713
  {
18139
- filterType: "item",
18140
16714
  type: {
18141
16715
  any: ["Dashboard"],
18142
16716
  not: ["Operation View"],
@@ -18148,7 +16722,6 @@
18148
16722
  ],
18149
16723
  $dataset: [
18150
16724
  {
18151
- filterType: "item",
18152
16725
  type: {
18153
16726
  any: [
18154
16727
  "Scene Service",
@@ -18183,13 +16756,11 @@
18183
16756
  },
18184
16757
  },
18185
16758
  {
18186
- filterType: "item",
18187
16759
  typekeywords: ["OGC", "Geodata Service"],
18188
16760
  },
18189
16761
  ],
18190
16762
  $document: [
18191
16763
  {
18192
- filterType: "item",
18193
16764
  type: [
18194
16765
  "PDF",
18195
16766
  "Microsoft Excel",
@@ -18205,48 +16776,40 @@
18205
16776
  ],
18206
16777
  $initiative: [
18207
16778
  {
18208
- filterType: "item",
18209
16779
  type: "Hub Initiative",
18210
16780
  },
18211
16781
  ],
18212
16782
  $experience: [
18213
16783
  {
18214
- filterType: "item",
18215
16784
  type: "Web Experience",
18216
16785
  },
18217
16786
  ],
18218
16787
  $feedback: [
18219
16788
  {
18220
- filterType: "item",
18221
16789
  type: "Form",
18222
16790
  },
18223
16791
  ],
18224
16792
  $page: [
18225
16793
  {
18226
- filterType: "item",
18227
16794
  typekeywords: "hubPage",
18228
16795
  },
18229
16796
  ],
18230
16797
  $site: [
18231
16798
  {
18232
- filterType: "item",
18233
16799
  type: ["Hub Site Application", "Site Application"],
18234
16800
  },
18235
16801
  ],
18236
16802
  $storymap: [
18237
16803
  {
18238
- filterType: "item",
18239
16804
  type: "Storymap",
18240
16805
  },
18241
16806
  {
18242
- filterType: "item",
18243
16807
  type: "Web Mapping Application",
18244
16808
  typekeywords: "Story Map",
18245
16809
  },
18246
16810
  ],
18247
16811
  $template: [
18248
16812
  {
18249
- filterType: "item",
18250
16813
  type: [
18251
16814
  "Web Mapping Application",
18252
16815
  "Hub Initiative",
@@ -18261,7 +16824,6 @@
18261
16824
  ],
18262
16825
  $webmap: [
18263
16826
  {
18264
- filterType: "item",
18265
16827
  type: {
18266
16828
  any: ["Web Map", "Web Scene"],
18267
16829
  not: "Web Mapping Application",
@@ -18330,7 +16892,7 @@
18330
16892
  function isWellKnownTypeFilter(key) {
18331
16893
  var result = false;
18332
16894
  if (typeof key === "string") {
18333
- result = key in WellKnownItemFilters;
16895
+ result = key in WellKnownItemPredicates;
18334
16896
  }
18335
16897
  return result;
18336
16898
  }
@@ -18340,14 +16902,7 @@
18340
16902
  * @returns
18341
16903
  */
18342
16904
  function lookupTypePredicates(key) {
18343
- var rawPredicates = WellKnownItemFilters[key];
18344
- // Remove the filterType property as it's not needed in an IPredicate
18345
- var predicates = rawPredicates.map(function (entry) {
18346
- var c = cloneObject$1(entry);
18347
- delete c.filterType;
18348
- return c;
18349
- });
18350
- return predicates;
16905
+ return WellKnownItemPredicates[key];
18351
16906
  }
18352
16907
 
18353
16908
  // ## ## ####### ######## ########
@@ -18362,194 +16917,18 @@
18362
16917
  /**
18363
16918
  * @private
18364
16919
  * Execute item search against the Hub API
18365
- * @param filter
16920
+ * @param query
18366
16921
  * @param options
18367
16922
  * @returns
18368
16923
  */
18369
16924
  /* istanbul ignore next */
18370
- function hubSearchItems(filters, options) {
18371
- var _a;
16925
+ function hubSearchItems(query, options) {
18372
16926
  return __awaiter(this, void 0, void 0, function () {
18373
- var api, apiUrl, cleanFilters, searchRequest, aggs, session, opts, raw, json, token_1, us, tokenizeThubmnailUrl, conversion, results, facets, response, ex_1;
18374
- return __generator(this, function (_b) {
18375
- switch (_b.label) {
18376
- case 0:
18377
- api = expandApi(options.api || "hub");
18378
- apiUrl = api.url + "/api/items/beta/search";
18379
- cleanFilters = [];
18380
- filters.forEach(function (block) {
18381
- var b = {
18382
- operation: block.operation,
18383
- filters: block.filters.map(function (f) {
18384
- var c = cloneObject$1(f);
18385
- delete c.filterType;
18386
- return c;
18387
- }),
18388
- };
18389
- cleanFilters.push(b);
18390
- });
18391
- searchRequest = {
18392
- q: cleanFilters,
18393
- options: {
18394
- num: options.num || 10,
18395
- start: options.start || 1,
18396
- sortField: options.sortField,
18397
- sortOrder: options.sortOrder,
18398
- },
18399
- };
18400
- // Add optional props via setProp b/c typescript really does not like
18401
- // adding properties after defining an object
18402
- if ((_a = options.aggFields) === null || _a === void 0 ? void 0 : _a.length) {
18403
- aggs = [
18404
- {
18405
- mode: "terms",
18406
- fields: options.aggFields,
18407
- num: options.aggLimit || 10,
18408
- },
18409
- ];
18410
- setProp("aggregations", aggs, searchRequest.options);
18411
- }
18412
- if (options.authentication) {
18413
- session = {
18414
- token: options.authentication.token,
18415
- portal: options.authentication.portal,
18416
- };
18417
- setProp("session", session, searchRequest.options);
18418
- }
18419
- opts = {
18420
- method: "POST",
18421
- mode: "cors",
18422
- cache: "no-cache",
18423
- headers: {
18424
- "Content-Type": "application/json",
18425
- },
18426
- body: JSON.stringify(searchRequest),
18427
- };
18428
- _b.label = 1;
18429
- case 1:
18430
- _b.trys.push([1, 5, , 6]);
18431
- return [4 /*yield*/, fetch(apiUrl, opts)];
18432
- case 2:
18433
- raw = _b.sent();
18434
- return [4 /*yield*/, raw.json()];
18435
- case 3:
18436
- json = _b.sent();
18437
- if (options.authentication) {
18438
- us = options.authentication;
18439
- token_1 = us.token;
18440
- }
18441
- tokenizeThubmnailUrl = function (entry) {
18442
- if (token_1 && entry.attributes.access !== "public") {
18443
- entry.attributes.thumbnailUrl = entry.attributes.thumbnailUrl + "?token=" + token_1;
18444
- }
18445
- return entry;
18446
- };
18447
- json.data = json.data.map(tokenizeThubmnailUrl);
18448
- conversion = function (entry) {
18449
- return hubContentToSearchResult(jsonApiToHubContent(entry));
18450
- };
18451
- return [4 /*yield*/, Promise.all(json.data.map(conversion))];
18452
- case 4:
18453
- results = _b.sent();
18454
- facets = convertHubResponseToFacets(json);
18455
- response = {
18456
- total: json.meta.total,
18457
- results: results,
18458
- facets: facets,
18459
- hasNext: json.meta.hasNext,
18460
- next: function () {
18461
- // tslint:disable-next-line
18462
- Promise.resolve(null);
18463
- },
18464
- };
18465
- return [2 /*return*/, Promise.resolve(response)];
18466
- case 5:
18467
- ex_1 = _b.sent();
18468
- // TODO: Turn into a formal error
18469
- throw ex_1;
18470
- case 6: return [2 /*return*/];
18471
- }
16927
+ return __generator(this, function (_a) {
16928
+ throw new Error("Not implemented");
18472
16929
  });
18473
16930
  });
18474
16931
  }
18475
- /**
18476
- * Re-structure a jsonApi data entry into a flat object cast into
18477
- * IHubContent
18478
- * @param data
18479
- * @returns
18480
- */
18481
- /* istanbul ignore next */
18482
- function jsonApiToHubContent(data) {
18483
- var content = cloneObject$1(data.attributes);
18484
- content.id = data.id;
18485
- return content;
18486
- }
18487
- /* istanbul ignore next */
18488
- function hubContentToSearchResult(content) {
18489
- var result = {
18490
- access: content.access,
18491
- id: content.id,
18492
- type: content.type,
18493
- name: content.name,
18494
- owner: content.owner,
18495
- summary: content.snippet || content.description,
18496
- createdDate: new Date(content.createdDate),
18497
- createdDateSource: content.createdDateSource,
18498
- updatedDate: new Date(content.updatedDate),
18499
- updatedDateSource: content.updatedDateSource,
18500
- thumbnailUrl: content.thumbnailUrl,
18501
- metadata: [],
18502
- family: content.family,
18503
- urls: {
18504
- portalHome: "not-implemented",
18505
- relative: "not-implemented",
18506
- },
18507
- };
18508
- // TODO: Per-type plucking of props into the `meta` hash for use in the card components
18509
- return Promise.resolve(result);
18510
- }
18511
- /* istanbul ignore next */
18512
- function convertHubResponseToFacets(response, operation) {
18513
- var _a;
18514
- if (operation === void 0) { operation = "OR"; }
18515
- var result = [];
18516
- if ((_a = response.meta) === null || _a === void 0 ? void 0 : _a.aggregations) {
18517
- var meta = response.meta;
18518
- meta.aggregations.forEach(function (entry) {
18519
- // Dyanmic facets typically "AND" so we are refining
18520
- var facet = {
18521
- label: entry.field,
18522
- key: entry.field,
18523
- aggField: entry.field,
18524
- display: "multi-select",
18525
- operation: operation,
18526
- };
18527
- var options = [];
18528
- entry.values.forEach(function (fv) {
18529
- var filter = {
18530
- filterType: "item",
18531
- };
18532
- // construct the filter based on the operation
18533
- var matchKey = operation === "OR" ? "any" : "all";
18534
- var filterMatchOption = {};
18535
- filterMatchOption[matchKey] = [fv.value];
18536
- filter[entry.field] = filterMatchOption;
18537
- // construct the FacetOption
18538
- var fo = {
18539
- label: fv.value + " (" + fv.count + ")",
18540
- key: fv.value,
18541
- count: fv.count,
18542
- selected: false,
18543
- filters: [filter],
18544
- };
18545
- options.push(fo);
18546
- });
18547
- facet.options = options;
18548
- result.push(facet);
18549
- });
18550
- }
18551
- return result;
18552
- }
18553
16932
 
18554
16933
  /**
18555
16934
  * @private
@@ -18622,7 +17001,6 @@
18622
17001
  return [2 /*return*/, {
18623
17002
  total: resp.total,
18624
17003
  results: results,
18625
- facets: [],
18626
17004
  hasNext: resp.nextStart > -1,
18627
17005
  next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$1),
18628
17006
  }];
@@ -18723,102 +17101,672 @@
18723
17101
  return [2 /*return*/, {
18724
17102
  total: resp.total,
18725
17103
  results: results,
18726
- facets: [],
18727
17104
  hasNext: resp.nextStart > -1,
18728
17105
  next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal),
18729
17106
  }];
18730
17107
  }
18731
17108
  });
18732
- });
18733
- }
17109
+ });
17110
+ }
17111
+ /**
17112
+ * Convert an Item to a IHubSearchResult
17113
+ * Fetches the includes and attaches them to the item
17114
+ * @param item
17115
+ * @param includes
17116
+ * @param requestOptions
17117
+ * @returns
17118
+ */
17119
+ function userToSearchResult(user, includes, requestOptions) {
17120
+ if (includes === void 0) { includes = []; }
17121
+ return __awaiter(this, void 0, void 0, function () {
17122
+ return __generator(this, function (_a) {
17123
+ // Delegate to HubGroups module
17124
+ // This layer of indirection is not necessary but
17125
+ // aligns with how the items search works and
17126
+ // allows for future specialization
17127
+ return [2 /*return*/, enrichUserSearchResult(user, includes, requestOptions)];
17128
+ });
17129
+ });
17130
+ }
17131
+
17132
+ /**
17133
+ * @private
17134
+ * TEMPORARY - this function only exists to allow incremental
17135
+ * changes and should be removed as soon as arcgis-hub-gallery
17136
+ * is changed to call `hubSearch(...)` directly
17137
+ *
17138
+ * Default's to search ArcGIS Portal but can delegate
17139
+ * to Hub API when it's available.
17140
+ * @param filterGroups
17141
+ * @param options
17142
+ * @returns
17143
+ */
17144
+ function hubSearchQuery(query, options) {
17145
+ return __awaiter(this, void 0, void 0, function () {
17146
+ return __generator(this, function (_a) {
17147
+ // delegate
17148
+ return [2 /*return*/, hubSearch(query, options)];
17149
+ });
17150
+ });
17151
+ }
17152
+ /**
17153
+ * Main entrypoint for searching via Hub
17154
+ *
17155
+ * Default's to search ArcGIS Portal but can delegate
17156
+ * to Hub API when it's available.
17157
+ * @param query
17158
+ * @param options
17159
+ * @returns
17160
+ */
17161
+ function hubSearch(query, options) {
17162
+ return __awaiter(this, void 0, void 0, function () {
17163
+ var filterType, apiType, fnHash, fn;
17164
+ return __generator(this, function (_a) {
17165
+ // Validate inputs
17166
+ if (!query) {
17167
+ throw new HubError$1("hubSearch", "Query is required.");
17168
+ }
17169
+ if (!query.filters || !query.filters.length) {
17170
+ throw new HubError$1("hubSearch", "Query must contain at least one Filter.");
17171
+ }
17172
+ if (!options.requestOptions) {
17173
+ throw new HubError$1("hubSearch", "requestOptions: IHubRequestOptions is required.");
17174
+ }
17175
+ // Ensure includes is an array
17176
+ if (!options.include) {
17177
+ options.include = [];
17178
+ }
17179
+ filterType = query.targetEntity;
17180
+ apiType = expandApi(options.api || "arcgis").type;
17181
+ fnHash = {
17182
+ arcgis: {
17183
+ item: portalSearchItems,
17184
+ group: portalSearchGroups,
17185
+ user: portalSearchUsers,
17186
+ },
17187
+ "arcgis-hub": {
17188
+ item: hubSearchItems,
17189
+ },
17190
+ };
17191
+ fn = getProp(fnHash, apiType + "." + filterType);
17192
+ if (!fn) {
17193
+ throw new HubError$1("hubSearch", "Search via \"" + filterType + "\" filter against \"" + apiType + "\" api is not implemented. Please ensure \"targetEntity\" is defined on the query.");
17194
+ }
17195
+ return [2 /*return*/, fn(cloneObject$1(query), options)];
17196
+ });
17197
+ });
17198
+ }
17199
+
17200
+ /**
17201
+ * Collection Class
17202
+ *
17203
+ * Abstracts searching a Collection
17204
+ *
17205
+ * For more information, check out the [Catalog & Collection Guide](/hub.js/guides/concepts/catalog-collection/)
17206
+ */
17207
+ var Collection = /** @class */ (function () {
17208
+ function Collection(collection, context) {
17209
+ this._collection = collection;
17210
+ this._context = context;
17211
+ }
17212
+ /**
17213
+ * Create an instance of a Collection from a JSON object
17214
+ * @param collection
17215
+ * @param context
17216
+ * @returns
17217
+ */
17218
+ Collection.fromJson = function (collection, context) {
17219
+ return new Collection(collection, context);
17220
+ };
17221
+ /**
17222
+ * Return the JSON object backing the instance
17223
+ * @returns
17224
+ */
17225
+ Collection.prototype.toJson = function () {
17226
+ return cloneObject$1(this._collection);
17227
+ };
17228
+ Object.defineProperty(Collection.prototype, "label", {
17229
+ // Getters
17230
+ get: function () {
17231
+ return this._collection.label;
17232
+ },
17233
+ enumerable: false,
17234
+ configurable: true
17235
+ });
17236
+ Object.defineProperty(Collection.prototype, "key", {
17237
+ get: function () {
17238
+ return this._collection.key;
17239
+ },
17240
+ enumerable: false,
17241
+ configurable: true
17242
+ });
17243
+ Object.defineProperty(Collection.prototype, "include", {
17244
+ get: function () {
17245
+ return this._collection.include || [];
17246
+ },
17247
+ enumerable: false,
17248
+ configurable: true
17249
+ });
17250
+ Object.defineProperty(Collection.prototype, "scope", {
17251
+ get: function () {
17252
+ return this._collection.scope;
17253
+ },
17254
+ enumerable: false,
17255
+ configurable: true
17256
+ });
17257
+ Object.defineProperty(Collection.prototype, "sortField", {
17258
+ get: function () {
17259
+ return this._collection.sortField || "title";
17260
+ },
17261
+ enumerable: false,
17262
+ configurable: true
17263
+ });
17264
+ Object.defineProperty(Collection.prototype, "sortDirection", {
17265
+ get: function () {
17266
+ return this._collection.sortDirection || "asc";
17267
+ },
17268
+ enumerable: false,
17269
+ configurable: true
17270
+ });
17271
+ Object.defineProperty(Collection.prototype, "targetEntity", {
17272
+ get: function () {
17273
+ return this._collection.targetEntity;
17274
+ },
17275
+ enumerable: false,
17276
+ configurable: true
17277
+ });
17278
+ /**
17279
+ * Search the collection using a string or IQuery
17280
+ * @param query
17281
+ * @param options
17282
+ * @returns
17283
+ */
17284
+ Collection.prototype.search = function (query, options) {
17285
+ if (options === void 0) { options = {}; }
17286
+ return __awaiter(this, void 0, void 0, function () {
17287
+ var qry, opts;
17288
+ return __generator(this, function (_a) {
17289
+ if (typeof query === "string") {
17290
+ // construct a query from that...
17291
+ qry = {
17292
+ targetEntity: this._collection.targetEntity,
17293
+ filters: [
17294
+ {
17295
+ predicates: [
17296
+ {
17297
+ term: query,
17298
+ },
17299
+ ],
17300
+ },
17301
+ ],
17302
+ };
17303
+ }
17304
+ else {
17305
+ qry = query;
17306
+ }
17307
+ // TODO: What should happen when a Query is passed in that has a targetEntity that doesn't match the collection's targetEntity?
17308
+ // merge the passed in query w/ the scope
17309
+ qry.filters = __spreadArrays(qry.filters, this.scope.filters);
17310
+ opts = cloneObject$1(options);
17311
+ opts.requestOptions = this._context.hubRequestOptions;
17312
+ // inject default sort info if not specified
17313
+ opts.sortField = options.sortField || this.sortField;
17314
+ opts.sortOrder = options.sortOrder || this.sortDirection;
17315
+ // inject default includes if not specified
17316
+ opts.include = options.include || this.include;
17317
+ // execute the search and return results
17318
+ return [2 /*return*/, hubSearch(qry, opts)];
17319
+ });
17320
+ });
17321
+ };
17322
+ return Collection;
17323
+ }());
17324
+
18734
17325
  /**
18735
- * Convert an Item to a IHubSearchResult
18736
- * Fetches the includes and attaches them to the item
18737
- * @param item
18738
- * @param includes
17326
+ * Fetch a IHubCatalog from a backing item.
17327
+ * This will apply schema upgrades to the structure
17328
+ * @param identifier
18739
17329
  * @param requestOptions
18740
17330
  * @returns
18741
17331
  */
18742
- function userToSearchResult(user, includes, requestOptions) {
18743
- if (includes === void 0) { includes = []; }
17332
+ function fetchCatalog(identifier, requestOptions) {
18744
17333
  return __awaiter(this, void 0, void 0, function () {
17334
+ var getPrms, url, fetched;
18745
17335
  return __generator(this, function (_a) {
18746
- // Delegate to HubGroups module
18747
- // This layer of indirection is not necessary but
18748
- // aligns with how the items search works and
18749
- // allows for future specialization
18750
- return [2 /*return*/, enrichUserSearchResult(user, includes, requestOptions)];
17336
+ switch (_a.label) {
17337
+ case 0:
17338
+ // identifier can be a guid or a url
17339
+ if (identifier.indexOf("http") === 0) {
17340
+ url = identifier;
17341
+ // get down the the hostname
17342
+ url = stripProtocol(url);
17343
+ // if url does not include a hash (i.e. it's not portal)
17344
+ // then we want to split on the first slash to get the hostname
17345
+ // lookupDomain will handle the enterprise base urls
17346
+ if (!url.includes("#")) {
17347
+ url = url.split("/")[0];
17348
+ }
17349
+ getPrms = lookupDomain(url, requestOptions)
17350
+ // get the item's data, and read the catalog out of it
17351
+ .then(function (_a) {
17352
+ var siteId = _a.siteId;
17353
+ return getItemData(siteId, requestOptions);
17354
+ })
17355
+ .then(function (data) {
17356
+ return upgradeCatalogSchema(data.catalog || {});
17357
+ });
17358
+ }
17359
+ else if (isGuid(identifier)) {
17360
+ // get the item's data, and read the catalog out of it
17361
+ getPrms = getItemData(identifier, requestOptions).then(function (data) {
17362
+ return upgradeCatalogSchema(data.catalog || {});
17363
+ });
17364
+ }
17365
+ else {
17366
+ throw new HubError$1("Catalog.create", "Identifier must be a url, guid");
17367
+ }
17368
+ return [4 /*yield*/, getPrms];
17369
+ case 1:
17370
+ fetched = _a.sent();
17371
+ return [2 /*return*/, fetched];
17372
+ }
18751
17373
  });
18752
17374
  });
18753
17375
  }
18754
17376
 
18755
17377
  /**
18756
- * @private
18757
- * TEMPORARY - this function only exists to allow incremental
18758
- * changes and should be removed as soon as arcgis-hub-gallery
18759
- * is changed to call `hubSearch(...)` directly
17378
+ * Catalog Class
18760
17379
  *
18761
- * Default's to search ArcGIS Portal but can delegate
18762
- * to Hub API when it's available.
18763
- * @param filterGroups
18764
- * @param options
18765
- * @returns
17380
+ * Abstracts working with Catalogs and fetching collections with
17381
+ * the correct scope applied.
17382
+ *
17383
+ * For more information, check out the [Catalog & Collection Guide](/hub.js/guides/concepts/catalog-collection/)
18766
17384
  */
18767
- function hubSearchQuery(query, options) {
18768
- return __awaiter(this, void 0, void 0, function () {
18769
- return __generator(this, function (_a) {
18770
- // delegate
18771
- return [2 /*return*/, hubSearch(query, options)];
17385
+ var Catalog = /** @class */ (function () {
17386
+ // internal - use static factory methods
17387
+ function Catalog(catalog, context) {
17388
+ this._catalog = catalog;
17389
+ this._context = context;
17390
+ }
17391
+ /**
17392
+ * Create a Collection instance from a Catalog json object, a site url or itemId
17393
+ * '''js
17394
+ * const catalog = await Catalog.create('https://site-org.hub.arcgis.com', context);
17395
+ * '''
17396
+ *
17397
+ * @param identifier
17398
+ * @param context
17399
+ * @returns
17400
+ */
17401
+ Catalog.init = function (identifier, context) {
17402
+ return __awaiter(this, void 0, void 0, function () {
17403
+ var mgr, fetched;
17404
+ return __generator(this, function (_a) {
17405
+ switch (_a.label) {
17406
+ case 0:
17407
+ if (!!context) return [3 /*break*/, 2];
17408
+ return [4 /*yield*/, ArcGISContextManager.create()];
17409
+ case 1:
17410
+ mgr = _a.sent();
17411
+ context = mgr.context;
17412
+ _a.label = 2;
17413
+ case 2: return [4 /*yield*/, fetchCatalog(identifier, context.hubRequestOptions)];
17414
+ case 3:
17415
+ fetched = _a.sent();
17416
+ // return an instance
17417
+ return [2 /*return*/, new Catalog(fetched, context)];
17418
+ }
17419
+ });
18772
17420
  });
17421
+ };
17422
+ /**
17423
+ * Create a Catalog instance from a Catalog Json object
17424
+ * @param json
17425
+ * @param context
17426
+ * @returns
17427
+ */
17428
+ Catalog.fromJson = function (json, context) {
17429
+ // ensure it's in the latest structure
17430
+ var catalog = upgradeCatalogSchema(json);
17431
+ return new Catalog(catalog, context);
17432
+ };
17433
+ /**
17434
+ * Return the JSON object backing the instance
17435
+ * @returns
17436
+ */
17437
+ Catalog.prototype.toJson = function () {
17438
+ return cloneObject$1(this._catalog);
17439
+ };
17440
+ Object.defineProperty(Catalog.prototype, "schemaVersion", {
17441
+ /**
17442
+ * Return the schema version
17443
+ */
17444
+ get: function () {
17445
+ return this._catalog.schemaVersion;
17446
+ },
17447
+ enumerable: false,
17448
+ configurable: true
18773
17449
  });
18774
- }
18775
- /**
18776
- * Main entrypoint for searching via Hub
18777
- *
18778
- * Default's to search ArcGIS Portal but can delegate
18779
- * to Hub API when it's available.
18780
- * @param query
18781
- * @param options
18782
- * @returns
18783
- */
18784
- function hubSearch(query, options) {
18785
- return __awaiter(this, void 0, void 0, function () {
18786
- var filterType, apiType, fnHash, fn;
18787
- return __generator(this, function (_a) {
18788
- // Validate inputs
18789
- if (!query) {
18790
- throw new HubError$1("hubSearch", "Query is required.");
18791
- }
18792
- if (!query.filters || !query.filters.length) {
18793
- throw new HubError$1("hubSearch", "Query must contain at least one Filter.");
18794
- }
18795
- if (!options.requestOptions) {
18796
- throw new HubError$1("hubSearch", "requestOptions: IHubRequestOptions is required.");
18797
- }
18798
- // Ensure includes is an array
18799
- if (!options.include) {
18800
- options.include = [];
17450
+ Object.defineProperty(Catalog.prototype, "title", {
17451
+ /**
17452
+ * Title getter
17453
+ */
17454
+ get: function () {
17455
+ return this._catalog.title;
17456
+ },
17457
+ /**
17458
+ * Title setter
17459
+ */
17460
+ set: function (v) {
17461
+ this._catalog.title = v;
17462
+ },
17463
+ enumerable: false,
17464
+ configurable: true
17465
+ });
17466
+ Object.defineProperty(Catalog.prototype, "scopes", {
17467
+ /**
17468
+ * Return the existing scopes hash
17469
+ */
17470
+ get: function () {
17471
+ return this._catalog.scopes;
17472
+ },
17473
+ enumerable: false,
17474
+ configurable: true
17475
+ });
17476
+ Object.defineProperty(Catalog.prototype, "availableScopes", {
17477
+ /**
17478
+ * Return an array of the entity types available in this Catalog
17479
+ */
17480
+ get: function () {
17481
+ return Object.keys(this.scopes);
17482
+ },
17483
+ enumerable: false,
17484
+ configurable: true
17485
+ });
17486
+ /**
17487
+ * Get the scope's query for a particular entity type
17488
+ * @param type
17489
+ * @returns
17490
+ */
17491
+ Catalog.prototype.getScope = function (type) {
17492
+ return this._catalog.scopes[type];
17493
+ };
17494
+ /**
17495
+ * Set the scope for a specific entity type
17496
+ * @param type
17497
+ * @param query
17498
+ */
17499
+ Catalog.prototype.setScope = function (type, query) {
17500
+ this._catalog.scopes[type] = query;
17501
+ };
17502
+ Object.defineProperty(Catalog.prototype, "collections", {
17503
+ /**
17504
+ * Get the collections array. Returns simple objects not Collection instances
17505
+ */
17506
+ get: function () {
17507
+ return this._catalog.collections || [];
17508
+ },
17509
+ enumerable: false,
17510
+ configurable: true
17511
+ });
17512
+ Object.defineProperty(Catalog.prototype, "collectionNames", {
17513
+ /**
17514
+ * Get the names of the collections
17515
+ */
17516
+ get: function () {
17517
+ return mapBy("key", this.collections);
17518
+ },
17519
+ enumerable: false,
17520
+ configurable: true
17521
+ });
17522
+ /**
17523
+ * Get a Collection instance by name
17524
+ * @param name
17525
+ * @returns
17526
+ */
17527
+ Catalog.prototype.getCollection = function (name) {
17528
+ var json = this.collections.find(function (entry) { return entry.key === name; });
17529
+ if (json) {
17530
+ // clone it then merge in the associated scope filter
17531
+ var clone = cloneObject$1(json);
17532
+ var catalogScope = this.getScope(clone.scope.targetEntity);
17533
+ if (catalogScope === null || catalogScope === void 0 ? void 0 : catalogScope.filters) {
17534
+ clone.scope.filters = __spreadArrays(clone.scope.filters, catalogScope.filters);
18801
17535
  }
18802
- filterType = query.targetEntity;
18803
- apiType = expandApi(options.api || "arcgis").type;
18804
- fnHash = {
18805
- arcgis: {
18806
- item: portalSearchItems,
18807
- group: portalSearchGroups,
18808
- user: portalSearchUsers,
17536
+ return Collection.fromJson(clone, this._context);
17537
+ }
17538
+ else {
17539
+ throw new HubError$1("getCollection", "Collection \"" + name + "\" is not present in the Catalog");
17540
+ }
17541
+ };
17542
+ /**
17543
+ * Search for Items
17544
+ * Will throw if the Catalog does not have a scope defined for items
17545
+ * @param query
17546
+ * @param options
17547
+ * @returns
17548
+ */
17549
+ Catalog.prototype.searchItems = function (query, options) {
17550
+ if (options === void 0) { options = {}; }
17551
+ if (!this.getScope("item")) {
17552
+ var result = this.getEmptyResult();
17553
+ result.messages = [
17554
+ {
17555
+ code: "missingScope",
17556
+ message: "Catalog does not have a scope for items",
17557
+ data: {
17558
+ scope: "item",
17559
+ },
18809
17560
  },
18810
- "arcgis-hub": {
18811
- item: hubSearchItems,
17561
+ ];
17562
+ return Promise.resolve(result);
17563
+ }
17564
+ else {
17565
+ // ensure it's an item search
17566
+ options.targetEntity = "item";
17567
+ return this.search(query, options);
17568
+ }
17569
+ };
17570
+ /**
17571
+ * Search for Groups
17572
+ * Will throw if the Catalog does not have a scope defined for groups
17573
+ * @param query
17574
+ * @param options
17575
+ * @returns
17576
+ */
17577
+ Catalog.prototype.searchGroups = function (query, options) {
17578
+ if (options === void 0) { options = {}; }
17579
+ if (!this.getScope("group")) {
17580
+ var result = this.getEmptyResult();
17581
+ result.messages = [
17582
+ {
17583
+ code: "missingScope",
17584
+ message: "Catalog does not have a scope for groups",
17585
+ data: {
17586
+ scope: "group",
17587
+ },
18812
17588
  },
18813
- };
18814
- fn = getProp(fnHash, apiType + "." + filterType);
18815
- if (!fn) {
18816
- throw new HubError$1("hubSearch", "Search via \"" + filterType + "\" filter against \"" + apiType + "\" api is not implemented");
18817
- }
18818
- return [2 /*return*/, fn(cloneObject$1(query), options)];
17589
+ ];
17590
+ return Promise.resolve(result);
17591
+ }
17592
+ else {
17593
+ // ensure it's an group search
17594
+ options.targetEntity = "group";
17595
+ return this.search(query, options);
17596
+ }
17597
+ };
17598
+ /**
17599
+ * Search for Users
17600
+ * Will throw if the Catalog does not have a scope defined for users
17601
+ * @param query
17602
+ * @param options
17603
+ * @returns
17604
+ */
17605
+ Catalog.prototype.searchUsers = function (query, options) {
17606
+ if (options === void 0) { options = {}; }
17607
+ if (!this.getScope("user")) {
17608
+ var result = this.getEmptyResult();
17609
+ result.messages = [
17610
+ {
17611
+ code: "missingScope",
17612
+ message: "Catalog does not have a scope for user",
17613
+ data: {
17614
+ scope: "user",
17615
+ },
17616
+ },
17617
+ ];
17618
+ return Promise.resolve(result);
17619
+ }
17620
+ else {
17621
+ // ensure it's an group search
17622
+ options.targetEntity = "user";
17623
+ return this.search(query, options);
17624
+ }
17625
+ };
17626
+ /**
17627
+ * Execute a search against all the collections in the Catalog
17628
+ * @param query
17629
+ * @param options
17630
+ * @returns
17631
+ */
17632
+ Catalog.prototype.searchCollections = function (query, options) {
17633
+ if (options === void 0) { options = {}; }
17634
+ return __awaiter(this, void 0, void 0, function () {
17635
+ var qry, promiseKeys, promises, responses, hash, i;
17636
+ var _this = this;
17637
+ return __generator(this, function (_a) {
17638
+ switch (_a.label) {
17639
+ case 0:
17640
+ qry = {
17641
+ targetEntity: "item",
17642
+ filters: [
17643
+ {
17644
+ predicates: [
17645
+ {
17646
+ term: query,
17647
+ },
17648
+ ],
17649
+ },
17650
+ ],
17651
+ };
17652
+ promiseKeys = [];
17653
+ promises = this.collectionNames.map(function (name) {
17654
+ var col = _this.getCollection(name);
17655
+ promiseKeys.push(name);
17656
+ qry.targetEntity = col.targetEntity;
17657
+ return col.search(qry, options);
17658
+ });
17659
+ return [4 /*yield*/, Promise.all(promises)];
17660
+ case 1:
17661
+ responses = _a.sent();
17662
+ hash = {};
17663
+ for (i = 0; i < promiseKeys.length; i++) {
17664
+ hash[promiseKeys[i]] = responses[i];
17665
+ }
17666
+ return [2 /*return*/, hash];
17667
+ }
17668
+ });
18819
17669
  });
18820
- });
18821
- }
17670
+ };
17671
+ /**
17672
+ * Execute a search against all the scopes in the Catalog
17673
+ * @param query
17674
+ * @param options
17675
+ * @returns
17676
+ */
17677
+ Catalog.prototype.searchScopes = function (query, options) {
17678
+ if (options === void 0) { options = {}; }
17679
+ return __awaiter(this, void 0, void 0, function () {
17680
+ var qry, promiseKeys, promises, responses, hash, i;
17681
+ var _this = this;
17682
+ return __generator(this, function (_a) {
17683
+ switch (_a.label) {
17684
+ case 0:
17685
+ qry = {
17686
+ targetEntity: "item",
17687
+ filters: [
17688
+ {
17689
+ predicates: [
17690
+ {
17691
+ term: query,
17692
+ },
17693
+ ],
17694
+ },
17695
+ ],
17696
+ };
17697
+ promiseKeys = [];
17698
+ promises = this.availableScopes.map(function (name) {
17699
+ promiseKeys.push(name);
17700
+ // make clones
17701
+ var qryClone = cloneObject$1(qry);
17702
+ var optsClone = cloneObject$1(options);
17703
+ // set the target entity
17704
+ qryClone.targetEntity = name;
17705
+ optsClone.targetEntity = name;
17706
+ // return the search promise
17707
+ return _this.search(qryClone, optsClone);
17708
+ });
17709
+ return [4 /*yield*/, Promise.all(promises)];
17710
+ case 1:
17711
+ responses = _a.sent();
17712
+ hash = {};
17713
+ for (i = 0; i < promiseKeys.length; i++) {
17714
+ hash[promiseKeys[i]] = responses[i];
17715
+ }
17716
+ return [2 /*return*/, hash];
17717
+ }
17718
+ });
17719
+ });
17720
+ };
17721
+ /**
17722
+ * Execute a search against the Catalog as a whole
17723
+ * @param query
17724
+ * @param targetEntity
17725
+ * @returns
17726
+ */
17727
+ Catalog.prototype.search = function (query, options) {
17728
+ var targetEntity = options.targetEntity;
17729
+ var qry;
17730
+ if (typeof query === "string") {
17731
+ qry = {
17732
+ targetEntity: targetEntity,
17733
+ filters: [
17734
+ {
17735
+ predicates: [
17736
+ {
17737
+ term: query,
17738
+ },
17739
+ ],
17740
+ },
17741
+ ],
17742
+ };
17743
+ }
17744
+ else {
17745
+ qry = cloneObject$1(query);
17746
+ }
17747
+ // Now merge in catalog scope level filters
17748
+ qry.filters = __spreadArrays(qry.filters, this.getScope(targetEntity).filters);
17749
+ var opts = cloneObject$1(options);
17750
+ // An Catalog instance always uses the context so we remove/replace any passed in auth
17751
+ delete opts.authentication;
17752
+ opts.requestOptions = this._context.hubRequestOptions;
17753
+ return hubSearch(qry, opts);
17754
+ };
17755
+ /**
17756
+ * Construct an empty result. Returned when a search is performed against an entity type that
17757
+ * does not have a scope defined.
17758
+ * @returns
17759
+ */
17760
+ Catalog.prototype.getEmptyResult = function () {
17761
+ return {
17762
+ results: [],
17763
+ total: 0,
17764
+ hasNext: false,
17765
+ next: null,
17766
+ };
17767
+ };
17768
+ return Catalog;
17769
+ }());
18822
17770
 
18823
17771
  /**
18824
17772
  * Enrich a generic search result
@@ -20430,6 +19378,8 @@
20430
19378
 
20431
19379
  exports.ArcGISContext = ArcGISContext;
20432
19380
  exports.ArcGISContextManager = ArcGISContextManager;
19381
+ exports.Catalog = Catalog;
19382
+ exports.Collection = Collection;
20433
19383
  exports.DEFAULT_THEME = DEFAULT_THEME;
20434
19384
  exports.ENTERPRISE_SITE_ITEM_TYPE = ENTERPRISE_SITE_ITEM_TYPE;
20435
19385
  exports.GLOBAL_EXTENT = GLOBAL_EXTENT;
@@ -20479,9 +19429,6 @@
20479
19429
  exports._processInvite = _processInvite;
20480
19430
  exports._processPrimaryEmail = _processPrimaryEmail;
20481
19431
  exports._processSecondaryEmail = _processSecondaryEmail;
20482
- exports._searchContent = _searchContent;
20483
- exports._searchGroups = _searchGroups;
20484
- exports._searchUsers = _searchUsers;
20485
19432
  exports._unprotectAndRemoveGroup = _unprotectAndRemoveGroup;
20486
19433
  exports._unprotectAndRemoveItem = _unprotectAndRemoveItem;
20487
19434
  exports.addContextToSlug = addContextToSlug;
@@ -20491,7 +19438,6 @@
20491
19438
  exports.addSiteDomains = addSiteDomains;
20492
19439
  exports.addSolutionResourceUrlToAssets = addSolutionResourceUrlToAssets;
20493
19440
  exports.addUsersToGroup = addUsersToGroup;
20494
- exports.applyCollectionState = applyCollectionState;
20495
19441
  exports.applyPropertiesToItems = applyPropertiesToItems;
20496
19442
  exports.arrayToObject = arrayToObject;
20497
19443
  exports.atob = abab.atob;
@@ -20518,12 +19464,8 @@
20518
19464
  exports.composeContent = composeContent;
20519
19465
  exports.constructSlug = constructSlug;
20520
19466
  exports.convertCatalog = convertCatalog;
20521
- exports.convertContentDefinitionToFilter = convertContentDefinitionToFilter;
20522
- exports.convertContentFilterToSearchOptions = convertContentFilterToSearchOptions;
20523
19467
  exports.convertItemToProject = convertItemToProject;
20524
19468
  exports.convertItemToSite = convertItemToSite;
20525
- exports.convertPortalItemResponseToFacets = convertPortalItemResponseToFacets;
20526
- exports.convertPortalResponseToFacets = convertPortalResponseToFacets;
20527
19469
  exports.convertSolutionTemplateResourcesToAssets = convertSolutionTemplateResourcesToAssets;
20528
19470
  exports.convertToWellKnownLocale = convertToWellKnownLocale;
20529
19471
  exports.convertUrlsToAnchorTags = convertUrlsToAnchorTags;
@@ -20561,10 +19503,6 @@
20561
19503
  exports.ensureUniqueString = ensureUniqueString;
20562
19504
  exports.expandApi = expandApi;
20563
19505
  exports.expandApis = expandApis;
20564
- exports.expandContentFilter = expandContentFilter;
20565
- exports.expandGroupFilter = expandGroupFilter;
20566
- exports.expandTypeField = expandTypeField;
20567
- exports.expandUserFilter = expandUserFilter;
20568
19506
  exports.extend = extend;
20569
19507
  exports.extentToBBox = extentToBBox;
20570
19508
  exports.extentToPolygon = extentToPolygon;
@@ -20665,8 +19603,6 @@
20665
19603
  exports.isDomainForLegacySite = isDomainForLegacySite;
20666
19604
  exports.isDomainUsedElsewhere = isDomainUsedElsewhere;
20667
19605
  exports.isDownloadable = isDownloadable;
20668
- exports.isEmptyFilter = isEmptyFilter;
20669
- exports.isEmptyFilterGroup = isEmptyFilterGroup;
20670
19606
  exports.isExtentCoordinateArray = isExtentCoordinateArray;
20671
19607
  exports.isFeatureService = isFeatureService$1;
20672
19608
  exports.isFieldworkerView = isFieldworkerView;
@@ -20685,13 +19621,7 @@
20685
19621
  exports.mapBy = mapBy;
20686
19622
  exports.maybeAdd = maybeAdd;
20687
19623
  exports.maybePush = maybePush;
20688
- exports.mergeContentFilter = mergeContentFilter;
20689
- exports.mergeDateRange = mergeDateRange;
20690
- exports.mergeGroupFilters = mergeGroupFilters;
20691
- exports.mergeMatchOptions = mergeMatchOptions;
20692
19624
  exports.mergeObjects = mergeObjects;
20693
- exports.mergeSearchOptions = mergeSearchOptions$1;
20694
- exports.mergeUserFilters = mergeUserFilters;
20695
19625
  exports.normalizeItemType = normalizeItemType;
20696
19626
  exports.normalizeSolutionTemplateItem = normalizeSolutionTemplateItem;
20697
19627
  exports.objectToArray = objectToArray;
@@ -20713,16 +19643,9 @@
20713
19643
  exports.saveSession = saveSession;
20714
19644
  exports.searchProjects = searchProjects;
20715
19645
  exports.searchSites = searchSites;
20716
- exports.serializeCollectionState = serializeCollectionState;
20717
- exports.serializeContentFilterForPortal = serializeContentFilterForPortal;
20718
- exports.serializeDateRange = serializeDateRange$1;
20719
- exports.serializeGroupFilterForPortal = serializeGroupFilterForPortal;
20720
- exports.serializeMatchOptions = serializeMatchOptions$1;
20721
19646
  exports.serializeModel = serializeModel;
20722
19647
  exports.serializeQueryForPortal = serializeQueryForPortal;
20723
19648
  exports.serializeSpatialReference = serializeSpatialReference;
20724
- exports.serializeStringOrArray = serializeStringOrArray$1;
20725
- exports.serializeUserFilterForPortal = serializeUserFilterForPortal;
20726
19649
  exports.setContentHubId = setContentHubId;
20727
19650
  exports.setContentSiteUrls = setContentSiteUrls;
20728
19651
  exports.setContentType = setContentType;
@@ -20741,6 +19664,7 @@
20741
19664
  exports.updateModel = updateModel;
20742
19665
  exports.updateProject = updateProject;
20743
19666
  exports.updateSite = updateSite;
19667
+ exports.upgradeCatalogSchema = upgradeCatalogSchema;
20744
19668
  exports.upgradeProtocol = upgradeProtocol;
20745
19669
  exports.upgradeSiteSchema = upgradeSiteSchema;
20746
19670
  exports.uploadResourcesFromUrl = uploadResourcesFromUrl;