@esri/hub-common 9.7.2 → 9.9.0

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 (59) hide show
  1. package/dist/es2017/content.js +20 -9
  2. package/dist/es2017/content.js.map +1 -1
  3. package/dist/es2017/search/_searchContent.js +1 -1
  4. package/dist/es2017/search/_searchContent.js.map +1 -1
  5. package/dist/es2017/search/_searchGroups.js +15 -21
  6. package/dist/es2017/search/_searchGroups.js.map +1 -1
  7. package/dist/es2017/search/_searchUsers.js +83 -0
  8. package/dist/es2017/search/_searchUsers.js.map +1 -0
  9. package/dist/es2017/search/index.js +2 -0
  10. package/dist/es2017/search/index.js.map +1 -1
  11. package/dist/es2017/search/user-utils.js +132 -0
  12. package/dist/es2017/search/user-utils.js.map +1 -0
  13. package/dist/es2017/search/utils.js +40 -0
  14. package/dist/es2017/search/utils.js.map +1 -1
  15. package/dist/es2017/sites/upgrade-site-schema.js +3 -0
  16. package/dist/es2017/sites/upgrade-site-schema.js.map +1 -1
  17. package/dist/esm/content.js +20 -9
  18. package/dist/esm/content.js.map +1 -1
  19. package/dist/esm/search/_searchContent.js +1 -1
  20. package/dist/esm/search/_searchContent.js.map +1 -1
  21. package/dist/esm/search/_searchGroups.js +15 -21
  22. package/dist/esm/search/_searchGroups.js.map +1 -1
  23. package/dist/esm/search/_searchUsers.js +88 -0
  24. package/dist/esm/search/_searchUsers.js.map +1 -0
  25. package/dist/esm/search/index.js +2 -0
  26. package/dist/esm/search/index.js.map +1 -1
  27. package/dist/esm/search/user-utils.js +136 -0
  28. package/dist/esm/search/user-utils.js.map +1 -0
  29. package/dist/esm/search/utils.js +40 -0
  30. package/dist/esm/search/utils.js.map +1 -1
  31. package/dist/esm/sites/upgrade-site-schema.js +3 -0
  32. package/dist/esm/sites/upgrade-site-schema.js.map +1 -1
  33. package/dist/node/content.js +21 -10
  34. package/dist/node/content.js.map +1 -1
  35. package/dist/node/search/_searchContent.js +1 -1
  36. package/dist/node/search/_searchContent.js.map +1 -1
  37. package/dist/node/search/_searchGroups.js +14 -20
  38. package/dist/node/search/_searchGroups.js.map +1 -1
  39. package/dist/node/search/_searchUsers.js +87 -0
  40. package/dist/node/search/_searchUsers.js.map +1 -0
  41. package/dist/node/search/index.js +2 -0
  42. package/dist/node/search/index.js.map +1 -1
  43. package/dist/node/search/user-utils.js +138 -0
  44. package/dist/node/search/user-utils.js.map +1 -0
  45. package/dist/node/search/utils.js +43 -1
  46. package/dist/node/search/utils.js.map +1 -1
  47. package/dist/node/sites/upgrade-site-schema.js +3 -0
  48. package/dist/node/sites/upgrade-site-schema.js.map +1 -1
  49. package/dist/types/content.d.ts +13 -2
  50. package/dist/types/search/_searchUsers.d.ts +28 -0
  51. package/dist/types/search/index.d.ts +2 -0
  52. package/dist/types/search/types.d.ts +7 -1
  53. package/dist/types/search/user-utils.d.ts +35 -0
  54. package/dist/types/search/utils.d.ts +25 -2
  55. package/dist/umd/common.umd.js +315 -26
  56. package/dist/umd/common.umd.js.map +1 -1
  57. package/dist/umd/common.umd.min.js +1 -1
  58. package/dist/umd/common.umd.min.js.map +1 -1
  59. package/package.json +2 -2
@@ -203,7 +203,7 @@ export declare function datasetToContent(dataset: DatasetResource): IHubContent;
203
203
  */
204
204
  export declare function datasetToItem(dataset: DatasetResource): IItem;
205
205
  /**
206
- * retunrs a new content that has the specified type and
206
+ * returns a new content that has the specified type and
207
207
  * and updated related properties like normalizedType, family, etc
208
208
  * @param content orignal content
209
209
  * @param type new type
@@ -211,12 +211,23 @@ export declare function datasetToItem(dataset: DatasetResource): IItem;
211
211
  */
