@carto/api-client 0.4.2-alpha.0 → 0.4.2

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.
package/CHANGELOG.md CHANGED
@@ -4,9 +4,13 @@
4
4
 
5
5
  ## 0.4
6
6
 
7
+ ### 0.4.2
8
+
9
+ - fix: Fix incorrect column name lowercasing in Picking Model API
10
+
7
11
  ### 0.4.1
8
12
 
9
- - add cache control mechanism for sources and query APIs
13
+ - feat: Add cache control mechanism for sources and query APIs
10
14
 
11
15
  ### 0.4.0
12
16
 
@@ -1,3 +1,3 @@
1
1
  import type { SourceOptions, QuerySourceOptions, QueryResult } from '../sources/types';
2
- export type QueryOptions = SourceOptions & QuerySourceOptions;
2
+ export type QueryOptions = SourceOptions & Omit<QuerySourceOptions, 'spatialDataColumn'>;
3
3
  export declare const query: (options: QueryOptions) => Promise<QueryResult>;
@@ -509,43 +509,41 @@ function executeModel(props) {
509
509
  data,
510
510
  filters,
511
511
  filtersLogicalOperator = 'and',
512
- spatialDataType = 'geo',
513
- spatialFiltersMode = 'intersects',
514
- spatialFiltersResolution = 0
512
+ geoColumn = DEFAULT_GEO_COLUMN
515
513
  } = source;
514
+ const queryParameters = source.queryParameters ? JSON.stringify(source.queryParameters) : '';
516
515
  const queryParams = {
517
516
  type,
518
517
  client: clientId,
519
518
  source: data,
520
- params,
521
- queryParameters: source.queryParameters || '',
522
- filters,
519
+ params: JSON.stringify(params),
520
+ queryParameters,
521
+ filters: JSON.stringify(filters),
523
522
  filtersLogicalOperator
524
523
  };
525
- const spatialDataColumn = source.spatialDataColumn || DEFAULT_GEO_COLUMN;
526
524
  // Picking Model API requires 'spatialDataColumn'.
527
525
  if (model === 'pick') {
528
- queryParams.spatialDataColumn = spatialDataColumn;
526
+ queryParams.spatialDataColumn = geoColumn;
529
527
  }
530
- // API supports multiple filters, we apply it only to spatialDataColumn
528
+ // API supports multiple filters, we apply it only to geoColumn
531
529
  const spatialFilters = source.spatialFilter ? {
532
- [spatialDataColumn]: source.spatialFilter
530
+ [geoColumn]: source.spatialFilter
533
531
  } : undefined;
534
532
  if (spatialFilters) {
535
- queryParams.spatialFilters = spatialFilters; // JSON.stringify(spatialFilters);
536
- queryParams.spatialDataColumn = spatialDataColumn;
537
- queryParams.spatialDataType = spatialDataType;
538
- }
539
- if (spatialDataType !== 'geo') {
540
- if (spatialFiltersResolution > 0) {
541
- queryParams.spatialFiltersResolution = spatialFiltersResolution;
542
- }
543
- queryParams.spatialFiltersMode = spatialFiltersMode;
533
+ queryParams.spatialFilters = JSON.stringify(spatialFilters);
544
534
  }
545
- const urlWithSearchParams = url + '?' + objectToURLSearchParams(queryParams).toString();
535
+ const urlWithSearchParams = url + '?' + new URLSearchParams(queryParams).toString();
546
536
  const isGet = urlWithSearchParams.length <= REQUEST_GET_MAX_URL_LENGTH;
547
537
  if (isGet) {
548
538
  url = urlWithSearchParams;
539
+ } else {
540
+ // undo the JSON.stringify, @TODO find a better pattern
541
+ queryParams.params = params;
542
+ queryParams.filters = filters;
543
+ queryParams.queryParameters = source.queryParameters;
544
+ if (spatialFilters) {
545
+ queryParams.spatialFilters = spatialFilters;
546
+ }
549
547
  }
550
548
  return makeCall({
551
549
  url,
@@ -559,68 +557,6 @@ function executeModel(props) {
559
557
  }
560
558
  });
561
559
  }
