@carto/api-client 0.3.0 → 0.4.0-alpha.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.
Files changed (66) hide show
  1. package/build/api/carto-api-error.d.ts +18 -0
  2. package/build/api/endpoints.d.ts +22 -0
  3. package/build/api/index.d.ts +4 -0
  4. package/build/api/query.d.ts +3 -0
  5. package/build/api/request-with-parameters.d.ts +8 -0
  6. package/build/api/types.d.ts +227 -0
  7. package/build/api-client.cjs +487 -24
  8. package/build/api-client.cjs.map +1 -1
  9. package/build/api-client.modern.js +423 -25
  10. package/build/api-client.modern.js.map +1 -1
  11. package/build/constants.d.ts +8 -0
  12. package/build/index.d.ts +6 -1
  13. package/build/sources/base-source.d.ts +4 -0
  14. package/build/sources/boundary-query-source.d.ts +9 -0
  15. package/build/sources/boundary-table-source.d.ts +7 -0
  16. package/build/sources/h3-query-source.d.ts +3 -0
  17. package/build/sources/h3-table-source.d.ts +3 -0
  18. package/build/sources/h3-tileset-source.d.ts +3 -0
  19. package/build/sources/index.d.ts +27 -5
  20. package/build/sources/quadbin-query-source.d.ts +3 -0
  21. package/build/sources/quadbin-table-source.d.ts +3 -0
  22. package/build/sources/quadbin-tileset-source.d.ts +3 -0
  23. package/build/sources/raster-source.d.ts +3 -0
  24. package/build/sources/types.d.ts +208 -85
  25. package/build/sources/vector-query-source.d.ts +3 -0
  26. package/build/sources/vector-table-source.d.ts +3 -0
  27. package/build/sources/vector-tileset-source.d.ts +3 -0
  28. package/build/utils.d.ts +4 -0
  29. package/build/widget-sources/index.d.ts +5 -0
  30. package/build/widget-sources/types.d.ts +95 -0
  31. package/build/{sources → widget-sources}/widget-base-source.d.ts +1 -1
  32. package/build/{sources → widget-sources}/widget-query-source.d.ts +1 -1
  33. package/build/{sources → widget-sources}/widget-table-source.d.ts +1 -1
  34. package/build/{sources → widget-sources}/wrappers.d.ts +1 -1
  35. package/package.json +4 -3
  36. package/src/api/carto-api-error.ts +72 -0
  37. package/src/api/endpoints.ts +82 -0
  38. package/src/api/index.ts +17 -0
  39. package/src/api/query.ts +56 -0
  40. package/src/api/request-with-parameters.ts +139 -0
  41. package/src/api/types.ts +301 -0
  42. package/src/constants.ts +13 -0
  43. package/src/global.d.ts +3 -0
  44. package/src/index.ts +10 -1
  45. package/src/sources/base-source.ts +100 -0
  46. package/src/sources/boundary-query-source.ts +53 -0
  47. package/src/sources/boundary-table-source.ts +41 -0
  48. package/src/sources/h3-query-source.ts +63 -0
  49. package/src/sources/h3-table-source.ts +59 -0
  50. package/src/sources/h3-tileset-source.ts +26 -0
  51. package/src/sources/index.ts +49 -5
  52. package/src/sources/quadbin-query-source.ts +64 -0
  53. package/src/sources/quadbin-table-source.ts +60 -0
  54. package/src/sources/quadbin-tileset-source.ts +26 -0
  55. package/src/sources/raster-source.ts +34 -0
  56. package/src/sources/types.ts +226 -90
  57. package/src/sources/vector-query-source.ts +65 -0
  58. package/src/sources/vector-table-source.ts +59 -0
  59. package/src/sources/vector-tileset-source.ts +26 -0
  60. package/src/utils.ts +8 -0
  61. package/src/widget-sources/index.ts +5 -0
  62. package/src/widget-sources/types.ts +105 -0
  63. package/src/{sources → widget-sources}/widget-base-source.ts +4 -3
  64. package/src/{sources → widget-sources}/widget-query-source.ts +1 -1
  65. package/src/{sources → widget-sources}/widget-table-source.ts +1 -1
  66. package/src/{sources → widget-sources}/wrappers.ts +1 -21
