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

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.
@@ -16,10 +16,9 @@ import {
16
16
  TableResponse,
17
17
  TimeSeriesRequestOptions,
18
18
  TimeSeriesResponse,
19
- ViewState,
20
19
  } from './types.js';
21
20
  import {FilterLogicalOperator, Filter} from '../types.js';
22
- import {assert, getApplicableFilters, normalizeObjectKeys} from '../utils.js';
21
+ import {getApplicableFilters, normalizeObjectKeys} from '../utils.js';
23
22
  import {getClient} from '../client.js';
24
23
  import {ModelSource} from '../models/model.js';
25
24
  import {SourceOptions} from '../sources/index.js';
@@ -28,10 +27,10 @@ import {
28
27
  DEFAULT_GEO_COLUMN,
29
28
  DEFAULT_TILE_RESOLUTION,
30
29
  } from '../constants-internal.js';
31
- import {getSpatialFiltersResolution} from '../spatial-index.js';
32
30
 
33
31
  export interface WidgetBaseSourceProps extends Omit<SourceOptions, 'filters'> {
34
32
  apiVersion?: ApiVersion;
33
+ geoColumn?: string;
35
34
  filters?: Record<string, Filter>;
36
35
  filtersLogicalOperator?: FilterLogicalOperator;
37
36
  }
@@ -52,6 +51,7 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
52
51
  clientId: getClient(),
53
52
  filters: {},
54
53
  filtersLogicalOperator: 'and',
54
+ geoColumn: DEFAULT_GEO_COLUMN,
55
55
  };
56
56
 
57
57
  constructor(props: Props) {
@@ -78,8 +78,7 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
78
78
  connectionName: props.connectionName,
79
79
  filters: getApplicableFilters(owner, props.filters),
80
80
  filtersLogicalOperator: props.filtersLogicalOperator,
81
- spatialDataType: props.spatialDataType,
82
- spatialDataColumn: props.spatialDataColumn,
81
+ geoColumn: props.geoColumn,
83
82
  };
84
83
  }
85
84
 
