@deck.gl/carto 8.8.0-alpha.4 → 8.8.0-beta.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/dist/dist.dev.js +14087 -14019
- package/dist/es5/api/layer-map.js +7 -5
- package/dist/es5/api/layer-map.js.map +1 -1
- package/dist/es5/layers/carto-layer.js.map +1 -1
- package/dist/es5/layers/carto-tile-layer.js +17 -12
- package/dist/es5/layers/carto-tile-layer.js.map +1 -1
- package/dist/es5/layers/h3-tile-layer.js +21 -11
- package/dist/es5/layers/h3-tile-layer.js.map +1 -1
- package/dist/es5/layers/h3-tileset-2d.js +4 -8
- package/dist/es5/layers/h3-tileset-2d.js.map +1 -1
- package/dist/es5/layers/quadkey-tile-layer.js +24 -13
- package/dist/es5/layers/quadkey-tile-layer.js.map +1 -1
- package/dist/es5/layers/quadkey-tileset-2d.js.map +1 -1
- package/dist/es5/layers/schema/carto-tile.js +261 -188
- package/dist/es5/layers/schema/carto-tile.js.map +1 -1
- package/dist/es5/layers/spatial-index-tile-layer.js +3 -0
- package/dist/es5/layers/spatial-index-tile-layer.js.map +1 -1
- package/dist/esm/api/layer-map.js +8 -6
- package/dist/esm/api/layer-map.js.map +1 -1
- package/dist/esm/layers/carto-layer.js.map +1 -1
- package/dist/esm/layers/carto-tile-layer.js +20 -16
- package/dist/esm/layers/carto-tile-layer.js.map +1 -1
- package/dist/esm/layers/h3-tile-layer.js +13 -7
- package/dist/esm/layers/h3-tile-layer.js.map +1 -1
- package/dist/esm/layers/h3-tileset-2d.js +5 -9
- package/dist/esm/layers/h3-tileset-2d.js.map +1 -1
- package/dist/esm/layers/quadkey-tile-layer.js +16 -9
- package/dist/esm/layers/quadkey-tile-layer.js.map +1 -1
- package/dist/esm/layers/quadkey-tileset-2d.js.map +1 -1
- package/dist/esm/layers/schema/carto-tile.js +174 -189
- package/dist/esm/layers/schema/carto-tile.js.map +1 -1
- package/dist/esm/layers/spatial-index-tile-layer.js +3 -0
- package/dist/esm/layers/spatial-index-tile-layer.js.map +1 -1
- package/dist.min.js +4 -4
- package/package.json +11 -8
- package/src/api/layer-map.ts +16 -7
- package/src/layers/carto-layer.ts +11 -4
- package/src/layers/{carto-tile-layer.js → carto-tile-layer.ts} +63 -26
- package/src/layers/h3-tile-layer.ts +78 -0
- package/src/layers/{h3-tileset-2d.js → h3-tileset-2d.ts} +29 -26
- package/src/layers/quadkey-tile-layer.ts +68 -0
- package/src/layers/{quadkey-tileset-2d.js → quadkey-tileset-2d.ts} +10 -5
- package/src/layers/schema/carto-tile.ts +221 -0
- package/src/layers/{spatial-index-tile-layer.js → spatial-index-tile-layer.ts} +9 -6
- package/typed/api/index.d.ts +4 -0
- package/typed/api/index.d.ts.map +1 -0
- package/typed/api/index.js +3 -0
- package/typed/api/layer-map.d.ts +54 -0
- package/typed/api/layer-map.d.ts.map +1 -0
- package/typed/api/layer-map.js +264 -0
- package/typed/api/maps-api-common.d.ts +65 -0
- package/typed/api/maps-api-common.d.ts.map +1 -0
- package/typed/api/maps-api-common.js +50 -0
- package/typed/api/maps-client.d.ts +18 -0
- package/typed/api/maps-client.d.ts.map +1 -0
- package/typed/api/maps-client.js +125 -0
- package/typed/api/maps-v3-client.d.ts +45 -0
- package/typed/api/maps-v3-client.d.ts.map +1 -0
- package/typed/api/maps-v3-client.js +304 -0
- package/typed/api/parseMap.d.ts +11 -0
- package/typed/api/parseMap.d.ts.map +1 -0
- package/typed/api/parseMap.js +178 -0
- package/typed/basemap.d.ts +10 -0
- package/typed/basemap.d.ts.map +1 -0
- package/typed/basemap.js +9 -0
- package/typed/config.d.ts +26 -0
- package/typed/config.d.ts.map +1 -0
- package/typed/config.js +35 -0
- package/typed/index.d.ts +12 -0
- package/typed/index.d.ts.map +1 -0
- package/typed/index.js +10 -0
- package/typed/layers/carto-layer.d.ts +98 -0
- package/typed/layers/carto-layer.d.ts.map +1 -0
- package/typed/layers/carto-layer.js +173 -0
- package/typed/layers/carto-tile-layer.d.ts +63 -0
- package/typed/layers/carto-tile-layer.d.ts.map +1 -0
- package/typed/layers/carto-tile-layer.js +105 -0
- package/typed/layers/h3-tile-layer.d.ts +23 -0
- package/typed/layers/h3-tile-layer.d.ts.map +1 -0
- package/typed/layers/h3-tile-layer.js +47 -0
- package/typed/layers/h3-tileset-2d.d.ts +18 -0
- package/typed/layers/h3-tileset-2d.d.ts.map +1 -0
- package/typed/layers/h3-tileset-2d.js +85 -0
- package/typed/layers/quadkey-tile-layer.d.ts +23 -0
- package/typed/layers/quadkey-tile-layer.d.ts.map +1 -0
- package/typed/layers/quadkey-tile-layer.js +42 -0
- package/typed/layers/quadkey-tileset-2d.d.ts +15 -0
- package/typed/layers/quadkey-tileset-2d.d.ts.map +1 -0
- package/typed/layers/quadkey-tileset-2d.js +36 -0
- package/typed/layers/schema/carto-tile.d.ts +44 -0
- package/typed/layers/schema/carto-tile.d.ts.map +1 -0
- package/typed/layers/schema/carto-tile.js +161 -0
- package/typed/layers/spatial-index-tile-layer.d.ts +12 -0
- package/typed/layers/spatial-index-tile-layer.d.ts.map +1 -0
- package/typed/layers/spatial-index-tile-layer.js +40 -0
- package/typed/package.json +6 -0
- package/typed/style/color-bins-style.d.ts +9 -0
- package/typed/style/color-bins-style.d.ts.map +1 -0
- package/typed/style/color-bins-style.js +12 -0
- package/typed/style/color-categories-style.d.ts +10 -0
- package/typed/style/color-categories-style.d.ts.map +1 -0
- package/typed/style/color-categories-style.js +16 -0
- package/typed/style/color-continuous-style.d.ts +9 -0
- package/typed/style/color-continuous-style.d.ts.map +1 -0
- package/typed/style/color-continuous-style.js +12 -0
- package/typed/style/palette.d.ts +7 -0
- package/typed/style/palette.d.ts.map +1 -0
- package/typed/style/palette.js +62 -0
- package/typed/style/utils.d.ts +8 -0
- package/typed/style/utils.d.ts.map +1 -0
- package/typed/style/utils.js +15 -0
- package/typed/utils.d.ts +2 -0
- package/typed/utils.d.ts.map +1 -0
- package/typed/utils.js +4 -0
- package/src/layers/h3-tile-layer.js +0 -52
- package/src/layers/quadkey-tile-layer.js +0 -47
- package/src/layers/schema/carto-tile.js +0 -195
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const DEFAULT_USER_COMPONENT_IN_URL = '{user}';
|
|
2
|
+
export const DEFAULT_REGION_COMPONENT_IN_URL = '{region}';
|
|
3
|
+
export const API_VERSIONS = {
|
|
4
|
+
V1: 'v1',
|
|
5
|
+
V2: 'v2',
|
|
6
|
+
V3: 'v3'
|
|
7
|
+
};
|
|
8
|
+
export const DEFAULT_MAPS_URL_FORMAT = {
|
|
9
|
+
[API_VERSIONS.V1]: `https://${DEFAULT_USER_COMPONENT_IN_URL}.carto.com/api/v1/map`,
|
|
10
|
+
[API_VERSIONS.V2]: `https://maps-api-v2.${DEFAULT_REGION_COMPONENT_IN_URL}.carto.com/user/${DEFAULT_USER_COMPONENT_IN_URL}`
|
|
11
|
+
};
|
|
12
|
+
export const MAP_TYPES = {
|
|
13
|
+
QUERY: 'query',
|
|
14
|
+
TABLE: 'table',
|
|
15
|
+
TILESET: 'tileset'
|
|
16
|
+
};
|
|
17
|
+
export const COLUMNS_SUPPORT = [MAP_TYPES.TABLE];
|
|
18
|
+
export const GEO_COLUMN_SUPPORT = [MAP_TYPES.QUERY, MAP_TYPES.TABLE];
|
|
19
|
+
// AVAILABLE FORMATS
|
|
20
|
+
export const FORMATS = {
|
|
21
|
+
GEOJSON: 'geojson',
|
|
22
|
+
NDJSON: 'ndjson',
|
|
23
|
+
TILEJSON: 'tilejson',
|
|
24
|
+
JSON: 'json'
|
|
25
|
+
};
|
|
26
|
+
// AVAILABLE FORMATS FOR TILES
|
|
27
|
+
export const TILE_FORMATS = {
|
|
28
|
+
MVT: 'mvt',
|
|
29
|
+
JSON: 'json',
|
|
30
|
+
GEOJSON: 'geojson',
|
|
31
|
+
BINARY: 'binary'
|
|
32
|
+
};
|
|
33
|
+
export var SchemaFieldType;
|
|
34
|
+
(function (SchemaFieldType) {
|
|
35
|
+
SchemaFieldType["Number"] = "number";
|
|
36
|
+
SchemaFieldType["Bigint"] = "bigint";
|
|
37
|
+
SchemaFieldType["String"] = "string";
|
|
38
|
+
SchemaFieldType["Geometry"] = "geometry";
|
|
39
|
+
SchemaFieldType["Timestamp"] = "timestamp";
|
|
40
|
+
SchemaFieldType["Object"] = "object";
|
|
41
|
+
SchemaFieldType["Boolean"] = "boolean";
|
|
42
|
+
SchemaFieldType["Variant"] = "variant";
|
|
43
|
+
SchemaFieldType["Unknown"] = "unknown";
|
|
44
|
+
})(SchemaFieldType || (SchemaFieldType = {}));
|
|
45
|
+
/**
|
|
46
|
+
* Simple encode parameter
|
|
47
|
+
*/
|
|
48
|
+
export function encodeParameter(name, value) {
|
|
49
|
+
return `${name}=${encodeURIComponent(value)}`;
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps API Client for Maps API v1 and Maps API v2
|
|
3
|
+
*/
|
|
4
|
+
import { ClassicCredentials } from '../config';
|
|
5
|
+
import { MapType } from './maps-api-common';
|
|
6
|
+
export declare const CONNECTIONS: {
|
|
7
|
+
BIGQUERY: string;
|
|
8
|
+
CARTO: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Obtain a TileJson from Maps API v1 and v2
|
|
12
|
+
*/
|
|
13
|
+
export declare function getDataV2({ type, source, credentials }: {
|
|
14
|
+
type: MapType;
|
|
15
|
+
source: string;
|
|
16
|
+
credentials?: Partial<ClassicCredentials>;
|
|
17
|
+
}): Promise<any>;
|
|
18
|
+
//# sourceMappingURL=maps-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maps-client.d.ts","sourceRoot":"","sources":["../../src/api/maps-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,kBAAkB,EAInB,MAAM,WAAW,CAAC;AACnB,OAAO,EAML,OAAO,EAER,MAAM,mBAAmB,CAAC;AAE3B,eAAO,MAAM,WAAW;;;CAGvB,CAAC;AAKF;;GAEG;AACH,wBAAsB,SAAS,CAAC,EAC9B,IAAI,EACJ,MAAM,EACN,WAAW,EACZ,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC3C,gBAkCA"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps API Client for Maps API v1 and Maps API v2
|
|
3
|
+
*/
|
|
4
|
+
import { defaultClassicCredentials, defaultCloudNativeCredentials, getDefaultCredentials } from '../config';
|
|
5
|
+
import { API_VERSIONS, DEFAULT_MAPS_URL_FORMAT, DEFAULT_REGION_COMPONENT_IN_URL, DEFAULT_USER_COMPONENT_IN_URL, encodeParameter, MAP_TYPES } from './maps-api-common';
|
|
6
|
+
export const CONNECTIONS = {
|
|
7
|
+
BIGQUERY: 'bigquery',
|
|
8
|
+
CARTO: 'carto'
|
|
9
|
+
};
|
|
10
|
+
const BUFFER_SIZE = 16;
|
|
11
|
+
const TILE_EXTENT = 4096;
|
|
12
|
+
/**
|
|
13
|
+
* Obtain a TileJson from Maps API v1 and v2
|
|
14
|
+
*/
|
|
15
|
+
export async function getDataV2({ type, source, credentials }) {
|
|
16
|
+
const defaultCredentials = getDefaultCredentials();
|
|
17
|
+
const apiVersion = credentials?.apiVersion || defaultCredentials.apiVersion;
|
|
18
|
+
// Only pick up default credentials if they have been defined for
|
|
19
|
+
// correct API version
|
|
20
|
+
const localCreds = {
|
|
21
|
+
...(apiVersion === API_VERSIONS.V3 ? defaultCloudNativeCredentials : defaultClassicCredentials),
|
|
22
|
+
mapsUrl: DEFAULT_MAPS_URL_FORMAT[apiVersion],
|
|
23
|
+
...(defaultCredentials.apiVersion === apiVersion && defaultCredentials),
|
|
24
|
+
...credentials
|
|
25
|
+
};
|
|
26
|
+
let url;
|
|
27
|
+
const connection = type === MAP_TYPES.TILESET ? CONNECTIONS.BIGQUERY : CONNECTIONS.CARTO;
|
|
28
|
+
switch (apiVersion) {
|
|
29
|
+
case API_VERSIONS.V1:
|
|
30
|
+
// Maps API v1
|
|
31
|
+
const mapConfig = createMapConfig(source);
|
|
32
|
+
url = buildURLMapsAPIv1({ mapConfig, credentials: localCreds });
|
|
33
|
+
const layergroup = await request({ url, credentials: localCreds });
|
|
34
|
+
return layergroup.metadata.tilejson.vector;
|
|
35
|
+
case API_VERSIONS.V2:
|
|
36
|
+
// Maps API v2
|
|
37
|
+
url = buildURLMapsAPIv2({ connection, type, source, credentials: localCreds });
|
|
38
|
+
return await request({ url, credentials: localCreds });
|
|
39
|
+
default:
|
|
40
|
+
throw new Error(`Invalid maps API version. It should be ${API_VERSIONS.V1} or ${API_VERSIONS.V2}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Request against Maps API
|
|
45
|
+
*/
|
|
46
|
+
async function request({ url, credentials }) {
|
|
47
|
+
let response;
|
|
48
|
+
try {
|
|
49
|
+
/* global fetch */
|
|
50
|
+
response = await fetch(url, {
|
|
51
|
+
headers: {
|
|
52
|
+
Accept: 'application/json'
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new Error(`Failed to connect to Maps API: ${error}`);
|
|
58
|
+
}
|
|
59
|
+
const json = await response.json();
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
dealWithError({ response, json, credentials });
|
|
62
|
+
}
|
|
63
|
+
return json;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Display proper message from Maps API error
|
|
67
|
+
*/
|
|
68
|
+
function dealWithError({ response, json, credentials }) {
|
|
69
|
+
switch (response.status) {
|
|
70
|
+
case 401:
|
|
71
|
+
throw new Error(`Unauthorized access to Maps API: invalid combination of user ('${credentials.username}') and apiKey ('${credentials.apiKey}')`);
|
|
72
|
+
case 403:
|
|
73
|
+
throw new Error(`Unauthorized access to dataset: the provided apiKey('${credentials.apiKey}') doesn't provide access to the requested data`);
|
|
74
|
+
default:
|
|
75
|
+
const e = credentials.apiVersion === API_VERSIONS.V1 ? JSON.stringify(json.errors) : json.error;
|
|
76
|
+
throw new Error(e);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function initURLParameters(credentials) {
|
|
80
|
+
const encodedApiKey = encodeParameter('api_key', credentials.apiKey);
|
|
81
|
+
const encodedClient = encodeParameter('client', 'deck-gl-carto');
|
|
82
|
+
return [encodedApiKey, encodedClient];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Build a URL with all required parameters
|
|
86
|
+
*/
|
|
87
|
+
function buildURLMapsAPIv1({ mapConfig, credentials }) {
|
|
88
|
+
const parameters = initURLParameters(credentials);
|
|
89
|
+
const cfg = JSON.stringify(mapConfig);
|
|
90
|
+
return `${mapsUrl(credentials)}?${parameters.join('&')}&${encodeParameter('config', cfg)}`;
|
|
91
|
+
}
|
|
92
|
+
function buildURLMapsAPIv2({ connection, type, source, credentials }) {
|
|
93
|
+
const parameters = initURLParameters(credentials);
|
|
94
|
+
// Query type is mapped to 'sql' at maps api v1
|
|
95
|
+
const mapsApiType = type === MAP_TYPES.QUERY ? 'sql' : type;
|
|
96
|
+
let url = `${mapsUrl(credentials)}/${connection}/${mapsApiType}?`;
|
|
97
|
+
url += `${encodeParameter('source', source)}&format=tilejson&${parameters.join('&')}`;
|
|
98
|
+
return url;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Prepare a url valid for the specified user
|
|
102
|
+
*/
|
|
103
|
+
function mapsUrl(credentials) {
|
|
104
|
+
return credentials.mapsUrl
|
|
105
|
+
.replace(DEFAULT_USER_COMPONENT_IN_URL, credentials.username)
|
|
106
|
+
.replace(DEFAULT_REGION_COMPONENT_IN_URL, credentials.region);
|
|
107
|
+
}
|
|
108
|
+
function createMapConfig(sql) {
|
|
109
|
+
return {
|
|
110
|
+
version: '1.3.1',
|
|
111
|
+
buffersize: {
|
|
112
|
+
mvt: BUFFER_SIZE
|
|
113
|
+
},
|
|
114
|
+
layers: [
|
|
115
|
+
{
|
|
116
|
+
type: 'mapnik',
|
|
117
|
+
options: {
|
|
118
|
+
sql,
|
|
119
|
+
// eslint-disable-next-line camelcase
|
|
120
|
+
vector_extent: TILE_EXTENT
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
};
|
|
125
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps API Client for Carto 3
|
|
3
|
+
*/
|
|
4
|
+
import { CloudNativeCredentials } from '../config';
|
|
5
|
+
import { Format, MapInstantiation, MapType, SchemaField, TileFormat } from './maps-api-common';
|
|
6
|
+
declare type FetchLayerDataParams = {
|
|
7
|
+
type: MapType;
|
|
8
|
+
source: string;
|
|
9
|
+
connection: string;
|
|
10
|
+
credentials: CloudNativeCredentials;
|
|
11
|
+
geoColumn?: string;
|
|
12
|
+
columns?: string[];
|
|
13
|
+
clientId?: string;
|
|
14
|
+
format?: Format;
|
|
15
|
+
formatTiles?: TileFormat;
|
|
16
|
+
aggregationExp?: string;
|
|
17
|
+
aggregationResLevel?: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function mapInstantiation({ type, source, connection, credentials, geoColumn, columns, clientId, aggregationExp, aggregationResLevel }: FetchLayerDataParams): Promise<MapInstantiation>;
|
|
20
|
+
export interface FetchLayerDataResult {
|
|
21
|
+
data: any;
|
|
22
|
+
format?: Format;
|
|
23
|
+
schema: SchemaField[];
|
|
24
|
+
}
|
|
25
|
+
export declare function fetchLayerData({ type, source, connection, credentials, geoColumn, columns, format, formatTiles, clientId, aggregationExp, aggregationResLevel }: FetchLayerDataParams): Promise<FetchLayerDataResult>;
|
|
26
|
+
export declare function getData({ type, source, connection, credentials, geoColumn, columns, format, clientId }: FetchLayerDataParams): Promise<any>;
|
|
27
|
+
export declare function fetchMap({ cartoMapId, clientId, credentials, autoRefresh, onNewData }: {
|
|
28
|
+
cartoMapId: string;
|
|
29
|
+
clientId: string;
|
|
30
|
+
credentials?: CloudNativeCredentials;
|
|
31
|
+
autoRefresh?: number;
|
|
32
|
+
onNewData?: (map: any) => void;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
stopAutoRefresh: (() => void) | undefined;
|
|
35
|
+
id: any;
|
|
36
|
+
title: any;
|
|
37
|
+
description: any;
|
|
38
|
+
createdAt: any;
|
|
39
|
+
updatedAt: any;
|
|
40
|
+
initialViewState: any;
|
|
41
|
+
mapStyle: any;
|
|
42
|
+
layers: (import("@deck.gl/core").Layer<{}> | undefined)[];
|
|
43
|
+
}>;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=maps-v3-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maps-v3-client.d.ts","sourceRoot":"","sources":["../../src/api/maps-v3-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAA8C,sBAAsB,EAAC,MAAM,WAAW,CAAC;AAC9F,OAAO,EAIL,MAAM,EAGN,gBAAgB,EAChB,OAAO,EAEP,WAAW,EACX,UAAU,EAEX,MAAM,mBAAmB,CAAC;AA0F3B,aAAK,oBAAoB,GAAG;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,sBAAsB,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAmCF,wBAAsB,gBAAgB,CAAC,EACrC,IAAI,EACJ,MAAM,EACN,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,QAAQ,EACR,cAAc,EACd,mBAAmB,EACpB,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuBlD;AAsDD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AACD,wBAAsB,cAAc,CAAC,EACnC,IAAI,EACJ,MAAM,EACN,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,MAAM,EACN,WAAW,EACX,QAAQ,EACR,cAAc,EACd,mBAAmB,EACpB,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAoBtD;AAgFD,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,MAAM,EACN,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,MAAM,EACN,QAAQ,EACT,EAAE,oBAAoB,gBAatB;AA4CD,wBAAsB,QAAQ,CAAC,EAC7B,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,SAAS,EACV,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;CAChC;4BA8B6B,IAAI;;;;;;;;;GA8BjC"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps API Client for Carto 3
|
|
3
|
+
*/
|
|
4
|
+
import { getDefaultCredentials, buildMapsUrlFromBase } from '../config';
|
|
5
|
+
import { API_VERSIONS, COLUMNS_SUPPORT, encodeParameter, FORMATS, GEO_COLUMN_SUPPORT, MAP_TYPES, TILE_FORMATS } from './maps-api-common';
|
|
6
|
+
import { parseMap } from './parseMap';
|
|
7
|
+
import { log } from '@deck.gl/core';
|
|
8
|
+
import { assert } from '../utils';
|
|
9
|
+
const MAX_GET_LENGTH = 2048;
|
|
10
|
+
const DEFAULT_CLIENT = 'deck-gl-carto';
|
|
11
|
+
/**
|
|
12
|
+
* Request against Maps API
|
|
13
|
+
*/
|
|
14
|
+
async function request({ method, url, accessToken, body }) {
|
|
15
|
+
const headers = {
|
|
16
|
+
Accept: 'application/json'
|
|
17
|
+
};
|
|
18
|
+
if (accessToken) {
|
|
19
|
+
headers.Authorization = `Bearer ${accessToken}`;
|
|
20
|
+
}
|
|
21
|
+
if (method === 'POST') {
|
|
22
|
+
headers['Content-Type'] = 'application/json';
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
/* global fetch */
|
|
26
|
+
return await fetch(url, {
|
|
27
|
+
method,
|
|
28
|
+
headers,
|
|
29
|
+
body
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
throw new Error(`Failed to connect to Maps API: ${error}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function requestJson({ method, url, accessToken, body }) {
|
|
37
|
+
const response = await request({ method, url, accessToken, body });
|
|
38
|
+
const json = await response.json();
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
dealWithError({ response, error: json.error });
|
|
41
|
+
}
|
|
42
|
+
return json;
|
|
43
|
+
}
|
|
44
|
+
async function requestData({ method, url, accessToken, format, body }) {
|
|
45
|
+
if (format === FORMATS.NDJSON) {
|
|
46
|
+
return request({ method, url, accessToken, body });
|
|
47
|
+
}
|
|
48
|
+
const data = await requestJson({ method, url, accessToken, body });
|
|
49
|
+
return data.rows ? data.rows : data;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Display proper message from Maps API error
|
|
53
|
+
*/
|
|
54
|
+
function dealWithError({ response, error }) {
|
|
55
|
+
switch (response.status) {
|
|
56
|
+
case 400:
|
|
57
|
+
throw new Error(`Bad request. ${error}`);
|
|
58
|
+
case 401:
|
|
59
|
+
case 403:
|
|
60
|
+
throw new Error(`Unauthorized access. ${error}`);
|
|
61
|
+
default:
|
|
62
|
+
throw new Error(error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Build a URL with all required parameters
|
|
67
|
+
*/
|
|
68
|
+
function getParameters({ type, source, geoColumn, columns, clientId, aggregationExp, aggregationResLevel }) {
|
|
69
|
+
const parameters = [encodeParameter('client', clientId || DEFAULT_CLIENT)];
|
|
70
|
+
const sourceName = type === MAP_TYPES.QUERY ? 'q' : 'name';
|
|
71
|
+
parameters.push(encodeParameter(sourceName, source));
|
|
72
|
+
if (geoColumn) {
|
|
73
|
+
parameters.push(encodeParameter('geo_column', geoColumn));
|
|
74
|
+
}
|
|
75
|
+
if (columns) {
|
|
76
|
+
parameters.push(encodeParameter('columns', columns.join(',')));
|
|
77
|
+
}
|
|
78
|
+
if (aggregationExp) {
|
|
79
|
+
parameters.push(encodeParameter('aggregationExp', aggregationExp));
|
|
80
|
+
}
|
|
81
|
+
if (aggregationResLevel) {
|
|
82
|
+
parameters.push(encodeParameter('aggregationResLevel', aggregationResLevel));
|
|
83
|
+
}
|
|
84
|
+
return parameters.join('&');
|
|
85
|
+
}
|
|
86
|
+
export async function mapInstantiation({ type, source, connection, credentials, geoColumn, columns, clientId, aggregationExp, aggregationResLevel }) {
|
|
87
|
+
const baseUrl = `${credentials.mapsUrl}/${connection}/${type}`;
|
|
88
|
+
const url = `${baseUrl}?${getParameters({
|
|
89
|
+
type,
|
|
90
|
+
source,
|
|
91
|
+
geoColumn,
|
|
92
|
+
columns,
|
|
93
|
+
clientId,
|
|
94
|
+
aggregationExp,
|
|
95
|
+
aggregationResLevel
|
|
96
|
+
})}`;
|
|
97
|
+
const { accessToken } = credentials;
|
|
98
|
+
if (url.length > MAX_GET_LENGTH && type === MAP_TYPES.QUERY) {
|
|
99
|
+
// need to be a POST request
|
|
100
|
+
const body = JSON.stringify({
|
|
101
|
+
q: source,
|
|
102
|
+
client: clientId || DEFAULT_CLIENT
|
|
103
|
+
});
|
|
104
|
+
return await requestJson({ method: 'POST', url: baseUrl, accessToken, body });
|
|
105
|
+
}
|
|
106
|
+
return await requestJson({ url, accessToken });
|
|
107
|
+
}
|
|
108
|
+
function getUrlFromMetadata(metadata, format) {
|
|
109
|
+
const m = metadata[format];
|
|
110
|
+
if (m && !m.error && m.url) {
|
|
111
|
+
return m.url[0];
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
function checkFetchLayerDataParameters({ type, source, connection, credentials, geoColumn, columns, aggregationExp, aggregationResLevel }) {
|
|
116
|
+
assert(connection, 'Must define connection');
|
|
117
|
+
assert(type, 'Must define a type');
|
|
118
|
+
assert(source, 'Must define a source');
|
|
119
|
+
assert(credentials.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
|
|
120
|
+
assert(credentials.apiBaseUrl, 'Must define apiBaseUrl');
|
|
121
|
+
assert(credentials.accessToken, 'Must define an accessToken');
|
|
122
|
+
if (columns) {
|
|
123
|
+
assert(COLUMNS_SUPPORT.includes(type), `The columns parameter is not supported by type ${type}`);
|
|
124
|
+
}
|
|
125
|
+
if (geoColumn) {
|
|
126
|
+
assert(GEO_COLUMN_SUPPORT.includes(type), `The geoColumn parameter is not supported by type ${type}`);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
assert(!aggregationExp, 'Have aggregationExp, but geoColumn parameter is missing');
|
|
130
|
+
assert(!aggregationResLevel, 'Have aggregationResLevel, but geoColumn parameter is missing');
|
|
131
|
+
}
|
|
132
|
+
if (!aggregationExp) {
|
|
133
|
+
assert(!aggregationResLevel, 'Have aggregationResLevel, but aggregationExp parameter is missing');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
export async function fetchLayerData({ type, source, connection, credentials, geoColumn, columns, format, formatTiles, clientId, aggregationExp, aggregationResLevel }) {
|
|
137
|
+
// Internally we split data fetching into two parts to allow us to
|
|
138
|
+
// conditionally fetch the actual data, depending on the metadata state
|
|
139
|
+
const { url, accessToken, mapFormat, metadata } = await _fetchDataUrl({
|
|
140
|
+
type,
|
|
141
|
+
source,
|
|
142
|
+
connection,
|
|
143
|
+
credentials,
|
|
144
|
+
geoColumn,
|
|
145
|
+
columns,
|
|
146
|
+
format,
|
|
147
|
+
formatTiles,
|
|
148
|
+
clientId,
|
|
149
|
+
aggregationExp,
|
|
150
|
+
aggregationResLevel
|
|
151
|
+
});
|
|
152
|
+
const data = await requestData({ url, format: mapFormat, accessToken });
|
|
153
|
+
const result = { data, format: mapFormat, schema: metadata.schema };
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
async function _fetchDataUrl({ type, source, connection, credentials, geoColumn, columns, format, formatTiles, clientId, aggregationExp, aggregationResLevel }) {
|
|
157
|
+
const defaultCredentials = getDefaultCredentials();
|
|
158
|
+
// Only pick up default credentials if they have been defined for
|
|
159
|
+
// correct API version
|
|
160
|
+
const localCreds = {
|
|
161
|
+
...(defaultCredentials.apiVersion === API_VERSIONS.V3 && defaultCredentials),
|
|
162
|
+
...credentials
|
|
163
|
+
};
|
|
164
|
+
checkFetchLayerDataParameters({
|
|
165
|
+
type,
|
|
166
|
+
source,
|
|
167
|
+
connection,
|
|
168
|
+
credentials: localCreds,
|
|
169
|
+
geoColumn,
|
|
170
|
+
columns,
|
|
171
|
+
aggregationExp,
|
|
172
|
+
aggregationResLevel
|
|
173
|
+
});
|
|
174
|
+
if (!localCreds.mapsUrl) {
|
|
175
|
+
localCreds.mapsUrl = buildMapsUrlFromBase(localCreds.apiBaseUrl);
|
|
176
|
+
}
|
|
177
|
+
const metadata = await mapInstantiation({
|
|
178
|
+
type,
|
|
179
|
+
source,
|
|
180
|
+
connection,
|
|
181
|
+
credentials: localCreds,
|
|
182
|
+
geoColumn,
|
|
183
|
+
columns,
|
|
184
|
+
clientId,
|
|
185
|
+
aggregationExp,
|
|
186
|
+
aggregationResLevel
|
|
187
|
+
});
|
|
188
|
+
let url = null;
|
|
189
|
+
let mapFormat;
|
|
190
|
+
if (format) {
|
|
191
|
+
mapFormat = format;
|
|
192
|
+
url = getUrlFromMetadata(metadata, format);
|
|
193
|
+
assert(url, `Format ${format} not available`);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// guess map format
|
|
197
|
+
const prioritizedFormats = [FORMATS.GEOJSON, FORMATS.JSON, FORMATS.NDJSON, FORMATS.TILEJSON];
|
|
198
|
+
for (const f of prioritizedFormats) {
|
|
199
|
+
url = getUrlFromMetadata(metadata, f);
|
|
200
|
+
if (url) {
|
|
201
|
+
mapFormat = f;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
assert(url && mapFormat, 'Unsupported data formats received from backend.');
|
|
206
|
+
}
|
|
207
|
+
if (format === FORMATS.TILEJSON && formatTiles) {
|
|
208
|
+
log.assert(Object.values(TILE_FORMATS).includes(formatTiles), `Invalid value for formatTiles: ${formatTiles}. Use value from TILE_FORMATS`);
|
|
209
|
+
url += `&${encodeParameter('formatTiles', formatTiles)}`;
|
|
210
|
+
}
|
|
211
|
+
const { accessToken } = localCreds;
|
|
212
|
+
return { url, accessToken, mapFormat, metadata };
|
|
213
|
+
}
|
|
214
|
+
export async function getData({ type, source, connection, credentials, geoColumn, columns, format, clientId }) {
|
|
215
|
+
log.deprecated('getData', 'fetchLayerData')();
|
|
216
|
+
const layerData = await fetchLayerData({
|
|
217
|
+
type,
|
|
218
|
+
source,
|
|
219
|
+
connection,
|
|
220
|
+
credentials,
|
|
221
|
+
geoColumn,
|
|
222
|
+
columns,
|
|
223
|
+
format,
|
|
224
|
+
clientId
|
|
225
|
+
});
|
|
226
|
+
return layerData.data;
|
|
227
|
+
}
|
|
228
|
+
/* global clearInterval, setInterval, URL */
|
|
229
|
+
async function _fetchMapDataset(dataset, accessToken, credentials, clientId) {
|
|
230
|
+
const { connectionName: connection, columns, format, geoColumn, source, type } = dataset;
|
|
231
|
+
// First fetch metadata
|
|
232
|
+
const { url, mapFormat } = await _fetchDataUrl({
|
|
233
|
+
clientId,
|
|
234
|
+
credentials: { ...credentials, accessToken },
|
|
235
|
+
connection,
|
|
236
|
+
columns,
|
|
237
|
+
format,
|
|
238
|
+
geoColumn,
|
|
239
|
+
source,
|
|
240
|
+
type
|
|
241
|
+
});
|
|
242
|
+
// Extract the last time the data changed
|
|
243
|
+
const cache = parseInt(new URL(url).searchParams.get('cache') || '', 10);
|
|
244
|
+
if (cache && dataset.cache === cache) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
dataset.cache = cache;
|
|
248
|
+
// Only fetch if the data has changed
|
|
249
|
+
dataset.data = await requestData({ url, format: mapFormat, accessToken });
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
async function fillInMapDatasets({ datasets, token }, clientId, credentials) {
|
|
253
|
+
const promises = datasets.map(dataset => _fetchMapDataset(dataset, token, credentials, clientId));
|
|
254
|
+
return await Promise.all(promises);
|
|
255
|
+
}
|
|
256
|
+
export async function fetchMap({ cartoMapId, clientId, credentials, autoRefresh, onNewData }) {
|
|
257
|
+
const defaultCredentials = getDefaultCredentials();
|
|
258
|
+
const localCreds = {
|
|
259
|
+
...(defaultCredentials.apiVersion === API_VERSIONS.V3 && defaultCredentials),
|
|
260
|
+
...credentials
|
|
261
|
+
};
|
|
262
|
+
const { accessToken } = localCreds;
|
|
263
|
+
assert(cartoMapId, 'Must define CARTO map id: fetchMap({cartoMapId: "XXXX-XXXX-XXXX"})');
|
|
264
|
+
assert(localCreds.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
|
|
265
|
+
assert(localCreds.apiBaseUrl, 'Must define apiBaseUrl');
|
|
266
|
+
if (!localCreds.mapsUrl) {
|
|
267
|
+
localCreds.mapsUrl = buildMapsUrlFromBase(localCreds.apiBaseUrl);
|
|
268
|
+
}
|
|
269
|
+
if (autoRefresh || onNewData) {
|
|
270
|
+
assert(onNewData, 'Must define `onNewData` when using autoRefresh');
|
|
271
|
+
assert(typeof onNewData === 'function', '`onNewData` must be a function');
|
|
272
|
+
assert(typeof autoRefresh === 'number' && autoRefresh > 0, '`autoRefresh` must be a positive number');
|
|
273
|
+
}
|
|
274
|
+
const url = `${localCreds.mapsUrl}/public/${cartoMapId}`;
|
|
275
|
+
const map = await requestJson({ url, accessToken });
|
|
276
|
+
// Periodically check if the data has changed. Note that this
|
|
277
|
+
// will not update when a map is published.
|
|
278
|
+
let stopAutoRefresh;
|
|
279
|
+
if (autoRefresh) {
|
|
280
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
281
|
+
const intervalId = setInterval(async () => {
|
|
282
|
+
const changed = await fillInMapDatasets(map, clientId, localCreds);
|
|
283
|
+
if (onNewData && changed.some(v => v === true)) {
|
|
284
|
+
onNewData(parseMap(map));
|
|
285
|
+
}
|
|
286
|
+
}, autoRefresh * 1000);
|
|
287
|
+
stopAutoRefresh = () => {
|
|
288
|
+
clearInterval(intervalId);
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
const geojsonLayers = map.keplerMapConfig.config.visState.layers.filter(({ type }) => type === 'geojson' || type === 'point');
|
|
292
|
+
const geojsonDatasetIds = geojsonLayers.map(({ config }) => config.dataId);
|
|
293
|
+
map.datasets.forEach(dataset => {
|
|
294
|
+
if (geojsonDatasetIds.includes(dataset.id)) {
|
|
295
|
+
dataset.format = 'geojson';
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
// Mutates map.datasets so that dataset.data contains data
|
|
299
|
+
await fillInMapDatasets(map, clientId, localCreds);
|
|
300
|
+
return {
|
|
301
|
+
...parseMap(map),
|
|
302
|
+
...{ stopAutoRefresh }
|
|
303
|
+
};
|
|
304
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function parseMap(json: any): {
|
|
2
|
+
id: any;
|
|
3
|
+
title: any;
|
|
4
|
+
description: any;
|
|
5
|
+
createdAt: any;
|
|
6
|
+
updatedAt: any;
|
|
7
|
+
initialViewState: any;
|
|
8
|
+
mapStyle: any;
|
|
9
|
+
layers: (import("@deck.gl/core").Layer<{}> | undefined)[];
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=parseMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseMap.d.ts","sourceRoot":"","sources":["../../src/api/parseMap.ts"],"names":[],"mappings":"AAeA,wBAAgB,QAAQ,CAAC,IAAI,KAAA;;;;;;;;;EAqC5B"}
|