@esri/hub-common 9.39.0 → 9.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/es2017/content/_internal.js +83 -0
  2. package/dist/es2017/content/_internal.js.map +1 -1
  3. package/dist/es2017/content/compose.js +7 -11
  4. package/dist/es2017/content/compose.js.map +1 -1
  5. package/dist/es2017/core/types/IHubContent.js +7 -0
  6. package/dist/es2017/core/types/IHubContent.js.map +1 -1
  7. package/dist/es2017/index.js +2 -0
  8. package/dist/es2017/index.js.map +1 -1
  9. package/dist/es2017/items/_enrichments.js +21 -0
  10. package/dist/es2017/items/_enrichments.js.map +1 -1
  11. package/dist/es2017/org/fetch-org.js +21 -0
  12. package/dist/es2017/org/fetch-org.js.map +1 -0
  13. package/dist/es2017/org/index.js +2 -0
  14. package/dist/es2017/org/index.js.map +1 -0
  15. package/dist/es2017/search/_internal/portalSearchGroups.js.map +1 -1
  16. package/dist/es2017/search/_internal/portalSearchUsers.js +89 -0
  17. package/dist/es2017/search/_internal/portalSearchUsers.js.map +1 -0
  18. package/dist/es2017/search/filter-utils.js +59 -26
  19. package/dist/es2017/search/filter-utils.js.map +1 -1
  20. package/dist/es2017/search/hubSearch.js +4 -1
  21. package/dist/es2017/search/hubSearch.js.map +1 -1
  22. package/dist/es2017/urls/getUserHomeUrl.js +12 -0
  23. package/dist/es2017/urls/getUserHomeUrl.js.map +1 -0
  24. package/dist/es2017/urls/index.js +1 -0
  25. package/dist/es2017/urls/index.js.map +1 -1
  26. package/dist/es2017/users/HubUsers.js +64 -0
  27. package/dist/es2017/users/HubUsers.js.map +1 -0
  28. package/dist/es2017/users/_internal/enrichments.js +85 -0
  29. package/dist/es2017/users/_internal/enrichments.js.map +1 -0
  30. package/dist/es2017/users/index.js +2 -0
  31. package/dist/es2017/users/index.js.map +1 -0
  32. package/dist/esm/content/_internal.js +85 -0
  33. package/dist/esm/content/_internal.js.map +1 -1
  34. package/dist/esm/content/compose.js +5 -11
  35. package/dist/esm/content/compose.js.map +1 -1
  36. package/dist/esm/core/types/IHubContent.js +7 -0
  37. package/dist/esm/core/types/IHubContent.js.map +1 -1
  38. package/dist/esm/index.js +2 -0
  39. package/dist/esm/index.js.map +1 -1
  40. package/dist/esm/items/_enrichments.js +21 -0
  41. package/dist/esm/items/_enrichments.js.map +1 -1
  42. package/dist/esm/org/fetch-org.js +22 -0
  43. package/dist/esm/org/fetch-org.js.map +1 -0
  44. package/dist/esm/org/index.js +2 -0
  45. package/dist/esm/org/index.js.map +1 -0
  46. package/dist/esm/search/_internal/portalSearchGroups.js.map +1 -1
  47. package/dist/esm/search/_internal/portalSearchUsers.js +104 -0
  48. package/dist/esm/search/_internal/portalSearchUsers.js.map +1 -0
  49. package/dist/esm/search/filter-utils.js +60 -27
  50. package/dist/esm/search/filter-utils.js.map +1 -1
  51. package/dist/esm/search/hubSearch.js +4 -1
  52. package/dist/esm/search/hubSearch.js.map +1 -1
  53. package/dist/esm/urls/getUserHomeUrl.js +12 -0
  54. package/dist/esm/urls/getUserHomeUrl.js.map +1 -0
  55. package/dist/esm/urls/index.js +1 -0
  56. package/dist/esm/urls/index.js.map +1 -1
  57. package/dist/esm/users/HubUsers.js +66 -0
  58. package/dist/esm/users/HubUsers.js.map +1 -0
  59. package/dist/esm/users/_internal/enrichments.js +86 -0
  60. package/dist/esm/users/_internal/enrichments.js.map +1 -0
  61. package/dist/esm/users/index.js +2 -0
  62. package/dist/esm/users/index.js.map +1 -0
  63. package/dist/node/content/_internal.js +84 -1
  64. package/dist/node/content/_internal.js.map +1 -1
  65. package/dist/node/content/compose.js +6 -10
  66. package/dist/node/content/compose.js.map +1 -1
  67. package/dist/node/core/types/IHubContent.js +8 -0
  68. package/dist/node/core/types/IHubContent.js.map +1 -1
  69. package/dist/node/index.js +2 -0
  70. package/dist/node/index.js.map +1 -1
  71. package/dist/node/items/_enrichments.js +21 -0
  72. package/dist/node/items/_enrichments.js.map +1 -1
  73. package/dist/node/org/fetch-org.js +24 -0
  74. package/dist/node/org/fetch-org.js.map +1 -0
  75. package/dist/node/org/index.js +5 -0
  76. package/dist/node/org/index.js.map +1 -0
  77. package/dist/node/search/_internal/portalSearchGroups.js.map +1 -1
  78. package/dist/node/search/_internal/portalSearchUsers.js +93 -0
  79. package/dist/node/search/_internal/portalSearchUsers.js.map +1 -0
  80. package/dist/node/search/filter-utils.js +59 -26
  81. package/dist/node/search/filter-utils.js.map +1 -1
  82. package/dist/node/search/hubSearch.js +4 -1
  83. package/dist/node/search/hubSearch.js.map +1 -1
  84. package/dist/node/urls/getUserHomeUrl.js +16 -0
  85. package/dist/node/urls/getUserHomeUrl.js.map +1 -0
  86. package/dist/node/urls/index.js +1 -0
  87. package/dist/node/urls/index.js.map +1 -1
  88. package/dist/node/users/HubUsers.js +68 -0
  89. package/dist/node/users/HubUsers.js.map +1 -0
  90. package/dist/node/users/_internal/enrichments.js +89 -0
  91. package/dist/node/users/_internal/enrichments.js.map +1 -0
  92. package/dist/node/users/index.js +5 -0
  93. package/dist/node/users/index.js.map +1 -0
  94. package/dist/types/content/_internal.d.ts +54 -5
  95. package/dist/types/core/types/IHubContent.d.ts +21 -0
  96. package/dist/types/index.d.ts +2 -0
  97. package/dist/types/org/fetch-org.d.ts +9 -0
  98. package/dist/types/org/index.d.ts +1 -0
  99. package/dist/types/search/_internal/portalSearchUsers.d.ts +8 -0
  100. package/dist/types/search/types/types.d.ts +18 -1
  101. package/dist/types/urls/getUserHomeUrl.d.ts +10 -0
  102. package/dist/types/urls/index.d.ts +1 -0
  103. package/dist/types/users/HubUsers.d.ts +11 -0
  104. package/dist/types/users/_internal/enrichments.d.ts +28 -0
  105. package/dist/types/users/index.d.ts +1 -0
  106. package/dist/umd/common.umd.js +477 -69
  107. package/dist/umd/common.umd.js.map +1 -1
  108. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /* @preserve
2
- * @esri/hub-common - v9.38.0 - Mon Jun 06 2022 22:49:18 GMT+0000 (Coordinated Universal Time)
2
+ * @esri/hub-common - v9.41.0 - Mon Jun 13 2022 14:36:13 GMT+0000 (Coordinated Universal Time)
3
3
  * Copyright (c) 2022 Environmental Systems Research Institute, Inc.
4
4
  * Apache-2.0
5
5
  */
