@esri/hub-common 9.3.0 → 9.4.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 (40) hide show
  1. package/dist/es2017/search/_searchContent.js +62 -0
  2. package/dist/es2017/search/_searchContent.js.map +1 -0
  3. package/dist/es2017/search/content-utils.js +422 -0
  4. package/dist/es2017/search/content-utils.js.map +1 -0
  5. package/dist/es2017/search/index.js +4 -0
  6. package/dist/es2017/search/index.js.map +1 -1
  7. package/dist/es2017/search/types.js +1 -0
  8. package/dist/es2017/search/types.js.map +1 -0
  9. package/dist/es2017/search/utils.js +344 -0
  10. package/dist/es2017/search/utils.js.map +1 -0
  11. package/dist/esm/search/_searchContent.js +70 -0
  12. package/dist/esm/search/_searchContent.js.map +1 -0
  13. package/dist/esm/search/content-utils.js +426 -0
  14. package/dist/esm/search/content-utils.js.map +1 -0
  15. package/dist/esm/search/index.js +4 -0
  16. package/dist/esm/search/index.js.map +1 -1
  17. package/dist/esm/search/types.js +1 -0
  18. package/dist/esm/search/types.js.map +1 -0
  19. package/dist/esm/search/utils.js +341 -0
  20. package/dist/esm/search/utils.js.map +1 -0
  21. package/dist/node/search/_searchContent.js +66 -0
  22. package/dist/node/search/_searchContent.js.map +1 -0
  23. package/dist/node/search/content-utils.js +432 -0
  24. package/dist/node/search/content-utils.js.map +1 -0
  25. package/dist/node/search/index.js +4 -0
  26. package/dist/node/search/index.js.map +1 -1
  27. package/dist/node/search/types.js +3 -0
  28. package/dist/node/search/types.js.map +1 -0
  29. package/dist/node/search/utils.js +357 -0
  30. package/dist/node/search/utils.js.map +1 -0
  31. package/dist/types/search/_searchContent.d.ts +7 -0
  32. package/dist/types/search/content-utils.d.ts +70 -0
  33. package/dist/types/search/index.d.ts +4 -0
  34. package/dist/types/search/types.d.ts +294 -0
  35. package/dist/types/search/utils.d.ts +92 -0
  36. package/dist/umd/common.umd.js +842 -1
  37. package/dist/umd/common.umd.js.map +1 -1
  38. package/dist/umd/common.umd.min.js +1 -1
  39. package/dist/umd/common.umd.min.js.map +1 -1
  40. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  /* @preserve
2
- * @esri/hub-common - v9.2.0 - Wed Oct 27 2021 08:57:00 GMT-0600 (Mountain Daylight Time)
2
+ * @esri/hub-common - v9.3.0 - Thu Oct 28 2021 14:17:26 GMT-0600 (Mountain Daylight Time)
3
3
  * Copyright (c) 2021 Environmental Systems Research Institute, Inc.
4
4
  * Apache-2.0
5
5
  */
@@ -7979,6 +7979,828 @@
7979
7979
  return hubApiRequest("/search", __assign(__assign({}, defaults), requestOptions));
7980
7980
  }
7981
7981
 
