@carto/api-client 0.5.5 → 0.5.6-alpha.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.
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.5",
11
+ "version": "0.5.6-alpha.1",
12
12
  "license": "MIT",
13
13
  "publishConfig": {
14
14
  "access": "public"
@@ -188,6 +188,14 @@ export type TilesetSourceOptions = {
188
188
  * are used by default if the runtime environment supports ES Module Workers.
189
189
  */
190
190
  widgetWorker?: boolean;
191
+
192
+ /**
193
+ * Script URL used to create Web Workers for local widget calculations. In
194
+ * most cases a custom URL is not needed; bundlers will resolve the worker
195
+ * URL from a `@carto/api-client/worker` import internally. Advanced uses
196
+ * may require deploying the script manually and providing a custom URL.
197
+ */
198
+ widgetWorkerUrl?: string;
191
199
  };
192
200
 
193
201
  export type ColumnsOption = {
@@ -3,6 +3,7 @@ import type {
3
3
  TileResolution,
4
4
  } from '../sources/types.js';
5
5
  import type {
6
+ AggregationType,
6
7
  Filters,
7
8
  GroupDateType,
8
9
  SortColumnType,
@@ -30,10 +31,31 @@ export interface BaseRequestOptions {
30
31
  filterOwner?: string;
31
32
  }
32
33
 
33
- /** Options for {@link WidgetRemoteSource#getCategories}. */
34
+ /**
35
+ * Examples:
36
+ * * population by state
37
+ * * column: 'state'
38
+ * * operation: 'sum'
39
+ * * operationColumn: 'population'
40
+ * * average salary by department
41
+ * * column: 'department'
42
+ * * operation: 'avg'
43
+ * * operationColumn: 'salary'
44
+ * * custom aggregation by storetype
45
+ * * column: 'storetype'
46
+ * * operation: 'custom'
47
+ * * operationExp: 'sum(sales)/sum(area)'
48
+ *
49
+ * Options for {@link WidgetRemoteSource#getCategories}.
50
+ */
34
51
  export interface CategoryRequestOptions extends BaseRequestOptions {
52
+ /** The column that to categorize by. */
35
53
  column: string;
36
- operation?: 'count' | 'avg' | 'min' | 'max' | 'sum';
54
+ /** The type of aggregation to apply on data in scope of each category. */
55
+ operation: AggregationType;
56
+ /** Remote only. Only valid if operation is 'custom' */
57
+ operationExp?: string;
58
+ /** The aggregated column per each category. */
37
59
  operationColumn?: string;
38
60
  /** Local only. */
39
61
  joinOperation?: 'count' | 'avg' | 'min' | 'max' | 'sum';
@@ -82,11 +104,28 @@ export interface FeaturesRequestOptions extends BaseRequestOptions {
82
104
  tileResolution?: TileResolution;
83
105
  }
84
106
 
85
- /** Options for {@link WidgetRemoteSource#getFormula}. */
107
+ /**
108
+ * Examples:
109
+ * * sum of all sales
110
+ * * column: 'sales'
111
+ * * operation: 'sum'
112
+ * * average salary
113
+ * * column: 'salary'
114
+ * * operation: 'avg'
115
+ * * custom aggregation over all rows
116
+ * * operation: 'custom'
117
+ * * operationExp: 'sum(sales)/sum(area)'
118
+ *
119
+ * Options for {@link WidgetRemoteSource#getFormula}.
120
+ */
86
121
  export interface FormulaRequestOptions extends BaseRequestOptions {
87
- column: string;
88
- operation?: 'count' | 'avg' | 'min' | 'max' | 'sum' | 'custom';
122
+ /** The column to apply the aggregation operation on. Not needed for 'custom' operation. */
123
+ column?: string;
124
+ /** The type of aggregation to apply on data. */
125
+ operation: AggregationType;
126
+ /** Remote only. Only valid if operation is 'custom' */
89
127
  operationExp?: string;
128
+ /** Local only. */
90
129
  joinOperation?: 'count' | 'avg' | 'min' | 'max' | 'sum';
91
130
  }
92
131
 
@@ -126,12 +165,25 @@ export interface TableRequestOptions extends BaseRequestOptions {
126
165
  searchFilterText?: string;
127
166
  }
128
167
 
129
- /** Options for {@link WidgetRemoteSource#getTimeSeries}. */
168
+ /**
169
+ * Examples:
170
+ * * sum of all sales by month
171
+ * * column: 'sales'
172
+ * * stepSize: 'month'
173
+ * * operation: 'sum'
174
+ * * average salary by year
175
+ * * column: 'salary'
176
+ * * stepSize: 'year'
177
+ * * operation: 'avg'
178
+ * Options for {@link WidgetRemoteSource#getTimeSeries}.
179
+ */
130
180
  export interface TimeSeriesRequestOptions extends BaseRequestOptions {
131
181
  column: string;
132
182
  stepSize: GroupDateType;
133
183
  stepMultiplier?: number;
134
- operation?: 'count' | 'avg' | 'min' | 'max' | 'sum';
184
+ operation: AggregationType;
185
+ /** Remote only. Only valid if operation is 'custom' */
186
+ operationExp?: string;
135
187
  operationColumn?: string;
136
188
  joinOperation?: 'count' | 'avg' | 'min' | 'max' | 'sum';
137
189
  splitByCategory?: string;
@@ -17,7 +17,7 @@ import type {
17
17
  TimeSeriesRequestOptions,
18
18
  TimeSeriesResponse,
19
19
  } from './types.js';
20
- import {normalizeObjectKeys} from '../utils.js';
20
+ import {assert, normalizeObjectKeys} from '../utils.js';
21
21
  import {DEFAULT_TILE_RESOLUTION} from '../constants-internal.js';
22
22
  import {WidgetSource, type WidgetSourceProps} from './widget-source.js';
23
23
  import type {Filters} from '../types.js';
@@ -74,7 +74,11 @@ export abstract class WidgetRemoteSource<
74
74
  spatialFiltersMode,
75
75
  ...params
76
76
  } = options;
77
- const {column, operation, operationColumn} = params;
77
+ const {column, operation, operationColumn, operationExp} = params;
78
+
79
+ if (operation === 'custom') {
80
+ assert(operationExp, 'operationExp is required for custom operation');
81
+ }
78
82
 
79
83
  type CategoriesModelResponse = {rows: {name: string; value: number}[]};
80
84
 
@@ -88,6 +92,7 @@ export abstract class WidgetRemoteSource<
88
92
  params: {
89
93
  column,
90
94
  operation,
95
+ operationExp,
91
96
  operationColumn: operationColumn || column,
92
97
  },
93
98
  opts: {signal, headers: this.props.headers},
@@ -143,6 +148,10 @@ export abstract class WidgetRemoteSource<
143
148
 
144
149
  type FormulaModelResponse = {rows: {value: number}[]};
145
150
 
151
+ if (operation === 'custom') {
152
+ assert(operationExp, 'operationExp is required for custom operation');
153
+ }
154
+
146
155
  return executeModel({
147
156
  model: 'formula',
148
157
  source: {
@@ -314,6 +323,7 @@ export abstract class WidgetRemoteSource<
314
323
  operationColumn,
315
324
  joinOperation,
316
325
  operation,
326
+ operationExp,
317
327
  stepSize,
318
328
  stepMultiplier,
319
329
  splitByCategory,
@@ -321,6 +331,10 @@ export abstract class WidgetRemoteSource<
321
331
  splitByCategoryValues,
322
332
  } = params;
323
333
 
334
+ if (operation === 'custom') {
335
+ assert(operationExp, 'operationExp is required for custom operation');
336
+ }
337
+
324
338
  type TimeSeriesModelResponse = {
325
339
  rows: {name: string; value: number}[];
326
340
  metadata: {categories: string[]};
@@ -340,6 +354,7 @@ export abstract class WidgetRemoteSource<
340
354
  operationColumn: operationColumn || column,
341
355
  joinOperation,
342
356
  operation,
357
+ operationExp,
343
358
  splitByCategory,
344
359
  splitByCategoryLimit,
345
360
  splitByCategoryValues,
@@ -329,6 +329,10 @@ export class WidgetTilesetSourceImpl extends WidgetSource<WidgetTilesetSourcePro
329
329
  }
330
330
 
331
331
  assertColumn(this._features, column, operationColumn as string);
332
+ assert(
333
+ operation !== 'custom',
334
+ 'Custom operation not supported for tilesets'
335
+ );
332
336
 
333
337
  const rows =
334
338
  groupValuesByDateColumn({
@@ -99,13 +99,22 @@ export class WidgetTilesetSource<
99
99
  return this._workerImpl;
100
100
  }
101
101
 
102
- this._workerImpl = new Worker(
103
- new URL('@carto/api-client/worker', import.meta.url),
104
- {
102
+ // For Vite (and perhaps other bundlers) to parse WorkerOptions, it
103
+ // must be a static, inline object – duplicated below.
104
+ if (this.props.widgetWorkerUrl) {
105
+ this._workerImpl = new Worker(this.props.widgetWorkerUrl, {
105
106
  type: 'module',
106
107
  name: 'cartowidgettileset',
107
- }
108
- );
108
+ });
109
+ } else {
110
+ this._workerImpl = new Worker(
111
+ new URL('@carto/api-client/worker', import.meta.url),
112
+ {
113
+ type: 'module',
114
+ name: 'cartowidgettileset',
115
+ }
116
+ );
117
+ }
109
118
 
110
119
  this._workerImpl.postMessage({
111
120
  method: Method.INIT,