@carto/api-client 0.4.6 → 0.4.7-alpha.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 (124) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/build/api/carto-api-error.d.ts +1 -1
  3. package/build/api/query.d.ts +1 -1
  4. package/build/api/request-with-parameters.d.ts +2 -2
  5. package/build/api-client.cjs +2365 -279
  6. package/build/api-client.cjs.map +1 -1
  7. package/build/api-client.modern.js +2274 -298
  8. package/build/api-client.modern.js.map +1 -1
  9. package/build/client.d.ts +2 -2
  10. package/build/constants-internal.d.ts +5 -5
  11. package/build/constants.d.ts +25 -3
  12. package/build/deck/get-data-filter-extension-props.d.ts +28 -0
  13. package/build/deck/index.d.ts +1 -0
  14. package/build/filters/Filter.d.ts +25 -0
  15. package/build/filters/FilterTypes.d.ts +3 -0
  16. package/build/filters/geosjonFeatures.d.ts +8 -0
  17. package/build/filters/index.d.ts +6 -0
  18. package/build/filters/tileFeatures.d.ts +20 -0
  19. package/build/filters/tileFeaturesGeometries.d.ts +13 -0
  20. package/build/filters/tileFeaturesSpatialIndex.d.ts +10 -0
  21. package/build/filters.d.ts +2 -2
  22. package/build/geo.d.ts +1 -1
  23. package/build/index.d.ts +5 -0
  24. package/build/models/common.d.ts +5 -4
  25. package/build/models/index.d.ts +1 -1
  26. package/build/models/model.d.ts +2 -2
  27. package/build/operations/aggregation.d.ts +8 -0
  28. package/build/operations/applySorting.d.ts +20 -0
  29. package/build/operations/groupBy.d.ts +15 -0
  30. package/build/operations/groupByDate.d.ts +11 -0
  31. package/build/operations/histogram.d.ts +13 -0
  32. package/build/operations/index.d.ts +6 -0
  33. package/build/operations/scatterPlot.d.ts +14 -0
  34. package/build/sources/base-source.d.ts +2 -2
  35. package/build/sources/boundary-query-source.d.ts +1 -1
  36. package/build/sources/boundary-table-source.d.ts +1 -1
  37. package/build/sources/h3-query-source.d.ts +2 -2
  38. package/build/sources/h3-table-source.d.ts +2 -2
  39. package/build/sources/h3-tileset-source.d.ts +1 -1
  40. package/build/sources/index.d.ts +26 -26
  41. package/build/sources/quadbin-query-source.d.ts +2 -2
  42. package/build/sources/quadbin-table-source.d.ts +2 -2
  43. package/build/sources/quadbin-tileset-source.d.ts +1 -1
  44. package/build/sources/raster-source.d.ts +1 -1
  45. package/build/sources/types.d.ts +3 -3
  46. package/build/sources/vector-query-source.d.ts +1 -1
  47. package/build/sources/vector-table-source.d.ts +1 -1
  48. package/build/sources/vector-tileset-source.d.ts +1 -1
  49. package/build/spatial-index.d.ts +3 -3
  50. package/build/types-internal.d.ts +9 -5
  51. package/build/types.d.ts +74 -14
  52. package/build/utils/dateUtils.d.ts +10 -0
  53. package/build/utils/getTileFormat.d.ts +3 -0
  54. package/build/utils/makeIntervalComplete.d.ts +2 -0
  55. package/build/utils/transformTileCoordsToWGS84.d.ts +8 -0
  56. package/build/utils/transformToTileCoords.d.ts +9 -0
  57. package/build/utils.d.ts +3 -3
  58. package/build/widget-sources/index.d.ts +3 -1
  59. package/build/widget-sources/types.d.ts +38 -25
  60. package/build/widget-sources/widget-query-source.d.ts +4 -3
  61. package/build/widget-sources/widget-remote-source.d.ts +18 -0
  62. package/build/widget-sources/{widget-base-source.d.ts → widget-source.d.ts} +16 -41
  63. package/build/widget-sources/widget-table-source.d.ts +4 -3
  64. package/build/widget-sources/widget-tileset-source.d.ts +75 -0
  65. package/package.json +46 -29
  66. package/src/api/carto-api-error.ts +1 -1
  67. package/src/api/query.ts +5 -5
  68. package/src/api/request-with-parameters.ts +6 -6
  69. package/src/client.ts +3 -3
  70. package/src/constants-internal.ts +5 -5
  71. package/src/constants.ts +28 -3
  72. package/src/deck/get-data-filter-extension-props.ts +164 -0
  73. package/src/deck/index.ts +1 -0
  74. package/src/filters/Filter.ts +179 -0
  75. package/src/filters/FilterTypes.ts +109 -0
  76. package/src/filters/geosjonFeatures.ts +32 -0
  77. package/src/filters/index.ts +6 -0
  78. package/src/filters/tileFeatures.ts +50 -0
  79. package/src/filters/tileFeaturesGeometries.ts +444 -0
  80. package/src/filters/tileFeaturesSpatialIndex.ts +119 -0
  81. package/src/filters.ts +4 -4
  82. package/src/geo.ts +12 -14
  83. package/src/index.ts +7 -0
  84. package/src/models/common.ts +11 -9
  85. package/src/models/index.ts +1 -1
  86. package/src/models/model.ts +3 -4
  87. package/src/operations/aggregation.ts +154 -0
  88. package/src/operations/applySorting.ts +109 -0
  89. package/src/operations/groupBy.ts +59 -0
  90. package/src/operations/groupByDate.ts +98 -0
  91. package/src/operations/histogram.ts +66 -0
  92. package/src/operations/index.ts +6 -0
  93. package/src/operations/scatterPlot.ts +50 -0
  94. package/src/sources/base-source.ts +8 -8
  95. package/src/sources/boundary-query-source.ts +2 -2
  96. package/src/sources/boundary-table-source.ts +2 -2
  97. package/src/sources/h3-query-source.ts +7 -5
  98. package/src/sources/h3-table-source.ts +7 -5
  99. package/src/sources/h3-tileset-source.ts +2 -2
  100. package/src/sources/index.ts +26 -26
  101. package/src/sources/quadbin-query-source.ts +7 -5
  102. package/src/sources/quadbin-table-source.ts +7 -5
  103. package/src/sources/quadbin-tileset-source.ts +2 -2
  104. package/src/sources/raster-source.ts +3 -2
  105. package/src/sources/types.ts +3 -3
  106. package/src/sources/vector-query-source.ts +7 -5
  107. package/src/sources/vector-table-source.ts +7 -5
  108. package/src/sources/vector-tileset-source.ts +2 -2
  109. package/src/spatial-index.ts +4 -5
  110. package/src/types-internal.ts +11 -5
  111. package/src/types.ts +73 -15
  112. package/src/utils/dateUtils.ts +28 -0
  113. package/src/utils/getTileFormat.ts +9 -0
  114. package/src/utils/makeIntervalComplete.ts +17 -0
  115. package/src/utils/transformTileCoordsToWGS84.ts +77 -0
  116. package/src/utils/transformToTileCoords.ts +85 -0
  117. package/src/utils.ts +3 -3
  118. package/src/widget-sources/index.ts +3 -1
  119. package/src/widget-sources/types.ts +39 -25
  120. package/src/widget-sources/widget-query-source.ts +12 -5
  121. package/src/widget-sources/{widget-base-source.ts → widget-remote-source.ts} +51 -171
  122. package/src/widget-sources/widget-source.ts +173 -0
  123. package/src/widget-sources/widget-table-source.ts +12 -5
  124. package/src/widget-sources/widget-tileset-source.ts +456 -0
@@ -1,19 +1,24 @@
1
- import bboxClip from '@turf/bbox-clip';
1
+ import intersects from '@turf/boolean-intersects';
2
2
  import bboxPolygon from '@turf/bbox-polygon';
3
+ import booleanWithin from '@turf/boolean-within';
4
+ import intersect from '@turf/intersect';
5
+ import { featureCollection, feature, polygon, multiPolygon } from '@turf/helpers';
6
+ import bboxClip from '@turf/bbox-clip';
7
+ import { getResolution as getResolution$2, polygonToCells } from 'h3-js';
3
8
  import union from '@turf/union';
4
9
  import { getType } from '@turf/invariant';
5
- import { featureCollection, feature, polygon, multiPolygon } from '@turf/helpers';
10
+ import { booleanEqual } from '@turf/boolean-equal';
6
11
 
7
12
  /**
8
13
  * @internal
9
- * @internalRemarks Source: @carto/react-core, @carto/constants, @deck.gl/carto
14
+ * @privateRemarks Source: @carto/react-core, @carto/constants, @deck.gl/carto
10
15
  */
11
16
  let client = 'deck-gl-carto';
12
17
  /**
13
18
  * Returns current client ID, used to categorize API requests. For internal use only.
14
19
  *
15
20
  * @internal
16
- * @internalRemarks Source: @carto/react-core
21
+ * @privateRemarks Source: @carto/react-core
17
22
  */
