@carto/api-client 0.2.2-alpha.0 → 0.2.2

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.
@@ -34,6 +34,8 @@ function setClient(c) {
34
34
  client = c;
35
35
  }
36
36
 
37
+ /** Current version of @carto/api-client. */
38
+ const API_CLIENT_VERSION = "0.2.2";
37
39
  /**
38
40
  * Defines a comparator used when matching a column's values against given filter values.
39
41
  *
@@ -101,7 +103,7 @@ function normalizeObjectKeys(el) {
101
103
  }, {});
102
104
  }
103
105
  /** @internalRemarks Source: @carto/react-core */
104
- function assert(condition, message) {
106
+ function assert$2(condition, message) {
105
107
  if (!condition) {
106
108
  throw new Error(message);
107
109
  }
@@ -120,7 +122,7 @@ class InvalidColumnError extends Error {
120
122
  }
121
123
  }
122
124
  InvalidColumnError.NAME = 'InvalidColumnError';
123
- function isEmptyObject(object) {
125
+ function isEmptyObject$1(object) {
124
126
  for (const _ in object) {
125
127
  return false;
126
128
  }
@@ -170,7 +172,7 @@ function removeFilter(filters, _ref2) {
170
172
  }
171
173
  }
172
174
  }
173
- if (!owner || isEmptyObject(filter)) {
175
+ if (!owner || isEmptyObject$1(filter)) {
174
176
  delete filters[column];
175
177
  }
176
178
  return filters;
@@ -480,10 +482,10 @@ const REQUEST_GET_MAX_URL_LENGTH = 2048;
480
482
  * @internalRemarks Source: @carto/react-api
481
483
  */
482
484
  function executeModel(props) {
483
- assert(props.source, 'executeModel: missing source');
484
- assert(props.model, 'executeModel: missing model');
485
- assert(props.params, 'executeModel: missing params');
486
- assert(AVAILABLE_MODELS.includes(props.model), `executeModel: model provided isn't valid. Available models: ${AVAILABLE_MODELS.join(', ')}`);
485
+ assert$2(props.source, 'executeModel: missing source');
486
+ assert$2(props.model, 'executeModel: missing model');
487
+ assert$2(props.params, 'executeModel: missing params');
488
+ assert$2(AVAILABLE_MODELS.includes(props.model), `executeModel: model provided isn't valid. Available models: ${AVAILABLE_MODELS.join(', ')}`);
487
489
  const {
488
490
  model,
489
491
  source,
@@ -498,10 +500,10 @@ function executeModel(props) {
498
500
  connectionName,
499
501
  clientId
500
502
  } = source;
501
- assert(apiBaseUrl, 'executeModel: missing apiBaseUrl');
502
- assert(accessToken, 'executeModel: missing accessToken');
503
- assert(apiVersion === V3, 'executeModel: SQL Model API requires CARTO 3+');
504
- assert(type !== MapType.TILESET, 'executeModel: Tilesets not supported');
503
+ assert$2(apiBaseUrl, 'executeModel: missing apiBaseUrl');
504
+ assert$2(accessToken, 'executeModel: missing accessToken');
505
+ assert$2(apiVersion === V3, 'executeModel: SQL Model API requires CARTO 3+');
506
+ assert$2(type !== MapType.TILESET, 'executeModel: Tilesets not supported');
505
507
  let url = `${apiBaseUrl}/v3/sql/${connectionName}/model/${model}`;
506
508
  const {
507
509
  filters,
@@ -977,6 +979,1373 @@ class WidgetTableSource extends WidgetBaseSource {
977
979
  }
978
980
  }
979
981
 
982
+ /**
983
+ * Throws an `Error` with the optional `message` if `condition` is falsy
984
+ * @note Replacement for the external assert method to reduce bundle size
985
+ */
986
+ function assert$1(condition, message) {
987
+ if (!condition) {
988
+ throw new Error(message || 'loader assertion failed.');
989
+ }
990
+ }
991
+
992
+ // Purpose: include this in your module to avoid
993
+ /** true if running in a browser */
994
+ const isBrowser$1 =
995
+ // @ts-ignore process does not exist on browser
996
+ Boolean(typeof process !== 'object' || String(process) !== '[object process]' || process.browser);
997
+ // Extract node major version
998
+ typeof process !== 'undefined' && process.version && /v([0-9]*)/.exec(process.version);
999
+
1000
+ // Do not name these variables the same as the global objects - will break bundling
1001
+ const window_ = globalThis;
1002
+ const process_ = globalThis.process || {};
1003
+
1004
+ // based on https://github.com/cheton/is-electron
1005
+ // https://github.com/electron/electron/issues/2288
1006
+ /* eslint-disable complexity */
1007
+ function isElectron(mockUserAgent) {
1008
+ // Renderer process
1009
+ // @ts-expect-error
1010
+ if (typeof window !== 'undefined' && window.process?.type === 'renderer') {
1011
+ return true;
1012
+ }
1013
+ // Main process
1014
+ // eslint-disable-next-line
1015
+ if (typeof process !== 'undefined' && Boolean(process.versions?.['electron'])) {
1016
+ return true;
1017
+ }
1018
+ // Detect the user agent when the `nodeIntegration` option is set to true
1019
+ const realUserAgent = typeof navigator !== 'undefined' && navigator.userAgent;
1020
+ const userAgent = mockUserAgent || realUserAgent;
1021
+ return Boolean(userAgent && userAgent.indexOf('Electron') >= 0);
1022
+ }
1023
+
1024
+ // This function is needed in initialization stages,
1025
+ /** Check if in browser by duck-typing Node context */
1026
+ function isBrowser() {
1027
+ const isNode =
1028
+ // @ts-expect-error
1029
+ typeof process === 'object' && String(process) === '[object process]' && !process?.browser;
1030
+ return !isNode || isElectron();
1031
+ }
1032
+
1033
+ // Extract injected version from package.json (injected by babel plugin)
1034
+ // @ts-expect-error
1035
+ const VERSION$2 = "4.0.7" ;
1036
+ // TODO - wish we could just export a constant
1037
+ // export const isBrowser = checkIfBrowser();
1038
+
1039
+ // probe.gl, MIT license
1040
+ function getStorage(type) {
1041
+ try {
1042
+ const storage = window[type];
1043
+ const x = '__storage_test__';
1044
+ storage.setItem(x, x);
1045
+ storage.removeItem(x);
1046
+ return storage;
1047
+ } catch (e) {
1048
+ return null;
1049
+ }
1050
+ }
1051
+ // Store keys in local storage via simple interface
1052
+ class LocalStorage {
1053
+ constructor(id, defaultConfig, type = 'sessionStorage') {
1054
+ this.storage = getStorage(type);
1055
+ this.id = id;
1056
+ this.config = defaultConfig;
1057
+ this._loadConfiguration();
1058
+ }
1059
+ getConfiguration() {
1060
+ return this.config;
1061
+ }
1062
+ setConfiguration(configuration) {
1063
+ Object.assign(this.config, configuration);
1064
+ if (this.storage) {
1065
+ const serialized = JSON.stringify(this.config);
1066
+ this.storage.setItem(this.id, serialized);
1067
+ }
1068
+ }
1069
+ // Get config from persistent store, if available
1070
+ _loadConfiguration() {
1071
+ let configuration = {};
1072
+ if (this.storage) {
1073
+ const serializedConfiguration = this.storage.getItem(this.id);
1074
+ configuration = serializedConfiguration ? JSON.parse(serializedConfiguration) : {};
1075
+ }
1076
+ Object.assign(this.config, configuration);
1077
+ return this;
1078
+ }
1079
+ }
1080
+
1081
+ // probe.gl, MIT license
1082
+ /**
1083
+ * Format time
1084
+ */
1085
+ function formatTime(ms) {
1086
+ let formatted;
1087
+ if (ms < 10) {
1088
+ formatted = `${ms.toFixed(2)}ms`;
1089
+ } else if (ms < 100) {
1090
+ formatted = `${ms.toFixed(1)}ms`;
1091
+ } else if (ms < 1000) {
1092
+ formatted = `${ms.toFixed(0)}ms`;
1093
+ } else {
1094
+ formatted = `${(ms / 1000).toFixed(2)}s`;
1095
+ }
1096
+ return formatted;
1097
+ }
1098
+ function leftPad(string, length = 8) {
1099
+ const padLength = Math.max(length - string.length, 0);
1100
+ return `${' '.repeat(padLength)}${string}`;
1101
+ }
1102
+
1103
+ var COLOR;
1104
+ (function (COLOR) {
1105
+ COLOR[COLOR["BLACK"] = 30] = "BLACK";
1106
+ COLOR[COLOR["RED"] = 31] = "RED";
1107
+ COLOR[COLOR["GREEN"] = 32] = "GREEN";
1108
+ COLOR[COLOR["YELLOW"] = 33] = "YELLOW";
1109
+ COLOR[COLOR["BLUE"] = 34] = "BLUE";
1110
+ COLOR[COLOR["MAGENTA"] = 35] = "MAGENTA";
1111
+ COLOR[COLOR["CYAN"] = 36] = "CYAN";
1112
+ COLOR[COLOR["WHITE"] = 37] = "WHITE";
1113
+ COLOR[COLOR["BRIGHT_BLACK"] = 90] = "BRIGHT_BLACK";
1114
+ COLOR[COLOR["BRIGHT_RED"] = 91] = "BRIGHT_RED";
1115
+ COLOR[COLOR["BRIGHT_GREEN"] = 92] = "BRIGHT_GREEN";
1116
+ COLOR[COLOR["BRIGHT_YELLOW"] = 93] = "BRIGHT_YELLOW";
1117
+ COLOR[COLOR["BRIGHT_BLUE"] = 94] = "BRIGHT_BLUE";
1118
+ COLOR[COLOR["BRIGHT_MAGENTA"] = 95] = "BRIGHT_MAGENTA";
1119
+ COLOR[COLOR["BRIGHT_CYAN"] = 96] = "BRIGHT_CYAN";
1120
+ COLOR[COLOR["BRIGHT_WHITE"] = 97] = "BRIGHT_WHITE";
1121
+ })(COLOR || (COLOR = {}));
1122
+ const BACKGROUND_INCREMENT = 10;
1123
+ function getColor(color) {
1124
+ if (typeof color !== 'string') {
1125
+ return color;
1126
+ }
1127
+ color = color.toUpperCase();
1128
+ return COLOR[color] || COLOR.WHITE;
1129
+ }
1130
+ function addColor(string, color, background) {
1131
+ if (!isBrowser && typeof string === 'string') {
1132
+ if (color) {
1133
+ const colorCode = getColor(color);
1134
+ string = `\u001b[${colorCode}m${string}\u001b[39m`;
1135
+ }
1136
+ if (background) {
1137
+ // background colors values are +10
1138
+ const colorCode = getColor(background);
1139
+ string = `\u001b[${colorCode + BACKGROUND_INCREMENT}m${string}\u001b[49m`;
1140
+ }
1141
+ }
1142
+ return string;
1143
+ }
1144
+
1145
+ // Copyright (c) 2015 - 2017 Uber Technologies, Inc.
1146
+ //
1147
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
1148
+ // of this software and associated documentation files (the "Software"), to deal
1149
+ // in the Software without restriction, including without limitation the rights
1150
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1151
+ // copies of the Software, and to permit persons to whom the Software is
1152
+ // furnished to do so, subject to the following conditions:
1153
+ //
1154
+ // The above copyright notice and this permission notice shall be included in
1155
+ // all copies or substantial portions of the Software.
1156
+ //
1157
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1158
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1159
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1160
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1161
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1162
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1163
+ // THE SOFTWARE.
1164
+ /**
1165
+ * Binds the "this" argument of all functions on a class instance to the instance
1166
+ * @param obj - class instance (typically a react component)
1167
+ */
1168
+ function autobind(obj, predefined = ['constructor']) {
1169
+ const proto = Object.getPrototypeOf(obj);
1170
+ const propNames = Object.getOwnPropertyNames(proto);
1171
+ const object = obj;
1172
+ for (const key of propNames) {
1173
+ const value = object[key];
1174
+ if (typeof value === 'function') {
1175
+ if (!predefined.find(name => key === name)) {
1176
+ object[key] = value.bind(obj);
1177
+ }
1178
+ }
1179
+ }
1180
+ }
1181
+
1182
+ function assert(condition, message) {
1183
+ if (!condition) {
1184
+ throw new Error(message || 'Assertion failed');
1185
+ }
1186
+ }
1187
+
1188
+ // probe.gl, MIT license
1189
+ /** Get best timer available. */
1190
+ function getHiResTimestamp() {
1191
+ let timestamp;
1192
+ if (isBrowser() && window_.performance) {
1193
+ timestamp = window_?.performance?.now?.();
1194
+ } else if ('hrtime' in process_) {
1195
+ // @ts-ignore
1196
+ const timeParts = process_?.hrtime?.();
1197
+ timestamp = timeParts[0] * 1000 + timeParts[1] / 1e6;
1198
+ } else {
1199
+ timestamp = Date.now();
1200
+ }
1201
+ return timestamp;
1202
+ }
1203
+
1204
+ // probe.gl, MIT license
1205
+ // Instrumentation in other packages may override console methods, so preserve them here
1206
+ const originalConsole = {
1207
+ debug: isBrowser() ? console.debug || console.log : console.log,
1208
+ log: console.log,
1209
+ info: console.info,
1210
+ warn: console.warn,
1211
+ error: console.error
1212
+ };
1213
+ const DEFAULT_LOG_CONFIGURATION = {
1214
+ enabled: true,
1215
+ level: 0
1216
+ };
1217
+ function noop() {} // eslint-disable-line @typescript-eslint/no-empty-function
1218
+ const cache = {};
1219
+ const ONCE = {
1220
+ once: true
1221
+ };
1222
+ /** A console wrapper */
1223
+ class Log {
1224
+ constructor({
1225
+ id
1226
+ } = {
1227
+ id: ''
1228
+ }) {
1229
+ this.VERSION = VERSION$2;
1230
+ this._startTs = getHiResTimestamp();
1231
+ this._deltaTs = getHiResTimestamp();
1232
+ this.userData = {};
1233
+ // TODO - fix support from throttling groups
1234
+ this.LOG_THROTTLE_TIMEOUT = 0; // Time before throttled messages are logged again
1235
+ this.id = id;
1236
+ this.userData = {};
1237
+ this._storage = new LocalStorage(`__probe-${this.id}__`, DEFAULT_LOG_CONFIGURATION);
1238
+ this.timeStamp(`${this.id} started`);
1239
+ autobind(this);
1240
+ Object.seal(this);
1241
+ }
1242
+ set level(newLevel) {
1243
+ this.setLevel(newLevel);
1244
+ }
1245
+ get level() {
1246
+ return this.getLevel();
1247
+ }
1248
+ isEnabled() {
1249
+ return this._storage.config.enabled;
1250
+ }
1251
+ getLevel() {
1252
+ return this._storage.config.level;
1253
+ }
1254
+ /** @return milliseconds, with fractions */
1255
+ getTotal() {
1256
+ return Number((getHiResTimestamp() - this._startTs).toPrecision(10));
1257
+ }
1258
+ /** @return milliseconds, with fractions */
1259
+ getDelta() {
1260
+ return Number((getHiResTimestamp() - this._deltaTs).toPrecision(10));
1261
+ }
1262
+ /** @deprecated use logLevel */
1263
+ set priority(newPriority) {
1264
+ this.level = newPriority;
1265
+ }
1266
+ /** @deprecated use logLevel */
1267
+ get priority() {
1268
+ return this.level;
1269
+ }
1270
+ /** @deprecated use logLevel */
1271
+ getPriority() {
1272
+ return this.level;
1273
+ }
1274
+ // Configure
1275
+ enable(enabled = true) {
1276
+ this._storage.setConfiguration({
1277
+ enabled
1278
+ });
1279
+ return this;
1280
+ }
1281
+ setLevel(level) {
1282
+ this._storage.setConfiguration({
1283
+ level
1284
+ });
1285
+ return this;
1286
+ }
1287
+ /** return the current status of the setting */
1288
+ get(setting) {
1289
+ return this._storage.config[setting];
1290
+ }
1291
+ // update the status of the setting
1292
+ set(setting, value) {
1293
+ this._storage.setConfiguration({
1294
+ [setting]: value
1295
+ });
1296
+ }
1297
+ /** Logs the current settings as a table */
1298
+ settings() {
1299
+ if (console.table) {
1300
+ console.table(this._storage.config);
1301
+ } else {
1302
+ console.log(this._storage.config);
1303
+ }
1304
+ }
1305
+ // Unconditional logging
1306
+ assert(condition, message) {
1307
+ if (!condition) {
1308
+ throw new Error(message || 'Assertion failed');
1309
+ }
1310
+ }
1311
+ warn(message) {
1312
+ return this._getLogFunction(0, message, originalConsole.warn, arguments, ONCE);
1313
+ }
1314
+ error(message) {
1315
+ return this._getLogFunction(0, message, originalConsole.error, arguments);
1316
+ }
1317
+ /** Print a deprecation warning */
1318
+ deprecated(oldUsage, newUsage) {
1319
+ return this.warn(`\`${oldUsage}\` is deprecated and will be removed \
1320
+ in a later version. Use \`${newUsage}\` instead`);
1321
+ }
1322
+ /** Print a removal warning */
1323
+ removed(oldUsage, newUsage) {
1324
+ return this.error(`\`${oldUsage}\` has been removed. Use \`${newUsage}\` instead`);
1325
+ }
1326
+ probe(logLevel, message) {
1327
+ return this._getLogFunction(logLevel, message, originalConsole.log, arguments, {
1328
+ time: true,
1329
+ once: true
1330
+ });
1331
+ }
1332
+ log(logLevel, message) {
1333
+ return this._getLogFunction(logLevel, message, originalConsole.debug, arguments);
1334
+ }
1335
+ info(logLevel, message) {
1336
+ return this._getLogFunction(logLevel, message, console.info, arguments);
1337
+ }
1338
+ once(logLevel, message) {
1339
+ return this._getLogFunction(logLevel, message, originalConsole.debug || originalConsole.info, arguments, ONCE);
1340
+ }
1341
+ /** Logs an object as a table */
1342
+ table(logLevel, table, columns) {
1343
+ if (table) {
1344
+ return this._getLogFunction(logLevel, table, console.table || noop, columns && [columns], {
1345
+ tag: getTableHeader(table)
1346
+ });
1347
+ }
1348
+ return noop;
1349
+ }
1350
+ time(logLevel, message) {
1351
+ return this._getLogFunction(logLevel, message, console.time ? console.time : console.info);
1352
+ }
1353
+ timeEnd(logLevel, message) {
1354
+ return this._getLogFunction(logLevel, message, console.timeEnd ? console.timeEnd : console.info);
1355
+ }
1356
+ timeStamp(logLevel, message) {
1357
+ return this._getLogFunction(logLevel, message, console.timeStamp || noop);
1358
+ }
1359
+ group(logLevel, message, opts = {
1360
+ collapsed: false
1361
+ }) {
1362
+ const options = normalizeArguments({
1363
+ logLevel,
1364
+ message,
1365
+ opts
1366
+ });
1367
+ const {
1368
+ collapsed
1369
+ } = opts;
1370
+ // @ts-expect-error
1371
+ options.method = (collapsed ? console.groupCollapsed : console.group) || console.info;
1372
+ return this._getLogFunction(options);
1373
+ }
1374
+ groupCollapsed(logLevel, message, opts = {}) {
1375
+ return this.group(logLevel, message, Object.assign({}, opts, {
1376
+ collapsed: true
1377
+ }));
1378
+ }
1379
+ groupEnd(logLevel) {
1380
+ return this._getLogFunction(logLevel, '', console.groupEnd || noop);
1381
+ }
1382
+ // EXPERIMENTAL
1383
+ withGroup(logLevel, message, func) {
1384
+ this.group(logLevel, message)();
1385
+ try {
1386
+ func();
1387
+ } finally {
1388
+ this.groupEnd(logLevel)();
1389
+ }
1390
+ }
1391
+ trace() {
1392
+ if (console.trace) {
1393
+ console.trace();
1394
+ }
1395
+ }
1396
+ // PRIVATE METHODS
1397
+ /** Deduces log level from a variety of arguments */
1398
+ _shouldLog(logLevel) {
1399
+ return this.isEnabled() && this.getLevel() >= normalizeLogLevel(logLevel);
1400
+ }
1401
+ _getLogFunction(logLevel, message, method, args, opts) {
1402
+ if (this._shouldLog(logLevel)) {
1403
+ // normalized opts + timings
1404
+ opts = normalizeArguments({
1405
+ logLevel,
1406
+ message,
1407
+ args,
1408
+ opts
1409
+ });
1410
+ method = method || opts.method;
1411
+ assert(method);
1412
+ opts.total = this.getTotal();
1413
+ opts.delta = this.getDelta();
1414
+ // reset delta timer
1415
+ this._deltaTs = getHiResTimestamp();
1416
+ const tag = opts.tag || opts.message;
1417
+ if (opts.once && tag) {
1418
+ if (!cache[tag]) {
1419
+ cache[tag] = getHiResTimestamp();
1420
+ } else {
1421
+ return noop;
1422
+ }
1423
+ }
1424
+ // TODO - Make throttling work with groups
1425
+ // if (opts.nothrottle || !throttle(tag, this.LOG_THROTTLE_TIMEOUT)) {
1426
+ // return noop;
1427
+ // }
1428
+ message = decorateMessage(this.id, opts.message, opts);
1429
+ // Bind console function so that it can be called after being returned
1430
+ return method.bind(console, message, ...opts.args);
1431
+ }
1432
+ return noop;
1433
+ }
1434
+ }
1435
+ Log.VERSION = VERSION$2;
1436
+ /**
1437
+ * Get logLevel from first argument:
1438
+ * - log(logLevel, message, args) => logLevel
1439
+ * - log(message, args) => 0
1440
+ * - log({logLevel, ...}, message, args) => logLevel
1441
+ * - log({logLevel, message, args}) => logLevel
1442
+ */
1443
+ function normalizeLogLevel(logLevel) {
1444
+ if (!logLevel) {
1445
+ return 0;
1446
+ }
1447
+ let resolvedLevel;
1448
+ switch (typeof logLevel) {
1449
+ case 'number':
1450
+ resolvedLevel = logLevel;
1451
+ break;
1452
+ case 'object':
1453
+ // Backward compatibility
1454
+ // TODO - deprecate `priority`
1455
+ // @ts-expect-error
1456
+ resolvedLevel = logLevel.logLevel || logLevel.priority || 0;
1457
+ break;
1458
+ default:
1459
+ return 0;
1460
+ }
1461
+ // 'log level must be a number'
1462
+ assert(Number.isFinite(resolvedLevel) && resolvedLevel >= 0);
1463
+ return resolvedLevel;
1464
+ }
1465
+ /**
1466
+ * "Normalizes" the various argument patterns into an object with known types
1467
+ * - log(logLevel, message, args) => {logLevel, message, args}
1468
+ * - log(message, args) => {logLevel: 0, message, args}
1469
+ * - log({logLevel, ...}, message, args) => {logLevel, message, args}
1470
+ * - log({logLevel, message, args}) => {logLevel, message, args}
1471
+ */
1472
+ function normalizeArguments(opts) {
1473
+ const {
1474
+ logLevel,
1475
+ message
1476
+ } = opts;
1477
+ opts.logLevel = normalizeLogLevel(logLevel);
1478
+ // We use `arguments` instead of rest parameters (...args) because IE
1479
+ // does not support the syntax. Rest parameters is transpiled to code with
1480
+ // perf impact. Doing it here instead avoids constructing args when logging is
1481
+ // disabled.
1482
+ // TODO - remove when/if IE support is dropped
1483
+ const args = opts.args ? Array.from(opts.args) : [];
1484
+ // args should only contain arguments that appear after `message`
1485
+ // eslint-disable-next-line no-empty
1486
+ while (args.length && args.shift() !== message) {}
1487
+ switch (typeof logLevel) {
1488
+ case 'string':
1489
+ case 'function':
1490
+ if (message !== undefined) {
1491
+ args.unshift(message);
1492
+ }
1493
+ opts.message = logLevel;
1494
+ break;
1495
+ case 'object':
1496
+ Object.assign(opts, logLevel);
1497
+ break;
1498
+ }
1499
+ // Resolve functions into strings by calling them
1500
+ if (typeof opts.message === 'function') {
1501
+ opts.message = opts.message();
1502
+ }
1503
+ const messageType = typeof opts.message;
1504
+ // 'log message must be a string' or object
1505
+ assert(messageType === 'string' || messageType === 'object');
1506
+ // original opts + normalized opts + opts arg + fixed up message
1507
+ return Object.assign(opts, {
1508
+ args
1509
+ }, opts.opts);
1510
+ }
1511
+ function decorateMessage(id, message, opts) {
1512
+ if (typeof message === 'string') {
1513
+ const time = opts.time ? leftPad(formatTime(opts.total)) : '';
1514
+ message = opts.time ? `${id}: ${time} ${message}` : `${id}: ${message}`;
1515
+ message = addColor(message, opts.color, opts.background);
1516
+ }
1517
+ return message;
1518
+ }
1519
+ function getTableHeader(table) {
1520
+ for (const key in table) {
1521
+ for (const title in table[key]) {
1522
+ return title || 'untitled';
1523
+ }
1524
+ }
1525
+ return 'empty';
1526
+ }
1527
+
1528
+ // loaders.gl
1529
+ /**
1530
+ * Helper for safely accessing global loaders.gl variables
1531
+ * Wraps initialization of global variable in function to defeat overly aggressive tree-shakers
1532
+ */
1533
+ function getGlobalLoaderState() {
1534
+ // @ts-ignore
1535
+ globalThis.loaders = globalThis.loaders || {};
1536
+ // @ts-ignore
1537
+ const {
1538
+ loaders
1539
+ } = globalThis;
1540
+ // Add _state object to keep separate from modules added to globalThis.loaders
1541
+ if (!loaders._state) {
1542
+ loaders._state = {};
1543
+ }
1544
+ return loaders._state;
1545
+ }
1546
+
1547
+ // loaders.gl
1548
+ function isLoaderObject(loader) {
1549
+ if (!loader) {
1550
+ return false;
1551
+ }
1552
+ if (Array.isArray(loader)) {
1553
+ loader = loader[0];
1554
+ }
1555
+ const hasExtensions = Array.isArray(loader?.extensions);
1556
+ /* Now handled by types and worker loaders do not have these
1557
+ let hasParser =
1558
+ loader.parseTextSync ||
1559
+ loader.parseSync ||
1560
+ loader.parse ||
1561
+ loader.parseStream || // TODO Remove, Replace with parseInBatches
1562
+ loader.parseInBatches;
1563
+ */
1564
+ return hasExtensions;
1565
+ }
1566
+ function normalizeLoader(loader) {
1567
+ // This error is fairly easy to trigger by mixing up import statements etc
1568
+ // So we make an exception and add a developer error message for this case
1569
+ // To help new users from getting stuck here
1570
+ assert$1(loader, 'null loader');
1571
+ assert$1(isLoaderObject(loader), 'invalid loader');
1572
+ // NORMALIZE [LOADER, OPTIONS] => LOADER
1573
+ // If [loader, options], create a new loaders object with options merged in
1574
+ let options;
1575
+ if (Array.isArray(loader)) {
1576
+ options = loader[1];
1577
+ loader = loader[0];
1578
+ loader = {
1579
+ ...loader,
1580
+ options: {
1581
+ ...loader.options,
1582
+ ...options
1583
+ }
1584
+ };
1585
+ }
1586
+ // NORMALIZE text and binary flags
1587
+ // Ensure at least one of text/binary flags are properly set
1588
+ // @ts-expect-error
1589
+ if (loader?.parseTextSync || loader?.parseText) {
1590
+ loader.text = true;
1591
+ }
1592
+ if (!loader.text) {
1593
+ loader.binary = true;
1594
+ }
1595
+ return loader;
1596
+ }
1597
+
1598
+ // loaders.gl
1599
+ /**
1600
+ * Store global registered loaders on the global object to increase chances of cross loaders-version interoperability
1601
+ * This use case is not reliable but can help when testing new versions of loaders.gl with existing frameworks
1602
+ */
1603
+ const getGlobalLoaderRegistry = () => {
1604
+ const state = getGlobalLoaderState();
1605
+ state.loaderRegistry = state.loaderRegistry || [];
1606
+ return state.loaderRegistry;
1607
+ };
1608
+ /** Register a list of global loaders */
1609
+ function registerLoaders(loaders) {
1610
+ const loaderRegistry = getGlobalLoaderRegistry();
1611
+ loaders = Array.isArray(loaders) ? loaders : [loaders];
1612
+ for (const loader of loaders) {
1613
+ const normalizedLoader = normalizeLoader(loader);
1614
+ if (!loaderRegistry.find(registeredLoader => normalizedLoader === registeredLoader)) {
1615
+ // add to the beginning of the loaderRegistry, so the last registeredLoader get picked
1616
+ loaderRegistry.unshift(normalizedLoader);
1617
+ }
1618
+ }
1619
+ }
1620
+
1621
+ // Version constant cannot be imported, it needs to correspond to the build version of **this** module.
1622
+ // __VERSION__ is injected by babel-plugin-version-inline
1623
+ // @ts-ignore TS2304: Cannot find name '__VERSION__'.
1624
+ const VERSION$1 = "4.2.3" ;
1625
+
1626
+ // @ts-ignore TS2339: Property does not exist on type
1627
+ const parseImageNode = globalThis.loaders?.parseImageNode;
1628
+ const IMAGE_SUPPORTED = typeof Image !== 'undefined'; // NOTE: "false" positives if jsdom is installed
1629
+ const IMAGE_BITMAP_SUPPORTED = typeof ImageBitmap !== 'undefined';
1630
+ const NODE_IMAGE_SUPPORTED = Boolean(parseImageNode);
1631
+ const DATA_SUPPORTED = isBrowser$1 ? true : NODE_IMAGE_SUPPORTED;
1632
+ /**
1633
+ * Checks if a loaders.gl image type is supported
1634
+ * @param type image type string
1635
+ */
1636
+ function isImageTypeSupported(type) {
1637
+ switch (type) {
1638
+ case 'auto':
1639
+ // Should only ever be false in Node.js, if polyfills have not been installed...
1640
+ return IMAGE_BITMAP_SUPPORTED || IMAGE_SUPPORTED || DATA_SUPPORTED;
1641
+ case 'imagebitmap':
1642
+ return IMAGE_BITMAP_SUPPORTED;
1643
+ case 'image':
1644
+ return IMAGE_SUPPORTED;
1645
+ case 'data':
1646
+ return DATA_SUPPORTED;
1647
+ default:
1648
+ throw new Error(`@loaders.gl/images: image ${type} not supported in this environment`);
1649
+ }
1650
+ }
1651
+ /**
1652
+ * Returns the "most performant" supported image type on this platform
1653
+ * @returns image type string
1654
+ */
1655
+ function getDefaultImageType() {
1656
+ if (IMAGE_BITMAP_SUPPORTED) {
1657
+ return 'imagebitmap';
1658
+ }
1659
+ if (IMAGE_SUPPORTED) {
1660
+ return 'image';
1661
+ }
1662
+ if (DATA_SUPPORTED) {
1663
+ return 'data';
1664
+ }
1665
+ // This should only happen in Node.js
1666
+ throw new Error('Install \'@loaders.gl/polyfills\' to parse images under Node.js');
1667
+ }
1668
+
1669
+ function getImageType(image) {
1670
+ const format = getImageTypeOrNull(image);
1671
+ if (!format) {
1672
+ throw new Error('Not an image');
1673
+ }
1674
+ return format;
1675
+ }
1676
+ function getImageData(image) {
1677
+ switch (getImageType(image)) {
1678
+ case 'data':
1679
+ return image;
1680
+ case 'image':
1681
+ case 'imagebitmap':
1682
+ // Extract the image data from the image via a canvas
1683
+ const canvas = document.createElement('canvas');
1684
+ // TODO - reuse the canvas?
1685
+ const context = canvas.getContext('2d');
1686
+ if (!context) {
1687
+ throw new Error('getImageData');
1688
+ }
1689
+ // @ts-ignore
1690
+ canvas.width = image.width;
1691
+ // @ts-ignore
1692
+ canvas.height = image.height;
1693
+ // @ts-ignore
1694
+ context.drawImage(image, 0, 0);
1695
+ // @ts-ignore
1696
+ return context.getImageData(0, 0, image.width, image.height);
1697
+ default:
1698
+ throw new Error('getImageData');
1699
+ }
1700
+ }
1701
+ // PRIVATE
1702
+ // eslint-disable-next-line complexity
1703
+ function getImageTypeOrNull(image) {
1704
+ if (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap) {
1705
+ return 'imagebitmap';
1706
+ }
1707
+ if (typeof Image !== 'undefined' && image instanceof Image) {
1708
+ return 'image';
1709
+ }
1710
+ if (image && typeof image === 'object' && image.data && image.width && image.height) {
1711
+ return 'data';
1712
+ }
1713
+ return null;
1714
+ }
1715
+
1716
+ // SVG parsing has limitations, e.g:
1717
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=606319
1718
+ const SVG_DATA_URL_PATTERN = /^data:image\/svg\+xml/;
1719
+ const SVG_URL_PATTERN = /\.svg((\?|#).*)?$/;
1720
+ function isSVG(url) {
1721
+ return url && (SVG_DATA_URL_PATTERN.test(url) || SVG_URL_PATTERN.test(url));
1722
+ }
1723
+ function getBlobOrSVGDataUrl(arrayBuffer, url) {
1724
+ if (isSVG(url)) {
1725
+ // Prepare a properly tagged data URL, and load using normal mechanism
1726
+ const textDecoder = new TextDecoder();
1727
+ let xmlText = textDecoder.decode(arrayBuffer);
1728
+ // TODO Escape in browser to support e.g. Chinese characters
1729
+ try {
1730
+ if (typeof unescape === 'function' && typeof encodeURIComponent === 'function') {
1731
+ xmlText = unescape(encodeURIComponent(xmlText));
1732
+ }
1733
+ } catch (error) {
1734
+ throw new Error(error.message);
1735
+ }
1736
+ // base64 encoding is safer. utf-8 fails in some browsers
1737
+ const src = `data:image/svg+xml;base64,${btoa(xmlText)}`;
1738
+ return src;
1739
+ }
1740
+ return getBlob(arrayBuffer, url);
1741
+ }
1742
+ function getBlob(arrayBuffer, url) {
1743
+ if (isSVG(url)) {
1744
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=606319
1745
+ // return new Blob([new Uint8Array(arrayBuffer)], {type: 'image/svg+xml'});
1746
+ throw new Error('SVG cannot be parsed directly to imagebitmap');
1747
+ }
1748
+ // TODO - how to determine mime type? Param? Sniff here?
1749
+ return new Blob([new Uint8Array(arrayBuffer)]); // MIME type not needed?
1750
+ }
1751
+
1752
+ // Parses html image from array buffer
1753
+ async function parseToImage(arrayBuffer, options, url) {
1754
+ // Note: image parsing requires conversion to Blob (for createObjectURL).
1755
+ // Potentially inefficient for not using `response.blob()` (and for File / Blob inputs)...
1756
+ // But presumably not worth adding 'blob' flag to loader objects?
1757
+ const blobOrDataUrl = getBlobOrSVGDataUrl(arrayBuffer, url);
1758
+ const URL = self.URL || self.webkitURL;
1759
+ const objectUrl = typeof blobOrDataUrl !== 'string' && URL.createObjectURL(blobOrDataUrl);
1760
+ try {
1761
+ return await loadToImage(objectUrl || blobOrDataUrl, options);
1762
+ } finally {
1763
+ if (objectUrl) {
1764
+ URL.revokeObjectURL(objectUrl);
1765
+ }
1766
+ }
1767
+ }
1768
+ async function loadToImage(url, options) {
1769
+ const image = new Image();
1770
+ image.src = url;
1771
+ // The `image.onload()` callback does not guarantee that the image has been decoded
1772
+ // so a main thread "freeze" can be incurred when using the image for the first time.
1773
+ // `Image.decode()` returns a promise that completes when image is decoded.
1774
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode
1775
+ // Note: When calling `img.decode()`, we do not need to wait for `img.onload()`
1776
+ // Note: `HTMLImageElement.decode()` is not available in Edge and IE11
1777
+ if (options.image && options.image.decode && image.decode) {
1778
+ await image.decode();
1779
+ return image;
1780
+ }
1781
+ // Create a promise that tracks onload/onerror callbacks
1782
+ return await new Promise((resolve, reject) => {
1783
+ try {
1784
+ image.onload = () => resolve(image);
1785
+ image.onerror = error => {
1786
+ const message = error instanceof Error ? error.message : 'error';
1787
+ reject(new Error(message));
1788
+ };
1789
+ } catch (error) {
1790
+ reject(error);
1791
+ }
1792
+ });
1793
+ }
1794
+
1795
+ const EMPTY_OBJECT = {};
1796
+ let imagebitmapOptionsSupported = true;
1797
+ /**
1798
+ * Asynchronously parses an array buffer into an ImageBitmap - this contains the decoded data
1799
+ * ImageBitmaps are supported on worker threads, but not supported on Edge, IE11 and Safari
1800
+ * https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap#Browser_compatibility
1801
+ *
1802
+ * TODO - createImageBitmap supports source rect (5 param overload), pass through?
1803
+ */
1804
+ async function parseToImageBitmap(arrayBuffer, options, url) {
1805
+ let blob;
1806
+ // Cannot parse SVG directly to ImageBitmap, parse to Image first
1807
+ if (isSVG(url)) {
1808
+ // Note: this only works on main thread
1809
+ const image = await parseToImage(arrayBuffer, options, url);
1810
+ blob = image;
1811
+ } else {
1812
+ // Create blob from the array buffer
1813
+ blob = getBlob(arrayBuffer, url);
1814
+ }
1815
+ const imagebitmapOptions = options && options.imagebitmap;
1816
+ return await safeCreateImageBitmap(blob, imagebitmapOptions);
1817
+ }
1818
+ /**
1819
+ * Safely creates an imageBitmap with options
1820
+ * *
1821
+ * Firefox crashes if imagebitmapOptions is supplied
1822
+ * Avoid supplying if not provided or supported, remember if not supported
1823
+ */
1824
+ async function safeCreateImageBitmap(blob, imagebitmapOptions = null) {
1825
+ if (isEmptyObject(imagebitmapOptions) || !imagebitmapOptionsSupported) {
1826
+ imagebitmapOptions = null;
1827
+ }
1828
+ if (imagebitmapOptions) {
1829
+ try {
1830
+ // @ts-ignore Options
1831
+ return await createImageBitmap(blob, imagebitmapOptions);
1832
+ } catch (error) {
1833
+ console.warn(error); // eslint-disable-line
1834
+ imagebitmapOptionsSupported = false;
1835
+ }
1836
+ }
1837
+ return await createImageBitmap(blob);
1838
+ }
1839
+ function isEmptyObject(object) {
1840
+ // @ts-ignore
1841
+ for (const key in object || EMPTY_OBJECT) {
1842
+ return false;
1843
+ }
1844
+ return true;
1845
+ }
1846
+
1847
+ // loaders.gl
1848
+ // SPDX-License-Identifier: MIT
1849
+ // Copyright (c) vis.gl contributors
1850
+ // code adapted from https://github.com/sindresorhus/file-type under MIT license
1851
+ /**
1852
+ * Tests if a buffer is in ISO base media file format (ISOBMFF) @see https://en.wikipedia.org/wiki/ISO_base_media_file_format
1853
+ * (ISOBMFF is a media container standard based on the Apple QuickTime container format)
1854
+ */
1855
+ function getISOBMFFMediaType(buffer) {
1856
+ // Almost all ISO base media files start with `ftyp` box. (It's not required to be first, but it's recommended to be.)
1857
+ if (!checkString(buffer, 'ftyp', 4)) {
1858
+ return null;
1859
+ }
1860
+ // Extra check: test for 8859-1 printable characters (for simplicity, it's a mask which also catches one non-printable character).
1861
+ if ((buffer[8] & 0x60) === 0x00) {
1862
+ return null;
1863
+ }
1864
+ // `ftyp` box must contain a brand major identifier, which must consist of ISO 8859-1 printable characters.
1865
+ return decodeMajorBrand(buffer);
1866
+ }
1867
+ /**
1868
+ * brands explained @see https://github.com/strukturag/libheif/issues/83
1869
+ * code adapted from @see https://github.com/sindresorhus/file-type/blob/main/core.js#L489-L492
1870
+ */
1871
+ function decodeMajorBrand(buffer) {
1872
+ const brandMajor = getUTF8String(buffer, 8, 12).replace('\0', ' ').trim();
1873
+ switch (brandMajor) {
1874
+ case 'avif':
1875
+ case 'avis':
1876
+ return {
1877
+ extension: 'avif',
1878
+ mimeType: 'image/avif'
1879
+ };
1880
+ default:
1881
+ return null;
1882
+ }
1883
+ // We don't need these now, but they are easy to add
1884
+ // case 'mif1':
1885
+ // return {extension: 'heic', mimeType: 'image/heif'};
1886
+ // case 'msf1':
1887
+ // return {extension: 'heic', mimeType: 'image/heif-sequence'};
1888
+ // case 'heic':
1889
+ // case 'heix':
1890
+ // return {extension: 'heic', mimeType: 'image/heic'};
1891
+ // case 'hevc':
1892
+ // case 'hevx':
1893
+ // return {extension: 'heic', mimeType: 'image/heic-sequence'};
1894
+ // case 'qt':
1895
+ // return {ext: 'mov', mime: 'video/quicktime'};
1896
+ // case 'M4V':
1897
+ // case 'M4VH':
1898
+ // case 'M4VP':
1899
+ // return {ext: 'm4v', mime: 'video/x-m4v'};
1900
+ // case 'M4P':
1901
+ // return {ext: 'm4p', mime: 'video/mp4'};
1902
+ // case 'M4B':
1903
+ // return {ext: 'm4b', mime: 'audio/mp4'};
1904
+ // case 'M4A':
1905
+ // return {ext: 'm4a', mime: 'audio/x-m4a'};
1906
+ // case 'F4V':
1907
+ // return {ext: 'f4v', mime: 'video/mp4'};
1908
+ // case 'F4P':
1909
+ // return {ext: 'f4p', mime: 'video/mp4'};
1910
+ // case 'F4A':
1911
+ // return {ext: 'f4a', mime: 'audio/mp4'};
1912
+ // case 'F4B':
1913
+ // return {ext: 'f4b', mime: 'audio/mp4'};
1914
+ // case 'crx':
1915
+ // return {ext: 'cr3', mime: 'image/x-canon-cr3'};
1916
+ // default:
1917
+ // if (brandMajor.startsWith('3g')) {
1918
+ // if (brandMajor.startsWith('3g2')) {
1919
+ // return {ext: '3g2', mime: 'video/3gpp2'};
1920
+ // }
1921
+ // return {ext: '3gp', mime: 'video/3gpp'};
1922
+ // }
1923
+ // return {ext: 'mp4', mime: 'video/mp4'};
1924
+ }
1925
+ /** Interpret a chunk of bytes as a UTF8 string */
1926
+ function getUTF8String(array, start, end) {
1927
+ return String.fromCharCode(...array.slice(start, end));
1928
+ }
1929
+ function stringToBytes(string) {
1930
+ return [...string].map(character => character.charCodeAt(0));
1931
+ }
1932
+ function checkString(buffer, header, offset = 0) {
1933
+ const headerBytes = stringToBytes(header);
1934
+ for (let i = 0; i < headerBytes.length; ++i) {
1935
+ if (headerBytes[i] !== buffer[i + offset]) {
1936
+ return false;
1937
+ }
1938
+ }
1939
+ return true;
1940
+ }
1941
+
1942
+ // Attributions
1943
+ const BIG_ENDIAN = false;
1944
+ const LITTLE_ENDIAN = true;
1945
+ /**
1946
+ * Extracts `{mimeType, width and height}` from a memory buffer containing a known image format
1947
+ * Currently supports `image/png`, `image/jpeg`, `image/bmp` and `image/gif`.
1948
+ * @param binaryData: DataView | ArrayBuffer image file memory to parse
1949
+ * @returns metadata or null if memory is not a valid image file format layout.
1950
+ */
1951
+ function getBinaryImageMetadata(binaryData) {
1952
+ const dataView = toDataView(binaryData);
1953
+ return getPngMetadata(dataView) || getJpegMetadata(dataView) || getGifMetadata(dataView) || getBmpMetadata(dataView) || getISOBMFFMetadata(dataView);
1954
+ }
1955
+ // ISOBMFF
1956
+ function getISOBMFFMetadata(binaryData) {
1957
+ const buffer = new Uint8Array(binaryData instanceof DataView ? binaryData.buffer : binaryData);
1958
+ const mediaType = getISOBMFFMediaType(buffer);
1959
+ if (!mediaType) {
1960
+ return null;
1961
+ }
1962
+ return {
1963
+ mimeType: mediaType.mimeType,
1964
+ // TODO - decode width and height
1965
+ width: 0,
1966
+ height: 0
1967
+ };
1968
+ }
1969
+ // PNG
1970
+ function getPngMetadata(binaryData) {
1971
+ const dataView = toDataView(binaryData);
1972
+ // Check file contains the first 4 bytes of the PNG signature.
1973
+ const isPng = dataView.byteLength >= 24 && dataView.getUint32(0, BIG_ENDIAN) === 0x89504e47;
1974
+ if (!isPng) {
1975
+ return null;
1976
+ }
1977
+ // Extract size from a binary PNG file
1978
+ return {
1979
+ mimeType: 'image/png',
1980
+ width: dataView.getUint32(16, BIG_ENDIAN),
1981
+ height: dataView.getUint32(20, BIG_ENDIAN)
1982
+ };
1983
+ }
1984
+ // GIF
1985
+ // Extract size from a binary GIF file
1986
+ // TODO: GIF is not this simple
1987
+ function getGifMetadata(binaryData) {
1988
+ const dataView = toDataView(binaryData);
1989
+ // Check first 4 bytes of the GIF signature ("GIF8").
1990
+ const isGif = dataView.byteLength >= 10 && dataView.getUint32(0, BIG_ENDIAN) === 0x47494638;
1991
+ if (!isGif) {
1992
+ return null;
1993
+ }
1994
+ // GIF is little endian.
1995
+ return {
1996
+ mimeType: 'image/gif',
1997
+ width: dataView.getUint16(6, LITTLE_ENDIAN),
1998
+ height: dataView.getUint16(8, LITTLE_ENDIAN)
1999
+ };
2000
+ }
2001
+ // BMP
2002
+ // TODO: BMP is not this simple
2003
+ function getBmpMetadata(binaryData) {
2004
+ const dataView = toDataView(binaryData);
2005
+ // Check magic number is valid (first 2 characters should be "BM").
2006
+ // The mandatory bitmap file header is 14 bytes long.
2007
+ const isBmp = dataView.byteLength >= 14 && dataView.getUint16(0, BIG_ENDIAN) === 0x424d && dataView.getUint32(2, LITTLE_ENDIAN) === dataView.byteLength;
2008
+ if (!isBmp) {
2009
+ return null;
2010
+ }
2011
+ // BMP is little endian.
2012
+ return {
2013
+ mimeType: 'image/bmp',
2014
+ width: dataView.getUint32(18, LITTLE_ENDIAN),
2015
+ height: dataView.getUint32(22, LITTLE_ENDIAN)
2016
+ };
2017
+ }
2018
+ // JPEG
2019
+ // Extract width and height from a binary JPEG file
2020
+ function getJpegMetadata(binaryData) {
2021
+ const dataView = toDataView(binaryData);
2022
+ // Check file contains the JPEG "start of image" (SOI) marker
2023
+ // followed by another marker.
2024
+ const isJpeg = dataView.byteLength >= 3 && dataView.getUint16(0, BIG_ENDIAN) === 0xffd8 && dataView.getUint8(2) === 0xff;
2025
+ if (!isJpeg) {
2026
+ return null;
2027
+ }
2028
+ const {
2029
+ tableMarkers,
2030
+ sofMarkers
2031
+ } = getJpegMarkers();
2032
+ // Exclude the two byte SOI marker.
2033
+ let i = 2;
2034
+ while (i + 9 < dataView.byteLength) {
2035
+ const marker = dataView.getUint16(i, BIG_ENDIAN);
2036
+ // The frame that contains the width and height of the JPEG image.
2037
+ if (sofMarkers.has(marker)) {
2038
+ return {
2039
+ mimeType: 'image/jpeg',
2040
+ height: dataView.getUint16(i + 5, BIG_ENDIAN),
2041
+ // Number of lines
2042
+ width: dataView.getUint16(i + 7, BIG_ENDIAN) // Number of pixels per line
2043
+ };
2044
+ }
2045
+ // Miscellaneous tables/data preceding the frame header.
2046
+ if (!tableMarkers.has(marker)) {
2047
+ return null;
2048
+ }
2049
+ // Length includes size of length parameter but not the two byte header.
2050
+ i += 2;
2051
+ i += dataView.getUint16(i, BIG_ENDIAN);
2052
+ }
2053
+ return null;
2054
+ }
2055
+ function getJpegMarkers() {
2056
+ // Tables/misc header markers.
2057
+ // DQT, DHT, DAC, DRI, COM, APP_n
2058
+ const tableMarkers = new Set([0xffdb, 0xffc4, 0xffcc, 0xffdd, 0xfffe]);
2059
+ for (let i = 0xffe0; i < 0xfff0; ++i) {
2060
+ tableMarkers.add(i);
2061
+ }
2062
+ // SOF markers and DHP marker.
2063
+ // These markers are after tables/misc data.
2064
+ const sofMarkers = new Set([0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc5, 0xffc6, 0xffc7, 0xffc9, 0xffca, 0xffcb, 0xffcd, 0xffce, 0xffcf, 0xffde]);
2065
+ return {
2066
+ tableMarkers,
2067
+ sofMarkers
2068
+ };
2069
+ }
2070
+ // TODO - move into image module?
2071
+ function toDataView(data) {
2072
+ if (data instanceof DataView) {
2073
+ return data;
2074
+ }
2075
+ if (ArrayBuffer.isView(data)) {
2076
+ return new DataView(data.buffer);
2077
+ }
2078
+ // TODO: make these functions work for Node.js buffers?
2079
+ // if (bufferToArrayBuffer) {
2080
+ // data = bufferToArrayBuffer(data);
2081
+ // }
2082
+ // Careful - Node Buffers will look like ArrayBuffers (keep after isBuffer)
2083
+ if (data instanceof ArrayBuffer) {
2084
+ return new DataView(data);
2085
+ }
2086
+ throw new Error('toDataView');
2087
+ }
2088
+
2089
+ // Use polyfills if installed to parsed image using get-pixels
2090
+ async function parseToNodeImage(arrayBuffer, options) {
2091
+ const {
2092
+ mimeType
2093
+ } = getBinaryImageMetadata(arrayBuffer) || {};
2094
+ // @ts-ignore
2095
+ const parseImageNode = globalThis.loaders?.parseImageNode;
2096
+ assert$1(parseImageNode); // '@loaders.gl/polyfills not installed'
2097
+ // @ts-expect-error TODO should we throw error in this case?
2098
+ return await parseImageNode(arrayBuffer, mimeType);
2099
+ }
2100
+
2101
+ // Parse to platform defined image type (data on node, ImageBitmap or HTMLImage on browser)
2102
+ // eslint-disable-next-line complexity
2103
+ async function parseImage(arrayBuffer, options, context) {
2104
+ options = options || {};
2105
+ const imageOptions = options.image || {};
2106
+ // The user can request a specific output format via `options.image.type`
2107
+ const imageType = imageOptions.type || 'auto';
2108
+ const {
2109
+ url
2110
+ } = context || {};
2111
+ // Note: For options.image.type === `data`, we may still need to load as `image` or `imagebitmap`
2112
+ const loadType = getLoadableImageType(imageType);
2113
+ let image;
2114
+ switch (loadType) {
2115
+ case 'imagebitmap':
2116
+ image = await parseToImageBitmap(arrayBuffer, options, url);
2117
+ break;
2118
+ case 'image':
2119
+ image = await parseToImage(arrayBuffer, options, url);
2120
+ break;
2121
+ case 'data':
2122
+ // Node.js loads imagedata directly
2123
+ image = await parseToNodeImage(arrayBuffer);
2124
+ break;
2125
+ default:
2126
+ assert$1(false);
2127
+ }
2128
+ // Browser: if options.image.type === 'data', we can now extract data from the loaded image
2129
+ if (imageType === 'data') {
2130
+ image = getImageData(image);
2131
+ }
2132
+ return image;
2133
+ }
2134
+ // Get a loadable image type from image type
2135
+ function getLoadableImageType(type) {
2136
+ switch (type) {
2137
+ case 'auto':
2138
+ case 'data':
2139
+ // Browser: For image data we need still need to load using an image format
2140
+ // Node: the default image type is `data`.
2141
+ return getDefaultImageType();
2142
+ default:
2143
+ // Throw an error if not supported
2144
+ isImageTypeSupported(type);
2145
+ return type;
2146
+ }
2147
+ }
2148
+
2149
+ // import type { ImageType } from '@loaders.gl/schema';
2150
+ const EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'ico', 'svg', 'avif'];
2151
+ const MIME_TYPES = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/avif', 'image/bmp', 'image/vnd.microsoft.icon', 'image/svg+xml'];
2152
+ const DEFAULT_IMAGE_LOADER_OPTIONS = {
2153
+ image: {
2154
+ type: 'auto',
2155
+ decode: true // if format is HTML
2156
+ }
2157
+ // imagebitmap: {} - passes (platform dependent) parameters to ImageBitmap constructor
2158
+ };
2159
+ /**
2160
+ * Loads a platform-specific image type
2161
+ * Note: This type can be used as input data to WebGL texture creation
2162
+ */
2163
+ const ImageLoader = {
2164
+ dataType: null,
2165
+ batchType: null,
2166
+ id: 'image',
2167
+ module: 'images',
2168
+ name: 'Images',
2169
+ version: VERSION$1,
2170
+ mimeTypes: MIME_TYPES,
2171
+ extensions: EXTENSIONS,
2172
+ parse: parseImage,
2173
+ // TODO: byteOffset, byteLength;
2174
+ tests: [arrayBuffer => Boolean(getBinaryImageMetadata(new DataView(arrayBuffer)))],
2175
+ options: DEFAULT_IMAGE_LOADER_OPTIONS
2176
+ };
2177
+
2178
+ const defaultLogger = new Log({
2179
+ id: 'deck'
2180
+ });
2181
+ var log = defaultLogger;
2182
+
2183
+ const logState = {
2184
+ attributeUpdateStart: -1,
2185
+ attributeManagerUpdateStart: -1,
2186
+ attributeUpdateMessages: []
2187
+ };
2188
+ const LOG_LEVEL_MAJOR_UPDATE = 1; // Events with direct perf impact
2189
+ const LOG_LEVEL_MINOR_UPDATE = 2; // Events that may affect perf
2190
+ const LOG_LEVEL_UPDATE_DETAIL = 3;
2191
+ const LOG_LEVEL_INFO = 4;
2192
+ const LOG_LEVEL_DRAW = 2;
2193
+ const getLoggers = log => ({
2194
+ /* Layer events */
2195
+ 'layer.changeFlag': (layer, key, flags) => {
2196
+ log.log(LOG_LEVEL_UPDATE_DETAIL, `${layer.id} ${key}: `, flags[key])();
2197
+ },
2198
+ 'layer.initialize': layer => {
2199
+ log.log(LOG_LEVEL_MAJOR_UPDATE, `Initializing ${layer}`)();
2200
+ },
2201
+ 'layer.update': (layer, needsUpdate) => {
2202
+ if (needsUpdate) {
2203
+ const flags = layer.getChangeFlags();
2204
+ log.log(LOG_LEVEL_MINOR_UPDATE, `Updating ${layer} because: ${Object.keys(flags).filter(key => flags[key]).join(', ')}`)();
2205
+ } else {
2206
+ log.log(LOG_LEVEL_INFO, `${layer} does not need update`)();
2207
+ }
2208
+ },
2209
+ 'layer.matched': (layer, changed) => {
2210
+ if (changed) {
2211
+ log.log(LOG_LEVEL_INFO, `Matched ${layer}, state transfered`)();
2212
+ }
2213
+ },
2214
+ 'layer.finalize': layer => {
2215
+ log.log(LOG_LEVEL_MAJOR_UPDATE, `Finalizing ${layer}`)();
2216
+ },
2217
+ /* CompositeLayer events */
2218
+ 'compositeLayer.renderLayers': (layer, updated, subLayers) => {
2219
+ if (updated) {
2220
+ log.log(LOG_LEVEL_MINOR_UPDATE, `Composite layer rendered new subLayers ${layer}`, subLayers)();
2221
+ } else {
2222
+ log.log(LOG_LEVEL_INFO, `Composite layer reused subLayers ${layer}`, subLayers)();
2223
+ }
2224
+ },
2225
+ /* LayerManager events */
2226
+ 'layerManager.setLayers': (layerManager, updated, layers) => {
2227
+ if (updated) {
2228
+ log.log(LOG_LEVEL_MINOR_UPDATE, `Updating ${layers.length} deck layers`)();
2229
+ }
2230
+ },
2231
+ 'layerManager.activateViewport': (layerManager, viewport) => {
2232
+ log.log(LOG_LEVEL_UPDATE_DETAIL, 'Viewport changed', viewport)();
2233
+ },
2234
+ /* AttributeManager events */
2235
+ 'attributeManager.invalidate': (attributeManager, trigger, attributeNames) => {
2236
+ log.log(LOG_LEVEL_MAJOR_UPDATE, attributeNames ? `invalidated attributes ${attributeNames} (${trigger}) for ${attributeManager.id}` : `invalidated all attributes for ${attributeManager.id}`)();
2237
+ },
2238
+ 'attributeManager.updateStart': attributeManager => {
2239
+ logState.attributeUpdateMessages.length = 0;
2240
+ logState.attributeManagerUpdateStart = Date.now();
2241
+ },
2242
+ 'attributeManager.updateEnd': (attributeManager, numInstances) => {
2243
+ const timeMs = Math.round(Date.now() - logState.attributeManagerUpdateStart);
2244
+ log.groupCollapsed(LOG_LEVEL_MINOR_UPDATE, `Updated attributes for ${numInstances} instances in ${attributeManager.id} in ${timeMs}ms`)();
2245
+ for (const updateMessage of logState.attributeUpdateMessages) {
2246
+ log.log(LOG_LEVEL_UPDATE_DETAIL, updateMessage)();
2247
+ }
2248
+ log.groupEnd(LOG_LEVEL_MINOR_UPDATE)();
2249
+ },
2250
+ /* Attribute events */
2251
+ 'attribute.updateStart': attribute => {
2252
+ logState.attributeUpdateStart = Date.now();
2253
+ },
2254
+ 'attribute.allocate': (attribute, numInstances) => {
2255
+ const message = `${attribute.id} allocated ${numInstances}`;
2256
+ logState.attributeUpdateMessages.push(message);
2257
+ },
2258
+ 'attribute.updateEnd': (attribute, numInstances) => {
2259
+ const timeMs = Math.round(Date.now() - logState.attributeUpdateStart);
2260
+ const message = `${attribute.id} updated ${numInstances} in ${timeMs}ms`;
2261
+ logState.attributeUpdateMessages.push(message);
2262
+ },
2263
+ /* Render events */
2264
+ 'deckRenderer.renderLayers': (deckRenderer, renderStats, opts) => {
2265
+ const {
2266
+ pass,
2267
+ redrawReason,
2268
+ stats
2269
+ } = opts;
2270
+ for (const status of renderStats) {
2271
+ const {
2272
+ totalCount,
2273
+ visibleCount,
2274
+ compositeCount,
2275
+ pickableCount
2276
+ } = status;
2277
+ const primitiveCount = totalCount - compositeCount;
2278
+ const hiddenCount = primitiveCount - visibleCount;
2279
+ log.log(LOG_LEVEL_DRAW, `RENDER #${deckRenderer.renderCount} \
2280
+ ${visibleCount} (of ${totalCount} layers) to ${pass} because ${redrawReason} \
2281
+ (${hiddenCount} hidden, ${compositeCount} composite ${pickableCount} pickable)`)();
2282
+ if (stats) {
2283
+ stats.get('Redraw Layers').add(visibleCount);
2284
+ }
2285
+ }
2286
+ }
2287
+ });
2288
+
2289
+ // Conditionally load default loggers in development mode
2290
+ // eslint-disable-next-line
2291
+ if (process.env.NODE_ENV !== 'production') {
2292
+ getLoggers(log);
2293
+ }
2294
+ function register(handlers) {
2295
+ }
2296
+
2297
+ function isJSON(text) {
2298
+ const firstChar = text[0];
2299
+ const lastChar = text[text.length - 1];
2300
+ return firstChar === '{' && lastChar === '}' || firstChar === '[' && lastChar === ']';
2301
+ }
2302
+ // A light weight version instead of @loaders.gl/json (stream processing etc.)
2303
+ var jsonLoader = {
2304
+ dataType: null,
2305
+ batchType: null,
2306
+ id: 'JSON',
2307
+ name: 'JSON',
2308
+ module: '',
2309
+ version: '',
2310
+ options: {},
2311
+ extensions: ['json', 'geojson'],
2312
+ mimeTypes: ['application/json', 'application/geo+json'],
2313
+ testText: isJSON,
2314
+ parseTextSync: JSON.parse
2315
+ };
2316
+
2317
+ // Copyright (c) 2015 - 2017 Uber Technologies, Inc.
2318
+ function checkVersion() {
2319
+ // Version detection using typescript plugin.
2320
+ // Fallback for tests and SSR since global variable is defined by esbuild.
2321
+ const version = "9.0.30" ;
2322
+ // Note: a `deck` object not created by deck.gl may exist in the global scope
2323
+ const existingVersion = globalThis.deck && globalThis.deck.VERSION;
2324
+ if (existingVersion && existingVersion !== version) {
2325
+ throw new Error(`deck.gl - multiple versions detected: ${existingVersion} vs ${version}`);
2326
+ }
2327
+ if (!existingVersion) {
2328
+ log.log(1, `deck.gl ${version}`)();
2329
+ globalThis.deck = {
2330
+ ...globalThis.deck,
2331
+ VERSION: version,
2332
+ version,
2333
+ log,
2334
+ // experimental
2335
+ _registerLoggers: register
2336
+ };
2337
+ registerLoaders([jsonLoader,
2338
+ // @ts-expect-error non-standard Loader format
2339
+ [ImageLoader, {
2340
+ imagebitmap: {
2341
+ premultiplyAlpha: 'none'
2342
+ }
2343
+ }]]);
2344
+ }
2345
+ return version;
2346
+ }
2347
+ const VERSION = checkVersion();
2348
+
980
2349
  const DEFAULT_TILE_RESOLUTION = 0.5;
981
2350
  const DEFAULT_AGGREGATION_RES_LEVEL_H3 = 4;
982
2351
  const DEFAULT_AGGREGATION_RES_LEVEL_QUADBIN = 6;
@@ -1056,7 +2425,7 @@ function buildSourceUrl({
1056
2425
  */
1057
2426
  const DEFAULT_PARAMETERS = {
1058
2427
  v: V3_MINOR_VERSION,
1059
- deckglVersion: "0.2.2-alpha.0"
2428
+ deckglVersion: VERSION
1060
2429
  };
1061
2430
  const DEFAULT_HEADERS = {
1062
2431
  Accept: 'application/json',
@@ -1579,6 +2948,7 @@ function assignDefaultProps(props) {
1579
2948
  }
1580
2949
  }
1581
2950
 
2951
+ exports.API_CLIENT_VERSION = API_CLIENT_VERSION;
1582
2952
  exports.WidgetBaseSource = WidgetBaseSource;
1583
2953
  exports.WidgetQuerySource = WidgetQuerySource;
1584
2954
  exports.WidgetTableSource = WidgetTableSource;