@@ -5444,6 +5444,17 @@
5444
5444
  return portalUrl + "/home/group.html?id=" + groupId;
5445
5445
  }
5446
5446
 
5447
+ /**
5448
+ * Return the URL of the user's page in the Portal Home application
5449
+ * @param username The username
5450
+ * @param portalUrlOrObject a portal base or API URL, a portal object, or request options containing either of those
5451
+ * @returns URL to the user's profile, defaults to `https://www.arcgis.com/home/user.html?user={username}`
5452
+ */
5453
+ function getUserHomeUrl(username, portalUrlOrObject) {
5454
+ var portalUrl = getPortalUrl(portalUrlOrObject);
5455
+ return portalUrl + "/home/user.html?user=" + username;
5456
+ }
5457
+
5447
5458
  var MAP_OR_FEATURE_SERVER_URL_REGEX = /\/(map|feature)server/i;
5448
5459
  /**
5449
5460
  *
@@ -6434,6 +6445,14 @@
6434
6445
  return request(cleanUrl(options.url), options);
6435
6446
  }
6436
6447
 
6448
+ exports.PublisherSource = void 0;
6449
+ (function (PublisherSource) {
6450
+ PublisherSource["CitationContact"] = "metadata.resource.citation.contact";
6451
+ PublisherSource["ResourceContact"] = "metadata.resource.contact";
6452
+ PublisherSource["ItemOwner"] = "item.owner";
6453
+ PublisherSource["None"] = "none";
6454
+ })(exports.PublisherSource || (exports.PublisherSource = {}));
6455
+
6437
6456
  /**
6438
6457
  * Turns an bounding box coordinate array into an extent object
6439
6458
  * @param bBox bounding box coordinate array
@@ -7012,6 +7031,90 @@
7012
7031
  : undefined;
7013
7032
  return itemExtent || extentEnrichmentCoordinates || layerExtent;
7014
7033
  };
7034
+ /**
7035
+ * @private
7036
+ *
7037
+ * Extracts the first contact from a given formal item metadata path.
7038
+ * This is particularly helpful if the contact path is either an object or an array.
7039
+ *
7040
+ * Note: the raw contact object must have the following properties:
7041
+ * - `rpIndName`: name of the individual
7042
+ * - `rpOrgName`: name of the individual's organization
7043
+ *
7044
+ * @param metadata formal item metadata
7045
+ * @param path path to the contact object/array
7046
+ * @returns
7047
+ */
7048
+ var extractFirstContact = function (metadata, path) {
7049
+ var rawContacts = getProp(metadata, path) || {};
7050
+ var _a = Array.isArray(rawContacts)
7051
+ ? rawContacts[0]
7052
+ : rawContacts, rpIndName = _a.rpIndName, rpOrgName = _a.rpOrgName;
7053
+ return { individualName: rpIndName, organizationName: rpOrgName };
7054
+ };
7055
+ /**
7056
+ * Determines the correct orgId for an item.
7057
+ * Note: it's undocumented, but the portal API will return orgId for items... sometimes.
7058
+ *
7059
+ * @param item
7060
+ * @param ownerUser item owner's hydrated user object
7061
+ */
7062
+ var getItemOrgId = function (item, ownerUser) {
7063
+ return item.orgId || (ownerUser === null || ownerUser === void 0 ? void 0 : ownerUser.orgId);
7064
+ };
7065
+ /**
7066
+ * Calculates the Publisher display info for the given item.
7067
+ * Utilizes this fallback pattern:
7068
+ * 1) Formal Item Metadata > Resource > Citation > Contact
7069
+ * 2) Formal Item Metadata > Resource > Contact
7070
+ * 3) Item’s Owner and Org Name
7071
+ * 4) Undefined (Item Owner / Org are private and we can't access additional info)
7072
+ *
7073
+ * @param item
7074
+ * @param metadata
7075
+ * @param org portal info of the item's organization
7076
+ * @param ownerUser the item owner's hydrated user
7077
+ * @returns
7078
+ */
7079
+ var getPublisherInfo = function (item, metadata, org, ownerUser) {
7080
+ var result = {
7081
+ nameSource: exports.PublisherSource.None,
7082
+ organizationSource: exports.PublisherSource.None,
7083
+ };
7084
+ var citationContact = extractFirstContact(metadata, "metadata.dataIdInfo.idCitation.citRespParty");
7085
+ var resourceContact = extractFirstContact(metadata, "metadata.mdContact");
7086
+ // Determine publisher name properties
7087
+ var ownerFullName = getProp(ownerUser, "fullName");
7088
+ if (citationContact.individualName) {
7089
+ result.name = citationContact.individualName;
7090
+ result.nameSource = exports.PublisherSource.CitationContact;
7091
+ }
7092
+ else if (resourceContact.individualName) {
7093
+ result.name = resourceContact.individualName;
7094
+ result.nameSource = exports.PublisherSource.ResourceContact;
7095
+ }
7096
+ else if (ownerFullName) {
7097
+ result.name = ownerFullName;
7098
+ result.username = ownerUser.username;
7099
+ result.nameSource = exports.PublisherSource.ItemOwner;
7100
+ }
7101
+ // Determine publisher org properties
7102
+ var orgName = getProp(org, "name");
7103
+ if (citationContact.organizationName) {
7104
+ result.organization = citationContact.organizationName;
7105
+ result.organizationSource = exports.PublisherSource.CitationContact;
7106
+ }
7107
+ else if (resourceContact.organizationName) {
7108
+ result.organization = resourceContact.organizationName;
7109
+ result.organizationSource = exports.PublisherSource.ResourceContact;
7110
+ }
7111
+ else if (orgName) {
7112
+ result.organization = orgName;
7113
+ result.orgId = getItemOrgId(item, ownerUser);
7114
+ result.organizationSource = exports.PublisherSource.ItemOwner;
7115
+ }
7116
+ return result;
7117
+ };
7015
7118
 