562
- function objectToURLSearchParams(object) {
563
- const params = new URLSearchParams();
564
- for (const key in object) {
565
- if (isPureObject(object[key])) {
566
- params.append(key, JSON.stringify(object[key]));
567
- } else if (Array.isArray(object[key])) {
568
- params.append(key, JSON.stringify(object[key]));
569
- } else if (object[key] === null) {
570
- params.append(key, 'null');
571
- } else if (object[key] !== undefined) {
572
- params.append(key, String(object[key]));
573
- }
574
- }
575
- return params;
576
- }
577
-
578
- const DEFAULT_TILE_SIZE = 512;
579
- const QUADBIN_ZOOM_MAX_OFFSET = 4;
580
- function getSpatialFiltersResolution(_ref) {
581
- let {
582
- source,
583
- viewState
584
- } = _ref;
585
- assert(viewState, 'viewState prop is required to compute automatic spatialFiltersResolution when using spatialFilter with spatial indexes. Either pass a `spatialFiltersResolution` prop or a `viewState` prop to avoid this error');
586
- const dataResolution = source.dataResolution ?? Number.MAX_VALUE;
587
- const aggregationResLevel = source.aggregationResLevel ?? (source.spatialDataType === 'h3' ? DEFAULT_AGGREGATION_RES_LEVEL_H3 : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN);
588
- const aggregationResLevelOffset = Math.max(0, Math.floor(aggregationResLevel));
589
- const currentZoomInt = Math.ceil(viewState.zoom);
590
- if (source.spatialDataType === 'h3') {
591
- const tileSize = DEFAULT_TILE_SIZE;
592
- const maxResolutionForZoom = maxH3SpatialFiltersResolutions.find(_ref2 => {
593
- let [zoom] = _ref2;
594
- return zoom === currentZoomInt;
595
- })?.[1] ?? Math.max(0, currentZoomInt - 3);
596
- const maxSpatialFiltersResolution = maxResolutionForZoom ? Math.min(dataResolution, maxResolutionForZoom) : dataResolution;
597
- const hexagonResolution = getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
598
- return Math.min(hexagonResolution, maxSpatialFiltersResolution);
599
- }
600
- if (source.spatialDataType === 'quadbin') {
601
- const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
602
- const maxSpatialFiltersResolution = Math.min(dataResolution, maxResolutionForZoom);
603
- const quadsResolution = Math.floor(viewState.zoom) + aggregationResLevelOffset;
604
- return Math.min(quadsResolution, maxSpatialFiltersResolution);
605
- }
606
- return undefined;
607
- }
608
- 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]];
609
- // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
610
- // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
611
- const BIAS = 2;
612
- // Resolution conversion function. Takes a WebMercatorViewport and returns
613
- // a H3 resolution such that the screen space size of the hexagons is
614
- // similar
615
- function getHexagonResolution(viewport, tileSize) {
616
- // Difference in given tile size compared to deck's internal 512px tile size,
617
- // expressed as an offset to the viewport zoom.
618
- const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
619
- const hexagonScaleFactor = 2 / 3 * (viewport.zoom - zoomOffset);
620
- const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
621
- // Clip and bias
622
- return Math.max(0, Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS));
623
- }
624
560
 