7982
+ /* Copyright (c) 2018-2021 Environmental Systems Research Institute, Inc.
7983
+ * Apache-2.0 */
7984
+ /**
7985
+ * Well known APIs
7986
+ * Short-forms for specifying common APIs
7987
+ */
7988
+ var SEARCH_APIS = {
7989
+ arcgis: {
7990
+ label: "ArcGIS Online",
7991
+ url: "https://www.arcgis.com",
7992
+ type: "arcgis",
7993
+ },
7994
+ arcgisQA: {
7995
+ label: "ArcGIS Online QAEXT",
7996
+ url: "https://qaext.arcgis.com",
7997
+ type: "arcgis",
7998
+ },
7999
+ arcgisDEV: {
8000
+ label: "ArcGIS Online DEVEXT",
8001
+ url: "https://devext.arcgis.com",
8002
+ type: "arcgis",
8003
+ },
8004
+ hub: {
8005
+ label: "ArcGIS Hub",
8006
+ url: "https://hub.arcgis.com/api",
8007
+ type: "arcgis-hub",
8008
+ },
8009
+ hubDEV: {
8010
+ label: "ArcGIS Hub DEV",
8011
+ url: "https://hubdev.arcgis.com/api",
8012
+ type: "arcgis-hub",
8013
+ },
8014
+ hubQA: {
8015
+ label: "ArcGIS Hub QA",
8016
+ url: "https://hubqa.arcgis.com/api",
8017
+ type: "arcgis-hub",
8018
+ },
8019
+ };
8020
+ /**
8021
+ * @private
8022
+ * Convert api "names" into full ApiDefinitions
8023
+ * @param apis
8024
+ * @returns
8025
+ */
8026
+ function expandApis(apis) {
8027
+ return apis.map(function (api) {
8028
+ if (typeof api === "string" && api in SEARCH_APIS) {
8029
+ return SEARCH_APIS[api];
8030
+ }
8031
+ else {
8032
+ // it's an object, so we trust that it's well formed
8033
+ return api;
8034
+ }
8035
+ });
8036
+ }
8037
+ /**
8038
+ * @private
8039
+ * Merge multiple search responses
8040
+ *
8041
+ * Naieve implementation that just merges arrays
8042
+ * @param responses
8043
+ * @returns
8044
+ */
8045
+ function mergeSearchResults(responses) {
8046
+ // Merge content
8047
+ var content = responses.reduce(function (acc, response) {
8048
+ if (response.content) {
8049
+ acc = acc.concat(response.content);
8050
+ }
8051
+ return acc;
8052
+ }, []);
8053
+ // Merge Facets
8054
+ var facets = responses.reduce(function (acc, response) {
8055
+ if (response.facets) {
8056
+ acc = acc.concat(response.facets);
8057
+ }
8058
+ return acc;
8059
+ }, []);
8060
+ return { content: content, facets: facets };
8061
+ }
8062
+ /**
8063
+ * @private
8064
+ * Merge two date ranges by taking the longest span
8065
+ * @param dr1
8066
+ * @param dr2
8067
+ * @returns
8068
+ */
8069
+ function mergeDateRange(dr1, dr2) {
8070
+ var result = cloneObject$1(dr1);
8071
+ // feels like there is a more concise way to do this...
8072
+ if (dr2.from < dr1.from) {
8073
+ result.from = dr2.from;
8074
+ }
8075
+ if (dr2.to > dr1.to) {
8076
+ result.to = dr2.to;
8077
+ }
8078
+ return result;
8079
+ }
8080
+ /**
8081
+ * @private
8082
+ * Merge two [`MatchOptions`](../MatchOptions)
8083
+ *
8084
+ * Currently a naieve implementation where the arrays are simply merged
8085
+ *
8086
+ * @param mo1
8087
+ * @param mo2
8088
+ * @returns
8089
+ */
8090
+ function mergeMatchOptions(mo1, mo2) {
8091
+ var result = {};
8092
+ // None of these props are required, so we can't just
8093
+ // use Object.keys/.entries
8094
+ var props = ["any", "all", "not", "exact"];
8095
+ props.forEach(function (prop) {
8096
+ var key = prop;
8097
+ var merged = __spreadArrays(getMatchValue(mo1, key), getMatchValue(mo2, key));
8098
+ if (merged.length) {
8099
+ // remove any dupes and set on the return
8100
+ result[key] = merged.filter(unique);
8101
+ }
8102
+ });
8103
+ return result;
8104
+ }
8105
+ /**
8106
+ * Get the value of a property on an IMatchOptions
8107
+ *
8108
+ * This is complex b/c all the props are optional, and
8109
+ * they could be a simple string, or an array of strings.
8110
+ *
8111
+ * This function normalizes all that and returns an array,
8112
+ * which may or may not be empty
8113
+ * @param option
8114
+ * @param key
8115
+ * @returns
8116
+ */
8117
+ function getMatchValue(option, key) {
8118
+ var matchValue = [];
8119
+ if (option[key]) {
8120
+ var val = option[key];
8121
+ if (Array.isArray(val)) {
8122
+ matchValue = val;
8123
+ }
8124
+ else {
8125
+ matchValue = [val];
8126
+ }
8127
+ }
8128
+ return matchValue;
8129
+ }
8130
+ /**
8131
+ * @private
8132
+ * Convert a field value into a MatchOptions if it's not already one
8133
+ * @param value
8134
+ * @returns
8135
+ */
8136
+ function valueToMatchOptions(value) {
8137
+ var result = {};
8138
+ if (Array.isArray(value)) {
8139
+ result = {
8140
+ any: value,
8141
+ };
8142
+ }
8143
+ else {
8144
+ if (typeof value === "string") {
8145
+ result = {
8146
+ any: [value],
8147
+ };
8148
+ }
8149
+ if (typeof value === "object") {
8150
+ result = value;
8151
+ }
8152
+ }
8153
+ return result;
8154
+ }
8155
+ /**
8156
+ * @private
8157
+ * Convert a RelativeDate to a DateRange<number>
8158
+ * @param relative
8159
+ * @returns
8160
+ */
8161
+ function relativeDateToDateRange(relative) {
8162
+ // hash of offsets
8163
+ var offsetMs = {
8164
+ min: 1000 * 60,
8165
+ hours: 1000 * 60 * 60,
8166
+ days: 1000 * 60 * 60 * 24,
8167
+ weeks: 1000 * 60 * 60 * 24 * 7,
8168
+ };
8169
+ var now = new Date();
8170
+ // default
8171
+ var result = {
8172
+ type: "date-range",
8173
+ from: now.getTime(),
8174
+ to: now.getTime(),
8175
+ };
8176
+ //
8177
+ switch (relative.unit) {
8178
+ case "hours":
8179
+ case "days":
8180
+ case "weeks":
8181
+ result.from = result.to - offsetMs[relative.unit] * relative.num;
8182
+ break;
8183
+ case "months":
8184
+ // get the current month and subtract num
8185
+ now.setMonth(now.getMonth() - relative.num);
8186
+ result.from = now.getTime();
8187
+ break;
8188
+ case "years":
8189
+ now.setFullYear(now.getFullYear() - relative.num);
8190
+ result.from = now.getTime();
8191
+ break;
8192
+ }
8193
+ return result;
8194
+ }
8195
+ /**
8196
+ * @private
8197
+ * As a final `ISearchOptions` object gets created, many such objects are created, and
8198
+ * need to be systematically "merged" so as to return consistently structured `q` and `filter`
8199
+ * values.
8200
+ * @param so1
8201
+ * @param so2
8202
+ * @param join
8203
+ * @returns
8204
+ */
8205
+ function mergeSearchOptions(so1, so2, join) {
8206
+ var result = cloneObject$1(so1);
8207
+ var q = so2.q, filter = so2.filter;
8208
+ if (q) {
8209
+ result.q = (result.q ? " (" + result.q + " " + join + " " + q + ")" : q).trim();
8210
+ }
8211
+ if (filter) {
8212
+ result.filter = (result.filter ? "(" + result.filter + " " + join + " " + filter + ")" : filter).trim();
8213
+ }
8214
+ return result;
8215
+ }
8216
+ /**
8217
+ * @private
8218
+ * Serialize a `MatchOptions` into `q` or `filter` on an `ISearchOptions`
8219
+ * @param key
8220
+ * @param opts
8221
+ * @returns
8222
+ */
8223
+ function serializeMatchOptions(key, opts) {
8224
+ var result = {
8225
+ q: "",
8226
+ filter: "",
8227
+ };
8228
+ if (opts.exact) {
8229
+ // defined separately for refactoring later
8230
+ var userFilterableFields = [
8231
+ "username",
8232
+ "firstname",
8233
+ "lastname",
8234
+ "fullname",
8235
+ "email",
8236
+ ];
8237
+ var itemFilterableFields = [
8238
+ "title",
8239
+ "tags",
8240
+ "typekeywords",
8241
+ "type",
8242
+ "name",
8243
+ "owner",
8244
+ ];
8245
+ var groupFilterableFields = ["title", "typekeywords", "owner"];
8246
+ var filterableFields = __spreadArrays(userFilterableFields, itemFilterableFields, groupFilterableFields);
8247
+ if (filterableFields.includes(key)) {
8248
+ result.filter = serializeStringOrArray("AND", key, opts.exact);
8249
+ }
8250
+ else {
8251
+ // Treat it the same as .all
8252
+ if (typeof opts.exact === "string") {
8253
+ if (!opts.all) {
8254
+ opts.all = [];
8255
+ }
8256
+ if (typeof opts.all === "string") {
8257
+ opts.all = [opts.all];
8258
+ }
8259
+ opts.all.push(opts.exact);
8260
+ }
8261
+ if (Array.isArray(opts.exact)) {
8262
+ if (!opts.all) {
8263
+ opts.all = [];
8264
+ }
8265
+ if (typeof opts.all === "string") {
8266
+ opts.all = [opts.all];
8267
+ }
8268
+ opts.all = opts.all.concat(opts.exact);
8269
+ }
8270
+ }
8271
+ }
8272
+ // Handle the other props
8273
+ if (opts.any) {
8274
+ result.q = serializeStringOrArray("OR", key, opts.any);
8275
+ }
8276
+ if (opts.all) {
8277
+ result.q =
8278
+ (result.q ? result.q + " AND " : "") +
8279
+ serializeStringOrArray("AND", key, opts.all);
8280
+ }
8281
+ if (opts.not) {
8282
+ // negate the entries if they are not
8283
+ result.q =
8284
+ (result.q ? result.q + " AND " : "") +
8285
+ serializeStringOrArray("OR", "-" + key, opts.not);
8286
+ }
8287
+ return result;
8288
+ }
8289
+ /**
8290
+ * @private
8291
+ * Serialize a DateRange<number> into a Portal Query string
8292
+ * @param key
8293
+ * @param range
8294
+ * @returns
8295
+ */
8296
+ function serializeDateRange(key, range) {
8297
+ return {
8298
+ q: key + ":[" + range.from + " TO " + range.to + "]",
8299
+ filter: "",
8300
+ };
8301
+ }
8302
+ /**
8303
+ * @private
8304
+ * Serialize a `string` or `string[]` into a string
8305
+ * @param join
8306
+ * @param key
8307
+ * @param value
8308
+ * @returns
8309
+ */
8310
+ function serializeStringOrArray(join, key, value) {
8311
+ var q = "";
8312
+ if (Array.isArray(value)) {
8313
+ q = "(" + key + ":\"" + value.join("\" " + join + " " + key + ":\"") + "\")";
8314
+ }
8315
+ else {
8316
+ q = key + ":\"" + value + "\"";
8317
+ }
8318
+ return q;
8319
+ }
8320
+
8321
+ // TODO: Implement $dataset
8322
+ var ContentFilterExpansions = {
8323
+ $apps: [
8324
+ {
8325
+ type: {
8326
+ any: [
8327
+ "Code Sample",
8328
+ "Web Mapping Application",
8329
+ "Mobile Application",
8330
+ "Application",
8331
+ "Desktop Application Template",
8332
+ "Desktop Application",
8333
+ "Operation View",
8334
+ "Dashboard",
8335
+ "Operations Dashboard Extension",
8336
+ "Workforce Project",
8337
+ "Insights Workbook",
8338
+ "Insights Page",
8339
+ "Insights Model",
8340
+ "Hub Page",
8341
+ "Hub Initiative",
8342
+ "Hub Site Application",
8343
+ "StoryMap",
8344
+ "Web Experience",
8345
+ "Web Experience Template",
8346
+ "Form",
8347
+ ],
8348
+ not: [
8349
+ "Code Attachment",
8350
+ "Featured Items",
8351
+ "Symbol Set",
8352
+ "Color Set",
8353
+ "Windows Viewer Add In",
8354
+ "Windows Viewer Configuration",
8355
+ "Map Area",
8356
+ "Indoors Map Configuration",
8357
+ ],
8358
+ },
8359
+ typekeywords: {
8360
+ not: ["MapAreaPackage", "SMX"],
8361
+ },
8362
+ },
8363
+ ],
8364
+ $storymap: [
8365
+ {
8366
+ type: "StoryMap",
8367
+ },
8368
+ {
8369
+ type: "Web Mapping Application",
8370
+ typekeywords: ["Story Map"],
8371
+ },
8372
+ ],
8373
+ $dashboard: [
8374
+ {
8375
+ type: "Dashboard",
8376
+ typekeywords: {
8377
+ any: ["Dashboard"],
8378
+ not: ["ArcGIS Operation View", "Add In", "Extension"],
8379
+ },
8380
+ },
8381
+ ],
8382
+ $dataset: [],
8383
+ $experience: [
8384
+ {
8385
+ type: {
8386
+ any: ["Web Experience"],
8387
+ not: ["Web Experience Template"],
8388
+ },
8389
+ },
8390
+ ],
8391
+ $site: [
8392
+ {
8393
+ type: ["Hub Site Application", "Site Application"],
8394
+ },
8395
+ {
8396
+ type: ["Web Mapping Application"],
8397
+ typekeywords: ["hubSite"],
8398
+ },
8399
+ ],
8400
+ $initiative: [
8401
+ {
8402
+ type: {
8403
+ any: "Hub Initiative",
8404
+ not: "Hub Initiative Template",
8405
+ },
8406
+ },
8407
+ ],
8408
+ $document: [
8409
+ {
8410
+ typekeywords: {
8411
+ any: "Document",
8412
+ not: ["MapAreaPackage", "SMX"],
8413
+ },
8414
+ type: {
8415
+ any: [
8416
+ "Image",
8417
+ "Layout",
8418
+ "Desktop Style",
8419
+ "Project Template",
8420
+ "Report Template",
8421
+ "Pro Report",
8422
+ "Statistical Data Collection",
8423
+ "360 VR Experience",
8424
+ "netCDF",
8425
+ "PDF",
8426
+ "CSV",
8427
+ "Administrative Report",
8428
+ "Raster function template",
8429
+ ],
8430
+ not: [
8431
+ "Image Service",
8432
+ "Explorer Document",
8433
+ "Explorer Map",
8434
+ "Globe Document",
8435
+ "Scene Document",
8436
+ "Code Attachment",
8437
+ "Featured Items",
8438
+ "Symbol Set",
8439
+ "ColorSet",
8440
+ "Windows Viewer Add In",
8441
+ "Windows Viewer Configuration",
8442
+ "Map Area",
8443
+ "Indoors Map Configuration",
8444
+ ],
8445
+ },
8446
+ },
8447
+ ],
8448
+ };
8449
+ /**
8450
+ * @private
8451
+ * Convert portal search response to items
8452
+ * @param response
8453
+ * @returns
8454
+ */
8455
+ function convertPortalResponseToFacets(response) {
8456
+ var _a;
8457
+ var result = [];
8458
+ if ((_a = response.aggregations) === null || _a === void 0 ? void 0 : _a.counts) {
8459
+ response.aggregations.counts.forEach(function (entry) {
8460
+ var facet = {
8461
+ label: entry.fieldName,
8462
+ attribute: entry.fieldName,
8463
+ type: "multi-select",
8464
+ };
8465
+ var options = [];
8466
+ entry.fieldValues.forEach(function (fv) {
8467
+ var filter = {
8468
+ filterType: "content",
8469
+ };
8470
+ filter[entry.fieldName] = fv.value;
8471
+ var fo = {
8472
+ label: fv.value,
8473
+ value: fv.value,
8474
+ count: fv.count,
8475
+ selected: false,
8476
+ filter: filter,
8477
+ };
8478
+ options.push(fo);
8479
+ });
8480
+ facet.options = options;
8481
+ result.push(facet);
8482
+ });
8483
+ }
8484
+ return result;
8485
+ }
8486
+ /**
8487
+ * @private
8488
+ * Merge `Filter<"content">` objects
8489
+ * @param filters
8490
+ * @returns
8491
+ */
8492
+ function mergeContentFilter(filters) {
8493
+ // expand all the filters so all prop types are consistent
8494
+ var expanded = filters.map(expandContentFilter);
8495
+ // now we can merge based on fields
8496
+ var dateFields = ["created", "modified"];
8497
+ var specialFields = __spreadArrays(["filterType", "subFilters"], dateFields);
8498
+ var result = expanded.reduce(function (acc, entry) {
8499
+ // process fields
8500
+ Object.entries(entry).forEach(function (_a) {
8501
+ var key = _a[0], value = _a[1];
8502
+ // MatchOption fields
8503
+ if (!specialFields.includes(key)) {
8504
+ if (acc[key]) {
8505
+ acc[key] = mergeMatchOptions(acc[key], value);
8506
+ }
8507
+ else {
8508
+ acc[key] = cloneObject$1(value);
8509
+ }
8510
+ }
8511
+ // Dates
8512
+ if (dateFields.includes(key)) {
8513
+ if (acc[key]) {
8514
+ acc[key] = mergeDateRange(acc[key], value);
8515
+ }
8516
+ else {
8517
+ acc[key] = cloneObject$1(value);
8518
+ }
8519
+ }
8520
+ // SubFilters
8521
+ if (key === "subFilters" && Array.isArray(value)) {
8522
+ if (acc.subFilters) {
8523
+ acc.subFilters = mergeSubFilters(acc.subFilters, value);
8524
+ }
8525
+ else {
8526
+ acc.subFilters = cloneObject$1(value);
8527
+ }
8528
+ }
8529
+ });
8530
+ return acc;
8531
+ }, {});
8532
+ result.filterType = "content";
8533
+ return result;
8534
+ }
8535
+ function mergeSubFilters(sf1, sf2) {
8536
+ // Simplistic implementation: we just merge the arrays
8537
+ // in the future we may try to de-dupe things as a safeguard
8538
+ return __spreadArrays(sf1, sf2);
8539
+ }
8540
+ /**
8541
+ * Prior to serialization into the query syntax for the backing APIs, we first expand [Filters](../Filter)
8542
+ *
8543
+ * Filter's can express their intent in a very terse form, but to ensure consistent
8544
+ * into their more verbose form.
8545
+ *
8546
+ * i.e. `title: "Water"` expands into `title: { any: ["Water"]}`
8547
+ *
8548
+ * - "well known" type values are expanded
8549
+ * - i.e. `type: "$storymap"` expands into two `subFilter` entries
8550
+ * - Fields defined as `string | string[] | MatchOptions` will be converted to a `MatchOptions`
8551
+ * - RelativeDate fields are converted to DateRange<number>
8552
+ *
8553
+ * @param filter
8554
+ * @returns
8555
+ */
8556
+ function expandContentFilter(filter) {
8557
+ // Expand filter.type first
8558
+ var expandedTypeFilter = expandTypeField(filter);
8559
+ // Expand subfilters
8560
+ // Guard - JS Clients could send in anything...
8561
+ if (Array.isArray(filter.subFilters)) {
8562
+ // Convert any strings into the coresponding ContentFilterDefinition
8563
+ expandedTypeFilter.subFilters = expandedTypeFilter.subFilters.reduce(function (acc, entry) {
8564
+ if (typeof entry === "string") {
8565
+ // if the entry is not a key of ContentFilterExpansions
8566
+ // we just skip over it
8567
+ if (ContentFilterExpansions[entry]) {
8568
+ acc = acc.concat(ContentFilterExpansions[entry]);
8569
+ }
8570
+ }
8571
+ else {
8572
+ acc.push(entry); // should be a ContentFilterDefinition
8573
+ }
8574
+ return acc;
8575
+ }, []);
8576
+ }
8577
+ // Convert all props into MatchOptions/DateRanges
8578
+ return convertContentDefinitionToFilter(expandedTypeFilter);
8579
+ }
8580
+ /**
8581
+ * @private
8582
+ * Expand from a well-known "type" into it's longer form
8583
+ *
8584
+ * i.e. `type: "$storymap"` expands into two subFilters entries
8585
+ *
8586
+ * @param filter
8587
+ * @returns
8588
+ */
8589
+ function expandTypeField(filter) {
8590
+ var clone = cloneObject$1(filter);
8591
+ // ensure subFilters is defined as an array
8592
+ clone.subFilters = clone.subFilters || [];
8593
+ if (clone.type) {
8594
+ // if .type is an Array...
8595
+ if (Array.isArray(clone.type)) {
8596
+ // remove any well-known-keys and move their expansions into subfilters
8597
+ clone.type = clone.type.reduce(function (acc, entry) {
8598
+ if (isWellKnownType(entry)) {
8599
+ // working with dynamic objects in typescript requires some assertions
8600
+ var key = entry;
8601
+ clone.subFilters = clone.subFilters.concat(lookupTypeFilters(key));
8602
+ }
8603
+ else {
8604
+ acc.push(entry);
8605
+ }
8606
+ return acc;
8607
+ }, []);
8608
+ }
8609
+ else if (isWellKnownType(clone.type)) {
8610
+ var key = clone.type;
8611
+ clone.subFilters = clone.subFilters.concat(lookupTypeFilters(key));
8612
+ delete clone.type;
8613
+ }
8614
+ else ;
8615
+ }
8616
+ return clone;
8617
+ }
8618
+ /**
8619
+ * Is the argument a well-known type "key"
8620
+ *
8621
+ * Accepts `string`, `string[]` or `IMatchOptions`
8622
+ * but only string values can possibly be properties
8623
+ * on `ContentFilterExpansions`
8624
+ * @param key
8625
+ * @returns
8626
+ */
8627
+ function isWellKnownType(key) {
8628
+ var result = false;
8629
+ if (typeof key === "string") {
8630
+ result = key in ContentFilterExpansions;
8631
+ }
8632
+ return result;
8633
+ }
8634
+ function lookupTypeFilters(key) {
8635
+ return ContentFilterExpansions[key];
8636
+ }
8637
+ /**
8638
+ * @private
8639
+ * Convert a `ContentFilterDefinition` to a `ContentFilter`
8640
+ *
8641
+ * ContentFilter is a narrower version of ContentFilterDefinition, without
8642
+ * the union types. Using a ContentFilter makes working with the structure
8643
+ * in typescript much easier.
8644
+ *
8645
+ * @param filter
8646
+ * @returns
8647
+ */
8648
+ function convertContentDefinitionToFilter(filter) {
8649
+ var result = {};
8650
+ if (filter.term) {
8651
+ result.term = filter.term;
8652
+ }
8653
+ var dateProps = ["created", "modified"];
8654
+ // Some properties should not get converted to MatchOptions
8655
+ var specialProps = __spreadArrays(["filterType", "subFilters", "term"], dateProps);
8656
+ // Do the conversion
8657
+ Object.entries(filter).forEach(function (_a) {
8658
+ var key = _a[0], value = _a[1];
8659
+ if (!specialProps.includes(key)) {
8660
+ result[key] = valueToMatchOptions(value);
8661
+ }
8662
+ });
8663
+ // Special Cases
8664
+ // subFilters; Array of ContentFilterDefinitions
8665
+ if (filter.subFilters && Array.isArray(filter.subFilters)) {
8666
+ // downcast - would be nice to skip this or use some other constuct
8667
+ var sf = filter.subFilters;
8668
+ result.subFilters = sf.map(convertContentDefinitionToFilter);
8669
+ }
8670
+ // Dates; Ensure they are all DateRange<number>
8671
+ dateProps.forEach(function (fld) {
8672
+ if (filter[fld]) {
8673
+ if (filter[fld].type === "relative-date") {
8674
+ result[fld] = relativeDateToDateRange(filter[fld]);
8675
+ }
8676
+ else {
8677
+ result[fld] = cloneObject$1(filter[fld]);
8678
+ }
8679
+ }
8680
+ });
8681
+ return result;
8682
+ }
8683
+ /**
8684
+ * @private
8685
+ * Serialize a `ContentFilter` into an `ISearchOptions` for use with `searchItems`
8686
+ * @param filter
8687
+ * @returns
8688
+ */
8689
+ function serializeContentFilterForPortal(filter) {
8690
+ var searchOptions = convertContentFilterToSearchOptions(filter);
8691
+ if (filter.subFilters) {
8692
+ var subFilterOptions = filter.subFilters.reduce(function (acc, entry) {
8693
+ // Next guard is present b/c this can be used from javascript
8694
+ // but our tests are written in typescript which prevents us
8695
+ // from hitting the else
8696
+ /* istanbul ignore else */
8697
+ if (typeof entry === "object") {
8698
+ acc = mergeSearchOptions(acc, convertContentFilterToSearchOptions(entry), "OR");
8699
+ }
8700
+ return acc;
8701
+ }, { q: "", filter: "" });
8702
+ // merge with searchOptions using AND
8703
+ searchOptions = mergeSearchOptions(searchOptions, subFilterOptions, "AND");
8704
+ }
8705
+ // term is always last, and pre-pended on searchOptions.q
8706
+ if (filter.term) {
8707
+ searchOptions.q = (filter.term + " " + searchOptions.q).trim();
8708
+ }
8709
+ return searchOptions;
8710
+ }
8711
+ /**
8712
+ * @private
8713
+ * Convert a ContentFilter to a SearchOptions
8714
+ *
8715
+ * @param filter
8716
+ * @returns
8717
+ */
8718
+ function convertContentFilterToSearchOptions(filter) {
8719
+ var result = {
8720
+ q: "",
8721
+ filter: "",
8722
+ };
8723
+ var dateProps = ["created", "modified"];
8724
+ var specialProps = __spreadArrays(["filterType", "subFilters", "term"], dateProps);
8725
+ Object.entries(filter).forEach(function (_a) {
8726
+ var key = _a[0], value = _a[1];
8727
+ // MatchOptions may go into either q or filter
8728
+ if (!specialProps.includes(key)) {
8729
+ result = mergeSearchOptions(result, serializeMatchOptions(key, value), "AND");
8730
+ }
8731
+ // Dates only go into q
8732
+ if (dateProps.includes(key)) {
8733
+ result = mergeSearchOptions(result, serializeDateRange(key, value), "AND");
8734
+ }
8735
+ });
8736
+ return result;
8737
+ }
8738
+
8739
+ /**
8740
+ * Search for content via the Portal or Hub API
8741
+ * @param filter
8742
+ * @param options
8743
+ */
8744
+ function _searchContent(filter, options) {
8745
+ return __awaiter(this, void 0, void 0, function () {
8746
+ var expanded, apis, searchPromises, results;
8747
+ return __generator(this, function (_a) {
8748
+ switch (_a.label) {
8749
+ case 0:
8750
+ expanded = expandContentFilter(filter);
8751
+ // APIs
8752
+ if (!options.apis) {
8753
+ // default to AGO PROD
8754
+ options.apis = ["arcgis"];
8755
+ }
8756
+ apis = expandApis(options.apis);
8757
+ searchPromises = apis.map(function (api) {
8758
+ var _a;
8759
+ // Portal Search
8760
+ if (api.type === "arcgis") {
8761
+ // serialize for portal
8762
+ var so = serializeContentFilterForPortal(expanded);
8763
+ // pass auth forward
8764
+ if (options.authentication) {
8765
+ so.authentication = options.authentication;
8766
+ }
8767
+ // Aggregations
8768
+ if ((_a = options.aggregations) === null || _a === void 0 ? void 0 : _a.length) {
8769
+ so.countFields = options.aggregations.join(",");
8770
+ so.countSize = 200;
8771
+ }
8772
+ if (options.num) {
8773
+ so.num = options.num;
8774
+ }
8775
+ return searchPortal(so);
8776
+ }
8777
+ else {
8778
+ // Hub API Search
8779
+ // TODO: Implement hub api content search
8780
+ return Promise.resolve({
8781
+ content: [],
8782
+ facets: [],
8783
+ });
8784
+ }
8785
+ });
8786
+ return [4 /*yield*/, Promise.all(searchPromises)];
8787
+ case 1:
8788
+ results = _a.sent();
8789
+ // merge and return
8790
+ return [2 /*return*/, mergeSearchResults(results)];
8791
+ }
8792
+ });
8793
+ });
8794
+ }
8795
+ function searchPortal(searchOptions) {
8796
+ return searchItems(searchOptions).then(function (resp) {
8797
+ var content = resp.results.map(itemToContent);
8798
+ // convert aggregations into facets
8799
+ var facets = convertPortalResponseToFacets(resp);
8800
+ return { content: content, facets: facets };
8801
+ });
8802
+ }
8803
+
7982
8804
  /**
7983
8805
  * Parse a response object, and throw if it contains an error.
7984
8806
  * Just a wrapper to hide some platform idiosyncracies
@@ -9188,6 +10010,7 @@
9188
10010
  exports.PORTAL_EXPORT_TYPES = PORTAL_EXPORT_TYPES;
9189
10011
  exports.REQUIRED_PRIVS = REQUIRED_PRIVS;
9190
10012
  exports.RemoteServerError = RemoteServerError;
10013
+ exports.SEARCH_APIS = SEARCH_APIS;
9191
10014
  exports.SITE_SCHEMA_VERSION = SITE_SCHEMA_VERSION;
9192
10015
  exports.STANDARD_LICENSES = STANDARD_LICENSES;
9193
10016
  exports.WGS84_WKID = WGS84_WKID;
@@ -9218,6 +10041,7 @@
9218
10041
  exports._processInvite = _processInvite;
9219
10042
  exports._processPrimaryEmail = _processPrimaryEmail;
9220
10043
  exports._processSecondaryEmail = _processSecondaryEmail;
10044
+ exports._searchContent = _searchContent;
9221
10045
  exports._unprotectAndRemoveGroup = _unprotectAndRemoveGroup;
9222
10046
  exports._unprotectAndRemoveItem = _unprotectAndRemoveItem;
9223
10047
  exports.addContextToSlug = addContextToSlug;
@@ -9245,6 +10069,9 @@
9245
10069
  exports.cloneObject = cloneObject$1;
9246
10070
  exports.completeOAuth2 = completeOAuth2;
9247
10071
  exports.compose = compose;
10072
+ exports.convertContentDefinitionToFilter = convertContentDefinitionToFilter;
10073
+ exports.convertContentFilterToSearchOptions = convertContentFilterToSearchOptions;
10074
+ exports.convertPortalResponseToFacets = convertPortalResponseToFacets;
9248
10075
  exports.convertSolutionTemplateResourcesToAssets = convertSolutionTemplateResourcesToAssets;
9249
10076
  exports.convertToWellKnownLocale = convertToWellKnownLocale;
9250
10077
  exports.createExtent = createExtent;
@@ -9262,6 +10089,9 @@
9262
10089
  exports.ensureProp = ensureProp;
9263
10090
  exports.ensureUniqueDomainName = ensureUniqueDomainName;
9264
10091
  exports.ensureUniqueString = ensureUniqueString;
10092
+ exports.expandApis = expandApis;
10093
+ exports.expandContentFilter = expandContentFilter;
10094
+ exports.expandTypeField = expandTypeField;
9265
10095
  exports.extend = extend;
9266
10096
  exports.extentToBBox = extentToBBox;
9267
10097
  exports.failSafe = failSafe;
@@ -9349,7 +10179,12 @@
9349
10179
  exports.mapBy = mapBy;
9350
10180
  exports.maybeAdd = maybeAdd;
9351
10181
  exports.maybePush = maybePush;
10182
+ exports.mergeContentFilter = mergeContentFilter;
10183
+ exports.mergeDateRange = mergeDateRange;
10184
+ exports.mergeMatchOptions = mergeMatchOptions;
9352
10185
  exports.mergeObjects = mergeObjects;
10186
+ exports.mergeSearchOptions = mergeSearchOptions;
10187
+ exports.mergeSearchResults = mergeSearchResults;
9353
10188
  exports.normalizeItemType = normalizeItemType;
9354
10189
  exports.normalizeSolutionTemplateItem = normalizeSolutionTemplateItem;
9355
10190
  exports.objectToArray = objectToArray;
@@ -9358,13 +10193,18 @@
9358
10193
  exports.parseItemCategories = parseItemCategories;
9359
10194
  exports.processRevertableTasks = processRevertableTasks;
9360
10195
  exports.propifyString = propifyString;
10196
+ exports.relativeDateToDateRange = relativeDateToDateRange;
9361
10197
  exports.removeContextFromSlug = removeContextFromSlug;
9362
10198
  exports.removeDomain = removeDomain;
9363
10199
  exports.removeEmptyProps = removeEmptyProps;
9364
10200
  exports.replaceItemId = replaceItemId;
9365
10201
  exports.runRevertableTask = runRevertableTask;
10202
+ exports.serializeContentFilterForPortal = serializeContentFilterForPortal;
10203
+ exports.serializeDateRange = serializeDateRange;
10204
+ exports.serializeMatchOptions = serializeMatchOptions;
9366
10205
  exports.serializeModel = serializeModel;
9367
10206
  exports.serializeSpatialReference = serializeSpatialReference;
10207
+ exports.serializeStringOrArray = serializeStringOrArray;
9368
10208
  exports.setContentHubId = setContentHubId;
9369
10209
  exports.setContentSiteUrls = setContentSiteUrls;
9370
10210
  exports.setContentType = setContentType;
@@ -9380,6 +10220,7 @@
9380
10220
  exports.updateDomain = updateDomain;
9381
10221
  exports.upgradeSiteSchema = upgradeSiteSchema;
9382
10222
  exports.uploadResourcesFromUrl = uploadResourcesFromUrl;
10223
+ exports.valueToMatchOptions = valueToMatchOptions;
9383
10224
  exports.without = without;
9384
10225
  exports.withoutByProp = withoutByProp;
9385
10226