7016
7119
  var STANDARD_LICENSES = [
7017
7120
  {
@@ -7919,13 +8022,8 @@
7919
8022
  get metadataUpdateFrequency() {
7920
8023
  return getUpdateFrequencyFromMetadata(metadata, "metadataUpdateFrequency");
7921
8024
  },
7922
- // TODO: add the publisher logic outlined here:
7923
- // https://devtopia.esri.com/dc/hub/issues/2932#issuecomment-3276309
7924
8025
  get publisher() {
7925
- return {
7926
- name: item.owner,
7927
- username: item.owner,
7928
- };
8026
+ return getPublisherInfo(item, metadata, org, ownerUser);
7929
8027
  },
7930
8028
  // TODO: is metrics in use?
7931
8029
  get metrics() {
@@ -7945,11 +8043,10 @@
7945
8043
  Array.isArray(data.layers) &&
7946
8044
  data.layers.find(function (_layer) { return _layer.id === layer.id; });
7947
8045
  return dataLayer ? dataLayer.layerDefinition : undefined;
8046
+ }, get orgId() {
8047
+ return org ? org.id : getItemOrgId(item, ownerUser);
7948
8048
  },
7949
- get orgId() {
7950
- // NOTE: it's undocumented, but the portal API will return orgId for items... sometimes
7951
- return org ? org.id : item.orgId || (ownerUser === null || ownerUser === void 0 ? void 0 : ownerUser.orgId);
7952
- }, get contentTypeIcon() {
8049
+ get contentTypeIcon() {
7953
8050
  /* Note: only returns calcite-icons */
7954
8051
  return getContentTypeIcon(type);
7955
8052
  },
@@ -9882,6 +9979,24 @@
9882
9979
  };
9883
9980
  });
9884
9981
 
