@carto/api-client 0.4.6 → 0.4.7-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/build/api/carto-api-error.d.ts +1 -1
  3. package/build/api/query.d.ts +1 -1
  4. package/build/api/request-with-parameters.d.ts +2 -2
  5. package/build/api-client.cjs +2365 -279
  6. package/build/api-client.cjs.map +1 -1
  7. package/build/api-client.modern.js +2274 -298
  8. package/build/api-client.modern.js.map +1 -1
  9. package/build/client.d.ts +2 -2
  10. package/build/constants-internal.d.ts +5 -5
  11. package/build/constants.d.ts +25 -3
  12. package/build/deck/get-data-filter-extension-props.d.ts +28 -0
  13. package/build/deck/index.d.ts +1 -0
  14. package/build/filters/Filter.d.ts +25 -0
  15. package/build/filters/FilterTypes.d.ts +3 -0
  16. package/build/filters/geosjonFeatures.d.ts +8 -0
  17. package/build/filters/index.d.ts +6 -0
  18. package/build/filters/tileFeatures.d.ts +20 -0
  19. package/build/filters/tileFeaturesGeometries.d.ts +13 -0
  20. package/build/filters/tileFeaturesSpatialIndex.d.ts +10 -0
  21. package/build/filters.d.ts +2 -2
  22. package/build/geo.d.ts +1 -1
  23. package/build/index.d.ts +5 -0
  24. package/build/models/common.d.ts +5 -4
  25. package/build/models/index.d.ts +1 -1
  26. package/build/models/model.d.ts +2 -2
  27. package/build/operations/aggregation.d.ts +8 -0
  28. package/build/operations/applySorting.d.ts +20 -0
  29. package/build/operations/groupBy.d.ts +15 -0
  30. package/build/operations/groupByDate.d.ts +11 -0
  31. package/build/operations/histogram.d.ts +13 -0
  32. package/build/operations/index.d.ts +6 -0
  33. package/build/operations/scatterPlot.d.ts +14 -0
  34. package/build/sources/base-source.d.ts +2 -2
  35. package/build/sources/boundary-query-source.d.ts +1 -1
  36. package/build/sources/boundary-table-source.d.ts +1 -1
  37. package/build/sources/h3-query-source.d.ts +2 -2
  38. package/build/sources/h3-table-source.d.ts +2 -2
  39. package/build/sources/h3-tileset-source.d.ts +1 -1
  40. package/build/sources/index.d.ts +26 -26
  41. package/build/sources/quadbin-query-source.d.ts +2 -2
  42. package/build/sources/quadbin-table-source.d.ts +2 -2
  43. package/build/sources/quadbin-tileset-source.d.ts +1 -1
  44. package/build/sources/raster-source.d.ts +1 -1
  45. package/build/sources/types.d.ts +3 -3
  46. package/build/sources/vector-query-source.d.ts +1 -1
  47. package/build/sources/vector-table-source.d.ts +1 -1
  48. package/build/sources/vector-tileset-source.d.ts +1 -1
  49. package/build/spatial-index.d.ts +3 -3
  50. package/build/types-internal.d.ts +9 -5
  51. package/build/types.d.ts +74 -14
  52. package/build/utils/dateUtils.d.ts +10 -0
  53. package/build/utils/getTileFormat.d.ts +3 -0
  54. package/build/utils/makeIntervalComplete.d.ts +2 -0
  55. package/build/utils/transformTileCoordsToWGS84.d.ts +8 -0
  56. package/build/utils/transformToTileCoords.d.ts +9 -0
  57. package/build/utils.d.ts +3 -3
  58. package/build/widget-sources/index.d.ts +3 -1
  59. package/build/widget-sources/types.d.ts +38 -25
  60. package/build/widget-sources/widget-query-source.d.ts +4 -3
  61. package/build/widget-sources/widget-remote-source.d.ts +18 -0
  62. package/build/widget-sources/{widget-base-source.d.ts → widget-source.d.ts} +16 -41
  63. package/build/widget-sources/widget-table-source.d.ts +4 -3
  64. package/build/widget-sources/widget-tileset-source.d.ts +75 -0
  65. package/package.json +46 -29
  66. package/src/api/carto-api-error.ts +1 -1
  67. package/src/api/query.ts +5 -5
  68. package/src/api/request-with-parameters.ts +6 -6
  69. package/src/client.ts +3 -3
  70. package/src/constants-internal.ts +5 -5
  71. package/src/constants.ts +28 -3
  72. package/src/deck/get-data-filter-extension-props.ts +164 -0
  73. package/src/deck/index.ts +1 -0
  74. package/src/filters/Filter.ts +179 -0
  75. package/src/filters/FilterTypes.ts +109 -0
  76. package/src/filters/geosjonFeatures.ts +32 -0
  77. package/src/filters/index.ts +6 -0
  78. package/src/filters/tileFeatures.ts +50 -0
  79. package/src/filters/tileFeaturesGeometries.ts +444 -0
  80. package/src/filters/tileFeaturesSpatialIndex.ts +119 -0
  81. package/src/filters.ts +4 -4
  82. package/src/geo.ts +12 -14
  83. package/src/index.ts +7 -0
  84. package/src/models/common.ts +11 -9
  85. package/src/models/index.ts +1 -1
  86. package/src/models/model.ts +3 -4
  87. package/src/operations/aggregation.ts +154 -0
  88. package/src/operations/applySorting.ts +109 -0
  89. package/src/operations/groupBy.ts +59 -0
  90. package/src/operations/groupByDate.ts +98 -0
  91. package/src/operations/histogram.ts +66 -0
  92. package/src/operations/index.ts +6 -0
  93. package/src/operations/scatterPlot.ts +50 -0
  94. package/src/sources/base-source.ts +8 -8
  95. package/src/sources/boundary-query-source.ts +2 -2
  96. package/src/sources/boundary-table-source.ts +2 -2
  97. package/src/sources/h3-query-source.ts +7 -5
  98. package/src/sources/h3-table-source.ts +7 -5
  99. package/src/sources/h3-tileset-source.ts +2 -2
  100. package/src/sources/index.ts +26 -26
  101. package/src/sources/quadbin-query-source.ts +7 -5
  102. package/src/sources/quadbin-table-source.ts +7 -5
  103. package/src/sources/quadbin-tileset-source.ts +2 -2
  104. package/src/sources/raster-source.ts +3 -2
  105. package/src/sources/types.ts +3 -3
  106. package/src/sources/vector-query-source.ts +7 -5
  107. package/src/sources/vector-table-source.ts +7 -5
  108. package/src/sources/vector-tileset-source.ts +2 -2
  109. package/src/spatial-index.ts +4 -5
  110. package/src/types-internal.ts +11 -5
  111. package/src/types.ts +73 -15
  112. package/src/utils/dateUtils.ts +28 -0
  113. package/src/utils/getTileFormat.ts +9 -0
  114. package/src/utils/makeIntervalComplete.ts +17 -0
  115. package/src/utils/transformTileCoordsToWGS84.ts +77 -0
  116. package/src/utils/transformToTileCoords.ts +85 -0
  117. package/src/utils.ts +3 -3
  118. package/src/widget-sources/index.ts +3 -1
  119. package/src/widget-sources/types.ts +39 -25
  120. package/src/widget-sources/widget-query-source.ts +12 -5
  121. package/src/widget-sources/{widget-base-source.ts → widget-remote-source.ts} +51 -171
  122. package/src/widget-sources/widget-source.ts +173 -0
  123. package/src/widget-sources/widget-table-source.ts +12 -5
  124. package/src/widget-sources/widget-tileset-source.ts +456 -0