212
212
  export declare const setContentType: (content: IHubContent, type: string) => IHubContent;
213
213
  /**
214
- * retunrs a new content that has the specified hubId and updated identifier
214
+ * returns a new content that has the specified hubId and updated identifier
215
215
  * @param content orignal content
216
216
  * @param hubId new hubId
217
217
  * @returns new content
218
218
  */
219
219
  export declare const setContentHubId: (content: IHubContent, hubId: string) => IHubContent;
220
+ /**
221
+ * Calculates the relative and absolute urls for a given content on a specific site
222
+ *
223
+ * @param content
224
+ * @param siteModel
225
+ * @returns relative and absolute urls
226
+ */
227
+ export declare const getContentSiteUrls: (content: IHubContent, siteModel: IModel) => {
228
+ relative: string;
229
+ absolute: string;
230
+ };
220
231
  /**
221
232
  * append the absolute URL to the content on the site
222
233
  * also updates the relative URL in case the
@@ -0,0 +1,28 @@
1
+ import { IUser, UserSession } from "@esri/arcgis-rest-auth";
2
+ import { Filter, IHubSearchOptions, ISearchResponse } from "..";
3
+ /**
4
+ * Extends IHubSearchOptions to make auth mandatory
5
+ */
6
+ export interface IAuthenticatedHubSearchOptions extends IHubSearchOptions {
7
+ authentication: UserSession;
8
+ }
9
+ /**
10
+ * Extends `IUser` with url optional props for the user's
11
+ * profile and thumbnail
12
+ */
13
+ export interface IHubUser extends IUser {
14
+ profileUrl?: string;
15
+ thumbnailUrl?: string;
16
+ }
17
+ /**
18
+ * Search for Users via the Portal API.
19
+ *
20
+ * **Note** Authentication is required
21
+ *
22
+ * Note: in the future, there may be options to search via
23
+ * a Hub specific API
24
+ * @param filter
25
+ * @param options
26
+ * @returns
27
+ */
28
+ export declare function _searchUsers(filter: Filter<"user">, options: IAuthenticatedHubSearchOptions): Promise<ISearchResponse<IHubUser>>;
@@ -1,7 +1,9 @@
1
1
  export * from "./hub-api-search";
2
2
  export * from "./content-utils";
3
3
  export * from "./group-utils";
4
+ export * from "./user-utils";
4
5
  export * from "./utils";
5
6
  export * from "./types";
6
7
  export * from "./_searchContent";
7
8
  export * from "./_searchGroups";
9
+ export * from "./_searchUsers";
@@ -105,16 +105,21 @@ export interface IWellKnownContentFilters {
105
105
  }
106
106
  export declare type NamedContentFilter = keyof IWellKnownContentFilters;
107
107
  export interface IUserFilterDefinition {
108
+ created?: IDateRange<number> | IRelativeDate;
108
109
  disabled?: boolean;
109
110
  email?: string | string[] | IMatchOptions;
110
111
  firstname?: string | string[] | IMatchOptions;
111
112
  fullname?: string | string[] | IMatchOptions;
112
113
  groups?: string | string[] | IMatchOptions;
114
+ lastlogin?: IDateRange<number> | IRelativeDate;
113
115
  lastname?: string | string[] | IMatchOptions;
116
+ modified?: IDateRange<number> | IRelativeDate;
117
+ role?: string | string[] | IMatchOptions;
118
+ term?: string;
119
+ userlicensetype?: string | string[] | IMatchOptions;
114
120
  username?: string | string[] | IMatchOptions;
115
121
  }