9982
+ /**
9983
+ * Fetches the portal for a given org.
9984
+ *
9985
+ * @param orgId
9986
+ * @param options request options
9987
+ * @returns
9988
+ */
9989
+ var fetchOrg = function (orgId, options) {
9990
+ var orgPortalUrl = getProp(options, "portal") ||
9991
+ getProp(options, "authentication.portal") ||
9992
+ "www.arcgis.com";
9993
+ // In order to get the correct response, we must pass options.portal
9994
+ // as a base portal url (e.g., www.arcgis.com, qaext.arcgis.com, etc)
9995
+ // **not** an org portal (i.e. org.maps.arcgis.com).
9996
+ var basePortalUrl = getPortalBaseFromOrgUrl(orgPortalUrl) + "/sharing/rest";
9997
+ return getPortal(orgId, __assign(__assign({}, options), { portal: basePortalUrl }));
9998
+ };
9999
+
9885
10000
  /**
9886
10001
  * Parse metadataxml into json object
9887
10002
  * @param metadataXml
@@ -9928,7 +10043,7 @@
9928
10043
  requestOptions: requestOptions,
9929
10044
  };
9930
10045
  })
9931
- .catch(function (error) { return handleEnrichmentError$1(error, input, opId); });
10046
+ .catch(function (error) { return handleEnrichmentError$2(error, input, opId); });
9932
10047
  };
9933
10048
  var enrichMetadata = function (input) {
9934
10049
  var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
@@ -9960,7 +10075,25 @@
9960
10075
  requestOptions: requestOptions,
9961
10076
  };
9962
10077
  })
9963
- .catch(function (error) { return handleEnrichmentError$1(error, input, opId); });
10078
+ .catch(function (error) { return handleEnrichmentError$2(error, input, opId); });
10079
+ };
10080
+ // Note, this MUST be run after `enrichOwnerUser` to access the correct orgId during
10081
+ // processing. `item.orgId` is only SOMETIMES returned by Portal, so we need to have
10082
+ // the ownerUser's orgId as a backup.
10083
+ var enrichOrg = function (input) {
10084
+ var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
10085
+ var opId = stack.start("enrichOrg");
10086
+ var orgId = getItemOrgId(data.item, data.ownerUser);
10087
+ return fetchOrg(orgId, requestOptions)
10088
+ .then(function (org) {
10089
+ stack.finish(opId);
10090
+ return {
10091
+ data: __assign(__assign({}, data), { org: org }),
10092
+ stack: stack,
10093
+ requestOptions: requestOptions,
10094
+ };
10095
+ })
10096
+ .catch(function (error) { return handleEnrichmentError$2(error, input, opId); });
9964
10097
  };
9965
10098
  var enrichData = function (input) {
9966
10099
  var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
@@ -9970,7 +10103,7 @@
9970
10103
  stack.finish(opId);
9971
10104
  return { data: __assign(__assign({}, data), { data: itemData }), stack: stack, requestOptions: requestOptions };
9972
10105
  })
9973
- .catch(function (error) { return handleEnrichmentError$1(error, input, opId); });
10106
+ .catch(function (error) { return handleEnrichmentError$2(error, input, opId); });
9974
10107
  };
9975
10108
  var enrichServer = function (input) {
9976
10109
  var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
@@ -9982,7 +10115,7 @@
9982
10115
  stack.finish(opId);
9983
10116
  return { data: __assign(__assign({}, data), { server: server }), stack: stack, requestOptions: requestOptions };
9984
10117
  })
9985
- .catch(function (error) { return handleEnrichmentError$1(error, input, opId); });
10118
+ .catch(function (error) { return handleEnrichmentError$2(error, input, opId); });
9986
10119
  };
9987
10120
  var enrichLayers = function (input) {
9988
10121
  var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
@@ -10000,12 +10133,12 @@
10000
10133
  stack.finish(opId);
10001
10134
  return { data: __assign(__assign({}, data), { layers: layers }), stack: stack, requestOptions: requestOptions };
10002
10135
  })
10003
- .catch(function (error) { return handleEnrichmentError$1(error, input, opId); }));
10136
+ .catch(function (error) { return handleEnrichmentError$2(error, input, opId); }));
10004
10137
  };
10005
10138
  // add the error to the content.errors,
10006
10139
  // log current stack operation as finished with an error
10007
10140
  // and return output that can be piped into the next operation
10008
- var handleEnrichmentError$1 = function (error, input, opId) {
10141
+ var handleEnrichmentError$2 = function (error, input, opId) {
10009
10142
  var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
10010
10143
  stack.finish(opId, { error: error });
10011
10144
  return {
@@ -10018,6 +10151,7 @@
10018
10151
  groupIds: enrichGroupIds,
10019
10152
  metadata: enrichMetadata,
10020
10153
  ownerUser: enrichOwnerUser,
10154
+ org: enrichOrg,
10021
10155
  data: enrichData,
10022
10156
  server: enrichServer,
10023
10157
  layers: enrichLayers,
@@ -13099,7 +13233,7 @@
13099
13233
  requestOptions: requestOptions,
13100
13234
  };
13101
13235
  })
13102
- .catch(function (error) { return handleEnrichmentError(error, input, opId); });
13236
+ .catch(function (error) { return handleEnrichmentError$1(error, input, opId); });
13103
13237
  };
13104
13238
  /**
13105
13239
  * Create a summary of the Group membership by searching for members,
@@ -13124,12 +13258,12 @@
13124
13258
  requestOptions: requestOptions,
13125
13259
  };
13126
13260
  })
13127
- .catch(function (error) { return handleEnrichmentError(error, input, opId); });
13261
+ .catch(function (error) { return handleEnrichmentError$1(error, input, opId); });
13128
13262
  };
13129
13263
  // add the error to the content.errors,
13130
13264
  // log current stack operation as finished with an error
13131
13265
  // and return output that can be piped into the next operation
13132
- var handleEnrichmentError = function (error, input, opId) {
13266
+ var handleEnrichmentError$1 = function (error, input, opId) {
13133
13267
  var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
13134
13268
  stack.finish(opId, { error: error });
13135
13269
  return {
@@ -13141,7 +13275,7 @@
13141
13275
  /**
13142
13276
  * Available enrichments for Groups
13143
13277
  */
13144
- var groupEnrichementOperations = {
13278
+ var groupEnrichementOperations$1 = {
13145
13279
  membershipSummary: enrichGroupMembershipSummary,
13146
13280
  contentCount: enrichGroupContentCount,
13147
13281
  };
@@ -13155,7 +13289,7 @@
13155
13289
  function fetchGroupEnrichments(group, enrichments, requestOptions) {
13156
13290
  // create a pipeline of enrichment operations
13157
13291
  var operations = enrichments.reduce(function (ops, enrichment) {
13158
- var operation = groupEnrichementOperations[enrichment];
13292
+ var operation = groupEnrichementOperations$1[enrichment];
13159
13293
  // only include the enrichments that we know how to fetch
13160
13294
  operation && ops.push(operation);
13161
13295
  return ops;
@@ -13401,7 +13535,7 @@
13401
13535
  * @param join
13402
13536
  * @returns
13403
13537
  */
13404
- function mergeSearchOptions(so1, so2, join) {
13538
+ function mergeSearchOptions$1(so1, so2, join) {
13405
13539
  // TODO: Remove with _searchContent
13406
13540
  Logger.warn("DEPRECATION: mergeSearchOptions will be removed. Work with IFilterGroups<\"group\"> and hubSearch() instead");
13407
13541
  var result = cloneObject$1(so1);
@@ -13997,12 +14131,12 @@
13997
14131
  // from hitting the else
13998
14132
  /* istanbul ignore else */
13999
14133
  if (typeof entry === "object") {
14000
- acc = mergeSearchOptions(acc, convertContentFilterToSearchOptions(entry), "OR");
14134
+ acc = mergeSearchOptions$1(acc, convertContentFilterToSearchOptions(entry), "OR");
14001
14135
  }
14002
14136
  return acc;
14003
14137
  }, { q: "", filter: "" });
14004
14138
  // merge with searchOptions using AND
14005
- searchOptions = mergeSearchOptions(searchOptions, subFilterOptions, "AND");
14139
+ searchOptions = mergeSearchOptions$1(searchOptions, subFilterOptions, "AND");
14006
14140
  }
14007
14141
  // term is always last, and pre-pended on searchOptions.q
14008
14142
  if (filter.term) {
@@ -14030,11 +14164,11 @@
14030
14164
  var key = _a[0], value = _a[1];
14031
14165
  // MatchOptions may go into either q or filter
14032
14166
  if (!specialProps.includes(key)) {
14033
- result = mergeSearchOptions(result, serializeMatchOptions$1(key, value), "AND");
14167
+ result = mergeSearchOptions$1(result, serializeMatchOptions$1(key, value), "AND");
14034
14168
  }
14035
14169
  // Dates only go into q
14036
14170
  if (dateProps.includes(key)) {
14037
- result = mergeSearchOptions(result, serializeDateRange$1(key, value), "AND");
14171
+ result = mergeSearchOptions$1(result, serializeDateRange$1(key, value), "AND");
14038
14172
  }
14039
14173
  });
14040
14174
  return result;
@@ -14165,11 +14299,11 @@
14165
14299
  var key = _a[0], value = _a[1];
14166
14300
  // MatchOptions fields
14167
14301
  if (!specialProps.includes(key)) {
14168
- result = mergeSearchOptions(result, serializeMatchOptions$1(key, value), "AND");
14302
+ result = mergeSearchOptions$1(result, serializeMatchOptions$1(key, value), "AND");
14169
14303
  }
14170
14304
  // Dates only go into q
14171
14305
  if (dateProps.includes(key)) {
14172
- result = mergeSearchOptions(result, serializeDateRange$1(key, value), "AND");
14306
+ result = mergeSearchOptions$1(result, serializeDateRange$1(key, value), "AND");
14173
14307
  }
14174
14308
  });
