@carto/api-client 0.4.0 → 0.4.1-alpha.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.
@@ -38,6 +38,24 @@ export type SourceOptionalOptions = {
38
38
  * @default {@link DEFAULT_MAX_LENGTH_URL}
39
39
  */
40
40
  maxLengthURL?: number;
41
+ /**
42
+ * By default, local in-memory caching is enabled.
43
+ */
44
+ localCache?: LocalCacheOptions;
45
+ };
46
+ export type LocalCacheOptions = {
47
+ /**
48
+ * Map that stores requests and their responses.
49
+ */
50
+ cache?: Map<string, Promise<unknown>>;
51
+ /**
52
+ * Cache control
53
+ * * `no-cache`: If present, the source will always fetch from original source.
54
+ * * `no-store`: If present, source will not store result in cache (for later reuse).
55
+ *
56
+ * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#directives
57
+ */
58
+ cacheControl?: ('no-cache' | 'no-store')[];
41
59
  };
42
60
  export type SourceOptions = SourceRequiredOptions & Partial<SourceOptionalOptions>;
43
61
  export type AggregationOptions = {
@@ -166,16 +184,42 @@ export interface Tilejson {
166
184
  attribution: string;
167
185
  scheme: string;
168
186
  tiles: string[];
169
- properties_tiles: string[];
170
- minresolution: number;
171
- maxresolution: number;
172
187
  minzoom: number;
173
188
  maxzoom: number;
174
- bounds: [number, number, number, number];
175
- center: [number, number, number];
189
+ bounds: [left: number, bottom: number, right: number, top: number];
190
+ center: [longitute: number, latitude: number, zoom: number];
176
191
  vector_layers: VectorLayer[];
192
+ minresolution: number;
193
+ maxresolution: number;
194
+ properties_tiles: string[];
177
195
  tilestats: Tilestats;
178
196
  tileResolution?: TileResolution;
197
+ /**
198
+ * Resolution of data in spatial-index dataset (e.g. H3, Quadbin).
199
+ *
200
+ * @internal
201
+ */
202
+ dataresolution?: number;
203
+ /**
204
+ * Array of ratios of dropped features per zoom level.
205
+ *
206
+ * Example: `[0,0,0.5]` - means that 50% of features are dropped at zoom 2 and bigger.
207
+ *
208
+ * @internal
209
+ */
210
+ fraction_dropped_per_zoom?: number[];
211
+ /**
212
+ * Names of bands - rasters only.
213
+ *
214
+ * @internal
215
+ */
216
+ raster_bands?: string[];
217
+ /**
218
+ * Raster metadata - rasters only.
219
+ *
220
+ * @internal
221
+ */
222
+ raster_metadata?: RasterMetadata;
179
223
  }
180
224
  export interface Tilestats {
181
225
  layerCount: number;
@@ -196,7 +240,99 @@ export interface VectorLayer {
196
240
  minzoom: number;
197
241
  maxzoom: number;
198
242
  fields: Record<string, string>;
243
+ geometry_type?: string;
199
244
  }
245
+ export type RasterMetadataBandStats = {
246
+ approximated_stats?: boolean;
247
+ min: number;
248
+ max: number;
249
+ mean: number;
250
+ stddev: number;
251
+ sum: number;
252
+ sum_squares: number;
253
+ count: number;
254
+ /**
255
+ * Quantiles by number of buckets.
256
+ *
257
+ * Example:
258
+ * ```ts
259
+ * {
260
+ * // for 3 buckets, first 1/3 of items lies in range [min, 20], second 1/3 is in [20, 40], and last 1/3 is in [40, max]
261
+ * 3: [20, 40],
262
+ * 4: [20, 30, 50], for 4 buckets ...
263
+ * }
264
+ * ```
265
+ */
266
+ quantiles?: Record<number, number[]>;
267
+ /**
268
+ * Top values by number of values.
269
+ *
270
+ * Key of dictionary is value, value is count.
271
+ * Key order is random.
272
+ *
273
+ * Example:
274
+ * ```
275
+ * {
276
+ * 3: 5, // means there are 5 pixels with value 3
277
+ * 11: 222,
278
+ * 12: 333, // means that 12 is most common value with count 333
279
+ * ... // (assuming 333 was largest value in dict)
280
+ * }
281
+ * ```
282
+ */
283
+ top_values?: Record<number, number>;
284
+ /**
285
+ * Raster loader version.
286
+ */
287
+ version?: string;
288
+ };
289
+ export declare enum RasterBandColorinterp {
290
+ Gray = "gray",
291
+ Red = "red",
292
+ Green = "green",
293
+ Blue = "blue",
294
+ Alpha = "alpha",
295
+ Palette = "palette"
296
+ }
297
+ export type RasterMetadataBand = {
298
+ type: string;
299
+ name: string;
300
+ stats: RasterMetadataBandStats;
301
+ /**
302
+ * Known values:
303
+ * * `palette`: use unique value and `colortable` ad default mapping
304
+ * * `red`, `green`, `blue`: use the band as color channel
305
+ * * `gray`: use the band as grayscale
306
+ */
307
+ colorinterp?: string | RasterBandColorinterp;
308
+ /**
309
+ * Default color mapping for unique values (or if coloprinterp is `palette`)
310
+ */
311
+ colortable?: Record<string, number[]>;
312
+ /**
313
+ * No value representation.
314
+ * Observed values:
315
+ * * `'nan'` for `NaN`
316
+ * * `number`: both as string as number, so parsing is needed
317
+ */
318
+ nodata: string | number;
319
+ };
320
+ export type RasterMetadata = {
321
+ block_resolution: number;
322
+ minresolution: number;
323
+ maxresolution: number;
324
+ nodata: number | string;
325
+ bands: RasterMetadataBand[];
326
+ bounds: [left: number, bottom: number, right: number, top: number];
327
+ center: [longitute: number, latitude: number, zoom: number];
328
+ width: number;
329
+ height: number;
330
+ block_width: number;
331
+ block_height: number;
332
+ num_blocks: number;
333
+ num_pixels: number;
334
+ pixel_resolution: number;
335
+ };
200
336
  export type TilejsonResult = Tilejson & {
201
337
  accessToken: string;
202
338
  };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "repository": "github:CartoDB/carto-api-client",
5
5
  "author": "Don McCurdy <donmccurdy@carto.com>",
6
6
  "packageManager": "yarn@4.3.1",
7
- "version": "0.4.0",
7
+ "version": "0.4.1-alpha.1",
8
8
  "license": "MIT",
9
9
  "publishConfig": {
10
10
  "access": "public",
package/src/api/query.ts CHANGED
@@ -23,6 +23,7 @@ export const query = async function (
23
23
  apiBaseUrl = SOURCE_DEFAULTS.apiBaseUrl,
24
24
  clientId = SOURCE_DEFAULTS.clientId,
25
25
  maxLengthURL = SOURCE_DEFAULTS.maxLengthURL,
26
+ localCache,
26
27
  connectionName,
27
28
  sqlQuery,
28
29
  queryParameters,
@@ -52,5 +53,6 @@ export const query = async function (
52
53
  headers,
53
54
  errorContext,
54
55
  maxLengthURL,
56
+ localCache,
55
57
  });
56
58
  };
@@ -7,13 +7,14 @@ import {CartoAPIError, APIErrorContext} from './carto-api-error';
7
7
  import {V3_MINOR_VERSION} from '../constants-internal';
8
8
  import {DEFAULT_MAX_LENGTH_URL} from '../constants-internal';
9
9
  import {getClient} from '../client';
10
+ import {LocalCacheOptions} from '../sources/types';
10
11
 
11
12
  const DEFAULT_HEADERS = {
12
13
  Accept: 'application/json',
13
14
  'Content-Type': 'application/json',
14
15
  };
15
16
 
16
- const REQUEST_CACHE = new Map<string, Promise<unknown>>();
17
+ const DEFAULT_REQUEST_CACHE = new Map<string, Promise<unknown>>();
17
18
 
18
19
  export async function requestWithParameters<T = any>({
19
20
  baseUrl,
@@ -21,12 +22,14 @@ export async function requestWithParameters<T = any>({
21
22
  headers: customHeaders = {},
22
23
  errorContext,
23
24
  maxLengthURL = DEFAULT_MAX_LENGTH_URL,
25
+ localCache,
24
26
  }: {
25
27
  baseUrl: string;
26
28
  parameters?: Record<string, unknown>;
27
29
  headers?: Record<string, string>;
28
30
  errorContext: APIErrorContext;
29
31
  maxLengthURL?: number;
32
+ localCache?: LocalCacheOptions;
30
33
  }): Promise<T> {
31
34
  // Parameters added to all requests issued with `requestWithParameters()`.
32
35
  // These parameters override parameters already in the base URL, but not
@@ -41,7 +44,14 @@ export async function requestWithParameters<T = any>({
41
44
 
42
45
  baseUrl = excludeURLParameters(baseUrl, Object.keys(parameters));
43
46
  const key = createCacheKey(baseUrl, parameters, customHeaders);
44
- if (REQUEST_CACHE.has(key)) {
47
+
48
+ const {
49
+ cache: REQUEST_CACHE,
50
+ canReadCache,
51
+ canStoreInCache,
52
+ } = getCacheSettings(localCache);
53
+
54
+ if (canReadCache && REQUEST_CACHE.has(key)) {
45
55
  return REQUEST_CACHE.get(key) as Promise<T>;
46
56
  }
47
57
 
@@ -73,14 +83,34 @@ export async function requestWithParameters<T = any>({
73
83
  return json;
74
84
  })
75
85
  .catch((error: Error) => {
76
- REQUEST_CACHE.delete(key);
86
+ if (canStoreInCache) {
87
+ REQUEST_CACHE.delete(key);
88
+ }
77
89
  throw new CartoAPIError(error, errorContext, response, responseJson);
78
90
  });
79
91
 
80
- REQUEST_CACHE.set(key, jsonPromise);
92
+ if (canStoreInCache) {
93
+ REQUEST_CACHE.set(key, jsonPromise);
94
+ }
81
95
  return jsonPromise;
82
96
  }
83
97
 
98
+ function getCacheSettings(localCache: LocalCacheOptions | undefined) {
99
+ const canReadCache = localCache?.cacheControl?.includes('no-cache')
100
+ ? false
101
+ : true;
102
+ const canStoreInCache = localCache?.cacheControl?.includes('no-store')
103
+ ? false
104
+ : true;
105
+ const cache = localCache?.cache || DEFAULT_REQUEST_CACHE;
106
+
107
+ return {
108
+ cache,
109
+ canReadCache,
110
+ canStoreInCache,
111
+ };
112
+ }
113
+
84
114
  function createCacheKey(
85
115
  baseUrl: string,
86
116
  parameters: Record<string, unknown>,
@@ -45,7 +45,7 @@ export async function baseSource<UrlParameters extends Record<string, unknown>>(
45
45
  }
46
46
  }
47
47
  const baseUrl = buildSourceUrl(mergedOptions);
48
- const {clientId, maxLengthURL, format} = mergedOptions;
48
+ const {clientId, maxLengthURL, format, localCache} = mergedOptions;
49
49
  const headers = {
50
50
  Authorization: `Bearer ${options.accessToken}`,
51
51
  ...options.headers,
@@ -65,6 +65,7 @@ export async function baseSource<UrlParameters extends Record<string, unknown>>(
65
65
  headers,
66
66
  errorContext,
67
67
  maxLengthURL,
68
+ localCache,
68
69
  });
69
70
 
70
71
  const dataUrl = mapInstantiation[format].url[0];
@@ -82,6 +83,7 @@ export async function baseSource<UrlParameters extends Record<string, unknown>>(
82
83
  headers,
83
84
  errorContext,
84
85
  maxLengthURL,
86
+ localCache,
85
87
  });
86
88
  if (accessToken) {
87
89
  json.accessToken = accessToken;
@@ -94,5 +96,6 @@ export async function baseSource<UrlParameters extends Record<string, unknown>>(
94
96
  headers,
95
97
  errorContext,
96
98
  maxLengthURL,
99
+ localCache,
97
100
  });
98
101
  }
@@ -4,6 +4,11 @@
4
4
 
5
5
  export {SOURCE_DEFAULTS} from './base-source';
6
6
  export type {
7
+ VectorLayer,
8
+ RasterMetadataBandStats,
9
+ RasterBandColorinterp,
10
+ RasterMetadataBand,
11
+ RasterMetadata,
7
12
  TilejsonResult,
8
13
  GeojsonResult,
9
14
  JsonResult,
@@ -47,6 +47,27 @@ export type SourceOptionalOptions = {
47
47
  * @default {@link DEFAULT_MAX_LENGTH_URL}
48
48
  */
49
49
  maxLengthURL?: number;
50
+
51
+ /**
52
+ * By default, local in-memory caching is enabled.
53
+ */
54
+ localCache?: LocalCacheOptions;
55
+ };
56
+
57
+ export type LocalCacheOptions = {
58
+ /**
59
+ * Map that stores requests and their responses.
60
+ */
61
+ cache?: Map<string, Promise<unknown>>;
62
+
63
+ /**
64
+ * Cache control
65
+ * * `no-cache`: If present, the source will always fetch from original source.
66
+ * * `no-store`: If present, source will not store result in cache (for later reuse).
67
+ *
68
+ * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#directives
69
+ */
70
+ cacheControl?: ('no-cache' | 'no-store')[];
50
71
  };
51
72
 
52
73
  export type SourceOptions = SourceRequiredOptions &
@@ -191,16 +212,51 @@ export interface Tilejson {
191
212
  attribution: string;
192
213
  scheme: string;
193
214
  tiles: string[];
194
- properties_tiles: string[];
195
- minresolution: number;
196
- maxresolution: number;
197
215
  minzoom: number;
198
216
  maxzoom: number;
199
- bounds: [number, number, number, number];
200
- center: [number, number, number];
217
+ bounds: [left: number, bottom: number, right: number, top: number];
218
+ center: [longitute: number, latitude: number, zoom: number];
201
219
  vector_layers: VectorLayer[];
220
+
221
+ //
222
+ // Carto additions over standard Tilejson properties
223
+ //
224
+
225
+ minresolution: number;
226
+ maxresolution: number;
227
+ properties_tiles: string[];
202
228
  tilestats: Tilestats;
203
229
  tileResolution?: TileResolution;
230
+
231
+ /**
232
+ * Resolution of data in spatial-index dataset (e.g. H3, Quadbin).
233
+ *
234
+ * @internal
235
+ */
236
+ dataresolution?: number;
237
+
238
+ /**
239
+ * Array of ratios of dropped features per zoom level.
240
+ *
241
+ * Example: `[0,0,0.5]` - means that 50% of features are dropped at zoom 2 and bigger.
242
+ *
243
+ * @internal
244
+ */
245
+ fraction_dropped_per_zoom?: number[];
246
+
247
+ /**
248
+ * Names of bands - rasters only.
249
+ *
250
+ * @internal
251
+ */
252
+ raster_bands?: string[];
253
+
254
+ /**
255
+ * Raster metadata - rasters only.
256
+ *
257
+ * @internal
258
+ */
259
+ raster_metadata?: RasterMetadata;
204
260
  }
205
261
 
206
262
  export interface Tilestats {
@@ -221,12 +277,116 @@ export interface Attribute {
221
277
  }
222
278
 
223
279
  export interface VectorLayer {
280
+ // tilejson standard
224
281
  id: string;
225
282
  minzoom: number;
226
283
  maxzoom: number;
227
284
  fields: Record<string, string>;
285
+
286
+ // Carto additions over standard Tilejson properties
287
+ geometry_type?: string;
288
+ }
289
+
290
+ export type RasterMetadataBandStats = {
291
+ approximated_stats?: boolean;
292
+ min: number;
293
+ max: number;
294
+ mean: number;
295
+ stddev: number;
296
+ sum: number;
297
+ sum_squares: number;
298
+ count: number;
299
+
300
+ /**
301
+ * Quantiles by number of buckets.
302
+ *
303
+ * Example:
304
+ * ```ts
305
+ * {
306
+ * // for 3 buckets, first 1/3 of items lies in range [min, 20], second 1/3 is in [20, 40], and last 1/3 is in [40, max]
307
+ * 3: [20, 40],
308
+ * 4: [20, 30, 50], for 4 buckets ...
309
+ * }
310
+ * ```
311
+ */
312
+ quantiles?: Record<number, number[]>;
313
+
314
+ /**
315
+ * Top values by number of values.
316
+ *
317
+ * Key of dictionary is value, value is count.
318
+ * Key order is random.
319
+ *
320
+ * Example:
321
+ * ```
322
+ * {
323
+ * 3: 5, // means there are 5 pixels with value 3
324
+ * 11: 222,
325
+ * 12: 333, // means that 12 is most common value with count 333
326
+ * ... // (assuming 333 was largest value in dict)
327
+ * }
328
+ * ```
329
+ */
330
+ top_values?: Record<number, number>;
331
+
332
+ /**
333
+ * Raster loader version.
334
+ */
335
+ version?: string;
336
+ };
337
+
338
+ export enum RasterBandColorinterp {
339
+ Gray = 'gray',
340
+ Red = 'red',
341
+ Green = 'green',
342
+ Blue = 'blue',
343
+ Alpha = 'alpha',
344
+ Palette = 'palette',
228
345
  }
229
346
 
347
+ export type RasterMetadataBand = {
348
+ type: string;
349
+ name: string;
350
+ stats: RasterMetadataBandStats;
351
+ /**
352
+ * Known values:
353
+ * * `palette`: use unique value and `colortable` ad default mapping
354
+ * * `red`, `green`, `blue`: use the band as color channel
355
+ * * `gray`: use the band as grayscale
356
+ */
357
+ colorinterp?: string | RasterBandColorinterp; // use RasterBandColorinterp, but it's external value, so let's use string
358
+
359
+ /**
360
+ * Default color mapping for unique values (or if coloprinterp is `palette`)
361
+ */
362
+ colortable?: Record<string, number[]>;
363
+
364
+ /**
365
+ * No value representation.
366
+ * Observed values:
367
+ * * `'nan'` for `NaN`
368
+ * * `number`: both as string as number, so parsing is needed
369
+ */
370
+ nodata: string | number; // 255, '0', 'nan'
371
+ };
372
+
373
+ export type RasterMetadata = {
374
+ block_resolution: number;
375
+ minresolution: number;
376
+ maxresolution: number;
377
+ nodata: number | string;
378
+ bands: RasterMetadataBand[];
379
+ bounds: [left: number, bottom: number, right: number, top: number];
380
+ center: [longitute: number, latitude: number, zoom: number];
381
+ width: number;
382
+ height: number;
383
+ block_width: number;
384
+ block_height: number;
385
+ num_blocks: number;
386
+ num_pixels: number;
387
+ pixel_resolution: number;
388
+ };
389
+
230
390
  export type TilejsonResult = Tilejson & {accessToken: string};
231
391
  export type GeojsonResult = {type: 'FeatureCollection'; features: Feature[]};
232
392
  export type JsonResult = any[];