@carto/api-client 0.5.0-alpha.3 → 0.5.0-alpha.5
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 +4 -0
- package/build/api-client.cjs +3332 -3100
- package/build/api-client.d.cts +1373 -0
- package/build/api-client.d.ts +1373 -0
- package/build/api-client.js +1712 -0
- package/build/chunk-V3E7BKVR.js +2063 -0
- package/build/worker.d.ts +2 -0
- package/build/worker.js +25 -0
- package/package.json +51 -45
- package/src/api/carto-api-error.ts +1 -1
- package/src/api/query.ts +5 -5
- package/src/api/request-with-parameters.ts +6 -6
- package/src/client.ts +3 -3
- package/src/constants-internal.ts +5 -11
- package/src/constants.ts +6 -6
- package/src/deck/get-data-filter-extension-props.ts +146 -0
- package/src/deck/index.ts +1 -0
- package/src/filters/Filter.ts +18 -8
- package/src/filters/FilterTypes.ts +2 -2
- package/src/filters/geosjonFeatures.ts +2 -2
- package/src/filters/tileFeatures.ts +19 -41
- package/src/filters.ts +4 -4
- package/src/geo.ts +12 -14
- package/src/global.d.ts +3 -8
- package/src/index.ts +1 -0
- package/src/models/common.ts +9 -7
- package/src/models/model.ts +3 -4
- package/src/operations/aggregation.ts +5 -5
- package/src/operations/applySorting.ts +4 -4
- package/src/operations/groupBy.ts +4 -4
- package/src/operations/groupByDate.ts +1 -1
- package/src/operations/histogram.ts +4 -4
- package/src/operations/scatterPlot.ts +4 -4
- package/src/sources/base-source.ts +8 -8
- package/src/sources/boundary-query-source.ts +2 -2
- package/src/sources/boundary-table-source.ts +2 -2
- package/src/sources/h3-query-source.ts +7 -5
- package/src/sources/h3-table-source.ts +7 -5
- package/src/sources/h3-tileset-source.ts +12 -5
- package/src/sources/index.ts +26 -26
- package/src/sources/quadbin-query-source.ts +7 -5
- package/src/sources/quadbin-table-source.ts +7 -5
- package/src/sources/quadbin-tileset-source.ts +12 -5
- package/src/sources/raster-source.ts +7 -16
- package/src/sources/types.ts +10 -4
- package/src/sources/vector-query-source.ts +2 -3
- package/src/sources/vector-table-source.ts +2 -3
- package/src/sources/vector-tileset-source.ts +13 -6
- package/src/spatial-index.ts +4 -4
- package/src/types-internal.ts +5 -5
- package/src/types.ts +15 -21
- package/src/utils/makeIntervalComplete.ts +1 -1
- package/src/utils.ts +3 -3
- package/src/widget-sources/index.ts +1 -1
- package/src/widget-sources/types.ts +5 -3
- package/src/widget-sources/widget-query-source.ts +6 -2
- package/src/widget-sources/widget-remote-source.ts +66 -18
- package/src/widget-sources/widget-source.ts +0 -28
- package/src/widget-sources/widget-table-source.ts +6 -2
- package/src/widget-sources/widget-tileset-source.ts +130 -90
- package/src/widget-sources/widget-tileset-worker-source.ts +238 -0
- package/src/workers/constants.ts +13 -0
- package/src/workers/types.ts +20 -0
- package/src/workers/utils.ts +33 -0
- package/src/workers/widget-tileset-worker.ts +36 -0
- package/build/api/carto-api-error.d.ts +0 -26
- package/build/api/endpoints.d.ts +0 -24
- package/build/api/index.d.ts +0 -5
- package/build/api/query.d.ts +0 -3
- package/build/api/request-with-parameters.d.ts +0 -10
- package/build/api-client.cjs.map +0 -1
- package/build/api-client.modern.js +0 -3304
- package/build/api-client.modern.js.map +0 -1
- package/build/client.d.ts +0 -14
- package/build/constants-internal.d.ts +0 -26
- package/build/constants.d.ts +0 -53
- package/build/filters/Filter.d.ts +0 -13
- package/build/filters/FilterTypes.d.ts +0 -3
- package/build/filters/geosjonFeatures.d.ts +0 -8
- package/build/filters/index.d.ts +0 -6
- package/build/filters/tileFeatures.d.ts +0 -21
- package/build/filters/tileFeaturesGeometries.d.ts +0 -13
- package/build/filters/tileFeaturesRaster.d.ts +0 -16
- package/build/filters/tileFeaturesSpatialIndex.d.ts +0 -10
- package/build/filters.d.ts +0 -39
- package/build/geo.d.ts +0 -19
- package/build/index.d.ts +0 -15
- package/build/models/common.d.ts +0 -27
- package/build/models/index.d.ts +0 -3
- package/build/models/model.d.ts +0 -37
- package/build/operations/aggregation.d.ts +0 -8
- package/build/operations/applySorting.d.ts +0 -20
- package/build/operations/groupBy.d.ts +0 -15
- package/build/operations/groupByDate.d.ts +0 -11
- package/build/operations/histogram.d.ts +0 -13
- package/build/operations/index.d.ts +0 -6
- package/build/operations/scatterPlot.d.ts +0 -14
- package/build/sources/base-source.d.ts +0 -4
- package/build/sources/boundary-query-source.d.ts +0 -10
- package/build/sources/boundary-table-source.d.ts +0 -8
- package/build/sources/h3-query-source.d.ts +0 -5
- package/build/sources/h3-table-source.d.ts +0 -5
- package/build/sources/h3-tileset-source.d.ts +0 -5
- package/build/sources/index.d.ts +0 -26
- package/build/sources/quadbin-query-source.d.ts +0 -5
- package/build/sources/quadbin-table-source.d.ts +0 -5
- package/build/sources/quadbin-tileset-source.d.ts +0 -5
- package/build/sources/raster-source.d.ts +0 -5
- package/build/sources/types.d.ts +0 -366
- package/build/sources/vector-query-source.d.ts +0 -5
- package/build/sources/vector-table-source.d.ts +0 -5
- package/build/sources/vector-tileset-source.d.ts +0 -5
- package/build/spatial-index.d.ts +0 -14
- package/build/types-internal.d.ts +0 -56
- package/build/types.d.ts +0 -148
- package/build/utils/dateUtils.d.ts +0 -10
- package/build/utils/getTileFormat.d.ts +0 -3
- package/build/utils/makeIntervalComplete.d.ts +0 -2
- package/build/utils/transformTileCoordsToWGS84.d.ts +0 -8
- package/build/utils/transformToTileCoords.d.ts +0 -9
- package/build/utils.d.ts +0 -32
- package/build/widget-sources/index.d.ts +0 -7
- package/build/widget-sources/types.d.ts +0 -158
- package/build/widget-sources/widget-query-source.d.ts +0 -33
- package/build/widget-sources/widget-raster-source.d.ts +0 -11
- package/build/widget-sources/widget-remote-source.d.ts +0 -18
- package/build/widget-sources/widget-source.d.ts +0 -74
- package/build/widget-sources/widget-table-source.d.ts +0 -33
- package/build/widget-sources/widget-tileset-source.d.ts +0 -77
- package/src/filters/tileFeaturesRaster.ts +0 -111
- package/src/widget-sources/widget-raster-source.ts +0 -14
|
@@ -0,0 +1,1712 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiVersion,
|
|
3
|
+
DEFAULT_AGGREGATION_RES_LEVEL_H3,
|
|
4
|
+
DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN,
|
|
5
|
+
DEFAULT_API_BASE_URL,
|
|
6
|
+
DEFAULT_GEO_COLUMN,
|
|
7
|
+
DEFAULT_MAX_LENGTH_URL,
|
|
8
|
+
DEFAULT_TILE_RESOLUTION,
|
|
9
|
+
FEATURE_GEOM_PROPERTY,
|
|
10
|
+
FilterType,
|
|
11
|
+
InvalidColumnError,
|
|
12
|
+
Provider,
|
|
13
|
+
SpatialIndex,
|
|
14
|
+
TileFormat,
|
|
15
|
+
V3_MINOR_VERSION,
|
|
16
|
+
WidgetSource,
|
|
17
|
+
WidgetTilesetSource,
|
|
18
|
+
__publicField,
|
|
19
|
+
_buildFeatureFilter,
|
|
20
|
+
_getHexagonResolution,
|
|
21
|
+
aggregate,
|
|
22
|
+
aggregationFunctions,
|
|
23
|
+
applyFilters,
|
|
24
|
+
applySorting,
|
|
25
|
+
assert,
|
|
26
|
+
buildBinaryFeatureFilter,
|
|
27
|
+
filterFunctions,
|
|
28
|
+
geojsonFeatures,
|
|
29
|
+
getApplicableFilters,
|
|
30
|
+
getClient,
|
|
31
|
+
groupValuesByColumn,
|
|
32
|
+
groupValuesByDateColumn,
|
|
33
|
+
histogram,
|
|
34
|
+
isEmptyObject,
|
|
35
|
+
isPureObject,
|
|
36
|
+
makeIntervalComplete,
|
|
37
|
+
normalizeObjectKeys,
|
|
38
|
+
scatterPlot,
|
|
39
|
+
setClient,
|
|
40
|
+
tileFeatures,
|
|
41
|
+
tileFeaturesGeometries,
|
|
42
|
+
tileFeaturesSpatialIndex,
|
|
43
|
+
transformToTileCoords
|
|
44
|
+
} from "./chunk-V3E7BKVR.js";
|
|
45
|
+
|
|
46
|
+
// src/deck/get-data-filter-extension-props.ts
|
|
47
|
+
function getDataFilterExtensionProps(filters, filtersLogicalOperator, filterSize) {
|
|
48
|
+
filterSize ?? (filterSize = 4);
|
|
49
|
+
const { filtersWithoutTimeType, timeColumn, timeFilter } = getFiltersByType(filters);
|
|
50
|
+
return {
|
|
51
|
+
filterRange: getFilterRange(timeFilter, filterSize),
|
|
52
|
+
updateTriggers: getUpdateTriggers(
|
|
53
|
+
filtersWithoutTimeType,
|
|
54
|
+
timeColumn,
|
|
55
|
+
timeFilter
|
|
56
|
+
),
|
|
57
|
+
getFilterValue: getFilterValue(
|
|
58
|
+
filtersWithoutTimeType,
|
|
59
|
+
timeColumn,
|
|
60
|
+
timeFilter,
|
|
61
|
+
filterSize,
|
|
62
|
+
filtersLogicalOperator
|
|
63
|
+
)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function getFiltersByType(filters) {
|
|
67
|
+
const filtersWithoutTimeType = {};
|
|
68
|
+
let timeColumn = null;
|
|
69
|
+
let timeFilter = null;
|
|
70
|
+
for (const [column, columnData] of Object.entries(filters)) {
|
|
71
|
+
for (const [type, typeData] of Object.entries(columnData)) {
|
|
72
|
+
if (type === "time" /* TIME */) {
|
|
73
|
+
timeColumn = column;
|
|
74
|
+
timeFilter = typeData;
|
|
75
|
+
} else {
|
|
76
|
+
filtersWithoutTimeType[column] = { [type]: typeData };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
filtersWithoutTimeType,
|
|
82
|
+
timeColumn,
|
|
83
|
+
timeFilter
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function getFilterRange(timeFilter, filterSize) {
|
|
87
|
+
const result = Array(filterSize).fill([0, 0]);
|
|
88
|
+
result[0] = [1, 1];
|
|
89
|
+
if (timeFilter) {
|
|
90
|
+
const offsetBy = timeFilter.params?.offsetBy || 0;
|
|
91
|
+
result[1] = timeFilter.values[0].map((v) => v - offsetBy);
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
function getUpdateTriggers(filtersWithoutTimeType, timeColumn, timeFilter) {
|
|
96
|
+
const result = { ...filtersWithoutTimeType };
|
|
97
|
+
if (timeColumn && timeFilter) {
|
|
98
|
+
result[timeColumn] = {
|
|
99
|
+
...result[timeColumn],
|
|
100
|
+
offsetBy: timeFilter.params?.offsetBy,
|
|
101
|
+
["time" /* TIME */]: {}
|
|
102
|
+
// Allows working with other filters, without an impact on performance.
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
getFilterValue: JSON.stringify(result)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function getFilterValue(filtersWithoutTimeType, timeColumn, timeFilter, filterSize, filtersLogicalOperator) {
|
|
110
|
+
const result = Array(filterSize).fill(0);
|
|
111
|
+
const featureFilter = _buildFeatureFilter({
|
|
112
|
+
filters: filtersWithoutTimeType,
|
|
113
|
+
type: "number",
|
|
114
|
+
filtersLogicalOperator
|
|
115
|
+
});
|
|
116
|
+
return (feature2) => {
|
|
117
|
+
result[0] = featureFilter(feature2);
|
|
118
|
+
if (timeColumn && timeFilter) {
|
|
119
|
+
const offsetBy = timeFilter.params?.offsetBy || 0;
|
|
120
|
+
const f = feature2.properties || feature2;
|
|
121
|
+
result[1] = f[timeColumn] - offsetBy;
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/filters.ts
|
|
128
|
+
function addFilter(filters, { column, type, values, owner }) {
|
|
129
|
+
if (!filters[column]) {
|
|
130
|
+
filters[column] = {};
|
|
131
|
+
}
|
|
132
|
+
const filter = { values, owner };
|
|
133
|
+
filters[column][type] = filter;
|
|
134
|
+
return filters;
|
|
135
|
+
}
|
|
136
|
+
function removeFilter(filters, { column, owner }) {
|
|
137
|
+
const filter = filters[column];
|
|
138
|
+
if (!filter) {
|
|
139
|
+
return filters;
|
|
140
|
+
}
|
|
141
|
+
if (owner) {
|
|
142
|
+
for (const type of Object.values(FilterType)) {
|
|
143
|
+
if (owner === filter[type]?.owner) {
|
|
144
|
+
delete filter[type];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (!owner || isEmptyObject(filter)) {
|
|
149
|
+
delete filters[column];
|
|
150
|
+
}
|
|
151
|
+
return filters;
|
|
152
|
+
}
|
|
153
|
+
function clearFilters(filters) {
|
|
154
|
+
for (const column of Object.keys(filters)) {
|
|
155
|
+
delete filters[column];
|
|
156
|
+
}
|
|
157
|
+
return filters;
|
|
158
|
+
}
|
|
159
|
+
function hasFilter(filters, { column, owner }) {
|
|
160
|
+
const filter = filters[column];
|
|
161
|
+
if (!filter) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
if (!owner) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
for (const type of Object.values(FilterType)) {
|
|
168
|
+
if (owner === filter[type]?.owner) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
function getFilter(filters, { column, type, owner }) {
|
|
175
|
+
const filter = filters[column];
|
|
176
|
+
if (!filter) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if (!owner || owner === filter[type]?.owner) {
|
|
180
|
+
return filter[type] || null;
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/geo.ts
|
|
186
|
+
import bboxClip from "@turf/bbox-clip";
|
|
187
|
+
import bboxPolygon from "@turf/bbox-polygon";
|
|
188
|
+
import union from "@turf/union";
|
|
189
|
+
import { getType } from "@turf/invariant";
|
|
190
|
+
import { polygon, multiPolygon, feature, featureCollection } from "@turf/helpers";
|
|
191
|
+
function createViewportSpatialFilter(viewport) {
|
|
192
|
+
if (_isGlobalViewport(viewport)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
return createPolygonSpatialFilter(bboxPolygon(viewport).geometry);
|
|
196
|
+
}
|
|
197
|
+
function createPolygonSpatialFilter(spatialFilter) {
|
|
198
|
+
return spatialFilter && _normalizeGeometry(spatialFilter) || void 0;
|
|
199
|
+
}
|
|
200
|
+
function _isGlobalViewport(viewport) {
|
|
201
|
+
const [minx, miny, maxx, maxy] = viewport;
|
|
202
|
+
return maxx - minx > 179.5 * 2 && maxy - miny > 85.05 * 2;
|
|
203
|
+
}
|
|
204
|
+
function _normalizeGeometry(geometry) {
|
|
205
|
+
const WORLD = [-180, -90, 180, 90];
|
|
206
|
+
const worldClip = _clean(
|
|
207
|
+
bboxClip(geometry, WORLD).geometry
|
|
208
|
+
);
|
|
209
|
+
const geometryTxWest = _tx(geometry, 360);
|
|
210
|
+
const geometryTxEast = _tx(geometry, -360);
|
|
211
|
+
let result = worldClip;
|
|
212
|
+
if (result && geometryTxWest) {
|
|
213
|
+
const worldWestClip = _clean(
|
|
214
|
+
bboxClip(geometryTxWest, WORLD).geometry
|
|
215
|
+
);
|
|
216
|
+
if (worldWestClip) {
|
|
217
|
+
const collection = featureCollection([
|
|
218
|
+
feature(result),
|
|
219
|
+
feature(worldWestClip)
|
|
220
|
+
]);
|
|
221
|
+
const merged = union(collection);
|
|
222
|
+
result = merged ? _clean(merged.geometry) : result;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (result && geometryTxEast) {
|
|
226
|
+
const worldEastClip = _clean(
|
|
227
|
+
bboxClip(geometryTxEast, WORLD).geometry
|
|
228
|
+
);
|
|
229
|
+
if (worldEastClip) {
|
|
230
|
+
const collection = featureCollection([
|
|
231
|
+
feature(result),
|
|
232
|
+
feature(worldEastClip)
|
|
233
|
+
]);
|
|
234
|
+
const merged = union(collection);
|
|
235
|
+
result = merged ? _clean(merged.geometry) : result;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
function _cleanPolygonCoords(cc) {
|
|
241
|
+
const coords = cc.filter((c) => c.length > 0);
|
|
242
|
+
return coords.length > 0 ? coords : null;
|
|
243
|
+
}
|
|
244
|
+
function _cleanMultiPolygonCoords(ccc) {
|
|
245
|
+
const coords = ccc.map(_cleanPolygonCoords).filter((cc) => cc);
|
|
246
|
+
return coords.length > 0 ? coords : null;
|
|
247
|
+
}
|
|
248
|
+
function _clean(geometry) {
|
|
249
|
+
if (!geometry) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
if (_isPolygon(geometry)) {
|
|
253
|
+
const coords = _cleanPolygonCoords(geometry.coordinates);
|
|
254
|
+
return coords ? polygon(coords).geometry : null;
|
|
255
|
+
}
|
|
256
|
+
if (_isMultiPolygon(geometry)) {
|
|
257
|
+
const coords = _cleanMultiPolygonCoords(geometry.coordinates);
|
|
258
|
+
return coords ? multiPolygon(coords).geometry : null;
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
function _txContourCoords(cc, distance) {
|
|
263
|
+
return cc.map((c) => [c[0] + distance, c[1]]);
|
|
264
|
+
}
|
|
265
|
+
function _txPolygonCoords(ccc, distance) {
|
|
266
|
+
return ccc.map((cc) => _txContourCoords(cc, distance));
|
|
267
|
+
}
|
|
268
|
+
function _txMultiPolygonCoords(cccc, distance) {
|
|
269
|
+
return cccc.map((ccc) => _txPolygonCoords(ccc, distance));
|
|
270
|
+
}
|
|
271
|
+
function _tx(geometry, distance) {
|
|
272
|
+
if (geometry && getType(geometry) === "Polygon") {
|
|
273
|
+
const coords = _txPolygonCoords(
|
|
274
|
+
geometry.coordinates,
|
|
275
|
+
distance
|
|
276
|
+
);
|
|
277
|
+
return polygon(coords).geometry;
|
|
278
|
+
} else if (geometry && getType(geometry) === "MultiPolygon") {
|
|
279
|
+
const coords = _txMultiPolygonCoords(
|
|
280
|
+
geometry.coordinates,
|
|
281
|
+
distance
|
|
282
|
+
);
|
|
283
|
+
return multiPolygon(coords).geometry;
|
|
284
|
+
} else {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function _isPolygon(geometry) {
|
|
289
|
+
return getType(geometry) === "Polygon";
|
|
290
|
+
}
|
|
291
|
+
function _isMultiPolygon(geometry) {
|
|
292
|
+
return getType(geometry) === "MultiPolygon";
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/api/endpoints.ts
|
|
296
|
+
function joinPath(...args) {
|
|
297
|
+
return args.map((part) => part.endsWith("/") ? part.slice(0, -1) : part).join("/");
|
|
298
|
+
}
|
|
299
|
+
function buildV3Path(apiBaseUrl, version, endpoint, ...rest) {
|
|
300
|
+
return joinPath(apiBaseUrl, version, endpoint, ...rest);
|
|
301
|
+
}
|
|
302
|
+
function buildPublicMapUrl({
|
|
303
|
+
apiBaseUrl,
|
|
304
|
+
cartoMapId
|
|
305
|
+
}) {
|
|
306
|
+
return buildV3Path(apiBaseUrl, "v3", "maps", "public", cartoMapId);
|
|
307
|
+
}
|
|
308
|
+
function buildStatsUrl({
|
|
309
|
+
attribute,
|
|
310
|
+
apiBaseUrl,
|
|
311
|
+
connectionName,
|
|
312
|
+
source,
|
|
313
|
+
type
|
|
314
|
+
}) {
|
|
315
|
+
if (type === "query") {
|
|
316
|
+
return buildV3Path(apiBaseUrl, "v3", "stats", connectionName, attribute);
|
|
317
|
+
}
|
|
318
|
+
return buildV3Path(
|
|
319
|
+
apiBaseUrl,
|
|
320
|
+
"v3",
|
|
321
|
+
"stats",
|
|
322
|
+
connectionName,
|
|
323
|
+
source,
|
|
324
|
+
attribute
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
function buildSourceUrl({
|
|
328
|
+
apiBaseUrl,
|
|
329
|
+
connectionName,
|
|
330
|
+
endpoint
|
|
331
|
+
}) {
|
|
332
|
+
return buildV3Path(apiBaseUrl, "v3", "maps", connectionName, endpoint);
|
|
333
|
+
}
|
|
334
|
+
function buildQueryUrl({
|
|
335
|
+
apiBaseUrl,
|
|
336
|
+
connectionName
|
|
337
|
+
}) {
|
|
338
|
+
return buildV3Path(apiBaseUrl, "v3", "sql", connectionName, "query");
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// src/api/carto-api-error.ts
|
|
342
|
+
var CartoAPIError = class extends Error {
|
|
343
|
+
constructor(error, errorContext, response, responseJson) {
|
|
344
|
+
let responseString = "Failed to connect";
|
|
345
|
+
if (response) {
|
|
346
|
+
responseString = "Server returned: ";
|
|
347
|
+
if (response.status === 400) {
|
|
348
|
+
responseString += "Bad request";
|
|
349
|
+
} else if (response.status === 401 || response.status === 403) {
|
|
350
|
+
responseString += "Unauthorized access";
|
|
351
|
+
} else if (response.status === 404) {
|
|
352
|
+
responseString += "Not found";
|
|
353
|
+
} else {
|
|
354
|
+
responseString += "Error";
|
|
355
|
+
}
|
|
356
|
+
responseString += ` (${response.status}):`;
|
|
357
|
+
}
|
|
358
|
+
responseString += ` ${error.message || error}`;
|
|
359
|
+
let message = `${errorContext.requestType} API request failed`;
|
|
360
|
+
message += `
|
|
361
|
+
${responseString}`;
|
|
362
|
+
for (const key of Object.keys(errorContext)) {
|
|
363
|
+
if (key === "requestType") continue;
|
|
364
|
+
message += `
|
|
365
|
+
${formatErrorKey(key)}: ${errorContext[key]}`;
|
|
366
|
+
}
|
|
367
|
+
message += "\n";
|
|
368
|
+
super(message);
|
|
369
|
+
/** Source error from server */
|
|
370
|
+
__publicField(this, "error");
|
|
371
|
+
/** Context (API call & parameters) in which error occured */
|
|
372
|
+
__publicField(this, "errorContext");
|
|
373
|
+
/** Response from server */
|
|
374
|
+
__publicField(this, "response");
|
|
375
|
+
/** JSON Response from server */
|
|
376
|
+
__publicField(this, "responseJson");
|
|
377
|
+
this.name = "CartoAPIError";
|
|
378
|
+
this.response = response;
|
|
379
|
+
this.responseJson = responseJson;
|
|
380
|
+
this.error = error;
|
|
381
|
+
this.errorContext = errorContext;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
function formatErrorKey(key) {
|
|
385
|
+
return key.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase());
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/api/request-with-parameters.ts
|
|
389
|
+
var DEFAULT_HEADERS = {
|
|
390
|
+
Accept: "application/json",
|
|
391
|
+
"Content-Type": "application/json"
|
|
392
|
+
};
|
|
393
|
+
var DEFAULT_REQUEST_CACHE = /* @__PURE__ */ new Map();
|
|
394
|
+
async function requestWithParameters({
|
|
395
|
+
baseUrl,
|
|
396
|
+
parameters = {},
|
|
397
|
+
headers: customHeaders = {},
|
|
398
|
+
errorContext,
|
|
399
|
+
maxLengthURL = DEFAULT_MAX_LENGTH_URL,
|
|
400
|
+
localCache
|
|
401
|
+
}) {
|
|
402
|
+
parameters = {
|
|
403
|
+
v: V3_MINOR_VERSION,
|
|
404
|
+
client: getClient(),
|
|
405
|
+
...typeof deck !== "undefined" && deck.VERSION && { deckglVersion: deck.VERSION },
|
|
406
|
+
...parameters
|
|
407
|
+
};
|
|
408
|
+
baseUrl = excludeURLParameters(baseUrl, Object.keys(parameters));
|
|
409
|
+
const key = createCacheKey(baseUrl, parameters, customHeaders);
|
|
410
|
+
const {
|
|
411
|
+
cache: REQUEST_CACHE,
|
|
412
|
+
canReadCache,
|
|
413
|
+
canStoreInCache
|
|
414
|
+
} = getCacheSettings(localCache);
|
|
415
|
+
if (canReadCache && REQUEST_CACHE.has(key)) {
|
|
416
|
+
return REQUEST_CACHE.get(key);
|
|
417
|
+
}
|
|
418
|
+
const url = createURLWithParameters(baseUrl, parameters);
|
|
419
|
+
const headers = { ...DEFAULT_HEADERS, ...customHeaders };
|
|
420
|
+
const fetchPromise = url.length > maxLengthURL ? fetch(baseUrl, {
|
|
421
|
+
method: "POST",
|
|
422
|
+
body: JSON.stringify(parameters),
|
|
423
|
+
headers
|
|
424
|
+
}) : fetch(url, { headers });
|
|
425
|
+
let response;
|
|
426
|
+
let responseJson;
|
|
427
|
+
const jsonPromise = fetchPromise.then((_response) => {
|
|
428
|
+
response = _response;
|
|
429
|
+
return response.json();
|
|
430
|
+
}).then((json) => {
|
|
431
|
+
responseJson = json;
|
|
432
|
+
if (!response || !response.ok) {
|
|
433
|
+
throw new Error(json.error);
|
|
434
|
+
}
|
|
435
|
+
return json;
|
|
436
|
+
}).catch((error) => {
|
|
437
|
+
if (canStoreInCache) {
|
|
438
|
+
REQUEST_CACHE.delete(key);
|
|
439
|
+
}
|
|
440
|
+
throw new CartoAPIError(error, errorContext, response, responseJson);
|
|
441
|
+
});
|
|
442
|
+
if (canStoreInCache) {
|
|
443
|
+
REQUEST_CACHE.set(key, jsonPromise);
|
|
444
|
+
}
|
|
445
|
+
return jsonPromise;
|
|
446
|
+
}
|
|
447
|
+
function getCacheSettings(localCache) {
|
|
448
|
+
const canReadCache = localCache?.cacheControl?.includes("no-cache") ? false : true;
|
|
449
|
+
const canStoreInCache = localCache?.cacheControl?.includes("no-store") ? false : true;
|
|
450
|
+
const cache = localCache?.cache || DEFAULT_REQUEST_CACHE;
|
|
451
|
+
return {
|
|
452
|
+
cache,
|
|
453
|
+
canReadCache,
|
|
454
|
+
canStoreInCache
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
function createCacheKey(baseUrl, parameters, headers) {
|
|
458
|
+
const parameterEntries = Object.entries(parameters).sort(
|
|
459
|
+
([a], [b]) => a > b ? 1 : -1
|
|
460
|
+
);
|
|
461
|
+
const headerEntries = Object.entries(headers).sort(
|
|
462
|
+
([a], [b]) => a > b ? 1 : -1
|
|
463
|
+
);
|
|
464
|
+
return JSON.stringify({
|
|
465
|
+
baseUrl,
|
|
466
|
+
parameters: parameterEntries,
|
|
467
|
+
headers: headerEntries
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
function createURLWithParameters(baseUrlString, parameters) {
|
|
471
|
+
const baseUrl = new URL(baseUrlString);
|
|
472
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
473
|
+
if (isPureObject(value) || Array.isArray(value)) {
|
|
474
|
+
baseUrl.searchParams.set(key, JSON.stringify(value));
|
|
475
|
+
} else {
|
|
476
|
+
baseUrl.searchParams.set(
|
|
477
|
+
key,
|
|
478
|
+
value.toString()
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return baseUrl.toString();
|
|
483
|
+
}
|
|
484
|
+
function excludeURLParameters(baseUrlString, parameters) {
|
|
485
|
+
const baseUrl = new URL(baseUrlString);
|
|
486
|
+
for (const param of parameters) {
|
|
487
|
+
if (baseUrl.searchParams.has(param)) {
|
|
488
|
+
baseUrl.searchParams.delete(param);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return baseUrl.toString();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// src/sources/base-source.ts
|
|
495
|
+
var SOURCE_DEFAULTS = {
|
|
496
|
+
apiBaseUrl: DEFAULT_API_BASE_URL,
|
|
497
|
+
clientId: getClient(),
|
|
498
|
+
format: "tilejson",
|
|
499
|
+
headers: {},
|
|
500
|
+
maxLengthURL: DEFAULT_MAX_LENGTH_URL
|
|
501
|
+
};
|
|
502
|
+
async function baseSource(endpoint, options, urlParameters) {
|
|
503
|
+
const { accessToken, connectionName, cache, ...optionalOptions } = options;
|
|
504
|
+
const mergedOptions = {
|
|
505
|
+
...SOURCE_DEFAULTS,
|
|
506
|
+
accessToken,
|
|
507
|
+
connectionName,
|
|
508
|
+
endpoint
|
|
509
|
+
};
|
|
510
|
+
for (const key in optionalOptions) {
|
|
511
|
+
if (optionalOptions[key]) {
|
|
512
|
+
mergedOptions[key] = optionalOptions[key];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
const baseUrl = buildSourceUrl(mergedOptions);
|
|
516
|
+
const { clientId, maxLengthURL, format, localCache } = mergedOptions;
|
|
517
|
+
const headers = {
|
|
518
|
+
Authorization: `Bearer ${options.accessToken}`,
|
|
519
|
+
...options.headers
|
|
520
|
+
};
|
|
521
|
+
const parameters = { client: clientId, ...urlParameters };
|
|
522
|
+
const errorContext = {
|
|
523
|
+
requestType: "Map instantiation",
|
|
524
|
+
connection: options.connectionName,
|
|
525
|
+
type: endpoint,
|
|
526
|
+
source: JSON.stringify(parameters, void 0, 2)
|
|
527
|
+
};
|
|
528
|
+
const mapInstantiation = await requestWithParameters({
|
|
529
|
+
baseUrl,
|
|
530
|
+
parameters,
|
|
531
|
+
headers,
|
|
532
|
+
errorContext,
|
|
533
|
+
maxLengthURL,
|
|
534
|
+
localCache
|
|
535
|
+
});
|
|
536
|
+
const dataUrl = mapInstantiation[format].url[0];
|
|
537
|
+
if (cache) {
|
|
538
|
+
cache.value = parseInt(
|
|
539
|
+
new URL(dataUrl).searchParams.get("cache") || "",
|
|
540
|
+
10
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
errorContext.requestType = "Map data";
|
|
544
|
+
if (format === "tilejson") {
|
|
545
|
+
const json = await requestWithParameters({
|
|
546
|
+
baseUrl: dataUrl,
|
|
547
|
+
headers,
|
|
548
|
+
errorContext,
|
|
549
|
+
maxLengthURL,
|
|
550
|
+
localCache
|
|
551
|
+
});
|
|
552
|
+
if (accessToken) {
|
|
553
|
+
json.accessToken = accessToken;
|
|
554
|
+
}
|
|
555
|
+
return json;
|
|
556
|
+
}
|
|
557
|
+
return await requestWithParameters({
|
|
558
|
+
baseUrl: dataUrl,
|
|
559
|
+
headers,
|
|
560
|
+
errorContext,
|
|
561
|
+
maxLengthURL,
|
|
562
|
+
localCache
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// src/sources/boundary-query-source.ts
|
|
567
|
+
var boundaryQuerySource = async function(options) {
|
|
568
|
+
const {
|
|
569
|
+
columns,
|
|
570
|
+
filters,
|
|
571
|
+
tilesetTableName,
|
|
572
|
+
propertiesSqlQuery,
|
|
573
|
+
queryParameters
|
|
574
|
+
} = options;
|
|
575
|
+
const urlParameters = {
|
|
576
|
+
tilesetTableName,
|
|
577
|
+
propertiesSqlQuery
|
|
578
|
+
};
|
|
579
|
+
if (columns) {
|
|
580
|
+
urlParameters.columns = columns.join(",");
|
|
581
|
+
}
|
|
582
|
+
if (filters) {
|
|
583
|
+
urlParameters.filters = filters;
|
|
584
|
+
}
|
|
585
|
+
if (queryParameters) {
|
|
586
|
+
urlParameters.queryParameters = queryParameters;
|
|
587
|
+
}
|
|
588
|
+
return baseSource(
|
|
589
|
+
"boundary",
|
|
590
|
+
options,
|
|
591
|
+
urlParameters
|
|
592
|
+
);
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
// src/sources/boundary-table-source.ts
|
|
596
|
+
var boundaryTableSource = async function(options) {
|
|
597
|
+
const { filters, tilesetTableName, columns, propertiesTableName } = options;
|
|
598
|
+
const urlParameters = {
|
|
599
|
+
tilesetTableName,
|
|
600
|
+
propertiesTableName
|
|
601
|
+
};
|
|
602
|
+
if (columns) {
|
|
603
|
+
urlParameters.columns = columns.join(",");
|
|
604
|
+
}
|
|
605
|
+
if (filters) {
|
|
606
|
+
urlParameters.filters = filters;
|
|
607
|
+
}
|
|
608
|
+
return baseSource(
|
|
609
|
+
"boundary",
|
|
610
|
+
options,
|
|
611
|
+
urlParameters
|
|
612
|
+
);
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
// src/models/common.ts
|
|
616
|
+
function dealWithApiError({
|
|
617
|
+
response,
|
|
618
|
+
data
|
|
619
|
+
}) {
|
|
620
|
+
if (data.error === "Column not found") {
|
|
621
|
+
throw new InvalidColumnError(`${data.error} ${data.column_name}`);
|
|
622
|
+
}
|
|
623
|
+
if (typeof data.error === "string" && data.error?.includes("Missing columns")) {
|
|
624
|
+
throw new InvalidColumnError(data.error);
|
|
625
|
+
}
|
|
626
|
+
switch (response.status) {
|
|
627
|
+
case 401:
|
|
628
|
+
throw new Error("Unauthorized access. Invalid credentials");
|
|
629
|
+
case 403:
|
|
630
|
+
throw new Error("Forbidden access to the requested data");
|
|
631
|
+
default:
|
|
632
|
+
throw new Error(
|
|
633
|
+
data && data.error && typeof data.error === "string" ? data.error : JSON.stringify(data?.hint || data.error?.[0])
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
async function makeCall({
|
|
638
|
+
url,
|
|
639
|
+
accessToken,
|
|
640
|
+
opts
|
|
641
|
+
}) {
|
|
642
|
+
let response;
|
|
643
|
+
let data;
|
|
644
|
+
const isPost = opts?.method === "POST";
|
|
645
|
+
try {
|
|
646
|
+
response = await fetch(url.toString(), {
|
|
647
|
+
headers: {
|
|
648
|
+
Authorization: `Bearer ${accessToken}`,
|
|
649
|
+
...isPost && { "Content-Type": "application/json" },
|
|
650
|
+
...opts.headers
|
|
651
|
+
},
|
|
652
|
+
...isPost && {
|
|
653
|
+
method: opts?.method,
|
|
654
|
+
body: opts?.body
|
|
655
|
+
},
|
|
656
|
+
signal: opts?.abortController?.signal,
|
|
657
|
+
...opts?.otherOptions
|
|
658
|
+
});
|
|
659
|
+
data = await response.json();
|
|
660
|
+
} catch (error) {
|
|
661
|
+
if (error.name === "AbortError") throw error;
|
|
662
|
+
throw new Error(`Failed request: ${error}`);
|
|
663
|
+
}
|
|
664
|
+
if (!response.ok) {
|
|
665
|
+
dealWithApiError({ response, data });
|
|
666
|
+
}
|
|
667
|
+
return data;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/models/model.ts
|
|
671
|
+
var AVAILABLE_MODELS = [
|
|
672
|
+
"category",
|
|
673
|
+
"histogram",
|
|
674
|
+
"formula",
|
|
675
|
+
"pick",
|
|
676
|
+
"timeseries",
|
|
677
|
+
"range",
|
|
678
|
+
"scatterplot",
|
|
679
|
+
"table"
|
|
680
|
+
];
|
|
681
|
+
var { V3 } = ApiVersion;
|
|
682
|
+
var REQUEST_GET_MAX_URL_LENGTH = 2048;
|
|
683
|
+
function executeModel(props) {
|
|
684
|
+
assert(props.source, "executeModel: missing source");
|
|
685
|
+
assert(props.model, "executeModel: missing model");
|
|
686
|
+
assert(props.params, "executeModel: missing params");
|
|
687
|
+
assert(
|
|
688
|
+
AVAILABLE_MODELS.includes(props.model),
|
|
689
|
+
`executeModel: model provided isn't valid. Available models: ${AVAILABLE_MODELS.join(
|
|
690
|
+
", "
|
|
691
|
+
)}`
|
|
692
|
+
);
|
|
693
|
+
const { model, source, params, opts } = props;
|
|
694
|
+
const { type, apiVersion, apiBaseUrl, accessToken, connectionName, clientId } = source;
|
|
695
|
+
assert(apiBaseUrl, "executeModel: missing apiBaseUrl");
|
|
696
|
+
assert(accessToken, "executeModel: missing accessToken");
|
|
697
|
+
assert(apiVersion === V3, "executeModel: SQL Model API requires CARTO 3+");
|
|
698
|
+
assert(type !== "tileset", "executeModel: Tilesets not supported");
|
|
699
|
+
let url = `${apiBaseUrl}/v3/sql/${connectionName}/model/${model}`;
|
|
700
|
+
const {
|
|
701
|
+
data,
|
|
702
|
+
filters,
|
|
703
|
+
filtersLogicalOperator = "and",
|
|
704
|
+
spatialDataType = "geo",
|
|
705
|
+
spatialFiltersMode = "intersects",
|
|
706
|
+
spatialFiltersResolution = 0
|
|
707
|
+
} = source;
|
|
708
|
+
const queryParams = {
|
|
709
|
+
type,
|
|
710
|
+
client: clientId,
|
|
711
|
+
source: data,
|
|
712
|
+
params,
|
|
713
|
+
queryParameters: source.queryParameters || "",
|
|
714
|
+
filters,
|
|
715
|
+
filtersLogicalOperator
|
|
716
|
+
};
|
|
717
|
+
const spatialDataColumn = source.spatialDataColumn || DEFAULT_GEO_COLUMN;
|
|
718
|
+
if (model === "pick") {
|
|
719
|
+
queryParams.spatialDataColumn = spatialDataColumn;
|
|
720
|
+
}
|
|
721
|
+
const spatialFilters = source.spatialFilter ? { [spatialDataColumn]: source.spatialFilter } : void 0;
|
|
722
|
+
if (spatialFilters) {
|
|
723
|
+
queryParams.spatialFilters = spatialFilters;
|
|
724
|
+
queryParams.spatialDataColumn = spatialDataColumn;
|
|
725
|
+
queryParams.spatialDataType = spatialDataType;
|
|
726
|
+
}
|
|
727
|
+
if (spatialDataType !== "geo") {
|
|
728
|
+
if (spatialFiltersResolution > 0) {
|
|
729
|
+
queryParams.spatialFiltersResolution = spatialFiltersResolution;
|
|
730
|
+
}
|
|
731
|
+
queryParams.spatialFiltersMode = spatialFiltersMode;
|
|
732
|
+
}
|
|
733
|
+
const urlWithSearchParams = url + "?" + objectToURLSearchParams(queryParams).toString();
|
|
734
|
+
const isGet = urlWithSearchParams.length <= REQUEST_GET_MAX_URL_LENGTH;
|
|
735
|
+
if (isGet) {
|
|
736
|
+
url = urlWithSearchParams;
|
|
737
|
+
}
|
|
738
|
+
return makeCall({
|
|
739
|
+
url,
|
|
740
|
+
accessToken: source.accessToken,
|
|
741
|
+
opts: {
|
|
742
|
+
...opts,
|
|
743
|
+
method: isGet ? "GET" : "POST",
|
|
744
|
+
...!isGet && { body: JSON.stringify(queryParams) }
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
function objectToURLSearchParams(object) {
|
|
749
|
+
const params = new URLSearchParams();
|
|
750
|
+
for (const key in object) {
|
|
751
|
+
if (isPureObject(object[key])) {
|
|
752
|
+
params.append(key, JSON.stringify(object[key]));
|
|
753
|
+
} else if (Array.isArray(object[key])) {
|
|
754
|
+
params.append(key, JSON.stringify(object[key]));
|
|
755
|
+
} else if (object[key] === null) {
|
|
756
|
+
params.append(key, "null");
|
|
757
|
+
} else if (object[key] !== void 0) {
|
|
758
|
+
params.append(key, String(object[key]));
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return params;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/widget-sources/widget-remote-source.ts
|
|
765
|
+
var WidgetRemoteSource = class extends WidgetSource {
|
|
766
|
+
constructor() {
|
|
767
|
+
super(...arguments);
|
|
768
|
+
__publicField(this, "_headers", {});
|
|
769
|
+
}
|
|
770
|
+
/** Assigns HTTP headers to be included on API requests from this source. */
|
|
771
|
+
setRequestHeaders(headers) {
|
|
772
|
+
this._headers = headers;
|
|
773
|
+
}
|
|
774
|
+
_getModelSource(filters, filterOwner) {
|
|
775
|
+
const props = this.props;
|
|
776
|
+
return {
|
|
777
|
+
apiVersion: props.apiVersion,
|
|
778
|
+
apiBaseUrl: props.apiBaseUrl,
|
|
779
|
+
clientId: props.clientId,
|
|
780
|
+
accessToken: props.accessToken,
|
|
781
|
+
connectionName: props.connectionName,
|
|
782
|
+
filters: getApplicableFilters(filterOwner, filters || props.filters),
|
|
783
|
+
filtersLogicalOperator: props.filtersLogicalOperator,
|
|
784
|
+
spatialDataType: props.spatialDataType,
|
|
785
|
+
spatialDataColumn: props.spatialDataColumn,
|
|
786
|
+
dataResolution: props.dataResolution
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
async getCategories(options) {
|
|
790
|
+
const {
|
|
791
|
+
filters = this.props.filters,
|
|
792
|
+
filterOwner,
|
|
793
|
+
spatialFilter,
|
|
794
|
+
spatialFiltersMode,
|
|
795
|
+
spatialIndexReferenceViewState,
|
|
796
|
+
abortController,
|
|
797
|
+
...params
|
|
798
|
+
} = options;
|
|
799
|
+
const { column, operation, operationColumn } = params;
|
|
800
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
801
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
802
|
+
source,
|
|
803
|
+
spatialFilter,
|
|
804
|
+
spatialIndexReferenceViewState
|
|
805
|
+
);
|
|
806
|
+
return executeModel({
|
|
807
|
+
model: "category",
|
|
808
|
+
source: {
|
|
809
|
+
...source,
|
|
810
|
+
spatialFiltersResolution,
|
|
811
|
+
spatialFiltersMode,
|
|
812
|
+
spatialFilter
|
|
813
|
+
},
|
|
814
|
+
params: {
|
|
815
|
+
column,
|
|
816
|
+
operation,
|
|
817
|
+
operationColumn: operationColumn || column
|
|
818
|
+
},
|
|
819
|
+
opts: { abortController, headers: this._headers }
|
|
820
|
+
}).then((res) => normalizeObjectKeys(res.rows));
|
|
821
|
+
}
|
|
822
|
+
async getFeatures(options) {
|
|
823
|
+
const {
|
|
824
|
+
filters = this.props.filters,
|
|
825
|
+
filterOwner,
|
|
826
|
+
spatialFilter,
|
|
827
|
+
spatialFiltersMode,
|
|
828
|
+
spatialIndexReferenceViewState,
|
|
829
|
+
abortController,
|
|
830
|
+
...params
|
|
831
|
+
} = options;
|
|
832
|
+
const { columns, dataType, featureIds, z, limit, tileResolution } = params;
|
|
833
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
834
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
835
|
+
source,
|
|
836
|
+
spatialFilter,
|
|
837
|
+
spatialIndexReferenceViewState
|
|
838
|
+
);
|
|
839
|
+
return executeModel({
|
|
840
|
+
model: "pick",
|
|
841
|
+
source: {
|
|
842
|
+
...source,
|
|
843
|
+
spatialFiltersResolution,
|
|
844
|
+
spatialFiltersMode,
|
|
845
|
+
spatialFilter
|
|
846
|
+
},
|
|
847
|
+
params: {
|
|
848
|
+
columns,
|
|
849
|
+
dataType,
|
|
850
|
+
featureIds,
|
|
851
|
+
z,
|
|
852
|
+
limit: limit || 1e3,
|
|
853
|
+
tileResolution: tileResolution || DEFAULT_TILE_RESOLUTION
|
|
854
|
+
},
|
|
855
|
+
opts: { abortController, headers: this._headers }
|
|
856
|
+
// Avoid `normalizeObjectKeys()`, which changes column names.
|
|
857
|
+
}).then(({ rows }) => ({ rows }));
|
|
858
|
+
}
|
|
859
|
+
async getFormula(options) {
|
|
860
|
+
const {
|
|
861
|
+
filters = this.props.filters,
|
|
862
|
+
filterOwner,
|
|
863
|
+
spatialFilter,
|
|
864
|
+
spatialFiltersMode,
|
|
865
|
+
spatialIndexReferenceViewState,
|
|
866
|
+
abortController,
|
|
867
|
+
operationExp,
|
|
868
|
+
...params
|
|
869
|
+
} = options;
|
|
870
|
+
const { column, operation } = params;
|
|
871
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
872
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
873
|
+
source,
|
|
874
|
+
spatialFilter,
|
|
875
|
+
spatialIndexReferenceViewState
|
|
876
|
+
);
|
|
877
|
+
return executeModel({
|
|
878
|
+
model: "formula",
|
|
879
|
+
source: {
|
|
880
|
+
...source,
|
|
881
|
+
spatialFiltersResolution,
|
|
882
|
+
spatialFiltersMode,
|
|
883
|
+
spatialFilter
|
|
884
|
+
},
|
|
885
|
+
params: {
|
|
886
|
+
column: column ?? "*",
|
|
887
|
+
operation: operation ?? "count",
|
|
888
|
+
operationExp
|
|
889
|
+
},
|
|
890
|
+
opts: { abortController, headers: this._headers }
|
|
891
|
+
}).then((res) => normalizeObjectKeys(res.rows[0]));
|
|
892
|
+
}
|
|
893
|
+
async getHistogram(options) {
|
|
894
|
+
const {
|
|
895
|
+
filters = this.props.filters,
|
|
896
|
+
filterOwner,
|
|
897
|
+
spatialFilter,
|
|
898
|
+
spatialFiltersMode,
|
|
899
|
+
spatialIndexReferenceViewState,
|
|
900
|
+
abortController,
|
|
901
|
+
...params
|
|
902
|
+
} = options;
|
|
903
|
+
const { column, operation, ticks } = params;
|
|
904
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
905
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
906
|
+
source,
|
|
907
|
+
spatialFilter,
|
|
908
|
+
spatialIndexReferenceViewState
|
|
909
|
+
);
|
|
910
|
+
const data = await executeModel({
|
|
911
|
+
model: "histogram",
|
|
912
|
+
source: {
|
|
913
|
+
...source,
|
|
914
|
+
spatialFiltersResolution,
|
|
915
|
+
spatialFiltersMode,
|
|
916
|
+
spatialFilter
|
|
917
|
+
},
|
|
918
|
+
params: { column, operation, ticks },
|
|
919
|
+
opts: { abortController, headers: this._headers }
|
|
920
|
+
}).then((res) => normalizeObjectKeys(res.rows));
|
|
921
|
+
if (data.length) {
|
|
922
|
+
const result = Array(ticks.length + 1).fill(0);
|
|
923
|
+
data.forEach(
|
|
924
|
+
({ tick, value }) => result[tick] = value
|
|
925
|
+
);
|
|
926
|
+
return result;
|
|
927
|
+
}
|
|
928
|
+
return [];
|
|
929
|
+
}
|
|
930
|
+
async getRange(options) {
|
|
931
|
+
const {
|
|
932
|
+
filters = this.props.filters,
|
|
933
|
+
filterOwner,
|
|
934
|
+
spatialFilter,
|
|
935
|
+
spatialFiltersMode,
|
|
936
|
+
spatialIndexReferenceViewState,
|
|
937
|
+
abortController,
|
|
938
|
+
...params
|
|
939
|
+
} = options;
|
|
940
|
+
const { column } = params;
|
|
941
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
942
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
943
|
+
source,
|
|
944
|
+
spatialFilter,
|
|
945
|
+
spatialIndexReferenceViewState
|
|
946
|
+
);
|
|
947
|
+
return executeModel({
|
|
948
|
+
model: "range",
|
|
949
|
+
source: {
|
|
950
|
+
...source,
|
|
951
|
+
spatialFiltersResolution,
|
|
952
|
+
spatialFiltersMode,
|
|
953
|
+
spatialFilter
|
|
954
|
+
},
|
|
955
|
+
params: { column },
|
|
956
|
+
opts: { abortController, headers: this._headers }
|
|
957
|
+
}).then((res) => normalizeObjectKeys(res.rows[0]));
|
|
958
|
+
}
|
|
959
|
+
async getScatter(options) {
|
|
960
|
+
const {
|
|
961
|
+
filters = this.props.filters,
|
|
962
|
+
filterOwner,
|
|
963
|
+
spatialFilter,
|
|
964
|
+
spatialFiltersMode,
|
|
965
|
+
spatialIndexReferenceViewState,
|
|
966
|
+
abortController,
|
|
967
|
+
...params
|
|
968
|
+
} = options;
|
|
969
|
+
const { xAxisColumn, xAxisJoinOperation, yAxisColumn, yAxisJoinOperation } = params;
|
|
970
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
971
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
972
|
+
source,
|
|
973
|
+
spatialFilter,
|
|
974
|
+
spatialIndexReferenceViewState
|
|
975
|
+
);
|
|
976
|
+
const HARD_LIMIT = 500;
|
|
977
|
+
return executeModel({
|
|
978
|
+
model: "scatterplot",
|
|
979
|
+
source: {
|
|
980
|
+
...source,
|
|
981
|
+
spatialFiltersResolution,
|
|
982
|
+
spatialFiltersMode,
|
|
983
|
+
spatialFilter
|
|
984
|
+
},
|
|
985
|
+
params: {
|
|
986
|
+
xAxisColumn,
|
|
987
|
+
xAxisJoinOperation,
|
|
988
|
+
yAxisColumn,
|
|
989
|
+
yAxisJoinOperation,
|
|
990
|
+
limit: HARD_LIMIT
|
|
991
|
+
},
|
|
992
|
+
opts: { abortController, headers: this._headers }
|
|
993
|
+
}).then((res) => normalizeObjectKeys(res.rows)).then((res) => res.map(({ x, y }) => [x, y]));
|
|
994
|
+
}
|
|
995
|
+
async getTable(options) {
|
|
996
|
+
const {
|
|
997
|
+
filters = this.props.filters,
|
|
998
|
+
filterOwner,
|
|
999
|
+
spatialFilter,
|
|
1000
|
+
spatialFiltersMode,
|
|
1001
|
+
spatialIndexReferenceViewState,
|
|
1002
|
+
abortController,
|
|
1003
|
+
...params
|
|
1004
|
+
} = options;
|
|
1005
|
+
const { columns, sortBy, sortDirection, offset = 0, limit = 10 } = params;
|
|
1006
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
1007
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
1008
|
+
source,
|
|
1009
|
+
spatialFilter,
|
|
1010
|
+
spatialIndexReferenceViewState
|
|
1011
|
+
);
|
|
1012
|
+
return executeModel({
|
|
1013
|
+
model: "table",
|
|
1014
|
+
source: {
|
|
1015
|
+
...source,
|
|
1016
|
+
spatialFiltersResolution,
|
|
1017
|
+
spatialFiltersMode,
|
|
1018
|
+
spatialFilter
|
|
1019
|
+
},
|
|
1020
|
+
params: {
|
|
1021
|
+
column: columns,
|
|
1022
|
+
sortBy,
|
|
1023
|
+
sortDirection,
|
|
1024
|
+
limit,
|
|
1025
|
+
offset
|
|
1026
|
+
},
|
|
1027
|
+
opts: { abortController, headers: this._headers }
|
|
1028
|
+
}).then((res) => ({
|
|
1029
|
+
// Avoid `normalizeObjectKeys()`, which changes column names.
|
|
1030
|
+
rows: res.rows ?? res.ROWS,
|
|
1031
|
+
totalCount: res.metadata?.total ?? res.METADATA?.TOTAL
|
|
1032
|
+
}));
|
|
1033
|
+
}
|
|
1034
|
+
async getTimeSeries(options) {
|
|
1035
|
+
const {
|
|
1036
|
+
filters = this.props.filters,
|
|
1037
|
+
filterOwner,
|
|
1038
|
+
abortController,
|
|
1039
|
+
spatialFilter,
|
|
1040
|
+
spatialFiltersMode,
|
|
1041
|
+
spatialIndexReferenceViewState,
|
|
1042
|
+
...params
|
|
1043
|
+
} = options;
|
|
1044
|
+
const {
|
|
1045
|
+
column,
|
|
1046
|
+
operationColumn,
|
|
1047
|
+
joinOperation,
|
|
1048
|
+
operation,
|
|
1049
|
+
stepSize,
|
|
1050
|
+
stepMultiplier,
|
|
1051
|
+
splitByCategory,
|
|
1052
|
+
splitByCategoryLimit,
|
|
1053
|
+
splitByCategoryValues
|
|
1054
|
+
} = params;
|
|
1055
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
1056
|
+
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
1057
|
+
source,
|
|
1058
|
+
spatialFilter,
|
|
1059
|
+
spatialIndexReferenceViewState
|
|
1060
|
+
);
|
|
1061
|
+
return executeModel({
|
|
1062
|
+
model: "timeseries",
|
|
1063
|
+
source: {
|
|
1064
|
+
...source,
|
|
1065
|
+
spatialFiltersResolution,
|
|
1066
|
+
spatialFiltersMode,
|
|
1067
|
+
spatialFilter
|
|
1068
|
+
},
|
|
1069
|
+
params: {
|
|
1070
|
+
column,
|
|
1071
|
+
stepSize,
|
|
1072
|
+
stepMultiplier,
|
|
1073
|
+
operationColumn: operationColumn || column,
|
|
1074
|
+
joinOperation,
|
|
1075
|
+
operation,
|
|
1076
|
+
splitByCategory,
|
|
1077
|
+
splitByCategoryLimit,
|
|
1078
|
+
splitByCategoryValues
|
|
1079
|
+
},
|
|
1080
|
+
opts: { abortController, headers: this._headers }
|
|
1081
|
+
}).then((res) => ({
|
|
1082
|
+
rows: normalizeObjectKeys(res.rows),
|
|
1083
|
+
categories: res.metadata?.categories
|
|
1084
|
+
}));
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
|
|
1088
|
+
// src/widget-sources/widget-query-source.ts
|
|
1089
|
+
var WidgetQuerySource = class extends WidgetRemoteSource {
|
|
1090
|
+
getModelSource(filters, filterOwner) {
|
|
1091
|
+
return {
|
|
1092
|
+
...super._getModelSource(filters, filterOwner),
|
|
1093
|
+
type: "query",
|
|
1094
|
+
data: this.props.sqlQuery,
|
|
1095
|
+
queryParameters: this.props.queryParameters
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
// src/widget-sources/widget-table-source.ts
|
|
1101
|
+
var WidgetTableSource = class extends WidgetRemoteSource {
|
|
1102
|
+
getModelSource(filters, filterOwner) {
|
|
1103
|
+
return {
|
|
1104
|
+
...super._getModelSource(filters, filterOwner),
|
|
1105
|
+
type: "table",
|
|
1106
|
+
data: this.props.tableName
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
|
|
1111
|
+
// src/widget-sources/widget-tileset-worker-source.ts
|
|
1112
|
+
var _WidgetTilesetWorkerSource = class _WidgetTilesetWorkerSource extends WidgetSource {
|
|
1113
|
+
constructor(props) {
|
|
1114
|
+
super(props);
|
|
1115
|
+
_WidgetTilesetWorkerSource.init();
|
|
1116
|
+
_WidgetTilesetWorkerSource.WORKER.postMessage({
|
|
1117
|
+
tableName: this.props.tableName,
|
|
1118
|
+
method: "init" /* INIT */,
|
|
1119
|
+
params: [this.props]
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Loads features as a list of tiles (typically provided by deck.gl).
|
|
1124
|
+
* After tiles are loaded, {@link extractTileFeatures} must be called
|
|
1125
|
+
* before computing statistics on the tiles.
|
|
1126
|
+
*/
|
|
1127
|
+
loadTiles(tiles) {
|
|
1128
|
+
tiles = tiles.map(({ id, bbox, data }) => ({
|
|
1129
|
+
id,
|
|
1130
|
+
bbox,
|
|
1131
|
+
data
|
|
1132
|
+
}));
|
|
1133
|
+
_WidgetTilesetWorkerSource.WORKER.postMessage({
|
|
1134
|
+
tableName: this.props.tableName,
|
|
1135
|
+
method: "loadTiles" /* LOAD_TILES */,
|
|
1136
|
+
params: [tiles]
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
/** Configures options used to extract features from tiles. */
|
|
1140
|
+
setTileFeatureExtractOptions(options) {
|
|
1141
|
+
_WidgetTilesetWorkerSource.WORKER.postMessage({
|
|
1142
|
+
tableName: this.props.tableName,
|
|
1143
|
+
type: "setTileFeatureExtractOptions" /* SET_TILE_FEATURE_EXTRACT_OPTIONS */,
|
|
1144
|
+
params: [options]
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Loads features as GeoJSON (used for testing).
|
|
1149
|
+
* @experimental
|
|
1150
|
+
* @internal Not for public use. Spatial filters in other method calls will be ignored.
|
|
1151
|
+
*/
|
|
1152
|
+
loadGeoJSON({
|
|
1153
|
+
geojson,
|
|
1154
|
+
spatialFilter
|
|
1155
|
+
}) {
|
|
1156
|
+
_WidgetTilesetWorkerSource.WORKER.postMessage({
|
|
1157
|
+
tableName: this.props.tableName,
|
|
1158
|
+
method: "loadGeoJSON" /* LOAD_GEOJSON */,
|
|
1159
|
+
params: [{ geojson, spatialFilter }]
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
1163
|
+
async getFeatures() {
|
|
1164
|
+
throw new Error("getFeatures not supported for tilesets");
|
|
1165
|
+
}
|
|
1166
|
+
async getFormula({
|
|
1167
|
+
abortController,
|
|
1168
|
+
...options
|
|
1169
|
+
}) {
|
|
1170
|
+
return this._executeWorkerMethod(
|
|
1171
|
+
this.props.tableName,
|
|
1172
|
+
"getFormula" /* GET_FORMULA */,
|
|
1173
|
+
[options],
|
|
1174
|
+
abortController?.signal
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
async getHistogram({
|
|
1178
|
+
abortController,
|
|
1179
|
+
...options
|
|
1180
|
+
}) {
|
|
1181
|
+
return this._executeWorkerMethod(
|
|
1182
|
+
this.props.tableName,
|
|
1183
|
+
"getHistogram" /* GET_HISTOGRAM */,
|
|
1184
|
+
[options],
|
|
1185
|
+
abortController?.signal
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
async getCategories({
|
|
1189
|
+
abortController,
|
|
1190
|
+
...options
|
|
1191
|
+
}) {
|
|
1192
|
+
return this._executeWorkerMethod(
|
|
1193
|
+
this.props.tableName,
|
|
1194
|
+
"getCategories" /* GET_CATEGORIES */,
|
|
1195
|
+
[options],
|
|
1196
|
+
abortController?.signal
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
async getScatter({
|
|
1200
|
+
abortController,
|
|
1201
|
+
...options
|
|
1202
|
+
}) {
|
|
1203
|
+
return this._executeWorkerMethod(
|
|
1204
|
+
this.props.tableName,
|
|
1205
|
+
"getScatter" /* GET_SCATTER */,
|
|
1206
|
+
[options],
|
|
1207
|
+
abortController?.signal
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
async getTable({
|
|
1211
|
+
abortController,
|
|
1212
|
+
...options
|
|
1213
|
+
}) {
|
|
1214
|
+
return this._executeWorkerMethod(
|
|
1215
|
+
this.props.tableName,
|
|
1216
|
+
"getTable" /* GET_TABLE */,
|
|
1217
|
+
[options],
|
|
1218
|
+
abortController?.signal
|
|
1219
|
+
);
|
|
1220
|
+
}
|
|
1221
|
+
async getTimeSeries({
|
|
1222
|
+
abortController,
|
|
1223
|
+
...options
|
|
1224
|
+
}) {
|
|
1225
|
+
return this._executeWorkerMethod(
|
|
1226
|
+
this.props.tableName,
|
|
1227
|
+
"getTimeSeries" /* GET_TIME_SERIES */,
|
|
1228
|
+
[options],
|
|
1229
|
+
abortController?.signal
|
|
1230
|
+
);
|
|
1231
|
+
}
|
|
1232
|
+
async getRange({
|
|
1233
|
+
abortController,
|
|
1234
|
+
...options
|
|
1235
|
+
}) {
|
|
1236
|
+
return this._executeWorkerMethod(
|
|
1237
|
+
this.props.tableName,
|
|
1238
|
+
"getRange" /* GET_RANGE */,
|
|
1239
|
+
[options],
|
|
1240
|
+
abortController?.signal
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
static init() {
|
|
1244
|
+
_WidgetTilesetWorkerSource.WORKER = new Worker(
|
|
1245
|
+
new URL("@carto/api-client/worker", import.meta.url),
|
|
1246
|
+
{
|
|
1247
|
+
type: "module",
|
|
1248
|
+
name: "cartowidgettileset"
|
|
1249
|
+
}
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
_executeWorkerMethod(tableName, method, params, signal) {
|
|
1253
|
+
const worker = _WidgetTilesetWorkerSource.WORKER;
|
|
1254
|
+
const requestId = _WidgetTilesetWorkerSource._nextRequestID++;
|
|
1255
|
+
const options = params[0];
|
|
1256
|
+
if (options?.spatialIndexReferenceViewState) {
|
|
1257
|
+
const { zoom, latitude, longitude } = options.spatialIndexReferenceViewState;
|
|
1258
|
+
options.spatialIndexReferenceViewState = { zoom, latitude, longitude };
|
|
1259
|
+
}
|
|
1260
|
+
worker.postMessage({
|
|
1261
|
+
requestId,
|
|
1262
|
+
tableName,
|
|
1263
|
+
method,
|
|
1264
|
+
params
|
|
1265
|
+
});
|
|
1266
|
+
return new Promise((resolve, reject) => {
|
|
1267
|
+
function listener(e) {
|
|
1268
|
+
const response = e.data;
|
|
1269
|
+
if (response.requestId !== requestId) return;
|
|
1270
|
+
worker.removeEventListener("message", listener);
|
|
1271
|
+
if (signal?.aborted) {
|
|
1272
|
+
reject(new Error(signal.reason));
|
|
1273
|
+
} else if (response.ok) {
|
|
1274
|
+
resolve(response.result);
|
|
1275
|
+
} else {
|
|
1276
|
+
reject(new Error(response.error));
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
worker.addEventListener("message", listener);
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
1284
|
+
// WEB WORKER MANAGEMENT
|
|
1285
|
+
// TODO: Singleton? Pool shared among datasets? One per dataset?
|
|
1286
|
+
__publicField(_WidgetTilesetWorkerSource, "WORKER");
|
|
1287
|
+
__publicField(_WidgetTilesetWorkerSource, "_nextRequestID", 1);
|
|
1288
|
+
var WidgetTilesetWorkerSource = _WidgetTilesetWorkerSource;
|
|
1289
|
+
|
|
1290
|
+
// src/sources/h3-query-source.ts
|
|
1291
|
+
var h3QuerySource = async function(options) {
|
|
1292
|
+
const {
|
|
1293
|
+
aggregationExp,
|
|
1294
|
+
aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
|
|
1295
|
+
sqlQuery,
|
|
1296
|
+
spatialDataColumn = "h3",
|
|
1297
|
+
queryParameters,
|
|
1298
|
+
filters
|
|
1299
|
+
} = options;
|
|
1300
|
+
const spatialDataType = "h3";
|
|
1301
|
+
const urlParameters = {
|
|
1302
|
+
aggregationExp,
|
|
1303
|
+
spatialDataColumn,
|
|
1304
|
+
spatialDataType,
|
|
1305
|
+
q: sqlQuery
|
|
1306
|
+
};
|
|
1307
|
+
if (aggregationResLevel) {
|
|
1308
|
+
urlParameters.aggregationResLevel = String(aggregationResLevel);
|
|
1309
|
+
}
|
|
1310
|
+
if (queryParameters) {
|
|
1311
|
+
urlParameters.queryParameters = queryParameters;
|
|
1312
|
+
}
|
|
1313
|
+
if (filters) {
|
|
1314
|
+
urlParameters.filters = filters;
|
|
1315
|
+
}
|
|
1316
|
+
return baseSource("query", options, urlParameters).then(
|
|
1317
|
+
(result) => ({
|
|
1318
|
+
...result,
|
|
1319
|
+
widgetSource: new WidgetQuerySource({
|
|
1320
|
+
...options,
|
|
1321
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
1322
|
+
spatialDataColumn,
|
|
1323
|
+
spatialDataType
|
|
1324
|
+
})
|
|
1325
|
+
})
|
|
1326
|
+
);
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
// src/sources/h3-table-source.ts
|
|
1330
|
+
var h3TableSource = async function(options) {
|
|
1331
|
+
const {
|
|
1332
|
+
aggregationExp,
|
|
1333
|
+
aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_H3,
|
|
1334
|
+
spatialDataColumn = "h3",
|
|
1335
|
+
tableName,
|
|
1336
|
+
filters
|
|
1337
|
+
} = options;
|
|
1338
|
+
const spatialDataType = "h3";
|
|
1339
|
+
const urlParameters = {
|
|
1340
|
+
aggregationExp,
|
|
1341
|
+
name: tableName,
|
|
1342
|
+
spatialDataColumn,
|
|
1343
|
+
spatialDataType
|
|
1344
|
+
};
|
|
1345
|
+
if (aggregationResLevel) {
|
|
1346
|
+
urlParameters.aggregationResLevel = String(aggregationResLevel);
|
|
1347
|
+
}
|
|
1348
|
+
if (filters) {
|
|
1349
|
+
urlParameters.filters = filters;
|
|
1350
|
+
}
|
|
1351
|
+
return baseSource("table", options, urlParameters).then(
|
|
1352
|
+
(result) => ({
|
|
1353
|
+
...result,
|
|
1354
|
+
widgetSource: new WidgetTableSource({
|
|
1355
|
+
...options,
|
|
1356
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
1357
|
+
spatialDataColumn,
|
|
1358
|
+
spatialDataType
|
|
1359
|
+
})
|
|
1360
|
+
})
|
|
1361
|
+
);
|
|
1362
|
+
};
|
|
1363
|
+
|
|
1364
|
+
// src/utils/getTileFormat.ts
|
|
1365
|
+
function getTileFormat(tilejson) {
|
|
1366
|
+
const tileParams = new URL(tilejson.tiles[0]).searchParams;
|
|
1367
|
+
return tileParams.get("formatTiles") === "mvt" ? "mvt" /* MVT */ : "binary" /* BINARY */;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// src/workers/utils.ts
|
|
1371
|
+
var _isModuleWorkerSupported = false ? false : null;
|
|
1372
|
+
function isModuleWorkerSupported() {
|
|
1373
|
+
if (_isModuleWorkerSupported !== null) {
|
|
1374
|
+
return _isModuleWorkerSupported;
|
|
1375
|
+
}
|
|
1376
|
+
try {
|
|
1377
|
+
new Worker("blob://", {
|
|
1378
|
+
get type() {
|
|
1379
|
+
_isModuleWorkerSupported = true;
|
|
1380
|
+
return "module";
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1383
|
+
} catch {
|
|
1384
|
+
} finally {
|
|
1385
|
+
_isModuleWorkerSupported || (_isModuleWorkerSupported = false);
|
|
1386
|
+
}
|
|
1387
|
+
return _isModuleWorkerSupported;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
// src/sources/h3-tileset-source.ts
|
|
1391
|
+
var h3TilesetSource = async function(options) {
|
|
1392
|
+
const { tableName, spatialDataColumn = "h3" } = options;
|
|
1393
|
+
const urlParameters = { name: tableName };
|
|
1394
|
+
const WidgetSourceClass = options.widgetSourceWorker !== false && isModuleWorkerSupported() ? WidgetTilesetWorkerSource : WidgetTilesetSource;
|
|
1395
|
+
return baseSource("tileset", options, urlParameters).then(
|
|
1396
|
+
(result) => ({
|
|
1397
|
+
...result,
|
|
1398
|
+
widgetSource: new WidgetSourceClass({
|
|
1399
|
+
...options,
|
|
1400
|
+
tileFormat: getTileFormat(result),
|
|
1401
|
+
spatialDataColumn,
|
|
1402
|
+
spatialDataType: "h3"
|
|
1403
|
+
})
|
|
1404
|
+
})
|
|
1405
|
+
);
|
|
1406
|
+
};
|
|
1407
|
+
|
|
1408
|
+
// src/sources/raster-source.ts
|
|
1409
|
+
var rasterSource = async function(options) {
|
|
1410
|
+
const { tableName, filters } = options;
|
|
1411
|
+
const urlParameters = { name: tableName };
|
|
1412
|
+
if (filters) {
|
|
1413
|
+
urlParameters.filters = filters;
|
|
1414
|
+
}
|
|
1415
|
+
return baseSource(
|
|
1416
|
+
"raster",
|
|
1417
|
+
options,
|
|
1418
|
+
urlParameters
|
|
1419
|
+
);
|
|
1420
|
+
};
|
|
1421
|
+
|
|
1422
|
+
// src/sources/quadbin-query-source.ts
|
|
1423
|
+
var quadbinQuerySource = async function(options) {
|
|
1424
|
+
const {
|
|
1425
|
+
aggregationExp,
|
|
1426
|
+
aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN,
|
|
1427
|
+
sqlQuery,
|
|
1428
|
+
spatialDataColumn = "quadbin",
|
|
1429
|
+
queryParameters,
|
|
1430
|
+
filters
|
|
1431
|
+
} = options;
|
|
1432
|
+
const spatialDataType = "quadbin";
|
|
1433
|
+
const urlParameters = {
|
|
1434
|
+
aggregationExp,
|
|
1435
|
+
q: sqlQuery,
|
|
1436
|
+
spatialDataColumn,
|
|
1437
|
+
spatialDataType
|
|
1438
|
+
};
|
|
1439
|
+
if (aggregationResLevel) {
|
|
1440
|
+
urlParameters.aggregationResLevel = String(aggregationResLevel);
|
|
1441
|
+
}
|
|
1442
|
+
if (queryParameters) {
|
|
1443
|
+
urlParameters.queryParameters = queryParameters;
|
|
1444
|
+
}
|
|
1445
|
+
if (filters) {
|
|
1446
|
+
urlParameters.filters = filters;
|
|
1447
|
+
}
|
|
1448
|
+
return baseSource("query", options, urlParameters).then(
|
|
1449
|
+
(result) => ({
|
|
1450
|
+
...result,
|
|
1451
|
+
widgetSource: new WidgetQuerySource({
|
|
1452
|
+
...options,
|
|
1453
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
1454
|
+
spatialDataColumn,
|
|
1455
|
+
spatialDataType
|
|
1456
|
+
})
|
|
1457
|
+
})
|
|
1458
|
+
);
|
|
1459
|
+
};
|
|
1460
|
+
|
|
1461
|
+
// src/sources/quadbin-table-source.ts
|
|
1462
|
+
var quadbinTableSource = async function(options) {
|
|
1463
|
+
const {
|
|
1464
|
+
aggregationExp,
|
|
1465
|
+
aggregationResLevel = DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN,
|
|
1466
|
+
spatialDataColumn = "quadbin",
|
|
1467
|
+
tableName,
|
|
1468
|
+
filters
|
|
1469
|
+
} = options;
|
|
1470
|
+
const spatialDataType = "quadbin";
|
|
1471
|
+
const urlParameters = {
|
|
1472
|
+
aggregationExp,
|
|
1473
|
+
name: tableName,
|
|
1474
|
+
spatialDataColumn,
|
|
1475
|
+
spatialDataType
|
|
1476
|
+
};
|
|
1477
|
+
if (aggregationResLevel) {
|
|
1478
|
+
urlParameters.aggregationResLevel = String(aggregationResLevel);
|
|
1479
|
+
}
|
|
1480
|
+
if (filters) {
|
|
1481
|
+
urlParameters.filters = filters;
|
|
1482
|
+
}
|
|
1483
|
+
return baseSource("table", options, urlParameters).then(
|
|
1484
|
+
(result) => ({
|
|
1485
|
+
...result,
|
|
1486
|
+
widgetSource: new WidgetTableSource({
|
|
1487
|
+
...options,
|
|
1488
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
1489
|
+
spatialDataColumn,
|
|
1490
|
+
spatialDataType
|
|
1491
|
+
})
|
|
1492
|
+
})
|
|
1493
|
+
);
|
|
1494
|
+
};
|
|
1495
|
+
|
|
1496
|
+
// src/sources/quadbin-tileset-source.ts
|
|
1497
|
+
var quadbinTilesetSource = async function(options) {
|
|
1498
|
+
const { tableName, spatialDataColumn = "quadbin" } = options;
|
|
1499
|
+
const urlParameters = { name: tableName };
|
|
1500
|
+
const WidgetSourceClass = options.widgetSourceWorker !== false && isModuleWorkerSupported() ? WidgetTilesetWorkerSource : WidgetTilesetSource;
|
|
1501
|
+
return baseSource("tileset", options, urlParameters).then(
|
|
1502
|
+
(result) => ({
|
|
1503
|
+
...result,
|
|
1504
|
+
widgetSource: new WidgetSourceClass({
|
|
1505
|
+
...options,
|
|
1506
|
+
tileFormat: getTileFormat(result),
|
|
1507
|
+
spatialDataColumn,
|
|
1508
|
+
spatialDataType: "quadbin"
|
|
1509
|
+
})
|
|
1510
|
+
})
|
|
1511
|
+
);
|
|
1512
|
+
};
|
|
1513
|
+
|
|
1514
|
+
// src/sources/vector-query-source.ts
|
|
1515
|
+
var vectorQuerySource = async function(options) {
|
|
1516
|
+
const {
|
|
1517
|
+
columns,
|
|
1518
|
+
filters,
|
|
1519
|
+
spatialDataColumn = DEFAULT_GEO_COLUMN,
|
|
1520
|
+
sqlQuery,
|
|
1521
|
+
tileResolution = DEFAULT_TILE_RESOLUTION,
|
|
1522
|
+
queryParameters,
|
|
1523
|
+
aggregationExp
|
|
1524
|
+
} = options;
|
|
1525
|
+
const spatialDataType = "geo";
|
|
1526
|
+
const urlParameters = {
|
|
1527
|
+
spatialDataColumn,
|
|
1528
|
+
spatialDataType,
|
|
1529
|
+
tileResolution: tileResolution.toString(),
|
|
1530
|
+
q: sqlQuery
|
|
1531
|
+
};
|
|
1532
|
+
if (columns) {
|
|
1533
|
+
urlParameters.columns = columns.join(",");
|
|
1534
|
+
}
|
|
1535
|
+
if (filters) {
|
|
1536
|
+
urlParameters.filters = filters;
|
|
1537
|
+
}
|
|
1538
|
+
if (queryParameters) {
|
|
1539
|
+
urlParameters.queryParameters = queryParameters;
|
|
1540
|
+
}
|
|
1541
|
+
if (aggregationExp) {
|
|
1542
|
+
urlParameters.aggregationExp = aggregationExp;
|
|
1543
|
+
}
|
|
1544
|
+
return baseSource("query", options, urlParameters).then(
|
|
1545
|
+
(result) => ({
|
|
1546
|
+
...result,
|
|
1547
|
+
widgetSource: new WidgetQuerySource({
|
|
1548
|
+
...options,
|
|
1549
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
1550
|
+
spatialDataColumn,
|
|
1551
|
+
spatialDataType,
|
|
1552
|
+
tileResolution
|
|
1553
|
+
})
|
|
1554
|
+
})
|
|
1555
|
+
);
|
|
1556
|
+
};
|
|
1557
|
+
|
|
1558
|
+
// src/sources/vector-table-source.ts
|
|
1559
|
+
var vectorTableSource = async function(options) {
|
|
1560
|
+
const {
|
|
1561
|
+
columns,
|
|
1562
|
+
filters,
|
|
1563
|
+
spatialDataColumn = DEFAULT_GEO_COLUMN,
|
|
1564
|
+
tableName,
|
|
1565
|
+
tileResolution = DEFAULT_TILE_RESOLUTION,
|
|
1566
|
+
aggregationExp
|
|
1567
|
+
} = options;
|
|
1568
|
+
const spatialDataType = "geo";
|
|
1569
|
+
const urlParameters = {
|
|
1570
|
+
name: tableName,
|
|
1571
|
+
spatialDataColumn,
|
|
1572
|
+
spatialDataType,
|
|
1573
|
+
tileResolution: tileResolution.toString()
|
|
1574
|
+
};
|
|
1575
|
+
if (columns) {
|
|
1576
|
+
urlParameters.columns = columns.join(",");
|
|
1577
|
+
}
|
|
1578
|
+
if (filters) {
|
|
1579
|
+
urlParameters.filters = filters;
|
|
1580
|
+
}
|
|
1581
|
+
if (aggregationExp) {
|
|
1582
|
+
urlParameters.aggregationExp = aggregationExp;
|
|
1583
|
+
}
|
|
1584
|
+
return baseSource("table", options, urlParameters).then(
|
|
1585
|
+
(result) => ({
|
|
1586
|
+
...result,
|
|
1587
|
+
widgetSource: new WidgetTableSource({
|
|
1588
|
+
...options,
|
|
1589
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
1590
|
+
spatialDataColumn,
|
|
1591
|
+
spatialDataType,
|
|
1592
|
+
tileResolution
|
|
1593
|
+
})
|
|
1594
|
+
})
|
|
1595
|
+
);
|
|
1596
|
+
};
|
|
1597
|
+
|
|
1598
|
+
// src/sources/vector-tileset-source.ts
|
|
1599
|
+
var vectorTilesetSource = async function(options) {
|
|
1600
|
+
const { tableName, spatialDataColumn = DEFAULT_GEO_COLUMN } = options;
|
|
1601
|
+
const urlParameters = { name: tableName };
|
|
1602
|
+
const WidgetSourceClass = options.widgetSourceWorker !== false && isModuleWorkerSupported() ? WidgetTilesetWorkerSource : WidgetTilesetSource;
|
|
1603
|
+
return baseSource("tileset", options, urlParameters).then(
|
|
1604
|
+
(result) => ({
|
|
1605
|
+
...result,
|
|
1606
|
+
widgetSource: new WidgetSourceClass({
|
|
1607
|
+
...options,
|
|
1608
|
+
tileFormat: getTileFormat(result),
|
|
1609
|
+
spatialDataColumn,
|
|
1610
|
+
spatialDataType: "geo"
|
|
1611
|
+
})
|
|
1612
|
+
})
|
|
1613
|
+
);
|
|
1614
|
+
};
|
|
1615
|
+
|
|
1616
|
+
// src/api/query.ts
|
|
1617
|
+
var query = async function(options) {
|
|
1618
|
+
const {
|
|
1619
|
+
apiBaseUrl = SOURCE_DEFAULTS.apiBaseUrl,
|
|
1620
|
+
clientId = SOURCE_DEFAULTS.clientId,
|
|
1621
|
+
maxLengthURL = SOURCE_DEFAULTS.maxLengthURL,
|
|
1622
|
+
localCache,
|
|
1623
|
+
connectionName,
|
|
1624
|
+
sqlQuery,
|
|
1625
|
+
queryParameters
|
|
1626
|
+
} = options;
|
|
1627
|
+
const urlParameters = { q: sqlQuery };
|
|
1628
|
+
if (queryParameters) {
|
|
1629
|
+
urlParameters.queryParameters = JSON.stringify(queryParameters);
|
|
1630
|
+
}
|
|
1631
|
+
const baseUrl = buildQueryUrl({ apiBaseUrl, connectionName });
|
|
1632
|
+
const headers = {
|
|
1633
|
+
Authorization: `Bearer ${options.accessToken}`,
|
|
1634
|
+
...options.headers
|
|
1635
|
+
};
|
|
1636
|
+
const parameters = { client: clientId, ...urlParameters };
|
|
1637
|
+
const errorContext = {
|
|
1638
|
+
requestType: "SQL",
|
|
1639
|
+
connection: options.connectionName,
|
|
1640
|
+
type: "query",
|
|
1641
|
+
source: JSON.stringify(parameters, void 0, 2)
|
|
1642
|
+
};
|
|
1643
|
+
return await requestWithParameters({
|
|
1644
|
+
baseUrl,
|
|
1645
|
+
parameters,
|
|
1646
|
+
headers,
|
|
1647
|
+
errorContext,
|
|
1648
|
+
maxLengthURL,
|
|
1649
|
+
localCache
|
|
1650
|
+
});
|
|
1651
|
+
};
|
|
1652
|
+
export {
|
|
1653
|
+
ApiVersion,
|
|
1654
|
+
CartoAPIError,
|
|
1655
|
+
DEFAULT_API_BASE_URL,
|
|
1656
|
+
FEATURE_GEOM_PROPERTY,
|
|
1657
|
+
FilterType,
|
|
1658
|
+
Provider,
|
|
1659
|
+
SOURCE_DEFAULTS,
|
|
1660
|
+
SpatialIndex,
|
|
1661
|
+
TileFormat,
|
|
1662
|
+
WidgetQuerySource,
|
|
1663
|
+
WidgetRemoteSource,
|
|
1664
|
+
WidgetSource,
|
|
1665
|
+
WidgetTableSource,
|
|
1666
|
+
WidgetTilesetSource,
|
|
1667
|
+
WidgetTilesetWorkerSource,
|
|
1668
|
+
_buildFeatureFilter,
|
|
1669
|
+
_getHexagonResolution,
|
|
1670
|
+
addFilter,
|
|
1671
|
+
aggregate,
|
|
1672
|
+
aggregationFunctions,
|
|
1673
|
+
applyFilters,
|
|
1674
|
+
applySorting,
|
|
1675
|
+
boundaryQuerySource,
|
|
1676
|
+
boundaryTableSource,
|
|
1677
|
+
buildBinaryFeatureFilter,
|
|
1678
|
+
buildPublicMapUrl,
|
|
1679
|
+
buildStatsUrl,
|
|
1680
|
+
clearFilters,
|
|
1681
|
+
createPolygonSpatialFilter,
|
|
1682
|
+
createViewportSpatialFilter,
|
|
1683
|
+
filterFunctions,
|
|
1684
|
+
geojsonFeatures,
|
|
1685
|
+
getClient,
|
|
1686
|
+
getDataFilterExtensionProps,
|
|
1687
|
+
getFilter,
|
|
1688
|
+
groupValuesByColumn,
|
|
1689
|
+
groupValuesByDateColumn,
|
|
1690
|
+
h3QuerySource,
|
|
1691
|
+
h3TableSource,
|
|
1692
|
+
h3TilesetSource,
|
|
1693
|
+
hasFilter,
|
|
1694
|
+
histogram,
|
|
1695
|
+
makeIntervalComplete,
|
|
1696
|
+
quadbinQuerySource,
|
|
1697
|
+
quadbinTableSource,
|
|
1698
|
+
quadbinTilesetSource,
|
|
1699
|
+
query,
|
|
1700
|
+
rasterSource,
|
|
1701
|
+
removeFilter,
|
|
1702
|
+
requestWithParameters,
|
|
1703
|
+
scatterPlot,
|
|
1704
|
+
setClient,
|
|
1705
|
+
tileFeatures,
|
|
1706
|
+
tileFeaturesGeometries,
|
|
1707
|
+
tileFeaturesSpatialIndex,
|
|
1708
|
+
transformToTileCoords,
|
|
1709
|
+
vectorQuerySource,
|
|
1710
|
+
vectorTableSource,
|
|
1711
|
+
vectorTilesetSource
|
|
1712
|
+
};
|