116
122
  export interface IGroupFilterDefinition {
117
- term?: string;
118
123
  access?: string | string[] | IMatchOptions;
119
124
  created?: IDateRange<number> | IRelativeDate;
120
125
  id?: string | string[] | IMatchOptions;
@@ -124,6 +129,7 @@ export interface IGroupFilterDefinition {
124
129
  owner?: string | string[] | IMatchOptions;
125
130
  searchUserAccess?: "groupMember";
126
131
  tags?: string | string[] | IMatchOptions;
132
+ term?: string;
127
133
  title?: string | string[] | IMatchOptions;
128
134
  typekeywords?: string | string[] | IMatchOptions;
129
135
  }
@@ -0,0 +1,35 @@
1
+ import { ISearchOptions } from "@esri/arcgis-rest-portal";
2
+ import { Filter, IUserFilterDefinition } from "..";
3
+ /**
4
+ *
5
+ * Merge `Filter<"user">` objects
6
+ *
7
+ * Useful in components which may get partial filters from a variety of
8
+ * sub-components, which are then combined into a single filter prior
9
+ * to executing the search.
10
+ * @param filters
11
+ * @returns
12
+ */
13
+ export declare function mergeUserFilters(filters: Array<Filter<"user">>): Filter<"user">;
14
+ /**
15
+ * Prior to serialization into the query syntax for the backing APIs, we first expand [Filters](../Filter)
16
+ *
17
+ * Filter's can express their intent in a very terse form, but to ensure consistent structures
18
+ * we expand them into their more verbose form.
19
+ *
20
+ * i.e. `firstname: "John"` expands into `firstname: { any: ["John"]}`
21
+ *
22
+ * - Fields defined as `string | string[] | MatchOptions` will be converted to a `MatchOptions`
23
+ * - RelativeDate fields are converted to DateRange<number>
24
+ * @param filter
25
+ * @returns
26
+ */
27
+ export declare function expandUserFilter(filter: Filter<"user">): IUserFilterDefinition;
28
+ /**
29
+ * @private
30
+ * Serialize an `IUserFilterDefinition` into an `ISearchOptions` for use
31
+ * with `searchUsers`
32
+ * @param filter
33
+ * @returns
34
+ */
35
+ export declare function serializeUserFilterForPortal(filter: IUserFilterDefinition): ISearchOptions;
@@ -1,4 +1,5 @@
1
- import { ISearchOptions } from "@esri/arcgis-rest-portal";
1
+ import { IUser } from "@esri/arcgis-rest-auth";
2
+ import { IGroup, ISearchOptions } from "@esri/arcgis-rest-portal";
2
3
  import { ISearchResponse } from "..";
3
4
  import { IMatchOptions, IDateRange, IRelativeDate, IWellKnownApis, IApiDefinition, NamedApis } from "./types";
4
5
  /**
@@ -97,4 +98,26 @@ export declare function serializeStringOrArray(join: "AND" | "OR", key: string,
97
98
  * @param fn
98
99
  * @returns
99
100
  */
100
- export declare function getNextFunction<T>(request: ISearchOptions, nextStart: number, total: number, fn: (r: ISearchOptions) => Promise<ISearchResponse<T>>): () => Promise<ISearchResponse<T>>;
101
+ export declare function getNextFunction<T>(request: ISearchOptions, nextStart: number, total: number, fn: (r: any) => Promise<ISearchResponse<T>>): () => Promise<ISearchResponse<T>>;
102
+ /**
103
+ * Construct a the full url to a group thumbnail
104
+ *
105
+ * - If the group has a thumbnail, construct the full url
106
+ * - If the group is not public, append on the token
107
+ * @param portalUrl
108
+ * @param group
109
+ * @param token
110
+ * @returns
111
+ */
112
+ export declare function getGroupThumbnailUrl(portalUrl: string, group: IGroup, token?: string): string;
113
+ /**
114
+ * Construct a the full url to a user thumbnail
115
+ *
116
+ * - If the user has a thumbnail, construct the full url
117
+ * - If the user is not public, append on the token
118
+ * @param portalUrl
119
+ * @param user
120
+ * @param token
121
+ * @returns
122
+ */
123
+ export declare function getUserThumbnailUrl(portalUrl: string, user: IUser, token?: string): string;
@@ -1,5 +1,5 @@
1
1
  /* @preserve
2
- * @esri/hub-common - v9.7.1 - Wed Nov 17 2021 14:29:30 GMT-0700 (Mountain Standard Time)
2
+ * @esri/hub-common - v9.8.1 - Tue Dec 14 2021 12:30:36 GMT-0500 (Eastern Standard Time)
3
3
  * Copyright (c) 2021 Environmental Systems Research Institute, Inc.
4
4
  * Apache-2.0
5
5
  */
@@ -3220,6 +3220,22 @@
3220
3220
  return request(url, options);
3221
3221
  }
3222
3222
 