625
561
  /**
626
562
  * Source for Widget API requests on a data source defined by a SQL query.
@@ -645,9 +581,7 @@ class WidgetBaseSource {
645
581
  connectionName: props.connectionName,
646
582
  filters: getApplicableFilters(owner, props.filters),
647
583
  filtersLogicalOperator: props.filtersLogicalOperator,
648
- spatialDataType: props.spatialDataType,
649
- spatialDataColumn: props.spatialDataColumn,
650
- dataResolution: props.dataResolution
584
+ geoColumn: props.geoColumn
651
585
  };
652
586
  }
653
587
  /****************************************************************************
@@ -663,9 +597,7 @@ class WidgetBaseSource {
663
597
  const {
664
598
  filterOwner,
665
599
  spatialFilter,
666
- spatialFiltersMode,
667
600
  abortController,
668
- viewState,
669
601
  ...params
670
602
  } = options;
671
603
  const {
@@ -673,20 +605,10 @@ class WidgetBaseSource {
673
605
  operation,
674
606
  operationColumn
675
607
  } = params;
676
- const source = _this.getModelSource(filterOwner);
677
- let spatialFiltersResolution;
678
- if (spatialFilter && source.spatialDataType !== 'geo') {
679
- spatialFiltersResolution = getSpatialFiltersResolution({
680
- source,
681
- viewState
682
- });
683
- }
684
608
  return Promise.resolve(executeModel({
685
609
  model: 'category',
686
610
  source: {
687
- ...source,
688
- spatialFiltersResolution,
689
- spatialFiltersMode,
611
+ ..._this.getModelSource(filterOwner),
690
612
  spatialFilter
691
613
  },
692
614
  params: {
@@ -719,9 +641,7 @@ class WidgetBaseSource {
719
641
  const {
720
642
  filterOwner,
721
643
  spatialFilter,
722
- spatialFiltersMode,
723
644
  abortController,
724
- viewState,
725
645
  ...params
726
646
  } = options;
727
647
  const {
@@ -732,20 +652,10 @@ class WidgetBaseSource {
732
652
  limit,
733
653
  tileResolution
734
654
  } = params;
735
- const source = _this2.getModelSource(filterOwner);
736
- let spatialFiltersResolution;
737
- if (spatialFilter && source.spatialDataType !== 'geo') {
738
- spatialFiltersResolution = getSpatialFiltersResolution({
739
- source,
740
- viewState
741
- });
742
- }
743
655
  return Promise.resolve(executeModel({
744
656
  model: 'pick',
745
657
  source: {
746
- ...source,
747
- spatialFiltersResolution,
748
- spatialFiltersMode,
658
+ ..._this2.getModelSource(filterOwner),
749
659
  spatialFilter
750
660
  },
751
661
  params: {
@@ -759,9 +669,15 @@ class WidgetBaseSource {
759
669
  opts: {
760
670
  abortController
761
671
  }
762
- }).then(res => ({
763
- rows: normalizeObjectKeys(res.rows)
764
- })));
672
+ // Avoid `normalizeObjectKeys()`, which changes column names.
673
+ }).then(_ref => {
674
+ let {
675
+ rows
676
+ } = _ref;
677
+ return {
678
+ rows
679
+ };
680
+ }));
765
681
  } catch (e) {
766
682
  return Promise.reject(e);
767
683
  }
@@ -779,30 +695,18 @@ class WidgetBaseSource {
779
695
  const {
780
696
  filterOwner,
781
697
  spatialFilter,
782
- spatialFiltersMode,
783
698
  abortController,
784
699
  operationExp,
785
- viewState,
786
700
  ...params
787
701
  } = options;
788
702
  const {
789
703
  column,
790
704
  operation
791
705
  } = params;
792
- const source = _this3.getModelSource(filterOwner);
793
- let spatialFiltersResolution;
794
- if (spatialFilter && source.spatialDataType !== 'geo') {
795
- spatialFiltersResolution = getSpatialFiltersResolution({
796
- source,
797
- viewState
798
- });
799
- }
800
706
  return Promise.resolve(executeModel({
801
707
  model: 'formula',
802
708
  source: {
803
- ...source,
804
- spatialFiltersResolution,
805
- spatialFiltersMode,
709
+ ..._this3.getModelSource(filterOwner),
806
710
  spatialFilter
807
711
  },
808
712
  params: {
@@ -831,9 +735,7 @@ class WidgetBaseSource {
831
735
  const {
832
736
  filterOwner,
833
737
  spatialFilter,
834
- spatialFiltersMode,
835
738
  abortController,
836
- viewState,
837
739
  ...params
838
740
  } = options;
839
741
  const {
@@ -841,20 +743,10 @@ class WidgetBaseSource {
841
743
  operation,
842
744
  ticks
843
745
  } = params;
844
- const source = _this4.getModelSource(filterOwner);
845
- let spatialFiltersResolution;
846
- if (spatialFilter && source.spatialDataType !== 'geo') {
847
- spatialFiltersResolution = getSpatialFiltersResolution({
848
- source,
849
- viewState
850
- });
851
- }
852
746
  return Promise.resolve(executeModel({
853
747
  model: 'histogram',
854
748
  source: {
855
- ...source,
856
- spatialFiltersResolution,
857
- spatialFiltersMode,
749
+ ..._this4.getModelSource(filterOwner),
858
750
  spatialFilter
859
751
  },
860
752
  params: {
@@ -870,11 +762,11 @@ class WidgetBaseSource {
870
762
  // Given N ticks the API returns up to N+1 bins, omitting any empty bins. Bins
871
763
  // include 1 bin below the lowest tick, N-1 between ticks, and 1 bin above the highest tick.
872
764
  const result = Array(ticks.length + 1).fill(0);
873
- data.forEach(_ref => {
765
+ data.forEach(_ref2 => {
874
766
  let {
875
767
  tick,
876
768
  value
877
- } = _ref;
769
+ } = _ref2;
878
770
  return result[tick] = value;
879
771
  });
880
772
  return result;
@@ -899,28 +791,16 @@ class WidgetBaseSource {
899
791
  const {
900
792
  filterOwner,
901
793
  spatialFilter,
902
- spatialFiltersMode,
903
794
  abortController,
904
- viewState,
905
795
  ...params
906
796
  } = options;
907
797
  const {
908
798
  column
909
799
  } = params;
910
- const source = _this5.getModelSource(filterOwner);
911
- let spatialFiltersResolution;
912
- if (spatialFilter && source.spatialDataType !== 'geo') {
913
- spatialFiltersResolution = getSpatialFiltersResolution({
914
- source,
915
- viewState
916
- });
917
- }
918
800
  return Promise.resolve(executeModel({
919
801
  model: 'range',
920
802
  source: {
921
- ...source,
922
- spatialFiltersResolution,
923
- spatialFiltersMode,
803
+ ..._this5.getModelSource(filterOwner),
924
804
  spatialFilter
925
805
  },
926
806
  params: {
@@ -947,9 +827,7 @@ class WidgetBaseSource {
947
827
  const {
948
828
  filterOwner,
949
829
  spatialFilter,
950
- spatialFiltersMode,
951
830
  abortController,
952
- viewState,
953
831
  ...params
954
832
  } = options;
955
833
  const {
@@ -958,22 +836,12 @@ class WidgetBaseSource {
958
836
  yAxisColumn,
959
837
  yAxisJoinOperation
960
838
  } = params;
961
- const source = _this6.getModelSource(filterOwner);
962
- let spatialFiltersResolution;
963
- if (spatialFilter && source.spatialDataType !== 'geo') {
964
- spatialFiltersResolution = getSpatialFiltersResolution({
965
- source,
966
- viewState
967
- });
968
- }
969
839
  // Make sure this is sync with the same constant in cloud-native/maps-api
970
840
  const HARD_LIMIT = 500;
971
841
  return Promise.resolve(executeModel({
972
842
  model: 'scatterplot',
973
843
  source: {
974
- ...source,
975
- spatialFiltersResolution,
976
- spatialFiltersMode,
844
+ ..._this6.getModelSource(filterOwner),
977
845
  spatialFilter
978
846
  },
979
847
  params: {
@@ -986,11 +854,11 @@ class WidgetBaseSource {
986
854
  opts: {
987
855
  abortController
988
856
  }
989
- }).then(res => normalizeObjectKeys(res.rows)).then(res => res.map(_ref2 => {
857
+ }).then(res => normalizeObjectKeys(res.rows)).then(res => res.map(_ref3 => {
990
858
  let {
991
859
  x,
992
860
  y
993
- } = _ref2;
861
+ } = _ref3;
994
862
  return [x, y];
995
863
  })));
996
864
  } catch (e) {
@@ -1010,9 +878,7 @@ class WidgetBaseSource {
1010
878
  const {
1011
879
  filterOwner,
1012
880
  spatialFilter,
1013
- spatialFiltersMode,
1014
881
  abortController,
1015
- viewState,
1016
882
  ...params
1017
883
  } = options;
1018
884
  const {
@@ -1022,20 +888,10 @@ class WidgetBaseSource {
1022
888
  offset = 0,
1023
889
  limit = 10
1024
890
  } = params;
1025
- const source = _this7.getModelSource(filterOwner);
1026
- let spatialFiltersResolution;
1027
- if (spatialFilter && source.spatialDataType !== 'geo') {
1028
- spatialFiltersResolution = getSpatialFiltersResolution({
1029
- source,
1030
- viewState
1031
- });
1032
- }
1033
891
  return Promise.resolve(executeModel({
1034
892
  model: 'table',
1035
893
  source: {
1036
- ...source,
1037
- spatialFiltersResolution,
1038
- spatialFiltersMode,
894
+ ..._this7.getModelSource(filterOwner),
1039
895
  spatialFilter
1040
896
  },
1041
897
  params: {
@@ -1071,8 +927,6 @@ class WidgetBaseSource {
1071
927
  filterOwner,
1072
928
  abortController,
1073
929
  spatialFilter,
1074
- spatialFiltersMode,
1075
- viewState,
1076
930
  ...params
1077
931
  } = options;
1078
932
  const {
@@ -1086,20 +940,10 @@ class WidgetBaseSource {
1086
940
  splitByCategoryLimit,
1087
941
  splitByCategoryValues
1088
942
  } = params;
1089
- const source = _this8.getModelSource(filterOwner);
1090
- let spatialFiltersResolution;
1091
- if (spatialFilter && source.spatialDataType !== 'geo') {
1092
- spatialFiltersResolution = getSpatialFiltersResolution({
1093
- source,
1094
- viewState
1095
- });
1096
- }
1097
943
  return Promise.resolve(executeModel({
1098
944
  model: 'timeseries',
1099
945
  source: {
1100
- ...source,
1101
- spatialFiltersResolution,
1102
- spatialFiltersMode,
946
+ ..._this8.getModelSource(filterOwner),
1103
947
  spatialFilter
1104
948
  },
1105
949
  params: {
@@ -1130,7 +974,8 @@ WidgetBaseSource.defaultProps = {
1130
974
  apiBaseUrl: DEFAULT_API_BASE_URL,
1131
975
  clientId: getClient(),
1132
976
  filters: {},
1133
- filtersLogicalOperator: 'and'
977
+ filtersLogicalOperator: 'and',
978
+ geoColumn: DEFAULT_GEO_COLUMN
1134
979
  };
1135
980
 
1136
981
  /**
@@ -1610,12 +1455,7 @@ const h3QuerySource = function (options) {
1610
1455
  }
1611
1456
  return Promise.resolve(baseSource('query', options, urlParameters).then(result => ({
1612
1457
  ...result,
1613
- widgetSource: new WidgetQuerySource({
1614
- ...options,
1615
- // NOTE: passing redundant spatialDataColumn here to apply the default value 'h3'
1616
- spatialDataColumn,
1617
- spatialDataType: 'h3'
1618
- })
1458
+ widgetSource: new WidgetQuerySource(options)
1619
1459
  })));
1620
1460
  } catch (e) {
1621
1461
  return Promise.reject(e);
@@ -1646,12 +1486,7 @@ const h3TableSource = function (options) {
1646
1486
  }
1647
1487
  return Promise.resolve(baseSource('table', options, urlParameters).then(result => ({
1648
1488
  ...result,
1649
- widgetSource: new WidgetTableSource({
1650
- ...options,
1651
- // NOTE: passing redundant spatialDataColumn here to apply the default value 'h3'
1652
- spatialDataColumn,
1653
- spatialDataType: 'h3'
1654
- })
1489
+ widgetSource: new WidgetTableSource(options)
1655
1490
  })));
1656
1491
  } catch (e) {
1657
1492
  return Promise.reject(e);
@@ -1720,12 +1555,7 @@ const quadbinQuerySource = function (options) {
1720
1555
  }
1721
1556
  return Promise.resolve(baseSource('query', options, urlParameters).then(result => ({
1722
1557
  ...result,
1723
- widgetSource: new WidgetQuerySource({
1724
- ...options,
1725
- // NOTE: passing redundant spatialDataColumn here to apply the default value 'quadbin'
1726
- spatialDataColumn,
1727
- spatialDataType: 'quadbin'
1728
- })
1558
+ widgetSource: new WidgetQuerySource(options)
1729
1559
  })));
1730
1560
  } catch (e) {
1731
1561
  return Promise.reject(e);
@@ -1756,12 +1586,7 @@ const quadbinTableSource = function (options) {
1756
1586
  }
1757
1587
  return Promise.resolve(baseSource('table', options, urlParameters).then(result => ({
1758
1588
  ...result,
1759
- widgetSource: new WidgetTableSource({
1760
- ...options,
1761
- // NOTE: passing redundant spatialDataColumn here to apply the default value 'quadbin'
1762
- spatialDataColumn,
1763
- spatialDataType: 'quadbin'
1764
- })
1589
+ widgetSource: new WidgetTableSource(options)
1765
1590
  })));
1766
1591
  } catch (e) {
1767
1592
  return Promise.reject(e);
@@ -1811,10 +1636,7 @@ const vectorQuerySource = function (options) {
1811
1636
  }
1812
1637
  return Promise.resolve(baseSource('query', options, urlParameters).then(result => ({
1813
1638
  ...result,
1814
- widgetSource: new WidgetQuerySource({
1815
- ...options,
1816
- spatialDataType: 'geo'
1817
- })
1639
+ widgetSource: new WidgetQuerySource(options)
1818
1640
  })));
1819
1641
  } catch (e) {
1820
1642
  return Promise.reject(e);
@@ -1845,10 +1667,7 @@ const vectorTableSource = function (options) {
1845
1667
  }
1846
1668
  return Promise.resolve(baseSource('table', options, urlParameters).then(result => ({
1847
1669
  ...result,
1848
- widgetSource: new WidgetTableSource({
1849
- ...options,
1850
- spatialDataType: 'geo'
1851
- })
1670
+ widgetSource: new WidgetTableSource(options)
1852
1671
  })));
1853
1672
  } catch (e) {
1854
1673
  return Promise.reject(e);