@deck.gl/carto 9.0.16 → 9.0.17

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
- "version": "9.0.16",
6
+ "version": "9.0.17",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -73,5 +73,5 @@
73
73
  "@deck.gl/layers": "^9.0.0",
74
74
  "@loaders.gl/core": "^4.2.0"
75
75
  },
76
- "gitHead": "87e1629767fae5167a43dc9fa04786a16879f7aa"
76
+ "gitHead": "203d25c47f421a29d607a2a6fd9e1ef50f67b2bf"
77
77
  }
@@ -16,7 +16,15 @@ export class CartoAPIError extends Error {
16
16
  /** Response from server */
17
17
  response?: Response;
18
18
 
19
- constructor(error: Error, errorContext: APIErrorContext, response?: Response) {
19
+ /** JSON Response from server */
20
+ responseJson?: any;
21
+
22
+ constructor(
23
+ error: Error,
24
+ errorContext: APIErrorContext,
25
+ response?: Response,
26
+ responseJson?: any
27
+ ) {
20
28
  let responseString = 'Failed to connect';
21
29
  if (response) {
22
30
  responseString = 'Server returned: ';
@@ -46,6 +54,7 @@ export class CartoAPIError extends Error {
46
54
 
47
55
  this.name = 'CartoAPIError';
48
56
  this.response = response;
57
+ this.responseJson = responseJson;
49
58
  this.error = error;
50
59
  this.errorContext = errorContext;
51
60
  }
package/src/api/common.ts CHANGED
@@ -1,16 +1,4 @@
1
- import {VERSION} from '@deck.gl/core';
2
-
3
1
  export const DEFAULT_API_BASE_URL = 'https://gcp-us-east1.api.carto.com';
4
2
  export const DEFAULT_CLIENT = 'deck-gl-carto';
5
3
  export const V3_MINOR_VERSION = '3.4';
6
4
  export const MAX_GET_LENGTH = 8192;
7
-
8
- export const DEFAULT_PARAMETERS = {
9
- v: V3_MINOR_VERSION,
10
- deckglVersion: VERSION
11
- };
12
-
13
- export const DEFAULT_HEADERS = {
14
- Accept: 'application/json',
15
- 'Content-Type': 'application/json'
16
- };
@@ -1,37 +1,45 @@
1
+ import {VERSION} from '@deck.gl/core';
1
2
  import {isPureObject} from '../utils';
2
3
  import {CartoAPIError} from './carto-api-error';
3
- import {DEFAULT_HEADERS, DEFAULT_PARAMETERS, MAX_GET_LENGTH} from './common';
4
+ import {MAX_GET_LENGTH, V3_MINOR_VERSION} from './common';
4
5
  import type {APIErrorContext} from './types';
5
6
 
6
7
  /**
7
- * Simple encode parameter
8
+ * Parameters added to all requests issued with `requestWithParameters()`.
9
+ * These parameters override parameters already in the base URL, but not
10
+ * user-provided parameters.
8
11
  */
9
- function encodeParameter(name: string, value: unknown): string {
10
- if (isPureObject(value) || Array.isArray(value)) {
11
- return `${name}=${encodeURIComponent(JSON.stringify(value))}`;
12
- }
13
- return `${name}=${encodeURIComponent(value as string | boolean | number)}`;
14
- }
12
+ const DEFAULT_PARAMETERS = {
13
+ v: V3_MINOR_VERSION,
14
+ deckglVersion: VERSION
15
+ };
16
+
17
+ const DEFAULT_HEADERS = {
18
+ Accept: 'application/json',
19
+ 'Content-Type': 'application/json'
20
+ };
15
21
 
16
22
  const REQUEST_CACHE = new Map<string, Promise<unknown>>();
23
+
17
24
  export async function requestWithParameters<T = any>({
18
25
  baseUrl,
19
- parameters,
20
- headers: customHeaders,
26
+ parameters = {},
27
+ headers: customHeaders = {},
21
28
  errorContext
22
29
  }: {
23
30
  baseUrl: string;
24
31
  parameters?: Record<string, unknown>;
25
- headers: Record<string, string>;
32
+ headers?: Record<string, string>;
26
33
  errorContext: APIErrorContext;
27
34
  }): Promise<T> {
28
35
  parameters = {...DEFAULT_PARAMETERS, ...parameters};
29
- const key = createCacheKey(baseUrl, parameters || {}, customHeaders || {});
36
+ baseUrl = excludeURLParameters(baseUrl, Object.keys(parameters));
37
+ const key = createCacheKey(baseUrl, parameters, customHeaders);
30
38
  if (REQUEST_CACHE.has(key)) {
31
39
  return REQUEST_CACHE.get(key) as Promise<T>;
32
40
  }
33
41
 
34
- const url = parameters ? createURLWithParameters(baseUrl, parameters) : baseUrl;
42
+ const url = createURLWithParameters(baseUrl, parameters);
35
43
  const headers = {...DEFAULT_HEADERS, ...customHeaders};
36
44
 
37
45
  /* global fetch */
@@ -41,12 +49,14 @@ export async function requestWithParameters<T = any>({
41
49
  : fetch(url, {headers});
42
50
 
43
51
  let response: Response | undefined;
52
+ let responseJson;
44
53
  const jsonPromise: Promise<T> = fetchPromise
45
54
  .then((_response: Response) => {
46
55
  response = _response;
47
56
  return response.json();
48
57
  })
49
58
  .then((json: any) => {
59
+ responseJson = json;
50
60
  if (!response || !response.ok) {
51
61
  throw new Error(json.error);
52
62
  }
@@ -54,7 +64,7 @@ export async function requestWithParameters<T = any>({
54
64
  })
55
65
  .catch((error: Error) => {
56
66
  REQUEST_CACHE.delete(key);
57
- throw new CartoAPIError(error, errorContext, response);
67
+ throw new CartoAPIError(error, errorContext, response, responseJson);
58
68
  });
59
69
 
60
70
  REQUEST_CACHE.set(key, jsonPromise);
@@ -71,9 +81,35 @@ function createCacheKey(
71
81
  return JSON.stringify({baseUrl, parameters: parameterEntries, headers: headerEntries});
72
82
  }
73
83
 
74
- function createURLWithParameters(baseUrl: string, parameters: Record<string, unknown>): string {
75
- const encodedParameters = Object.entries(parameters).map(([key, value]) =>
76
- encodeParameter(key, value)
77
- );
78
- return `${baseUrl}?${encodedParameters.join('&')}`;
84
+ /**
85
+ * Appends query string parameters to a URL. Existing URL parameters are kept,
86
+ * unless there is a conflict, in which case the new parameters override
87
+ * those already in the URL.
88
+ */
89
+ function createURLWithParameters(
90
+ baseUrlString: string,
91
+ parameters: Record<string, unknown>
92
+ ): string {
93
+ const baseUrl = new URL(baseUrlString);
94
+ for (const [key, value] of Object.entries(parameters)) {
95
+ if (isPureObject(value) || Array.isArray(value)) {
96
+ baseUrl.searchParams.set(key, JSON.stringify(value));
97
+ } else {
98
+ baseUrl.searchParams.set(key, (value as string | boolean | number).toString());
99
+ }
100
+ }
101
+ return baseUrl.toString();
102
+ }
103
+
104
+ /**
105
+ * Deletes query string parameters from a URL.
106
+ */
107
+ function excludeURLParameters(baseUrlString: string, parameters: string[]) {
108
+ const baseUrl = new URL(baseUrlString);
109
+ for (const param of parameters) {
110
+ if (baseUrl.searchParams.has(param)) {
111
+ baseUrl.searchParams.delete(param);
112
+ }
113
+ }
114
+ return baseUrl.toString();
79
115
  }
package/src/api/types.ts CHANGED
@@ -66,11 +66,11 @@ export interface Filters {
66
66
  }
67
67
 
68
68
  interface Filter {
69
- [FilterTypes.In]: number[];
70
- [FilterTypes.Between]: number[][];
71
- [FilterTypes.ClosedOpen]: number[][];
72
- [FilterTypes.Time]: number[][];
73
- [FilterTypes.StringSearch]: string[];
69
+ [FilterTypes.In]?: number[];
70
+ [FilterTypes.Between]?: number[][];
71
+ [FilterTypes.ClosedOpen]?: number[][];
72
+ [FilterTypes.Time]?: number[][];
73
+ [FilterTypes.StringSearch]?: string[];
74
74
  }
75
75
 
76
76
  export enum FilterTypes {
@@ -80,7 +80,16 @@ class QuadbinHeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends C
80
80
  static defaultProps = defaultProps;
81
81
 
82
82
  renderLayers(): Layer {
83
- const {getWeight, colorDomain, colorRange, radiusPixels, _subLayerProps} = this.props;
83
+ const {
84
+ data,
85
+ getWeight,
86
+ colorDomain,
87
+ colorRange,
88
+ radiusPixels,
89
+ _subLayerProps,
90
+ updateTriggers,
91
+ ...tileLayerProps
92
+ } = this.props;
84
93
 
85
94
  // Inject modified polygon layer as sublayer into TileLayer
86
95
  const subLayerProps = {
@@ -103,9 +112,10 @@ class QuadbinHeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends C
103
112
  : encodeWeight(getWeight);
104
113
 
105
114
  return new PostProcessQuadbinTileLayer(
115
+ tileLayerProps as Omit<QuadbinTileLayerProps, 'data'>,
106
116
  this.getSubLayerProps({
107
117
  id: 'heatmap',
108
- data: this.props.data,
118
+ data,
109
119
 
110
120
  getFillColor,
111
121
 
@@ -115,7 +125,7 @@ class QuadbinHeatmapTileLayer<DataT = any, ExtraProps extends {} = {}> extends C
115
125
  _subLayerProps: subLayerProps,
116
126
 
117
127
  updateTriggers: {
118
- getPosition: this.props.updateTriggers.getWeight
128
+ getPosition: updateTriggers.getWeight
119
129
  }
120
130
  })
121
131
  );
@@ -1,12 +1,17 @@
1
1
  import {baseSource} from './base-source';
2
- import type {SourceOptions, TilejsonResult, TilesetSourceOptions} from './types';
2
+ import type {FilterOptions, SourceOptions, TilejsonResult, TilesetSourceOptions} from './types';
3
3
 
4
- export type RasterSourceOptions = SourceOptions & TilesetSourceOptions;
5
- type UrlParameters = {name: string};
4
+ export type RasterSourceOptions = SourceOptions & TilesetSourceOptions & FilterOptions;
5
+ type UrlParameters = {
6
+ name: string;
7
+ filters?: Record<string, unknown>;
8
+ };
6
9
 
7
10
  export const rasterSource = async function (options: RasterSourceOptions): Promise<TilejsonResult> {
8
- const {tableName} = options;
11
+ const {tableName, filters} = options;
9
12
  const urlParameters: UrlParameters = {name: tableName};
10
-
13
+ if (filters) {
14
+ urlParameters.filters = filters;
15
+ }
11
16
  return baseSource<UrlParameters>('raster', options, urlParameters) as Promise<TilejsonResult>;
12
17
  };