@@ -0,0 +1,179 @@
1
+ import {filterFunctions} from './FilterTypes.js';
2
+ import {Filter, FilterLogicalOperator, Filters} from '../types.js';
3
+ import {Feature} from 'geojson';
4
+ import {FilterType} from '../constants.js';
5
+ import {FeatureData} from '../types-internal.js';
6
+ import {BinaryFeature} from '@loaders.gl/schema';
7
+
8
+ const LOGICAL_OPERATOR_METHODS: Record<
9
+ FilterLogicalOperator,
10
+ 'every' | 'some'
11
+ > = {
12
+ and: 'every',
13
+ or: 'some',
14
+ };
15
+
16
+ function passesFilter(
17
+ columns: string[],
18
+ filters: Filters,
19
+ feature: FeatureData,
20
+ filtersLogicalOperator: FilterLogicalOperator
21
+ ): boolean {
22
+ const method = LOGICAL_OPERATOR_METHODS[filtersLogicalOperator];
23
+ return columns[method]((column) => {
24
+ const columnFilters = filters[column];
25
+ const columnFilterTypes = Object.keys(columnFilters) as FilterType[];
26
+
27
+ if (!feature || feature[column] === null || feature[column] === undefined) {
28
+ return false;
29
+ }
30
+
31
+ return columnFilterTypes.every((filter) => {
32
+ const filterFunction = filterFunctions[filter];
33
+
34
+ if (!filterFunction) {
35
+ throw new Error(`"${filter}" filter is not implemented.`);
36
+ }
37
+
38
+ return filterFunction(
39
+ columnFilters[filter]!.values,
40
+ feature[column],
41
+ (columnFilters[filter] as Filter[FilterType.STRING_SEARCH])!.params
42
+ );
43
+ });
44
+ });
45
+ }
46
+
47
+ /**
48
+ * @internal
49
+ * @privateRemarks Exported for use in @deck.gl/carto's getDataFilterExtensionProps.
50
+ */
51
+ export function _buildFeatureFilter({
52
+ filters = {},
53
+ type = 'boolean',
54
+ filtersLogicalOperator = 'and',
55
+ }: {
56
+ filters?: Filters;
57
+ type?: 'number' | 'boolean';
58
+ filtersLogicalOperator?: FilterLogicalOperator;
59
+ }) {
60
+ const columns = Object.keys(filters);
61
+
62
+ if (!columns.length) {
63
+ return () => (type === 'number' ? 1 : true);
64
+ }
65
+
66
+ return (feature: Feature | FeatureData) => {
67
+ const f = feature.properties || feature;
68
+ const featurePassesFilter = passesFilter(
69
+ columns,
70
+ filters,
71
+ f as FeatureData,
72
+ filtersLogicalOperator
73
+ );
74
+
75
+ return type === 'number'
76
+ ? Number(featurePassesFilter)
77
+ : featurePassesFilter;
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Apply certain filters to a collection of features.
83
+ * @internal
84
+ */
85
+ export function applyFilters(
86
+ features: FeatureData[],
87
+ filters: Filters,
88
+ filtersLogicalOperator: FilterLogicalOperator
89
+ ) {
90
+ return Object.keys(filters).length
91
+ ? features.filter(_buildFeatureFilter({filters, filtersLogicalOperator}))
92
+ : features;
93
+ }
94
+
95
+ /**
96
+ * Binary.
97
+ * @internal
98
+ */
99
+ export function buildBinaryFeatureFilter({filters = {}}: {filters: Filters}) {
100
+ const columns = Object.keys(filters);
101
+
102
+ if (!columns.length) {
103
+ return () => 1;
104
+ }
105
+
106
+ return (featureIdIdx: number, binaryData: BinaryFeature) =>
107
+ passesFilterUsingBinary(columns, filters, featureIdIdx, binaryData);
108
+ }
109
+
110
+ function getValueFromNumericProps(
111
+ featureIdIdx: number,
112
+ binaryData: BinaryFeature,
113
+ {column}: {column: string}
114
+ ) {
115
+ return binaryData.numericProps?.[column]?.value[featureIdIdx];
116
+ }
117
+
118
+ function getValueFromProperties(
119
+ featureIdIdx: number,
120
+ binaryData: BinaryFeature,
121
+ {column}: {column: string}
122
+ ) {
123
+ const propertyIdx = binaryData.featureIds.value[featureIdIdx];
124
+ return (binaryData.properties[propertyIdx] as Record<string, unknown>)?.[
125
+ column
126
+ ];
127
+ }
128
+
129
+ const GET_VALUE_BY_BINARY_PROP = {
130
+ properties: getValueFromProperties,
131
+ numericProps: getValueFromNumericProps,
132
+ };
133
+
134
+ function getBinaryPropertyByFilterValues(filterValues: unknown[]) {
135
+ return typeof filterValues.flat()[0] === 'string'
136
+ ? 'properties'
137
+ : 'numericProps';
138
+ }
139
+
140
+ function getFeatureValue(
141
+ featureIdIdx: number,
142
+ binaryData: any,
143
+ filter: {type: FilterType; column: string; values: unknown[]}
144
+ ) {
145
+ const {column, values} = filter;
146
+ const binaryProp = getBinaryPropertyByFilterValues(values);
147
+ const getFeatureValueFn = GET_VALUE_BY_BINARY_PROP[binaryProp];
148
+ return getFeatureValueFn(featureIdIdx, binaryData, {column});
149
+ }
150
+
151
+ function passesFilterUsingBinary(
152
+ columns: string[],
153
+ filters: Filters,
154
+ featureIdIdx: number,
155
+ binaryData: BinaryFeature
156
+ ) {
157
+ return columns.every((column) => {
158
+ const columnFilters = filters[column];
159
+
160
+ return Object.entries(columnFilters).every(([type, {values}]) => {
161
+ const filterFn = filterFunctions[type as FilterType];
162
+ if (!filterFn) {
163
+ throw new Error(`"${type}" filter is not implemented.`);
164
+ }
165
+
166
+ if (!values) return 0;
167
+
168
+ const featureValue = getFeatureValue(featureIdIdx, binaryData, {
169
+ type: type as FilterType,
170
+ column,
171
+ values,
172
+ });
173
+
174
+ if (featureValue === undefined || featureValue === null) return 0;
175
+
176
+ return filterFn(values, featureValue);
177
+ });
178
+ });
179
+ }
@@ -0,0 +1,109 @@
1
+ import {FilterType} from '../constants.js';
2
+ import {FilterInterval, StringSearchOptions} from '../types.js';
3
+ import {makeIntervalComplete} from '../utils/makeIntervalComplete.js';
4
+
5
+ export type FilterFunction = (
6
+ filterValues: unknown[],
7
+ featureValue: unknown,
8
+ params?: Record<string, unknown>
9
+ ) => boolean;
10
+
11
+ export const filterFunctions: Record<FilterType, FilterFunction> = {
12
+ [FilterType.IN]: filterIn,
13
+ [FilterType.BETWEEN]: filterBetween,
14
+ [FilterType.TIME]: filterTime,
15
+ [FilterType.CLOSED_OPEN]: filterClosedOpen,
16
+ [FilterType.STRING_SEARCH]: filterStringSearch,
17
+ };
18
+
19
+ function filterIn(filterValues: unknown[], featureValue: unknown): boolean {
20
+ return filterValues.includes(featureValue);
21
+ }
22
+
23
+ // FilterTypes.BETWEEN
24
+ function filterBetween(
25
+ filterValues: unknown[],
26
+ featureValue: unknown
27
+ ): boolean {
28
+ const checkRange = (range: [number, number]) => {
29
+ const [lowerBound, upperBound] = range;
30
+ return (
31
+ (featureValue as number) >= lowerBound &&
32
+ (featureValue as number) <= upperBound
33
+ );
34
+ };
35
+
36
+ return makeIntervalComplete(filterValues as FilterInterval[]).some(
37
+ checkRange
38
+ );
39
+ }
40
+
41
+ function filterTime(filterValues: unknown[], featureValue: unknown) {
42
+ const featureValueAsTimestamp = new Date(featureValue as number).getTime();
43
+ if (isFinite(featureValueAsTimestamp)) {
44
+ return filterBetween(filterValues, featureValueAsTimestamp);
45
+ } else {
46
+ throw new Error(`Column used to filter by time isn't well formatted.`);
47
+ }
48
+ }
49
+
50
+ // FilterTypes.CLOSED_OPEN
51
+ function filterClosedOpen(
52
+ filterValues: unknown[],
53
+ featureValue: unknown
54
+ ): boolean {
55
+ const checkRange = (range: [number, number]) => {
56
+ const [lowerBound, upperBound] = range;
57
+ return (
58
+ (featureValue as number) >= lowerBound &&
59
+ (featureValue as number) < upperBound
60
+ );
61
+ };
62
+
63
+ return makeIntervalComplete(filterValues as [number, number][]).some(
64
+ checkRange
65
+ );
66
+ }
67
+
68
+ // FilterTypes.STRING_SEARCH
69
+ function filterStringSearch(
70
+ filterValues: unknown[],
71
+ featureValue: unknown,
72
+ params: StringSearchOptions = {}
73
+ ): boolean {
74
+ const normalizedFeatureValue = normalize(featureValue, params);
75
+ const stringRegExp = params.useRegExp
76
+ ? filterValues
77
+ : filterValues.map((filterValue) => {
78
+ let stringRegExp = escapeRegExp(normalize(filterValue, params));
79
+
80
+ if (params.mustStart) stringRegExp = `^${stringRegExp}`;
81
+ if (params.mustEnd) stringRegExp = `${stringRegExp}$`;
82
+
83
+ return stringRegExp;
84
+ });
85
+
86
+ const regex = new RegExp(
87
+ stringRegExp.join('|'),
88
+ params.caseSensitive ? 'g' : 'gi'
89
+ );
90
+ return !!normalizedFeatureValue.match(regex);
91
+ }
92
+
93
+ // Aux
94
+ const specialCharRegExp = /[.*+?^${}()|[\]\\]/g;
95
+ const normalizeRegExp = /\p{Diacritic}/gu;
96
+
97
+ function escapeRegExp(value: string) {
98
+ return value.replace(specialCharRegExp, '\\$&');
99
+ }
100
+
101
+ function normalize(data: unknown, params: StringSearchOptions) {
102
+ let normalizedData = String(data);
103
+ if (!params.keepSpecialCharacters)
104
+ normalizedData = normalizedData
105
+ .normalize('NFD')
106
+ .replace(normalizeRegExp, '');
107
+
108
+ return normalizedData;
109
+ }
@@ -0,0 +1,32 @@
1
+ import intersects from '@turf/boolean-intersects';
2
+ import {FeatureCollection} from 'geojson';
3
+ import {FeatureData} from '../types-internal.js';
4
+ import {SpatialFilter} from '../types.js';
5
+
6
+ export function geojsonFeatures({
7
+ geojson,
8
+ spatialFilter,
9
+ uniqueIdProperty,
10
+ }: {
11
+ geojson: FeatureCollection;
12
+ spatialFilter: SpatialFilter;
13
+ uniqueIdProperty?: string;
14
+ }): FeatureData[] {
15
+ let uniqueIdx = 0;
16
+ const map = new Map();
17
+
18
+ if (!spatialFilter) {
19
+ return [];
20
+ }
21
+
22
+ for (const feature of geojson.features) {
23
+ const uniqueId = uniqueIdProperty
24
+ ? feature.properties![uniqueIdProperty]
25
+ : ++uniqueIdx;
26
+ if (!map.has(uniqueId) && intersects(spatialFilter, feature)) {
27
+ map.set(uniqueId, feature.properties);
28
+ }
29
+ }
30
+
31
+ return Array.from(map.values());
32
+ }
@@ -0,0 +1,6 @@
1
+ export * from './Filter.js';
2
+ export * from './FilterTypes.js';
3
+ export * from './geosjonFeatures.js';
4
+ export * from './tileFeatures.js';
5
+ export * from './tileFeaturesGeometries.js';
6
+ export * from './tileFeaturesSpatialIndex.js';
@@ -0,0 +1,50 @@
1
+ import {SpatialFilter, SpatialIndexTile, Tile} from '../types.js';
2
+ import {tileFeaturesGeometries} from './tileFeaturesGeometries.js';
3
+ import {tileFeaturesSpatialIndex} from './tileFeaturesSpatialIndex.js';
4
+ import {TileFormat} from '../constants.js';
5
+ import {DEFAULT_GEO_COLUMN} from '../constants-internal.js';
6
+ import {FeatureData} from '../types-internal.js';
7
+ import {SpatialDataType} from '../sources/types.js';
8
+
9
+ /** @privateRemarks Source: @carto/react-core */
10
+ export type TileFeatures = {
11
+ tiles: Tile[];
12
+ tileFormat: TileFormat;
13
+ spatialDataType: SpatialDataType;
14
+ spatialDataColumn?: string;
15
+ spatialFilter: SpatialFilter;
16
+ uniqueIdProperty?: string;
17
+ options?: TileFeatureExtractOptions;
18
+ };
19
+
20
+ /** @privateRemarks Source: @carto/react-core */
21
+ export type TileFeatureExtractOptions = {
22
+ storeGeometry?: boolean;
23
+ };
24
+
25
+ /** @privateRemarks Source: @carto/react-core */
26
+ export function tileFeatures({
27
+ tiles,
28
+ spatialFilter,
29
+ uniqueIdProperty,
30
+ tileFormat,
31
+ spatialDataColumn = DEFAULT_GEO_COLUMN,
32
+ spatialDataType,
33
+ options = {},
34
+ }: TileFeatures): FeatureData[] {
35
+ if (spatialDataType !== 'geo') {
36
+ return tileFeaturesSpatialIndex({
37
+ tiles: tiles as SpatialIndexTile[],
38
+ spatialFilter,
39
+ spatialDataColumn,
40
+ spatialDataType,
41
+ });
42
+ }
43
+ return tileFeaturesGeometries({
44
+ tiles,
45
+ tileFormat,
46
+ spatialFilter,
47
+ uniqueIdProperty,
48
+ options,
49
+ });
50
+ }