3223
+ /**
3224
+ * ```js
3225
+ * import { searchItems } from "@esri/arcgis-rest-portal";
3226
+ * //
3227
+ * searchUsers({ q: 'tommy', authentication })
3228
+ * .then(response) // response.total => 355
3229
+ * ```
3230
+ * Search a portal for users.
3231
+ *
3232
+ * @param search - A RequestOptions object to pass through to the endpoint.
3233
+ * @returns A Promise that will resolve with the data from the response.
3234
+ */
3235
+ function searchUsers(search) {
3236
+ return genericSearch(search, "user");
3237
+ }
3238
+
3223
3239
  /**
3224
3240
  * ```js
3225
3241
  * import { isItemSharedWithGroup } from "@esri/arcgis-rest-portal";
@@ -6163,7 +6179,7 @@
6163
6179
  };
6164
6180
  }
6165
6181
  /**
6166
- * retunrs a new content that has the specified type and
6182
+ * returns a new content that has the specified type and
6167
6183
  * and updated related properties like normalizedType, family, etc
6168
6184
  * @param content orignal content
6169
6185
  * @param type new type
@@ -6171,8 +6187,8 @@
6171
6187
  */
6172
6188
  var setContentType = function (content, type) {
6173
6189
  // get family and normalized type based on new type
6174
- var family = getFamily(type);
6175
6190
  var normalizedType = normalizeItemType(__assign(__assign({}, content.item), { type: type }));
6191
+ var family = getFamily(normalizedType);
6176
6192
  var updated = __assign(__assign({}, content), { type: type, family: family, normalizedType: normalizedType });
6177
6193
  // update the relative URL to the content
6178
6194
  // which is based on type and family
@@ -6181,7 +6197,7 @@
6181
6197
  });
6182
6198
  };
6183
6199
  /**
6184
- * retunrs a new content that has the specified hubId and updated identifier
6200
+ * returns a new content that has the specified hubId and updated identifier
6185
6201
  * @param content orignal content
6186
6202
  * @param hubId new hubId
6187
6203
  * @returns new content
@@ -6198,19 +6214,30 @@
6198
6214
  });
6199
6215
  };
6200
6216
  /**
6201
- * append the absolute URL to the content on the site
6202
- * also updates the relative URL in case the
6217
+ * Calculates the relative and absolute urls for a given content on a specific site
6218
+ *
6203
6219
  * @param content
6204
6220
  * @param siteModel
6205
- * @returns
6221
+ * @returns relative and absolute urls
6206
6222
  */
