@carto/api-client 0.5.15-alpha.raster-5 → 0.5.16
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 +9 -0
- package/build/api-client.cjs +325 -979
- package/build/api-client.cjs.map +1 -1
- package/build/api-client.d.cts +87 -154
- package/build/api-client.d.ts +87 -154
- package/build/api-client.js +319 -965
- package/build/api-client.js.map +1 -1
- package/build/worker-compat.js +1395 -1276
- package/build/worker-compat.js.map +1 -1
- package/build/worker.js +34 -0
- package/build/worker.js.map +1 -1
- package/package.json +3 -5
- package/src/fetch-map/basemap-styles.ts +1 -1
- package/src/fetch-map/index.ts +1 -6
- package/src/fetch-map/layer-map.ts +40 -130
- package/src/fetch-map/parse-map.ts +165 -284
- package/src/fetch-map/types.ts +7 -21
- package/src/fetch-map/utils.ts +0 -56
- package/src/index.ts +1 -7
- package/src/models/model.ts +1 -0
- package/src/sources/index.ts +12 -0
- package/src/sources/trajectory-query-source.ts +101 -0
- package/src/sources/trajectory-table-source.ts +96 -0
- package/src/sources/types.ts +12 -53
- package/src/widget-sources/types.ts +29 -1
- package/src/widget-sources/widget-remote-source.ts +30 -0
- package/src/widget-sources/widget-source.ts +11 -0
- package/src/widget-sources/widget-tileset-source-impl.ts +49 -0
- package/src/widget-sources/widget-tileset-source.ts +13 -0
- package/src/workers/constants.ts +1 -0
- package/src/fetch-map/raster-layer.ts +0 -536
- package/src/fetch-map/vec-expr-evaluator.ts +0 -374
package/src/index.ts
CHANGED
|
@@ -2,13 +2,7 @@ export * from './client.js';
|
|
|
2
2
|
export * from './constants.js';
|
|
3
3
|
export * from './deck/index.js';
|
|
4
4
|
export * from './fetch-map/index.js';
|
|
5
|
-
export {
|
|
6
|
-
createVecExprEvaluator as _createVecExprEvaluator,
|
|
7
|
-
evaluateVecExpr as _evaluateVecExpr,
|
|
8
|
-
validateVecExprSyntax as _validateVecExprSyntax,
|
|
9
|
-
type VecExprResult as _VecExprResult,
|
|
10
|
-
ErrorCode as _ErrorCode,
|
|
11
|
-
} from './fetch-map/vec-expr-evaluator.js';
|
|
5
|
+
export type {LayerDescriptor, LayerType} from './fetch-map/index.js';
|
|
12
6
|
export * from './filters.js';
|
|
13
7
|
export * from './geo.js';
|
|
14
8
|
export * from './sources/index.js';
|
package/src/models/model.ts
CHANGED
package/src/sources/index.ts
CHANGED
|
@@ -97,3 +97,15 @@ export type {
|
|
|
97
97
|
VectorTilesetSourceOptions,
|
|
98
98
|
VectorTilesetSourceResponse,
|
|
99
99
|
} from './vector-tileset-source.js';
|
|
100
|
+
|
|
101
|
+
export {trajectoryQuerySource} from './trajectory-query-source.js';
|
|
102
|
+
export type {
|
|
103
|
+
TrajectoryQuerySourceOptions,
|
|
104
|
+
TrajectoryQuerySourceResponse,
|
|
105
|
+
} from './trajectory-query-source.js';
|
|
106
|
+
|
|
107
|
+
export {trajectoryTableSource} from './trajectory-table-source.js';
|
|
108
|
+
export type {
|
|
109
|
+
TrajectoryTableSourceOptions,
|
|
110
|
+
TrajectoryTableSourceResponse,
|
|
111
|
+
} from './trajectory-table-source.js';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_GEO_COLUMN,
|
|
3
|
+
DEFAULT_TILE_RESOLUTION,
|
|
4
|
+
} from '../constants-internal.js';
|
|
5
|
+
import {
|
|
6
|
+
WidgetQuerySource,
|
|
7
|
+
type RangeResponse,
|
|
8
|
+
type WidgetQuerySourceResult,
|
|
9
|
+
} from '../widget-sources/index.js';
|
|
10
|
+
import {baseSource} from './base-source.js';
|
|
11
|
+
import type {
|
|
12
|
+
SourceOptions,
|
|
13
|
+
QuerySourceOptions,
|
|
14
|
+
SpatialDataType,
|
|
15
|
+
TilejsonResult,
|
|
16
|
+
ColumnsOption,
|
|
17
|
+
} from './types.js';
|
|
18
|
+
|
|
19
|
+
export type TrajectoryQuerySourceOptions = SourceOptions &
|
|
20
|
+
QuerySourceOptions &
|
|
21
|
+
ColumnsOption & {
|
|
22
|
+
/** Column name containing the trajectory identifier */
|
|
23
|
+
trajectoryIdColumn: string;
|
|
24
|
+
/** Column name containing the timestamp */
|
|
25
|
+
timestampColumn: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type UrlParameters = {
|
|
29
|
+
columns?: string;
|
|
30
|
+
spatialDataType: SpatialDataType;
|
|
31
|
+
spatialDataColumn?: string;
|
|
32
|
+
tileResolution?: string;
|
|
33
|
+
q: string;
|
|
34
|
+
queryParameters?: Record<string, unknown> | unknown[];
|
|
35
|
+
aggregationExp?: string;
|
|
36
|
+
trajectoryIdColumn: string;
|
|
37
|
+
timestampColumn: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type TrajectoryQuerySourceResponse = TilejsonResult &
|
|
41
|
+
WidgetQuerySourceResult & {
|
|
42
|
+
timestampRange: RangeResponse;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const trajectoryQuerySource = async function (
|
|
46
|
+
options: TrajectoryQuerySourceOptions
|
|
47
|
+
): Promise<TrajectoryQuerySourceResponse> {
|
|
48
|
+
const {
|
|
49
|
+
columns,
|
|
50
|
+
spatialDataColumn = DEFAULT_GEO_COLUMN,
|
|
51
|
+
sqlQuery,
|
|
52
|
+
tileResolution = DEFAULT_TILE_RESOLUTION,
|
|
53
|
+
queryParameters,
|
|
54
|
+
aggregationExp,
|
|
55
|
+
trajectoryIdColumn,
|
|
56
|
+
timestampColumn,
|
|
57
|
+
} = options;
|
|
58
|
+
|
|
59
|
+
const spatialDataType = 'trajectory';
|
|
60
|
+
|
|
61
|
+
const urlParameters: UrlParameters = {
|
|
62
|
+
spatialDataColumn,
|
|
63
|
+
spatialDataType,
|
|
64
|
+
tileResolution: tileResolution.toString(),
|
|
65
|
+
q: sqlQuery,
|
|
66
|
+
trajectoryIdColumn,
|
|
67
|
+
timestampColumn,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (columns) {
|
|
71
|
+
urlParameters.columns = columns.join(',');
|
|
72
|
+
}
|
|
73
|
+
if (queryParameters) {
|
|
74
|
+
urlParameters.queryParameters = queryParameters;
|
|
75
|
+
}
|
|
76
|
+
if (aggregationExp) {
|
|
77
|
+
urlParameters.aggregationExp = aggregationExp;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const result = await baseSource<UrlParameters>(
|
|
81
|
+
'query',
|
|
82
|
+
options,
|
|
83
|
+
urlParameters
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const widgetSource = new WidgetQuerySource({
|
|
87
|
+
...options,
|
|
88
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
89
|
+
spatialDataColumn,
|
|
90
|
+
spatialDataType,
|
|
91
|
+
tileResolution,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const timestampRange = await widgetSource.getRange({column: timestampColumn});
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
...result,
|
|
98
|
+
widgetSource,
|
|
99
|
+
timestampRange,
|
|
100
|
+
};
|
|
101
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_GEO_COLUMN,
|
|
3
|
+
DEFAULT_TILE_RESOLUTION,
|
|
4
|
+
} from '../constants-internal.js';
|
|
5
|
+
import {
|
|
6
|
+
WidgetTableSource,
|
|
7
|
+
type RangeResponse,
|
|
8
|
+
type WidgetTableSourceResult,
|
|
9
|
+
} from '../widget-sources/index.js';
|
|
10
|
+
import {baseSource} from './base-source.js';
|
|
11
|
+
import type {
|
|
12
|
+
ColumnsOption,
|
|
13
|
+
SourceOptions,
|
|
14
|
+
SpatialDataType,
|
|
15
|
+
TableSourceOptions,
|
|
16
|
+
TilejsonResult,
|
|
17
|
+
} from './types.js';
|
|
18
|
+
|
|
19
|
+
export type TrajectoryTableSourceOptions = SourceOptions &
|
|
20
|
+
TableSourceOptions &
|
|
21
|
+
ColumnsOption & {
|
|
22
|
+
/** Column name containing the trajectory identifier */
|
|
23
|
+
trajectoryIdColumn: string;
|
|
24
|
+
/** Column name containing the timestamp */
|
|
25
|
+
timestampColumn: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type UrlParameters = {
|
|
29
|
+
columns?: string;
|
|
30
|
+
spatialDataType: SpatialDataType;
|
|
31
|
+
spatialDataColumn?: string;
|
|
32
|
+
tileResolution?: string;
|
|
33
|
+
name: string;
|
|
34
|
+
aggregationExp?: string;
|
|
35
|
+
trajectoryIdColumn: string;
|
|
36
|
+
timestampColumn: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type TrajectoryTableSourceResponse = TilejsonResult &
|
|
40
|
+
WidgetTableSourceResult & {
|
|
41
|
+
timestampRange: RangeResponse;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const trajectoryTableSource = async function (
|
|
45
|
+
options: TrajectoryTableSourceOptions
|
|
46
|
+
): Promise<TrajectoryTableSourceResponse> {
|
|
47
|
+
const {
|
|
48
|
+
columns,
|
|
49
|
+
spatialDataColumn = DEFAULT_GEO_COLUMN,
|
|
50
|
+
tableName,
|
|
51
|
+
tileResolution = DEFAULT_TILE_RESOLUTION,
|
|
52
|
+
aggregationExp,
|
|
53
|
+
trajectoryIdColumn,
|
|
54
|
+
timestampColumn,
|
|
55
|
+
} = options;
|
|
56
|
+
|
|
57
|
+
const spatialDataType = 'trajectory';
|
|
58
|
+
|
|
59
|
+
const urlParameters: UrlParameters = {
|
|
60
|
+
name: tableName,
|
|
61
|
+
spatialDataColumn,
|
|
62
|
+
spatialDataType,
|
|
63
|
+
tileResolution: tileResolution.toString(),
|
|
64
|
+
trajectoryIdColumn,
|
|
65
|
+
timestampColumn,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
if (columns) {
|
|
69
|
+
urlParameters.columns = columns.join(',');
|
|
70
|
+
}
|
|
71
|
+
if (aggregationExp) {
|
|
72
|
+
urlParameters.aggregationExp = aggregationExp;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const result = await baseSource<UrlParameters>(
|
|
76
|
+
'table',
|
|
77
|
+
options,
|
|
78
|
+
urlParameters
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const widgetSource = new WidgetTableSource({
|
|
82
|
+
...options,
|
|
83
|
+
// NOTE: Parameters with default values above must be explicitly passed here.
|
|
84
|
+
spatialDataColumn,
|
|
85
|
+
spatialDataType,
|
|
86
|
+
tileResolution,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const timestampRange = await widgetSource.getRange({column: timestampColumn});
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
...result,
|
|
93
|
+
widgetSource,
|
|
94
|
+
timestampRange,
|
|
95
|
+
};
|
|
96
|
+
};
|
package/src/sources/types.ts
CHANGED
|
@@ -211,7 +211,7 @@ export type ColumnsOption = {
|
|
|
211
211
|
columns?: string[];
|
|
212
212
|
};
|
|
213
213
|
|
|
214
|
-
export type SpatialDataType = 'geo' | 'h3' | 'quadbin';
|
|
214
|
+
export type SpatialDataType = 'geo' | 'h3' | 'quadbin' | 'trajectory';
|
|
215
215
|
|
|
216
216
|
/**
|
|
217
217
|
* Strategy used for covering spatial filter geometry with spatial indexes.
|
|
@@ -292,64 +292,14 @@ export interface Tilestats {
|
|
|
292
292
|
|
|
293
293
|
export interface Layer {
|
|
294
294
|
layer: string;
|
|
295
|
-
/** Number of features in the layer. */
|
|
296
295
|
count: number;
|
|
297
|
-
|
|
298
|
-
/** Number of attributes in the layer. */
|
|
299
296
|
attributeCount: number;
|
|
300
297
|
attributes: Attribute[];
|
|
301
|
-
|
|
302
|
-
/** Type of geometry as in geojson geometry type (Point, LineString, Polygon, etc.) */
|
|
303
|
-
geometry?: string;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
export interface AttributeCategoryItem {
|
|
307
|
-
category: string;
|
|
308
|
-
frequency: number;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Quantiles by number of buckets.
|
|
313
|
-
*
|
|
314
|
-
* Example:
|
|
315
|
-
* ```ts
|
|
316
|
-
* {
|
|
317
|
-
* // for 3 buckets, first 1/3 of items lies in range [min, 20], second 1/3 is in [20, 40], and last 1/3 is in [40, max]
|
|
318
|
-
* 3: [20, 40],
|
|
319
|
-
* 4: [20, 30, 50], for 4 buckets ...
|
|
320
|
-
* }
|
|
321
|
-
* ```
|
|
322
|
-
*/
|
|
323
|
-
export interface QuantileStats {
|
|
324
|
-
[bucketCount: number]: number[];
|
|
325
298
|
}
|
|
326
299
|
|
|
327
300
|
export interface Attribute {
|
|
328
|
-
/**
|
|
329
|
-
* String, Number, Timestamp, Boolean
|
|
330
|
-
*/
|
|
331
|
-
type: string;
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Attribute name.
|
|
335
|
-
*/
|
|
336
301
|
attribute: string;
|
|
337
|
-
|
|
338
|
-
// Stats for numeric attributes
|
|
339
|
-
min?: number;
|
|
340
|
-
max?: number;
|
|
341
|
-
sum?: number;
|
|
342
|
-
|
|
343
|
-
/** Quantiles by number of buckets */
|
|
344
|
-
quantiles?:
|
|
345
|
-
| {
|
|
346
|
-
// Quantile stats for numeric attributes in static spatial index tilesets are enclosed in extra global object
|
|
347
|
-
global: QuantileStats;
|
|
348
|
-
}
|
|
349
|
-
| QuantileStats;
|
|
350
|
-
|
|
351
|
-
// Stats for string/boolean attributes
|
|
352
|
-
categories?: AttributeCategoryItem[];
|
|
302
|
+
type: string;
|
|
353
303
|
}
|
|
354
304
|
|
|
355
305
|
export interface VectorLayer {
|
|
@@ -375,8 +325,17 @@ export type RasterMetadataBandStats = {
|
|
|
375
325
|
|
|
376
326
|
/**
|
|
377
327
|
* Quantiles by number of buckets.
|
|
328
|
+
*
|
|
329
|
+
* Example:
|
|
330
|
+
* ```ts
|
|
331
|
+
* {
|
|
332
|
+
* // for 3 buckets, first 1/3 of items lies in range [min, 20], second 1/3 is in [20, 40], and last 1/3 is in [40, max]
|
|
333
|
+
* 3: [20, 40],
|
|
334
|
+
* 4: [20, 30, 50], for 4 buckets ...
|
|
335
|
+
* }
|
|
336
|
+
* ```
|
|
378
337
|
*/
|
|
379
|
-
quantiles?:
|
|
338
|
+
quantiles?: Record<number, number[]>;
|
|
380
339
|
|
|
381
340
|
/**
|
|
382
341
|
* Top values by number of values.
|
|
@@ -207,6 +207,26 @@ export interface TimeSeriesRequestOptions extends BaseRequestOptions {
|
|
|
207
207
|
splitByCategoryValues?: string[];
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Examples:
|
|
212
|
+
* * aggregations with array syntax
|
|
213
|
+
* * aggregations: [{column: 'pop_high', operation: 'sum', alias: 'high_pop'}, {column: 'pop_low', operation: 'avg'}]
|
|
214
|
+
* * aggregations with string syntax
|
|
215
|
+
* * aggregations: 'sum(pop_high) as high_pop, avg(pop_low) as avg_low'
|
|
216
|
+
*
|
|
217
|
+
* Options for {@link WidgetRemoteSource#getAggregations}.
|
|
218
|
+
*/
|
|
219
|
+
export interface AggregationsRequestOptions extends BaseRequestOptions {
|
|
220
|
+
/** Aggregations to compute. Can be an array of objects or a SQL string expression. */
|
|
221
|
+
aggregations:
|
|
222
|
+
| {
|
|
223
|
+
column: string;
|
|
224
|
+
operation: Exclude<AggregationType, 'custom'>;
|
|
225
|
+
alias: string;
|
|
226
|
+
}[]
|
|
227
|
+
| string;
|
|
228
|
+
}
|
|
229
|
+
|
|
210
230
|
/** @experimental */
|
|
211
231
|
export type ExtentRequestOptions = BaseRequestOptions;
|
|
212
232
|
|
|
@@ -241,7 +261,10 @@ export type CategoryResponseRaw = {
|
|
|
241
261
|
};
|
|
242
262
|
|
|
243
263
|
/** Response from {@link WidgetRemoteSource#getRange}. */
|
|
244
|
-
export type RangeResponse =
|
|
264
|
+
export type RangeResponse =
|
|
265
|
+
| {min: number; max: number}
|
|
266
|
+
| {min: string; max: string}
|
|
267
|
+
| null;
|
|
245
268
|
|
|
246
269
|
/** Response from {@link WidgetRemoteSource#getTable}. */
|
|
247
270
|
export type TableResponse = {
|
|
@@ -261,5 +284,10 @@ export type TimeSeriesResponse = {
|
|
|
261
284
|
/** Response from {@link WidgetRemoteSource#getHistogram}. */
|
|
262
285
|
export type HistogramResponse = number[];
|
|
263
286
|
|
|
287
|
+
/** Response from {@link WidgetRemoteSource#getAggregations}. */
|
|
288
|
+
export type AggregationsResponse = {
|
|
289
|
+
rows: Record<string, number | string | null>[];
|
|
290
|
+
};
|
|
291
|
+
|
|
264
292
|
/** @experimental */
|
|
265
293
|
export type ExtentResponse = {bbox: BBox};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {executeModel, type ModelSource} from '../models/index.js';
|
|
2
2
|
import type {
|
|
3
|
+
AggregationsRequestOptions,
|
|
4
|
+
AggregationsResponse,
|
|
3
5
|
CategoryRequestOptions,
|
|
4
6
|
CategoryResponse,
|
|
5
7
|
ExtentRequestOptions,
|
|
@@ -394,6 +396,34 @@ export abstract class WidgetRemoteSource<
|
|
|
394
396
|
}));
|
|
395
397
|
}
|
|
396
398
|
|
|
399
|
+
async getAggregations(
|
|
400
|
+
options: AggregationsRequestOptions
|
|
401
|
+
): Promise<AggregationsResponse> {
|
|
402
|
+
const {
|
|
403
|
+
signal,
|
|
404
|
+
filters = this.props.filters,
|
|
405
|
+
filterOwner,
|
|
406
|
+
spatialFilter,
|
|
407
|
+
spatialFiltersMode,
|
|
408
|
+
aggregations,
|
|
409
|
+
} = options;
|
|
410
|
+
|
|
411
|
+
return executeModel({
|
|
412
|
+
model: 'aggregations',
|
|
413
|
+
source: {
|
|
414
|
+
...this.getModelSource(filters, filterOwner),
|
|
415
|
+
spatialFiltersMode,
|
|
416
|
+
spatialFilter,
|
|
417
|
+
},
|
|
418
|
+
params: {
|
|
419
|
+
aggregations,
|
|
420
|
+
},
|
|
421
|
+
opts: {signal, headers: this.props.headers},
|
|
422
|
+
}).then((res: AggregationsResponse) => ({
|
|
423
|
+
rows: res.rows.map((row) => normalizeObjectKeys(row)),
|
|
424
|
+
}));
|
|
425
|
+
}
|
|
426
|
+
|
|
397
427
|
/** @experimental */
|
|
398
428
|
async getExtent(options: ExtentRequestOptions = {}): Promise<ExtentResponse> {
|
|
399
429
|
const {signal, filters = this.props.filters, filterOwner} = options;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
AggregationsRequestOptions,
|
|
3
|
+
AggregationsResponse,
|
|
2
4
|
CategoryRequestOptions,
|
|
3
5
|
CategoryResponse,
|
|
4
6
|
ExtentRequestOptions,
|
|
@@ -127,6 +129,15 @@ export abstract class WidgetSource<
|
|
|
127
129
|
options: TimeSeriesRequestOptions
|
|
128
130
|
): Promise<TimeSeriesResponse>;
|
|
129
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Returns multiple aggregated values computed over matching data. Suitable
|
|
134
|
+
* for aggregated statistics from pivoted tables, such as H3 tables with
|
|
135
|
+
* pre-computed aggregations across multiple columns.
|
|
136
|
+
*/
|
|
137
|
+
abstract getAggregations(
|
|
138
|
+
options: AggregationsRequestOptions
|
|
139
|
+
): Promise<AggregationsResponse>;
|
|
140
|
+
|
|
130
141
|
/** @experimental */
|
|
131
142
|
abstract getExtent(options?: ExtentRequestOptions): Promise<ExtentResponse>;
|
|
132
143
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/require-await */
|
|
2
2
|
import type {
|
|
3
|
+
AggregationsRequestOptions,
|
|
4
|
+
AggregationsResponse,
|
|
3
5
|
CategoryRequestOptions,
|
|
4
6
|
CategoryResponse,
|
|
5
7
|
ExtentResponse,
|
|
@@ -148,6 +150,8 @@ export class WidgetTilesetSourceImpl extends WidgetSource<WidgetTilesetSourcePro
|
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
const targetOperation = aggregationFunctions[operation];
|
|
153
|
+
assert(targetOperation, `Unsupported aggregation operation: ${operation}`);
|
|
154
|
+
|
|
151
155
|
return {
|
|
152
156
|
value: targetOperation(filteredFeatures, column, joinOperation),
|
|
153
157
|
};
|
|
@@ -391,6 +395,51 @@ export class WidgetTilesetSourceImpl extends WidgetSource<WidgetTilesetSourcePro
|
|
|
391
395
|
};
|
|
392
396
|
}
|
|
393
397
|
|
|
398
|
+
async getAggregations({
|
|
399
|
+
aggregations,
|
|
400
|
+
filters,
|
|
401
|
+
filterOwner,
|
|
402
|
+
spatialFilter,
|
|
403
|
+
}: AggregationsRequestOptions): Promise<AggregationsResponse> {
|
|
404
|
+
const filteredFeatures = this._getFilteredFeatures(
|
|
405
|
+
spatialFilter,
|
|
406
|
+
filters,
|
|
407
|
+
filterOwner
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
if (!this._features.length) {
|
|
411
|
+
return {rows: []};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// SQL aggregations require remote execution, and are not supported for tilesets.
|
|
415
|
+
assert(
|
|
416
|
+
typeof aggregations !== 'string',
|
|
417
|
+
'Unsupported tileset SQL aggregation'
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
// Handle array-based aggregations
|
|
421
|
+
const result: Record<string, number> = {};
|
|
422
|
+
const usedAliases = new Set<string>();
|
|
423
|
+
|
|
424
|
+
for (const {column, operation, alias} of aggregations) {
|
|
425
|
+
// Column is required except when operation is 'count'.
|
|
426
|
+
if ((column && column !== '*') || operation !== AggregationTypes.Count) {
|
|
427
|
+
assertColumn(this._features, column);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const aliasKey = alias.toLowerCase();
|
|
431
|
+
assert(!usedAliases.has(aliasKey), `Duplicate alias: ${aliasKey}`);
|
|
432
|
+
usedAliases.add(aliasKey);
|
|
433
|
+
|
|
434
|
+
const targetOperation = aggregationFunctions[operation];
|
|
435
|
+
assert(targetOperation, `Unsupported operation: ${operation}`);
|
|
436
|
+
|
|
437
|
+
result[alias] = targetOperation(filteredFeatures, column);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return {rows: [result]};
|
|
441
|
+
}
|
|
442
|
+
|
|
394
443
|
/** @experimental */
|
|
395
444
|
async getExtent(): Promise<ExtentResponse> {
|
|
396
445
|
return Promise.reject(new Error('not implemented'));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
AggregationsRequestOptions,
|
|
3
|
+
AggregationsResponse,
|
|
2
4
|
CategoryRequestOptions,
|
|
3
5
|
CategoryResponse,
|
|
4
6
|
ExtentResponse,
|
|
@@ -326,6 +328,17 @@ export class WidgetTilesetSource<
|
|
|
326
328
|
return this._executeWorkerMethod(Method.GET_RANGE, [options], signal);
|
|
327
329
|
}
|
|
328
330
|
|
|
331
|
+
async getAggregations({
|
|
332
|
+
signal,
|
|
333
|
+
...options
|
|
334
|
+
}: AggregationsRequestOptions): Promise<AggregationsResponse> {
|
|
335
|
+
return this._executeWorkerMethod(
|
|
336
|
+
Method.GET_AGGREGATIONS,
|
|
337
|
+
[options],
|
|
338
|
+
signal
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
329
342
|
/** @experimental */
|
|
330
343
|
async getExtent(): Promise<ExtentResponse> {
|
|
331
344
|
return Promise.resolve({
|