@deck.gl/carto 8.9.0-alpha.5 → 8.9.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 +13784 -58311
- package/dist/es5/api/carto-api-error.js +87 -0
- package/dist/es5/api/carto-api-error.js.map +1 -0
- package/dist/es5/api/index.js +8 -0
- package/dist/es5/api/index.js.map +1 -1
- package/dist/es5/api/layer-map.js +4 -1
- package/dist/es5/api/layer-map.js.map +1 -1
- package/dist/es5/api/maps-api-common.js +9 -1
- package/dist/es5/api/maps-api-common.js.map +1 -1
- package/dist/es5/api/maps-v3-client.js +140 -115
- package/dist/es5/api/maps-v3-client.js.map +1 -1
- package/dist/es5/index.js +6 -0
- package/dist/es5/index.js.map +1 -1
- package/dist/es5/layers/carto-layer.js.map +1 -1
- package/dist/es5/layers/carto-tile-layer.js.map +1 -1
- package/dist/es5/layers/quadbin-layer.js +3 -1
- package/dist/es5/layers/quadbin-layer.js.map +1 -1
- package/dist/es5/layers/quadbin-tile-layer.js +8 -2
- package/dist/es5/layers/quadbin-tile-layer.js.map +1 -1
- package/dist/es5/layers/quadbin-utils.js +5 -3
- package/dist/es5/layers/quadbin-utils.js.map +1 -1
- package/dist/es5/layers/spatial-index-tile-layer.js +21 -0
- package/dist/es5/layers/spatial-index-tile-layer.js.map +1 -1
- package/dist/esm/api/carto-api-error.js +51 -0
- package/dist/esm/api/carto-api-error.js.map +1 -0
- package/dist/esm/api/index.js +1 -0
- package/dist/esm/api/index.js.map +1 -1
- package/dist/esm/api/layer-map.js +4 -1
- package/dist/esm/api/layer-map.js.map +1 -1
- package/dist/esm/api/maps-api-common.js +6 -0
- package/dist/esm/api/maps-api-common.js.map +1 -1
- package/dist/esm/api/maps-v3-client.js +64 -41
- package/dist/esm/api/maps-v3-client.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/layers/carto-layer.js.map +1 -1
- package/dist/esm/layers/carto-tile-layer.js.map +1 -1
- package/dist/esm/layers/quadbin-layer.js +3 -1
- package/dist/esm/layers/quadbin-layer.js.map +1 -1
- package/dist/esm/layers/quadbin-tile-layer.js +4 -4
- package/dist/esm/layers/quadbin-tile-layer.js.map +1 -1
- package/dist/esm/layers/quadbin-utils.js +4 -4
- package/dist/esm/layers/quadbin-utils.js.map +1 -1
- package/dist/esm/layers/spatial-index-tile-layer.js +20 -0
- package/dist/esm/layers/spatial-index-tile-layer.js.map +1 -1
- package/dist.min.js +24 -278
- package/package.json +13 -13
- package/src/api/carto-api-error.ts +67 -0
- package/src/api/index.ts +2 -0
- package/src/api/layer-map.ts +3 -1
- package/src/api/maps-api-common.ts +8 -0
- package/src/api/maps-v3-client.ts +42 -38
- package/src/index.ts +2 -1
- package/src/layers/carto-layer.ts +4 -3
- package/src/layers/carto-tile-layer.ts +1 -1
- package/src/layers/quadbin-layer.ts +4 -2
- package/src/layers/quadbin-tile-layer.ts +4 -2
- package/src/layers/quadbin-utils.ts +4 -4
- package/src/layers/spatial-index-tile-layer.ts +28 -1
- package/typed/api/carto-api-error.d.ts +24 -0
- package/typed/api/carto-api-error.d.ts.map +1 -0
- package/typed/api/index.d.ts +2 -0
- package/typed/api/index.d.ts.map +1 -1
- package/typed/api/index.js +3 -0
- package/typed/api/layer-map.d.ts.map +1 -1
- package/typed/api/layer-map.js +264 -0
- package/typed/api/maps-api-common.d.ts +7 -0
- package/typed/api/maps-api-common.d.ts.map +1 -1
- package/typed/api/maps-api-common.js +50 -0
- package/typed/api/maps-client.js +125 -0
- package/typed/api/maps-v3-client.d.ts.map +1 -1
- package/typed/api/maps-v3-client.js +304 -0
- package/typed/api/parseMap.js +178 -0
- package/typed/basemap.js +9 -0
- package/typed/config.js +35 -0
- package/typed/index.d.ts +2 -2
- package/typed/index.d.ts.map +1 -1
- package/typed/index.js +10 -0
- package/typed/layers/carto-layer.d.ts +3 -2
- package/typed/layers/carto-layer.d.ts.map +1 -1
- package/typed/layers/carto-layer.js +173 -0
- package/typed/layers/carto-tile-layer.js +105 -0
- package/typed/layers/h3-tile-layer.js +47 -0
- package/typed/layers/h3-tileset-2d.js +85 -0
- package/typed/layers/quadbin-layer.d.ts.map +1 -1
- package/typed/layers/quadbin-tile-layer.d.ts +4 -1
- package/typed/layers/quadbin-tile-layer.d.ts.map +1 -1
- package/typed/layers/quadbin-utils.d.ts +2 -2
- package/typed/layers/quadbin-utils.d.ts.map +1 -1
- package/typed/layers/quadkey-tile-layer.d.ts +21 -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.js +161 -0
- package/typed/layers/spatial-index-tile-layer.d.ts +11 -1
- package/typed/layers/spatial-index-tile-layer.d.ts.map +1 -1
- package/typed/layers/spatial-index-tile-layer.js +40 -0
- package/typed/style/color-bins-style.js +12 -0
- package/typed/style/color-categories-style.js +16 -0
- package/typed/style/color-continuous-style.js +12 -0
- package/typed/style/palette.js +62 -0
- package/typed/style/utils.js +15 -0
- package/typed/utils.js +4 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@deck.gl/carto",
|
|
3
3
|
"description": "CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "8.9.0-
|
|
5
|
+
"version": "8.9.0-beta.1",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -28,28 +28,28 @@
|
|
|
28
28
|
],
|
|
29
29
|
"sideEffects": false,
|
|
30
30
|
"scripts": {
|
|
31
|
-
"build-bundle": "
|
|
32
|
-
"prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env
|
|
31
|
+
"build-bundle": "ocular-bundle ./bundle.ts",
|
|
32
|
+
"prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env=dev"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@loaders.gl/gis": "^3.
|
|
36
|
-
"@loaders.gl/loader-utils": "^3.
|
|
37
|
-
"@loaders.gl/mvt": "^3.
|
|
38
|
-
"@loaders.gl/tiles": "^3.
|
|
35
|
+
"@loaders.gl/gis": "^3.3.0-alpha.10",
|
|
36
|
+
"@loaders.gl/loader-utils": "^3.3.0-alpha.10",
|
|
37
|
+
"@loaders.gl/mvt": "^3.3.0-alpha.10",
|
|
38
|
+
"@loaders.gl/tiles": "^3.3.0-alpha.10",
|
|
39
39
|
"@luma.gl/constants": "^8.5.16",
|
|
40
40
|
"@math.gl/web-mercator": "^3.6.2",
|
|
41
41
|
"cartocolor": "^4.0.2",
|
|
42
|
-
"d3-array": "^2.
|
|
43
|
-
"d3-color": "^
|
|
44
|
-
"d3-format": "^
|
|
45
|
-
"d3-scale": "^
|
|
42
|
+
"d3-array": "^3.2.0",
|
|
43
|
+
"d3-color": "^3.1.0",
|
|
44
|
+
"d3-format": "^3.1.0",
|
|
45
|
+
"d3-scale": "^4.0.0",
|
|
46
46
|
"h3-js": "^3.7.0",
|
|
47
47
|
"moment-timezone": "^0.5.33",
|
|
48
48
|
"pbf": "^3.2.1",
|
|
49
49
|
"quadbin": "^0.1.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@loaders.gl/schema": "^3.
|
|
52
|
+
"@loaders.gl/schema": "^3.3.0-alpha.10",
|
|
53
53
|
"@types/d3-array": "^3.0.2",
|
|
54
54
|
"@types/d3-color": "^1.4.2",
|
|
55
55
|
"@types/d3-scale": "^3.0.0"
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"@deck.gl/layers": "^8.0.0",
|
|
63
63
|
"@loaders.gl/core": "^3.0.0"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "47223d1ea084c3f9b0c9f0f9736682850bb5db85"
|
|
66
66
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {MapType, RequestType} from './maps-api-common';
|
|
2
|
+
|
|
3
|
+
export type APIErrorContext = {
|
|
4
|
+
requestType: RequestType;
|
|
5
|
+
mapId?: string;
|
|
6
|
+
connection?: string;
|
|
7
|
+
source?: string;
|
|
8
|
+
type?: MapType;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* Custom error for reported errors in CARTO Maps API.
|
|
14
|
+
* Provides useful debugging information in console and context for applications.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
export class CartoAPIError extends Error {
|
|
18
|
+
/** Source error from server */
|
|
19
|
+
error: Error;
|
|
20
|
+
|
|
21
|
+
/** Context (API call & parameters) in which error occured */
|
|
22
|
+
errorContext: APIErrorContext;
|
|
23
|
+
|
|
24
|
+
/** Response from server */
|
|
25
|
+
response?: Response;
|
|
26
|
+
|
|
27
|
+
constructor(error: Error, errorContext: APIErrorContext, response?: Response) {
|
|
28
|
+
let responseString = 'Failed to connect';
|
|
29
|
+
if (response) {
|
|
30
|
+
responseString = 'Server returned: ';
|
|
31
|
+
if (response.status === 400) {
|
|
32
|
+
responseString += 'Bad request';
|
|
33
|
+
} else if (response.status === 401 || response.status === 403) {
|
|
34
|
+
responseString += 'Unauthorized access';
|
|
35
|
+
} else if (response.status === 404) {
|
|
36
|
+
responseString += 'Not found';
|
|
37
|
+
} else {
|
|
38
|
+
responseString += 'Error';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
responseString += ` (${response.status}):`;
|
|
42
|
+
}
|
|
43
|
+
responseString += ` ${error.message || error}`;
|
|
44
|
+
|
|
45
|
+
let message = `${errorContext.requestType} API request failed`;
|
|
46
|
+
message += `\n${responseString}`;
|
|
47
|
+
for (const key of Object.keys(errorContext)) {
|
|
48
|
+
if (key === 'requestType') continue; // eslint-disable-line no-continue
|
|
49
|
+
message += `\n${formatErrorKey(key)}: ${errorContext[key]}`;
|
|
50
|
+
}
|
|
51
|
+
message += '\n';
|
|
52
|
+
|
|
53
|
+
super(message);
|
|
54
|
+
|
|
55
|
+
this.name = 'CartoAPIError';
|
|
56
|
+
this.response = response;
|
|
57
|
+
this.error = error;
|
|
58
|
+
this.errorContext = errorContext;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Converts camelCase to Camel Case
|
|
64
|
+
*/
|
|
65
|
+
function formatErrorKey(key) {
|
|
66
|
+
return key.replace(/([A-Z])/g, ' $1').replace(/^./, s => s.toUpperCase());
|
|
67
|
+
}
|
package/src/api/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export {CartoAPIError} from './carto-api-error';
|
|
2
|
+
export type {APIErrorContext} from './carto-api-error';
|
|
1
3
|
export {FORMATS, TILE_FORMATS, MAP_TYPES, API_VERSIONS} from './maps-api-common';
|
|
2
4
|
export type {QueryParameters} from './maps-api-common';
|
|
3
5
|
export {getDataV2, CONNECTIONS} from './maps-client';
|
package/src/api/layer-map.ts
CHANGED
|
@@ -435,7 +435,9 @@ export function getSizeAccessor(
|
|
|
435
435
|
) {
|
|
436
436
|
const scale = scaleType ? SCALE_FUNCS[scaleType as any]() : identity;
|
|
437
437
|
if (scaleType) {
|
|
438
|
-
|
|
438
|
+
if (aggregation !== 'count') {
|
|
439
|
+
scale.domain(calculateDomain(data, name, scaleType));
|
|
440
|
+
}
|
|
439
441
|
scale.range(range);
|
|
440
442
|
}
|
|
441
443
|
|
|
@@ -71,6 +71,14 @@ type MapInstantiationFormats = Record<
|
|
|
71
71
|
}
|
|
72
72
|
>;
|
|
73
73
|
|
|
74
|
+
export const REQUEST_TYPES = {
|
|
75
|
+
DATA: 'Map data',
|
|
76
|
+
INSTANTIATION: 'Map instantiation',
|
|
77
|
+
PUBLIC_MAP: 'Public map',
|
|
78
|
+
TILE_STATS: 'Tile stats'
|
|
79
|
+
} as const;
|
|
80
|
+
export type RequestType = ValuesOf<typeof REQUEST_TYPES>;
|
|
81
|
+
|
|
74
82
|
/**
|
|
75
83
|
* Simple encode parameter
|
|
76
84
|
*/
|
|
@@ -18,15 +18,19 @@ import {
|
|
|
18
18
|
MapType,
|
|
19
19
|
MAP_TYPES,
|
|
20
20
|
QueryParameters,
|
|
21
|
+
REQUEST_TYPES,
|
|
21
22
|
SchemaField,
|
|
22
23
|
TileFormat,
|
|
23
24
|
TILE_FORMATS
|
|
24
25
|
} from './maps-api-common';
|
|
26
|
+
|
|
27
|
+
import {APIErrorContext, CartoAPIError} from './carto-api-error';
|
|
28
|
+
|
|
25
29
|
import {parseMap} from './parseMap';
|
|
26
30
|
import {log} from '@deck.gl/core';
|
|
27
31
|
import {assert} from '../utils';
|
|
28
32
|
|
|
29
|
-
const MAX_GET_LENGTH =
|
|
33
|
+
const MAX_GET_LENGTH = 8192;
|
|
30
34
|
const DEFAULT_CLIENT = 'deck-gl-carto';
|
|
31
35
|
const V3_MINOR_VERSION = '3.1';
|
|
32
36
|
|
|
@@ -37,6 +41,7 @@ interface RequestParams {
|
|
|
37
41
|
headers?: Headers;
|
|
38
42
|
accessToken?: string;
|
|
39
43
|
body?: any;
|
|
44
|
+
errorContext: APIErrorContext;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
/**
|
|
@@ -47,7 +52,8 @@ async function request({
|
|
|
47
52
|
url,
|
|
48
53
|
headers: customHeaders,
|
|
49
54
|
accessToken,
|
|
50
|
-
body
|
|
55
|
+
body,
|
|
56
|
+
errorContext
|
|
51
57
|
}: RequestParams): Promise<Response> {
|
|
52
58
|
const headers: Headers = {
|
|
53
59
|
...customHeaders,
|
|
@@ -70,7 +76,7 @@ async function request({
|
|
|
70
76
|
body
|
|
71
77
|
});
|
|
72
78
|
} catch (error) {
|
|
73
|
-
throw new
|
|
79
|
+
throw new CartoAPIError(error as Error, errorContext);
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
82
|
|
|
@@ -79,13 +85,14 @@ async function requestJson<T = unknown>({
|
|
|
79
85
|
url,
|
|
80
86
|
headers,
|
|
81
87
|
accessToken,
|
|
82
|
-
body
|
|
88
|
+
body,
|
|
89
|
+
errorContext
|
|
83
90
|
}: RequestParams): Promise<T> {
|
|
84
|
-
const response = await request({method, url, headers, accessToken, body});
|
|
91
|
+
const response = await request({method, url, headers, accessToken, body, errorContext});
|
|
85
92
|
const json = await response.json();
|
|
86
93
|
|
|
87
94
|
if (!response.ok) {
|
|
88
|
-
|
|
95
|
+
throw new CartoAPIError(json.error, errorContext, response);
|
|
89
96
|
}
|
|
90
97
|
return json as T;
|
|
91
98
|
}
|
|
@@ -95,33 +102,19 @@ async function requestData({
|
|
|
95
102
|
url,
|
|
96
103
|
accessToken,
|
|
97
104
|
format,
|
|
98
|
-
body
|
|
105
|
+
body,
|
|
106
|
+
errorContext
|
|
99
107
|
}: RequestParams & {
|
|
100
108
|
format: Format;
|
|
101
109
|
}): Promise<Response | unknown> {
|
|
102
110
|
if (format === FORMATS.NDJSON) {
|
|
103
|
-
return request({method, url, accessToken, body});
|
|
111
|
+
return request({method, url, accessToken, body, errorContext});
|
|
104
112
|
}
|
|
105
113
|
|
|
106
|
-
const data = await requestJson<any>({method, url, accessToken, body});
|
|
114
|
+
const data = await requestJson<any>({method, url, accessToken, body, errorContext});
|
|
107
115
|
return data.rows ? data.rows : data;
|
|
108
116
|
}
|
|
109
117
|
|
|
110
|
-
/**
|
|
111
|
-
* Display proper message from Maps API error
|
|
112
|
-
*/
|
|
113
|
-
function dealWithError({response, error}: {response: Response; error?: string}): never {
|
|
114
|
-
switch (response.status) {
|
|
115
|
-
case 400:
|
|
116
|
-
throw new Error(`Bad request. ${error}`);
|
|
117
|
-
case 401:
|
|
118
|
-
case 403:
|
|
119
|
-
throw new Error(`Unauthorized access. ${error}`);
|
|
120
|
-
default:
|
|
121
|
-
throw new Error(error);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
118
|
type FetchLayerDataParams = {
|
|
126
119
|
type: MapType;
|
|
127
120
|
source: string;
|
|
@@ -211,17 +204,28 @@ export async function mapInstantiation({
|
|
|
211
204
|
})}`;
|
|
212
205
|
const {accessToken} = credentials;
|
|
213
206
|
|
|
207
|
+
const errorContext = {requestType: REQUEST_TYPES.INSTANTIATION, connection, type, source};
|
|
214
208
|
if (url.length > MAX_GET_LENGTH && type === MAP_TYPES.QUERY) {
|
|
215
209
|
// need to be a POST request
|
|
216
210
|
const body = JSON.stringify({
|
|
217
211
|
q: source,
|
|
218
212
|
client: clientId || DEFAULT_CLIENT,
|
|
213
|
+
aggregationResLevel,
|
|
214
|
+
aggregationExp,
|
|
215
|
+
geoColumn,
|
|
219
216
|
queryParameters
|
|
220
217
|
});
|
|
221
|
-
return await requestJson({
|
|
218
|
+
return await requestJson({
|
|
219
|
+
method: 'POST',
|
|
220
|
+
url: baseUrl,
|
|
221
|
+
headers,
|
|
222
|
+
accessToken,
|
|
223
|
+
body,
|
|
224
|
+
errorContext
|
|
225
|
+
});
|
|
222
226
|
}
|
|
223
227
|
|
|
224
|
-
return await requestJson({url, headers, accessToken});
|
|
228
|
+
return await requestJson({url, headers, accessToken, errorContext});
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
function getUrlFromMetadata(metadata: MapInstantiation, format: Format): string | null {
|
|
@@ -267,13 +271,6 @@ function checkFetchLayerDataParameters({
|
|
|
267
271
|
assert(!aggregationExp, 'Have aggregationExp, but geoColumn parameter is missing');
|
|
268
272
|
assert(!aggregationResLevel, 'Have aggregationResLevel, but geoColumn parameter is missing');
|
|
269
273
|
}
|
|
270
|
-
|
|
271
|
-
if (!aggregationExp) {
|
|
272
|
-
assert(
|
|
273
|
-
!aggregationResLevel,
|
|
274
|
-
'Have aggregationResLevel, but aggregationExp parameter is missing'
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
274
|
}
|
|
278
275
|
|
|
279
276
|
export interface FetchLayerDataResult {
|
|
@@ -314,7 +311,8 @@ export async function fetchLayerData({
|
|
|
314
311
|
queryParameters
|
|
315
312
|
});
|
|
316
313
|
|
|
317
|
-
const
|
|
314
|
+
const errorContext = {requestType: REQUEST_TYPES.DATA, connection, type, source};
|
|
315
|
+
const data = await requestData({url, format: mapFormat, accessToken, errorContext});
|
|
318
316
|
const result: FetchLayerDataResult = {data, format: mapFormat, schema: metadata.schema};
|
|
319
317
|
return result;
|
|
320
318
|
}
|
|
@@ -444,7 +442,8 @@ async function _fetchMapDataset(
|
|
|
444
442
|
dataset.cache = cache;
|
|
445
443
|
|
|
446
444
|
// Only fetch if the data has changed
|
|
447
|
-
|
|
445
|
+
const errorContext = {requestType: REQUEST_TYPES.DATA, connection, type, source};
|
|
446
|
+
dataset.data = await requestData({url, format: mapFormat, accessToken, errorContext});
|
|
448
447
|
|
|
449
448
|
return true;
|
|
450
449
|
}
|
|
@@ -465,7 +464,8 @@ async function _fetchTilestats(
|
|
|
465
464
|
// MAP_TYPE.TABLE
|
|
466
465
|
url += `${source}/${attribute}`;
|
|
467
466
|
}
|
|
468
|
-
const
|
|
467
|
+
const errorContext = {requestType: REQUEST_TYPES.TILE_STATS, connection, type, source};
|
|
468
|
+
const stats = await requestData({url, format: FORMATS.JSON, accessToken, errorContext});
|
|
469
469
|
|
|
470
470
|
// Replace tilestats for attribute with value from API
|
|
471
471
|
const {attributes} = dataset.data.tilestats.layers[0];
|
|
@@ -562,7 +562,8 @@ export async function fetchMap({
|
|
|
562
562
|
}
|
|
563
563
|
|
|
564
564
|
const url = `${localCreds.mapsUrl}/public/${cartoMapId}`;
|
|
565
|
-
const
|
|
565
|
+
const errorContext = {requestType: REQUEST_TYPES.PUBLIC_MAP, mapId: cartoMapId};
|
|
566
|
+
const map = await requestJson<any>({url, headers, accessToken, errorContext});
|
|
566
567
|
|
|
567
568
|
// Periodically check if the data has changed. Note that this
|
|
568
569
|
// will not update when a map is published.
|
|
@@ -588,7 +589,10 @@ export async function fetchMap({
|
|
|
588
589
|
if (geojsonDatasetIds.includes(dataset.id)) {
|
|
589
590
|
const {config} = geojsonLayers.find(({config}) => config.dataId === dataset.id);
|
|
590
591
|
dataset.format = 'geojson';
|
|
591
|
-
|
|
592
|
+
// Support for very old maps. geoColumn was not stored in the past
|
|
593
|
+
if (!dataset.geoColumn && config.columns.geojson) {
|
|
594
|
+
dataset.geoColumn = config.columns.geojson;
|
|
595
|
+
}
|
|
592
596
|
}
|
|
593
597
|
});
|
|
594
598
|
|
package/src/index.ts
CHANGED
|
@@ -12,10 +12,11 @@ export {
|
|
|
12
12
|
TILE_FORMATS,
|
|
13
13
|
MAP_TYPES,
|
|
14
14
|
API_VERSIONS,
|
|
15
|
+
CartoAPIError,
|
|
15
16
|
fetchLayerData,
|
|
16
17
|
fetchMap,
|
|
17
18
|
getDataV2 as _getDataV2,
|
|
18
19
|
mapInstantiation as _mapInstantiation
|
|
19
20
|
} from './api';
|
|
20
|
-
export type {QueryParameters} from './api';
|
|
21
|
+
export type {APIErrorContext, QueryParameters} from './api';
|
|
21
22
|
export type {CartoLayerProps} from './layers/carto-layer';
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
import {MVTLayer} from '@deck.gl/geo-layers';
|
|
11
11
|
import {fetchLayerData, getDataV2, API_VERSIONS} from '../api';
|
|
12
|
+
import {CartoAPIError} from '../api/carto-api-error';
|
|
12
13
|
import {layerFromTileDataset} from '../api/layer-map';
|
|
13
14
|
import {
|
|
14
15
|
COLUMNS_SUPPORT,
|
|
@@ -145,9 +146,9 @@ type _CartoLayerProps = {
|
|
|
145
146
|
/**
|
|
146
147
|
* Called when the request to the CARTO Maps API failed.
|
|
147
148
|
*
|
|
148
|
-
* By default the
|
|
149
|
+
* By default the CartoAPIError is thrown.
|
|
149
150
|
*/
|
|
150
|
-
onDataError?: (err:
|
|
151
|
+
onDataError?: (err: CartoAPIError) => void;
|
|
151
152
|
|
|
152
153
|
clientId?: string;
|
|
153
154
|
|
|
@@ -272,7 +273,7 @@ export default class CartoLayer<ExtraProps = {}> extends CompositeLayer<
|
|
|
272
273
|
});
|
|
273
274
|
} catch (err) {
|
|
274
275
|
if (this.props.onDataError) {
|
|
275
|
-
this.props.onDataError(err as
|
|
276
|
+
this.props.onDataError(err as CartoAPIError);
|
|
276
277
|
} else {
|
|
277
278
|
throw err;
|
|
278
279
|
}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
_TileLoadProps as TileLoadProps
|
|
14
14
|
} from '@deck.gl/geo-layers';
|
|
15
15
|
import {GeoJsonLayer} from '@deck.gl/layers';
|
|
16
|
-
import {binaryToGeojson
|
|
16
|
+
import {binaryToGeojson} from '@loaders.gl/gis';
|
|
17
17
|
import type {BinaryFeatures} from '@loaders.gl/schema';
|
|
18
18
|
import {TileFormat, TILE_FORMATS} from '../api/maps-api-common';
|
|
19
19
|
import type {Feature} from 'geojson';
|
|
@@ -30,14 +30,16 @@ export default class QuadbinLayer<DataT = any, ExtraProps = {}> extends GeoCellL
|
|
|
30
30
|
static defaultProps = defaultProps;
|
|
31
31
|
|
|
32
32
|
indexToBounds(): Partial<GeoCellLayer['props']> | null {
|
|
33
|
-
const {data, getQuadbin} = this.props;
|
|
33
|
+
const {data, extruded, getQuadbin} = this.props;
|
|
34
|
+
// To avoid z-fighting reduce polygon footprint when extruding
|
|
35
|
+
const coverage = extruded ? 0.99 : 1;
|
|
34
36
|
|
|
35
37
|
return {
|
|
36
38
|
data,
|
|
37
39
|
_normalize: false,
|
|
38
40
|
positionFormat: 'XY',
|
|
39
41
|
|
|
40
|
-
getPolygon: (x: DataT, objectInfo) => getQuadbinPolygon(getQuadbin(x, objectInfo))
|
|
42
|
+
getPolygon: (x: DataT, objectInfo) => getQuadbinPolygon(getQuadbin(x, objectInfo), coverage)
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
}
|
|
@@ -9,12 +9,14 @@ import {
|
|
|
9
9
|
import QuadbinLayer, {QuadbinLayerProps} from './quadbin-layer';
|
|
10
10
|
import QuadbinTileset2D from './quadbin-tileset-2d';
|
|
11
11
|
import SpatialIndexTileLayer from './spatial-index-tile-layer';
|
|
12
|
+
import {hexToBigInt} from 'quadbin';
|
|
12
13
|
|
|
13
|
-
const renderSubLayers = props => {
|
|
14
|
+
export const renderSubLayers = props => {
|
|
14
15
|
const {data} = props;
|
|
15
16
|
if (!data || !data.length) return null;
|
|
17
|
+
const isBigInt = typeof data[0].id === 'bigint';
|
|
16
18
|
return new QuadbinLayer(props, {
|
|
17
|
-
getQuadbin: d => d.id
|
|
19
|
+
getQuadbin: isBigInt ? d => d.id : d => hexToBigInt(d.id)
|
|
18
20
|
});
|
|
19
21
|
};
|
|
20
22
|
|
|
@@ -3,18 +3,18 @@ import {cellToTile} from 'quadbin';
|
|
|
3
3
|
|
|
4
4
|
const TILE_SIZE = 512;
|
|
5
5
|
|
|
6
|
-
export function quadbinToWorldBounds(quadbin: bigint): [number[], number[]] {
|
|
6
|
+
export function quadbinToWorldBounds(quadbin: bigint, coverage: number): [number[], number[]] {
|
|
7
7
|
const {x, y, z} = cellToTile(quadbin);
|
|
8
8
|
const mask = 1 << z;
|
|
9
9
|
const scale = mask / TILE_SIZE;
|
|
10
10
|
return [
|
|
11
11
|
[x / scale, TILE_SIZE - y / scale],
|
|
12
|
-
[(x +
|
|
12
|
+
[(x + coverage) / scale, TILE_SIZE - (y + coverage) / scale]
|
|
13
13
|
];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export function getQuadbinPolygon(quadbin: bigint): number[] {
|
|
17
|
-
const [topLeft, bottomRight] = quadbinToWorldBounds(quadbin);
|
|
16
|
+
export function getQuadbinPolygon(quadbin: bigint, coverage = 1): number[] {
|
|
17
|
+
const [topLeft, bottomRight] = quadbinToWorldBounds(quadbin, coverage);
|
|
18
18
|
const [w, n] = worldToLngLat(topLeft);
|
|
19
19
|
const [e, s] = worldToLngLat(bottomRight);
|
|
20
20
|
return [e, n, e, s, w, s, w, n, e, n];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {registerLoaders} from '@loaders.gl/core';
|
|
2
|
+
import {DefaultProps, UpdateParameters} from '@deck.gl/core';
|
|
2
3
|
import CartoSpatialTileLoader from './schema/carto-spatial-tile-loader';
|
|
3
4
|
registerLoaders([CartoSpatialTileLoader]);
|
|
4
5
|
|
|
@@ -15,8 +16,25 @@ function isFeatureIdDefined(value: unknown): boolean {
|
|
|
15
16
|
return value !== undefined && value !== null && value !== '';
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
const defaultProps: DefaultProps<SpatialIndexTileLayerProps> = {
|
|
20
|
+
aggregationResLevel: 4
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** All properties supported by SpatialIndexTileLayer. */
|
|
24
|
+
export type SpatialIndexTileLayerProps<DataT = any> = _SpatialIndexTileLayerProps<DataT> &
|
|
25
|
+
TileLayer<DataT>;
|
|
26
|
+
|
|
27
|
+
/** Properties added by SpatialIndexTileLayer. */
|
|
28
|
+
type _SpatialIndexTileLayerProps<DataT = any> = {
|
|
29
|
+
aggregationResLevel?: number;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default class SpatialIndexTileLayer<DataT = any, ExtraProps = {}> extends TileLayer<
|
|
33
|
+
DataT,
|
|
34
|
+
ExtraProps & Required<_SpatialIndexTileLayerProps<DataT>>
|
|
35
|
+
> {
|
|
19
36
|
static layerName = 'SpatialIndexTileLayer';
|
|
37
|
+
static defaultProps = defaultProps;
|
|
20
38
|
|
|
21
39
|
getTileData(tile: TileLoadProps) {
|
|
22
40
|
const {data, getTileData, fetch} = this.props;
|
|
@@ -48,6 +66,15 @@ export default class SpatialIndexTileLayer<ExtraProps = {}> extends TileLayer<an
|
|
|
48
66
|
return fetch(tile.url, {propName: 'data', layer: this, loadOptions, signal});
|
|
49
67
|
}
|
|
50
68
|
|
|
69
|
+
updateState(params: UpdateParameters<this>) {
|
|
70
|
+
const {props, oldProps} = params;
|
|
71
|
+
if (props.aggregationResLevel !== oldProps.aggregationResLevel) {
|
|
72
|
+
// Tileset cache is invalid when resLevel changes
|
|
73
|
+
this.setState({tileset: null});
|
|
74
|
+
}
|
|
75
|
+
super.updateState(params);
|
|
76
|
+
}
|
|
77
|
+
|
|
51
78
|
protected _updateAutoHighlight(info: PickingInfo): void {
|
|
52
79
|
const {hoveredFeatureId} = this.state;
|
|
53
80
|
const hoveredFeature = info.object;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { MapType, RequestType } from './maps-api-common';
|
|
2
|
+
export declare type APIErrorContext = {
|
|
3
|
+
requestType: RequestType;
|
|
4
|
+
mapId?: string;
|
|
5
|
+
connection?: string;
|
|
6
|
+
source?: string;
|
|
7
|
+
type?: MapType;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* Custom error for reported errors in CARTO Maps API.
|
|
12
|
+
* Provides useful debugging information in console and context for applications.
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
export declare class CartoAPIError extends Error {
|
|
16
|
+
/** Source error from server */
|
|
17
|
+
error: Error;
|
|
18
|
+
/** Context (API call & parameters) in which error occured */
|
|
19
|
+
errorContext: APIErrorContext;
|
|
20
|
+
/** Response from server */
|
|
21
|
+
response?: Response;
|
|
22
|
+
constructor(error: Error, errorContext: APIErrorContext, response?: Response);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=carto-api-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carto-api-error.d.ts","sourceRoot":"","sources":["../../src/api/carto-api-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAEvD,oBAAY,eAAe,GAAG;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,+BAA+B;IAC/B,KAAK,EAAE,KAAK,CAAC;IAEb,6DAA6D;IAC7D,YAAY,EAAE,eAAe,CAAC;IAE9B,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC;gBAER,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,QAAQ;CAiC7E"}
|
package/typed/api/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { CartoAPIError } from './carto-api-error';
|
|
2
|
+
export type { APIErrorContext } from './carto-api-error';
|
|
1
3
|
export { FORMATS, TILE_FORMATS, MAP_TYPES, API_VERSIONS } from './maps-api-common';
|
|
2
4
|
export type { QueryParameters } from './maps-api-common';
|
|
3
5
|
export { getDataV2, CONNECTIONS } from './maps-client';
|
package/typed/api/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAC,MAAM,mBAAmB,CAAC;AACjF,YAAY,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAC,SAAS,EAAE,WAAW,EAAC,MAAM,eAAe,CAAC;AACrD,OAAO,EAAC,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAC,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAC,MAAM,mBAAmB,CAAC;AACjF,YAAY,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAC,SAAS,EAAE,WAAW,EAAC,MAAM,eAAe,CAAC;AACrD,OAAO,EAAC,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAC,MAAM,kBAAkB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-map.d.ts","sourceRoot":"","sources":["../../src/api/layer-map.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,aAAa,EACb,aAAa,EACb,SAAS,EACT,cAAc,EACf,MAAM,UAAU,CAAC;AAIlB,OAAO,EAAC,QAAQ,EAAE,KAAK,EAAE,cAAc,IAAI,aAAa,EAAC,MAAM,eAAe,CAAC;AAG/E,OAAO,EAAiB,QAAQ,EAAC,MAAM,qBAAqB,CAAC;AAE7D,OAAO,cAAc,MAAM,4BAA4B,CAAC;AACxD,OAAO,WAAW,MAAM,yBAAyB,CAAC;AAClD,OAAO,gBAAgB,MAAM,8BAA8B,CAAC;AAG5D,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,qBAAqB,EACrB,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB,QAAA,MAAM,WAAW;;;;;;;;;CAShB,CAAC;AACF,oBAAY,UAAU,GAAG,MAAM,OAAO,WAAW,CAAC;AAQlD,eAAO,MAAM,WAAW;;;;;CAKvB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;CAIvB,CAAC;AAuEF,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,UAAU,GAClB;IAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAAC,OAAO,EAAE,GAAG,CAAC;IAAC,YAAY,EAAE,GAAG,CAAA;CAAC,CA6DhE;AAED,wBAAgB,oBAAoB,CAClC,WAAW,2BAAkC,EAC7C,MAAM,EAAE,MAAM,GACb,OAAO,cAAc,GAAG,OAAO,WAAW,GAAG,OAAO,QAAQ,GAAG,OAAO,gBAAgB,CAaxF;AA2CD,iBAAS,gBAAgB,CAAC,MAAM,KAAA,EAAE,SAAS,EAAE,UAAU,OActD;AA8BD,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,UAE9C;AAqBD,wBAAgB,qBAAqB,CAAC,EAAC,IAAI,EAAC;;CAAA,EAAE,gBAAgB,KAAA,EAAE,IAAI,EAAE,GAAG,OAIxE;AAED,wBAAgB,gBAAgB,CAC9B,EAAC,IAAI,EAAC;;CAAA,EACN,SAAS,EAAE,UAAU,EACrB,EAAC,WAAW,EAAE,KAAK,EAAE,EAAC,MAAM,EAAE,QAAQ,EAAC,EAAC;;;;;;CAAA,EACxC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE,GAAG,OAmCV;AAKD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,EAC5C,KAAK,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,EAC5C,EAAC,WAAW,EAAE,WAAW,EAAE,cAAc,EAAC;;;;CAAA,EAC1C,IAAI,EAAE,GAAG,OAgCV;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,GAAG,MAAM,CAK7F;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAEpF;AAED,wBAAgB,eAAe,CAC7B,EAAC,IAAI,EAAC;;CAAA,EACN,SAAS,EAAE,UAAU,GAAG,SAAS,EACjC,WAAW,KAAA,EACX,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,SAAS,EAClC,IAAI,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"layer-map.d.ts","sourceRoot":"","sources":["../../src/api/layer-map.ts"],"names":[],"mappings":"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"}
|