18
23
  function getClient() {
19
24
  return client;
@@ -22,7 +27,7 @@ function getClient() {
22
27
  * Sets current client ID, used to categorize API requests. For internal use only.
23
28
  *
24
29
  * @internal
25
- * @internalRemarks Source: @carto/react-core
30
+ * @privateRemarks Source: @carto/react-core
26
31
  */
27
32
  function setClient(c) {
28
33
  client = c;
@@ -33,34 +38,1389 @@ function setClient(c) {
33
38
  *
34
39
  * Example:
35
40
  *
36
- * ```javascript
37
- * import { FilterType } from '@carto/api-client';
38
- * const filters = {
39
- * column_name: { [FilterType.IN]: { values: ['a', 'b', 'c'] } }
40
- * };
41
+ * ```javascript
42
+ * import { FilterType } from '@carto/api-client';
43
+ * const filters = {
44
+ * column_name: { [FilterType.IN]: { values: ['a', 'b', 'c'] } }
45
+ * };
46
+ * ```
47
+ *
48
+ * @privateRemarks Source: @carto/react-api, @deck.gl/carto
49
+ */
50
+ var FilterType;
51
+ (function (FilterType) {
52
+ FilterType["IN"] = "in";
53
+ /** [a, b] both are included. */
54
+ FilterType["BETWEEN"] = "between";
55
+ /** [a, b) a is included, b is not. */
56
+ FilterType["CLOSED_OPEN"] = "closed_open";
57
+ FilterType["TIME"] = "time";
58
+ FilterType["STRING_SEARCH"] = "stringSearch";
59
+ })(FilterType || (FilterType = {}));
60
+ /** @privateRemarks Source: @carto/constants */
61
+ var ApiVersion;
62
+ (function (ApiVersion) {
63
+ ApiVersion["V1"] = "v1";
64
+ ApiVersion["V2"] = "v2";
65
+ ApiVersion["V3"] = "v3";
66
+ })(ApiVersion || (ApiVersion = {}));
67
+ /** @privateRemarks Source: @carto/constants, @deck.gl/carto */
68
+ const DEFAULT_API_BASE_URL = 'https://gcp-us-east1.api.carto.com';
69
+ /** @privateRemarks Source: @carto/react-core */
70
+ var TileFormat;
71
+ (function (TileFormat) {
72
+ TileFormat["MVT"] = "mvt";
73
+ TileFormat["JSON"] = "json";
74
+ TileFormat["GEOJSON"] = "geojson";
75
+ TileFormat["BINARY"] = "binary";
76
+ })(TileFormat || (TileFormat = {}));
77
+ /** @privateRemarks Source: @carto/react-core */
78
+ var SpatialIndex;
79
+ (function (SpatialIndex) {
80
+ SpatialIndex["H3"] = "h3";
81
+ SpatialIndex["S2"] = "s2";
82
+ SpatialIndex["QUADBIN"] = "quadbin";
83
+ })(SpatialIndex || (SpatialIndex = {}));
84
+ /** @privateRemarks Source: @carto/react-core */
85
+ var Provider;
86
+ (function (Provider) {
87
+ Provider["BIGQUERY"] = "bigquery";
88
+ Provider["REDSHIFT"] = "redshift";
89
+ Provider["POSTGRES"] = "postgres";
90
+ Provider["SNOWFLAKE"] = "snowflake";
91
+ Provider["DATABRICKS"] = "databricks";
92
+ Provider["DATABRICKS_REST"] = "databricksRest";
93
+ })(Provider || (Provider = {}));
94
+
95
+ function _extends() {
96
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
97
+ for (var e = 1; e < arguments.length; e++) {
98
+ var t = arguments[e];
99
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
100
+ }
101
+ return n;
102
+ }, _extends.apply(null, arguments);
103
+ }
104
+ function _objectWithoutPropertiesLoose(r, e) {
105
+ if (null == r) return {};
106
+ var t = {};
107
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
108
+ if (e.includes(n)) continue;
109
+ t[n] = r[n];
110
+ }
111
+ return t;
112
+ }
113
+
114
+ function makeIntervalComplete(intervals) {
115
+ return intervals.map(val => {
116
+ if (val[0] === undefined || val[0] === null) {
117
+ return [Number.MIN_SAFE_INTEGER, val[1]];
118
+ }
119
+ if (val[1] === undefined || val[1] === null) {
120
+ return [val[0], Number.MAX_SAFE_INTEGER];
121
+ }
122
+ return val;
123
+ });
124
+ }
125
+
126
+ const filterFunctions = {
127
+ [FilterType.IN]: filterIn,
128
+ [FilterType.BETWEEN]: filterBetween,
129
+ [FilterType.TIME]: filterTime,
130
+ [FilterType.CLOSED_OPEN]: filterClosedOpen,
131
+ [FilterType.STRING_SEARCH]: filterStringSearch
132
+ };
133
+ function filterIn(filterValues, featureValue) {
134
+ return filterValues.includes(featureValue);
135
+ }
136
+ // FilterTypes.BETWEEN
137
+ function filterBetween(filterValues, featureValue) {
138
+ const checkRange = range => {
139
+ const [lowerBound, upperBound] = range;
140
+ return featureValue >= lowerBound && featureValue <= upperBound;
141
+ };
142
+ return makeIntervalComplete(filterValues).some(checkRange);
143
+ }
144
+ function filterTime(filterValues, featureValue) {
145
+ const featureValueAsTimestamp = new Date(featureValue).getTime();
146
+ if (isFinite(featureValueAsTimestamp)) {
147
+ return filterBetween(filterValues, featureValueAsTimestamp);
148
+ } else {
149
+ throw new Error(`Column used to filter by time isn't well formatted.`);
150
+ }
151
+ }
152
+ // FilterTypes.CLOSED_OPEN
153
+ function filterClosedOpen(filterValues, featureValue) {
154
+ const checkRange = range => {
155
+ const [lowerBound, upperBound] = range;
156
+ return featureValue >= lowerBound && featureValue < upperBound;
157
+ };
158
+ return makeIntervalComplete(filterValues).some(checkRange);
159
+ }
160
+ // FilterTypes.STRING_SEARCH
161
+ function filterStringSearch(filterValues, featureValue, params = {}) {
162
+ const normalizedFeatureValue = normalize(featureValue, params);
163
+ const stringRegExp = params.useRegExp ? filterValues : filterValues.map(filterValue => {
164
+ let stringRegExp = escapeRegExp(normalize(filterValue, params));
165
+ if (params.mustStart) stringRegExp = `^${stringRegExp}`;
166
+ if (params.mustEnd) stringRegExp = `${stringRegExp}$`;
167
+ return stringRegExp;
168
+ });
169
+ const regex = new RegExp(stringRegExp.join('|'), params.caseSensitive ? 'g' : 'gi');
170
+ return !!normalizedFeatureValue.match(regex);
171
+ }
172
+ // Aux
173
+ const specialCharRegExp = /[.*+?^${}()|[\]\\]/g;
174
+ const normalizeRegExp = /(?:[\^`\xA8\xAF\xB4\xB7\xB8\u02B0-\u034E\u0350-\u0357\u035D-\u0362\u0374\u0375\u037A\u0384\u0385\u0483-\u0487\u0559\u0591-\u05A1\u05A3-\u05BD\u05BF\u05C1\u05C2\u05C4\u064B-\u0652\u0657\u0658\u06DF\u06E0\u06E5\u06E6\u06EA-\u06EC\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F5\u0818\u0819\u0898-\u089F\u08C9-\u08D2\u08E3-\u08FE\u093C\u094D\u0951-\u0954\u0971\u09BC\u09CD\u0A3C\u0A4D\u0ABC\u0ACD\u0AFD-\u0AFF\u0B3C\u0B4D\u0B55\u0BCD\u0C3C\u0C4D\u0CBC\u0CCD\u0D3B\u0D3C\u0D4D\u0DCA\u0E3A\u0E47-\u0E4C\u0E4E\u0EBA\u0EC8-\u0ECC\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F82-\u0F84\u0F86\u0F87\u0FC6\u1037\u1039\u103A\u1063\u1064\u1069-\u106D\u1087-\u108D\u108F\u109A\u109B\u135D-\u135F\u1714\u1715\u1734\u17C9-\u17D3\u17DD\u1939-\u193B\u1A60\u1A75-\u1A7C\u1A7F\u1AB0-\u1ABE\u1AC1-\u1ACB\u1B34\u1B44\u1B6B-\u1B73\u1BAA\u1BAB\u1BE6\u1BF2\u1BF3\u1C36\u1C37\u1C78-\u1C7D\u1CD0-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1D2C-\u1D6A\u1DC4-\u1DCF\u1DF5-\u1DFF\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2CEF-\u2CF1\u2E2F\u302A-\u302F\u3099-\u309C\u30FC\uA66F\uA67C\uA67D\uA67F\uA69C\uA69D\uA6F0\uA6F1\uA700-\uA721\uA788-\uA78A\uA7F8\uA7F9\uA806\uA82C\uA8C4\uA8E0-\uA8F1\uA92B-\uA92E\uA953\uA9B3\uA9C0\uA9E5\uAA7B-\uAA7D\uAABF-\uAAC2\uAAF6\uAB5B-\uAB5F\uAB69-\uAB6B\uABEC\uABED\uFB1E\uFE20-\uFE2F\uFF3E\uFF40\uFF70\uFF9E\uFF9F\uFFE3]|\uD800\uDEE0|\uD801[\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD803[\uDD22-\uDD27\uDD4E\uDD69-\uDD6D\uDEFD-\uDEFF\uDF46-\uDF50\uDF82-\uDF85]|\uD804[\uDC46\uDC70\uDCB9\uDCBA\uDD33\uDD34\uDD73\uDDC0\uDDCA-\uDDCC\uDE35\uDE36\uDEE9\uDEEA\uDF3B\uDF3C\uDF4D\uDF66-\uDF6C\uDF70-\uDF74\uDFCE-\uDFD0\uDFD2\uDFD3\uDFE1\uDFE2]|\uD805[\uDC42\uDC46\uDCC2\uDCC3\uDDBF\uDDC0\uDE3F\uDEB6\uDEB7\uDF2B]|\uD806[\uDC39\uDC3A\uDD3D\uDD3E\uDD43\uDDE0\uDE34\uDE47\uDE99]|\uD807[\uDC3F\uDD42\uDD44\uDD45\uDD97\uDF41\uDF42\uDF5A]|\uD80D[\uDC47-\uDC55]|\uD818\uDD2F|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDD6B\uDD6C\uDF8F-\uDF9F\uDFF0\uDFF1]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD833[\uDF00-\uDF2D\uDF30-\uDF46]|\uD834[\uDD67-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD]|\uD838[\uDC30-\uDC6D\uDD30-\uDD36\uDEAE\uDEEC-\uDEEF]|\uD839[\uDDEE\uDDEF]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD46\uDD48-\uDD4A])/g;
175
+ function escapeRegExp(value) {
176
+ return value.replace(specialCharRegExp, '\\$&');
177
+ }
178
+ function normalize(data, params) {
179
+ let normalizedData = String(data);
180
+ if (!params.keepSpecialCharacters) normalizedData = normalizedData.normalize('NFD').replace(normalizeRegExp, '');
181
+ return normalizedData;
182
+ }
183
+
184
+ const LOGICAL_OPERATOR_METHODS = {
185
+ and: 'every',
186
+ or: 'some'
187
+ };
188
+ function passesFilter(columns, filters, feature, filtersLogicalOperator) {
189
+ const method = LOGICAL_OPERATOR_METHODS[filtersLogicalOperator];
190
+ return columns[method](column => {
191
+ const columnFilters = filters[column];
192
+ const columnFilterTypes = Object.keys(columnFilters);
193
+ if (!feature || feature[column] === null || feature[column] === undefined) {
194
+ return false;
195
+ }
196
+ return columnFilterTypes.every(filter => {
197
+ const filterFunction = filterFunctions[filter];
198
+ if (!filterFunction) {
199
+ throw new Error(`"${filter}" filter is not implemented.`);
200
+ }
201
+ return filterFunction(columnFilters[filter].values, feature[column], columnFilters[filter].params);
202
+ });
203
+ });
204
+ }
205
+ /**
206
+ * @internal
207
+ * @privateRemarks Exported for use in @deck.gl/carto's getDataFilterExtensionProps.
208
+ */
209
+ function _buildFeatureFilter({
210
+ filters = {},
211
+ type = 'boolean',
212
+ filtersLogicalOperator = 'and'
213
+ }) {
214
+ const columns = Object.keys(filters);
215
+ if (!columns.length) {
216
+ return () => type === 'number' ? 1 : true;
217
+ }
218
+ return feature => {
219
+ const f = feature.properties || feature;
220
+ const featurePassesFilter = passesFilter(columns, filters, f, filtersLogicalOperator);
221
+ return type === 'number' ? Number(featurePassesFilter) : featurePassesFilter;
222
+ };
223
+ }
224
+ /**
225
+ * Apply certain filters to a collection of features.
226
+ * @internal
227
+ */
228
+ function applyFilters(features, filters, filtersLogicalOperator) {
229
+ return Object.keys(filters).length ? features.filter(_buildFeatureFilter({
230
+ filters,
231
+ filtersLogicalOperator
232
+ })) : features;
233
+ }
234
+ /**
235
+ * Binary.
236
+ * @internal
237
+ */
238
+ function buildBinaryFeatureFilter({
239
+ filters = {}
240
+ }) {
241
+ const columns = Object.keys(filters);
242
+ if (!columns.length) {
243
+ return () => 1;
244
+ }
245
+ return (featureIdIdx, binaryData) => passesFilterUsingBinary(columns, filters, featureIdIdx, binaryData);
246
+ }
247
+ function getValueFromNumericProps(featureIdIdx, binaryData, {
248
+ column
249
+ }) {
250
+ var _binaryData$numericPr;
251
+ return (_binaryData$numericPr = binaryData.numericProps) == null || (_binaryData$numericPr = _binaryData$numericPr[column]) == null ? void 0 : _binaryData$numericPr.value[featureIdIdx];
252
+ }
253
+ function getValueFromProperties(featureIdIdx, binaryData, {
254
+ column
255
+ }) {
256
+ var _binaryData$propertie;
257
+ const propertyIdx = binaryData.featureIds.value[featureIdIdx];
258
+ return (_binaryData$propertie = binaryData.properties[propertyIdx]) == null ? void 0 : _binaryData$propertie[column];
259
+ }
260
+ const GET_VALUE_BY_BINARY_PROP = {
261
+ properties: getValueFromProperties,
262
+ numericProps: getValueFromNumericProps
263
+ };
264
+ function getBinaryPropertyByFilterValues(filterValues) {
265
+ return typeof filterValues.flat()[0] === 'string' ? 'properties' : 'numericProps';
266
+ }
267
+ function getFeatureValue(featureIdIdx, binaryData, filter) {
268
+ const {
269
+ column,
270
+ values
271
+ } = filter;
272
+ const binaryProp = getBinaryPropertyByFilterValues(values);
273
+ const getFeatureValueFn = GET_VALUE_BY_BINARY_PROP[binaryProp];
274
+ return getFeatureValueFn(featureIdIdx, binaryData, {
275
+ column
276
+ });
277
+ }
278
+ function passesFilterUsingBinary(columns, filters, featureIdIdx, binaryData) {
279
+ return columns.every(column => {
280
+ const columnFilters = filters[column];
281
+ return Object.entries(columnFilters).every(([type, {
282
+ values
283
+ }]) => {
284
+ const filterFn = filterFunctions[type];
285
+ if (!filterFn) {
286
+ throw new Error(`"${type}" filter is not implemented.`);
287
+ }
288
+ if (!values) return 0;
289
+ const featureValue = getFeatureValue(featureIdIdx, binaryData, {
290
+ type: type,
291
+ column,
292
+ values
293
+ });
294
+ if (featureValue === undefined || featureValue === null) return 0;
295
+ return filterFn(values, featureValue);
296
+ });
297
+ });
298
+ }
299
+
300
+ function geojsonFeatures({
301
+ geojson,
302
+ spatialFilter,
303
+ uniqueIdProperty
304
+ }) {
305
+ let uniqueIdx = 0;
306
+ const map = new Map();
307
+ if (!spatialFilter) {
308
+ return [];
309
+ }
310
+ for (const feature of geojson.features) {
311
+ const uniqueId = uniqueIdProperty ? feature.properties[uniqueIdProperty] : ++uniqueIdx;
312
+ if (!map.has(uniqueId) && intersects(spatialFilter, feature)) {
313
+ map.set(uniqueId, feature.properties);
314
+ }
315
+ }
316
+ return Array.from(map.values());
317
+ }
318
+
319
+ // math.gl
320
+ // SPDX-License-Identifier: MIT
321
+ // Copyright (c) vis.gl contributors
322
+ const DEFAULT_CONFIG = {
323
+ EPSILON: 1e-12,
324
+ debug: false,
325
+ precision: 4,
326
+ printTypes: false,
327
+ printDegrees: false,
328
+ printRowMajor: true,
329
+ _cartographicRadians: false
330
+ };
331
+ // Configuration is truly global as of v3.6 to ensure single config even if multiple copies of math.gl
332
+ // Multiple copies of config can be quite tricky to debug...
333
+ globalThis.mathgl = globalThis.mathgl || {
334
+ config: {
335
+ ...DEFAULT_CONFIG
336
+ }
337
+ };
338
+ /**
339
+ * Check if value is an "array"
340
+ * Returns `true` if value is either an array or a typed array
341
+ * Note: returns `false` for `ArrayBuffer` and `DataView` instances
342
+ * @note isTypedArray and isNumericArray are often more useful in TypeScript
343
+ */
344
+ function isArray(value) {
345
+ return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
346
+ }
347
+ function lerp(a, b, t) {
348
+ if (isArray(a)) {
349
+ return a.map((ai, i) => lerp(ai, b[i], t));
350
+ }
351
+ return t * b + (1 - t) * a;
352
+ }
353
+
354
+ // Replacement for the external assert method to reduce bundle size
355
+ // Note: We don't use the second "message" argument in calling code,
356
+ // so no need to support it here
357
+ function assert$1(condition, message) {
358
+ if (!condition) {
359
+ throw new Error(message || '@math.gl/web-mercator: assertion failed.');
360
+ }
361
+ }
362
+
363
+ // TODO - THE UTILITIES IN THIS FILE SHOULD BE IMPORTED FROM WEB-MERCATOR-VIEWPORT MODULE
364
+ // CONSTANTS
365
+ const PI = Math.PI;
366
+ const PI_4 = PI / 4;
367
+ const DEGREES_TO_RADIANS = PI / 180;
368
+ const RADIANS_TO_DEGREES = 180 / PI;
369
+ const TILE_SIZE = 512;
370
+ /**
371
+ * Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
372
+ * Performs the nonlinear part of the web mercator projection.
373
+ * Remaining projection is done with 4x4 matrices which also handles
374
+ * perspective.
375
+ *
376
+ * @param lngLat - [lng, lat] coordinates
377
+ * Specifies a point on the sphere to project onto the map.
378
+ * @return [x,y] coordinates.
379
+ */
380
+ function lngLatToWorld(lngLat) {
381
+ const [lng, lat] = lngLat;
382
+ assert$1(Number.isFinite(lng));
383
+ assert$1(Number.isFinite(lat) && lat >= -90 && lat <= 90, 'invalid latitude');
384
+ const lambda2 = lng * DEGREES_TO_RADIANS;
385
+ const phi2 = lat * DEGREES_TO_RADIANS;
386
+ const x = TILE_SIZE * (lambda2 + PI) / (2 * PI);
387
+ const y = TILE_SIZE * (PI + Math.log(Math.tan(PI_4 + phi2 * 0.5))) / (2 * PI);
388
+ return [x, y];
389
+ }
390
+ /**
391
+ * Unproject world point [x,y] on map onto {lat, lon} on sphere
392
+ *
393
+ * @param xy - array with [x,y] members
394
+ * representing point on projected map plane
395
+ * @return - array with [x,y] of point on sphere.
396
+ * Has toArray method if you need a GeoJSON Array.
397
+ * Per cartographic tradition, lat and lon are specified as degrees.
398
+ */
399
+ function worldToLngLat(xy) {
400
+ const [x, y] = xy;
401
+ const lambda2 = x / TILE_SIZE * (2 * PI) - PI;
402
+ const phi2 = 2 * (Math.atan(Math.exp(y / TILE_SIZE * (2 * PI) - PI)) - PI_4);
403
+ return [lambda2 * RADIANS_TO_DEGREES, phi2 * RADIANS_TO_DEGREES];
404
+ }
405
+
406
+ const TRANSFORM_FN$1 = {
407
+ Point: transformPoint$1,
408
+ MultiPoint: transformMultiPoint$1,
409
+ LineString: transformLineString$1,
410
+ MultiLineString: transformMultiLineString$1,
411
+ Polygon: transformPolygon$1,
412
+ MultiPolygon: transformMultiPolygon$1
413
+ };
414
+ /**
415
+ * Transform WGS84 coordinates to tile coords.
416
+ * It's the inverse of deck.gl coordinate-transform (https://github.com/visgl/deck.gl/blob/master/modules/geo-layers/src/mvt-layer/coordinate-transform.js)
417
+ *
418
+ * @param geometry - any valid geojson geometry
419
+ * @param bbox - geojson bbox
420
+ */
421
+ function transformToTileCoords(geometry, bbox) {
422
+ const [west, south, east, north] = bbox;
423
+ const nw = projectFlat([west, north]);
424
+ const se = projectFlat([east, south]);
425
+ const projectedBbox = [nw, se];
426
+ if (geometry.type === 'GeometryCollection') {
427
+ throw new Error('Unsupported geometry type GeometryCollection');
428
+ }
429
+ const transformFn = TRANSFORM_FN$1[geometry.type];
430
+ const coordinates = transformFn(geometry.coordinates, projectedBbox);
431
+ return _extends({}, geometry, {
432
+ coordinates
433
+ });
434
+ }
435
+ function transformPoint$1([pointX, pointY], [nw, se]) {
436
+ const x = inverseLerp(nw[0], se[0], pointX);
437
+ const y = inverseLerp(nw[1], se[1], pointY);
438
+ return [x, y];
439
+ }
440
+ function getPoints$1(geometry, bbox) {
441
+ return geometry.map(g => transformPoint$1(projectFlat(g), bbox));
442
+ }
443
+ function transformMultiPoint$1(multiPoint, bbox) {
444
+ return getPoints$1(multiPoint, bbox);
445
+ }
446
+ function transformLineString$1(line, bbox) {
447
+ return getPoints$1(line, bbox);
448
+ }
449
+ function transformMultiLineString$1(multiLineString, bbox) {
450
+ return multiLineString.map(lineString => transformLineString$1(lineString, bbox));
451
+ }
452
+ function transformPolygon$1(polygon, bbox) {
453
+ return polygon.map(polygonRing => getPoints$1(polygonRing, bbox));
454
+ }
455
+ function transformMultiPolygon$1(multiPolygon, bbox) {
456
+ return multiPolygon.map(polygon => transformPolygon$1(polygon, bbox));
457
+ }
458
+ function projectFlat(xyz) {
459
+ return lngLatToWorld(xyz);
460
+ }
461
+ function inverseLerp(a, b, x) {
462
+ return (x - a) / (b - a);
463
+ }
464
+
465
+ const TRANSFORM_FN = {
466
+ Point: transformPoint,
467
+ MultiPoint: transformMultiPoint,
468
+ LineString: transformLineString,
469
+ MultiLineString: transformMultiLineString,
470
+ Polygon: transformPolygon,
471
+ MultiPolygon: transformMultiPolygon
472
+ };
473
+ /**
474
+ * Transform tile coords to WGS84 coordinates.
475
+ *
476
+ * @param geometry - any valid geojson geometry
477
+ * @param bbox - geojson bbox
478
+ */
479
+ function transformTileCoordsToWGS84(geometry, bbox) {
480
+ const [west, south, east, north] = bbox;
481
+ const nw = lngLatToWorld([west, north]);
482
+ const se = lngLatToWorld([east, south]);
483
+ const projectedBbox = [nw, se];
484
+ if (geometry.type === 'GeometryCollection') {
485
+ throw new Error('Unsupported geometry type GeometryCollection');
486
+ }
487
+ const transformFn = TRANSFORM_FN[geometry.type];
488
+ const coordinates = transformFn(geometry.coordinates, projectedBbox);
489
+ return _extends({}, geometry, {
490
+ coordinates
491
+ });
492
+ }
493
+ function transformPoint([pointX, pointY], [nw, se]) {
494
+ const x = lerp(nw[0], se[0], pointX);
495
+ const y = lerp(nw[1], se[1], pointY);
496
+ return worldToLngLat([x, y]);
497
+ }
498
+ function getPoints(geometry, bbox) {
499
+ return geometry.map(g => transformPoint(g, bbox));
500
+ }
501
+ function transformMultiPoint(multiPoint, bbox) {
502
+ return getPoints(multiPoint, bbox);
503
+ }
504
+ function transformLineString(line, bbox) {
505
+ return getPoints(line, bbox);
506
+ }
507
+ function transformMultiLineString(multiLineString, bbox) {
508
+ return multiLineString.map(lineString => transformLineString(lineString, bbox));
509
+ }
510
+ function transformPolygon(polygon, bbox) {
511
+ return polygon.map(polygonRing => getPoints(polygonRing, bbox));
512
+ }
513
+ function transformMultiPolygon(multiPolygon, bbox) {
514
+ return multiPolygon.map(polygon => transformPolygon(polygon, bbox));
515
+ }
516
+
517
+ const FEATURE_GEOM_PROPERTY = '__geomValue';
518
+ function tileFeaturesGeometries({
519
+ tiles,
520
+ tileFormat,
521
+ spatialFilter,
522
+ uniqueIdProperty,
523
+ options
524
+ }) {
525
+ const map = new Map();
526
+ for (const tile of tiles) {
527
+ // Discard if it's not a visible tile (only check false value, not undefined)
528
+ // or tile has not data
529
+ if (tile.isVisible === false || !tile.data) {
530
+ continue;
531
+ }
532
+ const bbox = [tile.bbox.west, tile.bbox.south, tile.bbox.east, tile.bbox.north];
533
+ const bboxToGeom = bboxPolygon(bbox);
534
+ const tileIsFullyVisible = booleanWithin(bboxToGeom, spatialFilter);
535
+ // Clip the geometry to intersect with the tile
536
+ const spatialFilterFeature = {
537
+ type: 'Feature',
538
+ geometry: spatialFilter,
539
+ properties: {}
540
+ };
541
+ const clippedGeometryToIntersect = intersect(featureCollection([bboxToGeom, spatialFilterFeature]));
542
+ if (!clippedGeometryToIntersect) {
543
+ continue;
544
+ }
545
+ // We assume that MVT tileFormat uses local coordinates so we transform the geometry to intersect to tile coordinates [0..1],
546
+ // while in the case of 'geojson' or binary, the geometries are already in WGS84
547
+ const transformedGeometryToIntersect = tileFormat === TileFormat.MVT ? transformToTileCoords(clippedGeometryToIntersect.geometry, bbox) : clippedGeometryToIntersect.geometry;
548
+ createIndicesForPoints(tile.data.points);
549
+ calculateFeatures({
550
+ map,
551
+ tileIsFullyVisible,
552
+ geometryIntersection: transformedGeometryToIntersect,
553
+ data: tile.data.points,
554
+ type: 'Point',
555
+ bbox,
556
+ tileFormat,
557
+ uniqueIdProperty,
558
+ options
559
+ });
560
+ calculateFeatures({
561
+ map,
562
+ tileIsFullyVisible,
563
+ geometryIntersection: transformedGeometryToIntersect,
564
+ data: tile.data.lines,
565
+ type: 'LineString',
566
+ bbox,
567
+ tileFormat,
568
+ uniqueIdProperty,
569
+ options
570
+ });
571
+ calculateFeatures({
572
+ map,
573
+ tileIsFullyVisible,
574
+ geometryIntersection: transformedGeometryToIntersect,
575
+ data: tile.data.polygons,
576
+ type: 'Polygon',
577
+ bbox,
578
+ tileFormat,
579
+ uniqueIdProperty,
580
+ options
581
+ });
582
+ }
583
+ return Array.from(map.values());
584
+ }
585
+ function processTileFeatureProperties({
586
+ map,
587
+ data,
588
+ startIndex,
589
+ endIndex,
590
+ type,
591
+ bbox,
592
+ tileFormat,
593
+ uniqueIdProperty,
594
+ storeGeometry,
595
+ geometryIntersection
596
+ }) {
597
+ const tileProps = getPropertiesFromTile(data, startIndex);
598
+ const uniquePropertyValue = getUniquePropertyValue(tileProps, uniqueIdProperty, map);
599
+ if (!uniquePropertyValue || map.has(uniquePropertyValue)) {
600
+ return;
601
+ }
602
+ let geometry = null;
603
+ // Only calculate geometry if necessary
604
+ if (storeGeometry || geometryIntersection) {
605
+ const {
606
+ positions
607
+ } = data;
608
+ const ringCoordinates = getRingCoordinatesFor(startIndex, endIndex, positions);
609
+ geometry = getFeatureByType(ringCoordinates, type);
610
+ }
611
+ // If intersection is required, check before proceeding
612
+ if (geometry && geometryIntersection && !intersects(geometry, geometryIntersection)) {
613
+ return;
614
+ }
615
+ const properties = parseProperties(tileProps);
616
+ // Only save geometry if necessary
617
+ if (storeGeometry && geometry) {
618
+ properties[FEATURE_GEOM_PROPERTY] = tileFormat === TileFormat.MVT ? transformTileCoordsToWGS84(geometry, bbox) : geometry;
619
+ }
620
+ map.set(uniquePropertyValue, properties);
621
+ }
622
+ function addIntersectedFeaturesInTile({
623
+ map,
624
+ data,
625
+ geometryIntersection,
626
+ type,
627
+ bbox,
628
+ tileFormat,
629
+ uniqueIdProperty,
630
+ options
631
+ }) {
632
+ const indices = getIndices(data);
633
+ const storeGeometry = (options == null ? void 0 : options.storeGeometry) || false;
634
+ for (let i = 0; i < indices.length - 1; i++) {
635
+ const startIndex = indices[i];
636
+ const endIndex = indices[i + 1];
637
+ processTileFeatureProperties({
638
+ map,
639
+ data,
640
+ startIndex,
641
+ endIndex,
642
+ type,
643
+ bbox,
644
+ tileFormat,
645
+ uniqueIdProperty,
646
+ storeGeometry,
647
+ geometryIntersection
648
+ });
649
+ }
650
+ }
651
+ function getIndices(data) {
652
+ let indices;
653
+ switch (data.type) {
654
+ case 'Point':
655
+ // @ts-expect-error Missing or changed types?
656
+ indices = data.pointIndices;
657
+ break;
658
+ case 'LineString':
659
+ indices = data.pathIndices;
660
+ break;
661
+ case 'Polygon':
662
+ indices = data.primitivePolygonIndices;
663
+ break;
664
+ default:
665
+ throw new Error(`Unexpected type, "${data.type}"`);
666
+ }
667
+ return indices.value;
668
+ }
669
+ function getFeatureId(data, startIndex) {
670
+ return data.featureIds.value[startIndex];
671
+ }
672
+ function getPropertiesFromTile(data, startIndex) {
673
+ var _fields$featureId;
674
+ const featureId = getFeatureId(data, startIndex);
675
+ const {
676
+ properties,
677
+ numericProps,
678
+ fields
679
+ } = data;
680
+ const result = {
681
+ uniqueId: fields == null || (_fields$featureId = fields[featureId]) == null ? void 0 : _fields$featureId.id,
682
+ properties: properties[featureId],
683
+ numericProps: {}
684
+ };
685
+ for (const key in numericProps) {
686
+ result.numericProps[key] = numericProps[key].value[startIndex];
687
+ }
688
+ return result;
689
+ }
690
+ function parseProperties(tileProps) {
691
+ const {
692
+ properties,
693
+ numericProps
694
+ } = tileProps;
695
+ return Object.assign({}, properties, numericProps);
696
+ }
697
+ function getUniquePropertyValue(tileProps, uniqueIdProperty, map) {
698
+ if (uniqueIdProperty) {
699
+ return getValueFromTileProps(tileProps, uniqueIdProperty);
700
+ }
701
+ if (tileProps.uniqueId) {
702
+ return tileProps.uniqueId;
703
+ }
704
+ const artificialId = map.size + 1; // a counter, assumed as a valid new id
705
+ return getValueFromTileProps(tileProps, 'cartodb_id') || getValueFromTileProps(tileProps, 'geoid') || artificialId;
706
+ }
707
+ function getValueFromTileProps(tileProps, propertyName) {
708
+ const {
709
+ properties,
710
+ numericProps
711
+ } = tileProps;
712
+ return numericProps[propertyName] || properties[propertyName];
713
+ }
714
+ function getFeatureByType(coordinates, type) {
715
+ switch (type) {
716
+ case 'Polygon':
717
+ return {
718
+ type: 'Polygon',
719
+ coordinates: [coordinates]
720
+ };
721
+ case 'LineString':
722
+ return {
723
+ type: 'LineString',
724
+ coordinates
725
+ };
726
+ case 'Point':
727
+ return {
728
+ type: 'Point',
729
+ coordinates: coordinates[0]
730
+ };
731
+ default:
732
+ throw new Error('Invalid geometry type');
733
+ }
734
+ }
735
+ function getRingCoordinatesFor(startIndex, endIndex, positions) {
736
+ const ringCoordinates = [];
737
+ for (let j = startIndex; j < endIndex; j++) {
738
+ ringCoordinates.push(Array.from(positions.value.subarray(j * positions.size, (j + 1) * positions.size)));
739
+ }
740
+ return ringCoordinates;
741
+ }
742
+ function calculateFeatures({
743
+ map,
744
+ tileIsFullyVisible,
745
+ geometryIntersection,
746
+ data,
747
+ type,
748
+ bbox,
749
+ tileFormat,
750
+ uniqueIdProperty,
751
+ options
752
+ }) {
753
+ if (!(data != null && data.properties.length)) {
754
+ return;
755
+ }
756
+ if (tileIsFullyVisible) {
757
+ addAllFeaturesInTile({
758
+ map,
759
+ data,
760
+ type,
761
+ bbox,
762
+ tileFormat,
763
+ uniqueIdProperty,
764
+ options
765
+ });
766
+ } else {
767
+ addIntersectedFeaturesInTile({
768
+ map,
769
+ data,
770
+ geometryIntersection,
771
+ type,
772
+ bbox,
773
+ tileFormat,
774
+ uniqueIdProperty,
775
+ options
776
+ });
777
+ }
778
+ }
779
+ function addAllFeaturesInTile({
780
+ map,
781
+ data,
782
+ type,
783
+ bbox,
784
+ tileFormat,
785
+ uniqueIdProperty,
786
+ options
787
+ }) {
788
+ const indices = getIndices(data);
789
+ const storeGeometry = (options == null ? void 0 : options.storeGeometry) || false;
790
+ for (let i = 0; i < indices.length - 1; i++) {
791
+ const startIndex = indices[i];
792
+ const endIndex = indices[i + 1];
793
+ processTileFeatureProperties({
794
+ map,
795
+ data,
796
+ startIndex,
797
+ endIndex,
798
+ type,
799
+ bbox,
800
+ tileFormat,
801
+ uniqueIdProperty,
802
+ storeGeometry
803
+ });
804
+ }
805
+ }
806
+ function createIndicesForPoints(data) {
807
+ const featureIds = data.featureIds.value;
808
+ const lastFeatureId = featureIds[featureIds.length - 1];
809
+ const PointIndicesArray = featureIds.constructor;
810
+ const pointIndices = {
811
+ value: new PointIndicesArray(featureIds.length + 1),
812
+ size: 1
813
+ };
814
+ pointIndices.value.set(featureIds);
815
+ pointIndices.value.set([lastFeatureId + 1], featureIds.length);
816
+ // @ts-expect-error Missing or changed types?
817
+ data.pointIndices = pointIndices;
818
+ }
819
+
820
+ // a tile is an array [x,y,z]
821
+ var d2r = Math.PI / 180,
822
+ r2d = 180 / Math.PI;
823
+ function tileToBBOX(tile) {
824
+ var e = tile2lon(tile[0] + 1, tile[2]);
825
+ var w = tile2lon(tile[0], tile[2]);
826
+ var s = tile2lat(tile[1] + 1, tile[2]);
827
+ var n = tile2lat(tile[1], tile[2]);
828
+ return [w, s, e, n];
829
+ }
830
+ function tileToGeoJSON(tile) {
831
+ var bbox = tileToBBOX(tile);
832
+ var poly = {
833
+ type: 'Polygon',
834
+ coordinates: [[[bbox[0], bbox[1]], [bbox[0], bbox[3]], [bbox[2], bbox[3]], [bbox[2], bbox[1]], [bbox[0], bbox[1]]]]
835
+ };
836
+ return poly;
837
+ }
838
+ function tile2lon(x, z) {
839
+ return x / Math.pow(2, z) * 360 - 180;
840
+ }
841
+ function tile2lat(y, z) {
842
+ var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
843
+ return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
844
+ }
845
+ function pointToTile(lon, lat, z) {
846
+ var tile = pointToTileFraction(lon, lat, z);
847
+ tile[0] = Math.floor(tile[0]);
848
+ tile[1] = Math.floor(tile[1]);
849
+ return tile;
850
+ }
851
+ function getChildren(tile) {
852
+ return [[tile[0] * 2, tile[1] * 2, tile[2] + 1], [tile[0] * 2 + 1, tile[1] * 2, tile[2] + 1], [tile[0] * 2 + 1, tile[1] * 2 + 1, tile[2] + 1], [tile[0] * 2, tile[1] * 2 + 1, tile[2] + 1]];
853
+ }
854
+ function getParent(tile) {
855
+ // top left
856
+ if (tile[0] % 2 === 0 && tile[1] % 2 === 0) {
857
+ return [tile[0] / 2, tile[1] / 2, tile[2] - 1];
858
+ }
859
+ // bottom left
860
+ else if (tile[0] % 2 === 0 && !tile[1] % 2 === 0) {
861
+ return [tile[0] / 2, (tile[1] - 1) / 2, tile[2] - 1];
862
+ }
863
+ // top right
864
+ else if (!tile[0] % 2 === 0 && tile[1] % 2 === 0) {
865
+ return [(tile[0] - 1) / 2, tile[1] / 2, tile[2] - 1];
866
+ }
867
+ // bottom right
868
+ else {
869
+ return [(tile[0] - 1) / 2, (tile[1] - 1) / 2, tile[2] - 1];
870
+ }
871
+ }
872
+ function getSiblings(tile) {
873
+ return getChildren(getParent(tile));
874
+ }
875
+ function hasSiblings(tile, tiles) {
876
+ var siblings = getSiblings(tile);
877
+ for (var i = 0; i < siblings.length; i++) {
878
+ if (!hasTile(tiles, siblings[i])) return false;
879
+ }
880
+ return true;
881
+ }
882
+ function hasTile(tiles, tile) {
883
+ for (var i = 0; i < tiles.length; i++) {
884
+ if (tilesEqual(tiles[i], tile)) return true;
885
+ }
886
+ return false;
887
+ }
888
+ function tilesEqual(tile1, tile2) {
889
+ return tile1[0] === tile2[0] && tile1[1] === tile2[1] && tile1[2] === tile2[2];
890
+ }
891
+ function tileToQuadkey(tile) {
892
+ var index = '';
893
+ for (var z = tile[2]; z > 0; z--) {
894
+ var b = 0;
895
+ var mask = 1 << z - 1;
896
+ if ((tile[0] & mask) !== 0) b++;
897
+ if ((tile[1] & mask) !== 0) b += 2;
898
+ index += b.toString();
899
+ }
900
+ return index;
901
+ }
902
+ function quadkeyToTile(quadkey) {
903
+ var x = 0;
904
+ var y = 0;
905
+ var z = quadkey.length;
906
+ for (var i = z; i > 0; i--) {
907
+ var mask = 1 << i - 1;
908
+ switch (quadkey[z - i]) {
909
+ case '0':
910
+ break;
911
+ case '1':
912
+ x |= mask;
913
+ break;
914
+ case '2':
915
+ y |= mask;
916
+ break;
917
+ case '3':
918
+ x |= mask;
919
+ y |= mask;
920
+ break;
921
+ }
922
+ }
923
+ return [x, y, z];
924
+ }
925
+ function bboxToTile(bboxCoords) {
926
+ var min = pointToTile(bboxCoords[0], bboxCoords[1], 32);
927
+ var max = pointToTile(bboxCoords[2], bboxCoords[3], 32);
928
+ var bbox = [min[0], min[1], max[0], max[1]];
929
+ var z = getBboxZoom(bbox);
930
+ if (z === 0) return [0, 0, 0];
931
+ var x = bbox[0] >>> 32 - z;
932
+ var y = bbox[1] >>> 32 - z;
933
+ return [x, y, z];
934
+ }
935
+ function getBboxZoom(bbox) {
936
+ var MAX_ZOOM = 28;
937
+ for (var z = 0; z < MAX_ZOOM; z++) {
938
+ var mask = 1 << 32 - (z + 1);
939
+ if ((bbox[0] & mask) != (bbox[2] & mask) || (bbox[1] & mask) != (bbox[3] & mask)) {
940
+ return z;
941
+ }
942
+ }
943
+ return MAX_ZOOM;
944
+ }
945
+ function pointToTileFraction(lon, lat, z) {
946
+ var sin = Math.sin(lat * d2r),
947
+ z2 = Math.pow(2, z),
948
+ x = z2 * (lon / 360 + 0.5),
949
+ y = z2 * (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
950
+ return [x, y, z];
951
+ }
952
+ var tilebelt = {
953
+ tileToGeoJSON: tileToGeoJSON,
954
+ tileToBBOX: tileToBBOX,
955
+ getChildren: getChildren,
956
+ getParent: getParent,
957
+ getSiblings: getSiblings,
958
+ hasTile: hasTile,
959
+ hasSiblings: hasSiblings,
960
+ tilesEqual: tilesEqual,
961
+ tileToQuadkey: tileToQuadkey,
962
+ quadkeyToTile: quadkeyToTile,
963
+ pointToTile: pointToTile,
964
+ bboxToTile: bboxToTile,
965
+ pointToTileFraction: pointToTileFraction
966
+ };
967
+
968
+ /**
969
+ * Given a geometry, create cells and return them in their raw form,
970
+ * as an array of cell identifiers.
971
+ *
972
+ * @alias tiles
973
+ * @param {Object} geom GeoJSON geometry
974
+ * @param {Object} limits an object with min_zoom and max_zoom properties
975
+ * specifying the minimum and maximum level to be tiled.
976
+ * @returns {Array<Array<number>>} An array of tiles given as [x, y, z] arrays
977
+ */
978
+ var tiles = getTiles;
979
+ function getTiles(geom, limits) {
980
+ var i,
981
+ tile,
982
+ coords = geom.coordinates,
983
+ maxZoom = limits.max_zoom,
984
+ tileHash = {},
985
+ tiles = [];
986
+ if (geom.type === 'Point') {
987
+ return [tilebelt.pointToTile(coords[0], coords[1], maxZoom)];
988
+ } else if (geom.type === 'MultiPoint') {
989
+ for (i = 0; i < coords.length; i++) {
990
+ tile = tilebelt.pointToTile(coords[i][0], coords[i][1], maxZoom);
991
+ tileHash[toID(tile[0], tile[1], tile[2])] = true;
992
+ }
993
+ } else if (geom.type === 'LineString') {
994
+ lineCover(tileHash, coords, maxZoom);
995
+ } else if (geom.type === 'MultiLineString') {
996
+ for (i = 0; i < coords.length; i++) {
997
+ lineCover(tileHash, coords[i], maxZoom);
998
+ }
999
+ } else if (geom.type === 'Polygon') {
1000
+ polygonCover(tileHash, tiles, coords, maxZoom);
1001
+ } else if (geom.type === 'MultiPolygon') {
1002
+ for (i = 0; i < coords.length; i++) {
1003
+ polygonCover(tileHash, tiles, coords[i], maxZoom);
1004
+ }
1005
+ } else {
1006
+ throw new Error('Geometry type not implemented');
1007
+ }
1008
+ if (limits.min_zoom !== maxZoom) {
1009
+ // sync tile hash and tile array so that both contain the same tiles
1010
+ var len = tiles.length;
1011
+ appendHashTiles(tileHash, tiles);
1012
+ for (i = 0; i < len; i++) {
1013
+ var t = tiles[i];
1014
+ tileHash[toID(t[0], t[1], t[2])] = true;
1015
+ }
1016
+ return mergeTiles(tileHash, tiles, limits);
1017
+ }
1018
+ appendHashTiles(tileHash, tiles);
1019
+ return tiles;
1020
+ }
1021
+ function mergeTiles(tileHash, tiles, limits) {
1022
+ var mergedTiles = [];
1023
+ for (var z = limits.max_zoom; z > limits.min_zoom; z--) {
1024
+ var parentTileHash = {};
1025
+ var parentTiles = [];
1026
+ for (var i = 0; i < tiles.length; i++) {
1027
+ var t = tiles[i];
1028
+ if (t[0] % 2 === 0 && t[1] % 2 === 0) {
1029
+ var id2 = toID(t[0] + 1, t[1], z),
1030
+ id3 = toID(t[0], t[1] + 1, z),
1031
+ id4 = toID(t[0] + 1, t[1] + 1, z);
1032
+ if (tileHash[id2] && tileHash[id3] && tileHash[id4]) {
1033
+ tileHash[toID(t[0], t[1], t[2])] = false;
1034
+ tileHash[id2] = false;
1035
+ tileHash[id3] = false;
1036
+ tileHash[id4] = false;
1037
+ var parentTile = [t[0] / 2, t[1] / 2, z - 1];
1038
+ if (z - 1 === limits.min_zoom) mergedTiles.push(parentTile);else {
1039
+ parentTileHash[toID(t[0] / 2, t[1] / 2, z - 1)] = true;
1040
+ parentTiles.push(parentTile);
1041
+ }
1042
+ }
1043
+ }
1044
+ }
1045
+ for (i = 0; i < tiles.length; i++) {
1046
+ t = tiles[i];
1047
+ if (tileHash[toID(t[0], t[1], t[2])]) mergedTiles.push(t);
1048
+ }
1049
+ tileHash = parentTileHash;
1050
+ tiles = parentTiles;
1051
+ }
1052
+ return mergedTiles;
1053
+ }
1054
+ function polygonCover(tileHash, tileArray, geom, zoom) {
1055
+ var intersections = [];
1056
+ for (var i = 0; i < geom.length; i++) {
1057
+ var ring = [];
1058
+ lineCover(tileHash, geom[i], zoom, ring);
1059
+ for (var j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
1060
+ var m = (j + 1) % len;
1061
+ var y = ring[j][1];
1062
+
1063
+ // add interesction if it's not local extremum or duplicate
1064
+ if ((y > ring[k][1] || y > ring[m][1]) && (
1065
+ // not local minimum
1066
+ y < ring[k][1] || y < ring[m][1]) &&
1067
+ // not local maximum
1068
+ y !== ring[m][1]) intersections.push(ring[j]);
1069
+ }
1070
+ }
1071
+ intersections.sort(compareTiles); // sort by y, then x
1072
+
1073
+ for (i = 0; i < intersections.length; i += 2) {
1074
+ // fill tiles between pairs of intersections
1075
+ y = intersections[i][1];
1076
+ for (var x = intersections[i][0] + 1; x < intersections[i + 1][0]; x++) {
1077
+ var id = toID(x, y, zoom);
1078
+ if (!tileHash[id]) {
1079
+ tileArray.push([x, y, zoom]);
1080
+ }
1081
+ }
1082
+ }
1083
+ }
1084
+ function compareTiles(a, b) {
1085
+ return a[1] - b[1] || a[0] - b[0];
1086
+ }
1087
+ function lineCover(tileHash, coords, maxZoom, ring) {
1088
+ var prevX, prevY;
1089
+ for (var i = 0; i < coords.length - 1; i++) {
1090
+ var start = tilebelt.pointToTileFraction(coords[i][0], coords[i][1], maxZoom),
1091
+ stop = tilebelt.pointToTileFraction(coords[i + 1][0], coords[i + 1][1], maxZoom),
1092
+ x0 = start[0],
1093
+ y0 = start[1],
1094
+ x1 = stop[0],
1095
+ y1 = stop[1],
1096
+ dx = x1 - x0,
1097
+ dy = y1 - y0;
1098
+ if (dy === 0 && dx === 0) continue;
1099
+ var sx = dx > 0 ? 1 : -1,
1100
+ sy = dy > 0 ? 1 : -1,
1101
+ x = Math.floor(x0),
1102
+ y = Math.floor(y0),
1103
+ tMaxX = dx === 0 ? Infinity : Math.abs(((dx > 0 ? 1 : 0) + x - x0) / dx),
1104
+ tMaxY = dy === 0 ? Infinity : Math.abs(((dy > 0 ? 1 : 0) + y - y0) / dy),
1105
+ tdx = Math.abs(sx / dx),
1106
+ tdy = Math.abs(sy / dy);
1107
+ if (x !== prevX || y !== prevY) {
1108
+ tileHash[toID(x, y, maxZoom)] = true;
1109
+ if (ring && y !== prevY) ring.push([x, y]);
1110
+ prevX = x;
1111
+ prevY = y;
1112
+ }
1113
+ while (tMaxX < 1 || tMaxY < 1) {
1114
+ if (tMaxX < tMaxY) {
1115
+ tMaxX += tdx;
1116
+ x += sx;
1117
+ } else {
1118
+ tMaxY += tdy;
1119
+ y += sy;
1120
+ }
1121
+ tileHash[toID(x, y, maxZoom)] = true;
1122
+ if (ring && y !== prevY) ring.push([x, y]);
1123
+ prevX = x;
1124
+ prevY = y;
1125
+ }
1126
+ }
1127
+ if (ring && y === ring[0][1]) ring.pop();
1128
+ }
1129
+ function appendHashTiles(hash, tiles) {
1130
+ var keys = Object.keys(hash);
1131
+ for (var i = 0; i < keys.length; i++) {
1132
+ tiles.push(fromID(+keys[i]));
1133
+ }
1134
+ }
1135
+ function toID(x, y, z) {
1136
+ var dim = 2 * (1 << z);
1137
+ return (dim * y + x) * 32 + z;
1138
+ }
1139
+ function fromID(id) {
1140
+ var z = id % 32,
1141
+ dim = 2 * (1 << z),
1142
+ xy = (id - z) / 32,
1143
+ x = xy % dim,
1144
+ y = (xy - x) / dim % dim;
1145
+ return [x, y, z];
1146
+ }
1147
+
1148
+ const B = [0x5555555555555555n, 0x3333333333333333n, 0x0f0f0f0f0f0f0f0fn, 0x00ff00ff00ff00ffn, 0x0000ffff0000ffffn, 0x00000000ffffffffn];
1149
+ const S = [0n, 1n, 2n, 4n, 8n, 16n];
1150
+ function tileToCell(tile) {
1151
+ if (tile.z < 0 || tile.z > 26) {
1152
+ throw new Error('Wrong zoom');
1153
+ }
1154
+ const z = BigInt(tile.z);
1155
+ let x = BigInt(tile.x) << 32n - z;
1156
+ let y = BigInt(tile.y) << 32n - z;
1157
+ for (let i = 0; i < 5; i++) {
1158
+ const s = S[5 - i];
1159
+ const b = B[4 - i];
1160
+ x = (x | x << s) & b;
1161
+ y = (y | y << s) & b;
1162
+ }
1163
+ const quadbin = 0x4000000000000000n | 1n << 59n |
1164
+ // | (mode << 59) | (mode_dep << 57)
1165
+ z << 52n | (x | y << 1n) >> 12n | 0xfffffffffffffn >> z * 2n;
1166
+ return quadbin;
1167
+ }
1168
+ function getResolution$1(quadbin) {
1169
+ return quadbin >> 52n & 0x1fn;
1170
+ }
1171
+ function geometryToCells(geometry, resolution) {
1172
+ const zoom = Number(resolution);
1173
+ return tiles(geometry, {
1174
+ min_zoom: zoom,
1175
+ max_zoom: zoom
1176
+ }).map(([x, y, z]) => tileToCell({
1177
+ x,
1178
+ y,
1179
+ z
1180
+ }));
1181
+ }
1182
+
1183
+ function tileFeaturesSpatialIndex({
1184
+ tiles,
1185
+ spatialFilter,
1186
+ spatialDataColumn,
1187
+ spatialDataType
1188
+ }) {
1189
+ const map = new Map();
1190
+ const spatialIndex = getSpatialIndex(spatialDataType);
1191
+ const resolution = getResolution(tiles, spatialIndex);
1192
+ const spatialIndexIDName = spatialDataColumn ? spatialDataColumn : spatialIndex;
1193
+ if (!resolution) {
1194
+ return [];
1195
+ }
1196
+ const cells = getCellsCoverGeometry(spatialFilter, spatialIndex, resolution);
1197
+ if (!(cells != null && cells.length)) {
1198
+ return [];
1199
+ }
1200
+ // We transform cells to Set to improve the performace
1201
+ const cellsSet = new Set(cells);
1202
+ for (const tile of tiles) {
1203
+ if (tile.isVisible === false || !tile.data) {
1204
+ continue;
1205
+ }
1206
+ tile.data.forEach(d => {
1207
+ if (cellsSet.has(d.id)) {
1208
+ map.set(d.id, _extends({}, d.properties, {
1209
+ [spatialIndexIDName]: d.id
1210
+ }));
1211
+ }
1212
+ });
1213
+ }
1214
+ return Array.from(map.values());
1215
+ }
1216
+ function getResolution(tiles, spatialIndex) {
1217
+ var _tiles$find;
1218
+ const data = (_tiles$find = tiles.find(tile => {
1219
+ var _tile$data;
1220
+ return (_tile$data = tile.data) == null ? void 0 : _tile$data.length;
1221
+ })) == null ? void 0 : _tiles$find.data;
1222
+ if (!data) {
1223
+ return;
1224
+ }
1225
+ if (spatialIndex === SpatialIndex.QUADBIN) {
1226
+ return Number(getResolution$1(data[0].id));
1227
+ }
1228
+ if (spatialIndex === SpatialIndex.H3) {
1229
+ return getResolution$2(data[0].id);
1230
+ }
1231
+ }
1232
+ const bboxWest = [-180, -90, 0, 90];
1233
+ const bboxEast = [0, -90, 180, 90];
1234
+ function getCellsCoverGeometry(geometry, spatialIndex, resolution) {
1235
+ if (spatialIndex === SpatialIndex.QUADBIN) {
1236
+ // @ts-expect-error TODO: Probably ought to be stricter about number vs. bigint types in this file.
1237
+ return geometryToCells(geometry, resolution);
1238
+ }
1239
+ if (spatialIndex === SpatialIndex.H3) {
1240
+ // The current H3 polyfill algorithm can't deal with polygon segments of greater than 180 degrees longitude
1241
+ // so we clip the geometry to be sure that none of them is greater than 180 degrees
1242
+ // https://github.com/uber/h3-js/issues/24#issuecomment-431893796
1243
+ return polygonToCells(bboxClip(geometry, bboxWest).geometry.coordinates, resolution, true).concat(polygonToCells(bboxClip(geometry, bboxEast).geometry.coordinates, resolution, true));
1244
+ }
1245
+ }
1246
+ function getSpatialIndex(spatialDataType) {
1247
+ switch (spatialDataType) {
1248
+ case 'h3':
1249
+ return SpatialIndex.H3;
1250
+ case 'quadbin':
1251
+ return SpatialIndex.QUADBIN;
1252
+ default:
1253
+ throw new Error('Unexpected spatial data type');
1254
+ }
1255
+ }
1256
+
1257
+ /**
1258
+ * Current version of @carto/api-client.
1259
+ * @internal
1260
+ */
1261
+ /** @internal */
1262
+ const V3_MINOR_VERSION = '3.4';
1263
+ /** @privateRemarks Source: @carto/constants, @deck.gl/carto */
1264
+ const DEFAULT_GEO_COLUMN = 'geom';
1265
+ /**
1266
+ * Fastly default limit is 8192; leave some padding.
1267
+ * @privateRemarks Source: @deck.gl/carto
1268
+ */
1269
+ const DEFAULT_MAX_LENGTH_URL = 7000;
1270
+ /** @privateRemarks Source: @deck.gl/carto */
1271
+ const DEFAULT_TILE_RESOLUTION = 0.5;
1272
+ /**
1273
+ * @privateRemarks Source: @deck.gl/carto
1274
+ * @internal
1275
+ */
1276
+ const DEFAULT_AGGREGATION_RES_LEVEL_H3 = 4;
1277
+ /**
1278
+ * @privateRemarks Source: @deck.gl/carto
1279
+ * @internal
1280
+ */
1281
+ const DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN = 6;
1282
+
1283
+ /** @privateRemarks Source: @carto/react-core */
1284
+ function tileFeatures({
1285
+ tiles,
1286
+ spatialFilter,
1287
+ uniqueIdProperty,
1288
+ tileFormat,
1289
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
1290
+ spatialDataType,
1291
+ options = {}
1292
+ }) {
1293
+ if (spatialDataType !== 'geo') {
1294
+ return tileFeaturesSpatialIndex({
1295
+ tiles: tiles,
1296
+ spatialFilter,
1297
+ spatialDataColumn,
1298
+ spatialDataType
1299
+ });
1300
+ }
1301
+ return tileFeaturesGeometries({
1302
+ tiles,
1303
+ tileFormat,
1304
+ spatialFilter,
1305
+ uniqueIdProperty,
1306
+ options
1307
+ });
1308
+ }
1309
+
1310
+ /**
1311
+ * deck.gl's DataFilterExtension supports GPU filtering with 1–4 values. We
1312
+ * allocate filters[0] to generic filters and filters[1] to time filters.
1313
+ *
1314
+ * getFilterValue() _must_ return an array of the same size as the filterSize
1315
+ * used to initialize the DataFilterExtension. We document that users must use
1316
+ * filterSize=4 for compatibility with @link {getDataFilterExtensionProps}.
1317
+ */
1318
+ const DEFAULT_FILTER_SIZE = 4;
1319
+ /**
1320
+ * Creates props for DataFilterExtension, from `@deck.gl/extensions`, given
1321
+ * a set of filters. Requires that DataFilterExtension is initialized with
1322
+ * filterSize=4, where the CARTO filters will occupy the first two slots.
1323
+ *
1324
+ * @example To create a deck.gl layer with GPU data filtering:
1325
+ * ```typescript
1326
+ * import {DataFilterExtension} from '@deck.gl/extensions';
1327
+ * import {VectorTileLayer} from '@deck.gl/layers';
1328
+ * import {getDataFilterExtensionProps} from '@carto/api-client';
1329
+ *
1330
+ * const layer = new VectorTileLayer({
1331
+ * data: data,
1332
+ * extensions: [new DataFilterExtension({filterSize: 4})],
1333
+ * ...getDataFilterExtensionProps(filters),
1334
+ * });
41
1335
  * ```
42
- *
43
- * @internalRemarks Source: @carto/react-api, @deck.gl/carto
44
1336
  */
45
- var FilterType;
46
- (function (FilterType) {
47
- FilterType["IN"] = "in";
48
- /** [a, b] both are included. */
49
- FilterType["BETWEEN"] = "between";
50
- /** [a, b) a is included, b is not. */
51
- FilterType["CLOSED_OPEN"] = "closed_open";
52
- FilterType["TIME"] = "time";
53
- FilterType["STRING_SEARCH"] = "stringSearch";
54
- })(FilterType || (FilterType = {}));
55
- /** @internalRemarks Source: @carto/constants */
56
- var ApiVersion;
57
- (function (ApiVersion) {
58
- ApiVersion["V1"] = "v1";
59
- ApiVersion["V2"] = "v2";
60
- ApiVersion["V3"] = "v3";
61
- })(ApiVersion || (ApiVersion = {}));
62
- /** @internalRemarks Source: @carto/constants, @deck.gl/carto */
63
- const DEFAULT_API_BASE_URL = 'https://gcp-us-east1.api.carto.com';
1337
+ function getDataFilterExtensionProps(filters, filtersLogicalOperator) {
1338
+ const {
1339
+ filtersWithoutTimeType,
1340
+ timeColumn,
1341
+ timeFilter
1342
+ } = getFiltersByType(filters);
1343
+ return {
1344
+ filterRange: getFilterRange(timeFilter, DEFAULT_FILTER_SIZE),
1345
+ updateTriggers: getUpdateTriggers(filtersWithoutTimeType, timeColumn, timeFilter),
1346
+ getFilterValue: getFilterValue(filtersWithoutTimeType, timeColumn, timeFilter, DEFAULT_FILTER_SIZE, filtersLogicalOperator)
1347
+ };
1348
+ }
1349
+ /** @internal */
1350
+ function getFiltersByType(filters) {
1351
+ const filtersWithoutTimeType = {};
1352
+ let timeColumn = null;
1353
+ let timeFilter = null;
1354
+ for (const [column, columnData] of Object.entries(filters)) {
1355
+ for (const [type, typeData] of Object.entries(columnData)) {
1356
+ if (type === FilterType.TIME) {
1357
+ timeColumn = column;
1358
+ timeFilter = typeData;
1359
+ } else {
1360
+ filtersWithoutTimeType[column] = {
1361
+ [type]: typeData
1362
+ };
1363
+ }
1364
+ }
1365
+ }
1366
+ return {
1367
+ filtersWithoutTimeType,
1368
+ timeColumn,
1369
+ timeFilter
1370
+ };
1371
+ }
1372
+ /** @internal */
1373
+ function getFilterRange(timeFilter, filterSize) {
1374
+ const result = Array(filterSize).fill([0, 0]);
1375
+ // According to getFilterValue all filters are resolved as 0 or 1 in the first position of the array
1376
+ // except the time filter value that is resolved with the real value of the feature in the second position of the array
1377
+ result[0] = [1, 1];
1378
+ if (timeFilter) {
1379
+ var _timeFilter$params;
1380
+ const offsetBy = ((_timeFilter$params = timeFilter.params) == null ? void 0 : _timeFilter$params.offsetBy) || 0;
1381
+ result[1] = timeFilter.values[0].map(v => v - offsetBy);
1382
+ }
1383
+ return result;
1384
+ }
1385
+ /** @internal */
1386
+ function getUpdateTriggers(filtersWithoutTimeType, timeColumn, timeFilter) {
1387
+ const result = _extends({}, filtersWithoutTimeType);
1388
+ // We don't want to change the layer UpdateTriggers every time that the time filter changes
1389
+ // because this filter is changed by the time series widget during its animation
1390
+ // so we remove the time filter value from the `updateTriggers`
1391
+ if (timeColumn && timeFilter) {
1392
+ var _timeFilter$params2;
1393
+ result[timeColumn] = _extends({}, result[timeColumn], {
1394
+ offsetBy: (_timeFilter$params2 = timeFilter.params) == null ? void 0 : _timeFilter$params2.offsetBy,
1395
+ [FilterType.TIME]: {} // Allows working with other filters, without an impact on performance.
1396
+ });
1397
+ }
1398
+ return {
1399
+ getFilterValue: JSON.stringify(result)
1400
+ };
1401
+ }
1402
+ /** @internal */
1403
+ function getFilterValue(filtersWithoutTimeType, timeColumn, timeFilter, filterSize, filtersLogicalOperator) {
1404
+ const result = Array(filterSize).fill(0);
1405
+ const featureFilter = _buildFeatureFilter({
1406
+ filters: filtersWithoutTimeType,
1407
+ type: 'number',
1408
+ filtersLogicalOperator
1409
+ });
1410
+ // We evaluate all filters except the time filter using _buildFeatureFilter function.
1411
+ // For the time filter, we return the value of the feature and we will change the getFilterRange result
1412
+ // every time this filter changes
1413
+ return feature => {
1414
+ result[0] = featureFilter(feature);
1415
+ if (timeColumn && timeFilter) {
1416
+ var _timeFilter$params3;
1417
+ const offsetBy = ((_timeFilter$params3 = timeFilter.params) == null ? void 0 : _timeFilter$params3.offsetBy) || 0;
1418
+ const f = feature.properties || feature;
1419
+ result[1] = f[timeColumn] - offsetBy;
1420
+ }
1421
+ return result;
1422
+ };
1423
+ }
64
1424
 
65
1425
  const FILTER_TYPES = new Set(Object.values(FilterType));
66
1426
  const isFilterType = type => FILTER_TYPES.has(type);
@@ -88,7 +1448,7 @@ function getApplicableFilters(owner, filters) {
88
1448
  * Due to each data warehouse having its own behavior with columns,
89
1449
  * we need to normalize them and transform every key to lowercase.
90
1450
  *
91
- * @internalRemarks Source: @carto/react-widgets
1451
+ * @privateRemarks Source: @carto/react-widgets
92
1452
  * @internal
93
1453
  */
94
1454
  function normalizeObjectKeys(el) {
@@ -102,14 +1462,14 @@ function normalizeObjectKeys(el) {
102
1462
  return acc;
103
1463
  }, {});
104
1464
  }
105
- /** @internalRemarks Source: @carto/react-core */
1465
+ /** @privateRemarks Source: @carto/react-core */
106
1466
  function assert(condition, message) {
107
1467
  if (!condition) {
108
1468
  throw new Error(message);
109
1469
  }
110
1470
  }
111
1471
  /**
112
- * @internalRemarks Source: @carto/react-core
1472
+ * @privateRemarks Source: @carto/react-core
113
1473
  * @internal
114
1474
  */
115
1475
  class InvalidColumnError extends Error {
@@ -253,7 +1613,7 @@ function createPolygonSpatialFilter(spatialFilter) {
253
1613
  * Check if a viewport is large enough to represent a global coverage.
254
1614
  * In this case the spatial filter parameter for widget calculation is removed.
255
1615
  *
256
- * @internalRemarks Source: @carto/react-core
1616
+ * @privateRemarks Source: @carto/react-core
257
1617
  */
258
1618
  function _isGlobalViewport(viewport) {
259
1619
  const [minx, miny, maxx, maxy] = viewport;
@@ -266,7 +1626,7 @@ function _isGlobalViewport(viewport) {
266
1626
  *
267
1627
  * It results in a Polygon or MultiPolygon strictly inside the validity range.
268
1628
  *
269
- * @internalRemarks Source: @carto/react-core
1629
+ * @privateRemarks Source: @carto/react-core
270
1630
  */
271
1631
  function _normalizeGeometry(geometry) {
272
1632
  const WORLD = [-180, -90, +180, +90];
@@ -292,17 +1652,17 @@ function _normalizeGeometry(geometry) {
292
1652
  }
293
1653
  return result;
294
1654
  }
295
- /** @internalRemarks Source: @carto/react-core */
1655
+ /** @privateRemarks Source: @carto/react-core */
296
1656
  function _cleanPolygonCoords(cc) {
297
1657
  const coords = cc.filter(c => c.length > 0);
298
1658
  return coords.length > 0 ? coords : null;
299
1659
  }
300
- /** @internalRemarks Source: @carto/react-core */
1660
+ /** @privateRemarks Source: @carto/react-core */
301
1661
  function _cleanMultiPolygonCoords(ccc) {
302
1662
  const coords = ccc.map(_cleanPolygonCoords).filter(cc => cc);
303
1663
  return coords.length > 0 ? coords : null;
304
1664
  }
305
- /** @internalRemarks Source: @carto/react-core */
1665
+ /** @privateRemarks Source: @carto/react-core */
306
1666
  function _clean(geometry) {
307
1667
  if (!geometry) {
308
1668
  return null;
@@ -317,19 +1677,19 @@ function _clean(geometry) {
317
1677
  }
318
1678
  return null;
319
1679
  }
320
- /** @internalRemarks Source: @carto/react-core */
1680
+ /** @privateRemarks Source: @carto/react-core */
321
1681
  function _txContourCoords(cc, distance) {
322
1682
  return cc.map(c => [c[0] + distance, c[1]]);
323
1683
  }
324
- /** @internalRemarks Source: @carto/react-core */
1684
+ /** @privateRemarks Source: @carto/react-core */
325
1685
  function _txPolygonCoords(ccc, distance) {
326
1686
  return ccc.map(cc => _txContourCoords(cc, distance));
327
1687
  }
328
- /** @internalRemarks Source: @carto/react-core */
1688
+ /** @privateRemarks Source: @carto/react-core */
329
1689
  function _txMultiPolygonCoords(cccc, distance) {
330
1690
  return cccc.map(ccc => _txPolygonCoords(ccc, distance));
331
1691
  }
332
- /** @internalRemarks Source: @carto/react-core */
1692
+ /** @privateRemarks Source: @carto/react-core */
333
1693
  function _tx(geometry, distance) {
334
1694
  if (geometry && getType(geometry) === 'Polygon') {
335
1695
  const coords = _txPolygonCoords(geometry.coordinates, distance);
@@ -348,51 +1708,6 @@ function _isMultiPolygon(geometry) {
348
1708
  return getType(geometry) === 'MultiPolygon';
349
1709
  }
350
1710
 
351
- function _extends() {
352
- return _extends = Object.assign ? Object.assign.bind() : function (n) {
353
- for (var e = 1; e < arguments.length; e++) {
354
- var t = arguments[e];
355
- for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
356
- }
357
- return n;
358
- }, _extends.apply(null, arguments);
359
- }
360
- function _objectWithoutPropertiesLoose(r, e) {
361
- if (null == r) return {};
362
- var t = {};
363
- for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
364
- if (e.includes(n)) continue;
365
- t[n] = r[n];
366
- }
367
- return t;
368
- }
369
-
370
- /**
371
- * Current version of @carto/api-client.
372
- * @internal
373
- */
374
- /** @internal */
375
- const V3_MINOR_VERSION = '3.4';
376
- /** @internalRemarks Source: @carto/constants, @deck.gl/carto */
377
- const DEFAULT_GEO_COLUMN = 'geom';
378
- /**
379
- * Fastly default limit is 8192; leave some padding.
380
- * @internalRemarks Source: @deck.gl/carto
381
- */
382
- const DEFAULT_MAX_LENGTH_URL = 7000;
383
- /** @internalRemarks Source: @deck.gl/carto */
384
- const DEFAULT_TILE_RESOLUTION = 0.5;
385
- /**
386
- * @internalRemarks Source: @deck.gl/carto
387
- * @internal
388
- */
389
- const DEFAULT_AGGREGATION_RES_LEVEL_H3 = 4;
390
- /**
391
- * @internalRemarks Source: @deck.gl/carto
392
- * @internal
393
- */
394
- const DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN = 6;
395
-
396
1711
  // deck.gl
397
1712
  // SPDX-License-Identifier: MIT
398
1713
  // Copyright (c) vis.gl contributors
@@ -735,9 +2050,99 @@ const boundaryTableSource = async function boundaryTableSource(options) {
735
2050
  return baseSource('boundary', options, urlParameters);
736
2051
  };
737
2052
 
2053
+ const DEFAULT_TILE_SIZE = 512;
2054
+ const QUADBIN_ZOOM_MAX_OFFSET = 4;
2055
+ function getSpatialFiltersResolution(source, viewState) {
2056
+ var _source$dataResolutio, _source$aggregationRe;
2057
+ const dataResolution = (_source$dataResolutio = source.dataResolution) != null ? _source$dataResolutio : Number.MAX_VALUE;
2058
+ const aggregationResLevel = (_source$aggregationRe = source.aggregationResLevel) != null ? _source$aggregationRe : source.spatialDataType === 'h3' ? DEFAULT_AGGREGATION_RES_LEVEL_H3 : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN;
2059
+ const aggregationResLevelOffset = Math.max(0, Math.floor(aggregationResLevel));
2060
+ const currentZoomInt = Math.ceil(viewState.zoom);
2061
+ if (source.spatialDataType === 'h3') {
2062
+ var _maxH3SpatialFiltersR, _maxH3SpatialFiltersR2;
2063
+ const tileSize = DEFAULT_TILE_SIZE;
2064
+ const maxResolutionForZoom = (_maxH3SpatialFiltersR = (_maxH3SpatialFiltersR2 = maxH3SpatialFiltersResolutions.find(([zoom]) => zoom === currentZoomInt)) == null ? void 0 : _maxH3SpatialFiltersR2[1]) != null ? _maxH3SpatialFiltersR : Math.max(0, currentZoomInt - 3);
2065
+ const maxSpatialFiltersResolution = maxResolutionForZoom ? Math.min(dataResolution, maxResolutionForZoom) : dataResolution;
2066
+ const hexagonResolution = _getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
2067
+ return Math.min(hexagonResolution, maxSpatialFiltersResolution);
2068
+ }
2069
+ if (source.spatialDataType === 'quadbin') {
2070
+ const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
2071
+ const maxSpatialFiltersResolution = Math.min(dataResolution, maxResolutionForZoom);
2072
+ const quadsResolution = Math.floor(viewState.zoom) + aggregationResLevelOffset;
2073
+ return Math.min(quadsResolution, maxSpatialFiltersResolution);
2074
+ }
2075
+ return undefined;
2076
+ }
2077
+ const maxH3SpatialFiltersResolutions = [[20, 14], [19, 13], [18, 12], [17, 11], [16, 10], [15, 9], [14, 8], [13, 7], [12, 7], [11, 7], [10, 6], [9, 6], [8, 5], [7, 4], [6, 4], [5, 3], [4, 2], [3, 1], [2, 1], [1, 0]];
2078
+ // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
2079
+ // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
2080
+ const BIAS = 2;
2081
+ /**
2082
+ * Resolution conversion function. Takes a WebMercatorViewport and returns
2083
+ * a H3 resolution such that the screen space size of the hexagons is
2084
+ * "similar" to the given tileSize on screen. Intended for use with deck.gl.
2085
+ * @internal
2086
+ */
2087
+ function _getHexagonResolution(viewport, tileSize) {
2088
+ // Difference in given tile size compared to deck's internal 512px tile size,
2089
+ // expressed as an offset to the viewport zoom.
2090
+ const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
2091
+ const hexagonScaleFactor = 2 / 3 * (viewport.zoom - zoomOffset);
2092
+ const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
2093
+ // Clip and bias
2094
+ return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
2095
+ }
2096
+
2097
+ /**
2098
+ * Source for Widget API requests on a data source defined by a SQL query.
2099
+ *
2100
+ * Abstract class. Use {@link WidgetQuerySource} or {@link WidgetTableSource}.
2101
+ */
2102
+ class WidgetSource {
2103
+ constructor(props) {
2104
+ this.props = void 0;
2105
+ this.props = _extends({}, WidgetSource.defaultProps, {
2106
+ clientId: getClient()
2107
+ }, props);
2108
+ }
2109
+ _getModelSource(filters, filterOwner) {
2110
+ const props = this.props;
2111
+ return {
2112
+ apiVersion: props.apiVersion,
2113
+ apiBaseUrl: props.apiBaseUrl,
2114
+ clientId: props.clientId,
2115
+ accessToken: props.accessToken,
2116
+ connectionName: props.connectionName,
2117
+ filters: getApplicableFilters(filterOwner, filters || props.filters),
2118
+ filtersLogicalOperator: props.filtersLogicalOperator,
2119
+ spatialDataType: props.spatialDataType,
2120
+ spatialDataColumn: props.spatialDataColumn,
2121
+ dataResolution: props.dataResolution
2122
+ };
2123
+ }
2124
+ _getSpatialFiltersResolution(source, spatialFilter, referenceViewState) {
2125
+ // spatialFiltersResolution applies only to spatial index sources.
2126
+ if (!spatialFilter || source.spatialDataType === 'geo') {
2127
+ return;
2128
+ }
2129
+ if (!referenceViewState) {
2130
+ throw new Error('Missing required option, "spatialIndexReferenceViewState".');
2131
+ }
2132
+ return getSpatialFiltersResolution(source, referenceViewState);
2133
+ }
2134
+ }
2135
+ WidgetSource.defaultProps = {
2136
+ apiVersion: ApiVersion.V3,
2137
+ apiBaseUrl: DEFAULT_API_BASE_URL,
2138
+ clientId: getClient(),
2139
+ filters: {},
2140
+ filtersLogicalOperator: 'and'
2141
+ };
2142
+
738
2143
  /**
739
2144
  * Return more descriptive error from API
740
- * @internalRemarks Source: @carto/react-api
2145
+ * @privateRemarks Source: @carto/react-api
741
2146
  */
742
2147
  function dealWithApiError({
743
2148
  response,
@@ -756,11 +2161,10 @@ function dealWithApiError({
756
2161
  case 403:
757
2162
  throw new Error('Forbidden access to the requested data');
758
2163
  default:
759
- const msg = data && data.error && typeof data.error === 'string' ? data.error : JSON.stringify((data == null ? void 0 : data.hint) || ((_data$error2 = data.error) == null ? void 0 : _data$error2[0]));
760
- throw new Error(msg);
2164
+ throw new Error(data && data.error && typeof data.error === 'string' ? data.error : JSON.stringify((data == null ? void 0 : data.hint) || ((_data$error2 = data.error) == null ? void 0 : _data$error2[0])));
761
2165
  }
762
2166
  }
763
- /** @internalRemarks Source: @carto/react-api */
2167
+ /** @privateRemarks Source: @carto/react-api */
764
2168
  async function makeCall({
765
2169
  url,
766
2170
  accessToken,
@@ -770,18 +2174,17 @@ async function makeCall({
770
2174
  let data;
771
2175
  const isPost = (opts == null ? void 0 : opts.method) === 'POST';
772
2176
  try {
773
- var _opts$abortController;
774
2177
  response = await fetch(url.toString(), _extends({
775
2178
  headers: _extends({
776
2179
  Authorization: `Bearer ${accessToken}`
777
2180
  }, isPost && {
778
2181
  'Content-Type': 'application/json'
779
- })
2182
+ }, opts.headers)
780
2183
  }, isPost && {
781
2184
  method: opts == null ? void 0 : opts.method,
782
2185
  body: opts == null ? void 0 : opts.body
783
2186
  }, {
784
- signal: opts == null || (_opts$abortController = opts.abortController) == null ? void 0 : _opts$abortController.signal
2187
+ signal: opts == null ? void 0 : opts.signal
785
2188
  }, opts == null ? void 0 : opts.otherOptions));
786
2189
  data = await response.json();
787
2190
  } catch (error) {
@@ -797,7 +2200,7 @@ async function makeCall({
797
2200
  return data;
798
2201
  }
799
2202
 
800
- /** @internalRemarks Source: @carto/react-api */
2203
+ /** @privateRemarks Source: @carto/react-api */
801
2204
  const AVAILABLE_MODELS = ['category', 'histogram', 'formula', 'pick', 'timeseries', 'range', 'scatterplot', 'table'];
802
2205
  const {
803
2206
  V3
@@ -805,7 +2208,7 @@ const {
805
2208
  const REQUEST_GET_MAX_URL_LENGTH = 2048;
806
2209
  /**
807
2210
  * Execute a SQL model request.
808
- * @internalRemarks Source: @carto/react-api
2211
+ * @privateRemarks Source: @carto/react-api
809
2212
  */
810
2213
  function executeModel(props) {
811
2214
  assert(props.source, 'executeModel: missing source');
@@ -891,115 +2294,36 @@ function objectToURLSearchParams(object) {
891
2294
  } else if (Array.isArray(object[key])) {
892
2295
  params.append(key, JSON.stringify(object[key]));
893
2296
  } else if (object[key] === null) {
894
- params.append(key, 'null');
895
- } else if (object[key] !== undefined) {
896
- params.append(key, String(object[key]));
897
- }
898
- }
899
- return params;
900
- }
901
-
902
- const DEFAULT_TILE_SIZE = 512;
903
- const QUADBIN_ZOOM_MAX_OFFSET = 4;
904
- function getSpatialFiltersResolution(source, viewState) {
905
- var _source$dataResolutio, _source$aggregationRe;
906
- const dataResolution = (_source$dataResolutio = source.dataResolution) != null ? _source$dataResolutio : Number.MAX_VALUE;
907
- const aggregationResLevel = (_source$aggregationRe = source.aggregationResLevel) != null ? _source$aggregationRe : source.spatialDataType === 'h3' ? DEFAULT_AGGREGATION_RES_LEVEL_H3 : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN;
908
- const aggregationResLevelOffset = Math.max(0, Math.floor(aggregationResLevel));
909
- const currentZoomInt = Math.ceil(viewState.zoom);
910
- if (source.spatialDataType === 'h3') {
911
- var _maxH3SpatialFiltersR, _maxH3SpatialFiltersR2;
912
- const tileSize = DEFAULT_TILE_SIZE;
913
- const maxResolutionForZoom = (_maxH3SpatialFiltersR = (_maxH3SpatialFiltersR2 = maxH3SpatialFiltersResolutions.find(([zoom]) => zoom === currentZoomInt)) == null ? void 0 : _maxH3SpatialFiltersR2[1]) != null ? _maxH3SpatialFiltersR : Math.max(0, currentZoomInt - 3);
914
- const maxSpatialFiltersResolution = maxResolutionForZoom ? Math.min(dataResolution, maxResolutionForZoom) : dataResolution;
915
- const hexagonResolution = _getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
916
- return Math.min(hexagonResolution, maxSpatialFiltersResolution);
917
- }
918
- if (source.spatialDataType === 'quadbin') {
919
- const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
920
- const maxSpatialFiltersResolution = Math.min(dataResolution, maxResolutionForZoom);
921
- const quadsResolution = Math.floor(viewState.zoom) + aggregationResLevelOffset;
922
- return Math.min(quadsResolution, maxSpatialFiltersResolution);
923
- }
924
- return undefined;
925
- }
926
- const maxH3SpatialFiltersResolutions = [[20, 14], [19, 13], [18, 12], [17, 11], [16, 10], [15, 9], [14, 8], [13, 7], [12, 7], [11, 7], [10, 6], [9, 6], [8, 5], [7, 4], [6, 4], [5, 3], [4, 2], [3, 1], [2, 1], [1, 0]];
927
- // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
928
- // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
929
- const BIAS = 2;
930
- /**
931
- * Resolution conversion function. Takes a WebMercatorViewport and returns
932
- * a H3 resolution such that the screen space size of the hexagons is
933
- * "similar" to the given tileSize on screen. Intended for use with deck.gl.
934
- * @internal
935
- */
936
- function _getHexagonResolution(viewport, tileSize) {
937
- // Difference in given tile size compared to deck's internal 512px tile size,
938
- // expressed as an offset to the viewport zoom.
939
- const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
940
- const hexagonScaleFactor = 2 / 3 * (viewport.zoom - zoomOffset);
941
- const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
942
- // Clip and bias
943
- return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
944
- }
945
-
946
- const _excluded = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
947
- _excluded2 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
948
- _excluded3 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController", "operationExp"],
949
- _excluded4 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
950
- _excluded5 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
951
- _excluded6 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
952
- _excluded7 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
953
- _excluded8 = ["filterOwner", "abortController", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"];
954
- /**
955
- * Source for Widget API requests on a data source defined by a SQL query.
956
- *
957
- * Abstract class. Use {@link WidgetQuerySource} or {@link WidgetTableSource}.
958
- */
959
- class WidgetBaseSource {
960
- constructor(props) {
961
- this.props = void 0;
962
- this.props = _extends({}, WidgetBaseSource.defaultProps, props);
963
- }
964
- _getModelSource(owner) {
965
- const props = this.props;
966
- return {
967
- apiVersion: props.apiVersion,
968
- apiBaseUrl: props.apiBaseUrl,
969
- clientId: props.clientId,
970
- accessToken: props.accessToken,
971
- connectionName: props.connectionName,
972
- filters: getApplicableFilters(owner, props.filters),
973
- filtersLogicalOperator: props.filtersLogicalOperator,
974
- spatialDataType: props.spatialDataType,
975
- spatialDataColumn: props.spatialDataColumn,
976
- dataResolution: props.dataResolution
977
- };
978
- }
979
- _getSpatialFiltersResolution(source, spatialFilter, referenceViewState) {
980
- // spatialFiltersResolution applies only to spatial index sources.
981
- if (!spatialFilter || source.spatialDataType === 'geo') {
982
- return;
983
- }
984
- if (!referenceViewState) {
985
- throw new Error('Missing required option, "spatialIndexReferenceViewState".');
2297
+ params.append(key, 'null');
2298
+ } else if (object[key] !== undefined) {
2299
+ params.append(key, String(object[key]));
986
2300
  }
987
- return getSpatialFiltersResolution(source, referenceViewState);
988
2301
  }
989
- /****************************************************************************
990
- * CATEGORIES
991
- */
992
- /**
993
- * Returns a list of labeled datapoints for categorical data. Suitable for
994
- * charts including grouped bar charts, pie charts, and tree charts.
995
- */
2302
+ return params;
2303
+ }
2304
+
2305
+ const _excluded = ["signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"],
2306
+ _excluded2 = ["abortController", "signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"],
2307
+ _excluded3 = ["abortController", "signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "operationExp"],
2308
+ _excluded4 = ["abortController", "signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"],
2309
+ _excluded5 = ["abortController", "signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"],
2310
+ _excluded6 = ["abortController", "signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"],
2311
+ _excluded7 = ["abortController", "signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"],
2312
+ _excluded8 = ["abortController", "signal", "filters", "filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"];
2313
+ /**
2314
+ * Source for Widget API requests.
2315
+ *
2316
+ * Abstract class. Use {@link WidgetQuerySource} or {@link WidgetTableSource}.
2317
+ */
2318
+ class WidgetRemoteSource extends WidgetSource {
996
2319
  async getCategories(options) {
997
2320
  const {
2321
+ signal,
2322
+ filters = this.props.filters,
998
2323
  filterOwner,
999
2324
  spatialFilter,
1000
2325
  spatialFiltersMode,
1001
- spatialIndexReferenceViewState,
1002
- abortController
2326
+ spatialIndexReferenceViewState
1003
2327
  } = options,
1004
2328
  params = _objectWithoutPropertiesLoose(options, _excluded);
1005
2329
  const {
@@ -1007,7 +2331,7 @@ class WidgetBaseSource {
1007
2331
  operation,
1008
2332
  operationColumn
1009
2333
  } = params;
1010
- const source = this.getModelSource(filterOwner);
2334
+ const source = this.getModelSource(filters, filterOwner);
1011
2335
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1012
2336
  return executeModel({
1013
2337
  model: 'category',
@@ -1022,28 +2346,20 @@ class WidgetBaseSource {
1022
2346
  operationColumn: operationColumn || column
1023
2347
  },
1024
2348
  opts: {
1025
- abortController
2349
+ signal,
2350
+ headers: this.props.headers
1026
2351
  }
1027
2352
  }).then(res => normalizeObjectKeys(res.rows));
1028
2353
  }
1029
- /****************************************************************************
1030
- * FEATURES
1031
- */
1032
- /**
1033
- * Given a list of feature IDs (as found in `_carto_feature_id`) returns all
1034
- * matching features. In datasets containing features with duplicate geometries,
1035
- * feature IDs may be duplicated (IDs are a hash of geometry) and so more
1036
- * results may be returned than IDs in the request.
1037
- * @internal
1038
- * @experimental
1039
- */
1040
2354
  async getFeatures(options) {
1041
2355
  const {
2356
+ abortController,
2357
+ signal = abortController == null ? void 0 : abortController.signal,
2358
+ filters = this.props.filters,
1042
2359
  filterOwner,
1043
2360
  spatialFilter,
1044
2361
  spatialFiltersMode,
1045
- spatialIndexReferenceViewState,
1046
- abortController
2362
+ spatialIndexReferenceViewState
1047
2363
  } = options,
1048
2364
  params = _objectWithoutPropertiesLoose(options, _excluded2);
1049
2365
  const {
@@ -1054,7 +2370,7 @@ class WidgetBaseSource {
1054
2370
  limit,
1055
2371
  tileResolution
1056
2372
  } = params;
1057
- const source = this.getModelSource(filterOwner);
2373
+ const source = this.getModelSource(filters, filterOwner);
1058
2374
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1059
2375
  return executeModel({
1060
2376
  model: 'pick',
@@ -1072,7 +2388,8 @@ class WidgetBaseSource {
1072
2388
  tileResolution: tileResolution || DEFAULT_TILE_RESOLUTION
1073
2389
  },
1074
2390
  opts: {
1075
- abortController
2391
+ signal,
2392
+ headers: this.props.headers
1076
2393
  }
1077
2394
  // Avoid `normalizeObjectKeys()`, which changes column names.
1078
2395
  }).then(({
@@ -1081,20 +2398,15 @@ class WidgetBaseSource {
1081
2398
  rows
1082
2399
  }));
1083
2400
  }
1084
- /****************************************************************************
1085
- * FORMULA
1086
- */
1087
- /**
1088
- * Returns a scalar numerical statistic over all matching data. Suitable
1089
- * for 'headline' or 'scorecard' figures such as counts and sums.
1090
- */
1091
2401
  async getFormula(options) {
1092
2402
  const {
2403
+ abortController,
2404
+ signal = abortController == null ? void 0 : abortController.signal,
2405
+ filters = this.props.filters,
1093
2406
  filterOwner,
1094
2407
  spatialFilter,
1095
2408
  spatialFiltersMode,
1096
2409
  spatialIndexReferenceViewState,
1097
- abortController,
1098
2410
  operationExp
1099
2411
  } = options,
1100
2412
  params = _objectWithoutPropertiesLoose(options, _excluded3);
@@ -1102,7 +2414,7 @@ class WidgetBaseSource {
1102
2414
  column,
1103
2415
  operation
1104
2416
  } = params;
1105
- const source = this.getModelSource(filterOwner);
2417
+ const source = this.getModelSource(filters, filterOwner);
1106
2418
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1107
2419
  return executeModel({
1108
2420
  model: 'formula',
@@ -1113,28 +2425,24 @@ class WidgetBaseSource {
1113
2425
  }),
1114
2426
  params: {
1115
2427
  column: column != null ? column : '*',
1116
- operation,
2428
+ operation: operation != null ? operation : 'count',
1117
2429
  operationExp
1118
2430
  },
1119
2431
  opts: {
1120
- abortController
2432
+ signal,
2433
+ headers: this.props.headers
1121
2434
  }
1122
2435
  }).then(res => normalizeObjectKeys(res.rows[0]));
1123
2436
  }
1124
- /****************************************************************************
1125
- * HISTOGRAM
1126
- */
1127
- /**
1128
- * Returns a list of labeled datapoints for 'bins' of data defined as ticks
1129
- * over a numerical range. Suitable for histogram charts.
1130
- */
1131
2437
  async getHistogram(options) {
1132
2438
  const {
2439
+ abortController,
2440
+ signal = abortController == null ? void 0 : abortController.signal,
2441
+ filters = this.props.filters,
1133
2442
  filterOwner,
1134
2443
  spatialFilter,
1135
2444
  spatialFiltersMode,
1136
- spatialIndexReferenceViewState,
1137
- abortController
2445
+ spatialIndexReferenceViewState
1138
2446
  } = options,
1139
2447
  params = _objectWithoutPropertiesLoose(options, _excluded4);
1140
2448
  const {
@@ -1142,7 +2450,7 @@ class WidgetBaseSource {
1142
2450
  operation,
1143
2451
  ticks
1144
2452
  } = params;
1145
- const source = this.getModelSource(filterOwner);
2453
+ const source = this.getModelSource(filters, filterOwner);
1146
2454
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1147
2455
  const data = await executeModel({
1148
2456
  model: 'histogram',
@@ -1157,7 +2465,8 @@ class WidgetBaseSource {
1157
2465
  ticks
1158
2466
  },
1159
2467
  opts: {
1160
- abortController
2468
+ signal,
2469
+ headers: this.props.headers
1161
2470
  }
1162
2471
  }).then(res => normalizeObjectKeys(res.rows));
1163
2472
  if (data.length) {
@@ -1172,27 +2481,21 @@ class WidgetBaseSource {
1172
2481
  }
1173
2482
  return [];
1174
2483
  }
1175
- /****************************************************************************
1176
- * RANGE
1177
- */
1178
- /**
1179
- * Returns a range (min and max) for a numerical column of matching rows.
1180
- * Suitable for displaying certain 'headline' or 'scorecard' statistics,
1181
- * or rendering a range slider UI for filtering.
1182
- */
1183
2484
  async getRange(options) {
1184
2485
  const {
2486
+ abortController,
2487
+ signal = abortController == null ? void 0 : abortController.signal,
2488
+ filters = this.props.filters,
1185
2489
  filterOwner,
1186
2490
  spatialFilter,
1187
2491
  spatialFiltersMode,
1188
- spatialIndexReferenceViewState,
1189
- abortController
2492
+ spatialIndexReferenceViewState
1190
2493
  } = options,
1191
2494
  params = _objectWithoutPropertiesLoose(options, _excluded5);
1192
2495
  const {
1193
2496
  column
1194
2497
  } = params;
1195
- const source = this.getModelSource(filterOwner);
2498
+ const source = this.getModelSource(filters, filterOwner);
1196
2499
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1197
2500
  return executeModel({
1198
2501
  model: 'range',
@@ -1205,24 +2508,20 @@ class WidgetBaseSource {
1205
2508
  column
1206
2509
  },
1207
2510
  opts: {
1208
- abortController
2511
+ signal,
2512
+ headers: this.props.headers
1209
2513
  }
1210
2514
  }).then(res => normalizeObjectKeys(res.rows[0]));
1211
2515
  }
1212
- /****************************************************************************
1213
- * SCATTER
1214
- */
1215
- /**
1216
- * Returns a list of bivariate datapoints defined as numerical 'x' and 'y'
1217
- * values. Suitable for rendering scatter plots.
1218
- */
1219
2516
  async getScatter(options) {
1220
2517
  const {
2518
+ abortController,
2519
+ signal = abortController == null ? void 0 : abortController.signal,
2520
+ filters = this.props.filters,
1221
2521
  filterOwner,
1222
2522
  spatialFilter,
1223
2523
  spatialFiltersMode,
1224
- spatialIndexReferenceViewState,
1225
- abortController
2524
+ spatialIndexReferenceViewState
1226
2525
  } = options,
1227
2526
  params = _objectWithoutPropertiesLoose(options, _excluded6);
1228
2527
  const {
@@ -1231,7 +2530,7 @@ class WidgetBaseSource {
1231
2530
  yAxisColumn,
1232
2531
  yAxisJoinOperation
1233
2532
  } = params;
1234
- const source = this.getModelSource(filterOwner);
2533
+ const source = this.getModelSource(filters, filterOwner);
1235
2534
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1236
2535
  // Make sure this is sync with the same constant in cloud-native/maps-api
1237
2536
  const HARD_LIMIT = 500;
@@ -1250,27 +2549,23 @@ class WidgetBaseSource {
1250
2549
  limit: HARD_LIMIT
1251
2550
  },
1252
2551
  opts: {
1253
- abortController
2552
+ signal,
2553
+ headers: this.props.headers
1254
2554
  }
1255
2555
  }).then(res => normalizeObjectKeys(res.rows)).then(res => res.map(({
1256
2556
  x,
1257
2557
  y
1258
2558
  }) => [x, y]));
1259
2559
  }
1260
- /****************************************************************************
1261
- * TABLE
1262
- */
1263
- /**
1264
- * Returns a list of arbitrary data rows, with support for pagination and
1265
- * sorting. Suitable for displaying tables and lists.
1266
- */
1267
2560
  async getTable(options) {
1268
2561
  const {
2562
+ abortController,
2563
+ signal = abortController == null ? void 0 : abortController.signal,
2564
+ filters = this.props.filters,
1269
2565
  filterOwner,
1270
2566
  spatialFilter,
1271
2567
  spatialFiltersMode,
1272
- spatialIndexReferenceViewState,
1273
- abortController
2568
+ spatialIndexReferenceViewState
1274
2569
  } = options,
1275
2570
  params = _objectWithoutPropertiesLoose(options, _excluded7);
1276
2571
  const {
@@ -1280,7 +2575,7 @@ class WidgetBaseSource {
1280
2575
  offset = 0,
1281
2576
  limit = 10
1282
2577
  } = params;
1283
- const source = this.getModelSource(filterOwner);
2578
+ const source = this.getModelSource(filters, filterOwner);
1284
2579
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1285
2580
  return executeModel({
1286
2581
  model: 'table',
@@ -1297,7 +2592,8 @@ class WidgetBaseSource {
1297
2592
  offset
1298
2593
  },
1299
2594
  opts: {
1300
- abortController
2595
+ signal,
2596
+ headers: this.props.headers
1301
2597
  }
1302
2598
  }).then(res => {
1303
2599
  var _res$rows, _res$metadata$total, _res$metadata, _res$METADATA;
@@ -1308,17 +2604,12 @@ class WidgetBaseSource {
1308
2604
  };
1309
2605
  });
1310
2606
  }
1311
- /****************************************************************************
1312
- * TIME SERIES
1313
- */
1314
- /**
1315
- * Returns a series of labeled numerical values, grouped into equally-sized
1316
- * time intervals. Suitable for rendering time series charts.
1317
- */
1318
2607
  async getTimeSeries(options) {
1319
2608
  const {
1320
- filterOwner,
1321
2609
  abortController,
2610
+ signal = abortController == null ? void 0 : abortController.signal,
2611
+ filters = this.props.filters,
2612
+ filterOwner,
1322
2613
  spatialFilter,
1323
2614
  spatialFiltersMode,
1324
2615
  spatialIndexReferenceViewState
@@ -1335,7 +2626,7 @@ class WidgetBaseSource {
1335
2626
  splitByCategoryLimit,
1336
2627
  splitByCategoryValues
1337
2628
  } = params;
1338
- const source = this.getModelSource(filterOwner);
2629
+ const source = this.getModelSource(filters, filterOwner);
1339
2630
  const spatialFiltersResolution = this._getSpatialFiltersResolution(source, spatialFilter, spatialIndexReferenceViewState);
1340
2631
  return executeModel({
1341
2632
  model: 'timeseries',
@@ -1356,7 +2647,8 @@ class WidgetBaseSource {
1356
2647
  splitByCategoryValues
1357
2648
  },
1358
2649
  opts: {
1359
- abortController
2650
+ signal,
2651
+ headers: this.props.headers
1360
2652
  }
1361
2653
  }).then(res => {
1362
2654
  var _res$metadata2;
@@ -1367,13 +2659,6 @@ class WidgetBaseSource {
1367
2659
  });
1368
2660
  }
1369
2661
  }
1370
- WidgetBaseSource.defaultProps = {
1371
- apiVersion: ApiVersion.V3,
1372
- apiBaseUrl: DEFAULT_API_BASE_URL,
1373
- clientId: getClient(),
1374
- filters: {},
1375
- filtersLogicalOperator: 'and'
1376
- };
1377
2662
 
1378
2663
  /**
1379
2664
  * Source for Widget API requests on a data source defined by a SQL query.
@@ -1397,9 +2682,9 @@ WidgetBaseSource.defaultProps = {
1397
2682
  * const { widgetSource } = await data;
1398
2683
  * ```
1399
2684
  */
1400
- class WidgetQuerySource extends WidgetBaseSource {
1401
- getModelSource(owner) {
1402
- return _extends({}, super._getModelSource(owner), {
2685
+ class WidgetQuerySource extends WidgetRemoteSource {
2686
+ getModelSource(filters, filterOwner) {
2687
+ return _extends({}, super._getModelSource(filters, filterOwner), {
1403
2688
  type: 'query',
1404
2689
  data: this.props.sqlQuery,
1405
2690
  queryParameters: this.props.queryParameters
@@ -1429,15 +2714,706 @@ class WidgetQuerySource extends WidgetBaseSource {
1429
2714
  * const { widgetSource } = await data;
1430
2715
  * ```
1431
2716
  */
1432
- class WidgetTableSource extends WidgetBaseSource {
1433
- getModelSource(owner) {
1434
- return _extends({}, super._getModelSource(owner), {
2717
+ class WidgetTableSource extends WidgetRemoteSource {
2718
+ getModelSource(filters, filterOwner) {
2719
+ return _extends({}, super._getModelSource(filters, filterOwner), {
1435
2720
  type: 'table',
1436
2721
  data: this.props.tableName
1437
2722
  });
1438
2723
  }
1439
2724
  }
1440
2725
 
2726
+ /** @privateRemarks Source: @carto/react-core */
2727
+ const aggregationFunctions = {
2728
+ count: values => values.length,
2729
+ min: (...args) => applyAggregationFunction(min, ...args),
2730
+ max: (...args) => applyAggregationFunction(max, ...args),
2731
+ sum: (...args) => applyAggregationFunction(sum, ...args),
2732
+ avg: (...args) => applyAggregationFunction(avg, ...args)
2733
+ };
2734
+ /** @privateRemarks Source: @carto/react-core */
2735
+ function aggregate(feature, keys, operation) {
2736
+ if (!(keys != null && keys.length)) {
2737
+ throw new Error('Cannot aggregate a feature without having keys');
2738
+ } else if (keys.length === 1) {
2739
+ const value = feature[keys[0]];
2740
+ return isPotentiallyValidNumber(value) ? Number(value) : value;
2741
+ }
2742
+ const aggregationFn = aggregationFunctions[operation];
2743
+ if (!aggregationFn) {
2744
+ throw new Error(`${operation} isn't a valid aggregation function`);
2745
+ }
2746
+ return aggregationFn(keys.map(column => {
2747
+ const value = feature[column];
2748
+ return isPotentiallyValidNumber(value) ? Number(value) : value;
2749
+ }));
2750
+ }
2751
+ /*
2752
+ * Forced casting to Number (just of non empty strings) allows to work-around
2753
+ * some specific situations, where a big numeric field is transformed into a string when generating the tileset(eg.PG)
2754
+ */
2755
+ function isPotentiallyValidNumber(value) {
2756
+ return typeof value === 'string' && value.trim().length > 0;
2757
+ }
2758
+ const applyAggregationFunction = (aggFn, values, keys, operation) => {
2759
+ const normalizedKeys = normalizeKeys(keys);
2760
+ const elements = ((normalizedKeys == null ? void 0 : normalizedKeys.length) || 0) <= 1 ? filterFalsyElements(values, normalizedKeys || []) : values;
2761
+ return aggFn(elements, keys, operation);
2762
+ };
2763
+ function filterFalsyElements(values, keys) {
2764
+ const filterFn = value => value !== null && value !== undefined;
2765
+ if (!(keys != null && keys.length)) {
2766
+ return values.filter(filterFn);
2767
+ }
2768
+ return values.filter(v => filterFn(v[keys[0]]));
2769
+ }
2770
+ // Aggregation functions
2771
+ function avg(values, keys, joinOperation) {
2772
+ return sum(values, keys, joinOperation) / (values.length || 1);
2773
+ }
2774
+ function sum(values, keys, joinOperation) {
2775
+ const normalizedKeys = normalizeKeys(keys);
2776
+ if (normalizedKeys) {
2777
+ return values.reduce((a, b) => a + aggregate(b, normalizedKeys, joinOperation), 0);
2778
+ }
2779
+ return values.reduce((a, b) => a + b, 0);
2780
+ }
2781
+ function min(values, keys, joinOperation) {
2782
+ const normalizedKeys = normalizeKeys(keys);
2783
+ if (normalizedKeys) {
2784
+ return values.reduce((a, b) => Math.min(a, aggregate(b, normalizedKeys, joinOperation)), Infinity);
2785
+ }
2786
+ return Math.min(...values);
2787
+ }
2788
+ function max(values, keys, joinOperation) {
2789
+ const normalizedKeys = normalizeKeys(keys);
2790
+ if (normalizedKeys) {
2791
+ return values.reduce((a, b) => Math.max(a, aggregate(b, normalizedKeys, joinOperation)), -Infinity);
2792
+ }
2793
+ return Math.max(...values);
2794
+ }
2795
+ // Aux
2796
+ // Keys can come as a string (one column) or a strings array (multiple column)
2797
+ // Use always an array to make the code easier
2798
+ function normalizeKeys(keys) {
2799
+ return Array.isArray(keys) ? keys : typeof keys === 'string' ? [keys] : undefined;
2800
+ }
2801
+
2802
+ /***
2803
+ Copyright 2013 Teun Duynstee
2804
+
2805
+ Licensed under the Apache License, Version 2.0 (the "License");
2806
+ you may not use this file except in compliance with the License.
2807
+ You may obtain a copy of the License at
2808
+
2809
+ http://www.apache.org/licenses/LICENSE-2.0
2810
+
2811
+ Unless required by applicable law or agreed to in writing, software
2812
+ distributed under the License is distributed on an "AS IS" BASIS,
2813
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2814
+ See the License for the specific language governing permissions and
2815
+ limitations under the License.
2816
+ */
2817
+ var thenBy_module = function () {
2818
+ function identity(v) {
2819
+ return v;
2820
+ }
2821
+ function ignoreCase(v) {
2822
+ return typeof v === "string" ? v.toLowerCase() : v;
2823
+ }
2824
+ function makeCompareFunction(f, opt) {
2825
+ opt = typeof opt === "object" ? opt : {
2826
+ direction: opt
2827
+ };
2828
+ if (typeof f != "function") {
2829
+ var prop = f;
2830
+ // make unary function
2831
+ f = function (v1) {
2832
+ return !!v1[prop] ? v1[prop] : "";
2833
+ };
2834
+ }
2835
+ if (f.length === 1) {
2836
+ // f is a unary function mapping a single item to its sort score
2837
+ var uf = f;
2838
+ var preprocess = opt.ignoreCase ? ignoreCase : identity;
2839
+ var cmp = opt.cmp || function (v1, v2) {
2840
+ return v1 < v2 ? -1 : v1 > v2 ? 1 : 0;
2841
+ };
2842
+ f = function (v1, v2) {
2843
+ return cmp(preprocess(uf(v1)), preprocess(uf(v2)));
2844
+ };
2845
+ }
2846
+ const descTokens = {
2847
+ "-1": '',
2848
+ desc: ''
2849
+ };
2850
+ if (opt.direction in descTokens) return function (v1, v2) {
2851
+ return -f(v1, v2);
2852
+ };
2853
+ return f;
2854
+ }
2855
+
2856
+ /* adds a secondary compare function to the target function (`this` context)
2857
+ which is applied in case the first one returns 0 (equal)
2858
+ returns a new compare function, which has a `thenBy` method as well */
2859
+ function tb(func, opt) {
2860
+ /* should get value false for the first call. This can be done by calling the
2861
+ exported function, or the firstBy property on it (for es6 module compatibility)
2862
+ */
2863
+ var x = typeof this == "function" && !this.firstBy ? this : false;
2864
+ var y = makeCompareFunction(func, opt);
2865
+ var f = x ? function (a, b) {
2866
+ return x(a, b) || y(a, b);
2867
+ } : y;
2868
+ f.thenBy = tb;
2869
+ return f;
2870
+ }
2871
+ tb.firstBy = tb;
2872
+ return tb;
2873
+ }();
2874
+
2875
+ /**
2876
+ * Apply sort structure to a collection of features
2877
+ * @param features
2878
+ * @param [sortOptions]
2879
+ * @param [sortOptions.sortBy] - One or more columns to sort by
2880
+ * @param [sortOptions.sortByDirection] - Direction by the columns will be sorted
2881
+ * @param [sortOptions.sortByColumnType] - Column type
2882
+ * @internal
2883
+ * @privateRemarks Source: @carto/react-core
2884
+ */
2885
+ function applySorting(features, {
2886
+ sortBy,
2887
+ sortByDirection = 'asc',
2888
+ sortByColumnType = 'string'
2889
+ } = {}) {
2890
+ // If sortBy is undefined, pass all features
2891
+ if (sortBy === undefined) {
2892
+ return features;
2893
+ }
2894
+ // sortOptions exists, but are bad formatted
2895
+ const isValidSortBy = Array.isArray(sortBy) && sortBy.length ||
2896
+ // sortBy can be an array of columns
2897
+ typeof sortBy === 'string'; // or just one column
2898
+ if (!isValidSortBy) {
2899
+ throw new Error('Sorting options are bad formatted');
2900
+ }
2901
+ const sortFn = createSortFn({
2902
+ sortBy,
2903
+ sortByDirection,
2904
+ sortByColumnType: sortByColumnType || 'string'
2905
+ });
2906
+ return features.sort(sortFn);
2907
+ }
2908
+ // Aux
2909
+ function createSortFn({
2910
+ sortBy,
2911
+ sortByDirection,
2912
+ sortByColumnType
2913
+ }) {
2914
+ const [firstSortOption, ...othersSortOptions] = normalizeSortByOptions({
2915
+ sortBy,
2916
+ sortByDirection,
2917
+ sortByColumnType
2918
+ });
2919
+ let sortFn = thenBy_module.firstBy(...firstSortOption);
2920
+ for (const sortOptions of othersSortOptions) {
2921
+ sortFn = sortFn.thenBy(...sortOptions);
2922
+ }
2923
+ return sortFn;
2924
+ }
2925
+ function normalizeSortByOptions({
2926
+ sortBy,
2927
+ sortByDirection,
2928
+ sortByColumnType
2929
+ }) {
2930
+ const numberFormat = sortByColumnType === 'number' && {
2931
+ cmp: (a, b) => a - b
2932
+ };
2933
+ if (!Array.isArray(sortBy)) {
2934
+ sortBy = [sortBy];
2935
+ }
2936
+ return sortBy.map(sortByEl => {
2937
+ // sortByEl is 'column'
2938
+ if (typeof sortByEl === 'string') {
2939
+ return [sortByEl, _extends({
2940
+ direction: sortByDirection
2941
+ }, numberFormat)];
2942
+ }
2943
+ if (Array.isArray(sortByEl)) {
2944
+ // sortBy is ['column']
2945
+ if (sortByEl[1] === undefined) {
2946
+ return [sortByEl, _extends({
2947
+ direction: sortByDirection
2948
+ }, numberFormat)];
2949
+ }
2950
+ // sortBy is ['column', { ... }]
2951
+ if (typeof sortByEl[1] === 'object') {
2952
+ const othersSortOptions = numberFormat ? _extends({}, numberFormat, sortByEl[1]) : sortByEl[1];
2953
+ return [sortByEl[0], _extends({
2954
+ direction: sortByDirection
2955
+ }, othersSortOptions)];
2956
+ }
2957
+ }
2958
+ return sortByEl;
2959
+ });
2960
+ }
2961
+
2962
+ /** @privateRemarks Source: @carto/react-core */
2963
+ function groupValuesByColumn({
2964
+ data,
2965
+ valuesColumns,
2966
+ joinOperation,
2967
+ keysColumn,
2968
+ operation
2969
+ }) {
2970
+ if (Array.isArray(data) && data.length === 0) {
2971
+ return null;
2972
+ }
2973
+ const groups = data.reduce((accumulator, item) => {
2974
+ const group = item[keysColumn];
2975
+ const values = accumulator.get(group) || [];
2976
+ accumulator.set(group, values);
2977
+ const aggregatedValue = aggregate(item, valuesColumns, joinOperation);
2978
+ const isValid = (operation === 'count' ? true : aggregatedValue !== null) && aggregatedValue !== undefined;
2979
+ if (isValid) {
2980
+ values.push(aggregatedValue);
2981
+ accumulator.set(group, values);
2982
+ }
2983
+ return accumulator;
2984
+ }, new Map()); // We use a map to be able to maintain the type in the key value
2985
+ const targetOperation = aggregationFunctions[operation];
2986
+ if (targetOperation) {
2987
+ return Array.from(groups).map(([name, value]) => ({
2988
+ name,
2989
+ value: targetOperation(value)
2990
+ }));
2991
+ }
2992
+ return [];
2993
+ }
2994
+
2995
+ /**
2996
+ * Returns midnight (local time) on the Monday preceeding a given date, in
2997
+ * milliseconds since the UNIX epoch.
2998
+ */
2999
+ /**
3000
+ * Returns midnight (UTC) on the Monday preceeding a given date, in
3001
+ * milliseconds since the UNIX epoch.
3002
+ */
3003
+ function getUTCMonday(date) {
3004
+ const dateCp = new Date(date);
3005
+ const day = dateCp.getUTCDay();
3006
+ const diff = dateCp.getUTCDate() - day + (day ? 1 : -6); // adjust when day is sunday
3007
+ dateCp.setUTCDate(diff);
3008
+ return Date.UTC(dateCp.getUTCFullYear(), dateCp.getUTCMonth(), dateCp.getUTCDate());
3009
+ }
3010
+
3011
+ const GROUP_KEY_FN_MAPPING = {
3012
+ year: date => Date.UTC(date.getUTCFullYear()),
3013
+ month: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth()),
3014
+ week: date => getUTCMonday(date),
3015
+ day: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()),
3016
+ hour: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours()),
3017
+ minute: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes()),
3018
+ second: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds())
3019
+ };
3020
+ /** @privateRemarks Source: @carto/react-core */
3021
+ function groupValuesByDateColumn({
3022
+ data,
3023
+ valuesColumns,
3024
+ joinOperation,
3025
+ keysColumn,
3026
+ groupType,
3027
+ operation
3028
+ }) {
3029
+ if (Array.isArray(data) && data.length === 0) {
3030
+ return null;
3031
+ }
3032
+ const groupKeyFn = GROUP_KEY_FN_MAPPING[groupType];
3033
+ if (!groupKeyFn) {
3034
+ return null;
3035
+ }
3036
+ const groups = data.reduce((acc, item) => {
3037
+ const value = item[keysColumn];
3038
+ const formattedValue = new Date(value);
3039
+ const groupKey = groupKeyFn(formattedValue);
3040
+ if (!isNaN(groupKey)) {
3041
+ let groupedValues = acc.get(groupKey);
3042
+ if (!groupedValues) {
3043
+ groupedValues = [];
3044
+ acc.set(groupKey, groupedValues);
3045
+ }
3046
+ const aggregatedValue = aggregate(item, valuesColumns, joinOperation);
3047
+ const isValid = aggregatedValue !== null && aggregatedValue !== undefined;
3048
+ if (isValid) {
3049
+ groupedValues.push(aggregatedValue);
3050
+ acc.set(groupKey, groupedValues);
3051
+ }
3052
+ }
3053
+ return acc;
3054
+ }, new Map());
3055
+ const targetOperation = aggregationFunctions[operation];
3056
+ return [...groups.entries()].map(([name, value]) => ({
3057
+ name,
3058
+ value: targetOperation(value)
3059
+ })).sort((a, b) => a.name - b.name);
3060
+ }
3061
+
3062
+ /**
3063
+ * Histogram computation.
3064
+ * @privateRemarks Source: @carto/react-core
3065
+ */
3066
+ function histogram({
3067
+ data,
3068
+ valuesColumns,
3069
+ joinOperation,
3070
+ ticks,
3071
+ operation
3072
+ }) {
3073
+ if (Array.isArray(data) && data.length === 0) {
3074
+ return [];
3075
+ }
3076
+ const binsContainer = [Number.MIN_SAFE_INTEGER, ...ticks].map((tick, index, arr) => ({
3077
+ bin: index,
3078
+ start: tick,
3079
+ end: index === arr.length - 1 ? Number.MAX_SAFE_INTEGER : arr[index + 1],
3080
+ values: []
3081
+ }));
3082
+ data.forEach(feature => {
3083
+ const featureValue = aggregate(feature, valuesColumns, joinOperation);
3084
+ const isValid = featureValue !== null && featureValue !== undefined;
3085
+ if (!isValid) {
3086
+ return;
3087
+ }
3088
+ const binContainer = binsContainer.find(bin => bin.start <= featureValue && bin.end > featureValue);
3089
+ if (!binContainer) {
3090
+ return;
3091
+ }
3092
+ binContainer.values.push(featureValue);
3093
+ });
3094
+ const targetOperation = aggregationFunctions[operation];
3095
+ const transformedBins = binsContainer.map(binContainer => binContainer.values);
3096
+ return transformedBins.map(values => values.length ? targetOperation(values) : 0);
3097
+ }
3098
+
3099
+ /**
3100
+ * Filters invalid features and formats data.
3101
+ * @privateRemarks Source: @carto/react-core
3102
+ */
3103
+ function scatterPlot({
3104
+ data,
3105
+ xAxisColumns,
3106
+ xAxisJoinOperation,
3107
+ yAxisColumns,
3108
+ yAxisJoinOperation
3109
+ }) {
3110
+ return data.reduce((acc, feature) => {
3111
+ const xValue = aggregate(feature, xAxisColumns, xAxisJoinOperation);
3112
+ const xIsValid = xValue !== null && xValue !== undefined;
3113
+ const yValue = aggregate(feature, yAxisColumns, yAxisJoinOperation);
3114
+ const yIsValid = yValue !== null && yValue !== undefined;
3115
+ if (xIsValid && yIsValid) {
3116
+ acc.push([xValue, yValue]);
3117
+ }
3118
+ return acc;
3119
+ }, []);
3120
+ }
3121
+
3122
+ /**
3123
+ * Source for Widget API requests on a data source defined by a tileset.
3124
+ *
3125
+ * Generally not intended to be constructed directly. Instead, call
3126
+ * {@link vectorTilesetSource}, {@link h3TilesetSource}, or {@link quadbinTilesetSource},
3127
+ * which can be shared with map layers. Sources contain a `widgetSource`
3128
+ * property, for use by widget implementations.
3129
+ *
3130
+ * Example:
3131
+ *
3132
+ * ```javascript
3133
+ * import { vectorTilesetSource } from '@carto/api-client';
3134
+ *
3135
+ * const data = vectorTilesetSource({
3136
+ * accessToken: '••••',
3137
+ * connectionName: 'carto_dw',
3138
+ * tableName: 'carto-demo-data.demo_rasters.my_tileset_source'
3139
+ * });
3140
+ *
3141
+ * const { widgetSource } = await data;
3142
+ * ```
3143
+ */
3144
+ class WidgetTilesetSource extends WidgetSource {
3145
+ constructor(...args) {
3146
+ super(...args);
3147
+ this._tiles = [];
3148
+ this._features = [];
3149
+ this._tileFeatureExtractOptions = {};
3150
+ this._tileFeatureExtractPreviousInputs = {};
3151
+ }
3152
+ getModelSource(filters, filterOwner) {
3153
+ return _extends({}, super._getModelSource(filters, filterOwner), {
3154
+ type: 'tileset',
3155
+ data: this.props.tableName
3156
+ });
3157
+ }
3158
+ /**
3159
+ * Loads features as a list of tiles (typically provided by deck.gl).
3160
+ * After tiles are loaded, {@link extractTileFeatures} must be called
3161
+ * before computing statistics on the tiles.
3162
+ */
3163
+ loadTiles(tiles) {
3164
+ this._tiles = tiles;
3165
+ this._features.length = 0;
3166
+ }
3167
+ /** Configures options used to extract features from tiles. */
3168
+ setTileFeatureExtractOptions(options) {
3169
+ this._tileFeatureExtractOptions = options;
3170
+ this._features.length = 0;
3171
+ }
3172
+ _extractTileFeatures(spatialFilter) {
3173
+ // When spatial filter has not changed, don't redo extraction. If tiles or
3174
+ // tile extract options change, features will have been cleared already.
3175
+ const prevInputs = this._tileFeatureExtractPreviousInputs;
3176
+ if (this._features.length && prevInputs.spatialFilter && booleanEqual(prevInputs.spatialFilter, spatialFilter)) {
3177
+ return;
3178
+ }
3179
+ this._features = tileFeatures(_extends({
3180
+ tiles: this._tiles,
3181
+ tileFormat: this.props.tileFormat
3182
+ }, this._tileFeatureExtractOptions, {
3183
+ spatialFilter,
3184
+ spatialDataColumn: this.props.spatialDataColumn,
3185
+ spatialDataType: this.props.spatialDataType
3186
+ }));
3187
+ prevInputs.spatialFilter = spatialFilter;
3188
+ }
3189
+ /**
3190
+ * Loads features as GeoJSON (used for testing).
3191
+ * @experimental
3192
+ * @internal Not for public use. Spatial filters in other method calls will be ignored.
3193
+ */
3194
+ loadGeoJSON({
3195
+ geojson,
3196
+ spatialFilter
3197
+ }) {
3198
+ this._features = geojsonFeatures(_extends({
3199
+ geojson,
3200
+ spatialFilter
3201
+ }, this._tileFeatureExtractOptions));
3202
+ this._tileFeatureExtractPreviousInputs.spatialFilter = spatialFilter;
3203
+ }
3204
+ async getFeatures() {
3205
+ throw new Error('getFeatures not supported for tilesets');
3206
+ }
3207
+ async getFormula({
3208
+ column = '*',
3209
+ operation = 'count',
3210
+ joinOperation,
3211
+ filters,
3212
+ filterOwner,
3213
+ spatialFilter
3214
+ }) {
3215
+ if (operation === 'custom') {
3216
+ throw new Error('Custom aggregation not supported for tilesets');
3217
+ }
3218
+ // Column is required except when operation is 'count'.
3219
+ if (column && column !== '*' || operation !== 'count') {
3220
+ assertColumn(this._features, column);
3221
+ }
3222
+ const filteredFeatures = this._getFilteredFeatures(spatialFilter, filters, filterOwner);
3223
+ if (filteredFeatures.length === 0 && operation !== 'count') {
3224
+ return {
3225
+ value: null
3226
+ };
3227
+ }
3228
+ const targetOperation = aggregationFunctions[operation];
3229
+ return {
3230
+ value: targetOperation(filteredFeatures, column, joinOperation)
3231
+ };
3232
+ }
3233
+ async getHistogram({
3234
+ operation = 'count',
3235
+ ticks,
3236
+ column,
3237
+ joinOperation,
3238
+ filters,
3239
+ filterOwner,
3240
+ spatialFilter
3241
+ }) {
3242
+ const filteredFeatures = this._getFilteredFeatures(spatialFilter, filters, filterOwner);
3243
+ assertColumn(this._features, column);
3244
+ if (!this._features.length) {
3245
+ return [];
3246
+ }
3247
+ return histogram({
3248
+ data: filteredFeatures,
3249
+ valuesColumns: normalizeColumns(column),
3250
+ joinOperation,
3251
+ ticks,
3252
+ operation
3253
+ });
3254
+ }
3255
+ async getCategories({
3256
+ column,
3257
+ operation = 'count',
3258
+ operationColumn,
3259
+ joinOperation,
3260
+ filters,
3261
+ filterOwner,
3262
+ spatialFilter
3263
+ }) {
3264
+ const filteredFeatures = this._getFilteredFeatures(spatialFilter, filters, filterOwner);
3265
+ if (!filteredFeatures.length) {
3266
+ return [];
3267
+ }
3268
+ assertColumn(this._features, column, operationColumn);
3269
+ const groups = groupValuesByColumn({
3270
+ data: filteredFeatures,
3271
+ valuesColumns: normalizeColumns(operationColumn || column),
3272
+ joinOperation,
3273
+ keysColumn: column,
3274
+ operation
3275
+ });
3276
+ return groups || [];
3277
+ }
3278
+ async getScatter({
3279
+ xAxisColumn,
3280
+ yAxisColumn,
3281
+ xAxisJoinOperation,
3282
+ yAxisJoinOperation,
3283
+ filters,
3284
+ filterOwner,
3285
+ spatialFilter
3286
+ }) {
3287
+ const filteredFeatures = this._getFilteredFeatures(spatialFilter, filters, filterOwner);
3288
+ if (!filteredFeatures.length) {
3289
+ return [];
3290
+ }
3291
+ assertColumn(this._features, xAxisColumn, yAxisColumn);
3292
+ return scatterPlot({
3293
+ data: filteredFeatures,
3294
+ xAxisColumns: normalizeColumns(xAxisColumn),
3295
+ xAxisJoinOperation,
3296
+ yAxisColumns: normalizeColumns(yAxisColumn),
3297
+ yAxisJoinOperation
3298
+ });
3299
+ }
3300
+ async getTable({
3301
+ columns,
3302
+ searchFilterColumn,
3303
+ searchFilterText,
3304
+ sortBy,
3305
+ sortDirection,
3306
+ sortByColumnType,
3307
+ offset = 0,
3308
+ limit = 10,
3309
+ filters,
3310
+ filterOwner,
3311
+ spatialFilter
3312
+ }) {
3313
+ // Filter.
3314
+ let filteredFeatures = this._getFilteredFeatures(spatialFilter, filters, filterOwner);
3315
+ if (!filteredFeatures.length) {
3316
+ return {
3317
+ rows: [],
3318
+ totalCount: 0
3319
+ };
3320
+ }
3321
+ // Search.
3322
+ if (searchFilterColumn && searchFilterText) {
3323
+ filteredFeatures = filteredFeatures.filter(row => row[searchFilterColumn] && String(row[searchFilterColumn]).toLowerCase().includes(String(searchFilterText).toLowerCase()));
3324
+ }
3325
+ // Sort.
3326
+ let rows = applySorting(filteredFeatures, {
3327
+ sortBy,
3328
+ sortByDirection: sortDirection,
3329
+ sortByColumnType
3330
+ });
3331
+ const totalCount = rows.length;
3332
+ // Offset and limit.
3333
+ rows = rows.slice(Math.min(offset, totalCount), Math.min(offset + limit, totalCount));
3334
+ // Select columns.
3335
+ rows = rows.map(srcRow => {
3336
+ const dstRow = {};
3337
+ for (const column of columns) {
3338
+ dstRow[column] = srcRow[column];
3339
+ }
3340
+ return dstRow;
3341
+ });
3342
+ return {
3343
+ rows,
3344
+ totalCount
3345
+ };
3346
+ }
3347
+ async getTimeSeries({
3348
+ column,
3349
+ stepSize,
3350
+ operation,
3351
+ operationColumn,
3352
+ joinOperation,
3353
+ filters,
3354
+ filterOwner,
3355
+ spatialFilter
3356
+ }) {
3357
+ const filteredFeatures = this._getFilteredFeatures(spatialFilter, filters, filterOwner);
3358
+ if (!filteredFeatures.length) {
3359
+ return {
3360
+ rows: []
3361
+ };
3362
+ }
3363
+ assertColumn(this._features, column, operationColumn);
3364
+ const rows = groupValuesByDateColumn({
3365
+ data: filteredFeatures,
3366
+ valuesColumns: normalizeColumns(operationColumn || column),
3367
+ keysColumn: column,
3368
+ groupType: stepSize,
3369
+ operation,
3370
+ joinOperation
3371
+ }) || [];
3372
+ return {
3373
+ rows
3374
+ };
3375
+ }
3376
+ async getRange({
3377
+ column,
3378
+ filters,
3379
+ filterOwner,
3380
+ spatialFilter
3381
+ }) {
3382
+ assertColumn(this._features, column);
3383
+ const filteredFeatures = this._getFilteredFeatures(spatialFilter, filters, filterOwner);
3384
+ if (!this._features.length) {
3385
+ // TODO: Is this the only nullable response in the Widgets API? If so,
3386
+ // can we do something more consistent?
3387
+ return null;
3388
+ }
3389
+ return {
3390
+ min: aggregationFunctions.min(filteredFeatures, column),
3391
+ max: aggregationFunctions.max(filteredFeatures, column)
3392
+ };
3393
+ }
3394
+ /****************************************************************************
3395
+ * INTERNAL
3396
+ */
3397
+ _getFilteredFeatures(spatialFilter, filters, filterOwner) {
3398
+ assert(spatialFilter, 'spatialFilter required for tilesets');
3399
+ this._extractTileFeatures(spatialFilter);
3400
+ return applyFilters(this._features, getApplicableFilters(filterOwner, filters || this.props.filters), this.props.filtersLogicalOperator || 'and');
3401
+ }
3402
+ }
3403
+ function assertColumn(features, ...columnArgs) {
3404
+ // TODO(cleanup): Can drop support for multiple column shapes here?
3405
+ // Due to the multiple column shape, we normalise it as an array with normalizeColumns
3406
+ const columns = Array.from(new Set(columnArgs.map(normalizeColumns).flat()));
3407
+ const featureKeys = Object.keys(features[0]);
3408
+ const invalidColumns = columns.filter(column => !featureKeys.includes(column));
3409
+ if (invalidColumns.length) {
3410
+ throw new InvalidColumnError(`Missing column(s): ${invalidColumns.join(', ')}`);
3411
+ }
3412
+ }
3413
+ function normalizeColumns(columns) {
3414
+ return Array.isArray(columns) ? columns : typeof columns === 'string' ? [columns] : [];
3415
+ }
3416
+
1441
3417
  const h3QuerySource = async function h3QuerySource(options) {
1442
3418
  const {
1443
3419
  aggregationExp,
@@ -1613,7 +3589,7 @@ const vectorQuerySource = async function vectorQuerySource(options) {
1613
3589
  const {
1614
3590
  columns,
1615
3591
  filters,
1616
- spatialDataColumn = 'geom',
3592
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
1617
3593
  sqlQuery,
1618
3594
  tileResolution = DEFAULT_TILE_RESOLUTION,
1619
3595
  queryParameters,
@@ -1652,7 +3628,7 @@ const vectorTableSource = async function vectorTableSource(options) {
1652
3628
  const {
1653
3629
  columns,
1654
3630
  filters,
1655
- spatialDataColumn = 'geom',
3631
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
1656
3632
  tableName,
1657
3633
  tileResolution = DEFAULT_TILE_RESOLUTION,
1658
3634
  aggregationExp
@@ -1738,5 +3714,5 @@ const query = async function query(options) {
1738
3714
  });
1739
3715
  };
1740
3716
 
1741
- export { ApiVersion, CartoAPIError, DEFAULT_API_BASE_URL, FilterType, SOURCE_DEFAULTS, WidgetBaseSource, WidgetQuerySource, WidgetTableSource, _getHexagonResolution, addFilter, boundaryQuerySource, boundaryTableSource, buildPublicMapUrl, buildStatsUrl, clearFilters, createPolygonSpatialFilter, createViewportSpatialFilter, getClient, getFilter, h3QuerySource, h3TableSource, h3TilesetSource, hasFilter, quadbinQuerySource, quadbinTableSource, quadbinTilesetSource, query, rasterSource, removeFilter, requestWithParameters, setClient, vectorQuerySource, vectorTableSource, vectorTilesetSource };
3717
+ export { ApiVersion, CartoAPIError, DEFAULT_API_BASE_URL, FEATURE_GEOM_PROPERTY, FilterType, Provider, SOURCE_DEFAULTS, SpatialIndex, TileFormat, WidgetQuerySource, WidgetRemoteSource, WidgetSource, WidgetTableSource, WidgetTilesetSource, _buildFeatureFilter, _getHexagonResolution, addFilter, aggregate, aggregationFunctions, applyFilters, applySorting, boundaryQuerySource, boundaryTableSource, buildBinaryFeatureFilter, buildPublicMapUrl, buildStatsUrl, clearFilters, createPolygonSpatialFilter, createViewportSpatialFilter, filterFunctions, geojsonFeatures, getClient, getDataFilterExtensionProps, getFilter, groupValuesByColumn, groupValuesByDateColumn, h3QuerySource, h3TableSource, h3TilesetSource, hasFilter, histogram, makeIntervalComplete, quadbinQuerySource, quadbinTableSource, quadbinTilesetSource, query, rasterSource, removeFilter, requestWithParameters, scatterPlot, setClient, tileFeatures, tileFeaturesGeometries, tileFeaturesSpatialIndex, transformToTileCoords, vectorQuerySource, vectorTableSource, vectorTilesetSource };
1742
3718
  //# sourceMappingURL=api-client.modern.js.map