@carto/api-client 0.4.5 → 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 (78) hide show
  1. package/build/api-client.cjs +2179 -216
  2. package/build/api-client.cjs.map +1 -1
  3. package/build/api-client.modern.js +2061 -226
  4. package/build/api-client.modern.js.map +1 -1
  5. package/build/constants.d.ts +22 -0
  6. package/build/filters/Filter.d.ts +13 -0
  7. package/build/filters/FilterTypes.d.ts +3 -0
  8. package/build/filters/geosjonFeatures.d.ts +8 -0
  9. package/build/filters/index.d.ts +6 -0
  10. package/build/filters/tileFeatures.d.ts +20 -0
  11. package/build/filters/tileFeaturesGeometries.d.ts +13 -0
  12. package/build/filters/tileFeaturesSpatialIndex.d.ts +10 -0
  13. package/build/index.d.ts +4 -0
  14. package/build/models/index.d.ts +1 -1
  15. package/build/operations/aggregation.d.ts +8 -0
  16. package/build/operations/applySorting.d.ts +20 -0
  17. package/build/operations/groupBy.d.ts +15 -0
  18. package/build/operations/groupByDate.d.ts +11 -0
  19. package/build/operations/histogram.d.ts +13 -0
  20. package/build/operations/index.d.ts +6 -0
  21. package/build/operations/scatterPlot.d.ts +14 -0
  22. package/build/sources/h3-tileset-source.d.ts +2 -1
  23. package/build/sources/index.d.ts +1 -1
  24. package/build/sources/quadbin-tileset-source.d.ts +2 -1
  25. package/build/sources/vector-tileset-source.d.ts +2 -1
  26. package/build/types-internal.d.ts +4 -0
  27. package/build/types.d.ts +61 -1
  28. package/build/utils/dateUtils.d.ts +10 -0
  29. package/build/utils/getTileFormat.d.ts +3 -0
  30. package/build/utils/makeIntervalComplete.d.ts +2 -0
  31. package/build/utils/transformTileCoordsToWGS84.d.ts +8 -0
  32. package/build/utils/transformToTileCoords.d.ts +9 -0
  33. package/build/widget-sources/index.d.ts +3 -1
  34. package/build/widget-sources/types.d.ts +31 -22
  35. package/build/widget-sources/widget-query-source.d.ts +2 -2
  36. package/build/widget-sources/widget-remote-source.d.ts +18 -0
  37. package/build/widget-sources/{widget-base-source.d.ts → widget-source.d.ts} +13 -38
  38. package/build/widget-sources/widget-table-source.d.ts +2 -2
  39. package/build/widget-sources/widget-tileset-source.d.ts +76 -0
  40. package/package.json +10 -3
  41. package/src/constants.ts +25 -0
  42. package/src/filters/Filter.ts +169 -0
  43. package/src/filters/FilterTypes.ts +109 -0
  44. package/src/filters/geosjonFeatures.ts +32 -0
  45. package/src/filters/index.ts +6 -0
  46. package/src/filters/tileFeatures.ts +56 -0
  47. package/src/filters/tileFeaturesGeometries.ts +444 -0
  48. package/src/filters/tileFeaturesSpatialIndex.ts +119 -0
  49. package/src/index.ts +6 -0
  50. package/src/models/index.ts +1 -1
  51. package/src/operations/aggregation.ts +154 -0
  52. package/src/operations/applySorting.ts +109 -0
  53. package/src/operations/groupBy.ts +59 -0
  54. package/src/operations/groupByDate.ts +98 -0
  55. package/src/operations/histogram.ts +66 -0
  56. package/src/operations/index.ts +6 -0
  57. package/src/operations/scatterPlot.ts +50 -0
  58. package/src/sources/h3-tileset-source.ts +18 -6
  59. package/src/sources/index.ts +1 -1
  60. package/src/sources/quadbin-tileset-source.ts +18 -6
  61. package/src/sources/raster-source.ts +1 -0
  62. package/src/sources/vector-query-source.ts +5 -2
  63. package/src/sources/vector-table-source.ts +5 -2
  64. package/src/sources/vector-tileset-source.ts +19 -6
  65. package/src/types-internal.ts +6 -0
  66. package/src/types.ts +60 -2
  67. package/src/utils/dateUtils.ts +28 -0
  68. package/src/utils/getTileFormat.ts +9 -0
  69. package/src/utils/makeIntervalComplete.ts +17 -0
  70. package/src/utils/transformTileCoordsToWGS84.ts +77 -0
  71. package/src/utils/transformToTileCoords.ts +85 -0
  72. package/src/widget-sources/index.ts +3 -1
  73. package/src/widget-sources/types.ts +32 -22
  74. package/src/widget-sources/widget-query-source.ts +6 -3
  75. package/src/widget-sources/{widget-base-source.ts → widget-remote-source.ts} +12 -147
  76. package/src/widget-sources/widget-source.ts +160 -0
  77. package/src/widget-sources/widget-table-source.ts +6 -3
  78. package/src/widget-sources/widget-tileset-source.ts +407 -0
@@ -3,6 +3,10 @@ import bboxPolygon from '@turf/bbox-polygon';
3
3
  import union from '@turf/union';
4
4
  import { getType } from '@turf/invariant';
5
5
  import { featureCollection, feature, polygon, multiPolygon } from '@turf/helpers';
6
+ import intersects from '@turf/boolean-intersects';
7
+ import booleanWithin from '@turf/boolean-within';
8
+ import intersect from '@turf/intersect';
9
+ import { getResolution as getResolution$2, polygonToCells } from 'h3-js';
6
10
 
7
11
  /**
8
12
  * @internal
@@ -61,6 +65,31 @@ var ApiVersion;
61
65
  })(ApiVersion || (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
+ var TileFormat;
70
+ (function (TileFormat) {
71
+ TileFormat["MVT"] = "mvt";
72
+ TileFormat["JSON"] = "json";
73
+ TileFormat["GEOJSON"] = "geojson";
74
+ TileFormat["BINARY"] = "binary";
75
+ })(TileFormat || (TileFormat = {}));
76
+ /** @internalRemarks Source: @carto/react-core */
77
+ var SpatialIndex;
78
+ (function (SpatialIndex) {
79
+ SpatialIndex["H3"] = "h3";
80
+ SpatialIndex["S2"] = "s2";
81
+ SpatialIndex["QUADBIN"] = "quadbin";
82
+ })(SpatialIndex || (SpatialIndex = {}));
83
+ /** @internalRemarks Source: @carto/react-core */
84
+ var Provider;
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
+ })(Provider || (Provider = {}));
64
93
 
65
94
  const FILTER_TYPES = new Set(Object.values(FilterType));
66
95
  const isFilterType = type => FILTER_TYPES.has(type);
@@ -103,7 +132,7 @@ function normalizeObjectKeys(el) {
103
132
  }, {});
104
133
  }
105
134
  /** @internalRemarks Source: @carto/react-core */
