@carto/api-client 0.4.5-alpha.0 → 0.4.6-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 (79) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/build/api-client.cjs +2179 -216
  3. package/build/api-client.cjs.map +1 -1
  4. package/build/api-client.modern.js +2061 -226
  5. package/build/api-client.modern.js.map +1 -1
  6. package/build/constants.d.ts +22 -0
  7. package/build/filters/Filter.d.ts +13 -0
  8. package/build/filters/FilterTypes.d.ts +3 -0
  9. package/build/filters/geosjonFeatures.d.ts +8 -0
  10. package/build/filters/index.d.ts +6 -0
  11. package/build/filters/tileFeatures.d.ts +20 -0
  12. package/build/filters/tileFeaturesGeometries.d.ts +13 -0
  13. package/build/filters/tileFeaturesSpatialIndex.d.ts +10 -0
  14. package/build/index.d.ts +4 -0
  15. package/build/models/index.d.ts +1 -1
  16. package/build/operations/aggregation.d.ts +8 -0
  17. package/build/operations/applySorting.d.ts +20 -0
  18. package/build/operations/groupBy.d.ts +15 -0
  19. package/build/operations/groupByDate.d.ts +11 -0
  20. package/build/operations/histogram.d.ts +13 -0
  21. package/build/operations/index.d.ts +6 -0
  22. package/build/operations/scatterPlot.d.ts +14 -0
  23. package/build/sources/h3-tileset-source.d.ts +2 -1
  24. package/build/sources/index.d.ts +2 -2
  25. package/build/sources/quadbin-tileset-source.d.ts +2 -1
  26. package/build/sources/vector-tileset-source.d.ts +2 -1
  27. package/build/types-internal.d.ts +4 -0
  28. package/build/types.d.ts +61 -1
  29. package/build/utils/dateUtils.d.ts +10 -0
  30. package/build/utils/getTileFormat.d.ts +3 -0
  31. package/build/utils/makeIntervalComplete.d.ts +2 -0
  32. package/build/utils/transformTileCoordsToWGS84.d.ts +8 -0
  33. package/build/utils/transformToTileCoords.d.ts +9 -0
  34. package/build/widget-sources/index.d.ts +3 -1
  35. package/build/widget-sources/types.d.ts +31 -22
  36. package/build/widget-sources/widget-query-source.d.ts +2 -2
  37. package/build/widget-sources/widget-remote-source.d.ts +18 -0
  38. package/build/widget-sources/{widget-base-source.d.ts → widget-source.d.ts} +13 -38
  39. package/build/widget-sources/widget-table-source.d.ts +2 -2
  40. package/build/widget-sources/widget-tileset-source.d.ts +76 -0
  41. package/package.json +9 -3
  42. package/src/constants.ts +25 -0
  43. package/src/filters/Filter.ts +169 -0
  44. package/src/filters/FilterTypes.ts +109 -0
  45. package/src/filters/geosjonFeatures.ts +32 -0
  46. package/src/filters/index.ts +6 -0
  47. package/src/filters/tileFeatures.ts +56 -0
  48. package/src/filters/tileFeaturesGeometries.ts +444 -0
  49. package/src/filters/tileFeaturesSpatialIndex.ts +119 -0
  50. package/src/index.ts +6 -0
  51. package/src/models/index.ts +1 -1
  52. package/src/operations/aggregation.ts +154 -0
  53. package/src/operations/applySorting.ts +109 -0
  54. package/src/operations/groupBy.ts +59 -0
  55. package/src/operations/groupByDate.ts +98 -0
  56. package/src/operations/histogram.ts +66 -0
  57. package/src/operations/index.ts +6 -0
  58. package/src/operations/scatterPlot.ts +50 -0
  59. package/src/sources/h3-tileset-source.ts +18 -6
  60. package/src/sources/index.ts +3 -1
  61. package/src/sources/quadbin-tileset-source.ts +18 -6
  62. package/src/sources/raster-source.ts +1 -0
  63. package/src/sources/vector-query-source.ts +5 -2
  64. package/src/sources/vector-table-source.ts +5 -2
  65. package/src/sources/vector-tileset-source.ts +19 -6
  66. package/src/types-internal.ts +6 -0
  67. package/src/types.ts +60 -2
  68. package/src/utils/dateUtils.ts +28 -0
  69. package/src/utils/getTileFormat.ts +9 -0
  70. package/src/utils/makeIntervalComplete.ts +17 -0
  71. package/src/utils/transformTileCoordsToWGS84.ts +77 -0
  72. package/src/utils/transformToTileCoords.ts +85 -0
  73. package/src/widget-sources/index.ts +3 -1
  74. package/src/widget-sources/types.ts +32 -22
  75. package/src/widget-sources/widget-query-source.ts +6 -3
  76. package/src/widget-sources/{widget-base-source.ts → widget-remote-source.ts} +12 -147
  77. package/src/widget-sources/widget-source.ts +160 -0
  78. package/src/widget-sources/widget-table-source.ts +6 -3
  79. package/src/widget-sources/widget-tileset-source.ts +407 -0
@@ -3,6 +3,10 @@ var bboxPolygon = require('@turf/bbox-polygon');
3
3
  var union = require('@turf/union');
4
4
  var invariant = require('@turf/invariant');
5
5
  var helpers = require('@turf/helpers');
6
+ var intersects = require('@turf/boolean-intersects');
7
+ var booleanWithin = require('@turf/boolean-within');
8
+ var intersect = require('@turf/intersect');
9
+ var h3Js = require('h3-js');
6
10
 
7
11
  /**
8
12
  * @internal
@@ -61,6 +65,31 @@ exports.ApiVersion = void 0;
61
65
  })(exports.ApiVersion || (exports.ApiVersion = {}));
62
66
  /** @internalRemarks Source: @carto/constants, @deck.gl/carto */
63
67
  const DEFAULT_API_BASE_URL = 'https://gcp-us-east1.api.carto.com';
68
+ /** @internalRemarks Source: @carto/react-core */
69
+ exports.TileFormat = void 0;
70
+ (function (TileFormat) {
71
+ TileFormat["MVT"] = "mvt";
72
+ TileFormat["JSON"] = "json";
73
+ TileFormat["GEOJSON"] = "geojson";
74
+ TileFormat["BINARY"] = "binary";
75
+ })(exports.TileFormat || (exports.TileFormat = {}));
76
+ /** @internalRemarks Source: @carto/react-core */
77
+ exports.SpatialIndex = void 0;
78
+ (function (SpatialIndex) {
79
+ SpatialIndex["H3"] = "h3";
80
+ SpatialIndex["S2"] = "s2";
81
+ SpatialIndex["QUADBIN"] = "quadbin";
82
+ })(exports.SpatialIndex || (exports.SpatialIndex = {}));
83
+ /** @internalRemarks Source: @carto/react-core */
84
+ exports.Provider = void 0;
85
+ (function (Provider) {
86
+ Provider["BIGQUERY"] = "bigquery";
87
+ Provider["REDSHIFT"] = "redshift";
88
+ Provider["POSTGRES"] = "postgres";
89
+ Provider["SNOWFLAKE"] = "snowflake";
90
+ Provider["DATABRICKS"] = "databricks";
91
+ Provider["DATABRICKS_REST"] = "databricksRest";
92
+ })(exports.Provider || (exports.Provider = {}));
64
93
 
65
94
  const FILTER_TYPES = new Set(Object.values(exports.FilterType));
66
95
  const isFilterType = type => FILTER_TYPES.has(type);
@@ -104,7 +133,7 @@ function normalizeObjectKeys(el) {
104
133
  }, {});
105
134
  }
106
135
  /** @internalRemarks Source: @carto/react-core */
107
- function assert(condition, message) {
136
+ function assert$1(condition, message) {
108
137
  if (!condition) {
109
138
  throw new Error(message);
110
139
  }
@@ -767,6 +796,95 @@ const boundaryTableSource = function (options) {
767
796
  }
768
797
  };
769
798
 
799
+ const DEFAULT_TILE_SIZE = 512;
800
+ const QUADBIN_ZOOM_MAX_OFFSET = 4;
801
+ function getSpatialFiltersResolution(source, viewState) {
802
+ const dataResolution = source.dataResolution ?? Number.MAX_VALUE;
803
+ const aggregationResLevel = source.aggregationResLevel ?? (source.spatialDataType === 'h3' ? DEFAULT_AGGREGATION_RES_LEVEL_H3 : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN);
804
+ const aggregationResLevelOffset = Math.max(0, Math.floor(aggregationResLevel));
805
+ const currentZoomInt = Math.ceil(viewState.zoom);
806
+ if (source.spatialDataType === 'h3') {
807
+ const tileSize = DEFAULT_TILE_SIZE;
808
+ const maxResolutionForZoom = maxH3SpatialFiltersResolutions.find(_ref => {
809
+ let [zoom] = _ref;
810
+ return zoom === currentZoomInt;
811
+ })?.[1] ?? Math.max(0, currentZoomInt - 3);
812
+ const maxSpatialFiltersResolution = maxResolutionForZoom ? Math.min(dataResolution, maxResolutionForZoom) : dataResolution;
813
+ const hexagonResolution = getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
814
+ return Math.min(hexagonResolution, maxSpatialFiltersResolution);
815
+ }
816
+ if (source.spatialDataType === 'quadbin') {
817
+ const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
818
+ const maxSpatialFiltersResolution = Math.min(dataResolution, maxResolutionForZoom);
819
+ const quadsResolution = Math.floor(viewState.zoom) + aggregationResLevelOffset;
820
+ return Math.min(quadsResolution, maxSpatialFiltersResolution);
821
+ }
822
+ return undefined;
823
+ }
824
+ 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]];
825
+ // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
826
+ // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
827
+ const BIAS = 2;
828
+ // Resolution conversion function. Takes a WebMercatorViewport and returns
829
+ // a H3 resolution such that the screen space size of the hexagons is
830
+ // similar
831
+ function getHexagonResolution(viewport, tileSize) {
832
+ // Difference in given tile size compared to deck's internal 512px tile size,
833
+ // expressed as an offset to the viewport zoom.
834
+ const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
835
+ const hexagonScaleFactor = 2 / 3 * (viewport.zoom - zoomOffset);
836
+ const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
837
+ // Clip and bias
838
+ return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
839
+ }
840
+
841
+ /**
842
+ * Source for Widget API requests on a data source defined by a SQL query.
843
+ *
844
+ * Abstract class. Use {@link WidgetQuerySource} or {@link WidgetTableSource}.
845
+ */
846
+ class WidgetSource {
847
+ constructor(props) {
848
+ this.props = void 0;
849
+ this.props = {
850
+ ...WidgetSource.defaultProps,
851
+ ...props
852
+ };
853
+ }
854
+ _getModelSource(owner) {
855
+ const props = this.props;
856
+ return {
857
+ apiVersion: props.apiVersion,
858
+ apiBaseUrl: props.apiBaseUrl,
859
+ clientId: props.clientId,
860
+ accessToken: props.accessToken,
861
+ connectionName: props.connectionName,
862
+ filters: getApplicableFilters(owner, props.filters),
863
+ filtersLogicalOperator: props.filtersLogicalOperator,
864
+ spatialDataType: props.spatialDataType,
865
+ spatialDataColumn: props.spatialDataColumn,
866
+ dataResolution: props.dataResolution
867
+ };
868
+ }
869
+ _getSpatialFiltersResolution(source, spatialFilter, referenceViewState) {
870
+ // spatialFiltersResolution applies only to spatial index sources.
871
+ if (!spatialFilter || source.spatialDataType === 'geo') {
872
+ return;
873
+ }
874
+ if (!referenceViewState) {
875
+ throw new Error('Missing required option, "spatialIndexReferenceViewState".');
876
+ }
877
+ return getSpatialFiltersResolution(source, referenceViewState);
878
+ }
879
+ }
880
+ WidgetSource.defaultProps = {
881
+ apiVersion: exports.ApiVersion.V3,
882
+ apiBaseUrl: DEFAULT_API_BASE_URL,
883
+ clientId: getClient(),
884
+ filters: {},
885
+ filtersLogicalOperator: 'and'
886
+ };
887
+
770
888
  /**
771
889
  * Return more descriptive error from API
772
890
  * @internalRemarks Source: @carto/react-api
@@ -868,10 +986,10 @@ const REQUEST_GET_MAX_URL_LENGTH = 2048;
868
986
  * @internalRemarks Source: @carto/react-api
869
987
  */