14175
14309
  // searchUserAccess is also a top-level property
@@ -14305,11 +14439,11 @@
14305
14439
  var key = _a[0], value = _a[1];
14306
14440
  // MatchOptions fields
14307
14441
  if (!specialProps.includes(key)) {
14308
- result = mergeSearchOptions(result, serializeMatchOptions$1(key, value), "AND");
14442
+ result = mergeSearchOptions$1(result, serializeMatchOptions$1(key, value), "AND");
14309
14443
  }
14310
14444
  // Dates only go into q
14311
14445
  if (dateProps.includes(key)) {
14312
- result = mergeSearchOptions(result, serializeDateRange$1(key, value), "AND");
14446
+ result = mergeSearchOptions$1(result, serializeDateRange$1(key, value), "AND");
14313
14447
  }
14314
14448
  });
14315
14449
  // disabled is also a top-level property
@@ -14371,7 +14505,7 @@
14371
14505
  so_1.countFields = options.aggFields.join(",");
14372
14506
  so_1.countSize = options.aggLimit || 10;
14373
14507
  }
14374
- searchPromise = searchPortal$2(so_1);
14508
+ searchPromise = searchPortal$3(so_1);
14375
14509
  }
14376
14510
  else {
14377
14511
  // Hub API Search
@@ -14399,7 +14533,7 @@
14399
14533
  * @param site
14400
14534
  * @returns
14401
14535
  */
14402
- function searchPortal$2(searchOptions) {
14536
+ function searchPortal$3(searchOptions) {
14403
14537
  var _a;
14404
14538
  var portalUrl = ((_a = searchOptions.authentication) === null || _a === void 0 ? void 0 : _a.portal) || searchOptions.portal;
14405
14539
  var token;
@@ -14430,7 +14564,7 @@
14430
14564
  results: content,
14431
14565
  facets: facets,
14432
14566
  hasNext: hasNext,
14433
- next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$2),
14567
+ next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$3),
14434
14568
  };
14435
14569
  });
14436
14570
  }
@@ -14837,7 +14971,13 @@
14837
14971
  function expandFilter(filter) {
14838
14972
  var result = {};
14839
14973
  var dateProps = ["created", "modified", "lastlogin"];
14840
- var copyProps = ["filterType", "term", "searchUserAccess", "isopendata"];
14974
+ var copyProps = [
14975
+ "filterType",
14976
+ "term",
14977
+ "searchUserAccess",
14978
+ "isopendata",
14979
+ "searchUserName",
14980
+ ];
14841
14981
  var nonMatchOptionsFields = __spreadArrays(dateProps, copyProps);
14842
14982
  // Do the conversion
14843
14983
  Object.entries(filter).forEach(function (_a) {
@@ -14870,27 +15010,26 @@
14870
15010
  * @returns
14871
15011
  */
14872
15012
  function serializeFilterGroupsForPortal(filterGroups) {
14873
- var result = {
14874
- q: "",
14875
- filter: "",
14876
- };
14877
- result.q = filterGroups.map(serializeGroup).join(" AND ");
15013
+ var groupSearchOptions = filterGroups.map(serializeGroup);
15014
+ var result = mergeSearchOptions(groupSearchOptions, "AND");
14878
15015
  return result;
14879
15016
  }
14880
15017
  /**
14881
15018
  * Serialize the filters in a FitlerGroup into a Portal Query
14882
- * @param group
15019
+ * @param filterGroup
14883
15020
  * @returns
14884
15021
  */
14885
- function serializeGroup(group) {
14886
- var operation = group.operation || "AND";
14887
- var filters = group.filters.map(expandFilter);
14888
- var q = filters.map(serializeFilter).join(" " + operation + " ");
14889
- // Wrap in parens if there is more than one filter
15022
+ function serializeGroup(filterGroup) {
15023
+ var operation = filterGroup.operation || "AND";
15024
+ var filters = filterGroup.filters.map(expandFilter);
15025
+ var filterSearchOptions = filters.map(serializeFilter);
15026
+ // combine these searchOptions
15027
+ var groupSearchOptions = mergeSearchOptions(filterSearchOptions, operation);
15028
+ //
14890
15029
  if (filters.length > 1) {
14891
- q = "(" + q + ")";
15030
+ groupSearchOptions.q = "(" + groupSearchOptions.q + ")";
14892
15031
  }
14893
- return q;
15032
+ return groupSearchOptions;
14894
15033
  }
14895
15034
  /**
14896
15035
  * Serialize a Filter into a Portal Query
@@ -14900,36 +15039,64 @@
14900
15039
  function serializeFilter(filter) {
14901
15040
  var dateProps = ["created", "modified"];
14902
15041
  var boolProps = ["isopendata"];
15042
+ var passThroughProps = ["searchUserAccess", "searchUserName"];
14903
15043
  var specialProps = __spreadArrays([
14904
15044
  "filterType",
14905
- "searchUserAccess",
14906
15045
  "term"
14907
- ], dateProps, boolProps);
15046
+ ], dateProps, boolProps, passThroughProps);
15047
+ var qCount = 0;
14908
15048
  // TODO: Look at using reduce vs .map and remove the `.filter`
14909
- var stringFilters = Object.entries(filter)
15049
+ var opts = Object.entries(filter)
14910
15050
  .map(function (_a) {
14911
15051
  var key = _a[0], value = _a[1];
15052
+ var so = { q: "" };
14912
15053
  if (!specialProps.includes(key)) {
14913
- return serializeMatchOptions(key, value);
15054
+ qCount++;
15055
+ so.q = serializeMatchOptions(key, value);
14914
15056
  }
14915
15057
  if (dateProps.includes(key)) {
14916
- return serializeDateRange(key, value);
15058
+ qCount++;
15059
+ so.q = serializeDateRange(key, value);
14917
15060
  }
14918
15061
  if (boolProps.includes(key)) {
14919
- return key + ":" + value;
15062
+ qCount++;
15063
+ so.q = key + ":" + value;
15064
+ }
15065
+ if (passThroughProps.includes(key)) {
15066
+ so[key] = value;
14920
15067
  }
14921
15068
  if (key === "term") {
14922
- return value;
15069
+ qCount++;
15070
+ so.q = value;
14923
15071
  }
15072
+ return so;
14924
15073
  })
14925
15074
  .filter(function (e) { return e !== undefined; });
14926
- // eslint-disable-next-line unicorn/prefer-ternary
14927
- if (stringFilters.length > 1) {
14928
- return "(" + stringFilters.join(" AND ") + ")";
14929
- }
14930
- else {
14931
- return stringFilters[0];
15075
+ // merge up all the searchOptions
15076
+ var searchOptions = mergeSearchOptions(opts, "AND");
15077
+ if (qCount > 1) {
15078
+ searchOptions.q = "(" + searchOptions.q + ")";
14932
15079
  }
15080
+ return searchOptions;
15081
+ }
15082
+ function mergeSearchOptions(options, operation) {
15083
+ var result = options.reduce(function (acc, entry) {
15084
+ // walk the props
15085
+ Object.entries(entry).forEach(function (_a) {
15086
+ var key = _a[0], value = _a[1];
15087
+ // if prop exists
15088
+ if (acc[key]) {
15089
+ // combine via operation
15090
+ acc[key] = acc[key] + " " + operation + " " + value;
15091
+ }
15092
+ else {
15093
+ // just copy the value
15094
+ acc[key] = value;
15095
+ }
15096
+ });
15097
+ return acc;
15098
+ }, { q: "" });
15099
+ return result;
14933
15100
  }
14934
15101
  /**
14935
15102
  * Serialize MatchOptions into portal syntax
@@ -17680,7 +17847,7 @@
17680
17847
  so.countFields = options.aggFields.join(",");
17681
17848
  so.countSize = options.aggLimit || 10;
17682
17849
  }
17683
- return [2 /*return*/, searchPortal$1(so)];
17850
+ return [2 /*return*/, searchPortal$2(so)];
17684
17851
  });
17685
17852
  });