@@ -0,0 +1,56 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {SOURCE_DEFAULTS} from '../sources/index';
6
+ import type {
7
+ SourceOptions,
8
+ QuerySourceOptions,
9
+ QueryResult,
10
+ } from '../sources/types';
11
+ import {buildQueryUrl} from './endpoints';
12
+ import {requestWithParameters} from './request-with-parameters';
13
+ import {APIErrorContext} from './types';
14
+
15
+ export type QueryOptions = SourceOptions &
16
+ Omit<QuerySourceOptions, 'spatialDataColumn'>;
17
+ type UrlParameters = {q: string; queryParameters?: string};
18
+
19
+ export const query = async function (
20
+ options: QueryOptions
21
+ ): Promise<QueryResult> {
22
+ const {
23
+ apiBaseUrl = SOURCE_DEFAULTS.apiBaseUrl,
24
+ clientId = SOURCE_DEFAULTS.clientId,
25
+ maxLengthURL = SOURCE_DEFAULTS.maxLengthURL,
26
+ connectionName,
27
+ sqlQuery,
28
+ queryParameters,
29
+ } = options;
30
+ const urlParameters: UrlParameters = {q: sqlQuery};
31
+
32
+ if (queryParameters) {
33
+ urlParameters.queryParameters = JSON.stringify(queryParameters);
34
+ }
35
+
36
+ const baseUrl = buildQueryUrl({apiBaseUrl, connectionName});
37
+ const headers = {
38
+ Authorization: `Bearer ${options.accessToken}`,
39
+ ...options.headers,
40
+ };
41
+ const parameters = {client: clientId, ...urlParameters};
42
+
43
+ const errorContext: APIErrorContext = {
44
+ requestType: 'SQL',
45
+ connection: options.connectionName,
46
+ type: 'query',
47
+ source: JSON.stringify(parameters, undefined, 2),
48
+ };
49
+ return await requestWithParameters<QueryResult>({
50
+ baseUrl,
51
+ parameters,
52
+ headers,
53
+ errorContext,
54
+ maxLengthURL,
55
+ });
56
+ };
@@ -0,0 +1,139 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {isPureObject} from '../utils';
6
+ import {CartoAPIError} from './carto-api-error';
7
+ import type {APIErrorContext} from './types';
8
+ import {
9
+ DEFAULT_CLIENT,
10
+ DEFAULT_MAX_LENGTH_URL,
11
+ V3_MINOR_VERSION,
12
+ } from '../constants';
13
+
14
+ const DEFAULT_HEADERS = {
15
+ Accept: 'application/json',
16
+ 'Content-Type': 'application/json',
17
+ };
18
+
19
+ const REQUEST_CACHE = new Map<string, Promise<unknown>>();
20
+
21
+ export async function requestWithParameters<T = any>({
22
+ baseUrl,
23
+ parameters = {},
24
+ headers: customHeaders = {},
25
+ errorContext,
26
+ maxLengthURL = DEFAULT_MAX_LENGTH_URL,
27
+ }: {
28
+ baseUrl: string;
29
+ parameters?: Record<string, unknown>;
30
+ headers?: Record<string, string>;
31
+ errorContext: APIErrorContext;
32
+ maxLengthURL?: number;
33
+ }): Promise<T> {
34
+ // Parameters added to all requests issued with `requestWithParameters()`.
35
+ // These parameters override parameters already in the base URL, but not
36
+ // user-provided parameters.
37
+ parameters = {
38
+ v: V3_MINOR_VERSION,
39
+ clientId: DEFAULT_CLIENT,
40
+ ...(typeof deck !== 'undefined' &&
41
+ deck.VERSION && {deckglVersion: deck.VERSION}),
42
+ ...parameters,
43
+ };
44
+
45
+ baseUrl = excludeURLParameters(baseUrl, Object.keys(parameters));
46
+ const key = createCacheKey(baseUrl, parameters, customHeaders);
47
+ if (REQUEST_CACHE.has(key)) {
48
+ return REQUEST_CACHE.get(key) as Promise<T>;
49
+ }
50
+
51
+ const url = createURLWithParameters(baseUrl, parameters);
52
+ const headers = {...DEFAULT_HEADERS, ...customHeaders};
53
+
54
+ /* global fetch */
55
+ const fetchPromise =
56
+ url.length > maxLengthURL
57
+ ? fetch(baseUrl, {
58
+ method: 'POST',
59
+ body: JSON.stringify(parameters),
60
+ headers,
61
+ })
62
+ : fetch(url, {headers});
63
+
64
+ let response: Response | undefined;
65
+ let responseJson: unknown;
66
+ const jsonPromise: Promise<T> = fetchPromise
67
+ .then((_response: Response) => {
68
+ response = _response;
69
+ return response.json();
70
+ })
71
+ .then((json: any) => {
72
+ responseJson = json;
73
+ if (!response || !response.ok) {
74
+ throw new Error(json.error);
75
+ }
76
+ return json;
77
+ })
78
+ .catch((error: Error) => {
79
+ REQUEST_CACHE.delete(key);
80
+ throw new CartoAPIError(error, errorContext, response, responseJson);
81
+ });
82
+
83
+ REQUEST_CACHE.set(key, jsonPromise);
84
+ return jsonPromise;
85
+ }
86
+
87
+ function createCacheKey(
88
+ baseUrl: string,
89
+ parameters: Record<string, unknown>,
90
+ headers: Record<string, string>
91
+ ): string {
92
+ const parameterEntries = Object.entries(parameters).sort(([a], [b]) =>
93
+ a > b ? 1 : -1
94
+ );
95
+ const headerEntries = Object.entries(headers).sort(([a], [b]) =>
96
+ a > b ? 1 : -1
97
+ );
98
+ return JSON.stringify({
99
+ baseUrl,
100
+ parameters: parameterEntries,
101
+ headers: headerEntries,
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Appends query string parameters to a URL. Existing URL parameters are kept,
107
+ * unless there is a conflict, in which case the new parameters override
108
+ * those already in the URL.
109
+ */
110
+ function createURLWithParameters(
111
+ baseUrlString: string,
112
+ parameters: Record<string, unknown>
113
+ ): string {
114
+ const baseUrl = new URL(baseUrlString);
115
+ for (const [key, value] of Object.entries(parameters)) {
116
+ if (isPureObject(value) || Array.isArray(value)) {
117
+ baseUrl.searchParams.set(key, JSON.stringify(value));
118
+ } else {
119
+ baseUrl.searchParams.set(
120
+ key,
121
+ (value as string | boolean | number).toString()
122
+ );
123
+ }
124
+ }
125
+ return baseUrl.toString();
126
+ }
127
+
128
+ /**
129
+ * Deletes query string parameters from a URL.
130
+ */
131
+ function excludeURLParameters(baseUrlString: string, parameters: string[]) {
132
+ const baseUrl = new URL(baseUrlString);
133
+ for (const param of parameters) {
134
+ if (baseUrl.searchParams.has(param)) {
135
+ baseUrl.searchParams.delete(param);
136
+ }
137
+ }
138
+ return baseUrl.toString();
139
+ }
@@ -0,0 +1,301 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ export type Format = 'json' | 'geojson' | 'tilejson';
6
+ export type MapType = 'boundary' | 'query' | 'table' | 'tileset' | 'raster';
7
+ export type RequestType =
8
+ | 'Map data'
9
+ | 'Map instantiation'
10
+ | 'Public map'
11
+ | 'Tile stats'
12
+ | 'SQL'
13
+ | 'Basemap style';
14
+ export type ScaleType =
15
+ | 'linear'
16
+ | 'ordinal'
17
+ | 'log'
18
+ | 'point'
19
+ | 'quantile'
20
+ | 'quantize'
21
+ | 'sqrt'
22
+ | 'custom'
23
+ | 'identity';
24
+
25
+ export type APIErrorContext = {
26
+ requestType: RequestType;
27
+ mapId?: string;
28
+ connection?: string;
29
+ source?: string;
30
+ type?: MapType;
31
+ };
32
+
33
+ export enum SchemaFieldType {
34
+ Number = 'number',
35
+ Bigint = 'bigint',
36
+ String = 'string',
37
+ Geometry = 'geometry',
38
+ Timestamp = 'timestamp',
39
+ Object = 'object',
40
+ Boolean = 'boolean',
41
+ Variant = 'variant',
42
+ Unknown = 'unknown',
43
+ }
44
+ export interface SchemaField {
45
+ name: string;
46
+ type: SchemaFieldType; // Field type in the CARTO stack, common for all providers
47
+ }
48
+
49
+ export interface MapInstantiation extends MapInstantiationFormats {
50
+ nrows: number;
51
+ size?: number;
52
+ schema: SchemaField[];
53
+ }
54
+
55
+ type MapInstantiationFormats = Record<
56
+ Format,
57
+ {
58
+ url: string[];
59
+ error?: any;
60
+ }
61
+ >;
62
+
63
+ export type QueryParameterValue =
64
+ | string
65
+ | number
66
+ | boolean
67
+ | Array<QueryParameterValue>
68
+ | object;
69
+
70
+ export type NamedQueryParameter = Record<string, QueryParameterValue>;
71
+
72
+ export type PositionalQueryParameter = QueryParameterValue[];
73
+
74
+ export type QueryParameters = NamedQueryParameter | PositionalQueryParameter;
75
+ export type VisualChannelField = {
76
+ name: string;
77
+ type: string;
78
+ colorColumn?: string;
79
+ };
80
+
81
+ export interface Filters {
82
+ [column: string]: Filter;
83
+ }
84
+
85
+ interface Filter {
86
+ [FilterTypes.In]?: number[];
87
+ [FilterTypes.Between]?: number[][];
88
+ [FilterTypes.ClosedOpen]?: number[][];
89
+ [FilterTypes.Time]?: number[][];
90
+ [FilterTypes.StringSearch]?: string[];
91
+ }
92
+
93
+ export enum FilterTypes {
94
+ In = 'in',
95
+ Between = 'between', // [a, b] both are included
96
+ ClosedOpen = 'closed_open', // [a, b) a is included, b is not
97
+ Time = 'time',
98
+ StringSearch = 'stringSearch',
99
+ }
100
+
101
+ export type VisualChannels = {
102
+ colorField?: VisualChannelField;
103
+ colorScale?: ScaleType;
104
+
105
+ customMarkersField?: VisualChannelField;
106
+ customMarkersScale?: ScaleType;
107
+
108
+ radiusField?: VisualChannelField;
109
+ radiusScale?: ScaleType;
110
+
111
+ rotationScale?: ScaleType;
112
+ rotationField?: VisualChannelField;
113
+
114
+ sizeField?: VisualChannelField;
115
+ sizeScale?: ScaleType;
116
+
117
+ strokeColorField?: VisualChannelField;
118
+ strokeColorScale?: ScaleType;
119
+
120
+ heightField?: VisualChannelField;
121
+ heightScale?: ScaleType;
122
+
123
+ weightField?: VisualChannelField;
124
+ };
125
+
126
+ export type ColorRange = {
127
+ category: string;
128
+ colors: string[];
129
+ colorMap: string[][] | undefined;
130
+ name: string;
131
+ type: string;
132
+ };
133
+
134
+ export type CustomMarkersRange = {
135
+ markerMap: {
136
+ value: string;
137
+ markerUrl?: string;
138
+ }[];
139
+ othersMarker?: string;
140
+ };
141
+
142
+ export type VisConfig = {
143
+ filled?: boolean;
144
+ opacity?: number;
145
+ enable3d?: boolean;
146
+
147
+ colorAggregation?: any;
148
+ colorRange: ColorRange;
149
+
150
+ customMarkers?: boolean;
151
+ customMarkersRange?: CustomMarkersRange | null;
152
+ customMarkersUrl?: string | null;
153
+
154
+ radius: number;
155
+ radiusRange?: number[];
156
+
157
+ sizeAggregation?: any;
158
+ sizeRange?: any;
159
+
160
+ strokeColorAggregation?: any;
161
+ strokeOpacity?: number;
162
+ strokeColorRange?: ColorRange;
163
+
164
+ heightRange?: any;
165
+ heightAggregation?: any;
166
+
167
+ weightAggregation?: any;
168
+ };
169
+
170
+ export type TextLabel = {
171
+ field: VisualChannelField | null | undefined;
172
+ alignment?: 'center' | 'bottom' | 'top';
173
+ anchor?: 'middle' | 'start' | 'end';
174
+ size: number;
175
+ color?: number[];
176
+ offset?: [number, number];
177
+ outlineColor?: number[];
178
+ };
179
+
180
+ export type MapLayerConfig = {
181
+ columns?: Record<string, any>;
182
+ color?: number[];
183
+ label?: string;
184
+ dataId: string;
185
+ textLabel: TextLabel[];
186
+ visConfig: VisConfig;
187
+ };
188
+
189
+ export type MapTextSubLayerConfig = Omit<MapLayerConfig, 'textLabel'> & {
190
+ textLabel?: TextLabel;
191
+ };
192
+
193
+ export type MapConfigLayer = {
194
+ type: string;
195
+ id: string;
196
+ config: MapLayerConfig;
197
+ visualChannels: VisualChannels;
198
+ };
199
+
200
+ export type MapDataset = {
201
+ id: string;
202
+ data: any;
203
+ aggregationExp: string | null;
204
+ aggregationResLevel: number | null;
205
+ geoColumn: string;
206
+ };
207
+
208
+ export interface CustomStyle {
209
+ url?: string;
210
+ style?: any;
211
+ customAttribution?: string;
212
+ }
213
+
214
+ export type KeplerMapConfig = {
215
+ mapState: any;
216
+ mapStyle: {
217
+ styleType: string;
218
+ visibleLayerGroups: Record<string, boolean>;
219
+ };
220
+ visState: {
221
+ layers: MapConfigLayer[];
222
+ };
223
+ layerBlending: any;
224
+ interactionConfig: any;
225
+ customBaseMaps?: {
226
+ customStyle?: CustomStyle;
227
+ };
228
+ };
229
+
230
+ export type BasemapType = 'maplibre' | 'google-maps';
231
+
232
+ export type Basemap = MapLibreBasemap | GoogleBasemap;
233
+
234
+ export type BasemapCommon = {
235
+ /**
236
+ * Type of basemap.
237
+ */
238
+ type: BasemapType;
239
+
240
+ /**
241
+ * Custom attribution for style data if not provided by style definition.
242
+ */
243
+ attribution?: string;
244
+
245
+ /**
246
+ * Properties of the basemap. These properties are specific to the basemap type.
247
+ */
248
+ props: Record<string, any>;
249
+ };
250
+
251
+ export type MapLibreBasemap = BasemapCommon & {
252
+ type: 'maplibre';
253
+
254
+ /**
255
+ * MapLibre map properties.
256
+ *
257
+ * Meant to be passed to directly to `maplibregl.Map` object.
258
+ */
259
+ props: MapLibreBasemapProps;
260
+
261
+ /**
262
+ * Layer groups to be displayed in the basemap.
263
+ */
264
+ visibleLayerGroups?: Record<string, boolean>;
265
+
266
+ /**
267
+ * If `style` has been filtered by `visibleLayerGroups` then this property contains original style object, so user
268
+ * can use `applyLayerGroupFilters` again with new settings.
269
+ */
270
+ rawStyle?: string | Record<string, any>;
271
+ };
272
+
273
+ // Cherry-pick of maplibregl Map API props that are supported/provided by fetchMap interface
274
+ export type MapLibreBasemapProps = {
275
+ style: string | Record<string, any>;
276
+ center: [number, number];
277
+ zoom: number;
278
+ pitch?: number;
279
+ bearing?: number;
280
+ };
281
+
282
+ export type GoogleBasemap = BasemapCommon & {
283
+ type: 'google-maps';
284
+
285
+ /**
286
+ * Google map properties.
287
+ *
288
+ * Meant to be passed to directly to `google.maps.Map` object.
289
+ */
290
+ props: GoogleBasemapProps;
291
+ };
292
+
293
+ // Cherry-pick of Google Map API props that are supported/provided by fetchMap interface
294
+ export type GoogleBasemapProps = {
295
+ mapTypeId: string;
296
+ mapId?: string;
297
+ center?: {lat: number; lng: number};
298
+ zoom?: number;
299
+ tilt?: number;
300
+ heading?: number;
301
+ };
package/src/constants.ts CHANGED
@@ -1,6 +1,19 @@
1
1
  /** Current version of @carto/api-client. */
2
2
  export const API_CLIENT_VERSION = __CARTO_API_CLIENT_VERSION;
3
3
 
4
+ export const DEFAULT_API_BASE_URL = 'https://gcp-us-east1.api.carto.com';
5
+ export const DEFAULT_CLIENT = 'deck-gl-carto';
6
+ export const V3_MINOR_VERSION = '3.4';
7
+
8
+ // Fastly default limit is 8192; leave some padding.
9
+ export const DEFAULT_MAX_LENGTH_URL = 7000;
10
+
11
+ export const DEFAULT_TILE_SIZE = 512;
12
+ export const DEFAULT_TILE_RESOLUTION = 0.5;
13
+
14
+ export const DEFAULT_AGGREGATION_RES_LEVEL_H3 = 4;
15
+ export const DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN = 6;
16
+
4
17
  /**
5
18
  * Defines a comparator used when matching a column's values against given filter values.
6
19
  *
package/src/global.d.ts CHANGED
@@ -5,3 +5,6 @@
5
5
  * ```
6
6
  */
7
7
  declare const __CARTO_API_CLIENT_VERSION: string;
8
+
9
+ /** Defined by @deck.gl/core. */
10
+ declare const deck: {VERSION: string | undefined} | undefined;
package/src/index.ts CHANGED
@@ -2,5 +2,14 @@ export * from './client.js';
2
2
  export * from './constants.js';
3
3
  export * from './filters.js';
4
4
  export * from './geo.js';
5
- export * from './sources/index.js';
5
+ export * from './widget-sources/index.js';
6
6
  export * from './types.js';
7
+
8
+ export {
9
+ APIErrorContext,
10
+ Format, // TODO: Move to `types.ts`?
11
+ MapType, // TODO: De-duplicate?
12
+ RequestType, // TODO: Move to `types.ts`?
13
+ QueryParameters, // TODO: Move to `types.ts`?
14
+ QueryOptions, // TODO: Move to `types.ts`?
15
+ } from './api/index.js';
@@ -0,0 +1,100 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ /* eslint-disable camelcase */
6
+ import {
7
+ DEFAULT_API_BASE_URL,
8
+ DEFAULT_CLIENT,
9
+ DEFAULT_MAX_LENGTH_URL,
10
+ } from '../constants';
11
+ import {buildSourceUrl} from '../api/endpoints';
12
+ import {requestWithParameters} from '../api/request-with-parameters';
13
+ import type {APIErrorContext, MapType} from '../api/types';
14
+ import type {
15
+ GeojsonResult,
16
+ JsonResult,
17
+ SourceOptionalOptions,
18
+ SourceRequiredOptions,
19
+ TilejsonMapInstantiation,
20
+ TilejsonResult,
21
+ } from './types';
22
+
23
+ export const SOURCE_DEFAULTS: SourceOptionalOptions = {
24
+ apiBaseUrl: DEFAULT_API_BASE_URL,
25
+ clientId: DEFAULT_CLIENT,
26
+ format: 'tilejson',
27
+ headers: {},
28
+ maxLengthURL: DEFAULT_MAX_LENGTH_URL,
29
+ };
30
+
31
+ export async function baseSource<UrlParameters extends Record<string, unknown>>(
32
+ endpoint: MapType,
33
+ options: Partial<SourceOptionalOptions> & SourceRequiredOptions,
34
+ urlParameters: UrlParameters
35
+ ): Promise<TilejsonResult | GeojsonResult | JsonResult> {
36
+ const {accessToken, connectionName, cache, ...optionalOptions} = options;
37
+ const mergedOptions = {
38
+ ...SOURCE_DEFAULTS,
39
+ accessToken,
40
+ connectionName,
41
+ endpoint,
42
+ };
43
+ for (const key in optionalOptions) {
44
+ if (optionalOptions[key as keyof typeof optionalOptions]) {
45
+ (mergedOptions as any)[key] =
46
+ optionalOptions[key as keyof typeof optionalOptions];
47
+ }
48
+ }
49
+ const baseUrl = buildSourceUrl(mergedOptions);
50
+ const {clientId, maxLengthURL, format} = mergedOptions;
51
+ const headers = {
52
+ Authorization: `Bearer ${options.accessToken}`,
53
+ ...options.headers,
54
+ };
55
+ const parameters = {client: clientId, ...urlParameters};
56
+
57
+ const errorContext: APIErrorContext = {
58
+ requestType: 'Map instantiation',
59
+ connection: options.connectionName,
60
+ type: endpoint,
61
+ source: JSON.stringify(parameters, undefined, 2),
62
+ };
63
+ const mapInstantiation =
64
+ await requestWithParameters<TilejsonMapInstantiation>({
65
+ baseUrl,
66
+ parameters,
67
+ headers,
68
+ errorContext,
69
+ maxLengthURL,
70
+ });
71
+
72
+ const dataUrl = mapInstantiation[format].url[0];
73
+ if (cache) {
74
+ cache.value = parseInt(
75
+ new URL(dataUrl).searchParams.get('cache') || '',
76
+ 10
77
+ );
78
+ }
79
+ errorContext.requestType = 'Map data';
80
+
81
+ if (format === 'tilejson') {
82
+ const json = await requestWithParameters<TilejsonResult>({
83
+ baseUrl: dataUrl,
84
+ headers,
85
+ errorContext,
86
+ maxLengthURL,
87
+ });
88
+ if (accessToken) {
89
+ json.accessToken = accessToken;
90
+ }
91
+ return json;
92
+ }
93
+
94
+ return await requestWithParameters<GeojsonResult | JsonResult>({
95
+ baseUrl: dataUrl,
96
+ headers,
97
+ errorContext,
98
+ maxLengthURL,
99
+ });
100
+ }
@@ -0,0 +1,53 @@
1
+ // deck.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {QueryParameters} from '../api/index';
6
+ import {baseSource} from './base-source';
7
+ import type {FilterOptions, SourceOptions, TilejsonResult} from './types';
8
+
9
+ export type BoundaryQuerySourceOptions = SourceOptions &
10
+ FilterOptions & {
11
+ columns?: string[];
12
+ tilesetTableName: string;
13
+ propertiesSqlQuery: string;
14
+ queryParameters?: QueryParameters;
15
+ };
16
+ type UrlParameters = {
17
+ columns?: string;
18
+ filters?: Record<string, unknown>;
19
+ tilesetTableName: string;
20
+ propertiesSqlQuery: string;
21
+ queryParameters?: Record<string, unknown> | unknown[];
22
+ };
23
+
24
+ export const boundaryQuerySource = async function (
25
+ options: BoundaryQuerySourceOptions
26
+ ): Promise<TilejsonResult> {
27
+ const {
28
+ columns,
29
+ filters,
30
+ tilesetTableName,
31
+ propertiesSqlQuery,
32
+ queryParameters,
33
+ } = options;
34
+ const urlParameters: UrlParameters = {
35
+ tilesetTableName,
36
+ propertiesSqlQuery,
37
+ };
38
+
39
+ if (columns) {
40
+ urlParameters.columns = columns.join(',');
41
+ }
42
+ if (filters) {
43
+ urlParameters.filters = filters;
44
+ }
45
+ if (queryParameters) {
46
+ urlParameters.queryParameters = queryParameters;
47
+ }
48
+ return baseSource<UrlParameters>(
49
+ 'boundary',
50
+ options,
51
+ urlParameters
52
+ ) as Promise<TilejsonResult>;
53
+ };