@carto/api-client 0.5.26 → 0.5.27-alpha.dd7e837.114
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 +3 -0
- package/build/api-client.cjs +142 -47
- package/build/api-client.cjs.map +1 -1
- package/build/api-client.d.cts +22 -5
- package/build/api-client.d.ts +22 -5
- package/build/api-client.js +141 -47
- package/build/api-client.js.map +1 -1
- package/package.json +1 -1
- package/src/fetch-map/layer-map.ts +71 -14
- package/src/fetch-map/parse-map.ts +114 -38
- package/src/fetch-map/types.ts +13 -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.27-alpha.dd7e837.114",
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
@@ -342,9 +342,17 @@ function findAccessorKey(keys: string[], properties: any): string[] {
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
export function getColorAccessor(
|
|
345
|
-
{name, colorColumn}: VisualChannelField,
|
|
345
|
+
{name, colorColumn, accessorKey}: VisualChannelField,
|
|
346
346
|
scaleType: ScaleType,
|
|
347
|
-
{
|
|
347
|
+
{
|
|
348
|
+
aggregation,
|
|
349
|
+
range,
|
|
350
|
+
domainOverride,
|
|
351
|
+
}: {
|
|
352
|
+
aggregation?: string;
|
|
353
|
+
range: ColorRange;
|
|
354
|
+
domainOverride?: [number, number];
|
|
355
|
+
},
|
|
348
356
|
opacity: number | undefined,
|
|
349
357
|
data: TilejsonResult
|
|
350
358
|
): {
|
|
@@ -353,15 +361,23 @@ export function getColorAccessor(
|
|
|
353
361
|
scaleDomain: number[] | string[];
|
|
354
362
|
range: string[];
|
|
355
363
|
} {
|
|
364
|
+
// accessorKey (custom-agg alias) wins over colorColumn (legacy identity-color
|
|
365
|
+
// column), which wins over name (standard field).
|
|
366
|
+
const effectiveName = accessorKey ?? colorColumn ?? name;
|
|
367
|
+
const effectiveScaleType =
|
|
368
|
+
colorColumn && !accessorKey ? 'identity' : scaleType;
|
|
356
369
|
const {scale, domain} = calculateLayerScale(
|
|
357
|
-
|
|
358
|
-
|
|
370
|
+
effectiveName,
|
|
371
|
+
effectiveScaleType,
|
|
359
372
|
range,
|
|
360
|
-
data
|
|
373
|
+
data,
|
|
374
|
+
domainOverride
|
|
361
375
|
);
|
|
362
376
|
const alpha = opacityToAlpha(opacity);
|
|
363
377
|
|
|
364
|
-
let accessorKeys =
|
|
378
|
+
let accessorKeys = accessorKey
|
|
379
|
+
? [accessorKey]
|
|
380
|
+
: getAccessorKeys(colorColumn || name, aggregation);
|
|
365
381
|
const accessor = (properties: any) => {
|
|
366
382
|
if (!(accessorKeys[0] in properties)) {
|
|
367
383
|
accessorKeys = findAccessorKey(accessorKeys, properties);
|
|
@@ -383,13 +399,20 @@ export function calculateLayerScale(
|
|
|
383
399
|
name: string,
|
|
384
400
|
scaleType: ScaleType,
|
|
385
401
|
range: ColorRange,
|
|
386
|
-
data: TilejsonResult
|
|
402
|
+
data: TilejsonResult,
|
|
403
|
+
domainOverride?: [number, number]
|
|
387
404
|
): {scale: D3Scale; domain: string[] | number[]} {
|
|
388
405
|
let scaleDomain: number[] | string[] | undefined;
|
|
389
406
|
let scaleColors: string[] = [];
|
|
390
407
|
const {colors} = range;
|
|
391
408
|
|
|
392
|
-
|
|
409
|
+
// colorMap (explicit break values from Custom classification) wins over
|
|
410
|
+
// domainOverride (user Min/Max for Custom aggregation). colorMap defines
|
|
411
|
+
// its own domain, so the override does not apply.
|
|
412
|
+
const domain =
|
|
413
|
+
domainOverride && !range.colorMap
|
|
414
|
+
? domainOverride
|
|
415
|
+
: calculateDomain(data, name, scaleType, colors.length);
|
|
393
416
|
if (scaleType !== 'identity') {
|
|
394
417
|
if (range.colorMap) {
|
|
395
418
|
const {colorMap} = range;
|
|
@@ -506,11 +529,12 @@ export function negateAccessor(accessor: Accessor): Accessor {
|
|
|
506
529
|
}
|
|
507
530
|
|
|
508
531
|
export function getSizeAccessor(
|
|
509
|
-
{name}: VisualChannelField,
|
|
532
|
+
{name, accessorKey}: VisualChannelField,
|
|
510
533
|
scaleType: ScaleType | undefined,
|
|
511
534
|
aggregation: string | null | undefined,
|
|
512
535
|
range: number[] | undefined,
|
|
513
|
-
data: TilejsonResult
|
|
536
|
+
data: TilejsonResult,
|
|
537
|
+
domainOverride?: [number, number]
|
|
514
538
|
): {
|
|
515
539
|
accessor: any;
|
|
516
540
|
domain: number[];
|
|
@@ -521,7 +545,10 @@ export function getSizeAccessor(
|
|
|
521
545
|
let domain: number[] = [];
|
|
522
546
|
if (scaleType && range) {
|
|
523
547
|
if (aggregation !== AggregationTypes.Count) {
|
|
524
|
-
|
|
548
|
+
const source = accessorKey ?? name;
|
|
549
|
+
domain =
|
|
550
|
+
domainOverride ??
|
|
551
|
+
(calculateDomain(data, source, scaleType) as number[]);
|
|
525
552
|
(scale as D3Scale).domain(domain);
|
|
526
553
|
} else {
|
|
527
554
|
domain = (scale as D3Scale).domain();
|
|
@@ -529,7 +556,9 @@ export function getSizeAccessor(
|
|
|
529
556
|
(scale as D3Scale).range(range);
|
|
530
557
|
}
|
|
531
558
|
|
|
532
|
-
let accessorKeys =
|
|
559
|
+
let accessorKeys = accessorKey
|
|
560
|
+
? [accessorKey]
|
|
561
|
+
: getAccessorKeys(name, aggregation);
|
|
533
562
|
const accessor = (properties: any) => {
|
|
534
563
|
if (!(accessorKeys[0] in properties)) {
|
|
535
564
|
accessorKeys = findAccessorKey(accessorKeys, properties);
|
|
@@ -597,14 +626,42 @@ export function getDefaultAggregationExpColumnAliasForLayerType(
|
|
|
597
626
|
}
|
|
598
627
|
}
|
|
599
628
|
|
|
629
|
+
function hashString(input: string): string {
|
|
630
|
+
let h = 0x811c9dc5;
|
|
631
|
+
for (let i = 0; i < input.length; i++) {
|
|
632
|
+
h ^= input.charCodeAt(i);
|
|
633
|
+
h = Math.imul(h, 0x01000193);
|
|
634
|
+
}
|
|
635
|
+
return (h >>> 0).toString(16).padStart(8, '0');
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
function normalizeExpression(exp: string): string {
|
|
639
|
+
return exp.trim().replace(/\s+/g, ' ');
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
function applyProviderCase(alias: string, provider: ProviderType): string {
|
|
643
|
+
return provider === 'snowflake' ? alias.toUpperCase() : alias;
|
|
644
|
+
}
|
|
645
|
+
|
|
600
646
|
/** @privateRemarks Source: Builder */
|
|
601
647
|
function getColumnAliasForAggregationExp(
|
|
602
648
|
name: string,
|
|
603
649
|
aggregation: string,
|
|
604
650
|
provider: ProviderType
|
|
605
651
|
) {
|
|
606
|
-
|
|
607
|
-
|
|
652
|
+
return applyProviderCase(`${name}_${aggregation}`, provider);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
export function compileCustomAggregation(
|
|
656
|
+
exp: string,
|
|
657
|
+
opts: {provider: ProviderType}
|
|
658
|
+
): string {
|
|
659
|
+
const normalized = normalizeExpression(exp);
|
|
660
|
+
if (!normalized) {
|
|
661
|
+
throw new Error('Custom aggregation expression must not be empty');
|
|
662
|
+
}
|
|
663
|
+
const hash = hashString(normalized);
|
|
664
|
+
return applyProviderCase('custom_agg_' + hash, opts.provider);
|
|
608
665
|
}
|
|
609
666
|
|
|
610
667
|
/** @privateRemarks Source: Builder */
|
|
@@ -2,6 +2,7 @@ import type {ColorParameters} from '@luma.gl/core';
|
|
|
2
2
|
import {
|
|
3
3
|
calculateClusterRadius,
|
|
4
4
|
calculateClusterTextFontSize,
|
|
5
|
+
compileCustomAggregation,
|
|
5
6
|
getDefaultAggregationExpColumnAliasForLayerType,
|
|
6
7
|
getLayerProps,
|
|
7
8
|
getColorAccessor,
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
getRasterTileLayerStylePropsRgb,
|
|
36
37
|
getRasterTileLayerStylePropsScaledBand,
|
|
37
38
|
} from './raster-layer.js';
|
|
39
|
+
import type {ProviderType} from '../types.js';
|
|
38
40
|
import type {TilejsonResult} from '../sources/types.js';
|
|
39
41
|
|
|
40
42
|
export type Scale = {
|
|
@@ -53,6 +55,7 @@ export type ScaleKey =
|
|
|
53
55
|
| 'fillColor'
|
|
54
56
|
| 'pointRadius'
|
|
55
57
|
| 'lineColor'
|
|
58
|
+
| 'lineWidth'
|
|
56
59
|
| 'elevation'
|
|
57
60
|
| 'weight';
|
|
58
61
|
|
|
@@ -250,6 +253,37 @@ function createStyleProps(config: MapLayerConfig, mapping: any) {
|
|
|
250
253
|
return result;
|
|
251
254
|
}
|
|
252
255
|
|
|
256
|
+
function resolveCustomAggregation({
|
|
257
|
+
field,
|
|
258
|
+
aggregation,
|
|
259
|
+
expression,
|
|
260
|
+
domain,
|
|
261
|
+
providerId,
|
|
262
|
+
}: {
|
|
263
|
+
field: VisualChannelField | undefined;
|
|
264
|
+
aggregation: string | undefined;
|
|
265
|
+
expression: string | undefined;
|
|
266
|
+
domain: [number, number] | undefined;
|
|
267
|
+
providerId: ProviderType;
|
|
268
|
+
}): {
|
|
269
|
+
field: VisualChannelField | undefined;
|
|
270
|
+
aggregation: string | undefined;
|
|
271
|
+
domainOverride: [number, number] | undefined;
|
|
272
|
+
} {
|
|
273
|
+
if (aggregation !== 'custom') {
|
|
274
|
+
return {field, aggregation, domainOverride: undefined};
|
|
275
|
+
}
|
|
276
|
+
if (!field || !expression?.trim()) {
|
|
277
|
+
return {field, aggregation: undefined, domainOverride: undefined};
|
|
278
|
+
}
|
|
279
|
+
const alias = compileCustomAggregation(expression, {provider: providerId});
|
|
280
|
+
return {
|
|
281
|
+
field: {...field, accessorKey: alias},
|
|
282
|
+
aggregation: undefined,
|
|
283
|
+
domainOverride: domain,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
253
287
|
function createChannelProps(
|
|
254
288
|
id: string,
|
|
255
289
|
layerType: LayerType,
|
|
@@ -313,18 +347,25 @@ function createChannelProps(
|
|
|
313
347
|
// fill color
|
|
314
348
|
{
|
|
315
349
|
const {colorField, colorScale} = visualChannels;
|
|
316
|
-
const {colorRange
|
|
317
|
-
|
|
350
|
+
const {colorRange} = visConfig;
|
|
351
|
+
const {field, aggregation, domainOverride} = resolveCustomAggregation({
|
|
352
|
+
field: colorField,
|
|
353
|
+
aggregation: visConfig.colorAggregation,
|
|
354
|
+
expression: visConfig.colorAggregationExp,
|
|
355
|
+
domain: visConfig.colorAggregationDomain,
|
|
356
|
+
providerId: dataset.providerId,
|
|
357
|
+
});
|
|
358
|
+
if (field && colorScale && colorRange) {
|
|
318
359
|
const {accessor, ...scaleProps} = getColorAccessor(
|
|
319
|
-
|
|
360
|
+
field,
|
|
320
361
|
colorScale,
|
|
321
|
-
{aggregation
|
|
362
|
+
{aggregation, range: colorRange, domainOverride},
|
|
322
363
|
visConfig.opacity,
|
|
323
364
|
data
|
|
324
365
|
);
|
|
325
366
|
result.getFillColor = accessor;
|
|
326
367
|
scales.fillColor = updateTriggers.getFillColor = {
|
|
327
|
-
field
|
|
368
|
+
field,
|
|
328
369
|
type: colorScale,
|
|
329
370
|
...scaleProps,
|
|
330
371
|
};
|
|
@@ -398,44 +439,57 @@ function createChannelProps(
|
|
|
398
439
|
|
|
399
440
|
// point radius
|
|
400
441
|
{
|
|
401
|
-
const radiusRange = visConfig.radiusRange;
|
|
402
442
|
const {radiusField, radiusScale} = visualChannels;
|
|
403
|
-
|
|
443
|
+
const {radiusRange} = visConfig;
|
|
444
|
+
const {field, aggregation, domainOverride} = resolveCustomAggregation({
|
|
445
|
+
field: radiusField,
|
|
446
|
+
aggregation: visConfig.radiusAggregation,
|
|
447
|
+
expression: visConfig.radiusAggregationExp,
|
|
448
|
+
domain: visConfig.radiusAggregationDomain,
|
|
449
|
+
providerId: dataset.providerId,
|
|
450
|
+
});
|
|
451
|
+
if (field && radiusRange && radiusScale) {
|
|
404
452
|
const {accessor, ...scaleProps} = getSizeAccessor(
|
|
405
|
-
|
|
453
|
+
field,
|
|
406
454
|
radiusScale,
|
|
407
|
-
|
|
455
|
+
aggregation,
|
|
408
456
|
radiusRange,
|
|
409
|
-
data
|
|
457
|
+
data,
|
|
458
|
+
domainOverride
|
|
410
459
|
);
|
|
411
460
|
result.getPointRadius = accessor;
|
|
412
461
|
scales.pointRadius = updateTriggers.getPointRadius = {
|
|
413
|
-
field
|
|
462
|
+
field,
|
|
414
463
|
type: radiusScale,
|
|
415
464
|
...scaleProps,
|
|
416
465
|
};
|
|
417
466
|
}
|
|
418
467
|
}
|
|
419
468
|
|
|
420
|
-
// stroke/
|
|
469
|
+
// stroke/outline color
|
|
421
470
|
{
|
|
422
|
-
const strokeColorRange = visConfig.strokeColorRange;
|
|
423
471
|
const {strokeColorScale, strokeColorField} = visualChannels;
|
|
424
|
-
|
|
425
|
-
|
|
472
|
+
const {strokeColorRange} = visConfig;
|
|
473
|
+
const {field, aggregation, domainOverride} = resolveCustomAggregation({
|
|
474
|
+
field: strokeColorField,
|
|
475
|
+
aggregation: visConfig.strokeColorAggregation,
|
|
476
|
+
expression: visConfig.strokeColorAggregationExp,
|
|
477
|
+
domain: visConfig.strokeColorAggregationDomain,
|
|
478
|
+
providerId: dataset.providerId,
|
|
479
|
+
});
|
|
480
|
+
if (field && strokeColorRange && strokeColorScale) {
|
|
426
481
|
const opacity =
|
|
427
482
|
visConfig.strokeOpacity !== undefined ? visConfig.strokeOpacity : 1;
|
|
428
|
-
|
|
429
483
|
const {accessor, ...scaleProps} = getColorAccessor(
|
|
430
|
-
|
|
484
|
+
field,
|
|
431
485
|
strokeColorScale,
|
|
432
|
-
{aggregation, range: strokeColorRange},
|
|
486
|
+
{aggregation, range: strokeColorRange, domainOverride},
|
|
433
487
|
opacity,
|
|
434
488
|
data
|
|
435
489
|
);
|
|
436
490
|
result.getLineColor = accessor;
|
|
437
491
|
scales.lineColor = updateTriggers.getLineColor = {
|
|
438
|
-
field
|
|
492
|
+
field,
|
|
439
493
|
type: strokeColorScale,
|
|
440
494
|
...scaleProps,
|
|
441
495
|
};
|
|
@@ -446,19 +500,26 @@ function createChannelProps(
|
|
|
446
500
|
{
|
|
447
501
|
const {sizeField: strokeWidthField, sizeScale: strokeWidthScale} =
|
|
448
502
|
visualChannels;
|
|
449
|
-
const {sizeRange
|
|
450
|
-
|
|
451
|
-
|
|
503
|
+
const {sizeRange} = visConfig;
|
|
504
|
+
const {field, aggregation, domainOverride} = resolveCustomAggregation({
|
|
505
|
+
field: strokeWidthField,
|
|
506
|
+
aggregation: visConfig.sizeAggregation,
|
|
507
|
+
expression: visConfig.sizeAggregationExp,
|
|
508
|
+
domain: visConfig.sizeAggregationDomain,
|
|
509
|
+
providerId: dataset.providerId,
|
|
510
|
+
});
|
|
511
|
+
if (field && sizeRange) {
|
|
452
512
|
const {accessor, ...scaleProps} = getSizeAccessor(
|
|
453
|
-
|
|
513
|
+
field,
|
|
454
514
|
strokeWidthScale,
|
|
455
|
-
|
|
515
|
+
aggregation,
|
|
456
516
|
sizeRange,
|
|
457
|
-
data
|
|
517
|
+
data,
|
|
518
|
+
domainOverride
|
|
458
519
|
);
|
|
459
520
|
result.getLineWidth = accessor;
|
|
460
521
|
scales.lineWidth = updateTriggers.getLineWidth = {
|
|
461
|
-
field
|
|
522
|
+
field,
|
|
462
523
|
type: strokeWidthScale || 'identity',
|
|
463
524
|
...scaleProps,
|
|
464
525
|
};
|
|
@@ -467,19 +528,27 @@ function createChannelProps(
|
|
|
467
528
|
|
|
468
529
|
// height / elevation
|
|
469
530
|
{
|
|
470
|
-
const {enable3d, heightRange} = visConfig;
|
|
471
531
|
const {heightField, heightScale} = visualChannels;
|
|
472
|
-
|
|
532
|
+
const {enable3d, heightRange} = visConfig;
|
|
533
|
+
const {field, aggregation, domainOverride} = resolveCustomAggregation({
|
|
534
|
+
field: heightField,
|
|
535
|
+
aggregation: visConfig.heightAggregation,
|
|
536
|
+
expression: visConfig.heightAggregationExp,
|
|
537
|
+
domain: visConfig.heightAggregationDomain,
|
|
538
|
+
providerId: dataset.providerId,
|
|
539
|
+
});
|
|
540
|
+
if (field && heightRange && enable3d) {
|
|
473
541
|
const {accessor, ...scaleProps} = getSizeAccessor(
|
|
474
|
-
|
|
542
|
+
field,
|
|
475
543
|
heightScale,
|
|
476
|
-
|
|
544
|
+
aggregation,
|
|
477
545
|
heightRange,
|
|
478
|
-
data
|
|
546
|
+
data,
|
|
547
|
+
domainOverride
|
|
479
548
|
);
|
|
480
549
|
result.getElevation = accessor;
|
|
481
550
|
scales.elevation = updateTriggers.getElevation = {
|
|
482
|
-
field
|
|
551
|
+
field,
|
|
483
552
|
type: heightScale || 'identity',
|
|
484
553
|
...scaleProps,
|
|
485
554
|
};
|
|
@@ -489,18 +558,25 @@ function createChannelProps(
|
|
|
489
558
|
// weight
|
|
490
559
|
{
|
|
491
560
|
const {weightField} = visualChannels;
|
|
492
|
-
const {
|
|
493
|
-
|
|
561
|
+
const {field, aggregation, domainOverride} = resolveCustomAggregation({
|
|
562
|
+
field: weightField,
|
|
563
|
+
aggregation: visConfig.weightAggregation,
|
|
564
|
+
expression: visConfig.weightAggregationExp,
|
|
565
|
+
domain: visConfig.weightAggregationDomain,
|
|
566
|
+
providerId: dataset.providerId,
|
|
567
|
+
});
|
|
568
|
+
if (field && (aggregation || visConfig.weightAggregation === 'custom')) {
|
|
494
569
|
const {accessor, ...scaleProps} = getSizeAccessor(
|
|
495
|
-
|
|
570
|
+
field,
|
|
496
571
|
undefined,
|
|
497
|
-
|
|
572
|
+
aggregation,
|
|
498
573
|
undefined,
|
|
499
|
-
data
|
|
574
|
+
data,
|
|
575
|
+
domainOverride
|
|
500
576
|
);
|
|
501
577
|
result.getWeight = accessor;
|
|
502
578
|
scales.weight = updateTriggers.getWeight = {
|
|
503
|
-
field
|
|
579
|
+
field,
|
|
504
580
|
type: 'identity' as ScaleType,
|
|
505
581
|
...scaleProps,
|
|
506
582
|
};
|
package/src/fetch-map/types.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type VisualChannelField = {
|
|
|
6
6
|
name: string;
|
|
7
7
|
type: string;
|
|
8
8
|
colorColumn?: string;
|
|
9
|
+
accessorKey?: string;
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export type VisualChannels = {
|
|
@@ -65,6 +66,8 @@ export type VisConfig = {
|
|
|
65
66
|
enable3d?: boolean;
|
|
66
67
|
|
|
67
68
|
colorAggregation?: string;
|
|
69
|
+
colorAggregationExp?: string;
|
|
70
|
+
colorAggregationDomain?: [number, number];
|
|
68
71
|
colorRange: ColorRange;
|
|
69
72
|
|
|
70
73
|
customMarkers?: boolean;
|
|
@@ -74,18 +77,28 @@ export type VisConfig = {
|
|
|
74
77
|
radius: number;
|
|
75
78
|
radiusRange?: number[];
|
|
76
79
|
radiusAggregation?: string;
|
|
80
|
+
radiusAggregationExp?: string;
|
|
81
|
+
radiusAggregationDomain?: [number, number];
|
|
77
82
|
|
|
78
83
|
sizeAggregation?: string;
|
|
84
|
+
sizeAggregationExp?: string;
|
|
85
|
+
sizeAggregationDomain?: [number, number];
|
|
79
86
|
sizeRange?: number[];
|
|
80
87
|
|
|
81
88
|
strokeColorAggregation?: string;
|
|
89
|
+
strokeColorAggregationExp?: string;
|
|
90
|
+
strokeColorAggregationDomain?: [number, number];
|
|
82
91
|
strokeOpacity?: number;
|
|
83
92
|
strokeColorRange?: ColorRange;
|
|
84
93
|
|
|
85
94
|
heightRange?: number[];
|
|
86
95
|
heightAggregation?: string;
|
|
96
|
+
heightAggregationExp?: string;
|
|
97
|
+
heightAggregationDomain?: [number, number];
|
|
87
98
|
|
|
88
99
|
weightAggregation?: string;
|
|
100
|
+
weightAggregationExp?: string;
|
|
101
|
+
weightAggregationDomain?: [number, number];
|
|
89
102
|
|
|
90
103
|
// type = clusterTile
|
|
91
104
|
clusterLevel?: number;
|