17686
17853
  }
@@ -17691,7 +17858,7 @@
17691
17858
  * @param searchOptions
17692
17859
  * @returns
17693
17860
  */
17694
- function searchPortal$1(searchOptions) {
17861
+ function searchPortal$2(searchOptions) {
17695
17862
  return __awaiter(this, void 0, void 0, function () {
17696
17863
  var resp, fn, results, facets;
17697
17864
  return __generator(this, function (_a) {
@@ -17712,7 +17879,7 @@
17712
17879
  results: results,
17713
17880
  facets: facets,
17714
17881
  hasNext: resp.nextStart > -1,
17715
- next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$1),
17882
+ next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$2),
17716
17883
  }];
17717
17884
  }
17718
17885
  });
@@ -18000,7 +18167,7 @@
18000
18167
  if (!so.authentication) {
18001
18168
  so.portal = so.requestOptions.portal || api.url + "/sharing/rest";
18002
18169
  }
18003
- return [2 /*return*/, searchPortal(so)];
18170
+ return [2 /*return*/, searchPortal$1(so)];
18004
18171
  });
18005
18172
  });
18006
18173
  }
@@ -18011,7 +18178,7 @@
18011
18178
  * @param searchOptions
18012
18179
  * @returns
18013
18180
  */
18014
- function searchPortal(searchOptions) {
18181
+ function searchPortal$1(searchOptions) {
18015
18182
  return __awaiter(this, void 0, void 0, function () {
18016
18183
  var resp, fn, results;
18017
18184
  return __generator(this, function (_a) {
@@ -18032,7 +18199,7 @@
18032
18199
  results: results,
18033
18200
  facets: [],
18034
18201
  hasNext: resp.nextStart > -1,
18035
- next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal),
18202
+ next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal$1),
18036
18203
  }];
18037
18204
  }
18038
18205
  });
@@ -18059,6 +18226,104 @@
18059
18226
  });
18060
18227
  }
18061
18228
 