@@ -94,35 +93,14 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
94
93
  async getCategories(
95
94
  options: CategoryRequestOptions
96
95
  ): Promise<CategoryResponse> {
97
- const {
98
- filterOwner,
99
- spatialFilter,
100
- spatialFiltersMode,
101
- abortController,
102
- viewState,
103
- ...params
104
- } = options;
96
+ const {filterOwner, spatialFilter, abortController, ...params} = options;
105
97
  const {column, operation, operationColumn} = params;
106
- const source = this.getModelSource(filterOwner);
107
-
108
- let spatialFiltersResolution: number | undefined;
109
- if (spatialFilter && source.spatialDataType !== 'geo') {
110
- spatialFiltersResolution = getSpatialFiltersResolution({
111
- source,
112
- viewState,
113
- });
114
- }
115
98
 
116
99
  type CategoriesModelResponse = {rows: {name: string; value: number}[]};
117
100
 
118
101
  return executeModel({
119
102
  model: 'category',
120
- source: {
121
- ...source,
122
- spatialFiltersResolution,
123
- spatialFiltersMode,
124
- spatialFilter,
125
- },
103
+ source: {...this.getModelSource(filterOwner), spatialFilter},
126
104
  params: {
127
105
  column,
128
106
  operation,
@@ -147,35 +125,14 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
147
125
  async getFeatures(
148
126
  options: FeaturesRequestOptions
149
127
  ): Promise<FeaturesResponse> {
150
- const {
151
- filterOwner,
152
- spatialFilter,
153
- spatialFiltersMode,
154
- abortController,
155
- viewState,
156
- ...params
157
- } = options;
128
+ const {filterOwner, spatialFilter, abortController, ...params} = options;
158
129
  const {columns, dataType, featureIds, z, limit, tileResolution} = params;
159
- const source = this.getModelSource(filterOwner);
160
-
161
- let spatialFiltersResolution: number | undefined;
162
- if (spatialFilter && source.spatialDataType !== 'geo') {
163
- spatialFiltersResolution = getSpatialFiltersResolution({
164
- source,
165
- viewState,
166
- });
167
- }
168
130
 
169
131
  type FeaturesModelResponse = {rows: Record<string, unknown>[]};
170
132
 
171
133
  return executeModel({
172
134
  model: 'pick',
173
- source: {
174
- ...source,
175
- spatialFiltersResolution,
176
- spatialFiltersMode,
177
- spatialFilter,
178
- },
135
+ source: {...this.getModelSource(filterOwner), spatialFilter},
179
136
  params: {
180
137
  columns,
181
138
  dataType,
@@ -202,33 +159,17 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
202
159
  const {
203
160
  filterOwner,
204
161
  spatialFilter,
205
- spatialFiltersMode,
206
162
  abortController,
207
163
  operationExp,
208
- viewState,
209
164
  ...params
210
165
  } = options;
211
166
  const {column, operation} = params;
212
- const source = this.getModelSource(filterOwner);
213
-
214
- let spatialFiltersResolution: number | undefined;
215
- if (spatialFilter && source.spatialDataType !== 'geo') {
216
- spatialFiltersResolution = getSpatialFiltersResolution({
217
- source,
218
- viewState,
219
- });
220
- }
221
167
 
222
168
  type FormulaModelResponse = {rows: {value: number}[]};
223
169
 
224
170
  return executeModel({
225
171
  model: 'formula',
226
- source: {
227
- ...source,
228
- spatialFiltersResolution,
229
- spatialFiltersMode,
230
- spatialFilter,
231
- },
172
+ source: {...this.getModelSource(filterOwner), spatialFilter},
232
173
  params: {column: column ?? '*', operation, operationExp},
233
174
  opts: {abortController},
234
175
  }).then((res: FormulaModelResponse) => normalizeObjectKeys(res.rows[0]));
@@ -245,35 +186,14 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
245
186
  async getHistogram(
246
187
  options: HistogramRequestOptions
247
188
  ): Promise<HistogramResponse> {
248
- const {
249
- filterOwner,
250
- spatialFilter,
251
- spatialFiltersMode,
252
- abortController,
253
- viewState,
254
- ...params
255
- } = options;
189
+ const {filterOwner, spatialFilter, abortController, ...params} = options;
256
190
  const {column, operation, ticks} = params;
257
- const source = this.getModelSource(filterOwner);
258
-
259
- let spatialFiltersResolution: number | undefined;
260
- if (spatialFilter && source.spatialDataType !== 'geo') {
261
- spatialFiltersResolution = getSpatialFiltersResolution({
262
- source,
263
- viewState,
264
- });
265
- }
266
191
 
267
192
  type HistogramModelResponse = {rows: {tick: number; value: number}[]};
268
193
 
269
194
  const data = await executeModel({
270
195
  model: 'histogram',
271
- source: {
272
- ...source,
273
- spatialFiltersResolution,
274
- spatialFiltersMode,
275
- spatialFilter,
276
- },
196
+ source: {...this.getModelSource(filterOwner), spatialFilter},
277
197
  params: {column, operation, ticks},
278
198
  opts: {abortController},
279
199
  }).then((res: HistogramModelResponse) => normalizeObjectKeys(res.rows));
@@ -301,35 +221,14 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
301
221
  * or rendering a range slider UI for filtering.
302
222
  */
303
223
  async getRange(options: RangeRequestOptions): Promise<RangeResponse> {
304
- const {
305
- filterOwner,
306
- spatialFilter,
307
- spatialFiltersMode,
308
- abortController,
309
- viewState,
310
- ...params
311
- } = options;
224
+ const {filterOwner, spatialFilter, abortController, ...params} = options;
312
225
  const {column} = params;
313
- const source = this.getModelSource(filterOwner);
314
-
315
- let spatialFiltersResolution: number | undefined;
316
- if (spatialFilter && source.spatialDataType !== 'geo') {
317
- spatialFiltersResolution = getSpatialFiltersResolution({
318
- source,
319
- viewState,
320
- });
321
- }
322
226
 
323
227
  type RangeModelResponse = {rows: {min: number; max: number}[]};
324
228
 
325
229
  return executeModel({
326
230
  model: 'range',
327
- source: {
328
- ...source,
329
- spatialFiltersResolution,
330
- spatialFiltersMode,
331
- spatialFilter,
332
- },
231
+ source: {...this.getModelSource(filterOwner), spatialFilter},
333
232
  params: {column},
334
233
  opts: {abortController},
335
234
  }).then((res: RangeModelResponse) => normalizeObjectKeys(res.rows[0]));
@@ -344,27 +243,10 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
344
243
  * values. Suitable for rendering scatter plots.
345
244
  */
346
245
  async getScatter(options: ScatterRequestOptions): Promise<ScatterResponse> {
347
- const {
348
- filterOwner,
349
- spatialFilter,
350
- spatialFiltersMode,
351
- abortController,
352
- viewState,
353
- ...params
354
- } = options;
246
+ const {filterOwner, spatialFilter, abortController, ...params} = options;
355
247
  const {xAxisColumn, xAxisJoinOperation, yAxisColumn, yAxisJoinOperation} =
356
248
  params;
357
249
 
358
- const source = this.getModelSource(filterOwner);
359
-
360
- let spatialFiltersResolution: number | undefined;
361
- if (spatialFilter && source.spatialDataType !== 'geo') {
362
- spatialFiltersResolution = getSpatialFiltersResolution({
363
- source,
364
- viewState,
365
- });
366
- }
367
-
368
250
  // Make sure this is sync with the same constant in cloud-native/maps-api
369
251
  const HARD_LIMIT = 500;
370
252
 
@@ -372,12 +254,7 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
372
254
 
373
255
  return executeModel({
374
256
  model: 'scatterplot',
375
- source: {
376
- ...source,
377
- spatialFiltersResolution,
378
- spatialFiltersMode,
379
- spatialFilter,
380
- },
257
+ source: {...this.getModelSource(filterOwner), spatialFilter},
381
258
  params: {
382
259
  xAxisColumn,
383
260
  xAxisJoinOperation,
@@ -400,24 +277,8 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
400
277
  * sorting. Suitable for displaying tables and lists.
401
278
  */
402
279
  async getTable(options: TableRequestOptions): Promise<TableResponse> {
403
- const {
404
- filterOwner,
405
- spatialFilter,
406
- spatialFiltersMode,
407
- abortController,
408
- viewState,
409
- ...params
410
- } = options;
280
+ const {filterOwner, spatialFilter, abortController, ...params} = options;
411
281
  const {columns, sortBy, sortDirection, offset = 0, limit = 10} = params;
412
- const source = this.getModelSource(filterOwner);
413
-
414
- let spatialFiltersResolution: number | undefined;
415
- if (spatialFilter && source.spatialDataType !== 'geo') {
416
- spatialFiltersResolution = getSpatialFiltersResolution({
417
- source,
418
- viewState,
419
- });
420
- }
421
282
 
422
283
  type TableModelResponse = {
423
284
  rows: Record<string, number | string>[];
@@ -426,12 +287,7 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
426
287
 
427
288
  return executeModel({
428
289
  model: 'table',
429
- source: {
430
- ...source,
431
- spatialFiltersResolution,
432
- spatialFiltersMode,
433
- spatialFilter,
434
- },
290
+ source: {...this.getModelSource(filterOwner), spatialFilter},
435
291
  params: {
436
292
  column: columns,
437
293
  sortBy,
@@ -458,14 +314,7 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
458
314
  async getTimeSeries(
459
315
  options: TimeSeriesRequestOptions
460
316
  ): Promise<TimeSeriesResponse> {
461
- const {
462
- filterOwner,
463
- abortController,
464
- spatialFilter,
465
- spatialFiltersMode,
466
- viewState,
467
- ...params
468
- } = options;
317
+ const {filterOwner, abortController, spatialFilter, ...params} = options;
469
318
  const {
470
319
  column,
471
320
  operationColumn,
@@ -478,16 +327,6 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
478
327
  splitByCategoryValues,
479
328
  } = params;
480
329
 
481
- const source = this.getModelSource(filterOwner);
482
-
483
- let spatialFiltersResolution: number | undefined;
484
- if (spatialFilter && source.spatialDataType !== 'geo') {
485
- spatialFiltersResolution = getSpatialFiltersResolution({
486
- source,
487
- viewState,
488
- });
489
- }
490
-
491
330
  type TimeSeriesModelResponse = {
492
331
  rows: {name: string; value: number}[];
493
332
  metadata: {categories: string[]};
@@ -495,12 +334,7 @@ export abstract class WidgetBaseSource<Props extends WidgetBaseSourceProps> {
495
334
 
496
335
  return executeModel({
497
336
  model: 'timeseries',
498
- source: {
499
- ...source,
500
- spatialFiltersResolution,
501
- spatialFiltersMode,
502
- spatialFilter,
503
- },
337
+ source: {...this.getModelSource(filterOwner), spatialFilter},
504
338
  params: {
505
339
  column,
506
340
  stepSize,
@@ -1,11 +0,0 @@
1
- import type { ModelSource } from './models/model';
2
- import type { AggregationOptions } from './sources/types';
3
- import type { ViewState } from './widget-sources';
4
- export declare function getSpatialFiltersResolution({ source, viewState, }: {
5
- source: Partial<ModelSource & AggregationOptions>;
6
- viewState?: ViewState;
7
- }): number | undefined;
8
- export declare function getHexagonResolution(viewport: {
9
- zoom: number;
10
- latitude: number;
11
- }, tileSize: number): number;
@@ -1,119 +0,0 @@
1
- import {
2
- DEFAULT_AGGREGATION_RES_LEVEL_H3,
3
- DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN,
4
- } from './constants-internal';
5
- import type {ModelSource} from './models/model';
6
- import type {AggregationOptions} from './sources/types';
7
- import {assert} from './utils';
8
- import type {ViewState} from './widget-sources';
9
-
10
- const DEFAULT_TILE_SIZE = 512;
11
- const QUADBIN_ZOOM_MAX_OFFSET = 4;
12
-
13
- export function getSpatialFiltersResolution({
14
- source,
15
- viewState,
16
- }: {
17
- source: Partial<ModelSource & AggregationOptions>;
18
- viewState?: ViewState;
19
- }) {
20
- assert(
21
- viewState,
22
- 'viewState prop is required to compute automatic spatialFiltersResolution when using spatialFilter with spatial indexes. Either pass a `spatialFiltersResolution` prop or a `viewState` prop to avoid this error'
23
- );
24
-
25
- const dataResolution = source.dataResolution ?? Number.MAX_VALUE;
26
-
27
- const aggregationResLevel =
28
- source.aggregationResLevel ??
29
- (source.spatialDataType === 'h3'
30
- ? DEFAULT_AGGREGATION_RES_LEVEL_H3
31
- : DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN);
32
-
33
- const aggregationResLevelOffset = Math.max(
34
- 0,
35
- Math.floor(aggregationResLevel)
36
- );
37
-
38
- const currentZoomInt = Math.ceil(viewState.zoom);
39
- if (source.spatialDataType === 'h3') {
40
- const tileSize = DEFAULT_TILE_SIZE;
41
- const maxResolutionForZoom =
42
- maxH3SpatialFiltersResolutions.find(
43
- ([zoom]) => zoom === currentZoomInt
44
- )?.[1] ?? Math.max(0, currentZoomInt - 3);
45
-
46
- const maxSpatialFiltersResolution = maxResolutionForZoom
47
- ? Math.min(dataResolution, maxResolutionForZoom)
48
- : dataResolution;
49
-
50
- const hexagonResolution =
51
- getHexagonResolution(viewState, tileSize) + aggregationResLevelOffset;
52
-
53
- return Math.min(hexagonResolution, maxSpatialFiltersResolution);
54
- }
55
-
56
- if (source.spatialDataType === 'quadbin') {
57
- const maxResolutionForZoom = currentZoomInt + QUADBIN_ZOOM_MAX_OFFSET;
58
- const maxSpatialFiltersResolution = Math.min(
59
- dataResolution,
60
- maxResolutionForZoom
61
- );
62
-
63
- const quadsResolution =
64
- Math.floor(viewState.zoom) + aggregationResLevelOffset;
65
- return Math.min(quadsResolution, maxSpatialFiltersResolution);
66
- }
67
-
68
- return undefined;
69
- }
70
-
71
- const maxH3SpatialFiltersResolutions = [
72
- [20, 14],
73
- [19, 13],
74
- [18, 12],
75
- [17, 11],
76
- [16, 10],
77
- [15, 9],
78
- [14, 8],
79
- [13, 7],
80
- [12, 7],
81
- [11, 7],
82
- [10, 6],
83
- [9, 6],
84
- [8, 5],
85
- [7, 4],
86
- [6, 4],
87
- [5, 3],
88
- [4, 2],
89
- [3, 1],
90
- [2, 1],
91
- [1, 0],
92
- ];
93
-
94
- // stolen from https://github.com/visgl/deck.gl/blob/master/modules/carto/src/layers/h3-tileset-2d.ts
95
-
96
- // Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
97
- const BIAS = 2;
98
-
99
- // Resolution conversion function. Takes a WebMercatorViewport and returns
100
- // a H3 resolution such that the screen space size of the hexagons is
101
- // similar
102
- export function getHexagonResolution(
103
- viewport: {zoom: number; latitude: number},
104
- tileSize: number
105
- ): number {
106
- // Difference in given tile size compared to deck's internal 512px tile size,
107
- // expressed as an offset to the viewport zoom.
108
- const zoomOffset = Math.log2(tileSize / DEFAULT_TILE_SIZE);
109
- const hexagonScaleFactor = (2 / 3) * (viewport.zoom - zoomOffset);
110
- const latitudeScaleFactor = Math.log(
111
- 1 / Math.cos((Math.PI * viewport.latitude) / 180)
112
- );
113
-
114
- // Clip and bias
115
- return Math.max(
116
- 0,
117
- Math.floor(hexagonScaleFactor + latitudeScaleFactor - BIAS)
118
- );
119
- }