@deck.gl/carto 8.7.0-beta.4 → 8.7.0-beta.7

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.
Files changed (97) hide show
  1. package/dist/dist.dev.js +444 -362
  2. package/dist/es5/api/index.js.map +1 -1
  3. package/dist/es5/api/layer-map.js +32 -17
  4. package/dist/es5/api/layer-map.js.map +1 -1
  5. package/dist/es5/api/maps-api-common.js +15 -1
  6. package/dist/es5/api/maps-api-common.js.map +1 -1
  7. package/dist/es5/api/maps-client.js +15 -18
  8. package/dist/es5/api/maps-client.js.map +1 -1
  9. package/dist/es5/api/maps-v3-client.js +241 -181
  10. package/dist/es5/api/maps-v3-client.js.map +1 -1
  11. package/dist/es5/api/parseMap.js +9 -12
  12. package/dist/es5/api/parseMap.js.map +1 -1
  13. package/dist/es5/basemap.js +7 -7
  14. package/dist/es5/basemap.js.map +1 -1
  15. package/dist/es5/config.js.map +1 -1
  16. package/dist/es5/index.js +4 -4
  17. package/dist/es5/index.js.map +1 -1
  18. package/dist/es5/layers/carto-layer.js +31 -24
  19. package/dist/es5/layers/carto-layer.js.map +1 -1
  20. package/dist/es5/layers/{carto-dynamic-tile-layer.js → carto-tile-layer.js} +27 -25
  21. package/dist/es5/layers/carto-tile-layer.js.map +1 -0
  22. package/dist/es5/layers/schema/{carto-dynamic-tile.js → carto-tile.js} +1 -1
  23. package/dist/es5/layers/schema/carto-tile.js.map +1 -0
  24. package/dist/es5/style/color-bins-style.js +1 -1
  25. package/dist/es5/style/color-bins-style.js.map +1 -1
  26. package/dist/es5/style/color-categories-style.js +1 -1
  27. package/dist/es5/style/color-categories-style.js.map +1 -1
  28. package/dist/es5/style/color-continuous-style.js +1 -1
  29. package/dist/es5/style/color-continuous-style.js.map +1 -1
  30. package/dist/es5/style/palette.js +1 -6
  31. package/dist/es5/style/palette.js.map +1 -1
  32. package/dist/es5/style/utils.js +2 -6
  33. package/dist/es5/style/utils.js.map +1 -1
  34. package/dist/es5/utils.js +13 -0
  35. package/dist/es5/utils.js.map +1 -0
  36. package/dist/esm/api/index.js.map +1 -1
  37. package/dist/esm/api/layer-map.js +28 -12
  38. package/dist/esm/api/layer-map.js.map +1 -1
  39. package/dist/esm/api/maps-api-common.js +14 -0
  40. package/dist/esm/api/maps-api-common.js.map +1 -1
  41. package/dist/esm/api/maps-client.js +6 -10
  42. package/dist/esm/api/maps-client.js.map +1 -1
  43. package/dist/esm/api/maps-v3-client.js +73 -38
  44. package/dist/esm/api/maps-v3-client.js.map +1 -1
  45. package/dist/esm/api/parseMap.js +9 -8
  46. package/dist/esm/api/parseMap.js.map +1 -1
  47. package/dist/esm/basemap.js +7 -7
  48. package/dist/esm/basemap.js.map +1 -1
  49. package/dist/esm/config.js.map +1 -1
  50. package/dist/esm/index.js +2 -2
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/esm/layers/carto-layer.js +27 -23
  53. package/dist/esm/layers/carto-layer.js.map +1 -1
  54. package/dist/esm/layers/{carto-dynamic-tile-layer.js → carto-tile-layer.js} +20 -18
  55. package/dist/esm/layers/carto-tile-layer.js.map +1 -0
  56. package/dist/esm/layers/schema/{carto-dynamic-tile.js → carto-tile.js} +1 -1
  57. package/dist/esm/layers/schema/carto-tile.js.map +1 -0
  58. package/dist/esm/style/color-bins-style.js +1 -1
  59. package/dist/esm/style/color-bins-style.js.map +1 -1
  60. package/dist/esm/style/color-categories-style.js +1 -1
  61. package/dist/esm/style/color-categories-style.js.map +1 -1
  62. package/dist/esm/style/color-continuous-style.js +1 -1
  63. package/dist/esm/style/color-continuous-style.js.map +1 -1
  64. package/dist/esm/style/palette.js +1 -6
  65. package/dist/esm/style/palette.js.map +1 -1
  66. package/dist/esm/style/utils.js +2 -6
  67. package/dist/esm/style/utils.js.map +1 -1
  68. package/dist/esm/utils.js +5 -0
  69. package/dist/esm/utils.js.map +1 -0
  70. package/dist.min.js +4 -4
  71. package/package.json +8 -2
  72. package/src/api/{index.js → index.ts} +0 -0
  73. package/src/api/{layer-map.js → layer-map.ts} +50 -23
  74. package/src/api/maps-api-common.ts +76 -0
  75. package/src/api/{maps-client.js → maps-client.ts} +55 -20
  76. package/src/api/{maps-v3-client.js → maps-v3-client.ts} +145 -57
  77. package/src/api/{parseMap.js → parseMap.ts} +8 -7
  78. package/src/basemap.ts +10 -0
  79. package/src/{config.js → config.ts} +22 -6
  80. package/src/{index.js → index.ts} +2 -2
  81. package/src/layers/carto-layer.js +31 -32
  82. package/src/layers/{carto-dynamic-tile-layer.js → carto-tile-layer.js} +20 -16
  83. package/src/layers/schema/{carto-dynamic-tile.js → carto-tile.js} +0 -0
  84. package/src/style/color-bins-style.ts +26 -0
  85. package/src/style/{color-categories-style.js → color-categories-style.ts} +10 -4
  86. package/src/style/color-continuous-style.ts +25 -0
  87. package/src/style/{palette.js → palette.ts} +18 -15
  88. package/src/style/{utils.js → utils.ts} +7 -10
  89. package/src/utils.ts +5 -0
  90. package/dist/es5/layers/carto-dynamic-tile-layer.js.map +0 -1
  91. package/dist/es5/layers/schema/carto-dynamic-tile.js.map +0 -1
  92. package/dist/esm/layers/carto-dynamic-tile-layer.js.map +0 -1
  93. package/dist/esm/layers/schema/carto-dynamic-tile.js.map +0 -1
  94. package/src/api/maps-api-common.js +0 -41
  95. package/src/basemap.js +0 -10
  96. package/src/style/color-bins-style.js +0 -21
  97. 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 {API_VERSIONS, encodeParameter, FORMATS, MAP_TYPES} from './maps-api-common';
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, format, accessToken, body}) {
16
- let response;
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
- /* eslint no-undef: "error" */
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
- if (format === FORMATS.NDJSON) {
43
- return response;
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
+ }
51
71
 
52
- return json.rows ? json.rows : json;
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
+ }
84
+
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({type, source, geoColumn, columns, schema, clientId}) {
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 request({method: 'POST', url: baseUrl, format, accessToken, body});
167
+ return await requestJson({method: 'POST', url: baseUrl, accessToken, body});
117
168
  }