6207
- var setContentSiteUrls = function (content, siteModel) {
6208
- // recompute relative URL using a site specific identifier
6223
+ var getContentSiteUrls = function (content, siteModel) {
6224
+ // compute relative URL using a site specific identifier
6209
6225
  var siteIdentifier = getContentIdentifier(content, siteModel);
6210
6226
  var relative = getContentRelativeUrl(content, siteIdentifier);
6211
6227
  // get the absolute URL to this content on the site
6212
6228
  var siteUrl = getProp(siteModel, "item.url").replace(/\/$/, "");
6213
- var site = "" + siteUrl + relative;
6229
+ var absolute = "" + siteUrl + relative;
6230
+ return { relative: relative, absolute: absolute };
6231
+ };
6232
+ /**
6233
+ * append the absolute URL to the content on the site
6234
+ * also updates the relative URL in case the
6235
+ * @param content
6236
+ * @param siteModel
6237
+ * @returns
6238
+ */
6239
+ var setContentSiteUrls = function (content, siteModel) {
6240
+ var _a = getContentSiteUrls(content, siteModel), relative = _a.relative, site = _a.absolute;
6214
6241
  // append the updated URLs to a new content
6215
6242
  return appendContentUrls(content, {
6216
6243
  relative: relative,
@@ -8461,6 +8488,46 @@
8461
8488
  return fn(clonedRequest);
8462
8489
  };
8463
8490
  }
8491
+ /**
8492
+ * Construct a the full url to a group thumbnail
8493
+ *
8494
+ * - If the group has a thumbnail, construct the full url
8495
+ * - If the group is not public, append on the token
8496
+ * @param portalUrl
8497
+ * @param group
8498
+ * @param token
8499
+ * @returns
8500
+ */
8501
+ function getGroupThumbnailUrl(portalUrl, group, token) {
8502
+ var thumbnailUrl = null;
8503
+ if (group.thumbnail) {
8504
+ thumbnailUrl = portalUrl + "/community/groups/" + group.id + "/info/" + group.thumbnail;
8505
+ if (token && group.access !== "public") {
8506
+ thumbnailUrl = thumbnailUrl + "?token=" + token;
8507
+ }
8508
+ }
8509
+ return thumbnailUrl;
8510
+ }
8511
+ /**
8512
+ * Construct a the full url to a user thumbnail
8513
+ *
8514
+ * - If the user has a thumbnail, construct the full url
8515
+ * - If the user is not public, append on the token
8516
+ * @param portalUrl
8517
+ * @param user
8518
+ * @param token
8519
+ * @returns
8520
+ */
8521
+ function getUserThumbnailUrl(portalUrl, user, token) {
8522
+ var thumbnailUrl = null;
8523
+ if (user.thumbnail) {
8524
+ thumbnailUrl = portalUrl + "/community/users/" + user.username + "/info/" + user.thumbnail;
8525
+ if (token && user.access !== "public") {
8526
+ thumbnailUrl = thumbnailUrl + "?token=" + token;
8527
+ }
8528
+ }
8529
+ return thumbnailUrl;
8530
+ }
8464
8531
 
8465
8532
  // TODO: Implement $dataset
8466
8533
  var ContentFilterExpansions = {
@@ -9010,6 +9077,140 @@
9010
9077
  return result;
9011
9078
  }
9012
9079
 
9080
+ /**
9081
+ *
9082
+ * Merge `Filter<"user">` objects
9083
+ *
9084
+ * Useful in components which may get partial filters from a variety of
9085
+ * sub-components, which are then combined into a single filter prior
9086
+ * to executing the search.
9087
+ * @param filters
9088
+ * @returns
9089
+ */
9090
+ function mergeUserFilters(filters) {
9091
+ // expand all the filters so all prop types are consistent
9092
+ var expanded = filters.map(expandUserFilter);
9093
+ // now we can merge based on fields
9094
+ var dateFields = ["created", "modified", "lastlogin"];
9095
+ var specialFields = __spreadArrays(["disabled", "term", "filterType"], dateFields);
9096
+ // acc is initialized as Filter<group> but also needs it
9097
+ // in the function signature... for reasons?!
9098
+ var result = expanded.reduce(function (acc, entry) {
9099
+ // process fields
9100
+ Object.entries(entry).forEach(function (_a) {
9101
+ // Note: getProp/setProp are used to get around
9102
+ // typescript issues with string indexing
9103
+ var key = _a[0], value = _a[1];
9104
+ if (acc.hasOwnProperty(key)) {
9105
+ var existingValue = getProp(acc, key);
9106
+ // if the key is not to a special field
9107
+ if (!specialFields.includes(key)) {
9108
+ // treat as an IMatchOptions
9109
+ setProp(key, mergeMatchOptions(existingValue, value), acc);
9110
+ }
9111
+ else if (dateFields.includes(key)) {
9112
+ // treat as IDateRange
9113
+ setProp(key, mergeDateRange(existingValue, value), acc);
9114
+ }
9115
+ else if (key === "term") {
9116
+ // append terms
9117
+ acc[key] = acc[key] + " " + value;
9118
+ }
9119
+ }
9120
+ else {
9121
+ // Acc does not have an entry for this yet
9122
+ // so just clone it
9123
+ setProp(key, cloneObject$1(value), acc);
9124
+ }
9125
+ });
9126
+ return acc;
9127
+ }, {
9128
+ filterType: "user",
9129
+ });
9130
+ return result;
9131
+ }
9132
+ /**
9133
+ * Prior to serialization into the query syntax for the backing APIs, we first expand [Filters](../Filter)
9134
+ *
9135
+ * Filter's can express their intent in a very terse form, but to ensure consistent structures
9136
+ * we expand them into their more verbose form.
9137
+ *
9138
+ * i.e. `firstname: "John"` expands into `firstname: { any: ["John"]}`
9139
+ *
9140
+ * - Fields defined as `string | string[] | MatchOptions` will be converted to a `MatchOptions`
9141
+ * - RelativeDate fields are converted to DateRange<number>
9142
+ * @param filter
9143
+ * @returns
9144
+ */
9145
+ function expandUserFilter(filter) {
9146
+ var result = {};
9147
+ var dateProps = ["created", "modified", "lastlogin"];
9148
+ var specialProps = __spreadArrays(["disabled", "term"], dateProps);
9149
+ Object.entries(filter).forEach(function (_a) {
9150
+ var key = _a[0], value = _a[1];
9151
+ // handle Matchish fields
9152
+ if (!specialProps.includes(key)) {
9153
+ // setProp side-steps typescript complaining
9154
+ setProp(key, valueToMatchOptions(value), result);
9155
+ }
9156
+ // Handle date fields
9157
+ if (dateProps.includes(key)) {
9158
+ var dateFieldValue = cloneObject$1(getProp(filter, key));
9159
+ if (getProp(filter, key + ".type") === "relative-date") {
9160
+ setProp(key, relativeDateToDateRange(dateFieldValue), result);
9161
+ }
9162
+ else {
9163
+ setProp(key, dateFieldValue, result);
9164
+ }
9165
+ }
9166
+ });
9167
+ // disabled is boolean, so we check if the prop exists
9168
+ // vs checking if the value is truthy
9169
+ if (filter.hasOwnProperty("disabled")) {
9170
+ result.disabled = filter.disabled;
9171
+ }
9172
+ if (filter.term) {
9173
+ result.term = filter.term;
9174
+ }
9175
+ return result;
9176
+ }
9177
+ /**
9178
+ * @private
9179
+ * Serialize an `IUserFilterDefinition` into an `ISearchOptions` for use
9180
+ * with `searchUsers`
9181
+ * @param filter
9182
+ * @returns
9183
+ */
9184
+ function serializeUserFilterForPortal(filter) {
9185
+ var result = {
9186
+ q: "",
9187
+ filter: "",
9188
+ };
9189
+ var dateProps = ["created", "modified", "lastlogin"];
9190
+ var specialProps = __spreadArrays(["term", "filterType"], dateProps);
9191
+ Object.entries(filter).forEach(function (_a) {
9192
+ var key = _a[0], value = _a[1];
9193
+ // MatchOptions fields
9194
+ if (!specialProps.includes(key)) {
9195
+ result = mergeSearchOptions(result, serializeMatchOptions(key, value), "AND");
9196
+ }
9197
+ // Dates only go into q
9198
+ if (dateProps.includes(key)) {
9199
+ result = mergeSearchOptions(result, serializeDateRange(key, value), "AND");
9200
+ }
9201
+ });
9202
+ // disabled is also a top-level property
9203
+ if (filter.hasOwnProperty("disabled")) {
9204
+ result.disabled = filter.disabled;
9205
+ }
9206
+ // add the term
9207
+ if (filter.term) {
9208
+ // Note: this is slightly different from other types
9209
+ result.q = ("(" + filter.term + ") " + result.q).trim();
9210
+ }
9211
+ return result;
9212
+ }
9213
+
9013
9214
  /**
9014
9215
  * Search for content via the Portal or Hub API
9015
9216
  * @param filter
@@ -9040,7 +9241,7 @@
9040
9241
  so.countSize = 200;
9041
9242
  }
9042
9243
  // copy over various options
9043
- // TODO: Dry this up
9244
+ // TODO: Dry this up - typscript makes this... inconvenient
9044
9245
  if (options.num) {
9045
9246
  so.num = options.num;
9046
9247
  }
@@ -9127,9 +9328,16 @@
9127
9328
  else {
9128
9329
  so.portal = api.url + "/sharing/rest";
9129
9330
  }
9331
+ // TODO: Dry this up - typscript makes this... inconvenient
9130
9332
  if (options.num) {
9131
9333
  so.num = options.num;
9132
9334
  }
9335
+ if (options.sortField) {
9336
+ so.sortField = options.sortField;
9337
+ }
9338
+ if (options.sortOrder) {
9339
+ so.sortOrder = options.sortOrder;
9340
+ }
9133
9341
  api.url + "/sharing/rest";
9134
9342
  if ((_a = so.authentication) === null || _a === void 0 ? void 0 : _a.portal) {
9135
9343
  so.authentication.portal;
@@ -9145,6 +9353,11 @@
9145
9353
  });
9146
9354
  });
9147
9355
  }
9356
+ /**
9357
+ * Internal function that searches for groups using the ArcGIS Portal API
9358
+ * @param searchOptions
9359
+ * @returns
9360
+ */
9148
9361
  function searchPortalGroups(searchOptions) {
9149
9362
  var _a;
9150
9363
  var teamLinkify = function (group) {
@@ -9158,9 +9371,9 @@
9158
9371
  var us = searchOptions.authentication;
9159
9372
  token = us.token;
9160
9373
  }
9161
- // Partially apply url and token to addThumbnailUrl fn
9162
9374
  var thumbnailify = function (group) {
9163
- return addThumbnailUrl(portalUrl, group, token);
9375
+ group.thumbnailUrl = getGroupThumbnailUrl(portalUrl, group, token);
9376
+ return group;
9164
9377
  };
9165
9378
  // execute the search
9166
9379
  return searchGroups(searchOptions).then(function (response) {
@@ -9180,23 +9393,89 @@
9180
9393
  };
9181
9394
  });
9182
9395
  }
9396
+
9183
9397
  /**
9184
- * Internal helper that adds `thumbnailUrl` property to an `IGroup`
9185
- * if the `.thumbnail` property is defined.
9186
- * Will add a token if group is not public and a token is passed in
9187
- * @param portalUrl
9188
- * @param group
9189
- * @param token
9398
+ * Search for Users via the Portal API.
9399
+ *
9400
+ * **Note** Authentication is required
9401
+ *
9402
+ * Note: in the future, there may be options to search via
9403
+ * a Hub specific API
9404
+ * @param filter
9405
+ * @param options
9190
9406
  * @returns
9191
9407
  */
9192
- function addThumbnailUrl(portalUrl, group, token) {
9193
- if (group.thumbnail) {
9194
- group.thumbnailUrl = portalUrl + "/community/groups/" + group.id + "/info/" + group.thumbnail;
9195
- if (token && group.access !== "public") {
9196
- group.thumbnailUrl = group.thumbnailUrl + "?token=" + token;
9408
+ function _searchUsers(filter, options) {
9409
+ return __awaiter(this, void 0, void 0, function () {
9410
+ var expanded, api, searchOptions;
9411
+ return __generator(this, function (_a) {
9412
+ // JS Clients may not pass in authentication
9413
+ if (!options.authentication) {
9414
+ throw new Error("Authentication required to search for users.");
9415
+ }
9416
+ expanded = expandUserFilter(filter);
9417
+ api = expandApi(options.api || "arcgis");
9418
+ if (api.type === "arcgis") {
9419
+ searchOptions = serializeUserFilterForPortal(expanded);
9420
+ // carry the auth forward
9421
+ searchOptions.authentication = options.authentication;
9422
+ // TODO: Dry this up - typscript makes this... inconvenient
9423
+ if (options.num) {
9424
+ searchOptions.num = options.num;
9425
+ }
9426
+ if (options.sortField) {
9427
+ searchOptions.sortField = options.sortField;
9428
+ }
9429
+ if (options.sortOrder) {
9430
+ searchOptions.sortOrder = options.sortOrder;
9431
+ }
9432
+ if (options.site) {
9433
+ searchOptions.site = cloneObject$1(options.site);
9434
+ }
9435
+ return [2 /*return*/, searchPortalUsers(searchOptions)];
9436
+ }
9437
+ else {
9438
+ throw new Error("_searchUsers is not implemented for non-arcgis apis");
9439
+ }
9440
+ });
9441
+ });
9442
+ }
9443
+ /**
9444
+ * Internal function that executes the user search along with
9445
+ * some simple enrichments
9446
+ * @param searchOptions
9447
+ * @returns
9448
+ */
9449
+ function searchPortalUsers(searchOptions) {
9450
+ var portalUrl = searchOptions.authentication.portal;
9451
+ var token = searchOptions.authentication.token;
9452
+ // Partially applied functions for mapping over the results
9453
+ var userLinkify = function (user) {
9454
+ user.profileUrl = searchOptions.site.item.url + "/people/" + user.username + "/profile";
9455
+ return user;
9456
+ };
9457
+ var thumbnailify = function (user) {
9458
+ if (user.thumbnail) {
9459
+ user.thumbnailUrl = getUserThumbnailUrl(portalUrl, user, token);
9197
9460
  }
9198
- }
9199
- return group;
9461
+ return user;
9462
+ };
9463
+ return searchUsers(searchOptions).then(function (response) {
9464
+ var _a, _b;
9465
+ var hasNext = response.nextStart > -1;
9466
+ // upgrade thumbnail url
9467
+ var results = response.results.map(thumbnailify);
9468
+ // generate the site team url if site url is provided
9469
+ if ((_b = (_a = searchOptions.site) === null || _a === void 0 ? void 0 : _a.item) === null || _b === void 0 ? void 0 : _b.url) {
9470
+ results = response.results.map(userLinkify);
9471
+ }
9472
+ return {
9473
+ hasNext: hasNext,
9474
+ total: response.total,
9475
+ results: results,
9476
+ next: getNextFunction(searchOptions, response.nextStart, response.total, searchPortalUsers),
9477
+ };
9478
+ });
9200
9479
  }
9201
9480
 
9202
9481
  /**
@@ -9805,6 +10084,9 @@
9805
10084
  model = _purgeNonGuidsFromCatalog(model);
9806
10085
  model = _ensureTelemetry(model);
9807
10086
  model = _migrateFeedConfig(model);
10087
+ // WARNING - If you are writing a site schema migration,
10088
+ // you probably need to apply it to site drafts as well!
10089
+ // See https://github.com/Esri/hub.js/issues/498 for more details.
9808
10090
  return model;
9809
10091
  }
9810
10092
  }
@@ -10441,6 +10723,7 @@
10441
10723
  exports._processSecondaryEmail = _processSecondaryEmail;
10442
10724
  exports._searchContent = _searchContent;
10443
10725
  exports._searchGroups = _searchGroups;
10726
+ exports._searchUsers = _searchUsers;
10444
10727
  exports._unprotectAndRemoveGroup = _unprotectAndRemoveGroup;
10445
10728
  exports._unprotectAndRemoveItem = _unprotectAndRemoveItem;
10446
10729
  exports.addContextToSlug = addContextToSlug;
@@ -10495,6 +10778,7 @@
10495
10778
  exports.expandContentFilter = expandContentFilter;
10496
10779
  exports.expandGroupFilter = expandGroupFilter;
10497
10780
  exports.expandTypeField = expandTypeField;
10781
+ exports.expandUserFilter = expandUserFilter;
10498
10782
  exports.extend = extend;
10499
10783
  exports.extentToBBox = extentToBBox;
10500
10784
  exports.failSafe = failSafe;
@@ -10512,12 +10796,14 @@
10512
10796
  exports.getCategory = getCategory;
10513
10797
  exports.getCollection = getCollection;
10514
10798
  exports.getContentIdentifier = getContentIdentifier;
10799
+ exports.getContentSiteUrls = getContentSiteUrls;
10515
10800
  exports.getCulture = getCulture;
10516
10801
  exports.getDomainsForSite = getDomainsForSite;
10517
10802
  exports.getExportItemTypeKeyword = getExportItemTypeKeyword;
10518
10803
  exports.getExportLayerTypeKeyword = getExportLayerTypeKeyword;
10519
10804
  exports.getFamily = getFamily;
10520
10805
  exports.getGeographicOrgExtent = getGeographicOrgExtent;
10806
+ exports.getGroupThumbnailUrl = getGroupThumbnailUrl;
10521
10807
  exports.getHubApiUrl = getHubApiUrl;
10522
10808
  exports.getHubApiUrlFromPortal = getHubApiUrlFromPortal;
10523
10809
  exports.getHubLocaleAssetUrl = getHubLocaleAssetUrl;
@@ -10554,6 +10840,7 @@
10554
10840
  exports.getUniqueDomainName = getUniqueDomainName;
10555
10841
  exports.getUniqueDomainNamePortal = getUniqueDomainNamePortal;
10556
10842
  exports.getUniqueItemTitle = getUniqueItemTitle;
10843
+ exports.getUserThumbnailUrl = getUserThumbnailUrl;
10557
10844
  exports.getWithDefault = getWithDefault$1;
10558
10845
  exports.hasBasePriv = hasBasePriv;
10559
10846
  exports.hubApiRequest = hubApiRequest;
@@ -10589,6 +10876,7 @@
10589
10876
  exports.mergeMatchOptions = mergeMatchOptions;
10590
10877
  exports.mergeObjects = mergeObjects;
10591
10878
  exports.mergeSearchOptions = mergeSearchOptions;
10879
+ exports.mergeUserFilters = mergeUserFilters;
10592
10880
  exports.normalizeItemType = normalizeItemType;
10593
10881
  exports.normalizeSolutionTemplateItem = normalizeSolutionTemplateItem;
10594
10882
  exports.objectToArray = objectToArray;
@@ -10610,6 +10898,7 @@
10610
10898
  exports.serializeModel = serializeModel;
10611
10899
  exports.serializeSpatialReference = serializeSpatialReference;
10612
10900
  exports.serializeStringOrArray = serializeStringOrArray;
10901
+ exports.serializeUserFilterForPortal = serializeUserFilterForPortal;
10613
10902
  exports.setContentHubId = setContentHubId;
10614
10903
  exports.setContentSiteUrls = setContentSiteUrls;
10615
10904
  exports.setContentType = setContentType;