18229
+ /**
18230
+ * @private
18231
+ * Portal Search implementation for Users
18232
+ * @param filterGroups
18233
+ * @param options
18234
+ */
18235
+ function portalSearchUsers(filterGroups, options) {
18236
+ return __awaiter(this, void 0, void 0, function () {
18237
+ var expandedGroups, so, props;
18238
+ return __generator(this, function (_a) {
18239
+ // requestOptions is always required and user must be authd
18240
+ if (!options.requestOptions) {
18241
+ throw new HubError$1("portalSearchUsers", "requestOptions: IHubRequestOptions is required.");
18242
+ }
18243
+ if (!options.requestOptions.authentication) {
18244
+ throw new HubError$1("portalSearchUsers", "requestOptions must pass authentication.");
18245
+ }
18246
+ expandedGroups = filterGroups.map(function (fg) {
18247
+ fg.filters = fg.filters.map(expandFilter);
18248
+ return fg;
18249
+ });
18250
+ so = serializeFilterGroupsForPortal(expandedGroups);
18251
+ props = [
18252
+ "num",
18253
+ "sortField",
18254
+ "sortOrder",
18255
+ "include",
18256
+ "start",
18257
+ "requestOptions",
18258
+ ];
18259
+ // copy the props over
18260
+ props.forEach(function (prop) {
18261
+ if (options.hasOwnProperty(prop)) {
18262
+ so[prop] = options[prop];
18263
+ }
18264
+ });
18265
+ // Ensure authentication gets sent
18266
+ so.authentication = options.requestOptions.authentication;
18267
+ // Execute search
18268
+ return [2 /*return*/, searchPortal(so)];
18269
+ });
18270
+ });
18271
+ }
18272
+ /**
18273
+ * Internal portal search, which then converts `IGroup`s to `IHubSearchResult`s
18274
+ * handling enrichments & includes along the way
18275
+ *
18276
+ * @param searchOptions
18277
+ * @returns
18278
+ */
18279
+ function searchPortal(searchOptions) {
18280
+ return __awaiter(this, void 0, void 0, function () {
18281
+ var resp, fn, results;
18282
+ return __generator(this, function (_a) {
18283
+ switch (_a.label) {
18284
+ case 0: return [4 /*yield*/, searchUsers(searchOptions)];
18285
+ case 1:
18286
+ resp = _a.sent();
18287
+ fn = function (user) {
18288
+ return userToSearchResult(user, searchOptions.include, searchOptions.requestOptions);
18289
+ };
18290
+ return [4 /*yield*/, Promise.all(resp.results.map(fn))];
18291
+ case 2:
18292
+ results = _a.sent();
18293
+ // Group Search does not support aggregations
18294
+ // Construct the return
18295
+ return [2 /*return*/, {
18296
+ total: resp.total,
18297
+ results: results,
18298
+ facets: [],
18299
+ hasNext: resp.nextStart > -1,
18300
+ next: getNextFunction(searchOptions, resp.nextStart, resp.total, searchPortal),
18301
+ }];
18302
+ }
18303
+ });
18304
+ });
18305
+ }
18306
+ /**
18307
+ * Convert an Item to a IHubSearchResult
18308
+ * Fetches the includes and attaches them to the item
18309
+ * @param item
18310
+ * @param includes
18311
+ * @param requestOptions
18312
+ * @returns
18313
+ */
18314
+ function userToSearchResult(user, includes, requestOptions) {
18315
+ if (includes === void 0) { includes = []; }
18316
+ return __awaiter(this, void 0, void 0, function () {
18317
+ return __generator(this, function (_a) {
18318
+ // Delegate to HubGroups module
18319
+ // This layer of indirection is not necessary but
18320
+ // aligns with how the items search works and
18321
+ // allows for future specialization
18322
+ return [2 /*return*/, enrichUserSearchResult(user, includes, requestOptions)];
18323
+ });
18324
+ });
18325
+ }
18326
+
18062
18327
  /**
18063
18328
  * Main Search function for ArcGIS Hub
18064
18329
  *
@@ -18092,6 +18357,7 @@
18092
18357
  arcgis: {
18093
18358
  item: portalSearchItems,
18094
18359
  group: portalSearchGroups,
18360
+ user: portalSearchUsers,
18095
18361
  },
18096
18362
  "arcgis-hub": {
18097
18363
  item: hubSearchItems,
@@ -18101,7 +18367,7 @@
18101
18367
  if (!fn) {
18102
18368
  throw new HubError$1("hubSearch", "Search via \"" + filterType + "\" filter against \"" + apiType + "\" api is not implemented");
18103
18369
  }
18104
- return [2 /*return*/, fn(filterGroups, options)];
18370
+ return [2 /*return*/, fn(cloneObject$1(filterGroups), options)];
18105
18371
  });
18106
18372
  });
18107
18373
  }
@@ -19575,6 +19841,145 @@
19575
19841
  return Hub;
19576
19842
  }());
19577
19843
 