870
988
  function executeModel(props) {
871
- assert(props.source, 'executeModel: missing source');
872
- assert(props.model, 'executeModel: missing model');
873
- assert(props.params, 'executeModel: missing params');
874
- assert(AVAILABLE_MODELS.includes(props.model), `executeModel: model provided isn't valid. Available models: ${AVAILABLE_MODELS.join(', ')}`);
989
+ assert$1(props.source, 'executeModel: missing source');
990
+ assert$1(props.model, 'executeModel: missing model');
991
+ assert$1(props.params, 'executeModel: missing params');
992
+ assert$1(AVAILABLE_MODELS.includes(props.model), `executeModel: model provided isn't valid. Available models: ${AVAILABLE_MODELS.join(', ')}`);
875
993
  const {
876
994
  model,
877
995
  source,
@@ -886,10 +1004,10 @@ function executeModel(props) {
886
1004
  connectionName,
887
1005
  clientId
888
1006
  } = source;
889
- assert(apiBaseUrl, 'executeModel: missing apiBaseUrl');
890
- assert(accessToken, 'executeModel: missing accessToken');
891
- assert(apiVersion === V3, 'executeModel: SQL Model API requires CARTO 3+');
892
- assert(type !== 'tileset', 'executeModel: Tilesets not supported');
1007
+ assert$1(apiBaseUrl, 'executeModel: missing apiBaseUrl');
1008
+ assert$1(accessToken, 'executeModel: missing accessToken');
1009
+ assert$1(apiVersion === V3, 'executeModel: SQL Model API requires CARTO 3+');
1010
+ assert$1(type !== 'tileset', 'executeModel: Tilesets not supported');
893
1011
  let url = `${apiBaseUrl}/v3/sql/${connectionName}/model/${model}`;
894
1012
  const {
895
1013
  data,
@@ -961,93 +1079,12 @@ function objectToURLSearchParams(object) {
961
1079
  return params;
962
1080
  }
963
1081
 
964
- const DEFAULT_TILE_SIZE = 512;
965
- const QUADBIN_ZOOM_MAX_OFFSET = 4;
966
- function getSpatialFiltersResolution(source, viewState) {
967
- const dataResolution = source.dataResolution ?? Number.MAX_VALUE;
968
- const aggregationResLevel = source.aggregationResLevel ?? (source.spatialDataType === 'h3' ? DEFAULT_AGGREGATION_RES_LEVEL_H3 : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN);
969
- const aggregationResLevelOffset = Math.max(0, Math.floor(aggregationResLevel));
970
- const currentZoomInt = Math.ceil(viewState.zoom);
971
- if (source.spatialDataType === 'h3') {
972
- const tileSize = DEFAULT_TILE_SIZE;
973
- const maxResolutionForZoom = maxH3SpatialFiltersResolutions.find(_ref => {
974
- let [zoom] = _ref;
975
- return zoom === currentZoomInt;
976
- })?.[1] ?? Math.max(0, currentZoomInt - 3);
977
- const maxSpatialFiltersResolution = maxResolutionForZoom ? Math.min(dataResolution, maxResolutionForZoom) : dataResolution;
978
- const hexagonResolution = getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
979
- return Math.min(hexagonResolution, maxSpatialFiltersResolution);
980
- }
981
- if (source.spatialDataType === 'quadbin') {
982
- const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
983
- const maxSpatialFiltersResolution = Math.min(dataResolution, maxResolutionForZoom);
984
- const quadsResolution = Math.floor(viewState.zoom) + aggregationResLevelOffset;
985
- return Math.min(quadsResolution, maxSpatialFiltersResolution);
986
- }
987
- return undefined;
988
- }
989
- 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]];
990
- // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
991
- // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
992
- const BIAS = 2;
993
- // Resolution conversion function. Takes a WebMercatorViewport and returns
994
- // a H3 resolution such that the screen space size of the hexagons is
995
- // similar
996
- function getHexagonResolution(viewport, tileSize) {
997
- // Difference in given tile size compared to deck's internal 512px tile size,
998
- // expressed as an offset to the viewport zoom.
999
- const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
1000
- const hexagonScaleFactor = 2 / 3 * (viewport.zoom - zoomOffset);
1001
- const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
1002
- // Clip and bias
1003
- return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
1004
- }
1005
-
1006
1082
  /**
1007
- * Source for Widget API requests on a data source defined by a SQL query.
1083
+ * Source for Widget API requests.
1008
1084
  *
1009
1085
  * Abstract class. Use {@link WidgetQuerySource} or {@link WidgetTableSource}.
1010
1086
  */
1011
- class WidgetBaseSource {
1012
- constructor(props) {
1013
- this.props = void 0;
1014
- this.props = {
1015
- ...WidgetBaseSource.defaultProps,
1016
- ...props
1017
- };
1018
- }
1019
- _getModelSource(owner) {
1020
- const props = this.props;
1021
- return {
1022
- apiVersion: props.apiVersion,
1023
- apiBaseUrl: props.apiBaseUrl,
1024
- clientId: props.clientId,
1025
- accessToken: props.accessToken,
1026
- connectionName: props.connectionName,
1027
- filters: getApplicableFilters(owner, props.filters),
1028
- filtersLogicalOperator: props.filtersLogicalOperator,
1029
- spatialDataType: props.spatialDataType,
1030
- spatialDataColumn: props.spatialDataColumn,
1031
- dataResolution: props.dataResolution
1032
- };
1033
- }
1034
- _getSpatialFiltersResolution(source, spatialFilter, referenceViewState) {
1035
- // spatialFiltersResolution applies only to spatial index sources.
1036
- if (!spatialFilter || source.spatialDataType === 'geo') {
1037
- return;
1038
- }
1039
- if (!referenceViewState) {
1040
- throw new Error('Missing required option, "spatialIndexReferenceViewState".');
1041
- }
1042
- return getSpatialFiltersResolution(source, referenceViewState);
1043
- }
1044
- /****************************************************************************
1045
- * CATEGORIES
1046
- */
1047
- /**
1048
- * Returns a list of labeled datapoints for categorical data. Suitable for
1049
- * charts including grouped bar charts, pie charts, and tree charts.
1050
- */
1087
+ class WidgetRemoteSource extends WidgetSource {
1051
1088
  getCategories(options) {
1052
1089
  try {
1053
1090
  const _this = this;
@@ -1087,17 +1124,6 @@ class WidgetBaseSource {
1087
1124
  return Promise.reject(e);
1088
1125
  }
1089
1126
  }
1090
- /****************************************************************************
1091
- * FEATURES
1092
- */
1093
- /**
1094
- * Given a list of feature IDs (as found in `_carto_feature_id`) returns all
1095
- * matching features. In datasets containing features with duplicate geometries,
1096
- * feature IDs may be duplicated (IDs are a hash of geometry) and so more
1097
- * results may be returned than IDs in the request.
1098
- * @internal
1099
- * @experimental
1100
- */
1101
1127
  getFeatures(options) {
1102
1128
  try {
1103
1129
  const _this2 = this;
@@ -1151,13 +1177,6 @@ class WidgetBaseSource {
1151
1177
  return Promise.reject(e);
1152
1178
  }
1153
1179
  }
1154
- /****************************************************************************
1155
- * FORMULA
1156
- */
1157
- /**
1158
- * Returns a scalar numerical statistic over all matching data. Suitable
1159
- * for 'headline' or 'scorecard' figures such as counts and sums.
1160
- */
1161
1180
  getFormula(options) {
1162
1181
  try {
1163
1182
  const _this3 = this;
@@ -1186,7 +1205,7 @@ class WidgetBaseSource {
1186
1205
  },
1187
1206
  params: {
1188
1207
  column: column ?? '*',
1189
- operation,
1208
+ operation: operation ?? 'count',
1190
1209
  operationExp
1191
1210
  },
1192
1211
  opts: {
@@ -1197,13 +1216,6 @@ class WidgetBaseSource {
1197
1216
  return Promise.reject(e);
1198
1217
  }
1199
1218
  }
1200
- /****************************************************************************
1201
- * HISTOGRAM
1202
- */
1203
- /**
1204
- * Returns a list of labeled datapoints for 'bins' of data defined as ticks
1205
- * over a numerical range. Suitable for histogram charts.
1206
- */
1207
1219
  getHistogram(options) {
1208
1220
  try {
1209
1221
  const _this4 = this;
@@ -1258,14 +1270,6 @@ class WidgetBaseSource {
1258
1270
  return Promise.reject(e);
1259
1271
  }
1260
1272
  }
1261
- /****************************************************************************
1262
- * RANGE
1263
- */
1264
- /**
1265
- * Returns a range (min and max) for a numerical column of matching rows.
1266
- * Suitable for displaying certain 'headline' or 'scorecard' statistics,
1267
- * or rendering a range slider UI for filtering.
1268
- */
1269
1273
  getRange(options) {
1270
1274
  try {
1271
1275
  const _this5 = this;
@@ -1301,13 +1305,6 @@ class WidgetBaseSource {
1301
1305
  return Promise.reject(e);
1302
1306
  }
1303
1307
  }
1304
- /****************************************************************************
1305
- * SCATTER
1306
- */
1307
- /**
1308
- * Returns a list of bivariate datapoints defined as numerical 'x' and 'y'
1309
- * values. Suitable for rendering scatter plots.
1310
- */
1311
1308
  getScatter(options) {
1312
1309
  try {
1313
1310
  const _this6 = this;
@@ -1358,13 +1355,6 @@ class WidgetBaseSource {
1358
1355
  return Promise.reject(e);
1359
1356
  }
1360
1357
  }
1361
- /****************************************************************************
1362
- * TABLE
1363
- */
1364
- /**
1365
- * Returns a list of arbitrary data rows, with support for pagination and
1366
- * sorting. Suitable for displaying tables and lists.
1367
- */
1368
1358
  getTable(options) {
1369
1359
  try {
1370
1360
  const _this7 = this;
@@ -1412,13 +1402,6 @@ class WidgetBaseSource {
1412
1402
  return Promise.reject(e);
1413
1403
  }
1414
1404
  }
1415
- /****************************************************************************
1416
- * TIME SERIES
1417
- */
1418
- /**
1419
- * Returns a series of labeled numerical values, grouped into equally-sized
1420
- * time intervals. Suitable for rendering time series charts.
1421
- */
1422
1405
  getTimeSeries(options) {
1423
1406
  try {
1424
1407
  const _this8 = this;
@@ -1474,13 +1457,6 @@ class WidgetBaseSource {
1474
1457
  }
1475
1458
  }
1476
1459
  }
1477
- WidgetBaseSource.defaultProps = {
1478
- apiVersion: exports.ApiVersion.V3,
1479
- apiBaseUrl: DEFAULT_API_BASE_URL,
1480
- clientId: getClient(),
1481
- filters: {},
1482
- filtersLogicalOperator: 'and'
1483
- };
1484
1460
 
1485
1461
  /**
1486
1462
  * Source for Widget API requests on a data source defined by a SQL query.
@@ -1504,7 +1480,7 @@ WidgetBaseSource.defaultProps = {
1504
1480
  * const { widgetSource } = await data;
1505
1481
  * ```
1506
1482
  */
1507
- class WidgetQuerySource extends WidgetBaseSource {
1483
+ class WidgetQuerySource extends WidgetRemoteSource {
1508
1484
  getModelSource(owner) {
1509
1485
  return {
1510
1486
  ...super._getModelSource(owner),
@@ -1537,7 +1513,7 @@ class WidgetQuerySource extends WidgetBaseSource {
1537
1513
  * const { widgetSource } = await data;
1538
1514
  * ```
1539
1515
  */
1540
- class WidgetTableSource extends WidgetBaseSource {
1516
+ class WidgetTableSource extends WidgetRemoteSource {
1541
1517
  getModelSource(owner) {
1542
1518
  return {
1543
1519
  ...super._getModelSource(owner),
@@ -1547,60 +1523,1995 @@ class WidgetTableSource extends WidgetBaseSource {
1547
1523
  }
1548
1524
  }
1549
1525
 
1550
- // deck.gl
1551
- // SPDX-License-Identifier: MIT
1552
- // Copyright (c) vis.gl contributors
1553
- /* eslint-disable camelcase */
1554
- const h3QuerySource = function (options) {
1555
- try {
1556
- const {
1557
- aggregationExp,
1558
- aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
1559
- sqlQuery,
1560
- spatialDataColumn = 'h3',
1561
- queryParameters,
1562
- filters
1563
- } = options;
1564
- const spatialDataType = 'h3';
1565
- const urlParameters = {
1566
- aggregationExp,
1567
- spatialDataColumn,
1568
- spatialDataType,
1569
- q: sqlQuery
1570
- };
1571
- if (aggregationResLevel) {
1572
- urlParameters.aggregationResLevel = String(aggregationResLevel);
1573
- }
1574
- if (queryParameters) {
1575
- urlParameters.queryParameters = queryParameters;
1526
+ function makeIntervalComplete(intervals) {
1527
+ return intervals.map(val => {
1528
+ if (val[0] === undefined || val[0] === null) {
1529
+ return [Number.MIN_SAFE_INTEGER, val[1]];
1576
1530
  }
1577
- if (filters) {
1578
- urlParameters.filters = filters;
1531
+ if (val[1] === undefined || val[1] === null) {
1532
+ return [val[0], Number.MAX_SAFE_INTEGER];
1579
1533
  }
1580
- return Promise.resolve(baseSource('query', options, urlParameters).then(result => ({
1581
- ...result,
1582
- widgetSource: new WidgetQuerySource({
1583
- ...options,
1584
- // NOTE: Parameters with default values above must be explicitly passed here.
1585
- spatialDataColumn,
1586
- spatialDataType
1587
- })
1588
- })));
1589
- } catch (e) {
1590
- return Promise.reject(e);
1591
- }
1592
- };
1534
+ return val;
1535
+ });
1536
+ }
1593
1537
 
1594
- // deck.gl
1595
- // SPDX-License-Identifier: MIT
1596
- // Copyright (c) vis.gl contributors
1597
- /* eslint-disable camelcase */
1598
- const h3TableSource = function (options) {
1599
- try {
1600
- const {
1601
- aggregationExp,
1602
- aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
1603
- spatialDataColumn = 'h3',
1538
+ const filterFunctions = {
1539
+ [exports.FilterType.IN]: filterIn,
1540
+ [exports.FilterType.BETWEEN]: filterBetween,
1541
+ [exports.FilterType.TIME]: filterTime,
1542
+ [exports.FilterType.CLOSED_OPEN]: filterClosedOpen,
1543
+ [exports.FilterType.STRING_SEARCH]: filterStringSearch
1544
+ };
1545
+ function filterIn(filterValues, featureValue) {
1546
+ return filterValues.includes(featureValue);
1547
+ }
1548
+ // FilterTypes.BETWEEN
1549
+ function filterBetween(filterValues, featureValue) {
1550
+ const checkRange = range => {
1551
+ const [lowerBound, upperBound] = range;
1552
+ return featureValue >= lowerBound && featureValue <= upperBound;
1553
+ };
1554
+ return makeIntervalComplete(filterValues).some(checkRange);
1555
+ }
1556
+ function filterTime(filterValues, featureValue) {
1557
+ const featureValueAsTimestamp = new Date(featureValue).getTime();
1558
+ if (isFinite(featureValueAsTimestamp)) {
1559
+ return filterBetween(filterValues, featureValueAsTimestamp);
1560
+ } else {
1561
+ throw new Error(`Column used to filter by time isn't well formatted.`);
1562
+ }
1563
+ }
1564
+ // FilterTypes.CLOSED_OPEN
1565
+ function filterClosedOpen(filterValues, featureValue) {
1566
+ const checkRange = range => {
1567
+ const [lowerBound, upperBound] = range;
1568
+ return featureValue >= lowerBound && featureValue < upperBound;
1569
+ };
1570
+ return makeIntervalComplete(filterValues).some(checkRange);
1571
+ }
1572
+ // FilterTypes.STRING_SEARCH
1573
+ function filterStringSearch(filterValues, featureValue, params) {
1574
+ if (params === void 0) {
1575
+ params = {};
1576
+ }
1577
+ const normalizedFeatureValue = normalize(featureValue, params);
1578
+ const stringRegExp = params.useRegExp ? filterValues : filterValues.map(filterValue => {
1579
+ let stringRegExp = escapeRegExp(normalize(filterValue, params));
1580
+ if (params.mustStart) stringRegExp = `^${stringRegExp}`;
1581
+ if (params.mustEnd) stringRegExp = `${stringRegExp}$`;
1582
+ return stringRegExp;
1583
+ });
1584
+ const regex = new RegExp(stringRegExp.join('|'), params.caseSensitive ? 'g' : 'gi');
1585
+ return !!normalizedFeatureValue.match(regex);
1586
+ }
1587
+ // Aux
1588
+ const specialCharRegExp = /[.*+?^${}()|[\]\\]/g;
1589
+ const normalizeRegExp = /\p{Diacritic}/gu;
1590
+ function escapeRegExp(value) {
1591
+ return value.replace(specialCharRegExp, '\\$&');
1592
+ }
1593
+ function normalize(data, params) {
1594
+ let normalizedData = String(data);
1595
+ if (!params.keepSpecialCharacters) normalizedData = normalizedData.normalize('NFD').replace(normalizeRegExp, '');
1596
+ return normalizedData;
1597
+ }
1598
+
1599
+ const LOGICAL_OPERATOR_METHODS = {
1600
+ and: 'every',
1601
+ or: 'some'
1602
+ };
1603
+ function passesFilter(columns, filters, feature, filtersLogicalOperator) {
1604
+ const method = LOGICAL_OPERATOR_METHODS[filtersLogicalOperator];
1605
+ return columns[method](column => {
1606
+ const columnFilters = filters[column];
1607
+ const columnFilterTypes = Object.keys(columnFilters);
1608
+ if (!feature || feature[column] === null || feature[column] === undefined) {
1609
+ return false;
1610
+ }
1611
+ return columnFilterTypes.every(filter => {
1612
+ const filterFunction = filterFunctions[filter];
1613
+ if (!filterFunction) {
1614
+ throw new Error(`"${filter}" filter is not implemented.`);
1615
+ }
1616
+ return filterFunction(columnFilters[filter].values, feature[column], columnFilters[filter].params);
1617
+ });
1618
+ });
1619
+ }
1620
+ function buildFeatureFilter(_ref) {
1621
+ let {
1622
+ filters = {},
1623
+ type = 'boolean',
1624
+ filtersLogicalOperator = 'and'
1625
+ } = _ref;
1626
+ const columns = Object.keys(filters);
1627
+ if (!columns.length) {
1628
+ return () => type === 'number' ? 1 : true;
1629
+ }
1630
+ return feature => {
1631
+ const f = feature.properties || feature;
1632
+ const featurePassesFilter = passesFilter(columns, filters, f, filtersLogicalOperator);
1633
+ return type === 'number' ? Number(featurePassesFilter) : featurePassesFilter;
1634
+ };
1635
+ }
1636
+ // Apply certain filters to a collection of features
1637
+ function applyFilters(features, filters, filtersLogicalOperator) {
1638
+ return Object.keys(filters).length ? features.filter(buildFeatureFilter({
1639
+ filters,
1640
+ filtersLogicalOperator
1641
+ })) : features;
1642
+ }
1643
+ // Binary
1644
+ function buildBinaryFeatureFilter(_ref2) {
1645
+ let {
1646
+ filters = {}
1647
+ } = _ref2;
1648
+ const columns = Object.keys(filters);
1649
+ if (!columns.length) {
1650
+ return () => 1;
1651
+ }
1652
+ return (featureIdIdx, binaryData) => passesFilterUsingBinary(columns, filters, featureIdIdx, binaryData);
1653
+ }
1654
+ function getValueFromNumericProps(featureIdIdx, binaryData, _ref3) {
1655
+ let {
1656
+ column
1657
+ } = _ref3;
1658
+ return binaryData.numericProps?.[column]?.value[featureIdIdx];
1659
+ }
1660
+ function getValueFromProperties(featureIdIdx, binaryData, _ref4) {
1661
+ let {
1662
+ column
1663
+ } = _ref4;
1664
+ const propertyIdx = binaryData.featureIds.value[featureIdIdx];
1665
+ return binaryData.properties[propertyIdx]?.[column];
1666
+ }
1667
+ const GET_VALUE_BY_BINARY_PROP = {
1668
+ properties: getValueFromProperties,
1669
+ numericProps: getValueFromNumericProps
1670
+ };
1671
+ function getBinaryPropertyByFilterValues(filterValues) {
1672
+ return typeof filterValues.flat()[0] === 'string' ? 'properties' : 'numericProps';
1673
+ }
1674
+ function getFeatureValue(featureIdIdx, binaryData, filter) {
1675
+ const {
1676
+ column,
1677
+ values
1678
+ } = filter;
1679
+ const binaryProp = getBinaryPropertyByFilterValues(values);
1680
+ const getFeatureValueFn = GET_VALUE_BY_BINARY_PROP[binaryProp];
1681
+ return getFeatureValueFn(featureIdIdx, binaryData, {
1682
+ column
1683
+ });
1684
+ }
1685
+ function passesFilterUsingBinary(columns, filters, featureIdIdx, binaryData) {
1686
+ return columns.every(column => {
1687
+ const columnFilters = filters[column];
1688
+ return Object.entries(columnFilters).every(_ref5 => {
1689
+ let [type, {
1690
+ values
1691
+ }] = _ref5;
1692
+ const filterFn = filterFunctions[type];
1693
+ if (!filterFn) {
1694
+ throw new Error(`"${type}" filter is not implemented.`);
1695
+ }
1696
+ if (!values) return 0;
1697
+ const featureValue = getFeatureValue(featureIdIdx, binaryData, {
1698
+ type: type,
1699
+ column,
1700
+ values
1701
+ });
1702
+ if (featureValue === undefined || featureValue === null) return 0;
1703
+ return filterFn(values, featureValue);
1704
+ });
1705
+ });
1706
+ }
1707
+
1708
+ function geojsonFeatures(_ref) {
1709
+ let {
1710
+ geojson,
1711
+ spatialFilter,
1712
+ uniqueIdProperty
1713
+ } = _ref;
1714
+ let uniqueIdx = 0;
1715
+ const map = new Map();
1716
+ if (!spatialFilter) {
1717
+ return [];
1718
+ }
1719
+ for (const feature of geojson.features) {
1720
+ const uniqueId = uniqueIdProperty ? feature.properties[uniqueIdProperty] : ++uniqueIdx;
1721
+ if (!map.has(uniqueId) && intersects(spatialFilter, feature)) {
1722
+ map.set(uniqueId, feature.properties);
1723
+ }
1724
+ }
1725
+ return Array.from(map.values());
1726
+ }
1727
+
1728
+ // math.gl
1729
+ // SPDX-License-Identifier: MIT
1730
+ // Copyright (c) vis.gl contributors
1731
+ const DEFAULT_CONFIG = {
1732
+ EPSILON: 1e-12,
1733
+ debug: false,
1734
+ precision: 4,
1735
+ printTypes: false,
1736
+ printDegrees: false,
1737
+ printRowMajor: true,
1738
+ _cartographicRadians: false
1739
+ };
1740
+ // Configuration is truly global as of v3.6 to ensure single config even if multiple copies of math.gl
1741
+ // Multiple copies of config can be quite tricky to debug...
1742
+ globalThis.mathgl = globalThis.mathgl || {
1743
+ config: {
1744
+ ...DEFAULT_CONFIG
1745
+ }
1746
+ };
1747
+ /**
1748
+ * Check if value is an "array"
1749
+ * Returns `true` if value is either an array or a typed array
1750
+ * Note: returns `false` for `ArrayBuffer` and `DataView` instances
1751
+ * @note isTypedArray and isNumericArray are often more useful in TypeScript
1752
+ */
1753
+ function isArray(value) {
1754
+ return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
1755
+ }
1756
+ function lerp(a, b, t) {
1757
+ if (isArray(a)) {
1758
+ return a.map((ai, i) => lerp(ai, b[i], t));
1759
+ }
1760
+ return t * b + (1 - t) * a;
1761
+ }
1762
+
1763
+ // Replacement for the external assert method to reduce bundle size
1764
+ // Note: We don't use the second "message" argument in calling code,
1765
+ // so no need to support it here
1766
+ function assert(condition, message) {
1767
+ if (!condition) {
1768
+ throw new Error(message || '@math.gl/web-mercator: assertion failed.');
1769
+ }
1770
+ }
1771
+
1772
+ // TODO - THE UTILITIES IN THIS FILE SHOULD BE IMPORTED FROM WEB-MERCATOR-VIEWPORT MODULE
1773
+ // CONSTANTS
1774
+ const PI = Math.PI;
1775
+ const PI_4 = PI / 4;
1776
+ const DEGREES_TO_RADIANS = PI / 180;
1777
+ const RADIANS_TO_DEGREES = 180 / PI;
1778
+ const TILE_SIZE = 512;
1779
+ /**
1780
+ * Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
1781
+ * Performs the nonlinear part of the web mercator projection.
1782
+ * Remaining projection is done with 4x4 matrices which also handles
1783
+ * perspective.
1784
+ *
1785
+ * @param lngLat - [lng, lat] coordinates
1786
+ * Specifies a point on the sphere to project onto the map.
1787
+ * @return [x,y] coordinates.
1788
+ */
1789
+ function lngLatToWorld(lngLat) {
1790
+ const [lng, lat] = lngLat;
1791
+ assert(Number.isFinite(lng));
1792
+ assert(Number.isFinite(lat) && lat >= -90 && lat <= 90, 'invalid latitude');
1793
+ const lambda2 = lng * DEGREES_TO_RADIANS;
1794
+ const phi2 = lat * DEGREES_TO_RADIANS;
1795
+ const x = TILE_SIZE * (lambda2 + PI) / (2 * PI);
1796
+ const y = TILE_SIZE * (PI + Math.log(Math.tan(PI_4 + phi2 * 0.5))) / (2 * PI);
1797
+ return [x, y];
1798
+ }
1799
+ /**
1800
+ * Unproject world point [x,y] on map onto {lat, lon} on sphere
1801
+ *
1802
+ * @param xy - array with [x,y] members
1803
+ * representing point on projected map plane
1804
+ * @return - array with [x,y] of point on sphere.
1805
+ * Has toArray method if you need a GeoJSON Array.
1806
+ * Per cartographic tradition, lat and lon are specified as degrees.
1807
+ */
1808
+ function worldToLngLat(xy) {
1809
+ const [x, y] = xy;
1810
+ const lambda2 = x / TILE_SIZE * (2 * PI) - PI;
1811
+ const phi2 = 2 * (Math.atan(Math.exp(y / TILE_SIZE * (2 * PI) - PI)) - PI_4);
1812
+ return [lambda2 * RADIANS_TO_DEGREES, phi2 * RADIANS_TO_DEGREES];
1813
+ }
1814
+
1815
+ const TRANSFORM_FN$1 = {
1816
+ Point: transformPoint$1,
1817
+ MultiPoint: transformMultiPoint$1,
1818
+ LineString: transformLineString$1,
1819
+ MultiLineString: transformMultiLineString$1,
1820
+ Polygon: transformPolygon$1,
1821
+ MultiPolygon: transformMultiPolygon$1
1822
+ };
1823
+ /**
1824
+ * Transform WGS84 coordinates to tile coords.
1825
+ * 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)
1826
+ *
1827
+ * @param geometry - any valid geojson geometry
1828
+ * @param bbox - geojson bbox
1829
+ */
1830
+ function transformToTileCoords(geometry, bbox) {
1831
+ const [west, south, east, north] = bbox;
1832
+ const nw = projectFlat([west, north]);
1833
+ const se = projectFlat([east, south]);
1834
+ const projectedBbox = [nw, se];
1835
+ if (geometry.type === 'GeometryCollection') {
1836
+ throw new Error('Unsupported geometry type GeometryCollection');
1837
+ }
1838
+ const transformFn = TRANSFORM_FN$1[geometry.type];
1839
+ const coordinates = transformFn(geometry.coordinates, projectedBbox);
1840
+ return {
1841
+ ...geometry,
1842
+ coordinates
1843
+ };
1844
+ }
1845
+ function transformPoint$1(_ref, _ref2) {
1846
+ let [pointX, pointY] = _ref;
1847
+ let [nw, se] = _ref2;
1848
+ const x = inverseLerp(nw[0], se[0], pointX);
1849
+ const y = inverseLerp(nw[1], se[1], pointY);
1850
+ return [x, y];
1851
+ }
1852
+ function getPoints$1(geometry, bbox) {
1853
+ return geometry.map(g => transformPoint$1(projectFlat(g), bbox));
1854
+ }
1855
+ function transformMultiPoint$1(multiPoint, bbox) {
1856
+ return getPoints$1(multiPoint, bbox);
1857
+ }
1858
+ function transformLineString$1(line, bbox) {
1859
+ return getPoints$1(line, bbox);
1860
+ }
1861
+ function transformMultiLineString$1(multiLineString, bbox) {
1862
+ return multiLineString.map(lineString => transformLineString$1(lineString, bbox));
1863
+ }
1864
+ function transformPolygon$1(polygon, bbox) {
1865
+ return polygon.map(polygonRing => getPoints$1(polygonRing, bbox));
1866
+ }
1867
+ function transformMultiPolygon$1(multiPolygon, bbox) {
1868
+ return multiPolygon.map(polygon => transformPolygon$1(polygon, bbox));
1869
+ }
1870
+ function projectFlat(xyz) {
1871
+ return lngLatToWorld(xyz);
1872
+ }
1873
+ function inverseLerp(a, b, x) {
1874
+ return (x - a) / (b - a);
1875
+ }
1876
+
1877
+ const TRANSFORM_FN = {
1878
+ Point: transformPoint,
1879
+ MultiPoint: transformMultiPoint,
1880
+ LineString: transformLineString,
1881
+ MultiLineString: transformMultiLineString,
1882
+ Polygon: transformPolygon,
1883
+ MultiPolygon: transformMultiPolygon
1884
+ };
1885
+ /**
1886
+ * Transform tile coords to WGS84 coordinates.
1887
+ *
1888
+ * @param geometry - any valid geojson geometry
1889
+ * @param bbox - geojson bbox
1890
+ */
1891
+ function transformTileCoordsToWGS84(geometry, bbox) {
1892
+ const [west, south, east, north] = bbox;
1893
+ const nw = lngLatToWorld([west, north]);
1894
+ const se = lngLatToWorld([east, south]);
1895
+ const projectedBbox = [nw, se];
1896
+ if (geometry.type === 'GeometryCollection') {
1897
+ throw new Error('Unsupported geometry type GeometryCollection');
1898
+ }
1899
+ const transformFn = TRANSFORM_FN[geometry.type];
1900
+ const coordinates = transformFn(geometry.coordinates, projectedBbox);
1901
+ return {
1902
+ ...geometry,
1903
+ coordinates
1904
+ };
1905
+ }
1906
+ function transformPoint(_ref, _ref2) {
1907
+ let [pointX, pointY] = _ref;
1908
+ let [nw, se] = _ref2;
1909
+ const x = lerp(nw[0], se[0], pointX);
1910
+ const y = lerp(nw[1], se[1], pointY);
1911
+ return worldToLngLat([x, y]);
1912
+ }
1913
+ function getPoints(geometry, bbox) {
1914
+ return geometry.map(g => transformPoint(g, bbox));
1915
+ }
1916
+ function transformMultiPoint(multiPoint, bbox) {
1917
+ return getPoints(multiPoint, bbox);
1918
+ }
1919
+ function transformLineString(line, bbox) {
1920
+ return getPoints(line, bbox);
1921
+ }
1922
+ function transformMultiLineString(multiLineString, bbox) {
1923
+ return multiLineString.map(lineString => transformLineString(lineString, bbox));
1924
+ }
1925
+ function transformPolygon(polygon, bbox) {
1926
+ return polygon.map(polygonRing => getPoints(polygonRing, bbox));
1927
+ }
1928
+ function transformMultiPolygon(multiPolygon, bbox) {
1929
+ return multiPolygon.map(polygon => transformPolygon(polygon, bbox));
1930
+ }
1931
+
1932
+ const FEATURE_GEOM_PROPERTY = '__geomValue';
1933
+ function tileFeaturesGeometries(_ref) {
1934
+ let {
1935
+ tiles,
1936
+ tileFormat,
1937
+ spatialFilter,
1938
+ uniqueIdProperty,
1939
+ options
1940
+ } = _ref;
1941
+ const map = new Map();
1942
+ for (const tile of tiles) {
1943
+ // Discard if it's not a visible tile (only check false value, not undefined)
1944
+ // or tile has not data
1945
+ if (tile.isVisible === false || !tile.data) {
1946
+ continue;
1947
+ }
1948
+ const bbox = [tile.bbox.west, tile.bbox.south, tile.bbox.east, tile.bbox.north];
1949
+ const bboxToGeom = bboxPolygon(bbox);
1950
+ const tileIsFullyVisible = booleanWithin(bboxToGeom, spatialFilter);
1951
+ // Clip the geometry to intersect with the tile
1952
+ const spatialFilterFeature = {
1953
+ type: 'Feature',
1954
+ geometry: spatialFilter,
1955
+ properties: {}
1956
+ };
1957
+ const clippedGeometryToIntersect = intersect(helpers.featureCollection([bboxToGeom, spatialFilterFeature]));
1958
+ if (!clippedGeometryToIntersect) {
1959
+ continue;
1960
+ }
1961
+ // We assume that MVT tileFormat uses local coordinates so we transform the geometry to intersect to tile coordinates [0..1],
1962
+ // while in the case of 'geojson' or binary, the geometries are already in WGS84
1963
+ const transformedGeometryToIntersect = tileFormat === exports.TileFormat.MVT ? transformToTileCoords(clippedGeometryToIntersect.geometry, bbox) : clippedGeometryToIntersect.geometry;
1964
+ createIndicesForPoints(tile.data.points);
1965
+ calculateFeatures({
1966
+ map,
1967
+ tileIsFullyVisible,
1968
+ geometryIntersection: transformedGeometryToIntersect,
1969
+ data: tile.data.points,
1970
+ type: 'Point',
1971
+ bbox,
1972
+ tileFormat,
1973
+ uniqueIdProperty,
1974
+ options
1975
+ });
1976
+ calculateFeatures({
1977
+ map,
1978
+ tileIsFullyVisible,
1979
+ geometryIntersection: transformedGeometryToIntersect,
1980
+ data: tile.data.lines,
1981
+ type: 'LineString',
1982
+ bbox,
1983
+ tileFormat,
1984
+ uniqueIdProperty,
1985
+ options
1986
+ });
1987
+ calculateFeatures({
1988
+ map,
1989
+ tileIsFullyVisible,
1990
+ geometryIntersection: transformedGeometryToIntersect,
1991
+ data: tile.data.polygons,
1992
+ type: 'Polygon',
1993
+ bbox,
1994
+ tileFormat,
1995
+ uniqueIdProperty,
1996
+ options
1997
+ });
1998
+ }
1999
+ return Array.from(map.values());
2000
+ }
2001
+ function processTileFeatureProperties(_ref2) {
2002
+ let {
2003
+ map,
2004
+ data,
2005
+ startIndex,
2006
+ endIndex,
2007
+ type,
2008
+ bbox,
2009
+ tileFormat,
2010
+ uniqueIdProperty,
2011
+ storeGeometry,
2012
+ geometryIntersection
2013
+ } = _ref2;
2014
+ const tileProps = getPropertiesFromTile(data, startIndex);
2015
+ const uniquePropertyValue = getUniquePropertyValue(tileProps, uniqueIdProperty, map);
2016
+ if (!uniquePropertyValue || map.has(uniquePropertyValue)) {
2017
+ return;
2018
+ }
2019
+ let geometry = null;
2020
+ // Only calculate geometry if necessary
2021
+ if (storeGeometry || geometryIntersection) {
2022
+ const {
2023
+ positions
2024
+ } = data;
2025
+ const ringCoordinates = getRingCoordinatesFor(startIndex, endIndex, positions);
2026
+ geometry = getFeatureByType(ringCoordinates, type);
2027
+ }
2028
+ // If intersection is required, check before proceeding
2029
+ if (geometry && geometryIntersection && !intersects(geometry, geometryIntersection)) {
2030
+ return;
2031
+ }
2032
+ const properties = parseProperties(tileProps);
2033
+ // Only save geometry if necessary
2034
+ if (storeGeometry && geometry) {
2035
+ properties[FEATURE_GEOM_PROPERTY] = tileFormat === exports.TileFormat.MVT ? transformTileCoordsToWGS84(geometry, bbox) : geometry;
2036
+ }
2037
+ map.set(uniquePropertyValue, properties);
2038
+ }
2039
+ function addIntersectedFeaturesInTile(_ref3) {
2040
+ let {
2041
+ map,
2042
+ data,
2043
+ geometryIntersection,
2044
+ type,
2045
+ bbox,
2046
+ tileFormat,
2047
+ uniqueIdProperty,
2048
+ options
2049
+ } = _ref3;
2050
+ const indices = getIndices(data);
2051
+ const storeGeometry = options?.storeGeometry || false;
2052
+ for (let i = 0; i < indices.length - 1; i++) {
2053
+ const startIndex = indices[i];
2054
+ const endIndex = indices[i + 1];
2055
+ processTileFeatureProperties({
2056
+ map,
2057
+ data,
2058
+ startIndex,
2059
+ endIndex,
2060
+ type,
2061
+ bbox,
2062
+ tileFormat,
2063
+ uniqueIdProperty,
2064
+ storeGeometry,
2065
+ geometryIntersection
2066
+ });
2067
+ }
2068
+ }
2069
+ function getIndices(data) {
2070
+ let indices;
2071
+ switch (data.type) {
2072
+ case 'Point':
2073
+ // @ts-expect-error Missing or changed types?
2074
+ indices = data.pointIndices;
2075
+ break;
2076
+ case 'LineString':
2077
+ indices = data.pathIndices;
2078
+ break;
2079
+ case 'Polygon':
2080
+ indices = data.primitivePolygonIndices;
2081
+ break;
2082
+ default:
2083
+ throw new Error(`Unexpected type, "${data.type}"`);
2084
+ }
2085
+ return indices.value;
2086
+ }
2087
+ function getFeatureId(data, startIndex) {
2088
+ return data.featureIds.value[startIndex];
2089
+ }
2090
+ function getPropertiesFromTile(data, startIndex) {
2091
+ const featureId = getFeatureId(data, startIndex);
2092
+ const {
2093
+ properties,
2094
+ numericProps,
2095
+ fields
2096
+ } = data;
2097
+ const result = {
2098
+ uniqueId: fields?.[featureId]?.id,
2099
+ properties: properties[featureId],
2100
+ numericProps: {}
2101
+ };
2102
+ for (const key in numericProps) {
2103
+ result.numericProps[key] = numericProps[key].value[startIndex];
2104
+ }
2105
+ return result;
2106
+ }
2107
+ function parseProperties(tileProps) {
2108
+ const {
2109
+ properties,
2110
+ numericProps
2111
+ } = tileProps;
2112
+ return Object.assign({}, properties, numericProps);
2113
+ }
2114
+ function getUniquePropertyValue(tileProps, uniqueIdProperty, map) {
2115
+ if (uniqueIdProperty) {
2116
+ return getValueFromTileProps(tileProps, uniqueIdProperty);
2117
+ }
2118
+ if (tileProps.uniqueId) {
2119
+ return tileProps.uniqueId;
2120
+ }
2121
+ const artificialId = map.size + 1; // a counter, assumed as a valid new id
2122
+ return getValueFromTileProps(tileProps, 'cartodb_id') || getValueFromTileProps(tileProps, 'geoid') || artificialId;
2123
+ }
2124
+ function getValueFromTileProps(tileProps, propertyName) {
2125
+ const {
2126
+ properties,
2127
+ numericProps
2128
+ } = tileProps;
2129
+ return numericProps[propertyName] || properties[propertyName];
2130
+ }
2131
+ function getFeatureByType(coordinates, type) {
2132
+ switch (type) {
2133
+ case 'Polygon':
2134
+ return {
2135
+ type: 'Polygon',
2136
+ coordinates: [coordinates]
2137
+ };
2138
+ case 'LineString':
2139
+ return {
2140
+ type: 'LineString',
2141
+ coordinates
2142
+ };
2143
+ case 'Point':
2144
+ return {
2145
+ type: 'Point',
2146
+ coordinates: coordinates[0]
2147
+ };
2148
+ default:
2149
+ throw new Error('Invalid geometry type');
2150
+ }
2151
+ }
2152
+ function getRingCoordinatesFor(startIndex, endIndex, positions) {
2153
+ const ringCoordinates = [];
2154
+ for (let j = startIndex; j < endIndex; j++) {
2155
+ ringCoordinates.push(Array.from(positions.value.subarray(j * positions.size, (j + 1) * positions.size)));
2156
+ }
2157
+ return ringCoordinates;
2158
+ }
2159
+ function calculateFeatures(_ref4) {
2160
+ let {
2161
+ map,
2162
+ tileIsFullyVisible,
2163
+ geometryIntersection,
2164
+ data,
2165
+ type,
2166
+ bbox,
2167
+ tileFormat,
2168
+ uniqueIdProperty,
2169
+ options
2170
+ } = _ref4;
2171
+ if (!data?.properties.length) {
2172
+ return;
2173
+ }
2174
+ if (tileIsFullyVisible) {
2175
+ addAllFeaturesInTile({
2176
+ map,
2177
+ data,
2178
+ type,
2179
+ bbox,
2180
+ tileFormat,
2181
+ uniqueIdProperty,
2182
+ options
2183
+ });
2184
+ } else {
2185
+ addIntersectedFeaturesInTile({
2186
+ map,
2187
+ data,
2188
+ geometryIntersection,
2189
+ type,
2190
+ bbox,
2191
+ tileFormat,
2192
+ uniqueIdProperty,
2193
+ options
2194
+ });
2195
+ }
2196
+ }
2197
+ function addAllFeaturesInTile(_ref5) {
2198
+ let {
2199
+ map,
2200
+ data,
2201
+ type,
2202
+ bbox,
2203
+ tileFormat,
2204
+ uniqueIdProperty,
2205
+ options
2206
+ } = _ref5;
2207
+ const indices = getIndices(data);
2208
+ const storeGeometry = options?.storeGeometry || false;
2209
+ for (let i = 0; i < indices.length - 1; i++) {
2210
+ const startIndex = indices[i];
2211
+ const endIndex = indices[i + 1];
2212
+ processTileFeatureProperties({
2213
+ map,
2214
+ data,
2215
+ startIndex,
2216
+ endIndex,
2217
+ type,
2218
+ bbox,
2219
+ tileFormat,
2220
+ uniqueIdProperty,
2221
+ storeGeometry
2222
+ });
2223
+ }
2224
+ }
2225
+ function createIndicesForPoints(data) {
2226
+ const featureIds = data.featureIds.value;
2227
+ const lastFeatureId = featureIds[featureIds.length - 1];
2228
+ const PointIndicesArray = featureIds.constructor;
2229
+ const pointIndices = {
2230
+ value: new PointIndicesArray(featureIds.length + 1),
2231
+ size: 1
2232
+ };
2233
+ pointIndices.value.set(featureIds);
2234
+ pointIndices.value.set([lastFeatureId + 1], featureIds.length);
2235
+ // @ts-expect-error Missing or changed types?
2236
+ data.pointIndices = pointIndices;
2237
+ }
2238
+
2239
+ // a tile is an array [x,y,z]
2240
+ var d2r = Math.PI / 180,
2241
+ r2d = 180 / Math.PI;
2242
+ function tileToBBOX(tile) {
2243
+ var e = tile2lon(tile[0] + 1, tile[2]);
2244
+ var w = tile2lon(tile[0], tile[2]);
2245
+ var s = tile2lat(tile[1] + 1, tile[2]);
2246
+ var n = tile2lat(tile[1], tile[2]);
2247
+ return [w, s, e, n];
2248
+ }
2249
+ function tileToGeoJSON(tile) {
2250
+ var bbox = tileToBBOX(tile);
2251
+ var poly = {
2252
+ type: 'Polygon',
2253
+ coordinates: [[[bbox[0], bbox[1]], [bbox[0], bbox[3]], [bbox[2], bbox[3]], [bbox[2], bbox[1]], [bbox[0], bbox[1]]]]
2254
+ };
2255
+ return poly;
2256
+ }
2257
+ function tile2lon(x, z) {
2258
+ return x / Math.pow(2, z) * 360 - 180;
2259
+ }
2260
+ function tile2lat(y, z) {
2261
+ var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
2262
+ return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
2263
+ }
2264
+ function pointToTile(lon, lat, z) {
2265
+ var tile = pointToTileFraction(lon, lat, z);
2266
+ tile[0] = Math.floor(tile[0]);
2267
+ tile[1] = Math.floor(tile[1]);
2268
+ return tile;
2269
+ }
2270
+ function getChildren(tile) {
2271
+ 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]];
2272
+ }
2273
+ function getParent(tile) {
2274
+ // top left
2275
+ if (tile[0] % 2 === 0 && tile[1] % 2 === 0) {
2276
+ return [tile[0] / 2, tile[1] / 2, tile[2] - 1];
2277
+ }
2278
+ // bottom left
2279
+ else if (tile[0] % 2 === 0 && !tile[1] % 2 === 0) {
2280
+ return [tile[0] / 2, (tile[1] - 1) / 2, tile[2] - 1];
2281
+ }
2282
+ // top right
2283
+ else if (!tile[0] % 2 === 0 && tile[1] % 2 === 0) {
2284
+ return [(tile[0] - 1) / 2, tile[1] / 2, tile[2] - 1];
2285
+ }
2286
+ // bottom right
2287
+ else {
2288
+ return [(tile[0] - 1) / 2, (tile[1] - 1) / 2, tile[2] - 1];
2289
+ }
2290
+ }
2291
+ function getSiblings(tile) {
2292
+ return getChildren(getParent(tile));
2293
+ }
2294
+ function hasSiblings(tile, tiles) {
2295
+ var siblings = getSiblings(tile);
2296
+ for (var i = 0; i < siblings.length; i++) {
2297
+ if (!hasTile(tiles, siblings[i])) return false;
2298
+ }
2299
+ return true;
2300
+ }
2301
+ function hasTile(tiles, tile) {
2302
+ for (var i = 0; i < tiles.length; i++) {
2303
+ if (tilesEqual(tiles[i], tile)) return true;
2304
+ }
2305
+ return false;
2306
+ }
2307
+ function tilesEqual(tile1, tile2) {
2308
+ return tile1[0] === tile2[0] && tile1[1] === tile2[1] && tile1[2] === tile2[2];
2309
+ }
2310
+ function tileToQuadkey(tile) {
2311
+ var index = '';
2312
+ for (var z = tile[2]; z > 0; z--) {
2313
+ var b = 0;
2314
+ var mask = 1 << z - 1;
2315
+ if ((tile[0] & mask) !== 0) b++;
2316
+ if ((tile[1] & mask) !== 0) b += 2;
2317
+ index += b.toString();
2318
+ }
2319
+ return index;
2320
+ }
2321
+ function quadkeyToTile(quadkey) {
2322
+ var x = 0;
2323
+ var y = 0;
2324
+ var z = quadkey.length;
2325
+ for (var i = z; i > 0; i--) {
2326
+ var mask = 1 << i - 1;
2327
+ switch (quadkey[z - i]) {
2328
+ case '0':
2329
+ break;
2330
+ case '1':
2331
+ x |= mask;
2332
+ break;
2333
+ case '2':
2334
+ y |= mask;
2335
+ break;
2336
+ case '3':
2337
+ x |= mask;
2338
+ y |= mask;
2339
+ break;
2340
+ }
2341
+ }
2342
+ return [x, y, z];
2343
+ }
2344
+ function bboxToTile(bboxCoords) {
2345
+ var min = pointToTile(bboxCoords[0], bboxCoords[1], 32);
2346
+ var max = pointToTile(bboxCoords[2], bboxCoords[3], 32);
2347
+ var bbox = [min[0], min[1], max[0], max[1]];
2348
+ var z = getBboxZoom(bbox);
2349
+ if (z === 0) return [0, 0, 0];
2350
+ var x = bbox[0] >>> 32 - z;
2351
+ var y = bbox[1] >>> 32 - z;
2352
+ return [x, y, z];
2353
+ }
2354
+ function getBboxZoom(bbox) {
2355
+ var MAX_ZOOM = 28;
2356
+ for (var z = 0; z < MAX_ZOOM; z++) {
2357
+ var mask = 1 << 32 - (z + 1);
2358
+ if ((bbox[0] & mask) != (bbox[2] & mask) || (bbox[1] & mask) != (bbox[3] & mask)) {
2359
+ return z;
2360
+ }
2361
+ }
2362
+ return MAX_ZOOM;
2363
+ }
2364
+ function pointToTileFraction(lon, lat, z) {
2365
+ var sin = Math.sin(lat * d2r),
2366
+ z2 = Math.pow(2, z),
2367
+ x = z2 * (lon / 360 + 0.5),
2368
+ y = z2 * (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
2369
+ return [x, y, z];
2370
+ }
2371
+ var tilebelt = {
2372
+ tileToGeoJSON: tileToGeoJSON,
2373
+ tileToBBOX: tileToBBOX,
2374
+ getChildren: getChildren,
2375
+ getParent: getParent,
2376
+ getSiblings: getSiblings,
2377
+ hasTile: hasTile,
2378
+ hasSiblings: hasSiblings,
2379
+ tilesEqual: tilesEqual,
2380
+ tileToQuadkey: tileToQuadkey,
2381
+ quadkeyToTile: quadkeyToTile,
2382
+ pointToTile: pointToTile,
2383
+ bboxToTile: bboxToTile,
2384
+ pointToTileFraction: pointToTileFraction
2385
+ };
2386
+
2387
+ /**
2388
+ * Given a geometry, create cells and return them in their raw form,
2389
+ * as an array of cell identifiers.
2390
+ *
2391
+ * @alias tiles
2392
+ * @param {Object} geom GeoJSON geometry
2393
+ * @param {Object} limits an object with min_zoom and max_zoom properties
2394
+ * specifying the minimum and maximum level to be tiled.
2395
+ * @returns {Array<Array<number>>} An array of tiles given as [x, y, z] arrays
2396
+ */
2397
+ var tiles = getTiles;
2398
+ function getTiles(geom, limits) {
2399
+ var i,
2400
+ tile,
2401
+ coords = geom.coordinates,
2402
+ maxZoom = limits.max_zoom,
2403
+ tileHash = {},
2404
+ tiles = [];
2405
+ if (geom.type === 'Point') {
2406
+ return [tilebelt.pointToTile(coords[0], coords[1], maxZoom)];
2407
+ } else if (geom.type === 'MultiPoint') {
2408
+ for (i = 0; i < coords.length; i++) {
2409
+ tile = tilebelt.pointToTile(coords[i][0], coords[i][1], maxZoom);
2410
+ tileHash[toID(tile[0], tile[1], tile[2])] = true;
2411
+ }
2412
+ } else if (geom.type === 'LineString') {
2413
+ lineCover(tileHash, coords, maxZoom);
2414
+ } else if (geom.type === 'MultiLineString') {
2415
+ for (i = 0; i < coords.length; i++) {
2416
+ lineCover(tileHash, coords[i], maxZoom);
2417
+ }
2418
+ } else if (geom.type === 'Polygon') {
2419
+ polygonCover(tileHash, tiles, coords, maxZoom);
2420
+ } else if (geom.type === 'MultiPolygon') {
2421
+ for (i = 0; i < coords.length; i++) {
2422
+ polygonCover(tileHash, tiles, coords[i], maxZoom);
2423
+ }
2424
+ } else {
2425
+ throw new Error('Geometry type not implemented');
2426
+ }
2427
+ if (limits.min_zoom !== maxZoom) {
2428
+ // sync tile hash and tile array so that both contain the same tiles
2429
+ var len = tiles.length;
2430
+ appendHashTiles(tileHash, tiles);
2431
+ for (i = 0; i < len; i++) {
2432
+ var t = tiles[i];
2433
+ tileHash[toID(t[0], t[1], t[2])] = true;
2434
+ }
2435
+ return mergeTiles(tileHash, tiles, limits);
2436
+ }
2437
+ appendHashTiles(tileHash, tiles);
2438
+ return tiles;
2439
+ }
2440
+ function mergeTiles(tileHash, tiles, limits) {
2441
+ var mergedTiles = [];
2442
+ for (var z = limits.max_zoom; z > limits.min_zoom; z--) {
2443
+ var parentTileHash = {};
2444
+ var parentTiles = [];
2445
+ for (var i = 0; i < tiles.length; i++) {
2446
+ var t = tiles[i];
2447
+ if (t[0] % 2 === 0 && t[1] % 2 === 0) {
2448
+ var id2 = toID(t[0] + 1, t[1], z),
2449
+ id3 = toID(t[0], t[1] + 1, z),
2450
+ id4 = toID(t[0] + 1, t[1] + 1, z);
2451
+ if (tileHash[id2] && tileHash[id3] && tileHash[id4]) {
2452
+ tileHash[toID(t[0], t[1], t[2])] = false;
2453
+ tileHash[id2] = false;
2454
+ tileHash[id3] = false;
2455
+ tileHash[id4] = false;
2456
+ var parentTile = [t[0] / 2, t[1] / 2, z - 1];
2457
+ if (z - 1 === limits.min_zoom) mergedTiles.push(parentTile);else {
2458
+ parentTileHash[toID(t[0] / 2, t[1] / 2, z - 1)] = true;
2459
+ parentTiles.push(parentTile);
2460
+ }
2461
+ }
2462
+ }
2463
+ }
2464
+ for (i = 0; i < tiles.length; i++) {
2465
+ t = tiles[i];
2466
+ if (tileHash[toID(t[0], t[1], t[2])]) mergedTiles.push(t);
2467
+ }
2468
+ tileHash = parentTileHash;
2469
+ tiles = parentTiles;
2470
+ }
2471
+ return mergedTiles;
2472
+ }
2473
+ function polygonCover(tileHash, tileArray, geom, zoom) {
2474
+ var intersections = [];
2475
+ for (var i = 0; i < geom.length; i++) {
2476
+ var ring = [];
2477
+ lineCover(tileHash, geom[i], zoom, ring);
2478
+ for (var j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
2479
+ var m = (j + 1) % len;
2480
+ var y = ring[j][1];
2481
+
2482
+ // add interesction if it's not local extremum or duplicate
2483
+ if ((y > ring[k][1] || y > ring[m][1]) && (
2484
+ // not local minimum
2485
+ y < ring[k][1] || y < ring[m][1]) &&
2486
+ // not local maximum
2487
+ y !== ring[m][1]) intersections.push(ring[j]);
2488
+ }
2489
+ }
2490
+ intersections.sort(compareTiles); // sort by y, then x
2491
+
2492
+ for (i = 0; i < intersections.length; i += 2) {
2493
+ // fill tiles between pairs of intersections
2494
+ y = intersections[i][1];
2495
+ for (var x = intersections[i][0] + 1; x < intersections[i + 1][0]; x++) {
2496
+ var id = toID(x, y, zoom);
2497
+ if (!tileHash[id]) {
2498
+ tileArray.push([x, y, zoom]);
2499
+ }
2500
+ }
2501
+ }
2502
+ }
2503
+ function compareTiles(a, b) {
2504
+ return a[1] - b[1] || a[0] - b[0];
2505
+ }
2506
+ function lineCover(tileHash, coords, maxZoom, ring) {
2507
+ var prevX, prevY;
2508
+ for (var i = 0; i < coords.length - 1; i++) {
2509
+ var start = tilebelt.pointToTileFraction(coords[i][0], coords[i][1], maxZoom),
2510
+ stop = tilebelt.pointToTileFraction(coords[i + 1][0], coords[i + 1][1], maxZoom),
2511
+ x0 = start[0],
2512
+ y0 = start[1],
2513
+ x1 = stop[0],
2514
+ y1 = stop[1],
2515
+ dx = x1 - x0,
2516
+ dy = y1 - y0;
2517
+ if (dy === 0 && dx === 0) continue;
2518
+ var sx = dx > 0 ? 1 : -1,
2519
+ sy = dy > 0 ? 1 : -1,
2520
+ x = Math.floor(x0),
2521
+ y = Math.floor(y0),
2522
+ tMaxX = dx === 0 ? Infinity : Math.abs(((dx > 0 ? 1 : 0) + x - x0) / dx),
2523
+ tMaxY = dy === 0 ? Infinity : Math.abs(((dy > 0 ? 1 : 0) + y - y0) / dy),
2524
+ tdx = Math.abs(sx / dx),
2525
+ tdy = Math.abs(sy / dy);
2526
+ if (x !== prevX || y !== prevY) {
2527
+ tileHash[toID(x, y, maxZoom)] = true;
2528
+ if (ring && y !== prevY) ring.push([x, y]);
2529
+ prevX = x;
2530
+ prevY = y;
2531
+ }
2532
+ while (tMaxX < 1 || tMaxY < 1) {
2533
+ if (tMaxX < tMaxY) {
2534
+ tMaxX += tdx;
2535
+ x += sx;
2536
+ } else {
2537
+ tMaxY += tdy;
2538
+ y += sy;
2539
+ }
2540
+ tileHash[toID(x, y, maxZoom)] = true;
2541
+ if (ring && y !== prevY) ring.push([x, y]);
2542
+ prevX = x;
2543
+ prevY = y;
2544
+ }
2545
+ }
2546
+ if (ring && y === ring[0][1]) ring.pop();
2547
+ }
2548
+ function appendHashTiles(hash, tiles) {
2549
+ var keys = Object.keys(hash);
2550
+ for (var i = 0; i < keys.length; i++) {
2551
+ tiles.push(fromID(+keys[i]));
2552
+ }
2553
+ }
2554
+ function toID(x, y, z) {
2555
+ var dim = 2 * (1 << z);
2556
+ return (dim * y + x) * 32 + z;
2557
+ }
2558
+ function fromID(id) {
2559
+ var z = id % 32,
2560
+ dim = 2 * (1 << z),
2561
+ xy = (id - z) / 32,
2562
+ x = xy % dim,
2563
+ y = (xy - x) / dim % dim;
2564
+ return [x, y, z];
2565
+ }
2566
+
2567
+ const B = [0x5555555555555555n, 0x3333333333333333n, 0x0f0f0f0f0f0f0f0fn, 0x00ff00ff00ff00ffn, 0x0000ffff0000ffffn, 0x00000000ffffffffn];
2568
+ const S = [0n, 1n, 2n, 4n, 8n, 16n];
2569
+ function tileToCell(tile) {
2570
+ if (tile.z < 0 || tile.z > 26) {
2571
+ throw new Error('Wrong zoom');
2572
+ }
2573
+ const z = BigInt(tile.z);
2574
+ let x = BigInt(tile.x) << 32n - z;
2575
+ let y = BigInt(tile.y) << 32n - z;
2576
+ for (let i = 0; i < 5; i++) {
2577
+ const s = S[5 - i];
2578
+ const b = B[4 - i];
2579
+ x = (x | x << s) & b;
2580
+ y = (y | y << s) & b;
2581
+ }
2582
+ const quadbin = 0x4000000000000000n | 1n << 59n |
2583
+ // | (mode << 59) | (mode_dep << 57)
2584
+ z << 52n | (x | y << 1n) >> 12n | 0xfffffffffffffn >> z * 2n;
2585
+ return quadbin;
2586
+ }
2587
+ function getResolution$1(quadbin) {
2588
+ return quadbin >> 52n & 0x1fn;
2589
+ }
2590
+ function geometryToCells(geometry, resolution) {
2591
+ const zoom = Number(resolution);
2592
+ return tiles(geometry, {
2593
+ min_zoom: zoom,
2594
+ max_zoom: zoom
2595
+ }).map(([x, y, z]) => tileToCell({
2596
+ x,
2597
+ y,
2598
+ z
2599
+ }));
2600
+ }
2601
+
2602
+ function tileFeaturesSpatialIndex(_ref) {
2603
+ let {
2604
+ tiles,
2605
+ spatialFilter,
2606
+ spatialDataColumn,
2607
+ spatialDataType
2608
+ } = _ref;
2609
+ const map = new Map();
2610
+ const spatialIndex = getSpatialIndex(spatialDataType);
2611
+ const resolution = getResolution(tiles, spatialIndex);
2612
+ const spatialIndexIDName = spatialDataColumn ? spatialDataColumn : spatialIndex;
2613
+ if (!resolution) {
2614
+ return [];
2615
+ }
2616
+ const cells = getCellsCoverGeometry(spatialFilter, spatialIndex, resolution);
2617
+ if (!cells?.length) {
2618
+ return [];
2619
+ }
2620
+ // We transform cells to Set to improve the performace
2621
+ const cellsSet = new Set(cells);
2622
+ for (const tile of tiles) {
2623
+ if (tile.isVisible === false || !tile.data) {
2624
+ continue;
2625
+ }
2626
+ tile.data.forEach(d => {
2627
+ if (cellsSet.has(d.id)) {
2628
+ map.set(d.id, {
2629
+ ...d.properties,
2630
+ [spatialIndexIDName]: d.id
2631
+ });
2632
+ }
2633
+ });
2634
+ }
2635
+ return Array.from(map.values());
2636
+ }
2637
+ function getResolution(tiles, spatialIndex) {
2638
+ const data = tiles.find(tile => tile.data?.length)?.data;
2639
+ if (!data) {
2640
+ return;
2641
+ }
2642
+ if (spatialIndex === exports.SpatialIndex.QUADBIN) {
2643
+ return Number(getResolution$1(data[0].id));
2644
+ }
2645
+ if (spatialIndex === exports.SpatialIndex.H3) {
2646
+ return h3Js.getResolution(data[0].id);
2647
+ }
2648
+ }
2649
+ const bboxWest = [-180, -90, 0, 90];
2650
+ const bboxEast = [0, -90, 180, 90];
2651
+ function getCellsCoverGeometry(geometry, spatialIndex, resolution) {
2652
+ if (spatialIndex === exports.SpatialIndex.QUADBIN) {
2653
+ // @ts-expect-error TODO: Probably ought to be stricter about number vs. bigint types in this file.
2654
+ return geometryToCells(geometry, resolution);
2655
+ }
2656
+ if (spatialIndex === exports.SpatialIndex.H3) {
2657
+ // The current H3 polyfill algorithm can't deal with polygon segments of greater than 180 degrees longitude
2658
+ // so we clip the geometry to be sure that none of them is greater than 180 degrees
2659
+ // https://github.com/uber/h3-js/issues/24#issuecomment-431893796
2660
+ return h3Js.polygonToCells(bboxClip(geometry, bboxWest).geometry.coordinates, resolution, true).concat(h3Js.polygonToCells(bboxClip(geometry, bboxEast).geometry.coordinates, resolution, true));
2661
+ }
2662
+ }
2663
+ function getSpatialIndex(spatialDataType) {
2664
+ switch (spatialDataType) {
2665
+ case 'h3':
2666
+ return exports.SpatialIndex.H3;
2667
+ case 'quadbin':
2668
+ return exports.SpatialIndex.QUADBIN;
2669
+ default:
2670
+ throw new Error('Unexpected spatial data type');
2671
+ }
2672
+ }
2673
+
2674
+ /** @internalRemarks Source: @carto/react-core */
2675
+ function tileFeatures(_ref) {
2676
+ let {
2677
+ tiles,
2678
+ spatialFilter,
2679
+ uniqueIdProperty,
2680
+ tileFormat,
2681
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
2682
+ spatialDataType,
2683
+ options = {}
2684
+ } = _ref;
2685
+ // TODO(cleanup): Is an empty response the expected result when spatialFilter
2686
+ // is omitted? Why not make the parameter required, or return the full input?
2687
+ if (!spatialFilter) {
2688
+ return [];
2689
+ }
2690
+ if (spatialDataType !== 'geo') {
2691
+ return tileFeaturesSpatialIndex({
2692
+ tiles: tiles,
2693
+ spatialFilter,
2694
+ spatialDataColumn,
2695
+ spatialDataType
2696
+ });
2697
+ }
2698
+ return tileFeaturesGeometries({
2699
+ tiles,
2700
+ tileFormat,
2701
+ spatialFilter,
2702
+ uniqueIdProperty,
2703
+ options
2704
+ });
2705
+ }
2706
+
2707
+ /** @internalRemarks Source: @carto/react-core */
2708
+ const aggregationFunctions = {
2709
+ count: values => values.length,
2710
+ min: function () {
2711
+ return applyAggregationFunction(min, ...[].slice.call(arguments));
2712
+ },
2713
+ max: function () {
2714
+ return applyAggregationFunction(max, ...[].slice.call(arguments));
2715
+ },
2716
+ sum: function () {
2717
+ return applyAggregationFunction(sum, ...[].slice.call(arguments));
2718
+ },
2719
+ avg: function () {
2720
+ return applyAggregationFunction(avg, ...[].slice.call(arguments));
2721
+ }
2722
+ };
2723
+ /** @internalRemarks Source: @carto/react-core */
2724
+ function aggregate(feature, keys, operation) {
2725
+ if (!keys?.length) {
2726
+ throw new Error('Cannot aggregate a feature without having keys');
2727
+ } else if (keys.length === 1) {
2728
+ const value = feature[keys[0]];
2729
+ return isPotentiallyValidNumber(value) ? Number(value) : value;
2730
+ }
2731
+ const aggregationFn = aggregationFunctions[operation];
2732
+ if (!aggregationFn) {
2733
+ throw new Error(`${operation} isn't a valid aggregation function`);
2734
+ }
2735
+ return aggregationFn(keys.map(column => {
2736
+ const value = feature[column];
2737
+ return isPotentiallyValidNumber(value) ? Number(value) : value;
2738
+ }));
2739
+ }
2740
+ /*
2741
+ * Forced casting to Number (just of non empty strings) allows to work-around
2742
+ * some specific situations, where a big numeric field is transformed into a string when generating the tileset(eg.PG)
2743
+ */
2744
+ function isPotentiallyValidNumber(value) {
2745
+ return typeof value === 'string' && value.trim().length > 0;
2746
+ }
2747
+ const applyAggregationFunction = (aggFn, values, keys, operation) => {
2748
+ const normalizedKeys = normalizeKeys(keys);
2749
+ const elements = (normalizedKeys?.length || 0) <= 1 ? filterFalsyElements(values, normalizedKeys || []) : values;
2750
+ return aggFn(elements, keys, operation);
2751
+ };
2752
+ function filterFalsyElements(values, keys) {
2753
+ const filterFn = value => value !== null && value !== undefined;
2754
+ if (!keys?.length) {
2755
+ return values.filter(filterFn);
2756
+ }
2757
+ return values.filter(v => filterFn(v[keys[0]]));
2758
+ }
2759
+ // Aggregation functions
2760
+ function avg(values, keys, joinOperation) {
2761
+ return sum(values, keys, joinOperation) / (values.length || 1);
2762
+ }
2763
+ function sum(values, keys, joinOperation) {
2764
+ const normalizedKeys = normalizeKeys(keys);
2765
+ if (normalizedKeys) {
2766
+ return values.reduce((a, b) => a + aggregate(b, normalizedKeys, joinOperation), 0);
2767
+ }
2768
+ return values.reduce((a, b) => a + b, 0);
2769
+ }
2770
+ function min(values, keys, joinOperation) {
2771
+ const normalizedKeys = normalizeKeys(keys);
2772
+ if (normalizedKeys) {
2773
+ return values.reduce((a, b) => Math.min(a, aggregate(b, normalizedKeys, joinOperation)), Infinity);
2774
+ }
2775
+ return Math.min(...values);
2776
+ }
2777
+ function max(values, keys, joinOperation) {
2778
+ const normalizedKeys = normalizeKeys(keys);
2779
+ if (normalizedKeys) {
2780
+ return values.reduce((a, b) => Math.max(a, aggregate(b, normalizedKeys, joinOperation)), -Infinity);
2781
+ }
2782
+ return Math.max(...values);
2783
+ }
2784
+ // Aux
2785
+ // Keys can come as a string (one column) or a strings array (multiple column)
2786
+ // Use always an array to make the code easier
2787
+ function normalizeKeys(keys) {
2788
+ return Array.isArray(keys) ? keys : typeof keys === 'string' ? [keys] : undefined;
2789
+ }
2790
+
2791
+ /***
2792
+ Copyright 2013 Teun Duynstee
2793
+
2794
+ Licensed under the Apache License, Version 2.0 (the "License");
2795
+ you may not use this file except in compliance with the License.
2796
+ You may obtain a copy of the License at
2797
+
2798
+ http://www.apache.org/licenses/LICENSE-2.0
2799
+
2800
+ Unless required by applicable law or agreed to in writing, software
2801
+ distributed under the License is distributed on an "AS IS" BASIS,
2802
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2803
+ See the License for the specific language governing permissions and
2804
+ limitations under the License.
2805
+ */
2806
+ var thenBy_module = function () {
2807
+ function identity(v) {
2808
+ return v;
2809
+ }
2810
+ function ignoreCase(v) {
2811
+ return typeof v === "string" ? v.toLowerCase() : v;
2812
+ }
2813
+ function makeCompareFunction(f, opt) {
2814
+ opt = typeof opt === "object" ? opt : {
2815
+ direction: opt
2816
+ };
2817
+ if (typeof f != "function") {
2818
+ var prop = f;
2819
+ // make unary function
2820
+ f = function (v1) {
2821
+ return !!v1[prop] ? v1[prop] : "";
2822
+ };
2823
+ }
2824
+ if (f.length === 1) {
2825
+ // f is a unary function mapping a single item to its sort score
2826
+ var uf = f;
2827
+ var preprocess = opt.ignoreCase ? ignoreCase : identity;
2828
+ var cmp = opt.cmp || function (v1, v2) {
2829
+ return v1 < v2 ? -1 : v1 > v2 ? 1 : 0;
2830
+ };
2831
+ f = function (v1, v2) {
2832
+ return cmp(preprocess(uf(v1)), preprocess(uf(v2)));
2833
+ };
2834
+ }
2835
+ const descTokens = {
2836
+ "-1": '',
2837
+ desc: ''
2838
+ };
2839
+ if (opt.direction in descTokens) return function (v1, v2) {
2840
+ return -f(v1, v2);
2841
+ };
2842
+ return f;
2843
+ }
2844
+
2845
+ /* adds a secondary compare function to the target function (`this` context)
2846
+ which is applied in case the first one returns 0 (equal)
2847
+ returns a new compare function, which has a `thenBy` method as well */
2848
+ function tb(func, opt) {
2849
+ /* should get value false for the first call. This can be done by calling the
2850
+ exported function, or the firstBy property on it (for es6 module compatibility)
2851
+ */
2852
+ var x = typeof this == "function" && !this.firstBy ? this : false;
2853
+ var y = makeCompareFunction(func, opt);
2854
+ var f = x ? function (a, b) {
2855
+ return x(a, b) || y(a, b);
2856
+ } : y;
2857
+ f.thenBy = tb;
2858
+ return f;
2859
+ }
2860
+ tb.firstBy = tb;
2861
+ return tb;
2862
+ }();
2863
+
2864
+ /**
2865
+ * Apply sort structure to a collection of features
2866
+ * @param features
2867
+ * @param [sortOptions]
2868
+ * @param [sortOptions.sortBy] - One or more columns to sort by
2869
+ * @param [sortOptions.sortByDirection] - Direction by the columns will be sorted
2870
+ * @param [sortOptions.sortByColumnType] - Column type
2871
+ * @internal
2872
+ * @internalRemarks Source: @carto/react-core
2873
+ */
2874
+ function applySorting(features, _temp) {
2875
+ let {
2876
+ sortBy,
2877
+ sortByDirection = 'asc',
2878
+ sortByColumnType = 'string'
2879
+ } = _temp === void 0 ? {} : _temp;
2880
+ // If sortBy is undefined, pass all features
2881
+ if (sortBy === undefined) {
2882
+ return features;
2883
+ }
2884
+ // sortOptions exists, but are bad formatted
2885
+ const isValidSortBy = Array.isArray(sortBy) && sortBy.length ||
2886
+ // sortBy can be an array of columns
2887
+ typeof sortBy === 'string'; // or just one column
2888
+ if (!isValidSortBy) {
2889
+ throw new Error('Sorting options are bad formatted');
2890
+ }
2891
+ const sortFn = createSortFn({
2892
+ sortBy,
2893
+ sortByDirection,
2894
+ sortByColumnType: sortByColumnType || 'string'
2895
+ });
2896
+ return features.sort(sortFn);
2897
+ }
2898
+ // Aux
2899
+ function createSortFn(_ref) {
2900
+ let {
2901
+ sortBy,
2902
+ sortByDirection,
2903
+ sortByColumnType
2904
+ } = _ref;
2905
+ const [firstSortOption, ...othersSortOptions] = normalizeSortByOptions({
2906
+ sortBy,
2907
+ sortByDirection,
2908
+ sortByColumnType
2909
+ });
2910
+ let sortFn = thenBy_module.firstBy(...firstSortOption);
2911
+ for (let sortOptions of othersSortOptions) {
2912
+ sortFn = sortFn.thenBy(...sortOptions);
2913
+ }
2914
+ return sortFn;
2915
+ }
2916
+ function normalizeSortByOptions(_ref2) {
2917
+ let {
2918
+ sortBy,
2919
+ sortByDirection,
2920
+ sortByColumnType
2921
+ } = _ref2;
2922
+ const numberFormat = sortByColumnType === 'number' && {
2923
+ cmp: (a, b) => a - b
2924
+ };
2925
+ if (!Array.isArray(sortBy)) {
2926
+ sortBy = [sortBy];
2927
+ }
2928
+ return sortBy.map(sortByEl => {
2929
+ // sortByEl is 'column'
2930
+ if (typeof sortByEl === 'string') {
2931
+ return [sortByEl, {
2932
+ direction: sortByDirection,
2933
+ ...numberFormat
2934
+ }];
2935
+ }
2936
+ if (Array.isArray(sortByEl)) {
2937
+ // sortBy is ['column']
2938
+ if (sortByEl[1] === undefined) {
2939
+ return [sortByEl, {
2940
+ direction: sortByDirection,
2941
+ ...numberFormat
2942
+ }];
2943
+ }
2944
+ // sortBy is ['column', { ... }]
2945
+ if (typeof sortByEl[1] === 'object') {
2946
+ const othersSortOptions = numberFormat ? {
2947
+ ...numberFormat,
2948
+ ...sortByEl[1]
2949
+ } : sortByEl[1];
2950
+ return [sortByEl[0], {
2951
+ direction: sortByDirection,
2952
+ ...othersSortOptions
2953
+ }];
2954
+ }
2955
+ }
2956
+ return sortByEl;
2957
+ });
2958
+ }
2959
+
2960
+ /** @internalRemarks Source: @carto/react-core */
2961
+ function groupValuesByColumn(_ref) {
2962
+ let {
2963
+ data,
2964
+ valuesColumns,
2965
+ joinOperation,
2966
+ keysColumn,
2967
+ operation
2968
+ } = _ref;
2969
+ if (Array.isArray(data) && data.length === 0) {
2970
+ return null;
2971
+ }
2972
+ const groups = data.reduce((accumulator, item) => {
2973
+ const group = item[keysColumn];
2974
+ const values = accumulator.get(group) || [];
2975
+ accumulator.set(group, values);
2976
+ const aggregatedValue = aggregate(item, valuesColumns, joinOperation);
2977
+ const isValid = (operation === 'count' ? true : aggregatedValue !== null) && aggregatedValue !== undefined;
2978
+ if (isValid) {
2979
+ values.push(aggregatedValue);
2980
+ accumulator.set(group, values);
2981
+ }
2982
+ return accumulator;
2983
+ }, new Map()); // We use a map to be able to maintain the type in the key value
2984
+ const targetOperation = aggregationFunctions[operation];
2985
+ if (targetOperation) {
2986
+ return Array.from(groups).map(_ref2 => {
2987
+ let [name, value] = _ref2;
2988
+ return {
2989
+ name,
2990
+ value: targetOperation(value)
2991
+ };
2992
+ });
2993
+ }
2994
+ return [];
2995
+ }
2996
+
2997
+ /**
2998
+ * Returns midnight (local time) on the Monday preceeding a given date, in
2999
+ * milliseconds since the UNIX epoch.
3000
+ */
3001
+ /**
3002
+ * Returns midnight (UTC) on the Monday preceeding a given date, in
3003
+ * milliseconds since the UNIX epoch.
3004
+ */
3005
+ function getUTCMonday(date) {
3006
+ const dateCp = new Date(date);
3007
+ const day = dateCp.getUTCDay();
3008
+ const diff = dateCp.getUTCDate() - day + (day ? 1 : -6); // adjust when day is sunday
3009
+ dateCp.setUTCDate(diff);
3010
+ return Date.UTC(dateCp.getUTCFullYear(), dateCp.getUTCMonth(), dateCp.getUTCDate());
3011
+ }
3012
+
3013
+ const GROUP_KEY_FN_MAPPING = {
3014
+ year: date => Date.UTC(date.getUTCFullYear()),
3015
+ month: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth()),
3016
+ week: date => getUTCMonday(date),
3017
+ day: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()),
3018
+ hour: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours()),
3019
+ minute: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes()),
3020
+ second: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds())
3021
+ };
3022
+ /** @internalRemarks Source: @carto/react-core */
3023
+ function groupValuesByDateColumn(_ref) {
3024
+ let {
3025
+ data,
3026
+ valuesColumns,
3027
+ joinOperation,
3028
+ keysColumn,
3029
+ groupType,
3030
+ operation
3031
+ } = _ref;
3032
+ if (Array.isArray(data) && data.length === 0) {
3033
+ return null;
3034
+ }
3035
+ const groupKeyFn = GROUP_KEY_FN_MAPPING[groupType];
3036
+ if (!groupKeyFn) {
3037
+ return null;
3038
+ }
3039
+ const groups = data.reduce((acc, item) => {
3040
+ const value = item[keysColumn];
3041
+ const formattedValue = new Date(value);
3042
+ const groupKey = groupKeyFn(formattedValue);
3043
+ if (!isNaN(groupKey)) {
3044
+ let groupedValues = acc.get(groupKey);
3045
+ if (!groupedValues) {
3046
+ groupedValues = [];
3047
+ acc.set(groupKey, groupedValues);
3048
+ }
3049
+ const aggregatedValue = aggregate(item, valuesColumns, joinOperation);
3050
+ const isValid = aggregatedValue !== null && aggregatedValue !== undefined;
3051
+ if (isValid) {
3052
+ groupedValues.push(aggregatedValue);
3053
+ acc.set(groupKey, groupedValues);
3054
+ }
3055
+ }
3056
+ return acc;
3057
+ }, new Map());
3058
+ const targetOperation = aggregationFunctions[operation];
3059
+ return [...groups.entries()].map(_ref2 => {
3060
+ let [name, value] = _ref2;
3061
+ return {
3062
+ name,
3063
+ value: targetOperation(value)
3064
+ };
3065
+ }).sort((a, b) => a.name - b.name);
3066
+ }
3067
+
3068
+ /**
3069
+ * Histogram computation.
3070
+ * @internalRemarks Source: @carto/react-core
3071
+ */
3072
+ function histogram(_ref) {
3073
+ let {
3074
+ data,
3075
+ valuesColumns,
3076
+ joinOperation,
3077
+ ticks,
3078
+ operation
3079
+ } = _ref;
3080
+ if (Array.isArray(data) && data.length === 0) {
3081
+ return [];
3082
+ }
3083
+ const binsContainer = [Number.MIN_SAFE_INTEGER, ...ticks].map((tick, index, arr) => ({
3084
+ bin: index,
3085
+ start: tick,
3086
+ end: index === arr.length - 1 ? Number.MAX_SAFE_INTEGER : arr[index + 1],
3087
+ values: []
3088
+ }));
3089
+ data.forEach(feature => {
3090
+ const featureValue = aggregate(feature, valuesColumns, joinOperation);
3091
+ const isValid = featureValue !== null && featureValue !== undefined;
3092
+ if (!isValid) {
3093
+ return;
3094
+ }
3095
+ const binContainer = binsContainer.find(bin => bin.start <= featureValue && bin.end > featureValue);
3096
+ if (!binContainer) {
3097
+ return;
3098
+ }
3099
+ binContainer.values.push(featureValue);
3100
+ });
3101
+ const targetOperation = aggregationFunctions[operation];
3102
+ const transformedBins = binsContainer.map(binContainer => binContainer.values);
3103
+ return transformedBins.map(values => values.length ? targetOperation(values) : 0);
3104
+ }
3105
+
3106
+ /**
3107
+ * Filters invalid features and formats data.
3108
+ * @internalRemarks Source: @carto/react-core
3109
+ */
3110
+ function scatterPlot(_ref) {
3111
+ let {
3112
+ data,
3113
+ xAxisColumns,
3114
+ xAxisJoinOperation,
3115
+ yAxisColumns,
3116
+ yAxisJoinOperation
3117
+ } = _ref;
3118
+ return data.reduce((acc, feature) => {
3119
+ const xValue = aggregate(feature, xAxisColumns, xAxisJoinOperation);
3120
+ const xIsValid = xValue !== null && xValue !== undefined;
3121
+ const yValue = aggregate(feature, yAxisColumns, yAxisJoinOperation);
3122
+ const yIsValid = yValue !== null && yValue !== undefined;
3123
+ if (xIsValid && yIsValid) {
3124
+ acc.push([xValue, yValue]);
3125
+ }
3126
+ return acc;
3127
+ }, []);
3128
+ }
3129
+
3130
+ /**
3131
+ * Source for Widget API requests on a data source defined by a tileset.
3132
+ *
3133
+ * Generally not intended to be constructed directly. Instead, call
3134
+ * {@link vectorTilesetSource}, {@link h3TilesetSource}, or {@link quadbinTilesetSource},
3135
+ * which can be shared with map layers. Sources contain a `widgetSource`
3136
+ * property, for use by widget implementations.
3137
+ *
3138
+ * Example:
3139
+ *
3140
+ * ```javascript
3141
+ * import { vectorTilesetSource } from '@carto/api-client';
3142
+ *
3143
+ * const data = vectorTilesetSource({
3144
+ * accessToken: '••••',
3145
+ * connectionName: 'carto_dw',
3146
+ * tableName: 'carto-demo-data.demo_rasters.my_tileset_source'
3147
+ * });
3148
+ *
3149
+ * const { widgetSource } = await data;
3150
+ * ```
3151
+ */
3152
+ class WidgetTilesetSource extends WidgetSource {
3153
+ constructor() {
3154
+ super(...arguments);
3155
+ this._tiles = [];
3156
+ this._features = [];
3157
+ }
3158
+ getModelSource(owner) {
3159
+ return {
3160
+ ...super._getModelSource(owner),
3161
+ type: 'tileset',
3162
+ data: this.props.tableName
3163
+ };
3164
+ }
3165
+ /**
3166
+ * Loads features as a list of tiles (typically provided by deck.gl).
3167
+ * After tiles are loaded, {@link extractTileFeatures} must be called
3168
+ * before computing statistics on the tiles.
3169
+ */
3170
+ loadTiles(tiles) {
3171
+ this._tiles = tiles;
3172
+ }
3173
+ /**
3174
+ * Extracts feature data from tiles previously loaded with {@link loadTiles}.
3175
+ * Must be called before computing statistics on tiles.
3176
+ */
3177
+ extractTileFeatures(_ref) {
3178
+ let {
3179
+ spatialFilter,
3180
+ uniqueIdProperty,
3181
+ options
3182
+ } = _ref;
3183
+ this._features = tileFeatures({
3184
+ tiles: this._tiles,
3185
+ options,
3186
+ spatialFilter,
3187
+ uniqueIdProperty,
3188
+ tileFormat: this.props.tileFormat,
3189
+ spatialDataColumn: this.props.spatialDataColumn,
3190
+ spatialDataType: this.props.spatialDataType
3191
+ });
3192
+ }
3193
+ /** Loads features as GeoJSON (used for testing). */
3194
+ loadGeoJSON(_ref2) {
3195
+ let {
3196
+ geojson,
3197
+ spatialFilter,
3198
+ uniqueIdProperty
3199
+ } = _ref2;
3200
+ this._features = geojsonFeatures({
3201
+ geojson,
3202
+ spatialFilter,
3203
+ uniqueIdProperty
3204
+ });
3205
+ }
3206
+ getFeatures(options) {
3207
+ try {
3208
+ throw new Error('getFeatures not supported for tilesets');
3209
+ return Promise.resolve();
3210
+ } catch (e) {
3211
+ return Promise.reject(e);
3212
+ }
3213
+ }
3214
+ getFormula(_ref3) {
3215
+ let {
3216
+ column = '*',
3217
+ operation = 'count',
3218
+ joinOperation,
3219
+ filterOwner
3220
+ } = _ref3;
3221
+ try {
3222
+ const _this = this;
3223
+ if (operation === 'custom') {
3224
+ throw new Error('Custom aggregation not supported for tilesets');
3225
+ }
3226
+ if (!_this._features.length) {
3227
+ return Promise.resolve({
3228
+ value: null
3229
+ });
3230
+ }
3231
+ // Column is required except when operation is 'count'.
3232
+ if (column && column !== '*' || operation !== 'count') {
3233
+ assertColumn(_this._features, column);
3234
+ }
3235
+ const filteredFeatures = _this._getFilteredFeatures(filterOwner);
3236
+ if (filteredFeatures.length === 0 && operation !== 'count') {
3237
+ return Promise.resolve({
3238
+ value: null
3239
+ });
3240
+ }
3241
+ const targetOperation = aggregationFunctions[operation];
3242
+ return Promise.resolve({
3243
+ value: targetOperation(filteredFeatures, column, joinOperation)
3244
+ });
3245
+ } catch (e) {
3246
+ return Promise.reject(e);
3247
+ }
3248
+ }
3249
+ getHistogram(_ref4) {
3250
+ let {
3251
+ operation = 'count',
3252
+ ticks,
3253
+ column,
3254
+ joinOperation,
3255
+ filterOwner
3256
+ } = _ref4;
3257
+ try {
3258
+ const _this2 = this;
3259
+ if (!_this2._features.length) {
3260
+ return Promise.resolve([]);
3261
+ }
3262
+ const filteredFeatures = _this2._getFilteredFeatures(filterOwner);
3263
+ assertColumn(_this2._features, column);
3264
+ return Promise.resolve(histogram({
3265
+ data: filteredFeatures,
3266
+ valuesColumns: normalizeColumns(column),
3267
+ joinOperation,
3268
+ ticks,
3269
+ operation
3270
+ }));
3271
+ } catch (e) {
3272
+ return Promise.reject(e);
3273
+ }
3274
+ }
3275
+ getCategories(_ref5) {
3276
+ let {
3277
+ column,
3278
+ operation = 'count',
3279
+ operationColumn,
3280
+ joinOperation,
3281
+ filterOwner
3282
+ } = _ref5;
3283
+ try {
3284
+ const _this3 = this;
3285
+ if (!_this3._features.length) {
3286
+ return Promise.resolve([]);
3287
+ }
3288
+ const filteredFeatures = _this3._getFilteredFeatures(filterOwner);
3289
+ assertColumn(_this3._features, column, operationColumn);
3290
+ const groups = groupValuesByColumn({
3291
+ data: filteredFeatures,
3292
+ valuesColumns: normalizeColumns(operationColumn || column),
3293
+ joinOperation,
3294
+ keysColumn: column,
3295
+ operation
3296
+ });
3297
+ return Promise.resolve(groups || []);
3298
+ } catch (e) {
3299
+ return Promise.reject(e);
3300
+ }
3301
+ }
3302
+ getScatter(_ref6) {
3303
+ let {
3304
+ xAxisColumn,
3305
+ yAxisColumn,
3306
+ xAxisJoinOperation,
3307
+ yAxisJoinOperation,
3308
+ filterOwner
3309
+ } = _ref6;
3310
+ try {
3311
+ const _this4 = this;
3312
+ if (!_this4._features.length) {
3313
+ return Promise.resolve([]);
3314
+ }
3315
+ const filteredFeatures = _this4._getFilteredFeatures(filterOwner);
3316
+ assertColumn(_this4._features, xAxisColumn, yAxisColumn);
3317
+ return Promise.resolve(scatterPlot({
3318
+ data: filteredFeatures,
3319
+ xAxisColumns: normalizeColumns(xAxisColumn),
3320
+ xAxisJoinOperation,
3321
+ yAxisColumns: normalizeColumns(yAxisColumn),
3322
+ yAxisJoinOperation
3323
+ }));
3324
+ } catch (e) {
3325
+ return Promise.reject(e);
3326
+ }
3327
+ }
3328
+ getTable(options) {
3329
+ try {
3330
+ const _this5 = this;
3331
+ const {
3332
+ filterOwner,
3333
+ spatialFilter,
3334
+ abortController,
3335
+ ...params
3336
+ } = options;
3337
+ const {
3338
+ columns,
3339
+ searchFilterColumn,
3340
+ searchFilterText,
3341
+ sortBy,
3342
+ sortDirection,
3343
+ sortByColumnType,
3344
+ offset = 0,
3345
+ limit = 10
3346
+ } = params;
3347
+ if (!_this5._features.length) {
3348
+ return Promise.resolve({
3349
+ rows: [],
3350
+ totalCount: 0
3351
+ });
3352
+ }
3353
+ // Filter.
3354
+ let filteredFeatures = _this5._getFilteredFeatures(filterOwner);
3355
+ // Search.
3356
+ // TODO: Could we get the same behavior by applying filters in loadTiles()?
3357
+ if (searchFilterColumn && searchFilterText) {
3358
+ filteredFeatures = filteredFeatures.filter(row => row[searchFilterColumn] && String(row[searchFilterColumn]).toLowerCase().includes(String(searchFilterText).toLowerCase()));
3359
+ }
3360
+ // Sort.
3361
+ let rows = applySorting(filteredFeatures, {
3362
+ sortBy,
3363
+ sortByDirection: sortDirection,
3364
+ sortByColumnType
3365
+ });
3366
+ const totalCount = rows.length;
3367
+ // Offset and limit.
3368
+ rows = rows.slice(Math.min(offset, totalCount), Math.min(offset + limit, totalCount));
3369
+ // Select columns.
3370
+ rows = rows.map(srcRow => {
3371
+ const dstRow = {};
3372
+ for (const column of columns) {
3373
+ dstRow[column] = srcRow[column];
3374
+ }
3375
+ return dstRow;
3376
+ });
3377
+ return Promise.resolve({
3378
+ rows,
3379
+ totalCount
3380
+ });
3381
+ } catch (e) {
3382
+ return Promise.reject(e);
3383
+ }
3384
+ }
3385
+ getTimeSeries(_ref7) {
3386
+ let {
3387
+ column,
3388
+ stepSize,
3389
+ operation,
3390
+ operationColumn,
3391
+ joinOperation,
3392
+ filterOwner
3393
+ } = _ref7;
3394
+ try {
3395
+ const _this6 = this;
3396
+ if (!_this6._features.length) {
3397
+ return Promise.resolve({
3398
+ rows: []
3399
+ });
3400
+ }
3401
+ const filteredFeatures = _this6._getFilteredFeatures(filterOwner);
3402
+ assertColumn(_this6._features, column, operationColumn);
3403
+ const rows = groupValuesByDateColumn({
3404
+ data: filteredFeatures,
3405
+ valuesColumns: normalizeColumns(operationColumn || column),
3406
+ keysColumn: column,
3407
+ groupType: stepSize,
3408
+ operation,
3409
+ joinOperation
3410
+ }) || [];
3411
+ return Promise.resolve({
3412
+ rows
3413
+ });
3414
+ } catch (e) {
3415
+ return Promise.reject(e);
3416
+ }
3417
+ }
3418
+ getRange(_ref8) {
3419
+ let {
3420
+ column,
3421
+ filterOwner
3422
+ } = _ref8;
3423
+ try {
3424
+ const _this7 = this;
3425
+ if (!_this7._features.length) {
3426
+ // TODO: Is this the only nullable response in the Widgets API? If so,
3427
+ // can we do something more consistent?
3428
+ return Promise.resolve(null);
3429
+ }
3430
+ assertColumn(_this7._features, column);
3431
+ const filteredFeatures = _this7._getFilteredFeatures(filterOwner);
3432
+ return Promise.resolve({
3433
+ min: aggregationFunctions.min(filteredFeatures, column),
3434
+ max: aggregationFunctions.max(filteredFeatures, column)
3435
+ });
3436
+ } catch (e) {
3437
+ return Promise.reject(e);
3438
+ }
3439
+ }
3440
+ /****************************************************************************
3441
+ * INTERNAL
3442
+ */
3443
+ _getFilteredFeatures(filterOwner) {
3444
+ return applyFilters(this._features, getApplicableFilters(filterOwner, this.props.filters), this.props.filtersLogicalOperator || 'and');
3445
+ }
3446
+ }
3447
+ function assertColumn(features) {
3448
+ // TODO(cleanup): Can drop support for multiple column shapes here?
3449
+ // Due to the multiple column shape, we normalise it as an array with normalizeColumns
3450
+ const columns = Array.from(new Set([].slice.call(arguments, 1).map(normalizeColumns).flat()));
3451
+ const featureKeys = Object.keys(features[0]);
3452
+ const invalidColumns = columns.filter(column => !featureKeys.includes(column));
3453
+ if (invalidColumns.length) {
3454
+ throw new InvalidColumnError(`Missing column(s): ${invalidColumns.join(', ')}`);
3455
+ }
3456
+ }
3457
+ function normalizeColumns(columns) {
3458
+ return Array.isArray(columns) ? columns : typeof columns === 'string' ? [columns] : [];
3459
+ }
3460
+
3461
+ // deck.gl
3462
+ // SPDX-License-Identifier: MIT
3463
+ // Copyright (c) vis.gl contributors
3464
+ /* eslint-disable camelcase */
3465
+ const h3QuerySource = function (options) {
3466
+ try {
3467
+ const {
3468
+ aggregationExp,
3469
+ aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
3470
+ sqlQuery,
3471
+ spatialDataColumn = 'h3',
3472
+ queryParameters,
3473
+ filters
3474
+ } = options;
3475
+ const spatialDataType = 'h3';
3476
+ const urlParameters = {
3477
+ aggregationExp,
3478
+ spatialDataColumn,
3479
+ spatialDataType,
3480
+ q: sqlQuery
3481
+ };
3482
+ if (aggregationResLevel) {
3483
+ urlParameters.aggregationResLevel = String(aggregationResLevel);
3484
+ }
3485
+ if (queryParameters) {
3486
+ urlParameters.queryParameters = queryParameters;
3487
+ }
3488
+ if (filters) {
3489
+ urlParameters.filters = filters;
3490
+ }
3491
+ return Promise.resolve(baseSource('query', options, urlParameters).then(result => ({
3492
+ ...result,
3493
+ widgetSource: new WidgetQuerySource({
3494
+ ...options,
3495
+ // NOTE: Parameters with default values above must be explicitly passed here.
3496
+ spatialDataColumn,
3497
+ spatialDataType
3498
+ })
3499
+ })));
3500
+ } catch (e) {
3501
+ return Promise.reject(e);
3502
+ }
3503
+ };
3504
+
3505
+ // deck.gl
3506
+ // SPDX-License-Identifier: MIT
3507
+ // Copyright (c) vis.gl contributors
3508
+ /* eslint-disable camelcase */
3509
+ const h3TableSource = function (options) {
3510
+ try {
3511
+ const {
3512
+ aggregationExp,
3513
+ aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
3514
+ spatialDataColumn = 'h3',
1604
3515
  tableName,
1605
3516
  filters
1606
3517
  } = options;
@@ -1631,18 +3542,32 @@ const h3TableSource = function (options) {
1631
3542
  }
1632
3543
  };
1633
3544
 
3545
+ function getTileFormat(tilejson) {
3546
+ const tileParams = new URL(tilejson.tiles[0]).searchParams;
3547
+ return tileParams.get('formatTiles') === 'mvt' ? exports.TileFormat.MVT : exports.TileFormat.BINARY;
3548
+ }
3549
+
1634
3550
  // deck.gl
1635
3551
  // SPDX-License-Identifier: MIT
1636
3552
  // Copyright (c) vis.gl contributors
1637
3553
  const h3TilesetSource = function (options) {
1638
3554
  try {
1639
3555
  const {
1640
- tableName
3556
+ tableName,
3557
+ spatialDataColumn = 'h3'
1641
3558
  } = options;
1642
3559
  const urlParameters = {
1643
3560
  name: tableName
1644
3561
  };
1645
- return Promise.resolve(baseSource('tileset', options, urlParameters));
3562
+ return Promise.resolve(baseSource('tileset', options, urlParameters).then(result => ({
3563
+ ...result,
3564
+ widgetSource: new WidgetTilesetSource({
3565
+ ...options,
3566
+ tileFormat: getTileFormat(result),
3567
+ spatialDataColumn,
3568
+ spatialDataType: 'h3'
3569
+ })
3570
+ })));
1646
3571
  } catch (e) {
1647
3572
  return Promise.reject(e);
1648
3573
  }
@@ -1759,12 +3684,21 @@ const quadbinTableSource = function (options) {
1759
3684
  const quadbinTilesetSource = function (options) {
1760
3685
  try {
1761
3686
  const {
1762
- tableName
3687
+ tableName,
3688
+ spatialDataColumn = 'quadbin'
1763
3689
  } = options;
1764
3690
  const urlParameters = {
1765
3691
  name: tableName
1766
3692
  };
1767
- return Promise.resolve(baseSource('tileset', options, urlParameters));
3693
+ return Promise.resolve(baseSource('tileset', options, urlParameters).then(result => ({
3694
+ ...result,
3695
+ widgetSource: new WidgetTilesetSource({
3696
+ ...options,
3697
+ tileFormat: getTileFormat(result),
3698
+ spatialDataColumn,
3699
+ spatialDataType: 'quadbin'
3700
+ })
3701
+ })));
1768
3702
  } catch (e) {
1769
3703
  return Promise.reject(e);
1770
3704
  }
@@ -1779,7 +3713,7 @@ const vectorQuerySource = function (options) {
1779
3713
  const {
1780
3714
  columns,
1781
3715
  filters,
1782
- spatialDataColumn = 'geom',
3716
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
1783
3717
  sqlQuery,
1784
3718
  tileResolution = DEFAULT_TILE_RESOLUTION,
1785
3719
  queryParameters,
@@ -1828,7 +3762,7 @@ const vectorTableSource = function (options) {
1828
3762
  const {
1829
3763
  columns,
1830
3764
  filters,
1831
- spatialDataColumn = 'geom',
3765
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
1832
3766
  tableName,
1833
3767
  tileResolution = DEFAULT_TILE_RESOLUTION,
1834
3768
  aggregationExp
@@ -1870,12 +3804,21 @@ const vectorTableSource = function (options) {
1870
3804
  const vectorTilesetSource = function (options) {
1871
3805
  try {
1872
3806
  const {
1873
- tableName
3807
+ tableName,
3808
+ spatialDataColumn = DEFAULT_GEO_COLUMN
1874
3809
  } = options;
1875
3810
  const urlParameters = {
1876
3811
  name: tableName
1877
3812
  };
1878
- return Promise.resolve(baseSource('tileset', options, urlParameters));
3813
+ return Promise.resolve(baseSource('tileset', options, urlParameters).then(result => ({
3814
+ ...result,
3815
+ widgetSource: new WidgetTilesetSource({
3816
+ ...options,
3817
+ tileFormat: getTileFormat(result),
3818
+ spatialDataColumn,
3819
+ spatialDataType: 'geo'
3820
+ })
3821
+ })));
1879
3822
  } catch (e) {
1880
3823
  return Promise.reject(e);
1881
3824
  }
@@ -1934,24 +3877,39 @@ const query = function (options) {
1934
3877
 
1935
3878
  exports.CartoAPIError = CartoAPIError;
1936
3879
  exports.DEFAULT_API_BASE_URL = DEFAULT_API_BASE_URL;
3880
+ exports.FEATURE_GEOM_PROPERTY = FEATURE_GEOM_PROPERTY;
1937
3881
  exports.SOURCE_DEFAULTS = SOURCE_DEFAULTS;
1938
- exports.WidgetBaseSource = WidgetBaseSource;
1939
3882
  exports.WidgetQuerySource = WidgetQuerySource;
3883
+ exports.WidgetRemoteSource = WidgetRemoteSource;
3884
+ exports.WidgetSource = WidgetSource;
1940
3885
  exports.WidgetTableSource = WidgetTableSource;
3886
+ exports.WidgetTilesetSource = WidgetTilesetSource;
1941
3887
  exports.addFilter = addFilter;
3888
+ exports.aggregate = aggregate;
3889
+ exports.aggregationFunctions = aggregationFunctions;
3890
+ exports.applyFilters = applyFilters;
3891
+ exports.applySorting = applySorting;
1942
3892
  exports.boundaryQuerySource = boundaryQuerySource;
1943
3893
  exports.boundaryTableSource = boundaryTableSource;
3894
+ exports.buildBinaryFeatureFilter = buildBinaryFeatureFilter;
3895
+ exports.buildFeatureFilter = buildFeatureFilter;
1944
3896
  exports.buildPublicMapUrl = buildPublicMapUrl;
1945
3897
  exports.buildStatsUrl = buildStatsUrl;
1946
3898
  exports.clearFilters = clearFilters;
1947
3899
  exports.createPolygonSpatialFilter = createPolygonSpatialFilter;
1948
3900
  exports.createViewportSpatialFilter = createViewportSpatialFilter;
3901
+ exports.filterFunctions = filterFunctions;
3902
+ exports.geojsonFeatures = geojsonFeatures;
1949
3903
  exports.getClient = getClient;
1950
3904
  exports.getFilter = getFilter;
3905
+ exports.groupValuesByColumn = groupValuesByColumn;
3906
+ exports.groupValuesByDateColumn = groupValuesByDateColumn;
1951
3907
  exports.h3QuerySource = h3QuerySource;
1952
3908
  exports.h3TableSource = h3TableSource;
1953
3909
  exports.h3TilesetSource = h3TilesetSource;
1954
3910
  exports.hasFilter = hasFilter;
3911
+ exports.histogram = histogram;
3912
+ exports.makeIntervalComplete = makeIntervalComplete;
1955
3913
  exports.quadbinQuerySource = quadbinQuerySource;
1956
3914
  exports.quadbinTableSource = quadbinTableSource;
1957
3915
  exports.quadbinTilesetSource = quadbinTilesetSource;
@@ -1959,7 +3917,12 @@ exports.query = query;
1959
3917
  exports.rasterSource = rasterSource;
1960
3918
  exports.removeFilter = removeFilter;
1961
3919
  exports.requestWithParameters = requestWithParameters;
3920
+ exports.scatterPlot = scatterPlot;
1962
3921
  exports.setClient = setClient;
3922
+ exports.tileFeatures = tileFeatures;
3923
+ exports.tileFeaturesGeometries = tileFeaturesGeometries;
3924
+ exports.tileFeaturesSpatialIndex = tileFeaturesSpatialIndex;
3925
+ exports.transformToTileCoords = transformToTileCoords;
1963
3926
  exports.vectorQuerySource = vectorQuerySource;
1964
3927
  exports.vectorTableSource = vectorTableSource;
1965
3928
  exports.vectorTilesetSource = vectorTilesetSource;