106
- function assert(condition, message) {
135
+ function assert$1(condition, message) {
107
136
  if (!condition) {
108
137
  throw new Error(message);
109
138
  }
@@ -606,7 +635,7 @@ function excludeURLParameters(baseUrlString, parameters) {
606
635
  return baseUrl.toString();
607
636
  }
608
637
 
609
- const _excluded$1 = ["accessToken", "connectionName", "cache"];
638
+ const _excluded$2 = ["accessToken", "connectionName", "cache"];
610
639
  const SOURCE_DEFAULTS = {
611
640
  apiBaseUrl: DEFAULT_API_BASE_URL,
612
641
  clientId: getClient(),
@@ -620,7 +649,7 @@ async function baseSource(endpoint, options, urlParameters) {
620
649
  connectionName,
621
650
  cache
622
651
  } = options,
623
- optionalOptions = _objectWithoutPropertiesLoose(options, _excluded$1);
652
+ optionalOptions = _objectWithoutPropertiesLoose(options, _excluded$2);
624
653
  const mergedOptions = _extends({}, SOURCE_DEFAULTS, {
625
654
  accessToken,
626
655
  connectionName,
@@ -735,6 +764,91 @@ const boundaryTableSource = async function boundaryTableSource(options) {
735
764
  return baseSource('boundary', options, urlParameters);
736
765
  };
737
766
 
767
+ const DEFAULT_TILE_SIZE = 512;
768
+ const QUADBIN_ZOOM_MAX_OFFSET = 4;
769
+ function getSpatialFiltersResolution(source, viewState) {
770
+ var _source$dataResolutio, _source$aggregationRe;
771
+ const dataResolution = (_source$dataResolutio = source.dataResolution) != null ? _source$dataResolutio : Number.MAX_VALUE;
772
+ const aggregationResLevel = (_source$aggregationRe = source.aggregationResLevel) != null ? _source$aggregationRe : source.spatialDataType === 'h3' ? DEFAULT_AGGREGATION_RES_LEVEL_H3 : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN;
773
+ const aggregationResLevelOffset = Math.max(0, Math.floor(aggregationResLevel));
774
+ const currentZoomInt = Math.ceil(viewState.zoom);
775
+ if (source.spatialDataType === 'h3') {
776
+ var _maxH3SpatialFiltersR, _maxH3SpatialFiltersR2;
777
+ const tileSize = DEFAULT_TILE_SIZE;
778
+ const maxResolutionForZoom = (_maxH3SpatialFiltersR = (_maxH3SpatialFiltersR2 = maxH3SpatialFiltersResolutions.find(([zoom]) => zoom === currentZoomInt)) == null ? void 0 : _maxH3SpatialFiltersR2[1]) != null ? _maxH3SpatialFiltersR : Math.max(0, currentZoomInt - 3);
779
+ const maxSpatialFiltersResolution = maxResolutionForZoom ? Math.min(dataResolution, maxResolutionForZoom) : dataResolution;
780
+ const hexagonResolution = getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
781
+ return Math.min(hexagonResolution, maxSpatialFiltersResolution);
782
+ }
783
+ if (source.spatialDataType === 'quadbin') {
784
+ const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
785
+ const maxSpatialFiltersResolution = Math.min(dataResolution, maxResolutionForZoom);
786
+ const quadsResolution = Math.floor(viewState.zoom) + aggregationResLevelOffset;
787
+ return Math.min(quadsResolution, maxSpatialFiltersResolution);
788
+ }
789
+ return undefined;
790
+ }
791
+ 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]];
792
+ // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
793
+ // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
794
+ const BIAS = 2;
795
+ // Resolution conversion function. Takes a WebMercatorViewport and returns
796
+ // a H3 resolution such that the screen space size of the hexagons is
797
+ // similar
798
+ function getHexagonResolution(viewport, tileSize) {
799
+ // Difference in given tile size compared to deck's internal 512px tile size,
800
+ // expressed as an offset to the viewport zoom.
801
+ const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
802
+ const hexagonScaleFactor = 2 / 3 * (viewport.zoom - zoomOffset);
803
+ const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
804
+ // Clip and bias
805
+ return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
806
+ }
807
+
808
+ /**
809
+ * Source for Widget API requests on a data source defined by a SQL query.
810
+ *
811
+ * Abstract class. Use {@link WidgetQuerySource} or {@link WidgetTableSource}.
812
+ */
813
+ class WidgetSource {
814
+ constructor(props) {
815
+ this.props = void 0;
816
+ this.props = _extends({}, WidgetSource.defaultProps, props);
817
+ }
818
+ _getModelSource(owner) {
819
+ const props = this.props;
820
+ return {
821
+ apiVersion: props.apiVersion,
822
+ apiBaseUrl: props.apiBaseUrl,
823
+ clientId: props.clientId,
824
+ accessToken: props.accessToken,
825
+ connectionName: props.connectionName,
826
+ filters: getApplicableFilters(owner, props.filters),
827
+ filtersLogicalOperator: props.filtersLogicalOperator,
828
+ spatialDataType: props.spatialDataType,
829
+ spatialDataColumn: props.spatialDataColumn,
830
+ dataResolution: props.dataResolution
831
+ };
832
+ }
833
+ _getSpatialFiltersResolution(source, spatialFilter, referenceViewState) {
834
+ // spatialFiltersResolution applies only to spatial index sources.
835
+ if (!spatialFilter || source.spatialDataType === 'geo') {
836
+ return;
837
+ }
838
+ if (!referenceViewState) {
839
+ throw new Error('Missing required option, "spatialIndexReferenceViewState".');
840
+ }
841
+ return getSpatialFiltersResolution(source, referenceViewState);
842
+ }
843
+ }
844
+ WidgetSource.defaultProps = {
845
+ apiVersion: ApiVersion.V3,
846
+ apiBaseUrl: DEFAULT_API_BASE_URL,
847
+ clientId: getClient(),
848
+ filters: {},
849
+ filtersLogicalOperator: 'and'
850
+ };
851
+
738
852
  /**
739
853
  * Return more descriptive error from API
740
854
  * @internalRemarks Source: @carto/react-api
@@ -808,10 +922,10 @@ const REQUEST_GET_MAX_URL_LENGTH = 2048;
808
922
  * @internalRemarks Source: @carto/react-api
809
923
  */
810
924
  function executeModel(props) {
811
- assert(props.source, 'executeModel: missing source');
812
- assert(props.model, 'executeModel: missing model');
813
- assert(props.params, 'executeModel: missing params');
814
- assert(AVAILABLE_MODELS.includes(props.model), `executeModel: model provided isn't valid. Available models: ${AVAILABLE_MODELS.join(', ')}`);
925
+ assert$1(props.source, 'executeModel: missing source');
926
+ assert$1(props.model, 'executeModel: missing model');
927
+ assert$1(props.params, 'executeModel: missing params');
928
+ assert$1(AVAILABLE_MODELS.includes(props.model), `executeModel: model provided isn't valid. Available models: ${AVAILABLE_MODELS.join(', ')}`);
815
929
  const {
816
930
  model,
817
931
  source,
@@ -826,10 +940,10 @@ function executeModel(props) {
826
940
  connectionName,
827
941
  clientId
828
942
  } = source;
829
- assert(apiBaseUrl, 'executeModel: missing apiBaseUrl');
830
- assert(accessToken, 'executeModel: missing accessToken');
831
- assert(apiVersion === V3, 'executeModel: SQL Model API requires CARTO 3+');
832
- assert(type !== 'tileset', 'executeModel: Tilesets not supported');
943
+ assert$1(apiBaseUrl, 'executeModel: missing apiBaseUrl');
944
+ assert$1(accessToken, 'executeModel: missing accessToken');
945
+ assert$1(apiVersion === V3, 'executeModel: SQL Model API requires CARTO 3+');
946
+ assert$1(type !== 'tileset', 'executeModel: Tilesets not supported');
833
947
  let url = `${apiBaseUrl}/v3/sql/${connectionName}/model/${model}`;
834
948
  const {
835
949
  data,
@@ -899,48 +1013,7 @@ function objectToURLSearchParams(object) {
899
1013
  return params;
900
1014
  }
901
1015
 
902
- const DEFAULT_TILE_SIZE = 512;
903
- const QUADBIN_ZOOM_MAX_OFFSET = 4;
904
- function getSpatialFiltersResolution(source, viewState) {
905
- var _source$dataResolutio, _source$aggregationRe;
906
- const dataResolution = (_source$dataResolutio = source.dataResolution) != null ? _source$dataResolutio : Number.MAX_VALUE;
907
- const aggregationResLevel = (_source$aggregationRe = source.aggregationResLevel) != null ? _source$aggregationRe : source.spatialDataType === 'h3' ? DEFAULT_AGGREGATION_RES_LEVEL_H3 : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN;
908
- const aggregationResLevelOffset = Math.max(0, Math.floor(aggregationResLevel));
909
- const currentZoomInt = Math.ceil(viewState.zoom);
910
- if (source.spatialDataType === 'h3') {
911
- var _maxH3SpatialFiltersR, _maxH3SpatialFiltersR2;
912
- const tileSize = DEFAULT_TILE_SIZE;
913
- const maxResolutionForZoom = (_maxH3SpatialFiltersR = (_maxH3SpatialFiltersR2 = maxH3SpatialFiltersResolutions.find(([zoom]) => zoom === currentZoomInt)) == null ? void 0 : _maxH3SpatialFiltersR2[1]) != null ? _maxH3SpatialFiltersR : Math.max(0, currentZoomInt - 3);
914
- const maxSpatialFiltersResolution = maxResolutionForZoom ? Math.min(dataResolution, maxResolutionForZoom) : dataResolution;
915
- const hexagonResolution = getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
916
- return Math.min(hexagonResolution, maxSpatialFiltersResolution);
917
- }
918
- if (source.spatialDataType === 'quadbin') {
919
- const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
920
- const maxSpatialFiltersResolution = Math.min(dataResolution, maxResolutionForZoom);
921
- const quadsResolution = Math.floor(viewState.zoom) + aggregationResLevelOffset;
922
- return Math.min(quadsResolution, maxSpatialFiltersResolution);
923
- }
924
- return undefined;
925
- }
926
- const maxH3SpatialFiltersResolutions = [[20, 14], [19, 13], [18, 12], [17, 11], [16, 10], [15, 9], [14, 8], [13, 7], [12, 7], [11, 7], [10, 6], [9, 6], [8, 5], [7, 4], [6, 4], [5, 3], [4, 2], [3, 1], [2, 1], [1, 0]];
927
- // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
928
- // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
929
- const BIAS = 2;
930
- // Resolution conversion function. Takes a WebMercatorViewport and returns
931
- // a H3 resolution such that the screen space size of the hexagons is
932
- // similar
933
- function getHexagonResolution(viewport, tileSize) {
934
- // Difference in given tile size compared to deck's internal 512px tile size,
935
- // expressed as an offset to the viewport zoom.
936
- const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
937
- const hexagonScaleFactor = 2 / 3 * (viewport.zoom - zoomOffset);
938
- const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
939
- // Clip and bias
940
- return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
941
- }
942
-
943
- const _excluded = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
1016
+ const _excluded$1 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
944
1017
  _excluded2 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
945
1018
  _excluded3 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController", "operationExp"],
946
1019
  _excluded4 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
@@ -949,47 +1022,11 @@ const _excluded = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatia
949
1022
  _excluded7 = ["filterOwner", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState", "abortController"],
950
1023
  _excluded8 = ["filterOwner", "abortController", "spatialFilter", "spatialFiltersMode", "spatialIndexReferenceViewState"];
951
1024
  /**
952
- * Source for Widget API requests on a data source defined by a SQL query.
1025
+ * Source for Widget API requests.
953
1026
  *
954
1027
  * Abstract class. Use {@link WidgetQuerySource} or {@link WidgetTableSource}.
955
1028
  */
956
- class WidgetBaseSource {
957
- constructor(props) {
958
- this.props = void 0;
959
- this.props = _extends({}, WidgetBaseSource.defaultProps, props);
960
- }
961
- _getModelSource(owner) {
962
- const props = this.props;
963
- return {
964
- apiVersion: props.apiVersion,
965
- apiBaseUrl: props.apiBaseUrl,
966
- clientId: props.clientId,
967
- accessToken: props.accessToken,
968
- connectionName: props.connectionName,
969
- filters: getApplicableFilters(owner, props.filters),
970
- filtersLogicalOperator: props.filtersLogicalOperator,
971
- spatialDataType: props.spatialDataType,
972
- spatialDataColumn: props.spatialDataColumn,
973
- dataResolution: props.dataResolution
974
- };
975
- }
976
- _getSpatialFiltersResolution(source, spatialFilter, referenceViewState) {
977
- // spatialFiltersResolution applies only to spatial index sources.
978
- if (!spatialFilter || source.spatialDataType === 'geo') {
979
- return;
980
- }
981
- if (!referenceViewState) {
982
- throw new Error('Missing required option, "spatialIndexReferenceViewState".');
983
- }
984
- return getSpatialFiltersResolution(source, referenceViewState);
985
- }
986
- /****************************************************************************
987
- * CATEGORIES
988
- */
989
- /**
990
- * Returns a list of labeled datapoints for categorical data. Suitable for
991
- * charts including grouped bar charts, pie charts, and tree charts.
992
- */
1029
+ class WidgetRemoteSource extends WidgetSource {
993
1030
  async getCategories(options) {
994
1031
  const {
995
1032
  filterOwner,
@@ -998,7 +1035,7 @@ class WidgetBaseSource {
998
1035
  spatialIndexReferenceViewState,
999
1036
  abortController
1000
1037
  } = options,
1001
- params = _objectWithoutPropertiesLoose(options, _excluded);
1038
+ params = _objectWithoutPropertiesLoose(options, _excluded$1);
1002
1039
  const {
1003
1040
  column,
1004
1041
  operation,
@@ -1023,17 +1060,6 @@ class WidgetBaseSource {
1023
1060
  }
1024
1061
  }).then(res => normalizeObjectKeys(res.rows));
1025
1062
  }
1026
- /****************************************************************************
1027
- * FEATURES
1028
- */
1029
- /**
1030
- * Given a list of feature IDs (as found in `_carto_feature_id`) returns all
1031
- * matching features. In datasets containing features with duplicate geometries,
1032
- * feature IDs may be duplicated (IDs are a hash of geometry) and so more
1033
- * results may be returned than IDs in the request.
1034
- * @internal
1035
- * @experimental
1036
- */
1037
1063
  async getFeatures(options) {
1038
1064
  const {
1039
1065
  filterOwner,
@@ -1078,13 +1104,6 @@ class WidgetBaseSource {
1078
1104
  rows
1079
1105
  }));
1080
1106
  }
1081
- /****************************************************************************
1082
- * FORMULA
1083
- */
1084
- /**
1085
- * Returns a scalar numerical statistic over all matching data. Suitable
1086
- * for 'headline' or 'scorecard' figures such as counts and sums.
1087
- */
1088
1107
  async getFormula(options) {
1089
1108
  const {
1090
1109
  filterOwner,
@@ -1110,7 +1129,7 @@ class WidgetBaseSource {
1110
1129
  }),
1111
1130
  params: {
1112
1131
  column: column != null ? column : '*',
1113
- operation,
1132
+ operation: operation != null ? operation : 'count',
1114
1133
  operationExp
1115
1134
  },
1116
1135
  opts: {
@@ -1118,13 +1137,6 @@ class WidgetBaseSource {
1118
1137
  }
1119
1138
  }).then(res => normalizeObjectKeys(res.rows[0]));
1120
1139
  }
1121
- /****************************************************************************
1122
- * HISTOGRAM
1123
- */
1124
- /**
1125
- * Returns a list of labeled datapoints for 'bins' of data defined as ticks
1126
- * over a numerical range. Suitable for histogram charts.
1127
- */
1128
1140
  async getHistogram(options) {
1129
1141
  const {
1130
1142
  filterOwner,
@@ -1169,14 +1181,6 @@ class WidgetBaseSource {
1169
1181
  }
1170
1182
  return [];
1171
1183
  }
1172
- /****************************************************************************
1173
- * RANGE
1174
- */
1175
- /**
1176
- * Returns a range (min and max) for a numerical column of matching rows.
1177
- * Suitable for displaying certain 'headline' or 'scorecard' statistics,
1178
- * or rendering a range slider UI for filtering.
1179
- */
1180
1184
  async getRange(options) {
1181
1185
  const {
1182
1186
  filterOwner,
@@ -1206,13 +1210,6 @@ class WidgetBaseSource {
1206
1210
  }
1207
1211
  }).then(res => normalizeObjectKeys(res.rows[0]));
1208
1212
  }
1209
- /****************************************************************************
1210
- * SCATTER
1211
- */
1212
- /**
1213
- * Returns a list of bivariate datapoints defined as numerical 'x' and 'y'
1214
- * values. Suitable for rendering scatter plots.
1215
- */
1216
1213
  async getScatter(options) {
1217
1214
  const {
1218
1215
  filterOwner,
@@ -1254,13 +1251,6 @@ class WidgetBaseSource {
1254
1251
  y
1255
1252
  }) => [x, y]));
1256
1253
  }
1257
- /****************************************************************************
1258
- * TABLE
1259
- */
1260
- /**
1261
- * Returns a list of arbitrary data rows, with support for pagination and
1262
- * sorting. Suitable for displaying tables and lists.
1263
- */
1264
1254
  async getTable(options) {
1265
1255
  const {
1266
1256
  filterOwner,
@@ -1305,13 +1295,6 @@ class WidgetBaseSource {
1305
1295
  };
1306
1296
  });
1307
1297
  }
1308
- /****************************************************************************
1309
- * TIME SERIES
1310
- */
1311
- /**
1312
- * Returns a series of labeled numerical values, grouped into equally-sized
1313
- * time intervals. Suitable for rendering time series charts.
1314
- */
1315
1298
  async getTimeSeries(options) {
1316
1299
  const {
1317
1300
  filterOwner,
@@ -1364,13 +1347,6 @@ class WidgetBaseSource {
1364
1347
  });
1365
1348
  }
1366
1349
  }
1367
- WidgetBaseSource.defaultProps = {
1368
- apiVersion: ApiVersion.V3,
1369
- apiBaseUrl: DEFAULT_API_BASE_URL,
1370
- clientId: getClient(),
1371
- filters: {},
1372
- filtersLogicalOperator: 'and'
1373
- };
1374
1350
 
1375
1351
  /**
1376
1352
  * Source for Widget API requests on a data source defined by a SQL query.
@@ -1394,7 +1370,7 @@ WidgetBaseSource.defaultProps = {
1394
1370
  * const { widgetSource } = await data;
1395
1371
  * ```
1396
1372
  */
1397
- class WidgetQuerySource extends WidgetBaseSource {
1373
+ class WidgetQuerySource extends WidgetRemoteSource {
1398
1374
  getModelSource(owner) {
1399
1375
  return _extends({}, super._getModelSource(owner), {
1400
1376
  type: 'query',
@@ -1426,7 +1402,7 @@ class WidgetQuerySource extends WidgetBaseSource {
1426
1402
  * const { widgetSource } = await data;
1427
1403
  * ```
1428
1404
  */
1429
- class WidgetTableSource extends WidgetBaseSource {
1405
+ class WidgetTableSource extends WidgetRemoteSource {
1430
1406
  getModelSource(owner) {
1431
1407
  return _extends({}, super._getModelSource(owner), {
1432
1408
  type: 'table',
@@ -1435,60 +1411,1902 @@ class WidgetTableSource extends WidgetBaseSource {
1435
1411
  }
1436
1412
  }
1437
1413
 
1438
- const h3QuerySource = async function h3QuerySource(options) {
1439
- const {
1440
- aggregationExp,
1441
- aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
1442
- sqlQuery,
1443
- spatialDataColumn = 'h3',
1444
- queryParameters,
1445
- filters
1446
- } = options;
1447
- const spatialDataType = 'h3';
1448
- const urlParameters = {
1449
- aggregationExp,
1450
- spatialDataColumn,
1451
- spatialDataType,
1452
- q: sqlQuery
1453
- };
1454
- if (aggregationResLevel) {
1455
- urlParameters.aggregationResLevel = String(aggregationResLevel);
1456
- }
1457
- if (queryParameters) {
1458
- urlParameters.queryParameters = queryParameters;
1459
- }
1460
- if (filters) {
1461
- urlParameters.filters = filters;
1462
- }
1463
- return baseSource('query', options, urlParameters).then(result => _extends({}, result, {
1464
- widgetSource: new WidgetQuerySource(_extends({}, options, {
1465
- // NOTE: Parameters with default values above must be explicitly passed here.
1466
- spatialDataColumn,
1467
- spatialDataType
1468
- }))
1469
- }));
1470
- };
1414
+ function makeIntervalComplete(intervals) {
1415
+ return intervals.map(val => {
1416
+ if (val[0] === undefined || val[0] === null) {
1417
+ return [Number.MIN_SAFE_INTEGER, val[1]];
1418
+ }
1419
+ if (val[1] === undefined || val[1] === null) {
1420
+ return [val[0], Number.MAX_SAFE_INTEGER];
1421
+ }
1422
+ return val;
1423
+ });
1424
+ }
1471
1425
 
1472
- const h3TableSource = async function h3TableSource(options) {
1473
- const {
1474
- aggregationExp,
1475
- aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
1476
- spatialDataColumn = 'h3',
1477
- tableName,
1478
- filters
1479
- } = options;
1480
- const spatialDataType = 'h3';
1481
- const urlParameters = {
1482
- aggregationExp,
1483
- name: tableName,
1484
- spatialDataColumn,
1485
- spatialDataType
1426
+ const filterFunctions = {
1427
+ [FilterType.IN]: filterIn,
1428
+ [FilterType.BETWEEN]: filterBetween,
1429
+ [FilterType.TIME]: filterTime,
1430
+ [FilterType.CLOSED_OPEN]: filterClosedOpen,
1431
+ [FilterType.STRING_SEARCH]: filterStringSearch
1432
+ };
1433
+ function filterIn(filterValues, featureValue) {
1434
+ return filterValues.includes(featureValue);
1435
+ }
1436
+ // FilterTypes.BETWEEN
1437
+ function filterBetween(filterValues, featureValue) {
1438
+ const checkRange = range => {
1439
+ const [lowerBound, upperBound] = range;
1440
+ return featureValue >= lowerBound && featureValue <= upperBound;
1486
1441
  };
1487
- if (aggregationResLevel) {
1488
- urlParameters.aggregationResLevel = String(aggregationResLevel);
1489
- }
1490
- if (filters) {
1491
- urlParameters.filters = filters;
1442
+ return makeIntervalComplete(filterValues).some(checkRange);
1443
+ }
1444
+ function filterTime(filterValues, featureValue) {
1445
+ const featureValueAsTimestamp = new Date(featureValue).getTime();
1446
+ if (isFinite(featureValueAsTimestamp)) {
1447
+ return filterBetween(filterValues, featureValueAsTimestamp);
1448
+ } else {
1449
+ throw new Error(`Column used to filter by time isn't well formatted.`);
1450
+ }
1451
+ }
1452
+ // FilterTypes.CLOSED_OPEN
1453
+ function filterClosedOpen(filterValues, featureValue) {
1454
+ const checkRange = range => {
1455
+ const [lowerBound, upperBound] = range;
1456
+ return featureValue >= lowerBound && featureValue < upperBound;
1457
+ };
1458
+ return makeIntervalComplete(filterValues).some(checkRange);
1459
+ }
1460
+ // FilterTypes.STRING_SEARCH
1461
+ function filterStringSearch(filterValues, featureValue, params = {}) {
1462
+ const normalizedFeatureValue = normalize(featureValue, params);
1463
+ const stringRegExp = params.useRegExp ? filterValues : filterValues.map(filterValue => {
1464
+ let stringRegExp = escapeRegExp(normalize(filterValue, params));
1465
+ if (params.mustStart) stringRegExp = `^${stringRegExp}`;
1466
+ if (params.mustEnd) stringRegExp = `${stringRegExp}$`;
1467
+ return stringRegExp;
1468
+ });
1469
+ const regex = new RegExp(stringRegExp.join('|'), params.caseSensitive ? 'g' : 'gi');
1470
+ return !!normalizedFeatureValue.match(regex);
1471
+ }
1472
+ // Aux
1473
+ const specialCharRegExp = /[.*+?^${}()|[\]\\]/g;
1474
+ const normalizeRegExp = /(?:[\^`\xA8\xAF\xB4\xB7\xB8\u02B0-\u034E\u0350-\u0357\u035D-\u0362\u0374\u0375\u037A\u0384\u0385\u0483-\u0487\u0559\u0591-\u05A1\u05A3-\u05BD\u05BF\u05C1\u05C2\u05C4\u064B-\u0652\u0657\u0658\u06DF\u06E0\u06E5\u06E6\u06EA-\u06EC\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F5\u0818\u0819\u0898-\u089F\u08C9-\u08D2\u08E3-\u08FE\u093C\u094D\u0951-\u0954\u0971\u09BC\u09CD\u0A3C\u0A4D\u0ABC\u0ACD\u0AFD-\u0AFF\u0B3C\u0B4D\u0B55\u0BCD\u0C3C\u0C4D\u0CBC\u0CCD\u0D3B\u0D3C\u0D4D\u0DCA\u0E3A\u0E47-\u0E4C\u0E4E\u0EBA\u0EC8-\u0ECC\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F82-\u0F84\u0F86\u0F87\u0FC6\u1037\u1039\u103A\u1063\u1064\u1069-\u106D\u1087-\u108D\u108F\u109A\u109B\u135D-\u135F\u1714\u1715\u1734\u17C9-\u17D3\u17DD\u1939-\u193B\u1A60\u1A75-\u1A7C\u1A7F\u1AB0-\u1ABE\u1AC1-\u1ACB\u1B34\u1B44\u1B6B-\u1B73\u1BAA\u1BAB\u1BE6\u1BF2\u1BF3\u1C36\u1C37\u1C78-\u1C7D\u1CD0-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1D2C-\u1D6A\u1DC4-\u1DCF\u1DF5-\u1DFF\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2CEF-\u2CF1\u2E2F\u302A-\u302F\u3099-\u309C\u30FC\uA66F\uA67C\uA67D\uA67F\uA69C\uA69D\uA6F0\uA6F1\uA700-\uA721\uA788-\uA78A\uA7F8\uA7F9\uA806\uA82C\uA8C4\uA8E0-\uA8F1\uA92B-\uA92E\uA953\uA9B3\uA9C0\uA9E5\uAA7B-\uAA7D\uAABF-\uAAC2\uAAF6\uAB5B-\uAB5F\uAB69-\uAB6B\uABEC\uABED\uFB1E\uFE20-\uFE2F\uFF3E\uFF40\uFF70\uFF9E\uFF9F\uFFE3]|\uD800\uDEE0|\uD801[\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD803[\uDD22-\uDD27\uDD4E\uDD69-\uDD6D\uDEFD-\uDEFF\uDF46-\uDF50\uDF82-\uDF85]|\uD804[\uDC46\uDC70\uDCB9\uDCBA\uDD33\uDD34\uDD73\uDDC0\uDDCA-\uDDCC\uDE35\uDE36\uDEE9\uDEEA\uDF3B\uDF3C\uDF4D\uDF66-\uDF6C\uDF70-\uDF74\uDFCE-\uDFD0\uDFD2\uDFD3\uDFE1\uDFE2]|\uD805[\uDC42\uDC46\uDCC2\uDCC3\uDDBF\uDDC0\uDE3F\uDEB6\uDEB7\uDF2B]|\uD806[\uDC39\uDC3A\uDD3D\uDD3E\uDD43\uDDE0\uDE34\uDE47\uDE99]|\uD807[\uDC3F\uDD42\uDD44\uDD45\uDD97\uDF41\uDF42\uDF5A]|\uD80D[\uDC47-\uDC55]|\uD818\uDD2F|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDD6B\uDD6C\uDF8F-\uDF9F\uDFF0\uDFF1]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD833[\uDF00-\uDF2D\uDF30-\uDF46]|\uD834[\uDD67-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD]|\uD838[\uDC30-\uDC6D\uDD30-\uDD36\uDEAE\uDEEC-\uDEEF]|\uD839[\uDDEE\uDDEF]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD46\uDD48-\uDD4A])/g;
1475
+ function escapeRegExp(value) {
1476
+ return value.replace(specialCharRegExp, '\\$&');
1477
+ }
1478
+ function normalize(data, params) {
1479
+ let normalizedData = String(data);
1480
+ if (!params.keepSpecialCharacters) normalizedData = normalizedData.normalize('NFD').replace(normalizeRegExp, '');
1481
+ return normalizedData;
1482
+ }
1483
+
1484
+ const LOGICAL_OPERATOR_METHODS = {
1485
+ and: 'every',
1486
+ or: 'some'
1487
+ };
1488
+ function passesFilter(columns, filters, feature, filtersLogicalOperator) {
1489
+ const method = LOGICAL_OPERATOR_METHODS[filtersLogicalOperator];
1490
+ return columns[method](column => {
1491
+ const columnFilters = filters[column];
1492
+ const columnFilterTypes = Object.keys(columnFilters);
1493
+ if (!feature || feature[column] === null || feature[column] === undefined) {
1494
+ return false;
1495
+ }
1496
+ return columnFilterTypes.every(filter => {
1497
+ const filterFunction = filterFunctions[filter];
1498
+ if (!filterFunction) {
1499
+ throw new Error(`"${filter}" filter is not implemented.`);
1500
+ }
1501
+ return filterFunction(columnFilters[filter].values, feature[column], columnFilters[filter].params);
1502
+ });
1503
+ });
1504
+ }
1505
+ function buildFeatureFilter({
1506
+ filters = {},
1507
+ type = 'boolean',
1508
+ filtersLogicalOperator = 'and'
1509
+ }) {
1510
+ const columns = Object.keys(filters);
1511
+ if (!columns.length) {
1512
+ return () => type === 'number' ? 1 : true;
1513
+ }
1514
+ return feature => {
1515
+ const f = feature.properties || feature;
1516
+ const featurePassesFilter = passesFilter(columns, filters, f, filtersLogicalOperator);
1517
+ return type === 'number' ? Number(featurePassesFilter) : featurePassesFilter;
1518
+ };
1519
+ }
1520
+ // Apply certain filters to a collection of features
1521
+ function applyFilters(features, filters, filtersLogicalOperator) {
1522
+ return Object.keys(filters).length ? features.filter(buildFeatureFilter({
1523
+ filters,
1524
+ filtersLogicalOperator
1525
+ })) : features;
1526
+ }
1527
+ // Binary
1528
+ function buildBinaryFeatureFilter({
1529
+ filters = {}
1530
+ }) {
1531
+ const columns = Object.keys(filters);
1532
+ if (!columns.length) {
1533
+ return () => 1;
1534
+ }
1535
+ return (featureIdIdx, binaryData) => passesFilterUsingBinary(columns, filters, featureIdIdx, binaryData);
1536
+ }
1537
+ function getValueFromNumericProps(featureIdIdx, binaryData, {
1538
+ column
1539
+ }) {
1540
+ var _binaryData$numericPr;
1541
+ return (_binaryData$numericPr = binaryData.numericProps) == null || (_binaryData$numericPr = _binaryData$numericPr[column]) == null ? void 0 : _binaryData$numericPr.value[featureIdIdx];
1542
+ }
1543
+ function getValueFromProperties(featureIdIdx, binaryData, {
1544
+ column
1545
+ }) {
1546
+ var _binaryData$propertie;
1547
+ const propertyIdx = binaryData.featureIds.value[featureIdIdx];
1548
+ return (_binaryData$propertie = binaryData.properties[propertyIdx]) == null ? void 0 : _binaryData$propertie[column];
1549
+ }
1550
+ const GET_VALUE_BY_BINARY_PROP = {
1551
+ properties: getValueFromProperties,
1552
+ numericProps: getValueFromNumericProps
1553
+ };
1554
+ function getBinaryPropertyByFilterValues(filterValues) {
1555
+ return typeof filterValues.flat()[0] === 'string' ? 'properties' : 'numericProps';
1556
+ }
1557
+ function getFeatureValue(featureIdIdx, binaryData, filter) {
1558
+ const {
1559
+ column,
1560
+ values
1561
+ } = filter;
1562
+ const binaryProp = getBinaryPropertyByFilterValues(values);
1563
+ const getFeatureValueFn = GET_VALUE_BY_BINARY_PROP[binaryProp];
1564
+ return getFeatureValueFn(featureIdIdx, binaryData, {
1565
+ column
1566
+ });
1567
+ }
1568
+ function passesFilterUsingBinary(columns, filters, featureIdIdx, binaryData) {
1569
+ return columns.every(column => {
1570
+ const columnFilters = filters[column];
1571
+ return Object.entries(columnFilters).every(([type, {
1572
+ values
1573
+ }]) => {
1574
+ const filterFn = filterFunctions[type];
1575
+ if (!filterFn) {
1576
+ throw new Error(`"${type}" filter is not implemented.`);
1577
+ }
1578
+ if (!values) return 0;
1579
+ const featureValue = getFeatureValue(featureIdIdx, binaryData, {
1580
+ type: type,
1581
+ column,
1582
+ values
1583
+ });
1584
+ if (featureValue === undefined || featureValue === null) return 0;
1585
+ return filterFn(values, featureValue);
1586
+ });
1587
+ });
1588
+ }
1589
+
1590
+ function geojsonFeatures({
1591
+ geojson,
1592
+ spatialFilter,
1593
+ uniqueIdProperty
1594
+ }) {
1595
+ let uniqueIdx = 0;
1596
+ const map = new Map();
1597
+ if (!spatialFilter) {
1598
+ return [];
1599
+ }
1600
+ for (const feature of geojson.features) {
1601
+ const uniqueId = uniqueIdProperty ? feature.properties[uniqueIdProperty] : ++uniqueIdx;
1602
+ if (!map.has(uniqueId) && intersects(spatialFilter, feature)) {
1603
+ map.set(uniqueId, feature.properties);
1604
+ }
1605
+ }
1606
+ return Array.from(map.values());
1607
+ }
1608
+
1609
+ // math.gl
1610
+ // SPDX-License-Identifier: MIT
1611
+ // Copyright (c) vis.gl contributors
1612
+ const DEFAULT_CONFIG = {
1613
+ EPSILON: 1e-12,
1614
+ debug: false,
1615
+ precision: 4,
1616
+ printTypes: false,
1617
+ printDegrees: false,
1618
+ printRowMajor: true,
1619
+ _cartographicRadians: false
1620
+ };
1621
+ // Configuration is truly global as of v3.6 to ensure single config even if multiple copies of math.gl
1622
+ // Multiple copies of config can be quite tricky to debug...
1623
+ globalThis.mathgl = globalThis.mathgl || {
1624
+ config: {
1625
+ ...DEFAULT_CONFIG
1626
+ }
1627
+ };
1628
+ /**
1629
+ * Check if value is an "array"
1630
+ * Returns `true` if value is either an array or a typed array
1631
+ * Note: returns `false` for `ArrayBuffer` and `DataView` instances
1632
+ * @note isTypedArray and isNumericArray are often more useful in TypeScript
1633
+ */
1634
+ function isArray(value) {
1635
+ return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
1636
+ }
1637
+ function lerp(a, b, t) {
1638
+ if (isArray(a)) {
1639
+ return a.map((ai, i) => lerp(ai, b[i], t));
1640
+ }
1641
+ return t * b + (1 - t) * a;
1642
+ }
1643
+
1644
+ // Replacement for the external assert method to reduce bundle size
1645
+ // Note: We don't use the second "message" argument in calling code,
1646
+ // so no need to support it here
1647
+ function assert(condition, message) {
1648
+ if (!condition) {
1649
+ throw new Error(message || '@math.gl/web-mercator: assertion failed.');
1650
+ }
1651
+ }
1652
+
1653
+ // TODO - THE UTILITIES IN THIS FILE SHOULD BE IMPORTED FROM WEB-MERCATOR-VIEWPORT MODULE
1654
+ // CONSTANTS
1655
+ const PI = Math.PI;
1656
+ const PI_4 = PI / 4;
1657
+ const DEGREES_TO_RADIANS = PI / 180;
1658
+ const RADIANS_TO_DEGREES = 180 / PI;
1659
+ const TILE_SIZE = 512;
1660
+ /**
1661
+ * Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
1662
+ * Performs the nonlinear part of the web mercator projection.
1663
+ * Remaining projection is done with 4x4 matrices which also handles
1664
+ * perspective.
1665
+ *
1666
+ * @param lngLat - [lng, lat] coordinates
1667
+ * Specifies a point on the sphere to project onto the map.
1668
+ * @return [x,y] coordinates.
1669
+ */
1670
+ function lngLatToWorld(lngLat) {
1671
+ const [lng, lat] = lngLat;
1672
+ assert(Number.isFinite(lng));
1673
+ assert(Number.isFinite(lat) && lat >= -90 && lat <= 90, 'invalid latitude');
1674
+ const lambda2 = lng * DEGREES_TO_RADIANS;
1675
+ const phi2 = lat * DEGREES_TO_RADIANS;
1676
+ const x = TILE_SIZE * (lambda2 + PI) / (2 * PI);
1677
+ const y = TILE_SIZE * (PI + Math.log(Math.tan(PI_4 + phi2 * 0.5))) / (2 * PI);
1678
+ return [x, y];
1679
+ }
1680
+ /**
1681
+ * Unproject world point [x,y] on map onto {lat, lon} on sphere
1682
+ *
1683
+ * @param xy - array with [x,y] members
1684
+ * representing point on projected map plane
1685
+ * @return - array with [x,y] of point on sphere.
1686
+ * Has toArray method if you need a GeoJSON Array.
1687
+ * Per cartographic tradition, lat and lon are specified as degrees.
1688
+ */
1689
+ function worldToLngLat(xy) {
1690
+ const [x, y] = xy;
1691
+ const lambda2 = x / TILE_SIZE * (2 * PI) - PI;
1692
+ const phi2 = 2 * (Math.atan(Math.exp(y / TILE_SIZE * (2 * PI) - PI)) - PI_4);
1693
+ return [lambda2 * RADIANS_TO_DEGREES, phi2 * RADIANS_TO_DEGREES];
1694
+ }
1695
+
1696
+ const TRANSFORM_FN$1 = {
1697
+ Point: transformPoint$1,
1698
+ MultiPoint: transformMultiPoint$1,
1699
+ LineString: transformLineString$1,
1700
+ MultiLineString: transformMultiLineString$1,
1701
+ Polygon: transformPolygon$1,
1702
+ MultiPolygon: transformMultiPolygon$1
1703
+ };
1704
+ /**
1705
+ * Transform WGS84 coordinates to tile coords.
1706
+ * 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)
1707
+ *
1708
+ * @param geometry - any valid geojson geometry
1709
+ * @param bbox - geojson bbox
1710
+ */
1711
+ function transformToTileCoords(geometry, bbox) {
1712
+ const [west, south, east, north] = bbox;
1713
+ const nw = projectFlat([west, north]);
1714
+ const se = projectFlat([east, south]);
1715
+ const projectedBbox = [nw, se];
1716
+ if (geometry.type === 'GeometryCollection') {
1717
+ throw new Error('Unsupported geometry type GeometryCollection');
1718
+ }
1719
+ const transformFn = TRANSFORM_FN$1[geometry.type];
1720
+ const coordinates = transformFn(geometry.coordinates, projectedBbox);
1721
+ return _extends({}, geometry, {
1722
+ coordinates
1723
+ });
1724
+ }
1725
+ function transformPoint$1([pointX, pointY], [nw, se]) {
1726
+ const x = inverseLerp(nw[0], se[0], pointX);
1727
+ const y = inverseLerp(nw[1], se[1], pointY);
1728
+ return [x, y];
1729
+ }
1730
+ function getPoints$1(geometry, bbox) {
1731
+ return geometry.map(g => transformPoint$1(projectFlat(g), bbox));
1732
+ }
1733
+ function transformMultiPoint$1(multiPoint, bbox) {
1734
+ return getPoints$1(multiPoint, bbox);
1735
+ }
1736
+ function transformLineString$1(line, bbox) {
1737
+ return getPoints$1(line, bbox);
1738
+ }
1739
+ function transformMultiLineString$1(multiLineString, bbox) {
1740
+ return multiLineString.map(lineString => transformLineString$1(lineString, bbox));
1741
+ }
1742
+ function transformPolygon$1(polygon, bbox) {
1743
+ return polygon.map(polygonRing => getPoints$1(polygonRing, bbox));
1744
+ }
1745
+ function transformMultiPolygon$1(multiPolygon, bbox) {
1746
+ return multiPolygon.map(polygon => transformPolygon$1(polygon, bbox));
1747
+ }
1748
+ function projectFlat(xyz) {
1749
+ return lngLatToWorld(xyz);
1750
+ }
1751
+ function inverseLerp(a, b, x) {
1752
+ return (x - a) / (b - a);
1753
+ }
1754
+
1755
+ const TRANSFORM_FN = {
1756
+ Point: transformPoint,
1757
+ MultiPoint: transformMultiPoint,
1758
+ LineString: transformLineString,
1759
+ MultiLineString: transformMultiLineString,
1760
+ Polygon: transformPolygon,
1761
+ MultiPolygon: transformMultiPolygon
1762
+ };
1763
+ /**
1764
+ * Transform tile coords to WGS84 coordinates.
1765
+ *
1766
+ * @param geometry - any valid geojson geometry
1767
+ * @param bbox - geojson bbox
1768
+ */
1769
+ function transformTileCoordsToWGS84(geometry, bbox) {
1770
+ const [west, south, east, north] = bbox;
1771
+ const nw = lngLatToWorld([west, north]);
1772
+ const se = lngLatToWorld([east, south]);
1773
+ const projectedBbox = [nw, se];
1774
+ if (geometry.type === 'GeometryCollection') {
1775
+ throw new Error('Unsupported geometry type GeometryCollection');
1776
+ }
1777
+ const transformFn = TRANSFORM_FN[geometry.type];
1778
+ const coordinates = transformFn(geometry.coordinates, projectedBbox);
1779
+ return _extends({}, geometry, {
1780
+ coordinates
1781
+ });
1782
+ }
1783
+ function transformPoint([pointX, pointY], [nw, se]) {
1784
+ const x = lerp(nw[0], se[0], pointX);
1785
+ const y = lerp(nw[1], se[1], pointY);
1786
+ return worldToLngLat([x, y]);
1787
+ }
1788
+ function getPoints(geometry, bbox) {
1789
+ return geometry.map(g => transformPoint(g, bbox));
1790
+ }
1791
+ function transformMultiPoint(multiPoint, bbox) {
1792
+ return getPoints(multiPoint, bbox);
1793
+ }
1794
+ function transformLineString(line, bbox) {
1795
+ return getPoints(line, bbox);
1796
+ }
1797
+ function transformMultiLineString(multiLineString, bbox) {
1798
+ return multiLineString.map(lineString => transformLineString(lineString, bbox));
1799
+ }
1800
+ function transformPolygon(polygon, bbox) {
1801
+ return polygon.map(polygonRing => getPoints(polygonRing, bbox));
1802
+ }
1803
+ function transformMultiPolygon(multiPolygon, bbox) {
1804
+ return multiPolygon.map(polygon => transformPolygon(polygon, bbox));
1805
+ }
1806
+
1807
+ const FEATURE_GEOM_PROPERTY = '__geomValue';
1808
+ function tileFeaturesGeometries({
1809
+ tiles,
1810
+ tileFormat,
1811
+ spatialFilter,
1812
+ uniqueIdProperty,
1813
+ options
1814
+ }) {
1815
+ const map = new Map();
1816
+ for (const tile of tiles) {
1817
+ // Discard if it's not a visible tile (only check false value, not undefined)
1818
+ // or tile has not data
1819
+ if (tile.isVisible === false || !tile.data) {
1820
+ continue;
1821
+ }
1822
+ const bbox = [tile.bbox.west, tile.bbox.south, tile.bbox.east, tile.bbox.north];
1823
+ const bboxToGeom = bboxPolygon(bbox);
1824
+ const tileIsFullyVisible = booleanWithin(bboxToGeom, spatialFilter);
1825
+ // Clip the geometry to intersect with the tile
1826
+ const spatialFilterFeature = {
1827
+ type: 'Feature',
1828
+ geometry: spatialFilter,
1829
+ properties: {}
1830
+ };
1831
+ const clippedGeometryToIntersect = intersect(featureCollection([bboxToGeom, spatialFilterFeature]));
1832
+ if (!clippedGeometryToIntersect) {
1833
+ continue;
1834
+ }
1835
+ // We assume that MVT tileFormat uses local coordinates so we transform the geometry to intersect to tile coordinates [0..1],
1836
+ // while in the case of 'geojson' or binary, the geometries are already in WGS84
1837
+ const transformedGeometryToIntersect = tileFormat === TileFormat.MVT ? transformToTileCoords(clippedGeometryToIntersect.geometry, bbox) : clippedGeometryToIntersect.geometry;
1838
+ createIndicesForPoints(tile.data.points);
1839
+ calculateFeatures({
1840
+ map,
1841
+ tileIsFullyVisible,
1842
+ geometryIntersection: transformedGeometryToIntersect,
1843
+ data: tile.data.points,
1844
+ type: 'Point',
1845
+ bbox,
1846
+ tileFormat,
1847
+ uniqueIdProperty,
1848
+ options
1849
+ });
1850
+ calculateFeatures({
1851
+ map,
1852
+ tileIsFullyVisible,
1853
+ geometryIntersection: transformedGeometryToIntersect,
1854
+ data: tile.data.lines,
1855
+ type: 'LineString',
1856
+ bbox,
1857
+ tileFormat,
1858
+ uniqueIdProperty,
1859
+ options
1860
+ });
1861
+ calculateFeatures({
1862
+ map,
1863
+ tileIsFullyVisible,
1864
+ geometryIntersection: transformedGeometryToIntersect,
1865
+ data: tile.data.polygons,
1866
+ type: 'Polygon',
1867
+ bbox,
1868
+ tileFormat,
1869
+ uniqueIdProperty,
1870
+ options
1871
+ });
1872
+ }
1873
+ return Array.from(map.values());
1874
+ }
1875
+ function processTileFeatureProperties({
1876
+ map,
1877
+ data,
1878
+ startIndex,
1879
+ endIndex,
1880
+ type,
1881
+ bbox,
1882
+ tileFormat,
1883
+ uniqueIdProperty,
1884
+ storeGeometry,
1885
+ geometryIntersection
1886
+ }) {
1887
+ const tileProps = getPropertiesFromTile(data, startIndex);
1888
+ const uniquePropertyValue = getUniquePropertyValue(tileProps, uniqueIdProperty, map);
1889
+ if (!uniquePropertyValue || map.has(uniquePropertyValue)) {
1890
+ return;
1891
+ }
1892
+ let geometry = null;
1893
+ // Only calculate geometry if necessary
1894
+ if (storeGeometry || geometryIntersection) {
1895
+ const {
1896
+ positions
1897
+ } = data;
1898
+ const ringCoordinates = getRingCoordinatesFor(startIndex, endIndex, positions);
1899
+ geometry = getFeatureByType(ringCoordinates, type);
1900
+ }
1901
+ // If intersection is required, check before proceeding
1902
+ if (geometry && geometryIntersection && !intersects(geometry, geometryIntersection)) {
1903
+ return;
1904
+ }
1905
+ const properties = parseProperties(tileProps);
1906
+ // Only save geometry if necessary
1907
+ if (storeGeometry && geometry) {
1908
+ properties[FEATURE_GEOM_PROPERTY] = tileFormat === TileFormat.MVT ? transformTileCoordsToWGS84(geometry, bbox) : geometry;
1909
+ }
1910
+ map.set(uniquePropertyValue, properties);
1911
+ }
1912
+ function addIntersectedFeaturesInTile({
1913
+ map,
1914
+ data,
1915
+ geometryIntersection,
1916
+ type,
1917
+ bbox,
1918
+ tileFormat,
1919
+ uniqueIdProperty,
1920
+ options
1921
+ }) {
1922
+ const indices = getIndices(data);
1923
+ const storeGeometry = (options == null ? void 0 : options.storeGeometry) || false;
1924
+ for (let i = 0; i < indices.length - 1; i++) {
1925
+ const startIndex = indices[i];
1926
+ const endIndex = indices[i + 1];
1927
+ processTileFeatureProperties({
1928
+ map,
1929
+ data,
1930
+ startIndex,
1931
+ endIndex,
1932
+ type,
1933
+ bbox,
1934
+ tileFormat,
1935
+ uniqueIdProperty,
1936
+ storeGeometry,
1937
+ geometryIntersection
1938
+ });
1939
+ }
1940
+ }
1941
+ function getIndices(data) {
1942
+ let indices;
1943
+ switch (data.type) {
1944
+ case 'Point':
1945
+ // @ts-expect-error Missing or changed types?
1946
+ indices = data.pointIndices;
1947
+ break;
1948
+ case 'LineString':
1949
+ indices = data.pathIndices;
1950
+ break;
1951
+ case 'Polygon':
1952
+ indices = data.primitivePolygonIndices;
1953
+ break;
1954
+ default:
1955
+ throw new Error(`Unexpected type, "${data.type}"`);
1956
+ }
1957
+ return indices.value;
1958
+ }
1959
+ function getFeatureId(data, startIndex) {
1960
+ return data.featureIds.value[startIndex];
1961
+ }
1962
+ function getPropertiesFromTile(data, startIndex) {
1963
+ var _fields$featureId;
1964
+ const featureId = getFeatureId(data, startIndex);
1965
+ const {
1966
+ properties,
1967
+ numericProps,
1968
+ fields
1969
+ } = data;
1970
+ const result = {
1971
+ uniqueId: fields == null || (_fields$featureId = fields[featureId]) == null ? void 0 : _fields$featureId.id,
1972
+ properties: properties[featureId],
1973
+ numericProps: {}
1974
+ };
1975
+ for (const key in numericProps) {
1976
+ result.numericProps[key] = numericProps[key].value[startIndex];
1977
+ }
1978
+ return result;
1979
+ }
1980
+ function parseProperties(tileProps) {
1981
+ const {
1982
+ properties,
1983
+ numericProps
1984
+ } = tileProps;
1985
+ return Object.assign({}, properties, numericProps);
1986
+ }
1987
+ function getUniquePropertyValue(tileProps, uniqueIdProperty, map) {
1988
+ if (uniqueIdProperty) {
1989
+ return getValueFromTileProps(tileProps, uniqueIdProperty);
1990
+ }
1991
+ if (tileProps.uniqueId) {
1992
+ return tileProps.uniqueId;
1993
+ }
1994
+ const artificialId = map.size + 1; // a counter, assumed as a valid new id
1995
+ return getValueFromTileProps(tileProps, 'cartodb_id') || getValueFromTileProps(tileProps, 'geoid') || artificialId;
1996
+ }
1997
+ function getValueFromTileProps(tileProps, propertyName) {
1998
+ const {
1999
+ properties,
2000
+ numericProps
2001
+ } = tileProps;
2002
+ return numericProps[propertyName] || properties[propertyName];
2003
+ }
2004
+ function getFeatureByType(coordinates, type) {
2005
+ switch (type) {
2006
+ case 'Polygon':
2007
+ return {
2008
+ type: 'Polygon',
2009
+ coordinates: [coordinates]
2010
+ };
2011
+ case 'LineString':
2012
+ return {
2013
+ type: 'LineString',
2014
+ coordinates
2015
+ };
2016
+ case 'Point':
2017
+ return {
2018
+ type: 'Point',
2019
+ coordinates: coordinates[0]
2020
+ };
2021
+ default:
2022
+ throw new Error('Invalid geometry type');
2023
+ }
2024
+ }
2025
+ function getRingCoordinatesFor(startIndex, endIndex, positions) {
2026
+ const ringCoordinates = [];
2027
+ for (let j = startIndex; j < endIndex; j++) {
2028
+ ringCoordinates.push(Array.from(positions.value.subarray(j * positions.size, (j + 1) * positions.size)));
2029
+ }
2030
+ return ringCoordinates;
2031
+ }
2032
+ function calculateFeatures({
2033
+ map,
2034
+ tileIsFullyVisible,
2035
+ geometryIntersection,
2036
+ data,
2037
+ type,
2038
+ bbox,
2039
+ tileFormat,
2040
+ uniqueIdProperty,
2041
+ options
2042
+ }) {
2043
+ if (!(data != null && data.properties.length)) {
2044
+ return;
2045
+ }
2046
+ if (tileIsFullyVisible) {
2047
+ addAllFeaturesInTile({
2048
+ map,
2049
+ data,
2050
+ type,
2051
+ bbox,
2052
+ tileFormat,
2053
+ uniqueIdProperty,
2054
+ options
2055
+ });
2056
+ } else {
2057
+ addIntersectedFeaturesInTile({
2058
+ map,
2059
+ data,
2060
+ geometryIntersection,
2061
+ type,
2062
+ bbox,
2063
+ tileFormat,
2064
+ uniqueIdProperty,
2065
+ options
2066
+ });
2067
+ }
2068
+ }
2069
+ function addAllFeaturesInTile({
2070
+ map,
2071
+ data,
2072
+ type,
2073
+ bbox,
2074
+ tileFormat,
2075
+ uniqueIdProperty,
2076
+ options
2077
+ }) {
2078
+ const indices = getIndices(data);
2079
+ const storeGeometry = (options == null ? void 0 : options.storeGeometry) || false;
2080
+ for (let i = 0; i < indices.length - 1; i++) {
2081
+ const startIndex = indices[i];
2082
+ const endIndex = indices[i + 1];
2083
+ processTileFeatureProperties({
2084
+ map,
2085
+ data,
2086
+ startIndex,
2087
+ endIndex,
2088
+ type,
2089
+ bbox,
2090
+ tileFormat,
2091
+ uniqueIdProperty,
2092
+ storeGeometry
2093
+ });
2094
+ }
2095
+ }
2096
+ function createIndicesForPoints(data) {
2097
+ const featureIds = data.featureIds.value;
2098
+ const lastFeatureId = featureIds[featureIds.length - 1];
2099
+ const PointIndicesArray = featureIds.constructor;
2100
+ const pointIndices = {
2101
+ value: new PointIndicesArray(featureIds.length + 1),
2102
+ size: 1
2103
+ };
2104
+ pointIndices.value.set(featureIds);
2105
+ pointIndices.value.set([lastFeatureId + 1], featureIds.length);
2106
+ // @ts-expect-error Missing or changed types?
2107
+ data.pointIndices = pointIndices;
2108
+ }
2109
+
2110
+ // a tile is an array [x,y,z]
2111
+ var d2r = Math.PI / 180,
2112
+ r2d = 180 / Math.PI;
2113
+ function tileToBBOX(tile) {
2114
+ var e = tile2lon(tile[0] + 1, tile[2]);
2115
+ var w = tile2lon(tile[0], tile[2]);
2116
+ var s = tile2lat(tile[1] + 1, tile[2]);
2117
+ var n = tile2lat(tile[1], tile[2]);
2118
+ return [w, s, e, n];
2119
+ }
2120
+ function tileToGeoJSON(tile) {
2121
+ var bbox = tileToBBOX(tile);
2122
+ var poly = {
2123
+ type: 'Polygon',
2124
+ coordinates: [[[bbox[0], bbox[1]], [bbox[0], bbox[3]], [bbox[2], bbox[3]], [bbox[2], bbox[1]], [bbox[0], bbox[1]]]]
2125
+ };
2126
+ return poly;
2127
+ }
2128
+ function tile2lon(x, z) {
2129
+ return x / Math.pow(2, z) * 360 - 180;
2130
+ }
2131
+ function tile2lat(y, z) {
2132
+ var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
2133
+ return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
2134
+ }
2135
+ function pointToTile(lon, lat, z) {
2136
+ var tile = pointToTileFraction(lon, lat, z);
2137
+ tile[0] = Math.floor(tile[0]);
2138
+ tile[1] = Math.floor(tile[1]);
2139
+ return tile;
2140
+ }
2141
+ function getChildren(tile) {
2142
+ 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]];
2143
+ }
2144
+ function getParent(tile) {
2145
+ // top left
2146
+ if (tile[0] % 2 === 0 && tile[1] % 2 === 0) {
2147
+ return [tile[0] / 2, tile[1] / 2, tile[2] - 1];
2148
+ }
2149
+ // bottom left
2150
+ else if (tile[0] % 2 === 0 && !tile[1] % 2 === 0) {
2151
+ return [tile[0] / 2, (tile[1] - 1) / 2, tile[2] - 1];
2152
+ }
2153
+ // top right
2154
+ else if (!tile[0] % 2 === 0 && tile[1] % 2 === 0) {
2155
+ return [(tile[0] - 1) / 2, tile[1] / 2, tile[2] - 1];
2156
+ }
2157
+ // bottom right
2158
+ else {
2159
+ return [(tile[0] - 1) / 2, (tile[1] - 1) / 2, tile[2] - 1];
2160
+ }
2161
+ }
2162
+ function getSiblings(tile) {
2163
+ return getChildren(getParent(tile));
2164
+ }
2165
+ function hasSiblings(tile, tiles) {
2166
+ var siblings = getSiblings(tile);
2167
+ for (var i = 0; i < siblings.length; i++) {
2168
+ if (!hasTile(tiles, siblings[i])) return false;
2169
+ }
2170
+ return true;
2171
+ }
2172
+ function hasTile(tiles, tile) {
2173
+ for (var i = 0; i < tiles.length; i++) {
2174
+ if (tilesEqual(tiles[i], tile)) return true;
2175
+ }
2176
+ return false;
2177
+ }
2178
+ function tilesEqual(tile1, tile2) {
2179
+ return tile1[0] === tile2[0] && tile1[1] === tile2[1] && tile1[2] === tile2[2];
2180
+ }
2181
+ function tileToQuadkey(tile) {
2182
+ var index = '';
2183
+ for (var z = tile[2]; z > 0; z--) {
2184
+ var b = 0;
2185
+ var mask = 1 << z - 1;
2186
+ if ((tile[0] & mask) !== 0) b++;
2187
+ if ((tile[1] & mask) !== 0) b += 2;
2188
+ index += b.toString();
2189
+ }
2190
+ return index;
2191
+ }
2192
+ function quadkeyToTile(quadkey) {
2193
+ var x = 0;
2194
+ var y = 0;
2195
+ var z = quadkey.length;
2196
+ for (var i = z; i > 0; i--) {
2197
+ var mask = 1 << i - 1;
2198
+ switch (quadkey[z - i]) {
2199
+ case '0':
2200
+ break;
2201
+ case '1':
2202
+ x |= mask;
2203
+ break;
2204
+ case '2':
2205
+ y |= mask;
2206
+ break;
2207
+ case '3':
2208
+ x |= mask;
2209
+ y |= mask;
2210
+ break;
2211
+ }
2212
+ }
2213
+ return [x, y, z];
2214
+ }
2215
+ function bboxToTile(bboxCoords) {
2216
+ var min = pointToTile(bboxCoords[0], bboxCoords[1], 32);
2217
+ var max = pointToTile(bboxCoords[2], bboxCoords[3], 32);
2218
+ var bbox = [min[0], min[1], max[0], max[1]];
2219
+ var z = getBboxZoom(bbox);
2220
+ if (z === 0) return [0, 0, 0];
2221
+ var x = bbox[0] >>> 32 - z;
2222
+ var y = bbox[1] >>> 32 - z;
2223
+ return [x, y, z];
2224
+ }
2225
+ function getBboxZoom(bbox) {
2226
+ var MAX_ZOOM = 28;
2227
+ for (var z = 0; z < MAX_ZOOM; z++) {
2228
+ var mask = 1 << 32 - (z + 1);
2229
+ if ((bbox[0] & mask) != (bbox[2] & mask) || (bbox[1] & mask) != (bbox[3] & mask)) {
2230
+ return z;
2231
+ }
2232
+ }
2233
+ return MAX_ZOOM;
2234
+ }
2235
+ function pointToTileFraction(lon, lat, z) {
2236
+ var sin = Math.sin(lat * d2r),
2237
+ z2 = Math.pow(2, z),
2238
+ x = z2 * (lon / 360 + 0.5),
2239
+ y = z2 * (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
2240
+ return [x, y, z];
2241
+ }
2242
+ var tilebelt = {
2243
+ tileToGeoJSON: tileToGeoJSON,
2244
+ tileToBBOX: tileToBBOX,
2245
+ getChildren: getChildren,
2246
+ getParent: getParent,
2247
+ getSiblings: getSiblings,
2248
+ hasTile: hasTile,
2249
+ hasSiblings: hasSiblings,
2250
+ tilesEqual: tilesEqual,
2251
+ tileToQuadkey: tileToQuadkey,
2252
+ quadkeyToTile: quadkeyToTile,
2253
+ pointToTile: pointToTile,
2254
+ bboxToTile: bboxToTile,
2255
+ pointToTileFraction: pointToTileFraction
2256
+ };
2257
+
2258
+ /**
2259
+ * Given a geometry, create cells and return them in their raw form,
2260
+ * as an array of cell identifiers.
2261
+ *
2262
+ * @alias tiles
2263
+ * @param {Object} geom GeoJSON geometry
2264
+ * @param {Object} limits an object with min_zoom and max_zoom properties
2265
+ * specifying the minimum and maximum level to be tiled.
2266
+ * @returns {Array<Array<number>>} An array of tiles given as [x, y, z] arrays
2267
+ */
2268
+ var tiles = getTiles;
2269
+ function getTiles(geom, limits) {
2270
+ var i,
2271
+ tile,
2272
+ coords = geom.coordinates,
2273
+ maxZoom = limits.max_zoom,
2274
+ tileHash = {},
2275
+ tiles = [];
2276
+ if (geom.type === 'Point') {
2277
+ return [tilebelt.pointToTile(coords[0], coords[1], maxZoom)];
2278
+ } else if (geom.type === 'MultiPoint') {
2279
+ for (i = 0; i < coords.length; i++) {
2280
+ tile = tilebelt.pointToTile(coords[i][0], coords[i][1], maxZoom);
2281
+ tileHash[toID(tile[0], tile[1], tile[2])] = true;
2282
+ }
2283
+ } else if (geom.type === 'LineString') {
2284
+ lineCover(tileHash, coords, maxZoom);
2285
+ } else if (geom.type === 'MultiLineString') {
2286
+ for (i = 0; i < coords.length; i++) {
2287
+ lineCover(tileHash, coords[i], maxZoom);
2288
+ }
2289
+ } else if (geom.type === 'Polygon') {
2290
+ polygonCover(tileHash, tiles, coords, maxZoom);
2291
+ } else if (geom.type === 'MultiPolygon') {
2292
+ for (i = 0; i < coords.length; i++) {
2293
+ polygonCover(tileHash, tiles, coords[i], maxZoom);
2294
+ }
2295
+ } else {
2296
+ throw new Error('Geometry type not implemented');
2297
+ }
2298
+ if (limits.min_zoom !== maxZoom) {
2299
+ // sync tile hash and tile array so that both contain the same tiles
2300
+ var len = tiles.length;
2301
+ appendHashTiles(tileHash, tiles);
2302
+ for (i = 0; i < len; i++) {
2303
+ var t = tiles[i];
2304
+ tileHash[toID(t[0], t[1], t[2])] = true;
2305
+ }
2306
+ return mergeTiles(tileHash, tiles, limits);
2307
+ }
2308
+ appendHashTiles(tileHash, tiles);
2309
+ return tiles;
2310
+ }
2311
+ function mergeTiles(tileHash, tiles, limits) {
2312
+ var mergedTiles = [];
2313
+ for (var z = limits.max_zoom; z > limits.min_zoom; z--) {
2314
+ var parentTileHash = {};
2315
+ var parentTiles = [];
2316
+ for (var i = 0; i < tiles.length; i++) {
2317
+ var t = tiles[i];
2318
+ if (t[0] % 2 === 0 && t[1] % 2 === 0) {
2319
+ var id2 = toID(t[0] + 1, t[1], z),
2320
+ id3 = toID(t[0], t[1] + 1, z),
2321
+ id4 = toID(t[0] + 1, t[1] + 1, z);
2322
+ if (tileHash[id2] && tileHash[id3] && tileHash[id4]) {
2323
+ tileHash[toID(t[0], t[1], t[2])] = false;
2324
+ tileHash[id2] = false;
2325
+ tileHash[id3] = false;
2326
+ tileHash[id4] = false;
2327
+ var parentTile = [t[0] / 2, t[1] / 2, z - 1];
2328
+ if (z - 1 === limits.min_zoom) mergedTiles.push(parentTile);else {
2329
+ parentTileHash[toID(t[0] / 2, t[1] / 2, z - 1)] = true;
2330
+ parentTiles.push(parentTile);
2331
+ }
2332
+ }
2333
+ }
2334
+ }
2335
+ for (i = 0; i < tiles.length; i++) {
2336
+ t = tiles[i];
2337
+ if (tileHash[toID(t[0], t[1], t[2])]) mergedTiles.push(t);
2338
+ }
2339
+ tileHash = parentTileHash;
2340
+ tiles = parentTiles;
2341
+ }
2342
+ return mergedTiles;
2343
+ }
2344
+ function polygonCover(tileHash, tileArray, geom, zoom) {
2345
+ var intersections = [];
2346
+ for (var i = 0; i < geom.length; i++) {
2347
+ var ring = [];
2348
+ lineCover(tileHash, geom[i], zoom, ring);
2349
+ for (var j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
2350
+ var m = (j + 1) % len;
2351
+ var y = ring[j][1];
2352
+
2353
+ // add interesction if it's not local extremum or duplicate
2354
+ if ((y > ring[k][1] || y > ring[m][1]) && (
2355
+ // not local minimum
2356
+ y < ring[k][1] || y < ring[m][1]) &&
2357
+ // not local maximum
2358
+ y !== ring[m][1]) intersections.push(ring[j]);
2359
+ }
2360
+ }
2361
+ intersections.sort(compareTiles); // sort by y, then x
2362
+
2363
+ for (i = 0; i < intersections.length; i += 2) {
2364
+ // fill tiles between pairs of intersections
2365
+ y = intersections[i][1];
2366
+ for (var x = intersections[i][0] + 1; x < intersections[i + 1][0]; x++) {
2367
+ var id = toID(x, y, zoom);
2368
+ if (!tileHash[id]) {
2369
+ tileArray.push([x, y, zoom]);
2370
+ }
2371
+ }
2372
+ }
2373
+ }
2374
+ function compareTiles(a, b) {
2375
+ return a[1] - b[1] || a[0] - b[0];
2376
+ }
2377
+ function lineCover(tileHash, coords, maxZoom, ring) {
2378
+ var prevX, prevY;
2379
+ for (var i = 0; i < coords.length - 1; i++) {
2380
+ var start = tilebelt.pointToTileFraction(coords[i][0], coords[i][1], maxZoom),
2381
+ stop = tilebelt.pointToTileFraction(coords[i + 1][0], coords[i + 1][1], maxZoom),
2382
+ x0 = start[0],
2383
+ y0 = start[1],
2384
+ x1 = stop[0],
2385
+ y1 = stop[1],
2386
+ dx = x1 - x0,
2387
+ dy = y1 - y0;
2388
+ if (dy === 0 && dx === 0) continue;
2389
+ var sx = dx > 0 ? 1 : -1,
2390
+ sy = dy > 0 ? 1 : -1,
2391
+ x = Math.floor(x0),
2392
+ y = Math.floor(y0),
2393
+ tMaxX = dx === 0 ? Infinity : Math.abs(((dx > 0 ? 1 : 0) + x - x0) / dx),
2394
+ tMaxY = dy === 0 ? Infinity : Math.abs(((dy > 0 ? 1 : 0) + y - y0) / dy),
2395
+ tdx = Math.abs(sx / dx),
2396
+ tdy = Math.abs(sy / dy);
2397
+ if (x !== prevX || y !== prevY) {
2398
+ tileHash[toID(x, y, maxZoom)] = true;
2399
+ if (ring && y !== prevY) ring.push([x, y]);
2400
+ prevX = x;
2401
+ prevY = y;
2402
+ }
2403
+ while (tMaxX < 1 || tMaxY < 1) {
2404
+ if (tMaxX < tMaxY) {
2405
+ tMaxX += tdx;
2406
+ x += sx;
2407
+ } else {
2408
+ tMaxY += tdy;
2409
+ y += sy;
2410
+ }
2411
+ tileHash[toID(x, y, maxZoom)] = true;
2412
+ if (ring && y !== prevY) ring.push([x, y]);
2413
+ prevX = x;
2414
+ prevY = y;
2415
+ }
2416
+ }
2417
+ if (ring && y === ring[0][1]) ring.pop();
2418
+ }
2419
+ function appendHashTiles(hash, tiles) {
2420
+ var keys = Object.keys(hash);
2421
+ for (var i = 0; i < keys.length; i++) {
2422
+ tiles.push(fromID(+keys[i]));
2423
+ }
2424
+ }
2425
+ function toID(x, y, z) {
2426
+ var dim = 2 * (1 << z);
2427
+ return (dim * y + x) * 32 + z;
2428
+ }
2429
+ function fromID(id) {
2430
+ var z = id % 32,
2431
+ dim = 2 * (1 << z),
2432
+ xy = (id - z) / 32,
2433
+ x = xy % dim,
2434
+ y = (xy - x) / dim % dim;
2435
+ return [x, y, z];
2436
+ }
2437
+
2438
+ const B = [0x5555555555555555n, 0x3333333333333333n, 0x0f0f0f0f0f0f0f0fn, 0x00ff00ff00ff00ffn, 0x0000ffff0000ffffn, 0x00000000ffffffffn];
2439
+ const S = [0n, 1n, 2n, 4n, 8n, 16n];
2440
+ function tileToCell(tile) {
2441
+ if (tile.z < 0 || tile.z > 26) {
2442
+ throw new Error('Wrong zoom');
2443
+ }
2444
+ const z = BigInt(tile.z);
2445
+ let x = BigInt(tile.x) << 32n - z;
2446
+ let y = BigInt(tile.y) << 32n - z;
2447
+ for (let i = 0; i < 5; i++) {
2448
+ const s = S[5 - i];
2449
+ const b = B[4 - i];
2450
+ x = (x | x << s) & b;
2451
+ y = (y | y << s) & b;
2452
+ }
2453
+ const quadbin = 0x4000000000000000n | 1n << 59n |
2454
+ // | (mode << 59) | (mode_dep << 57)
2455
+ z << 52n | (x | y << 1n) >> 12n | 0xfffffffffffffn >> z * 2n;
2456
+ return quadbin;
2457
+ }
2458
+ function getResolution$1(quadbin) {
2459
+ return quadbin >> 52n & 0x1fn;
2460
+ }
2461
+ function geometryToCells(geometry, resolution) {
2462
+ const zoom = Number(resolution);
2463
+ return tiles(geometry, {
2464
+ min_zoom: zoom,
2465
+ max_zoom: zoom
2466
+ }).map(([x, y, z]) => tileToCell({
2467
+ x,
2468
+ y,
2469
+ z
2470
+ }));
2471
+ }
2472
+
2473
+ function tileFeaturesSpatialIndex({
2474
+ tiles,
2475
+ spatialFilter,
2476
+ spatialDataColumn,
2477
+ spatialDataType
2478
+ }) {
2479
+ const map = new Map();
2480
+ const spatialIndex = getSpatialIndex(spatialDataType);
2481
+ const resolution = getResolution(tiles, spatialIndex);
2482
+ const spatialIndexIDName = spatialDataColumn ? spatialDataColumn : spatialIndex;
2483
+ if (!resolution) {
2484
+ return [];
2485
+ }
2486
+ const cells = getCellsCoverGeometry(spatialFilter, spatialIndex, resolution);
2487
+ if (!(cells != null && cells.length)) {
2488
+ return [];
2489
+ }
2490
+ // We transform cells to Set to improve the performace
2491
+ const cellsSet = new Set(cells);
2492
+ for (const tile of tiles) {
2493
+ if (tile.isVisible === false || !tile.data) {
2494
+ continue;
2495
+ }
2496
+ tile.data.forEach(d => {
2497
+ if (cellsSet.has(d.id)) {
2498
+ map.set(d.id, _extends({}, d.properties, {
2499
+ [spatialIndexIDName]: d.id
2500
+ }));
2501
+ }
2502
+ });
2503
+ }
2504
+ return Array.from(map.values());
2505
+ }
2506
+ function getResolution(tiles, spatialIndex) {
2507
+ var _tiles$find;
2508
+ const data = (_tiles$find = tiles.find(tile => {
2509
+ var _tile$data;
2510
+ return (_tile$data = tile.data) == null ? void 0 : _tile$data.length;
2511
+ })) == null ? void 0 : _tiles$find.data;
2512
+ if (!data) {
2513
+ return;
2514
+ }
2515
+ if (spatialIndex === SpatialIndex.QUADBIN) {
2516
+ return Number(getResolution$1(data[0].id));
2517
+ }
2518
+ if (spatialIndex === SpatialIndex.H3) {
2519
+ return getResolution$2(data[0].id);
2520
+ }
2521
+ }
2522
+ const bboxWest = [-180, -90, 0, 90];
2523
+ const bboxEast = [0, -90, 180, 90];
2524
+ function getCellsCoverGeometry(geometry, spatialIndex, resolution) {
2525
+ if (spatialIndex === SpatialIndex.QUADBIN) {
2526
+ // @ts-expect-error TODO: Probably ought to be stricter about number vs. bigint types in this file.
2527
+ return geometryToCells(geometry, resolution);
2528
+ }
2529
+ if (spatialIndex === SpatialIndex.H3) {
2530
+ // The current H3 polyfill algorithm can't deal with polygon segments of greater than 180 degrees longitude
2531
+ // so we clip the geometry to be sure that none of them is greater than 180 degrees
2532
+ // https://github.com/uber/h3-js/issues/24#issuecomment-431893796
2533
+ return polygonToCells(bboxClip(geometry, bboxWest).geometry.coordinates, resolution, true).concat(polygonToCells(bboxClip(geometry, bboxEast).geometry.coordinates, resolution, true));
2534
+ }
2535
+ }
2536
+ function getSpatialIndex(spatialDataType) {
2537
+ switch (spatialDataType) {
2538
+ case 'h3':
2539
+ return SpatialIndex.H3;
2540
+ case 'quadbin':
2541
+ return SpatialIndex.QUADBIN;
2542
+ default:
2543
+ throw new Error('Unexpected spatial data type');
2544
+ }
2545
+ }
2546
+
2547
+ /** @internalRemarks Source: @carto/react-core */
2548
+ function tileFeatures({
2549
+ tiles,
2550
+ spatialFilter,
2551
+ uniqueIdProperty,
2552
+ tileFormat,
2553
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
2554
+ spatialDataType,
2555
+ options = {}
2556
+ }) {
2557
+ // TODO(cleanup): Is an empty response the expected result when spatialFilter
2558
+ // is omitted? Why not make the parameter required, or return the full input?
2559
+ if (!spatialFilter) {
2560
+ return [];
2561
+ }
2562
+ if (spatialDataType !== 'geo') {
2563
+ return tileFeaturesSpatialIndex({
2564
+ tiles: tiles,
2565
+ spatialFilter,
2566
+ spatialDataColumn,
2567
+ spatialDataType
2568
+ });
2569
+ }
2570
+ return tileFeaturesGeometries({
2571
+ tiles,
2572
+ tileFormat,
2573
+ spatialFilter,
2574
+ uniqueIdProperty,
2575
+ options
2576
+ });
2577
+ }
2578
+
2579
+ /** @internalRemarks Source: @carto/react-core */
2580
+ const aggregationFunctions = {
2581
+ count: values => values.length,
2582
+ min: (...args) => applyAggregationFunction(min, ...args),
2583
+ max: (...args) => applyAggregationFunction(max, ...args),
2584
+ sum: (...args) => applyAggregationFunction(sum, ...args),
2585
+ avg: (...args) => applyAggregationFunction(avg, ...args)
2586
+ };
2587
+ /** @internalRemarks Source: @carto/react-core */
2588
+ function aggregate(feature, keys, operation) {
2589
+ if (!(keys != null && keys.length)) {
2590
+ throw new Error('Cannot aggregate a feature without having keys');
2591
+ } else if (keys.length === 1) {
2592
+ const value = feature[keys[0]];
2593
+ return isPotentiallyValidNumber(value) ? Number(value) : value;
2594
+ }
2595
+ const aggregationFn = aggregationFunctions[operation];
2596
+ if (!aggregationFn) {
2597
+ throw new Error(`${operation} isn't a valid aggregation function`);
2598
+ }
2599
+ return aggregationFn(keys.map(column => {
2600
+ const value = feature[column];
2601
+ return isPotentiallyValidNumber(value) ? Number(value) : value;
2602
+ }));
2603
+ }
2604
+ /*
2605
+ * Forced casting to Number (just of non empty strings) allows to work-around
2606
+ * some specific situations, where a big numeric field is transformed into a string when generating the tileset(eg.PG)
2607
+ */
2608
+ function isPotentiallyValidNumber(value) {
2609
+ return typeof value === 'string' && value.trim().length > 0;
2610
+ }
2611
+ const applyAggregationFunction = (aggFn, values, keys, operation) => {
2612
+ const normalizedKeys = normalizeKeys(keys);
2613
+ const elements = ((normalizedKeys == null ? void 0 : normalizedKeys.length) || 0) <= 1 ? filterFalsyElements(values, normalizedKeys || []) : values;
2614
+ return aggFn(elements, keys, operation);
2615
+ };
2616
+ function filterFalsyElements(values, keys) {
2617
+ const filterFn = value => value !== null && value !== undefined;
2618
+ if (!(keys != null && keys.length)) {
2619
+ return values.filter(filterFn);
2620
+ }
2621
+ return values.filter(v => filterFn(v[keys[0]]));
2622
+ }
2623
+ // Aggregation functions
2624
+ function avg(values, keys, joinOperation) {
2625
+ return sum(values, keys, joinOperation) / (values.length || 1);
2626
+ }
2627
+ function sum(values, keys, joinOperation) {
2628
+ const normalizedKeys = normalizeKeys(keys);
2629
+ if (normalizedKeys) {
2630
+ return values.reduce((a, b) => a + aggregate(b, normalizedKeys, joinOperation), 0);
2631
+ }
2632
+ return values.reduce((a, b) => a + b, 0);
2633
+ }
2634
+ function min(values, keys, joinOperation) {
2635
+ const normalizedKeys = normalizeKeys(keys);
2636
+ if (normalizedKeys) {
2637
+ return values.reduce((a, b) => Math.min(a, aggregate(b, normalizedKeys, joinOperation)), Infinity);
2638
+ }
2639
+ return Math.min(...values);
2640
+ }
2641
+ function max(values, keys, joinOperation) {
2642
+ const normalizedKeys = normalizeKeys(keys);
2643
+ if (normalizedKeys) {
2644
+ return values.reduce((a, b) => Math.max(a, aggregate(b, normalizedKeys, joinOperation)), -Infinity);
2645
+ }
2646
+ return Math.max(...values);
2647
+ }
2648
+ // Aux
2649
+ // Keys can come as a string (one column) or a strings array (multiple column)
2650
+ // Use always an array to make the code easier
2651
+ function normalizeKeys(keys) {
2652
+ return Array.isArray(keys) ? keys : typeof keys === 'string' ? [keys] : undefined;
2653
+ }
2654
+
2655
+ /***
2656
+ Copyright 2013 Teun Duynstee
2657
+
2658
+ Licensed under the Apache License, Version 2.0 (the "License");
2659
+ you may not use this file except in compliance with the License.
2660
+ You may obtain a copy of the License at
2661
+
2662
+ http://www.apache.org/licenses/LICENSE-2.0
2663
+
2664
+ Unless required by applicable law or agreed to in writing, software
2665
+ distributed under the License is distributed on an "AS IS" BASIS,
2666
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2667
+ See the License for the specific language governing permissions and
2668
+ limitations under the License.
2669
+ */
2670
+ var thenBy_module = function () {
2671
+ function identity(v) {
2672
+ return v;
2673
+ }
2674
+ function ignoreCase(v) {
2675
+ return typeof v === "string" ? v.toLowerCase() : v;
2676
+ }
2677
+ function makeCompareFunction(f, opt) {
2678
+ opt = typeof opt === "object" ? opt : {
2679
+ direction: opt
2680
+ };
2681
+ if (typeof f != "function") {
2682
+ var prop = f;
2683
+ // make unary function
2684
+ f = function (v1) {
2685
+ return !!v1[prop] ? v1[prop] : "";
2686
+ };
2687
+ }
2688
+ if (f.length === 1) {
2689
+ // f is a unary function mapping a single item to its sort score
2690
+ var uf = f;
2691
+ var preprocess = opt.ignoreCase ? ignoreCase : identity;
2692
+ var cmp = opt.cmp || function (v1, v2) {
2693
+ return v1 < v2 ? -1 : v1 > v2 ? 1 : 0;
2694
+ };
2695
+ f = function (v1, v2) {
2696
+ return cmp(preprocess(uf(v1)), preprocess(uf(v2)));
2697
+ };
2698
+ }
2699
+ const descTokens = {
2700
+ "-1": '',
2701
+ desc: ''
2702
+ };
2703
+ if (opt.direction in descTokens) return function (v1, v2) {
2704
+ return -f(v1, v2);
2705
+ };
2706
+ return f;
2707
+ }
2708
+
2709
+ /* adds a secondary compare function to the target function (`this` context)
2710
+ which is applied in case the first one returns 0 (equal)
2711
+ returns a new compare function, which has a `thenBy` method as well */
2712
+ function tb(func, opt) {
2713
+ /* should get value false for the first call. This can be done by calling the
2714
+ exported function, or the firstBy property on it (for es6 module compatibility)
2715
+ */
2716
+ var x = typeof this == "function" && !this.firstBy ? this : false;
2717
+ var y = makeCompareFunction(func, opt);
2718
+ var f = x ? function (a, b) {
2719
+ return x(a, b) || y(a, b);
2720
+ } : y;
2721
+ f.thenBy = tb;
2722
+ return f;
2723
+ }
2724
+ tb.firstBy = tb;
2725
+ return tb;
2726
+ }();
2727
+
2728
+ /**
2729
+ * Apply sort structure to a collection of features
2730
+ * @param features
2731
+ * @param [sortOptions]
2732
+ * @param [sortOptions.sortBy] - One or more columns to sort by
2733
+ * @param [sortOptions.sortByDirection] - Direction by the columns will be sorted
2734
+ * @param [sortOptions.sortByColumnType] - Column type
2735
+ * @internal
2736
+ * @internalRemarks Source: @carto/react-core
2737
+ */
2738
+ function applySorting(features, {
2739
+ sortBy,
2740
+ sortByDirection = 'asc',
2741
+ sortByColumnType = 'string'
2742
+ } = {}) {
2743
+ // If sortBy is undefined, pass all features
2744
+ if (sortBy === undefined) {
2745
+ return features;
2746
+ }
2747
+ // sortOptions exists, but are bad formatted
2748
+ const isValidSortBy = Array.isArray(sortBy) && sortBy.length ||
2749
+ // sortBy can be an array of columns
2750
+ typeof sortBy === 'string'; // or just one column
2751
+ if (!isValidSortBy) {
2752
+ throw new Error('Sorting options are bad formatted');
2753
+ }
2754
+ const sortFn = createSortFn({
2755
+ sortBy,
2756
+ sortByDirection,
2757
+ sortByColumnType: sortByColumnType || 'string'
2758
+ });
2759
+ return features.sort(sortFn);
2760
+ }
2761
+ // Aux
2762
+ function createSortFn({
2763
+ sortBy,
2764
+ sortByDirection,
2765
+ sortByColumnType
2766
+ }) {
2767
+ const [firstSortOption, ...othersSortOptions] = normalizeSortByOptions({
2768
+ sortBy,
2769
+ sortByDirection,
2770
+ sortByColumnType
2771
+ });
2772
+ let sortFn = thenBy_module.firstBy(...firstSortOption);
2773
+ for (let sortOptions of othersSortOptions) {
2774
+ sortFn = sortFn.thenBy(...sortOptions);
2775
+ }
2776
+ return sortFn;
2777
+ }
2778
+ function normalizeSortByOptions({
2779
+ sortBy,
2780
+ sortByDirection,
2781
+ sortByColumnType
2782
+ }) {
2783
+ const numberFormat = sortByColumnType === 'number' && {
2784
+ cmp: (a, b) => a - b
2785
+ };
2786
+ if (!Array.isArray(sortBy)) {
2787
+ sortBy = [sortBy];
2788
+ }
2789
+ return sortBy.map(sortByEl => {
2790
+ // sortByEl is 'column'
2791
+ if (typeof sortByEl === 'string') {
2792
+ return [sortByEl, _extends({
2793
+ direction: sortByDirection
2794
+ }, numberFormat)];
2795
+ }
2796
+ if (Array.isArray(sortByEl)) {
2797
+ // sortBy is ['column']
2798
+ if (sortByEl[1] === undefined) {
2799
+ return [sortByEl, _extends({
2800
+ direction: sortByDirection
2801
+ }, numberFormat)];
2802
+ }
2803
+ // sortBy is ['column', { ... }]
2804
+ if (typeof sortByEl[1] === 'object') {
2805
+ const othersSortOptions = numberFormat ? _extends({}, numberFormat, sortByEl[1]) : sortByEl[1];
2806
+ return [sortByEl[0], _extends({
2807
+ direction: sortByDirection
2808
+ }, othersSortOptions)];
2809
+ }
2810
+ }
2811
+ return sortByEl;
2812
+ });
2813
+ }
2814
+
2815
+ /** @internalRemarks Source: @carto/react-core */
2816
+ function groupValuesByColumn({
2817
+ data,
2818
+ valuesColumns,
2819
+ joinOperation,
2820
+ keysColumn,
2821
+ operation
2822
+ }) {
2823
+ if (Array.isArray(data) && data.length === 0) {
2824
+ return null;
2825
+ }
2826
+ const groups = data.reduce((accumulator, item) => {
2827
+ const group = item[keysColumn];
2828
+ const values = accumulator.get(group) || [];
2829
+ accumulator.set(group, values);
2830
+ const aggregatedValue = aggregate(item, valuesColumns, joinOperation);
2831
+ const isValid = (operation === 'count' ? true : aggregatedValue !== null) && aggregatedValue !== undefined;
2832
+ if (isValid) {
2833
+ values.push(aggregatedValue);
2834
+ accumulator.set(group, values);
2835
+ }
2836
+ return accumulator;
2837
+ }, new Map()); // We use a map to be able to maintain the type in the key value
2838
+ const targetOperation = aggregationFunctions[operation];
2839
+ if (targetOperation) {
2840
+ return Array.from(groups).map(([name, value]) => ({
2841
+ name,
2842
+ value: targetOperation(value)
2843
+ }));
2844
+ }
2845
+ return [];
2846
+ }
2847
+
2848
+ /**
2849
+ * Returns midnight (local time) on the Monday preceeding a given date, in
2850
+ * milliseconds since the UNIX epoch.
2851
+ */
2852
+ /**
2853
+ * Returns midnight (UTC) on the Monday preceeding a given date, in
2854
+ * milliseconds since the UNIX epoch.
2855
+ */
2856
+ function getUTCMonday(date) {
2857
+ const dateCp = new Date(date);
2858
+ const day = dateCp.getUTCDay();
2859
+ const diff = dateCp.getUTCDate() - day + (day ? 1 : -6); // adjust when day is sunday
2860
+ dateCp.setUTCDate(diff);
2861
+ return Date.UTC(dateCp.getUTCFullYear(), dateCp.getUTCMonth(), dateCp.getUTCDate());
2862
+ }
2863
+
2864
+ const GROUP_KEY_FN_MAPPING = {
2865
+ year: date => Date.UTC(date.getUTCFullYear()),
2866
+ month: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth()),
2867
+ week: date => getUTCMonday(date),
2868
+ day: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()),
2869
+ hour: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours()),
2870
+ minute: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes()),
2871
+ second: date => Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds())
2872
+ };
2873
+ /** @internalRemarks Source: @carto/react-core */
2874
+ function groupValuesByDateColumn({
2875
+ data,
2876
+ valuesColumns,
2877
+ joinOperation,
2878
+ keysColumn,
2879
+ groupType,
2880
+ operation
2881
+ }) {
2882
+ if (Array.isArray(data) && data.length === 0) {
2883
+ return null;
2884
+ }
2885
+ const groupKeyFn = GROUP_KEY_FN_MAPPING[groupType];
2886
+ if (!groupKeyFn) {
2887
+ return null;
2888
+ }
2889
+ const groups = data.reduce((acc, item) => {
2890
+ const value = item[keysColumn];
2891
+ const formattedValue = new Date(value);
2892
+ const groupKey = groupKeyFn(formattedValue);
2893
+ if (!isNaN(groupKey)) {
2894
+ let groupedValues = acc.get(groupKey);
2895
+ if (!groupedValues) {
2896
+ groupedValues = [];
2897
+ acc.set(groupKey, groupedValues);
2898
+ }
2899
+ const aggregatedValue = aggregate(item, valuesColumns, joinOperation);
2900
+ const isValid = aggregatedValue !== null && aggregatedValue !== undefined;
2901
+ if (isValid) {
2902
+ groupedValues.push(aggregatedValue);
2903
+ acc.set(groupKey, groupedValues);
2904
+ }
2905
+ }
2906
+ return acc;
2907
+ }, new Map());
2908
+ const targetOperation = aggregationFunctions[operation];
2909
+ return [...groups.entries()].map(([name, value]) => ({
2910
+ name,
2911
+ value: targetOperation(value)
2912
+ })).sort((a, b) => a.name - b.name);
2913
+ }
2914
+
2915
+ /**
2916
+ * Histogram computation.
2917
+ * @internalRemarks Source: @carto/react-core
2918
+ */
2919
+ function histogram({
2920
+ data,
2921
+ valuesColumns,
2922
+ joinOperation,
2923
+ ticks,
2924
+ operation
2925
+ }) {
2926
+ if (Array.isArray(data) && data.length === 0) {
2927
+ return [];
2928
+ }
2929
+ const binsContainer = [Number.MIN_SAFE_INTEGER, ...ticks].map((tick, index, arr) => ({
2930
+ bin: index,
2931
+ start: tick,
2932
+ end: index === arr.length - 1 ? Number.MAX_SAFE_INTEGER : arr[index + 1],
2933
+ values: []
2934
+ }));
2935
+ data.forEach(feature => {
2936
+ const featureValue = aggregate(feature, valuesColumns, joinOperation);
2937
+ const isValid = featureValue !== null && featureValue !== undefined;
2938
+ if (!isValid) {
2939
+ return;
2940
+ }
2941
+ const binContainer = binsContainer.find(bin => bin.start <= featureValue && bin.end > featureValue);
2942
+ if (!binContainer) {
2943
+ return;
2944
+ }
2945
+ binContainer.values.push(featureValue);
2946
+ });
2947
+ const targetOperation = aggregationFunctions[operation];
2948
+ const transformedBins = binsContainer.map(binContainer => binContainer.values);
2949
+ return transformedBins.map(values => values.length ? targetOperation(values) : 0);
2950
+ }
2951
+
2952
+ /**
2953
+ * Filters invalid features and formats data.
2954
+ * @internalRemarks Source: @carto/react-core
2955
+ */
2956
+ function scatterPlot({
2957
+ data,
2958
+ xAxisColumns,
2959
+ xAxisJoinOperation,
2960
+ yAxisColumns,
2961
+ yAxisJoinOperation
2962
+ }) {
2963
+ return data.reduce((acc, feature) => {
2964
+ const xValue = aggregate(feature, xAxisColumns, xAxisJoinOperation);
2965
+ const xIsValid = xValue !== null && xValue !== undefined;
2966
+ const yValue = aggregate(feature, yAxisColumns, yAxisJoinOperation);
2967
+ const yIsValid = yValue !== null && yValue !== undefined;
2968
+ if (xIsValid && yIsValid) {
2969
+ acc.push([xValue, yValue]);
2970
+ }
2971
+ return acc;
2972
+ }, []);
2973
+ }
2974
+
2975
+ const _excluded = ["filterOwner", "spatialFilter", "abortController"];
2976
+ /**
2977
+ * Source for Widget API requests on a data source defined by a tileset.
2978
+ *
2979
+ * Generally not intended to be constructed directly. Instead, call
2980
+ * {@link vectorTilesetSource}, {@link h3TilesetSource}, or {@link quadbinTilesetSource},
2981
+ * which can be shared with map layers. Sources contain a `widgetSource`
2982
+ * property, for use by widget implementations.
2983
+ *
2984
+ * Example:
2985
+ *
2986
+ * ```javascript
2987
+ * import { vectorTilesetSource } from '@carto/api-client';
2988
+ *
2989
+ * const data = vectorTilesetSource({
2990
+ * accessToken: '••••',
2991
+ * connectionName: 'carto_dw',
2992
+ * tableName: 'carto-demo-data.demo_rasters.my_tileset_source'
2993
+ * });
2994
+ *
2995
+ * const { widgetSource } = await data;
2996
+ * ```
2997
+ */
2998
+ class WidgetTilesetSource extends WidgetSource {
2999
+ constructor(...args) {
3000
+ super(...args);
3001
+ this._tiles = [];
3002
+ this._features = [];
3003
+ }
3004
+ getModelSource(owner) {
3005
+ return _extends({}, super._getModelSource(owner), {
3006
+ type: 'tileset',
3007
+ data: this.props.tableName
3008
+ });
3009
+ }
3010
+ /**
3011
+ * Loads features as a list of tiles (typically provided by deck.gl).
3012
+ * After tiles are loaded, {@link extractTileFeatures} must be called
3013
+ * before computing statistics on the tiles.
3014
+ */
3015
+ loadTiles(tiles) {
3016
+ this._tiles = tiles;
3017
+ }
3018
+ /**
3019
+ * Extracts feature data from tiles previously loaded with {@link loadTiles}.
3020
+ * Must be called before computing statistics on tiles.
3021
+ */
3022
+ extractTileFeatures({
3023
+ spatialFilter,
3024
+ uniqueIdProperty,
3025
+ options
3026
+ }) {
3027
+ this._features = tileFeatures({
3028
+ tiles: this._tiles,
3029
+ options,
3030
+ spatialFilter,
3031
+ uniqueIdProperty,
3032
+ tileFormat: this.props.tileFormat,
3033
+ spatialDataColumn: this.props.spatialDataColumn,
3034
+ spatialDataType: this.props.spatialDataType
3035
+ });
3036
+ }
3037
+ /** Loads features as GeoJSON (used for testing). */
3038
+ loadGeoJSON({
3039
+ geojson,
3040
+ spatialFilter,
3041
+ uniqueIdProperty
3042
+ }) {
3043
+ this._features = geojsonFeatures({
3044
+ geojson,
3045
+ spatialFilter,
3046
+ uniqueIdProperty
3047
+ });
3048
+ }
3049
+ async getFeatures(options) {
3050
+ throw new Error('getFeatures not supported for tilesets');
3051
+ }
3052
+ async getFormula({
3053
+ column = '*',
3054
+ operation = 'count',
3055
+ joinOperation,
3056
+ filterOwner
3057
+ }) {
3058
+ if (operation === 'custom') {
3059
+ throw new Error('Custom aggregation not supported for tilesets');
3060
+ }
3061
+ if (!this._features.length) {
3062
+ return {
3063
+ value: null
3064
+ };
3065
+ }
3066
+ // Column is required except when operation is 'count'.
3067
+ if (column && column !== '*' || operation !== 'count') {
3068
+ assertColumn(this._features, column);
3069
+ }
3070
+ const filteredFeatures = this._getFilteredFeatures(filterOwner);
3071
+ if (filteredFeatures.length === 0 && operation !== 'count') {
3072
+ return {
3073
+ value: null
3074
+ };
3075
+ }
3076
+ const targetOperation = aggregationFunctions[operation];
3077
+ return {
3078
+ value: targetOperation(filteredFeatures, column, joinOperation)
3079
+ };
3080
+ }
3081
+ async getHistogram({
3082
+ operation = 'count',
3083
+ ticks,
3084
+ column,
3085
+ joinOperation,
3086
+ filterOwner
3087
+ }) {
3088
+ if (!this._features.length) {
3089
+ return [];
3090
+ }
3091
+ const filteredFeatures = this._getFilteredFeatures(filterOwner);
3092
+ assertColumn(this._features, column);
3093
+ return histogram({
3094
+ data: filteredFeatures,
3095
+ valuesColumns: normalizeColumns(column),
3096
+ joinOperation,
3097
+ ticks,
3098
+ operation
3099
+ });
3100
+ }
3101
+ async getCategories({
3102
+ column,
3103
+ operation = 'count',
3104
+ operationColumn,
3105
+ joinOperation,
3106
+ filterOwner
3107
+ }) {
3108
+ if (!this._features.length) {
3109
+ return [];
3110
+ }
3111
+ const filteredFeatures = this._getFilteredFeatures(filterOwner);
3112
+ assertColumn(this._features, column, operationColumn);
3113
+ const groups = groupValuesByColumn({
3114
+ data: filteredFeatures,
3115
+ valuesColumns: normalizeColumns(operationColumn || column),
3116
+ joinOperation,
3117
+ keysColumn: column,
3118
+ operation
3119
+ });
3120
+ return groups || [];
3121
+ }
3122
+ async getScatter({
3123
+ xAxisColumn,
3124
+ yAxisColumn,
3125
+ xAxisJoinOperation,
3126
+ yAxisJoinOperation,
3127
+ filterOwner
3128
+ }) {
3129
+ if (!this._features.length) {
3130
+ return [];
3131
+ }
3132
+ const filteredFeatures = this._getFilteredFeatures(filterOwner);
3133
+ assertColumn(this._features, xAxisColumn, yAxisColumn);
3134
+ return scatterPlot({
3135
+ data: filteredFeatures,
3136
+ xAxisColumns: normalizeColumns(xAxisColumn),
3137
+ xAxisJoinOperation,
3138
+ yAxisColumns: normalizeColumns(yAxisColumn),
3139
+ yAxisJoinOperation
3140
+ });
3141
+ }
3142
+ async getTable(options) {
3143
+ const {
3144
+ filterOwner
3145
+ } = options,
3146
+ params = _objectWithoutPropertiesLoose(options, _excluded);
3147
+ const {
3148
+ columns,
3149
+ searchFilterColumn,
3150
+ searchFilterText,
3151
+ sortBy,
3152
+ sortDirection,
3153
+ sortByColumnType,
3154
+ offset = 0,
3155
+ limit = 10
3156
+ } = params;
3157
+ if (!this._features.length) {
3158
+ return {
3159
+ rows: [],
3160
+ totalCount: 0
3161
+ };
3162
+ }
3163
+ // Filter.
3164
+ let filteredFeatures = this._getFilteredFeatures(filterOwner);
3165
+ // Search.
3166
+ // TODO: Could we get the same behavior by applying filters in loadTiles()?
3167
+ if (searchFilterColumn && searchFilterText) {
3168
+ filteredFeatures = filteredFeatures.filter(row => row[searchFilterColumn] && String(row[searchFilterColumn]).toLowerCase().includes(String(searchFilterText).toLowerCase()));
3169
+ }
3170
+ // Sort.
3171
+ let rows = applySorting(filteredFeatures, {
3172
+ sortBy,
3173
+ sortByDirection: sortDirection,
3174
+ sortByColumnType
3175
+ });
3176
+ const totalCount = rows.length;
3177
+ // Offset and limit.
3178
+ rows = rows.slice(Math.min(offset, totalCount), Math.min(offset + limit, totalCount));
3179
+ // Select columns.
3180
+ rows = rows.map(srcRow => {
3181
+ const dstRow = {};
3182
+ for (const column of columns) {
3183
+ dstRow[column] = srcRow[column];
3184
+ }
3185
+ return dstRow;
3186
+ });
3187
+ return {
3188
+ rows,
3189
+ totalCount
3190
+ };
3191
+ }
3192
+ async getTimeSeries({
3193
+ column,
3194
+ stepSize,
3195
+ operation,
3196
+ operationColumn,
3197
+ joinOperation,
3198
+ filterOwner
3199
+ }) {
3200
+ if (!this._features.length) {
3201
+ return {
3202
+ rows: []
3203
+ };
3204
+ }
3205
+ const filteredFeatures = this._getFilteredFeatures(filterOwner);
3206
+ assertColumn(this._features, column, operationColumn);
3207
+ const rows = groupValuesByDateColumn({
3208
+ data: filteredFeatures,
3209
+ valuesColumns: normalizeColumns(operationColumn || column),
3210
+ keysColumn: column,
3211
+ groupType: stepSize,
3212
+ operation,
3213
+ joinOperation
3214
+ }) || [];
3215
+ return {
3216
+ rows
3217
+ };
3218
+ }
3219
+ async getRange({
3220
+ column,
3221
+ filterOwner
3222
+ }) {
3223
+ if (!this._features.length) {
3224
+ // TODO: Is this the only nullable response in the Widgets API? If so,
3225
+ // can we do something more consistent?
3226
+ return null;
3227
+ }
3228
+ assertColumn(this._features, column);
3229
+ const filteredFeatures = this._getFilteredFeatures(filterOwner);
3230
+ return {
3231
+ min: aggregationFunctions.min(filteredFeatures, column),
3232
+ max: aggregationFunctions.max(filteredFeatures, column)
3233
+ };
3234
+ }
3235
+ /****************************************************************************
3236
+ * INTERNAL
3237
+ */
3238
+ _getFilteredFeatures(filterOwner) {
3239
+ return applyFilters(this._features, getApplicableFilters(filterOwner, this.props.filters), this.props.filtersLogicalOperator || 'and');
3240
+ }
3241
+ }
3242
+ function assertColumn(features, ...columnArgs) {
3243
+ // TODO(cleanup): Can drop support for multiple column shapes here?
3244
+ // Due to the multiple column shape, we normalise it as an array with normalizeColumns
3245
+ const columns = Array.from(new Set(columnArgs.map(normalizeColumns).flat()));
3246
+ const featureKeys = Object.keys(features[0]);
3247
+ const invalidColumns = columns.filter(column => !featureKeys.includes(column));
3248
+ if (invalidColumns.length) {
3249
+ throw new InvalidColumnError(`Missing column(s): ${invalidColumns.join(', ')}`);
3250
+ }
3251
+ }
3252
+ function normalizeColumns(columns) {
3253
+ return Array.isArray(columns) ? columns : typeof columns === 'string' ? [columns] : [];
3254
+ }
3255
+
3256
+ const h3QuerySource = async function h3QuerySource(options) {
3257
+ const {
3258
+ aggregationExp,
3259
+ aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
3260
+ sqlQuery,
3261
+ spatialDataColumn = 'h3',
3262
+ queryParameters,
3263
+ filters
3264
+ } = options;
3265
+ const spatialDataType = 'h3';
3266
+ const urlParameters = {
3267
+ aggregationExp,
3268
+ spatialDataColumn,
3269
+ spatialDataType,
3270
+ q: sqlQuery
3271
+ };
3272
+ if (aggregationResLevel) {
3273
+ urlParameters.aggregationResLevel = String(aggregationResLevel);
3274
+ }
3275
+ if (queryParameters) {
3276
+ urlParameters.queryParameters = queryParameters;
3277
+ }
3278
+ if (filters) {
3279
+ urlParameters.filters = filters;
3280
+ }
3281
+ return baseSource('query', options, urlParameters).then(result => _extends({}, result, {
3282
+ widgetSource: new WidgetQuerySource(_extends({}, options, {
3283
+ // NOTE: Parameters with default values above must be explicitly passed here.
3284
+ spatialDataColumn,
3285
+ spatialDataType
3286
+ }))
3287
+ }));
3288
+ };
3289
+
3290
+ const h3TableSource = async function h3TableSource(options) {
3291
+ const {
3292
+ aggregationExp,
3293
+ aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
3294
+ spatialDataColumn = 'h3',
3295
+ tableName,
3296
+ filters
3297
+ } = options;
3298
+ const spatialDataType = 'h3';
3299
+ const urlParameters = {
3300
+ aggregationExp,
3301
+ name: tableName,
3302
+ spatialDataColumn,
3303
+ spatialDataType
3304
+ };
3305
+ if (aggregationResLevel) {
3306
+ urlParameters.aggregationResLevel = String(aggregationResLevel);
3307
+ }
3308
+ if (filters) {
3309
+ urlParameters.filters = filters;
1492
3310
  }
1493
3311
  return baseSource('table', options, urlParameters).then(result => _extends({}, result, {
1494
3312
  widgetSource: new WidgetTableSource(_extends({}, options, {
@@ -1499,17 +3317,26 @@ const h3TableSource = async function h3TableSource(options) {
1499
3317
  }));
1500
3318
  };
1501
3319
 
1502
- // deck.gl
1503
- // SPDX-License-Identifier: MIT
1504
- // Copyright (c) vis.gl contributors
3320
+ function getTileFormat(tilejson) {
3321
+ const tileParams = new URL(tilejson.tiles[0]).searchParams;
3322
+ return tileParams.get('formatTiles') === 'mvt' ? TileFormat.MVT : TileFormat.BINARY;
3323
+ }
3324
+
1505
3325
  const h3TilesetSource = async function h3TilesetSource(options) {
1506
3326
  const {
1507
- tableName
3327
+ tableName,
3328
+ spatialDataColumn = 'h3'
1508
3329
  } = options;
1509
3330
  const urlParameters = {
1510
3331
  name: tableName
1511
3332
  };
1512
- return baseSource('tileset', options, urlParameters);
3333
+ return baseSource('tileset', options, urlParameters).then(result => _extends({}, result, {
3334
+ widgetSource: new WidgetTilesetSource(_extends({}, options, {
3335
+ tileFormat: getTileFormat(result),
3336
+ spatialDataColumn,
3337
+ spatialDataType: 'h3'
3338
+ }))
3339
+ }));
1513
3340
  };
1514
3341
 
1515
3342
  // deck.gl
@@ -1593,24 +3420,28 @@ const quadbinTableSource = async function quadbinTableSource(options) {
1593
3420
  }));
1594
3421
  };
1595
3422
 
1596
- // deck.gl
1597
- // SPDX-License-Identifier: MIT
1598
- // Copyright (c) vis.gl contributors
1599
3423
  const quadbinTilesetSource = async function quadbinTilesetSource(options) {
1600
3424
  const {
1601
- tableName
3425
+ tableName,
3426
+ spatialDataColumn = 'quadbin'
1602
3427
  } = options;
1603
3428
  const urlParameters = {
1604
3429
  name: tableName
1605
3430
  };
1606
- return baseSource('tileset', options, urlParameters);
3431
+ return baseSource('tileset', options, urlParameters).then(result => _extends({}, result, {
3432
+ widgetSource: new WidgetTilesetSource(_extends({}, options, {
3433
+ tileFormat: getTileFormat(result),
3434
+ spatialDataColumn,
3435
+ spatialDataType: 'quadbin'
3436
+ }))
3437
+ }));
1607
3438
  };
1608
3439
 
1609
3440
  const vectorQuerySource = async function vectorQuerySource(options) {
1610
3441
  const {
1611
3442
  columns,
1612
3443
  filters,
1613
- spatialDataColumn = 'geom',
3444
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
1614
3445
  sqlQuery,
1615
3446
  tileResolution = DEFAULT_TILE_RESOLUTION,
1616
3447
  queryParameters,
@@ -1649,7 +3480,7 @@ const vectorTableSource = async function vectorTableSource(options) {
1649
3480
  const {
1650
3481
  columns,
1651
3482
  filters,
1652
- spatialDataColumn = 'geom',
3483
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
1653
3484
  tableName,
1654
3485
  tileResolution = DEFAULT_TILE_RESOLUTION,
1655
3486
  aggregationExp
@@ -1680,17 +3511,21 @@ const vectorTableSource = async function vectorTableSource(options) {
1680
3511
  }));
1681
3512
  };
1682
3513
 
1683
- // deck.gl
1684
- // SPDX-License-Identifier: MIT
1685
- // Copyright (c) vis.gl contributors
1686
3514
  const vectorTilesetSource = async function vectorTilesetSource(options) {
1687
3515
  const {
1688
- tableName
3516
+ tableName,
3517
+ spatialDataColumn = DEFAULT_GEO_COLUMN
1689
3518
  } = options;
1690
3519
  const urlParameters = {
1691
3520
  name: tableName
1692
3521
  };
1693
- return baseSource('tileset', options, urlParameters);
3522
+ return baseSource('tileset', options, urlParameters).then(result => _extends({}, result, {
3523
+ widgetSource: new WidgetTilesetSource(_extends({}, options, {
3524
+ tileFormat: getTileFormat(result),
3525
+ spatialDataColumn,
3526
+ spatialDataType: 'geo'
3527
+ }))
3528
+ }));
1694
3529
  };
1695
3530
 
1696
3531
  const query = async function query(options) {
@@ -1735,5 +3570,5 @@ const query = async function query(options) {
1735
3570
  });
1736
3571
  };
1737
3572
 
1738
- export { ApiVersion, CartoAPIError, DEFAULT_API_BASE_URL, FilterType, SOURCE_DEFAULTS, WidgetBaseSource, WidgetQuerySource, WidgetTableSource, addFilter, boundaryQuerySource, boundaryTableSource, buildPublicMapUrl, buildStatsUrl, clearFilters, createPolygonSpatialFilter, createViewportSpatialFilter, getClient, getFilter, h3QuerySource, h3TableSource, h3TilesetSource, hasFilter, quadbinQuerySource, quadbinTableSource, quadbinTilesetSource, query, rasterSource, removeFilter, requestWithParameters, setClient, vectorQuerySource, vectorTableSource, vectorTilesetSource };
3573
+ export { ApiVersion, CartoAPIError, DEFAULT_API_BASE_URL, FEATURE_GEOM_PROPERTY, FilterType, Provider, SOURCE_DEFAULTS, SpatialIndex, TileFormat, WidgetQuerySource, WidgetRemoteSource, WidgetSource, WidgetTableSource, WidgetTilesetSource, addFilter, aggregate, aggregationFunctions, applyFilters, applySorting, boundaryQuerySource, boundaryTableSource, buildBinaryFeatureFilter, buildFeatureFilter, buildPublicMapUrl, buildStatsUrl, clearFilters, createPolygonSpatialFilter, createViewportSpatialFilter, filterFunctions, geojsonFeatures, getClient, getFilter, groupValuesByColumn, groupValuesByDateColumn, h3QuerySource, h3TableSource, h3TilesetSource, hasFilter, histogram, makeIntervalComplete, quadbinQuerySource, quadbinTableSource, quadbinTilesetSource, query, rasterSource, removeFilter, requestWithParameters, scatterPlot, setClient, tileFeatures, tileFeaturesGeometries, tileFeaturesSpatialIndex, transformToTileCoords, vectorQuerySource, vectorTableSource, vectorTilesetSource };
1739
3574
  //# sourceMappingURL=api-client.modern.js.map