19844
+ var enrichUserOrg = function (input) {
19845
+ var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
19846
+ var opId = stack.start("enrichUserOrg");
19847
+ var options = __assign(__assign({}, requestOptions), {
19848
+ // In order to get the correct response, we must pass options.portal
19849
+ // as a base portal url (e.g., www.arcgis.com, qaext.arcgis.com, etc)
19850
+ // **not** an org portal (i.e. org.maps.arcgis.com).
19851
+ portal: getPortalBaseFromOrgUrl(requestOptions.portal) + "/sharing/rest" });
19852
+ // TODO: Add Caching
19853
+ // Had implemented a simple caching system, but it leads to unstable
19854
+ // tests because we can't deterministically clear it
19855
+ // if (!orgCache[data.user.orgId]) {
19856
+ // orgCache[data.user.orgId] = fetchOrg(data.user.orgId, options);
19857
+ // }
19858
+ // return (orgCache[data.user.orgId] as Promise<IPortal>)
19859
+ return fetchOrg(data.user.orgId, options)
19860
+ .then(function (results) {
19861
+ stack.finish(opId);
19862
+ return {
19863
+ data: __assign(__assign({}, data), {
19864
+ org: results,
19865
+ }),
19866
+ stack: stack,
19867
+ requestOptions: requestOptions,
19868
+ };
19869
+ })
19870
+ .catch(function (error) { return handleEnrichmentError(error, input, opId); });
19871
+ };
19872
+ /**
19873
+ * Simple cache for user org's. This does not expire
19874
+ * but that seems reasonable as Org props rarely change
19875
+ */
19876
+ // This works find at run-time, but it's a problem in tests
19877
+ // where we are validating calls. Will work with Randy to
19878
+ // create something that's more robust
19879
+ // const orgCache: Record<string, any> = {};
19880
+ // add the error to the content.errors,
19881
+ // log current stack operation as finished with an error
19882
+ // and return output that can be piped into the next operation
19883
+ var handleEnrichmentError = function (error, input, opId) {
19884
+ var data = input.data, stack = input.stack, requestOptions = input.requestOptions;
19885
+ stack.finish(opId, { error: error });
19886
+ return {
19887
+ data: __assign(__assign({}, data), { errors: getEnrichmentErrors(error, data.errors) }),
19888
+ stack: stack,
19889
+ requestOptions: requestOptions,
19890
+ };
19891
+ };
19892
+ /**
19893
+ * Available enrichments for Groups
19894
+ */
19895
+ var groupEnrichementOperations = {
19896
+ org: enrichUserOrg,
19897
+ };
19898
+ /**
19899
+ * Fetch enrichments for Users
19900
+ * @param group
19901
+ * @param enrichments
19902
+ * @param requestOptions
19903
+ * @returns
19904
+ */
19905
+ function fetchUserEnrichments(user, enrichments, requestOptions) {
19906
+ // create a pipeline of enrichment operations
19907
+ var operations = enrichments.reduce(function (ops, enrichment) {
19908
+ var operation = groupEnrichementOperations[enrichment];
19909
+ // only include the enrichments that we know how to fetch
19910
+ operation && ops.push(operation);
19911
+ return ops;
19912
+ }, []);
19913
+ var pipeline = createOperationPipeline(operations);
19914
+ // execute pipeline and return the item and enrichments
19915
+ return pipeline({
19916
+ data: { user: user },
19917
+ stack: new OperationStack$1(),
19918
+ requestOptions: requestOptions,
19919
+ }).then(function (output) {
19920
+ // TODO: send telemetry so we have info on what enrichments are requested and possible errors
19921
+ return output.data;
19922
+ });
19923
+ }
19924
+
19925
+ /**
19926
+ * Enrich a User object
19927
+ * @param user
19928
+ * @param includes
19929
+ * @param requestOptions
19930
+ * @returns
19931
+ */
19932
+ function enrichUserSearchResult(user, include, requestOptions) {
19933
+ return __awaiter(this, void 0, void 0, function () {
19934
+ var result, DEFAULTS, specs, enrichments, enriched, token;
19935
+ return __generator(this, function (_a) {
19936
+ switch (_a.label) {
19937
+ case 0:
19938
+ result = {
19939
+ access: user.access,
19940
+ id: user.username,
19941
+ type: "User",
19942
+ name: user.fullName,
19943
+ owner: user.username,
19944
+ summary: user.description,
19945
+ createdDate: new Date(user.created),
19946
+ createdDateSource: "user.created",
19947
+ updatedDate: new Date(user.modified),
19948
+ updatedDateSource: "user.modified",
19949
+ family: "people",
19950
+ links: {
19951
+ self: "not-implemented",
19952
+ siteRelative: "not-implemented",
19953
+ thumbnail: "not-implemented",
19954
+ },
19955
+ };
19956
+ DEFAULTS = ["org.name AS orgName"];
19957
+ // merge includes
19958
+ include = __spreadArrays(DEFAULTS, include).filter(unique);
19959
+ specs = include.map(parseInclude);
19960
+ enrichments = mapBy("enrichment", specs).filter(unique);
19961
+ enriched = {};
19962
+ if (!enrichments.length) return [3 /*break*/, 2];
19963
+ return [4 /*yield*/, fetchUserEnrichments(user, enrichments, requestOptions)];
19964
+ case 1:
19965
+ enriched = _a.sent();
19966
+ _a.label = 2;
19967
+ case 2:
19968
+ // map the enriched props onto the result
19969
+ specs.forEach(function (spec) {
19970
+ result[spec.prop] = getProp(enriched, spec.path);
19971
+ });
19972
+ token = requestOptions.authentication.token;
19973
+ // Handle links
19974
+ result.links.thumbnail = getUserThumbnailUrl(requestOptions.portal, user, token);
19975
+ result.links.self = getUserHomeUrl(result.id, requestOptions);
19976
+ result.links.siteRelative = "/people/" + result.id;
19977
+ return [2 /*return*/, result];
19978
+ }
19979
+ });
19980
+ });
19981
+ }
19982
+
19578
19983
  exports.ArcGISContext = ArcGISContext;
19579
19984
  exports.ArcGISContextManager = ArcGISContextManager;
19580
19985
  exports.DEFAULT_THEME = DEFAULT_THEME;
@@ -19702,6 +20107,7 @@
19702
20107
  exports.enrichPageSearchResult = enrichPageSearchResult;
19703
20108
  exports.enrichProjectSearchResult = enrichProjectSearchResult;
19704
20109
  exports.enrichSiteSearchResult = enrichSiteSearchResult;
20110
+ exports.enrichUserSearchResult = enrichUserSearchResult;
19705
20111
  exports.ensureProp = ensureProp;
19706
20112
  exports.ensureUniqueDomainName = ensureUniqueDomainName;
19707
20113
  exports.ensureUniqueString = ensureUniqueString;
@@ -19724,6 +20130,7 @@
19724
20130
  exports.fetchHubTranslation = fetchHubTranslation;
19725
20131
  exports.fetchImageAsBlob = fetchImageAsBlob;
19726
20132
  exports.fetchModelFromItem = fetchModelFromItem;
20133
+ exports.fetchOrg = fetchOrg;
19727
20134
  exports.fetchProject = fetchProject;
19728
20135
  exports.fetchSite = fetchSite;
19729
20136
  exports.fetchSiteModel = fetchSiteModel;
@@ -19792,6 +20199,7 @@
19792
20199
  exports.getUniqueDomainNamePortal = getUniqueDomainNamePortal;
19793
20200
  exports.getUniqueItemTitle = getUniqueItemTitle;
19794
20201
  exports.getUniqueSlug = getUniqueSlug;
20202
+ exports.getUserHomeUrl = getUserHomeUrl;
19795
20203
  exports.getUserThumbnailUrl = getUserThumbnailUrl;
19796
20204
  exports.getWithDefault = getWithDefault$1;
19797
20205
  exports.hasBasePriv = hasBasePriv;
@@ -19830,7 +20238,7 @@
19830
20238
  exports.mergeGroupFilters = mergeGroupFilters;
19831
20239
  exports.mergeMatchOptions = mergeMatchOptions;
19832
20240
  exports.mergeObjects = mergeObjects;
19833
- exports.mergeSearchOptions = mergeSearchOptions;
20241
+ exports.mergeSearchOptions = mergeSearchOptions$1;
19834
20242
  exports.mergeUserFilters = mergeUserFilters;
19835
20243
  exports.normalizeItemType = normalizeItemType;
19836
20244
  exports.normalizeSolutionTemplateItem = normalizeSolutionTemplateItem;