118
169
 
119
- return await request({url, format, accessToken});
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({type, source, connection, localCreds}) {
133
- log.assert(connection, 'Must define connection');
134
- log.assert(type, 'Must define a type');
135
- log.assert(source, 'Must define a source');
136
-
137
- log.assert(localCreds.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
138
- log.assert(localCreds.apiBaseUrl, 'Must define apiBaseUrl');
139
- log.assert(localCreds.accessToken, 'Must define an accessToken');
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 request({url, format: mapFormat, accessToken});
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
- log.assert(url, `Format ${format} not available`);
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,
@@ -255,8 +317,13 @@ export async function getData({
255
317
  return layerData.data;
256
318
  }
257
319
 
258
- /* global clearInterval, setInterval, URLSearchParams */
259
- async function _fetchMapDataset(dataset, accessToken, credentials, clientId) {
320
+ /* global clearInterval, setInterval, URL */
321
+ async function _fetchMapDataset(
322
+ dataset,
323
+ accessToken: string,
324
+ credentials: CloudNativeCredentials,
325
+ clientId?: string
326
+ ) {
260
327
  // First fetch metadata
261
328
  const {connectionName: connection, source, type} = dataset;
262
329
  const {url, mapFormat} = await _fetchDataUrl({
@@ -268,54 +335,75 @@ async function _fetchMapDataset(dataset, accessToken, credentials, clientId) {
268
335
  });
269
336
 
270
337
  // Extract the last time the data changed
271
- const cache = parseInt(new URLSearchParams(url).get('cache'), 10);
338
+ const cache = parseInt(new URL(url).searchParams.get('cache') || '', 10);
272
339
  if (cache && dataset.cache === cache) {
273
340
  return false;
274
341
  }
275
342
  dataset.cache = cache;
276
343
 
277
344
  // Only fetch if the data has changed
278
- const data = await request({url, format: mapFormat, accessToken});
279
- dataset.data = data;
345
+ dataset.data = await requestData({url, format: mapFormat, accessToken});
346
+
280
347
  return true;
281
348
  }
282
349
 
283
- async function fillInMapDatasets({datasets, token}, clientId, credentials) {
350
+ async function fillInMapDatasets(
351
+ {datasets, token},
352
+ clientId: string,
353
+ credentials: CloudNativeCredentials
354
+ ) {
284
355
  const promises = datasets.map(dataset => _fetchMapDataset(dataset, token, credentials, clientId));
285
356
  return await Promise.all(promises);
286
357
  }
287
358
 
288
- export async function fetchMap({cartoMapId, clientId, credentials, autoRefresh, onNewData}) {
359
+ export async function fetchMap({
360
+ cartoMapId,
361
+ clientId,
362
+ credentials,
363
+ autoRefresh,
364
+ onNewData
365
+ }: {
366
+ cartoMapId: string;
367
+ clientId: string;
368
+ credentials?: CloudNativeCredentials;
369
+ autoRefresh?: number;
370
+ onNewData?: (map: any) => void;
371
+ }) {
289
372
  const defaultCredentials = getDefaultCredentials();
290
373
  const localCreds = {
291
374
  ...(defaultCredentials.apiVersion === API_VERSIONS.V3 && defaultCredentials),
292
375
  ...credentials
293
- };
376
+ } as CloudNativeCredentials;
377
+ const {accessToken} = localCreds;
294
378
 
295
- log.assert(cartoMapId, `Must define CARTO map id: fetchMap({cartoMapId: 'XXXX-XXXX-XXXX'})`);
379
+ assert(cartoMapId, 'Must define CARTO map id: fetchMap({cartoMapId: "XXXX-XXXX-XXXX"})');
296
380
 
297
- log.assert(localCreds.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
298
- log.assert(localCreds.apiBaseUrl, 'Must define apiBaseUrl');
381
+ assert(localCreds.apiVersion === API_VERSIONS.V3, 'Method only available for v3');
382
+ assert(localCreds.apiBaseUrl, 'Must define apiBaseUrl');
299
383
  if (!localCreds.mapsUrl) {
300
384
  localCreds.mapsUrl = buildMapsUrlFromBase(localCreds.apiBaseUrl);
301
385
  }
302
386
 
303
387
  if (autoRefresh || onNewData) {
304
- log.assert(onNewData, 'Must define `onNewData` when using autoRefresh');
305
- log.assert(typeof onNewData === 'function', '`onNewData` must be a function');
306
- log.assert(autoRefresh > 0, '`autoRefresh` must be a positive number');
388
+ assert(onNewData, 'Must define `onNewData` when using autoRefresh');
389
+ assert(typeof onNewData === 'function', '`onNewData` must be a function');
390
+ assert(
391
+ typeof autoRefresh === 'number' && autoRefresh > 0,
392
+ '`autoRefresh` must be a positive number'
393
+ );
307
394
  }
308
395
 
309
396
  const url = `${localCreds.mapsUrl}/public/${cartoMapId}`;
310
- const map = await request({url});
397
+ const map = await requestJson<any>({url, accessToken});
311
398
 
312
399
  // Periodically check if the data has changed. Note that this
313
400
  // will not update when a map is published.
314
- let stopAutoRefresh;
401
+ let stopAutoRefresh: (() => void) | undefined;
315
402
  if (autoRefresh) {
403
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
316
404
  const intervalId = setInterval(async () => {
317
- const changed = await fillInMapDatasets(map, clientId, credentials);
318
- if (changed.some(v => v === true)) {
405
+ const changed = await fillInMapDatasets(map, clientId, localCreds);
406
+ if (onNewData && changed.some(v => v === true)) {
319
407
  onNewData(parseMap(map));
320
408
  }
321
409
  }, autoRefresh * 1000);
@@ -325,7 +413,7 @@ export async function fetchMap({cartoMapId, clientId, credentials, autoRefresh,
325
413
  }
326
414
 
327
415
  // Mutates map.datasets so that dataset.data contains data
328
- await fillInMapDatasets(map, clientId, credentials);
416
+ await fillInMapDatasets(map, clientId, localCreds);
329
417
  return {
330
418
  ...parseMap(map),
331
419
  ...{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
- log.assert(keplerMapConfig.version === 'v1', 'Only support Kepler v1');
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
 
@@ -24,12 +25,12 @@ export function parseMap(json) {
24
25
  mapStyle,
25
26
  layers: extractTextLayers(layers.reverse()).map(({id, type, config, visualChannels}) => {
26
27
  try {
27
- const {Layer, propMap, defaultProps} = getLayer(type, config);
28
28
  const {dataId} = config;
29
29
  const dataset = datasets.find(d => d.id === dataId);
30
- log.assert(dataset, `No dataset matching dataId: ${dataId}`);
30
+ assert(dataset, `No dataset matching dataId: ${dataId}`);
31
31
  const {data} = dataset;
32
- log.assert(data, `No data loaded for dataId: ${dataId}`);
32
+ assert(data, `No data loaded for dataId: ${dataId}`);
33
+ const {Layer, propMap, defaultProps} = getLayer(type, config, dataset);
33
34
  return new Layer({
34
35
  id,
35
36
  data,
@@ -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
- let credentials = {};
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.js';
1
+ export {getDefaultCredentials, setDefaultCredentials} from './config';
2
2
  export {default as CartoLayer} from './layers/carto-layer';
3
- export {default as _CartoDynamicTileLayer} from './layers/carto-dynamic-tile-layer';
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 CartoDynamicTileLayer from './carto-dynamic-tile-layer';
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';
@@ -27,8 +27,8 @@ const defaultProps = {
27
27
  // (String, optional): format of data
28
28
  format: null,
29
29
 
30
- // (String, optional): format of data
31
- formatTiles: TILE_FORMATS.GEOJSON, // TODO: for 8.7 release switch to BINARY
30
+ // (String, optional): force format of data for tiles
31
+ formatTiles: null,
32
32
 
33
33
  // (String, optional): clientId identifier used for internal tracing, place here a string to identify the client who is doing the request.
34
34
  clientId: null,
@@ -126,40 +126,39 @@ export default class CartoLayer extends CompositeLayer {
126
126
  }
127
127
  }
128
128
 
129
- renderLayers() {
129
+ _getSubLayerAndProps() {
130
130
  const {data, format, apiVersion} = this.state;
131
131
 
132
- if (!data) return null;
132
+ const {uniqueIdProperty} = defaultProps;
133
+ const props = {uniqueIdProperty, ...this.props};
134
+ delete props.data;
133
135
 
134
- const {type, updateTriggers} = this.props;
135
-
136
- let layer;
137
-
138
- /* global URLSearchParams */
139
- const tilesFormat =
140
- apiVersion === API_VERSIONS.V3 &&
141
- format === FORMATS.TILEJSON &&
142
- new URLSearchParams(data.tiles[0]).get('format');
143
- const nonMvtTiles = tilesFormat && tilesFormat !== TILE_FORMATS.MVT;
144
-
145
- const dynamicTiles =
146
- apiVersion === API_VERSIONS.V3 && type === MAP_TYPES.TABLE && format === FORMATS.TILEJSON;
147
-
148
- if (nonMvtTiles || dynamicTiles) {
149
- layer = CartoDynamicTileLayer;
150
- } else if (
151
- apiVersion === API_VERSIONS.V1 ||
152
- apiVersion === API_VERSIONS.V2 ||
153
- format === FORMATS.TILEJSON
154
- ) {
155
- layer = MVTLayer;
156
- } else {
157
- layer = GeoJsonLayer;
136
+ if (apiVersion === API_VERSIONS.V1 || apiVersion === API_VERSIONS.V2) {
137
+ return [MVTLayer, props];
158
138
  }
159
139
 
160
- const {formatTiles, uniqueIdProperty} = defaultProps;
161
- const props = {formatTiles, uniqueIdProperty, ...this.props};
162
- delete props.data;
140
+ if (format === FORMATS.TILEJSON) {
141
+ /* global URL */
142
+ props.formatTiles =
143
+ props.formatTiles ||
144
+ new URL(data.tiles[0]).searchParams.get('formatTiles') ||
145
+ TILE_FORMATS.MVT;
146
+
147
+ return props.formatTiles === TILE_FORMATS.MVT ? [MVTLayer, props] : [CartoTileLayer, props];
148
+ }
149
+
150
+ // It's a geojson layer
151
+ return [GeoJsonLayer, props];
152
+ }
153
+
154
+ renderLayers() {
155
+ const {data} = this.state;
156
+
157
+ if (!data) return null;
158
+
159
+ const {updateTriggers} = this.props;
160
+
161
+ const [layer, props] = this._getSubLayerAndProps();
163
162
 
164
163
  // eslint-disable-next-line new-cap
165
164
  return new layer(
@@ -5,8 +5,8 @@ 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-dynamic-tile';
9
- import {encodeParameter, TILE_FORMATS} from '../api/maps-api-common';
8
+ import {Tile} from './schema/carto-tile';
9
+ import {TILE_FORMATS} from '../api/maps-api-common';
10
10
 
11
11
  function parseJSON(arrayBuffer) {
12
12
  return JSON.parse(new TextDecoder().decode(arrayBuffer));
@@ -31,9 +31,9 @@ function unpackProperties(properties) {
31
31
  });
32
32
  }
33
33
 
34
- function parseCartoDynamicTile(arrayBuffer, options) {
34
+ function parseCartoTile(arrayBuffer, options) {
35
35
  if (!arrayBuffer) return null;
36
- const formatTiles = options && options.cartoDynamicTile && options.cartoDynamicTile.formatTiles;
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,24 +48,25 @@ function parseCartoDynamicTile(arrayBuffer, options) {
48
48
  return data;
49
49
  }
50
50
 
51
- const CartoDynamicTileLoader = {
52
- name: 'CARTO Dynamic Tile',
53
- id: 'cartoDynamicTile',
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) => parseCartoDynamicTile(arrayBuffer, options),
60
- parseSync: parseCartoDynamicTile,
59
+ parse: async (arrayBuffer, options) => parseCartoTile(arrayBuffer, options),
60
+ parseSync: parseCartoTile,
61
61
  options: {
62
- cartoDynamicTile: {
62
+ cartoTile: {
63
+ // TODO change to BINARY for 8.7 prod release
63
64
  formatTiles: TILE_FORMATS.BINARY
64
65
  }
65
66
  }
66
67
  };
67
68
 
68
- export default class CartoDynamicTileLayer extends MVTLayer {
69
+ export default class CartoTileLayer extends MVTLayer {
69
70
  getTileData(tile) {
70
71
  let url = _getURLFromTemplate(this.state.data, tile);
71
72
  if (!url) {
@@ -86,8 +87,11 @@ export default class CartoDynamicTileLayer extends MVTLayer {
86
87
  Object.values(TILE_FORMATS).includes(formatTiles),
87
88
  `Invalid value for formatTiles: ${formatTiles}. Use value from TILE_FORMATS`
88
89
  );
89
- url += `&${encodeParameter('formatTiles', formatTiles)}`;
90
- loadOptions.cartoDynamicTile = {formatTiles};
90
+ // eslint-disable-next-line no-undef
91
+ const newUrl = new URL(url);
92
+ newUrl.searchParams.set('formatTiles', formatTiles);
93
+ url = newUrl.toString();
94
+ loadOptions.cartoTile = {formatTiles};
91
95
  }
92
96
 
93
97
  return fetch(url, {propName: 'data', layer: this, loadOptions, signal});
@@ -103,7 +107,7 @@ export default class CartoDynamicTileLayer extends MVTLayer {
103
107
  const {
104
108
  bbox: {west, south, east, north}
105
109
  } = props.tile;
106
- props.extensions = [new ClipExtension(), ...props.extensions];
110
+ props.extensions = [new ClipExtension(), ...(props.extensions || [])];
107
111
  props.clipBounds = [west, south, east, north];
108
112
 
109
113
  const subLayer = new GeoJsonLayer({
@@ -113,5 +117,5 @@ export default class CartoDynamicTileLayer extends MVTLayer {
113
117
  }
114
118
  }
115
119
 
116
- CartoDynamicTileLayer.layerName = 'CartoDynamicTileLayer';
117
- CartoDynamicTileLayer.defaultProps = {...MVTLayer.defaultProps, loaders: [CartoDynamicTileLoader]};
120
+ CartoTileLayer.layerName = 'CartoTileLayer';
121
+ CartoTileLayer.defaultProps = {...MVTLayer.defaultProps, loaders: [CartoTileLoader]};