@deck.gl/carto 8.7.0-beta.5 → 8.7.0
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 +398 -343
- package/dist/es5/api/index.js.map +1 -1
- package/dist/es5/api/layer-map.js +8 -8
- package/dist/es5/api/layer-map.js.map +1 -1
- package/dist/es5/api/maps-api-common.js +15 -1
- package/dist/es5/api/maps-api-common.js.map +1 -1
- package/dist/es5/api/maps-client.js +15 -18
- package/dist/es5/api/maps-client.js.map +1 -1
- package/dist/es5/api/maps-v3-client.js +237 -177
- package/dist/es5/api/maps-v3-client.js.map +1 -1
- package/dist/es5/api/parseMap.js +5 -8
- package/dist/es5/api/parseMap.js.map +1 -1
- package/dist/es5/basemap.js +7 -7
- package/dist/es5/basemap.js.map +1 -1
- package/dist/es5/config.js.map +1 -1
- package/dist/es5/index.js +4 -4
- package/dist/es5/index.js.map +1 -1
- package/dist/es5/layers/carto-layer.js +20 -18
- package/dist/es5/layers/carto-layer.js.map +1 -1
- package/dist/es5/layers/{carto-dynamic-tile-layer.js → carto-tile-layer.js} +24 -24
- package/dist/es5/layers/carto-tile-layer.js.map +1 -0
- package/dist/es5/layers/schema/{carto-dynamic-tile.js → carto-tile.js} +1 -1
- package/dist/es5/layers/schema/carto-tile.js.map +1 -0
- package/dist/es5/style/color-bins-style.js +1 -1
- package/dist/es5/style/color-bins-style.js.map +1 -1
- package/dist/es5/style/color-categories-style.js +1 -1
- package/dist/es5/style/color-categories-style.js.map +1 -1
- package/dist/es5/style/color-continuous-style.js +1 -1
- package/dist/es5/style/color-continuous-style.js.map +1 -1
- package/dist/es5/style/palette.js +1 -6
- package/dist/es5/style/palette.js.map +1 -1
- package/dist/es5/style/utils.js +2 -6
- package/dist/es5/style/utils.js.map +1 -1
- package/dist/es5/utils.js +13 -0
- package/dist/es5/utils.js.map +1 -0
- package/dist/esm/api/index.js.map +1 -1
- package/dist/esm/api/layer-map.js +5 -4
- package/dist/esm/api/layer-map.js.map +1 -1
- package/dist/esm/api/maps-api-common.js +14 -0
- package/dist/esm/api/maps-api-common.js.map +1 -1
- package/dist/esm/api/maps-client.js +6 -10
- package/dist/esm/api/maps-client.js.map +1 -1
- package/dist/esm/api/maps-v3-client.js +72 -37
- package/dist/esm/api/maps-v3-client.js.map +1 -1
- package/dist/esm/api/parseMap.js +4 -3
- package/dist/esm/api/parseMap.js.map +1 -1
- package/dist/esm/basemap.js +7 -7
- package/dist/esm/basemap.js.map +1 -1
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/layers/carto-layer.js +15 -17
- package/dist/esm/layers/carto-layer.js.map +1 -1
- package/dist/esm/layers/{carto-dynamic-tile-layer.js → carto-tile-layer.js} +16 -16
- package/dist/esm/layers/carto-tile-layer.js.map +1 -0
- package/dist/esm/layers/schema/{carto-dynamic-tile.js → carto-tile.js} +1 -1
- package/dist/esm/layers/schema/carto-tile.js.map +1 -0
- package/dist/esm/style/color-bins-style.js +1 -1
- package/dist/esm/style/color-bins-style.js.map +1 -1
- package/dist/esm/style/color-categories-style.js +1 -1
- package/dist/esm/style/color-categories-style.js.map +1 -1
- package/dist/esm/style/color-continuous-style.js +1 -1
- package/dist/esm/style/color-continuous-style.js.map +1 -1
- package/dist/esm/style/palette.js +1 -6
- package/dist/esm/style/palette.js.map +1 -1
- package/dist/esm/style/utils.js +2 -6
- package/dist/esm/style/utils.js.map +1 -1
- package/dist/esm/utils.js +5 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist.min.js +4 -4
- package/package.json +8 -2
- package/src/api/{index.js → index.ts} +0 -0
- package/src/api/{layer-map.js → layer-map.ts} +25 -14
- package/src/api/maps-api-common.ts +76 -0
- package/src/api/{maps-client.js → maps-client.ts} +55 -20
- package/src/api/{maps-v3-client.js → maps-v3-client.ts} +146 -57
- package/src/api/{parseMap.js → parseMap.ts} +7 -6
- package/src/basemap.ts +10 -0
- package/src/{config.js → config.ts} +22 -6
- package/src/{index.js → index.ts} +2 -2
- package/src/layers/carto-layer.js +13 -12
- package/src/layers/{carto-dynamic-tile-layer.js → carto-tile-layer.js} +14 -14
- package/src/layers/schema/{carto-dynamic-tile.js → carto-tile.js} +0 -0
- package/src/style/color-bins-style.ts +26 -0
- package/src/style/{color-categories-style.js → color-categories-style.ts} +10 -4
- package/src/style/color-continuous-style.ts +25 -0
- package/src/style/{palette.js → palette.ts} +18 -15
- package/src/style/{utils.js → utils.ts} +7 -10
- package/src/utils.ts +5 -0
- package/dist/es5/layers/carto-dynamic-tile-layer.js.map +0 -1
- package/dist/es5/layers/schema/carto-dynamic-tile.js.map +0 -1
- package/dist/esm/layers/carto-dynamic-tile-layer.js.map +0 -1
- package/dist/esm/layers/schema/carto-dynamic-tile.js.map +0 -1
- package/src/api/maps-api-common.js +0 -41
- package/src/basemap.js +0 -10
- package/src/style/color-bins-style.js +0 -21
- package/src/style/color-continuous-style.js +0 -20
|
@@ -1,21 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Maps API Client for Carto 3
|
|
3
3
|
*/
|
|
4
|
-
import {getDefaultCredentials, buildMapsUrlFromBase} from '../config';
|
|
5
|
-
import {
|
|
4
|
+
import {getDefaultCredentials, buildMapsUrlFromBase, CloudNativeCredentials} from '../config';
|
|
5
|
+
import {
|
|
6
|
+
API_VERSIONS,
|
|
7
|
+
encodeParameter,
|
|
8
|
+
Format,
|
|
9
|
+
FORMATS,
|
|
10
|
+
MapInstantiation,
|
|
11
|
+
MapType,
|
|
12
|
+
MAP_TYPES,
|
|
13
|
+
SchemaField
|
|
14
|
+
} from './maps-api-common';
|
|
6
15
|
import {parseMap} from './parseMap';
|
|
7
16
|
import {log} from '@deck.gl/core';
|
|
17
|
+
import {assert} from '../utils';
|
|
8
18
|
|
|
9
19
|
const MAX_GET_LENGTH = 2048;
|
|
10
20
|
const DEFAULT_CLIENT = 'deck-gl-carto';
|
|
11
21
|
|
|
22
|
+
interface RequestParams {
|
|
23
|
+
method?: string;
|
|
24
|
+
url: string;
|
|
25
|
+
accessToken?: string;
|
|
26
|
+
body?: any;
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
/**
|
|
13
30
|
* Request against Maps API
|
|
14
31
|
*/
|
|
15
|
-
async function request({method, url,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const headers = {
|
|
32
|
+
async function request({method, url, accessToken, body}: RequestParams): Promise<Response> {
|
|
33
|
+
const headers: Record<string, string> = {
|
|
19
34
|
Accept: 'application/json'
|
|
20
35
|
};
|
|
21
36
|
|
|
@@ -29,8 +44,7 @@ async function request({method, url, format, accessToken, body}) {
|
|
|
29
44
|
|
|
30
45
|
try {
|
|
31
46
|
/* global fetch */
|
|
32
|
-
|
|
33
|
-
response = await fetch(url, {
|
|
47
|
+
return await fetch(url, {
|
|
34
48
|
method,
|
|
35
49
|
headers,
|
|
36
50
|
body
|
|
@@ -38,24 +52,44 @@ async function request({method, url, format, accessToken, body}) {
|
|
|
38
52
|
} catch (error) {
|
|
39
53
|
throw new Error(`Failed to connect to Maps API: ${error}`);
|
|
40
54
|
}
|
|
55
|
+
}
|
|
41
56
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
async function requestJson<T = unknown>({
|
|
58
|
+
method,
|
|
59
|
+
url,
|
|
60
|
+
accessToken,
|
|
61
|
+
body
|
|
62
|
+
}: RequestParams): Promise<T> {
|
|
63
|
+
const response = await request({method, url, accessToken, body});
|
|
46
64
|
const json = await response.json();
|
|
47
65
|
|
|
48
66
|
if (!response.ok) {
|
|
49
67
|
dealWithError({response, error: json.error});
|
|
50
68
|
}
|
|
69
|
+
return json as T;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function requestData({
|
|
73
|
+
method,
|
|
74
|
+
url,
|
|
75
|
+
accessToken,
|
|
76
|
+
format,
|
|
77
|
+
body
|
|
78
|
+
}: RequestParams & {
|
|
79
|
+
format: Format;
|
|
80
|
+
}): Promise<Response | unknown> {
|
|
81
|
+
if (format === FORMATS.NDJSON) {
|
|
82
|
+
return request({method, url, accessToken, body});
|
|
83
|
+
}
|
|
51
84
|
|
|
52
|
-
|
|
85
|
+
const data = await requestJson<any>({method, url, accessToken, body});
|
|
86
|
+
return data.rows ? data.rows : data;
|
|
53
87
|
}
|
|
54
88
|
|
|
55
89
|
/**
|
|
56
90
|
* Display proper message from Maps API error
|
|
57
91
|
*/
|
|
58
|
-
function dealWithError({response, error}) {
|
|
92
|
+
function dealWithError({response, error}: {response: Response; error?: string}): never {
|
|
59
93
|
switch (response.status) {
|
|
60
94
|
case 400:
|
|
61
95
|
throw new Error(`Bad request. ${error}`);
|
|
@@ -67,10 +101,29 @@ function dealWithError({response, error}) {
|
|
|
67
101
|
}
|
|
68
102
|
}
|
|
69
103
|
|
|
104
|
+
type FetchLayerDataParams = {
|
|
105
|
+
type: MapType;
|
|
106
|
+
source: string;
|
|
107
|
+
connection: string;
|
|
108
|
+
credentials: CloudNativeCredentials;
|
|
109
|
+
geoColumn?: string;
|
|
110
|
+
columns?: string[];
|
|
111
|
+
schema?: boolean;
|
|
112
|
+
clientId?: string;
|
|
113
|
+
format?: Format;
|
|
114
|
+
};
|
|
115
|
+
|
|
70
116
|
/**
|
|
71
117
|
* Build a URL with all required parameters
|
|
72
118
|
*/
|
|
73
|
-
function getParameters({
|
|
119
|
+
function getParameters({
|
|
120
|
+
type,
|
|
121
|
+
source,
|
|
122
|
+
geoColumn,
|
|
123
|
+
columns,
|
|
124
|
+
schema,
|
|
125
|
+
clientId
|
|
126
|
+
}: Omit<FetchLayerDataParams, 'connection' | 'credentials'>) {
|
|
74
127
|
const parameters = [encodeParameter('client', clientId || DEFAULT_CLIENT)];
|
|
75
128
|
if (schema) {
|
|
76
129
|
parameters.push(encodeParameter('schema', true));
|
|
@@ -100,26 +153,24 @@ export async function mapInstantiation({
|
|
|
100
153
|
columns,
|
|
101
154
|
schema,
|
|
102
155
|
clientId
|
|
103
|
-
}) {
|
|
156
|
+
}: FetchLayerDataParams): Promise<MapInstantiation> {
|
|
104
157
|
const baseUrl = `${credentials.mapsUrl}/${connection}/${type}`;
|
|
105
158
|
const url = `${baseUrl}?${getParameters({type, source, geoColumn, columns, schema, clientId})}`;
|
|
106
159
|
const {accessToken} = credentials;
|
|
107
160
|
|
|
108
|
-
const format = 'json';
|
|
109
|
-
|
|
110
161
|
if (url.length > MAX_GET_LENGTH && type === MAP_TYPES.QUERY) {
|
|
111
162
|
// need to be a POST request
|
|
112
163
|
const body = JSON.stringify({
|
|
113
164
|
q: source,
|
|
114
165
|
client: clientId || DEFAULT_CLIENT
|
|
115
166
|
});
|
|
116
|
-
return await
|
|
167
|
+
return await requestJson({method: 'POST', url: baseUrl, accessToken, body});
|
|
117
168
|
}
|
|
118
169
|
|
|
119
|
-
return await
|
|
170
|
+
return await requestJson({url, accessToken});
|
|
120
171
|
}
|
|
121
172
|
|
|
122
|
-
function getUrlFromMetadata(metadata, format) {
|
|
173
|
+
function getUrlFromMetadata(metadata: MapInstantiation, format: Format): string | null {
|
|
123
174
|
const m = metadata[format];
|
|
124
175
|
|
|
125
176
|
if (m && !m.error && m.url) {
|
|
@@ -129,16 +180,26 @@ function getUrlFromMetadata(metadata, format) {
|
|
|
129
180
|
return null;
|
|
130
181
|
}
|
|
131
182
|
|
|
132
|
-
function checkFetchLayerDataParameters({
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
183
|
+
function checkFetchLayerDataParameters({
|
|
184
|
+
type,
|
|
185
|
+
source,
|
|
186
|
+
connection,
|
|
187
|
+
credentials
|
|
188
|
+
}: FetchLayerDataParams) {
|
|
189
|
+
assert(connection, 'Must define connection');
|
|
190
|
+
assert(type, 'Must define a type');
|
|
191
|
+
assert(source, 'Must define a source');
|
|
192
|
+
|
|
193
|
+
assert(credentials.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
|
|
194
|
+
assert(credentials.apiBaseUrl, 'Must define apiBaseUrl');
|
|
195
|
+
assert(credentials.accessToken, 'Must define an accessToken');
|
|
140
196
|
}
|
|
141
197
|
|
|
198
|
+
export interface FetchLayerDataResult {
|
|
199
|
+
data: any;
|
|
200
|
+
format: Format;
|
|
201
|
+
schema?: SchemaField[];
|
|
202
|
+
}
|
|
142
203
|
export async function fetchLayerData({
|
|
143
204
|
type,
|
|
144
205
|
source,
|
|
@@ -149,7 +210,7 @@ export async function fetchLayerData({
|
|
|
149
210
|
format,
|
|
150
211
|
schema,
|
|
151
212
|
clientId
|
|
152
|
-
}) {
|
|
213
|
+
}: FetchLayerDataParams): Promise<FetchLayerDataResult> {
|
|
153
214
|
// Internally we split data fetching into two parts to allow us to
|
|
154
215
|
// conditionally fetch the actual data, depending on the metadata state
|
|
155
216
|
const {url, accessToken, mapFormat, metadata} = await _fetchDataUrl({
|
|
@@ -164,8 +225,8 @@ export async function fetchLayerData({
|
|
|
164
225
|
clientId
|
|
165
226
|
});
|
|
166
227
|
|
|
167
|
-
const data = await
|
|
168
|
-
const result = {data, format: mapFormat};
|
|
228
|
+
const data = await requestData({url, format: mapFormat, accessToken});
|
|
229
|
+
const result: FetchLayerDataResult = {data, format: mapFormat};
|
|
169
230
|
if (schema) {
|
|
170
231
|
result.schema = metadata.schema;
|
|
171
232
|
}
|
|
@@ -183,7 +244,7 @@ async function _fetchDataUrl({
|
|
|
183
244
|
format,
|
|
184
245
|
schema,
|
|
185
246
|
clientId
|
|
186
|
-
}) {
|
|
247
|
+
}: FetchLayerDataParams) {
|
|
187
248
|
const defaultCredentials = getDefaultCredentials();
|
|
188
249
|
// Only pick up default credentials if they have been defined for
|
|
189
250
|
// correct API version
|
|
@@ -191,7 +252,7 @@ async function _fetchDataUrl({
|
|
|
191
252
|
...(defaultCredentials.apiVersion === API_VERSIONS.V3 && defaultCredentials),
|
|
192
253
|
...credentials
|
|
193
254
|
};
|
|
194
|
-
checkFetchLayerDataParameters({type, source, connection, localCreds});
|
|
255
|
+
checkFetchLayerDataParameters({type, source, connection, credentials: localCreds});
|
|
195
256
|
|
|
196
257
|
if (!localCreds.mapsUrl) {
|
|
197
258
|
localCreds.mapsUrl = buildMapsUrlFromBase(localCreds.apiBaseUrl);
|
|
@@ -207,13 +268,13 @@ async function _fetchDataUrl({
|
|
|
207
268
|
schema,
|
|
208
269
|
clientId
|
|
209
270
|
});
|
|
210
|
-
let url;
|
|
211
|
-
let mapFormat;
|
|
271
|
+
let url: string | null = null;
|
|
272
|
+
let mapFormat: Format | undefined;
|
|
212
273
|
|
|
213
274
|
if (format) {
|
|
214
275
|
mapFormat = format;
|
|
215
276
|
url = getUrlFromMetadata(metadata, format);
|
|
216
|
-
|
|
277
|
+
assert(url, `Format ${format} not available`);
|
|
217
278
|
} else {
|
|
218
279
|
// guess map format
|
|
219
280
|
const prioritizedFormats = [FORMATS.GEOJSON, FORMATS.JSON, FORMATS.NDJSON, FORMATS.TILEJSON];
|
|
@@ -224,6 +285,7 @@ async function _fetchDataUrl({
|
|
|
224
285
|
break;
|
|
225
286
|
}
|
|
226
287
|
}
|
|
288
|
+
assert(url && mapFormat, 'Unsupported data formats received from backend.');
|
|
227
289
|
}
|
|
228
290
|
|
|
229
291
|
const {accessToken} = localCreds;
|
|
@@ -239,7 +301,7 @@ export async function getData({
|
|
|
239
301
|
columns,
|
|
240
302
|
format,
|
|
241
303
|
clientId
|
|
242
|
-
}) {
|
|
304
|
+
}: FetchLayerDataParams) {
|
|
243
305
|
log.deprecated('getData', 'fetchLayerData')();
|
|
244
306
|
const layerData = await fetchLayerData({
|
|
245
307
|
type,
|
|
@@ -256,67 +318,94 @@ export async function getData({
|
|
|
256
318
|
}
|
|
257
319
|
|
|
258
320
|
/* global clearInterval, setInterval, URL */
|
|
259
|
-
async function _fetchMapDataset(
|
|
321
|
+
async function _fetchMapDataset(
|
|
322
|
+
dataset,
|
|
323
|
+
accessToken: string,
|
|
324
|
+
credentials: CloudNativeCredentials,
|
|
325
|
+
clientId?: string
|
|
326
|
+
) {
|
|
327
|
+
const {connectionName: connection, columns, geoColumn, source, type} = dataset;
|
|
260
328
|
// First fetch metadata
|
|
261
|
-
const {connectionName: connection, source, type} = dataset;
|
|
262
329
|
const {url, mapFormat} = await _fetchDataUrl({
|
|
263
330
|
credentials: {...credentials, accessToken},
|
|
264
331
|
connection,
|
|
332
|
+
columns,
|
|
333
|
+
geoColumn,
|
|
265
334
|
source,
|
|
266
335
|
type,
|
|
267
336
|
clientId
|
|
268
337
|
});
|
|
269
338
|
|
|
270
339
|
// Extract the last time the data changed
|
|
271
|
-
const cache = parseInt(new URL(url).searchParams.get('cache'), 10);
|
|
340
|
+
const cache = parseInt(new URL(url).searchParams.get('cache') || '', 10);
|
|
272
341
|
if (cache && dataset.cache === cache) {
|
|
273
342
|
return false;
|
|
274
343
|
}
|
|
275
344
|
dataset.cache = cache;
|
|
276
345
|
|
|
277
346
|
// Only fetch if the data has changed
|
|
278
|
-
|
|
279
|
-
|
|
347
|
+
dataset.data = await requestData({url, format: mapFormat, accessToken});
|
|
348
|
+
|
|
280
349
|
return true;
|
|
281
350
|
}
|
|
282
351
|
|
|
283
|
-
async function fillInMapDatasets(
|
|
352
|
+
async function fillInMapDatasets(
|
|
353
|
+
{datasets, token},
|
|
354
|
+
clientId: string,
|
|
355
|
+
credentials: CloudNativeCredentials
|
|
356
|
+
) {
|
|
284
357
|
const promises = datasets.map(dataset => _fetchMapDataset(dataset, token, credentials, clientId));
|
|
285
358
|
return await Promise.all(promises);
|
|
286
359
|
}
|
|
287
360
|
|
|
288
|
-
export async function fetchMap({
|
|
361
|
+
export async function fetchMap({
|
|
362
|
+
cartoMapId,
|
|
363
|
+
clientId,
|
|
364
|
+
credentials,
|
|
365
|
+
autoRefresh,
|
|
366
|
+
onNewData
|
|
367
|
+
}: {
|
|
368
|
+
cartoMapId: string;
|
|
369
|
+
clientId: string;
|
|
370
|
+
credentials?: CloudNativeCredentials;
|
|
371
|
+
autoRefresh?: number;
|
|
372
|
+
onNewData?: (map: any) => void;
|
|
373
|
+
}) {
|
|
289
374
|
const defaultCredentials = getDefaultCredentials();
|
|
290
375
|
const localCreds = {
|
|
291
376
|
...(defaultCredentials.apiVersion === API_VERSIONS.V3 && defaultCredentials),
|
|
292
377
|
...credentials
|
|
293
|
-
};
|
|
378
|
+
} as CloudNativeCredentials;
|
|
294
379
|
const {accessToken} = localCreds;
|
|
295
380
|
|
|
296
|
-
|
|
381
|
+
assert(cartoMapId, 'Must define CARTO map id: fetchMap({cartoMapId: "XXXX-XXXX-XXXX"})');
|
|
297
382
|
|
|
298
|
-
|
|
299
|
-
|
|
383
|
+
assert(localCreds.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
|
|
384
|
+
assert(localCreds.apiBaseUrl, 'Must define apiBaseUrl');
|
|
300
385
|
if (!localCreds.mapsUrl) {
|
|
301
386
|
localCreds.mapsUrl = buildMapsUrlFromBase(localCreds.apiBaseUrl);
|
|
302
387
|
}
|
|
303
388
|
|
|
304
389
|
if (autoRefresh || onNewData) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
390
|
+
assert(onNewData, 'Must define `onNewData` when using autoRefresh');
|
|
391
|
+
assert(typeof onNewData === 'function', '`onNewData` must be a function');
|
|
392
|
+
assert(
|
|
393
|
+
typeof autoRefresh === 'number' && autoRefresh > 0,
|
|
394
|
+
'`autoRefresh` must be a positive number'
|
|
395
|
+
);
|
|
308
396
|
}
|
|
309
397
|
|
|
310
398
|
const url = `${localCreds.mapsUrl}/public/${cartoMapId}`;
|
|
311
|
-
const map = await
|
|
399
|
+
const map = await requestJson<any>({url, accessToken});
|
|
312
400
|
|
|
313
401
|
// Periodically check if the data has changed. Note that this
|
|
314
402
|
// will not update when a map is published.
|
|
315
|
-
let stopAutoRefresh;
|
|
403
|
+
let stopAutoRefresh: (() => void) | undefined;
|
|
316
404
|
if (autoRefresh) {
|
|
405
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
317
406
|
const intervalId = setInterval(async () => {
|
|
318
|
-
const changed = await fillInMapDatasets(map, clientId,
|
|
319
|
-
if (changed.some(v => v === true)) {
|
|
407
|
+
const changed = await fillInMapDatasets(map, clientId, localCreds);
|
|
408
|
+
if (onNewData && changed.some(v => v === true)) {
|
|
320
409
|
onNewData(parseMap(map));
|
|
321
410
|
}
|
|
322
411
|
}, autoRefresh * 1000);
|
|
@@ -326,7 +415,7 @@ export async function fetchMap({cartoMapId, clientId, credentials, autoRefresh,
|
|
|
326
415
|
}
|
|
327
416
|
|
|
328
417
|
// Mutates map.datasets so that dataset.data contains data
|
|
329
|
-
await fillInMapDatasets(map, clientId,
|
|
418
|
+
await fillInMapDatasets(map, clientId, localCreds);
|
|
330
419
|
return {
|
|
331
420
|
...parseMap(map),
|
|
332
421
|
...{stopAutoRefresh}
|
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
getTextPixelOffsetAccessor
|
|
8
8
|
} from './layer-map';
|
|
9
9
|
import {_flatten as flatten, log} from '@deck.gl/core';
|
|
10
|
+
import {assert} from '../utils';
|
|
10
11
|
|
|
11
12
|
export function parseMap(json) {
|
|
12
13
|
const {keplerMapConfig, datasets} = json;
|
|
13
|
-
|
|
14
|
+
assert(keplerMapConfig.version === 'v1', 'Only support Kepler v1');
|
|
14
15
|
const {mapState, mapStyle} = keplerMapConfig.config;
|
|
15
16
|
const {layers, layerBlending, interactionConfig} = keplerMapConfig.config.visState;
|
|
16
17
|
|
|
@@ -26,9 +27,9 @@ export function parseMap(json) {
|
|
|
26
27
|
try {
|
|
27
28
|
const {dataId} = config;
|
|
28
29
|
const dataset = datasets.find(d => d.id === dataId);
|
|
29
|
-
|
|
30
|
+
assert(dataset, `No dataset matching dataId: ${dataId}`);
|
|
30
31
|
const {data} = dataset;
|
|
31
|
-
|
|
32
|
+
assert(data, `No data loaded for dataId: ${dataId}`);
|
|
32
33
|
const {Layer, propMap, defaultProps} = getLayer(type, config, dataset);
|
|
33
34
|
return new Layer({
|
|
34
35
|
id,
|
|
@@ -39,7 +40,7 @@ export function parseMap(json) {
|
|
|
39
40
|
...createStyleProps(config, propMap),
|
|
40
41
|
...createChannelProps(visualChannels, type, config, data) // Must come after style
|
|
41
42
|
});
|
|
42
|
-
} catch (e) {
|
|
43
|
+
} catch (e: any) {
|
|
43
44
|
log.error(e.message)();
|
|
44
45
|
return undefined;
|
|
45
46
|
}
|
|
@@ -121,7 +122,7 @@ function mapProps(source, target, mapping) {
|
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
function createStyleProps(config, mapping) {
|
|
124
|
-
const result = {};
|
|
125
|
+
const result: Record<string, any> = {};
|
|
125
126
|
mapProps(config, result, mapping);
|
|
126
127
|
result.highlightColor = config.visConfig.enable3d ? [255, 255, 255, 60] : [252, 242, 26, 255];
|
|
127
128
|
return result;
|
|
@@ -137,7 +138,7 @@ function createChannelProps(visualChannels, type, config, data) {
|
|
|
137
138
|
heightScale = sizeScale;
|
|
138
139
|
}
|
|
139
140
|
const {textLabel, visConfig} = config;
|
|
140
|
-
const result = {};
|
|
141
|
+
const result: Record<string, any> = {};
|
|
141
142
|
const textLabelField = textLabel && textLabel.field;
|
|
142
143
|
if (colorField) {
|
|
143
144
|
result.getFillColor = getColorAccessor(
|
package/src/basemap.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const baseUrl = 'https://basemaps.cartocdn.com/gl/{basemap}-gl-style/style.json';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
VOYAGER: baseUrl.replace('{basemap}', 'voyager'),
|
|
5
|
+
POSITRON: baseUrl.replace('{basemap}', 'positron'),
|
|
6
|
+
DARK_MATTER: baseUrl.replace('{basemap}', 'dark-matter'),
|
|
7
|
+
VOYAGER_NOLABELS: baseUrl.replace('{basemap}', 'voyager-nolabels'),
|
|
8
|
+
POSITRON_NOLABELS: baseUrl.replace('{basemap}', 'positron-nolabels'),
|
|
9
|
+
DARK_MATTER_NOLABELS: baseUrl.replace('{basemap}', 'dark-matter-nolabels')
|
|
10
|
+
} as const;
|
|
@@ -4,17 +4,33 @@ export const defaultClassicCredentials = {
|
|
|
4
4
|
apiKey: 'default_public',
|
|
5
5
|
region: 'us',
|
|
6
6
|
username: 'public'
|
|
7
|
-
};
|
|
7
|
+
} as const;
|
|
8
8
|
|
|
9
9
|
export const defaultCloudNativeCredentials = {
|
|
10
10
|
apiBaseUrl: 'https://gcp-us-east1.api.carto.com'
|
|
11
|
-
};
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
export interface ClassicCredentials {
|
|
14
|
+
apiVersion: 'v1' | 'v2';
|
|
15
|
+
apiKey: string;
|
|
16
|
+
region: string;
|
|
17
|
+
username: string;
|
|
18
|
+
mapsUrl?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CloudNativeCredentials {
|
|
22
|
+
apiVersion: 'v3';
|
|
23
|
+
apiBaseUrl: string;
|
|
24
|
+
accessToken?: string;
|
|
25
|
+
mapsUrl?: string;
|
|
26
|
+
}
|
|
12
27
|
|
|
13
|
-
|
|
28
|
+
export type Credentials = ClassicCredentials | CloudNativeCredentials;
|
|
29
|
+
let credentials: Credentials = {} as Credentials;
|
|
14
30
|
|
|
15
31
|
setDefaultCredentials({});
|
|
16
32
|
|
|
17
|
-
export function setDefaultCredentials({apiVersion, ...rest}) {
|
|
33
|
+
export function setDefaultCredentials({apiVersion, ...rest}: Partial<Credentials>) {
|
|
18
34
|
apiVersion = apiVersion || API_VERSIONS.V3;
|
|
19
35
|
|
|
20
36
|
switch (apiVersion) {
|
|
@@ -30,11 +46,11 @@ export function setDefaultCredentials({apiVersion, ...rest}) {
|
|
|
30
46
|
}
|
|
31
47
|
}
|
|
32
48
|
|
|
33
|
-
export function getDefaultCredentials() {
|
|
49
|
+
export function getDefaultCredentials(): Credentials {
|
|
34
50
|
return credentials;
|
|
35
51
|
}
|
|
36
52
|
|
|
37
|
-
export function buildMapsUrlFromBase(apiBaseUrl) {
|
|
53
|
+
export function buildMapsUrlFromBase(apiBaseUrl: string): string {
|
|
38
54
|
let suffix = '/v3/maps';
|
|
39
55
|
if (apiBaseUrl.endsWith('/')) {
|
|
40
56
|
suffix = suffix.substring(1);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export {getDefaultCredentials, setDefaultCredentials} from './config
|
|
1
|
+
export {getDefaultCredentials, setDefaultCredentials} from './config';
|
|
2
2
|
export {default as CartoLayer} from './layers/carto-layer';
|
|
3
|
-
export {default as
|
|
3
|
+
export {default as _CartoTileLayer} from './layers/carto-tile-layer';
|
|
4
4
|
export {default as BASEMAP} from './basemap';
|
|
5
5
|
export {default as colorBins} from './style/color-bins-style';
|
|
6
6
|
export {default as colorCategories} from './style/color-categories-style';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {CompositeLayer, log} from '@deck.gl/core';
|
|
2
|
-
import
|
|
2
|
+
import CartoTileLayer from './carto-tile-layer';
|
|
3
3
|
import {MVTLayer} from '@deck.gl/geo-layers';
|
|
4
4
|
import {GeoJsonLayer} from '@deck.gl/layers';
|
|
5
5
|
import {fetchLayerData, getDataV2, API_VERSIONS} from '../api';
|
|
@@ -126,24 +126,29 @@ export default class CartoLayer extends CompositeLayer {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
_getSubLayerAndProps() {
|
|
130
130
|
const {data, format, apiVersion} = this.state;
|
|
131
131
|
|
|
132
|
+
const {uniqueIdProperty} = defaultProps;
|
|
133
|
+
const props = {uniqueIdProperty, ...this.props};
|
|
134
|
+
delete props.data;
|
|
135
|
+
|
|
132
136
|
if (apiVersion === API_VERSIONS.V1 || apiVersion === API_VERSIONS.V2) {
|
|
133
|
-
return MVTLayer;
|
|
137
|
+
return [MVTLayer, props];
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
if (format === FORMATS.TILEJSON) {
|
|
137
141
|
/* global URL */
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
props.formatTiles =
|
|
143
|
+
props.formatTiles ||
|
|
140
144
|
new URL(data.tiles[0]).searchParams.get('formatTiles') ||
|
|
141
145
|
TILE_FORMATS.MVT;
|
|
142
|
-
|
|
146
|
+
|
|
147
|
+
return props.formatTiles === TILE_FORMATS.MVT ? [MVTLayer, props] : [CartoTileLayer, props];
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
// It's a geojson layer
|
|
146
|
-
return GeoJsonLayer;
|
|
151
|
+
return [GeoJsonLayer, props];
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
renderLayers() {
|
|
@@ -153,11 +158,7 @@ export default class CartoLayer extends CompositeLayer {
|
|
|
153
158
|
|
|
154
159
|
const {updateTriggers} = this.props;
|
|
155
160
|
|
|
156
|
-
const layer = this.
|
|
157
|
-
|
|
158
|
-
const {formatTiles, uniqueIdProperty} = defaultProps;
|
|
159
|
-
const props = {formatTiles, uniqueIdProperty, ...this.props};
|
|
160
|
-
delete props.data;
|
|
161
|
+
const [layer, props] = this._getSubLayerAndProps();
|
|
161
162
|
|
|
162
163
|
// eslint-disable-next-line new-cap
|
|
163
164
|
return new layer(
|
|
@@ -5,7 +5,7 @@ import {ClipExtension} from '@deck.gl/extensions';
|
|
|
5
5
|
import {MVTLayer, _getURLFromTemplate} from '@deck.gl/geo-layers';
|
|
6
6
|
import {GeoJsonLayer} from '@deck.gl/layers';
|
|
7
7
|
import {geojsonToBinary} from '@loaders.gl/gis';
|
|
8
|
-
import {Tile} from './schema/carto-
|
|
8
|
+
import {Tile} from './schema/carto-tile';
|
|
9
9
|
import {TILE_FORMATS} from '../api/maps-api-common';
|
|
10
10
|
|
|
11
11
|
function parseJSON(arrayBuffer) {
|
|
@@ -31,9 +31,9 @@ function unpackProperties(properties) {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function
|
|
34
|
+
function parseCartoTile(arrayBuffer, options) {
|
|
35
35
|
if (!arrayBuffer) return null;
|
|
36
|
-
const formatTiles = options && options.
|
|
36
|
+
const formatTiles = options && options.cartoTile && options.cartoTile.formatTiles;
|
|
37
37
|
if (formatTiles === TILE_FORMATS.GEOJSON) return geojsonToBinary(parseJSON(arrayBuffer).features);
|
|
38
38
|
|
|
39
39
|
const tile = parsePbf(arrayBuffer);
|
|
@@ -48,25 +48,25 @@ function parseCartoDynamicTile(arrayBuffer, options) {
|
|
|
48
48
|
return data;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
const
|
|
52
|
-
name: 'CARTO
|
|
53
|
-
id: '
|
|
51
|
+
const CartoTileLoader = {
|
|
52
|
+
name: 'CARTO Tile',
|
|
53
|
+
id: 'cartoTile',
|
|
54
54
|
module: 'carto',
|
|
55
55
|
extensions: ['pbf'],
|
|
56
56
|
mimeTypes: ['application/x-protobuf'],
|
|
57
57
|
category: 'geometry',
|
|
58
58
|
worker: false,
|
|
59
|
-
parse: async (arrayBuffer, options) =>
|
|
60
|
-
parseSync:
|
|
59
|
+
parse: async (arrayBuffer, options) => parseCartoTile(arrayBuffer, options),
|
|
60
|
+
parseSync: parseCartoTile,
|
|
61
61
|
options: {
|
|
62
|
-
|
|
62
|
+
cartoTile: {
|
|
63
63
|
// TODO change to BINARY for 8.7 prod release
|
|
64
|
-
formatTiles: TILE_FORMATS.
|
|
64
|
+
formatTiles: TILE_FORMATS.BINARY
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
export default class
|
|
69
|
+
export default class CartoTileLayer extends MVTLayer {
|
|
70
70
|
getTileData(tile) {
|
|
71
71
|
let url = _getURLFromTemplate(this.state.data, tile);
|
|
72
72
|
if (!url) {
|
|
@@ -91,7 +91,7 @@ export default class CartoDynamicTileLayer extends MVTLayer {
|
|
|
91
91
|
const newUrl = new URL(url);
|
|
92
92
|
newUrl.searchParams.set('formatTiles', formatTiles);
|
|
93
93
|
url = newUrl.toString();
|
|
94
|
-
loadOptions.
|
|
94
|
+
loadOptions.cartoTile = {formatTiles};
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
return fetch(url, {propName: 'data', layer: this, loadOptions, signal});
|
|
@@ -117,5 +117,5 @@ export default class CartoDynamicTileLayer extends MVTLayer {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
CartoTileLayer.layerName = 'CartoTileLayer';
|
|
121
|
+
CartoTileLayer.defaultProps = {...MVTLayer.defaultProps, loaders: [CartoTileLoader]};
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {scaleThreshold} from 'd3-scale';
|
|
2
|
+
import getPalette, {Color, DEFAULT_PALETTE, NULL_COLOR} from './palette';
|
|
3
|
+
import {assert, AttributeSelector, getAttrValue} from './utils';
|
|
4
|
+
|
|
5
|
+
export default function colorBins({
|
|
6
|
+
attr,
|
|
7
|
+
domain,
|
|
8
|
+
colors = DEFAULT_PALETTE,
|
|
9
|
+
nullColor = NULL_COLOR
|
|
10
|
+
}: {
|
|
11
|
+
attr: AttributeSelector;
|
|
12
|
+
domain: number[];
|
|
13
|
+
colors?: string | Color[];
|
|
14
|
+
nullColor?: Color;
|
|
15
|
+
}): AttributeSelector {
|
|
16
|
+
assert(Array.isArray(domain), 'Expected "domain" to be an array of numbers');
|
|
17
|
+
|
|
18
|
+
const palette = typeof colors === 'string' ? getPalette(colors, domain.length + 1) : colors;
|
|
19
|
+
|
|
20
|
+
const color = scaleThreshold<number, Color>().domain(domain).range(palette);
|
|
21
|
+
|
|
22
|
+
return d => {
|
|
23
|
+
const value = getAttrValue(attr, d);
|
|
24
|
+
return typeof value === 'number' && Number.isFinite(value) ? color(value) : nullColor;
|
|
25
|
+
};
|
|
26
|
+
}
|