@carto/api-client 0.5.15 → 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 +5 -0
- package/build/api-client.cjs +70 -1
- package/build/api-client.cjs.map +1 -1
- package/build/api-client.d.cts +33 -2
- package/build/api-client.d.ts +33 -2
- package/build/api-client.js +70 -1
- 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 +2 -2
- package/src/models/model.ts +1 -0
- package/src/widget-sources/types.ts +25 -0
- 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/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"homepage": "https://github.com/CartoDB/carto-api-client#readme",
|
|
9
9
|
"author": "Don McCurdy <donmccurdy@carto.com>",
|
|
10
10
|
"packageManager": "yarn@4.3.1",
|
|
11
|
-
"version": "0.5.
|
|
11
|
+
"version": "0.5.16",
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"rimraf": "^6.0.1",
|
|
122
122
|
"semver": "^7.7.1",
|
|
123
123
|
"thenby": "^1.3.4",
|
|
124
|
-
"tinybench": "^
|
|
124
|
+
"tinybench": "^5.0.1",
|
|
125
125
|
"tsup": "^8.3.6",
|
|
126
126
|
"typescript": "~5.9.2",
|
|
127
127
|
"typescript-eslint": "^8.26.1",
|
package/src/models/model.ts
CHANGED
|
@@ -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
|
|
|
@@ -264,5 +284,10 @@ export type TimeSeriesResponse = {
|
|
|
264
284
|
/** Response from {@link WidgetRemoteSource#getHistogram}. */
|
|
265
285
|
export type HistogramResponse = number[];
|
|
266
286
|
|
|
287
|
+
/** Response from {@link WidgetRemoteSource#getAggregations}. */
|
|
288
|
+
export type AggregationsResponse = {
|
|
289
|
+
rows: Record<string, number | string | null>[];
|
|
290
|
+
};
|
|
291
|
+
|
|
267
292
|
/** @experimental */
|
|
268
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({
|