radar-sdk-js 4.5.0-beta.0 → 4.5.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.
- package/README.md +8 -8
- package/dist/api/verify.d.ts +6 -4
- package/dist/api.d.ts +5 -4
- package/dist/logger.d.ts +1 -1
- package/dist/radar.js +235 -257
- package/dist/radar.js.map +1 -1
- package/dist/types.d.ts +31 -14
- package/dist/ui/RadarMap.d.ts +0 -1
- package/dist/ui/RadarMarker.d.ts +0 -2
- package/dist/ui/autocomplete.d.ts +4 -2
- package/dist/version.d.ts +1 -1
- package/package.json +13 -3
- package/src/api/geocoding.ts +2 -1
- package/src/api/search.ts +4 -0
- package/src/api/track.ts +0 -32
- package/src/api/verify.ts +110 -76
- package/src/api.ts +11 -6
- package/src/http.ts +6 -2
- package/src/logger.ts +2 -2
- package/src/navigator.ts +1 -1
- package/src/types.ts +38 -15
- package/src/ui/RadarLogoControl.ts +1 -0
- package/src/ui/RadarMap.ts +1 -12
- package/src/ui/RadarMarker.ts +81 -100
- package/src/ui/autocomplete.ts +34 -6
- package/src/version.ts +1 -1
package/dist/radar.js
CHANGED
|
@@ -42,9 +42,9 @@ const getLevel = () => {
|
|
|
42
42
|
return LOG_LEVELS.error; // default to error-level logging if not set
|
|
43
43
|
};
|
|
44
44
|
class Logger {
|
|
45
|
-
static debug(message) {
|
|
45
|
+
static debug(message, options) {
|
|
46
46
|
if (getLevel() === LOG_LEVELS.debug) {
|
|
47
|
-
console.log(`Radar SDK (debug): ${message.trim()}
|
|
47
|
+
console.log(`Radar SDK (debug): ${message.trim()}`, options);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
static info(message) {
|
|
@@ -305,7 +305,7 @@ class RadarAutocompleteContainerNotFound extends RadarError {
|
|
|
305
305
|
|
|
306
306
|
const DEFAULT_POSITION_OPTIONS = {
|
|
307
307
|
maximumAge: 0,
|
|
308
|
-
timeout: 1000 *
|
|
308
|
+
timeout: 1000 * 10,
|
|
309
309
|
enableHighAccuracy: true,
|
|
310
310
|
};
|
|
311
311
|
// set "enableHighAccuracy" for navigator only when desiredAccuracy is "high"
|
|
@@ -405,7 +405,7 @@ class Navigator {
|
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
-
var SDK_VERSION = '4.5.0
|
|
408
|
+
var SDK_VERSION = '4.5.0';
|
|
409
409
|
|
|
410
410
|
const inFlightRequests = new Map();
|
|
411
411
|
class Http {
|
|
@@ -537,11 +537,16 @@ class Http {
|
|
|
537
537
|
reject(new RadarVerifyAppError());
|
|
538
538
|
}
|
|
539
539
|
else {
|
|
540
|
-
reject(new
|
|
540
|
+
reject(new RadarNetworkError());
|
|
541
541
|
}
|
|
542
542
|
};
|
|
543
543
|
xhr.ontimeout = function () {
|
|
544
|
-
|
|
544
|
+
if (host && (host === 'http://localhost:52516' || host === 'https://radar-verify.com:52516')) {
|
|
545
|
+
reject(new RadarVerifyAppError());
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
reject(new RadarNetworkError());
|
|
549
|
+
}
|
|
545
550
|
};
|
|
546
551
|
xhr.send(JSON.stringify(body));
|
|
547
552
|
});
|
|
@@ -741,7 +746,7 @@ class Geocoding {
|
|
|
741
746
|
static forwardGeocode(params) {
|
|
742
747
|
return __awaiter(this, void 0, void 0, function* () {
|
|
743
748
|
const options = Config.get();
|
|
744
|
-
const { query, layers, country } = params;
|
|
749
|
+
const { query, layers, country, lang } = params;
|
|
745
750
|
const response = yield Http.request({
|
|
746
751
|
method: 'GET',
|
|
747
752
|
path: 'geocode/forward',
|
|
@@ -749,6 +754,7 @@ class Geocoding {
|
|
|
749
754
|
query,
|
|
750
755
|
layers,
|
|
751
756
|
country,
|
|
757
|
+
lang,
|
|
752
758
|
},
|
|
753
759
|
});
|
|
754
760
|
const forwardGeocodeRes = {
|
|
@@ -903,7 +909,7 @@ class SearchAPI {
|
|
|
903
909
|
static autocomplete(params, requestId) {
|
|
904
910
|
return __awaiter(this, void 0, void 0, function* () {
|
|
905
911
|
const options = Config.get();
|
|
906
|
-
let { query, near, limit, layers, countryCode, expandUnits, mailable, } = params;
|
|
912
|
+
let { query, near, limit, layers, countryCode, expandUnits, mailable, lang, postalCode, } = params;
|
|
907
913
|
// near can be provided as a string or Location object
|
|
908
914
|
// if "near" is not provided, request will fallback to IP based location
|
|
909
915
|
if (near && typeof near !== 'string') {
|
|
@@ -922,6 +928,8 @@ class SearchAPI {
|
|
|
922
928
|
countryCode,
|
|
923
929
|
expandUnits,
|
|
924
930
|
mailable,
|
|
931
|
+
lang,
|
|
932
|
+
postalCode,
|
|
925
933
|
},
|
|
926
934
|
requestId,
|
|
927
935
|
});
|
|
@@ -1165,51 +1173,6 @@ const signJWT = (payload, key) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
1165
1173
|
return `${encodedHeader}.${encodedPayload}.${signature}`;
|
|
1166
1174
|
});
|
|
1167
1175
|
|
|
1168
|
-
const ping = (host) => {
|
|
1169
|
-
return new Promise((resolve) => {
|
|
1170
|
-
const socket = new WebSocket(host);
|
|
1171
|
-
let pings = 0;
|
|
1172
|
-
const latencies = [];
|
|
1173
|
-
let pingInterval;
|
|
1174
|
-
let timeoutInterval;
|
|
1175
|
-
const ping = () => {
|
|
1176
|
-
pings++;
|
|
1177
|
-
const start = Date.now();
|
|
1178
|
-
socket.send('ping');
|
|
1179
|
-
socket.onmessage = (event) => {
|
|
1180
|
-
if (event.data === 'pong') {
|
|
1181
|
-
const latency = Date.now() - start;
|
|
1182
|
-
latencies.push(latency);
|
|
1183
|
-
if (pings >= 3) {
|
|
1184
|
-
clearInterval(pingInterval);
|
|
1185
|
-
clearInterval(timeoutInterval);
|
|
1186
|
-
const median = latencies.sort((a, b) => a - b)[1];
|
|
1187
|
-
socket.close();
|
|
1188
|
-
resolve(median);
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
};
|
|
1192
|
-
};
|
|
1193
|
-
const timeout = () => {
|
|
1194
|
-
Logger.warn('Socket timeout');
|
|
1195
|
-
clearInterval(pingInterval);
|
|
1196
|
-
clearInterval(timeoutInterval);
|
|
1197
|
-
socket.close();
|
|
1198
|
-
resolve(-1);
|
|
1199
|
-
};
|
|
1200
|
-
socket.onerror = (err) => {
|
|
1201
|
-
Logger.warn('Error opening socket');
|
|
1202
|
-
socket.close();
|
|
1203
|
-
resolve(-1);
|
|
1204
|
-
};
|
|
1205
|
-
socket.onopen = () => {
|
|
1206
|
-
ping();
|
|
1207
|
-
pingInterval = setInterval(ping, 1000);
|
|
1208
|
-
timeoutInterval = setInterval(timeout, 10000);
|
|
1209
|
-
};
|
|
1210
|
-
});
|
|
1211
|
-
};
|
|
1212
|
-
|
|
1213
1176
|
class TrackAPI {
|
|
1214
1177
|
static trackOnce(params) {
|
|
1215
1178
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1273,7 +1236,6 @@ class TrackAPI {
|
|
|
1273
1236
|
let response;
|
|
1274
1237
|
if (fraud) {
|
|
1275
1238
|
const host = 'https://api-verified.radar.io';
|
|
1276
|
-
const pingHost = 'ping.radar-verify.com';
|
|
1277
1239
|
const lang = navigator.language;
|
|
1278
1240
|
const langs = navigator.languages;
|
|
1279
1241
|
const { dk } = yield Http.request({
|
|
@@ -1290,26 +1252,8 @@ class TrackAPI {
|
|
|
1290
1252
|
'X-Radar-Desktop-Device-Type': 'Web',
|
|
1291
1253
|
},
|
|
1292
1254
|
});
|
|
1293
|
-
let sclVal = -1;
|
|
1294
|
-
let cslVal = -1;
|
|
1295
|
-
try {
|
|
1296
|
-
const [sclRes, csl] = yield Promise.all([
|
|
1297
|
-
Http.request({
|
|
1298
|
-
host: `https://${pingHost}`,
|
|
1299
|
-
method: 'GET',
|
|
1300
|
-
path: 'ping',
|
|
1301
|
-
}),
|
|
1302
|
-
ping(`wss://${pingHost}`),
|
|
1303
|
-
]);
|
|
1304
|
-
const { scl } = sclRes;
|
|
1305
|
-
sclVal = scl;
|
|
1306
|
-
cslVal = csl;
|
|
1307
|
-
}
|
|
1308
|
-
catch (err) {
|
|
1309
|
-
// do nothing, send scl = -1 and csl = -1
|
|
1310
|
-
}
|
|
1311
1255
|
const payload = {
|
|
1312
|
-
payload: JSON.stringify(Object.assign(Object.assign({}, body), {
|
|
1256
|
+
payload: JSON.stringify(Object.assign(Object.assign({}, body), { lang,
|
|
1313
1257
|
langs })),
|
|
1314
1258
|
};
|
|
1315
1259
|
const reqToken = yield signJWT(payload, dk);
|
|
@@ -1324,15 +1268,6 @@ class TrackAPI {
|
|
|
1324
1268
|
'X-Radar-Body-Is-Token': 'true',
|
|
1325
1269
|
},
|
|
1326
1270
|
});
|
|
1327
|
-
if (options.debug && response && response.user) {
|
|
1328
|
-
if (!response.user.metadata) {
|
|
1329
|
-
response.user.metadata = {};
|
|
1330
|
-
}
|
|
1331
|
-
response.user.metadata['radar:debug'] = {
|
|
1332
|
-
sclVal,
|
|
1333
|
-
cslVal,
|
|
1334
|
-
};
|
|
1335
|
-
}
|
|
1336
1271
|
let { user, events, token, expiresAt, expiresIn, passed, failureReasons, _id } = response;
|
|
1337
1272
|
const location = { latitude, longitude, accuracy };
|
|
1338
1273
|
if (expiresAt) {
|
|
@@ -1384,10 +1319,11 @@ class VerifyAPI {
|
|
|
1384
1319
|
static trackVerified(params, encrypted = false) {
|
|
1385
1320
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1386
1321
|
const options = Config.get();
|
|
1322
|
+
const { skipVerifyApp } = params;
|
|
1387
1323
|
// user indentification fields
|
|
1388
1324
|
const userId = params.userId || Storage.getItem(Storage.USER_ID);
|
|
1389
|
-
const deviceId =
|
|
1390
|
-
const installId =
|
|
1325
|
+
const deviceId = Device.getDeviceId();
|
|
1326
|
+
const installId = Device.getInstallId();
|
|
1391
1327
|
const sessionId = Session.getSessionId();
|
|
1392
1328
|
const description = params.description || Storage.getItem(Storage.DESCRIPTION);
|
|
1393
1329
|
// save userId
|
|
@@ -1399,46 +1335,57 @@ class VerifyAPI {
|
|
|
1399
1335
|
}
|
|
1400
1336
|
// other info
|
|
1401
1337
|
const metadata = params.metadata || Storage.getJSON(Storage.METADATA);
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
const apple = userAgent && (userAgent.toLowerCase().includes('mac') || userAgent.toLowerCase().includes('iphone') || userAgent.toLowerCase().includes('ipod') || userAgent.toLowerCase().includes('ipad'));
|
|
1411
|
-
const response = yield Http.request({
|
|
1412
|
-
method: 'GET',
|
|
1413
|
-
path: 'verify',
|
|
1414
|
-
data: body,
|
|
1415
|
-
host: apple ? 'https://radar-verify.com:52516' : 'http://localhost:52516',
|
|
1416
|
-
});
|
|
1417
|
-
let { user, events, token, expiresAt, expiresIn, passed, failureReasons, _id } = response;
|
|
1418
|
-
let location;
|
|
1419
|
-
if (user && user.location && user.location.coordinates && user.locationAccuracy) {
|
|
1420
|
-
location = {
|
|
1421
|
-
latitude: user.location.coordinates[1],
|
|
1422
|
-
longitude: user.location.coordinates[0],
|
|
1423
|
-
accuracy: user.locationAccuracy,
|
|
1424
|
-
};
|
|
1425
|
-
}
|
|
1426
|
-
if (expiresAt) {
|
|
1427
|
-
expiresAt = new Date(expiresAt);
|
|
1338
|
+
let trackRes;
|
|
1339
|
+
if (skipVerifyApp) {
|
|
1340
|
+
trackRes = yield TrackAPI.trackOnce({
|
|
1341
|
+
userId: userId !== null && userId !== void 0 ? userId : undefined,
|
|
1342
|
+
description: description !== null && description !== void 0 ? description : undefined,
|
|
1343
|
+
metadata: metadata,
|
|
1344
|
+
fraud: true,
|
|
1345
|
+
});
|
|
1428
1346
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1347
|
+
else {
|
|
1348
|
+
const body = Object.assign(Object.assign({}, params), { description,
|
|
1349
|
+
deviceId, foreground: true, installId,
|
|
1350
|
+
sessionId,
|
|
1351
|
+
metadata, sdkVersion: SDK_VERSION, stopped: true, userId,
|
|
1352
|
+
encrypted,
|
|
1353
|
+
expectedCountryCode,
|
|
1354
|
+
expectedStateCode });
|
|
1355
|
+
let userAgent = navigator.userAgent;
|
|
1356
|
+
const apple = userAgent && (userAgent.toLowerCase().includes('mac') || userAgent.toLowerCase().includes('iphone') || userAgent.toLowerCase().includes('ipod') || userAgent.toLowerCase().includes('ipad'));
|
|
1357
|
+
const response = yield Http.request({
|
|
1358
|
+
method: 'GET',
|
|
1359
|
+
path: 'verify',
|
|
1360
|
+
data: body,
|
|
1361
|
+
host: apple ? 'https://radar-verify.com:52516' : 'http://localhost:52516',
|
|
1362
|
+
});
|
|
1363
|
+
let { user, events, token, expiresAt, expiresIn, passed, failureReasons, _id } = response;
|
|
1364
|
+
let location;
|
|
1365
|
+
if (user && user.location && user.location.coordinates && user.locationAccuracy) {
|
|
1366
|
+
location = {
|
|
1367
|
+
latitude: user.location.coordinates[1],
|
|
1368
|
+
longitude: user.location.coordinates[0],
|
|
1369
|
+
accuracy: user.locationAccuracy,
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
if (expiresAt) {
|
|
1373
|
+
expiresAt = new Date(expiresAt);
|
|
1374
|
+
}
|
|
1375
|
+
trackRes = {
|
|
1376
|
+
user,
|
|
1377
|
+
events,
|
|
1378
|
+
location,
|
|
1379
|
+
token,
|
|
1380
|
+
expiresAt,
|
|
1381
|
+
expiresIn,
|
|
1382
|
+
passed,
|
|
1383
|
+
failureReasons,
|
|
1384
|
+
_id,
|
|
1385
|
+
};
|
|
1386
|
+
if (options.debug) {
|
|
1387
|
+
trackRes.response = response;
|
|
1388
|
+
}
|
|
1442
1389
|
}
|
|
1443
1390
|
lastToken = trackRes;
|
|
1444
1391
|
lastTokenNow = performance.now();
|
|
@@ -1449,49 +1396,65 @@ class VerifyAPI {
|
|
|
1449
1396
|
});
|
|
1450
1397
|
}
|
|
1451
1398
|
static startTrackingVerified(params) {
|
|
1452
|
-
|
|
1453
|
-
const
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
if
|
|
1459
|
-
expiresIn = (trackRes.expiresIn || expiresIn);
|
|
1460
|
-
// if expiresIn is shorter than interval, override interval
|
|
1461
|
-
minInterval = Math.min(expiresIn, interval);
|
|
1462
|
-
}
|
|
1399
|
+
const scheduleNextIntervalWithLastToken = () => __awaiter(this, void 0, void 0, function* () {
|
|
1400
|
+
const { interval } = params;
|
|
1401
|
+
let minInterval = interval;
|
|
1402
|
+
if (lastToken) {
|
|
1403
|
+
const lastTokenElapsed = (performance.now() - lastTokenNow) / 1000;
|
|
1404
|
+
const expiresIn = (lastToken.expiresIn || 0);
|
|
1405
|
+
// if expiresIn is shorter than interval, override interval
|
|
1463
1406
|
// re-request early to maximize the likelihood that a cached token is available
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
});
|
|
1476
|
-
doTrackVerified();
|
|
1407
|
+
minInterval = Math.min(expiresIn - lastTokenElapsed, interval);
|
|
1408
|
+
}
|
|
1409
|
+
minInterval = minInterval - 10;
|
|
1410
|
+
// min interval is 10 seconds
|
|
1411
|
+
if (minInterval < 10) {
|
|
1412
|
+
minInterval = 10;
|
|
1413
|
+
}
|
|
1414
|
+
if (tokenTimeoutId) {
|
|
1415
|
+
clearTimeout(tokenTimeoutId);
|
|
1416
|
+
}
|
|
1417
|
+
tokenTimeoutId = setTimeout(doTrackVerified, minInterval * 1000);
|
|
1477
1418
|
});
|
|
1419
|
+
const doTrackVerified = () => __awaiter(this, void 0, void 0, function* () {
|
|
1420
|
+
try {
|
|
1421
|
+
yield this.trackVerified(params);
|
|
1422
|
+
}
|
|
1423
|
+
catch (err) {
|
|
1424
|
+
Logger.error(`trackVerified error: ${err.message}`);
|
|
1425
|
+
}
|
|
1426
|
+
scheduleNextIntervalWithLastToken();
|
|
1427
|
+
});
|
|
1428
|
+
if (this.isLastTokenValid()) {
|
|
1429
|
+
scheduleNextIntervalWithLastToken();
|
|
1430
|
+
}
|
|
1431
|
+
else {
|
|
1432
|
+
doTrackVerified();
|
|
1433
|
+
}
|
|
1478
1434
|
}
|
|
1479
1435
|
static stopTrackingVerified() {
|
|
1480
1436
|
if (tokenTimeoutId) {
|
|
1481
1437
|
clearTimeout(tokenTimeoutId);
|
|
1482
1438
|
}
|
|
1483
1439
|
}
|
|
1484
|
-
static getVerifiedLocationToken() {
|
|
1440
|
+
static getVerifiedLocationToken(params) {
|
|
1485
1441
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
if (lastTokenElapsed < (lastToken.expiresIn || 0)) {
|
|
1489
|
-
return lastToken;
|
|
1490
|
-
}
|
|
1442
|
+
if (this.isLastTokenValid()) {
|
|
1443
|
+
return lastToken;
|
|
1491
1444
|
}
|
|
1492
|
-
return this.trackVerified(
|
|
1445
|
+
return this.trackVerified(params);
|
|
1493
1446
|
});
|
|
1494
1447
|
}
|
|
1448
|
+
static clearVerifiedLocationToken() {
|
|
1449
|
+
lastToken = null;
|
|
1450
|
+
}
|
|
1451
|
+
static isLastTokenValid() {
|
|
1452
|
+
if (!lastToken) {
|
|
1453
|
+
return false;
|
|
1454
|
+
}
|
|
1455
|
+
const lastTokenElapsed = (performance.now() - lastTokenNow) / 1000;
|
|
1456
|
+
return lastToken.passed && lastTokenElapsed < (lastToken.expiresIn || 0);
|
|
1457
|
+
}
|
|
1495
1458
|
static setExpectedJurisdiction(countryCode, stateCode) {
|
|
1496
1459
|
expectedCountryCode = countryCode || null;
|
|
1497
1460
|
expectedStateCode = stateCode || null;
|
|
@@ -1527,7 +1490,7 @@ let Radar$1 = class Radar {
|
|
|
1527
1490
|
Config.setup(radarOptions);
|
|
1528
1491
|
Logger.info(`initialized with ${live ? 'live' : 'test'} publishableKey.`);
|
|
1529
1492
|
if (options.debug) {
|
|
1530
|
-
Logger.
|
|
1493
|
+
Logger.debug('using options', options);
|
|
1531
1494
|
}
|
|
1532
1495
|
// NOTE(jasonl): this allows us to run jest tests
|
|
1533
1496
|
// without having to mock the ConfigAPI.getConfig call
|
|
@@ -1577,13 +1540,16 @@ let Radar$1 = class Radar {
|
|
|
1577
1540
|
return VerifyAPI.trackVerified(params);
|
|
1578
1541
|
}
|
|
1579
1542
|
static startTrackingVerified(params) {
|
|
1580
|
-
|
|
1543
|
+
VerifyAPI.startTrackingVerified(params);
|
|
1581
1544
|
}
|
|
1582
1545
|
static stopTrackingVerified() {
|
|
1583
|
-
|
|
1546
|
+
VerifyAPI.stopTrackingVerified();
|
|
1584
1547
|
}
|
|
1585
|
-
static getVerifiedLocationToken() {
|
|
1586
|
-
return VerifyAPI.getVerifiedLocationToken();
|
|
1548
|
+
static getVerifiedLocationToken(params = {}) {
|
|
1549
|
+
return VerifyAPI.getVerifiedLocationToken(params);
|
|
1550
|
+
}
|
|
1551
|
+
static clearVerifiedLocationToken() {
|
|
1552
|
+
VerifyAPI.clearVerifiedLocationToken();
|
|
1587
1553
|
}
|
|
1588
1554
|
static setExpectedJurisdiction(countryCode, stateCode) {
|
|
1589
1555
|
VerifyAPI.setExpectedJurisdiction(countryCode, stateCode);
|
|
@@ -1948,6 +1914,7 @@ class RadarLogoControl {
|
|
|
1948
1914
|
this.link.id = 'radar-map-logo';
|
|
1949
1915
|
this.link.href = 'https://radar.com?ref=powered_by_radar';
|
|
1950
1916
|
this.link.target = '_blank';
|
|
1917
|
+
this.link.style.pointerEvents = "auto";
|
|
1951
1918
|
this.link.appendChild(img);
|
|
1952
1919
|
return this.link;
|
|
1953
1920
|
}
|
|
@@ -2056,7 +2023,7 @@ class RadarMap extends maplibregl.Map {
|
|
|
2056
2023
|
// configure map options
|
|
2057
2024
|
const style = getStyle(config, radarMapOptions);
|
|
2058
2025
|
const mapOptions = Object.assign({}, defaultRadarMapOptions, defaultMaplibreOptions, radarMapOptions, { style });
|
|
2059
|
-
Logger.debug(
|
|
2026
|
+
Logger.debug('map initialized with options', mapOptions);
|
|
2060
2027
|
mapOptions.transformRequest = (url, resourceType) => {
|
|
2061
2028
|
// this handles when a style is switched
|
|
2062
2029
|
if (resourceType === 'Style' && isRadarStyle(url)) {
|
|
@@ -2106,14 +2073,6 @@ class RadarMap extends maplibregl.Map {
|
|
|
2106
2073
|
};
|
|
2107
2074
|
this.on('resize', onResize);
|
|
2108
2075
|
this.on('load', onResize);
|
|
2109
|
-
// parse radar metadata from style
|
|
2110
|
-
this.on('style.load', () => {
|
|
2111
|
-
const style = this.getStyle();
|
|
2112
|
-
const metadata = style.metadata || {};
|
|
2113
|
-
if (metadata['radar:marker']) { // default marker associated with custom style
|
|
2114
|
-
this._defaultMarker = metadata['radar:marker'];
|
|
2115
|
-
}
|
|
2116
|
-
});
|
|
2117
2076
|
}
|
|
2118
2077
|
addMarker(marker) {
|
|
2119
2078
|
this._markers.push(marker);
|
|
@@ -2207,7 +2166,7 @@ const useCachedImage = (url, timeoutMS = 5000) => new Promise((resolve, reject)
|
|
|
2207
2166
|
clearInterval(interval);
|
|
2208
2167
|
reject('failed');
|
|
2209
2168
|
}
|
|
2210
|
-
else { // return data
|
|
2169
|
+
else if (cachedData !== undefined) { // return data
|
|
2211
2170
|
clearInterval(interval);
|
|
2212
2171
|
resolve(cachedData);
|
|
2213
2172
|
}
|
|
@@ -2257,10 +2216,79 @@ class RadarMarker extends maplibregl.Marker {
|
|
|
2257
2216
|
maplibreOptions.scale = markerOptions.scale;
|
|
2258
2217
|
}
|
|
2259
2218
|
super(maplibreOptions);
|
|
2260
|
-
this._options = markerOptions;
|
|
2261
2219
|
// handle marker images (Radar marker, or custom URL)
|
|
2262
2220
|
if (markerOptions.marker || markerOptions.url) {
|
|
2263
|
-
this.
|
|
2221
|
+
const originalElement = this._element.cloneNode(true);
|
|
2222
|
+
this._element.childNodes.forEach((child) => {
|
|
2223
|
+
child.remove();
|
|
2224
|
+
});
|
|
2225
|
+
const onSuccess = (url) => {
|
|
2226
|
+
this._element.replaceChildren(createImageElement({
|
|
2227
|
+
width: markerOptions.width,
|
|
2228
|
+
height: markerOptions.height,
|
|
2229
|
+
url,
|
|
2230
|
+
}));
|
|
2231
|
+
};
|
|
2232
|
+
const onError = (err) => {
|
|
2233
|
+
Logger.error(`Could not load marker: ${err.message} - falling back to default marker`);
|
|
2234
|
+
IMAGE_CACHE.set(markerOptions.url, 'failed'); // mark as failed
|
|
2235
|
+
this._element.replaceChildren(...Array.from(originalElement.childNodes));
|
|
2236
|
+
};
|
|
2237
|
+
// custom URL image
|
|
2238
|
+
if (markerOptions.url) {
|
|
2239
|
+
const loadImage = () => {
|
|
2240
|
+
fetch(markerOptions.url)
|
|
2241
|
+
.then(res => {
|
|
2242
|
+
if (res.status === 200) {
|
|
2243
|
+
res.blob()
|
|
2244
|
+
.then((data) => {
|
|
2245
|
+
const url = URL.createObjectURL(data);
|
|
2246
|
+
IMAGE_CACHE.set(markerOptions.url, url); // cache data
|
|
2247
|
+
onSuccess(url);
|
|
2248
|
+
})
|
|
2249
|
+
.catch(onError);
|
|
2250
|
+
}
|
|
2251
|
+
else {
|
|
2252
|
+
onError(new Error(res.statusText));
|
|
2253
|
+
}
|
|
2254
|
+
})
|
|
2255
|
+
.catch(onError);
|
|
2256
|
+
};
|
|
2257
|
+
// attempt to use cached data, otherwise fetch marker image data from URL
|
|
2258
|
+
useCachedImage(markerOptions.url)
|
|
2259
|
+
.then(onSuccess)
|
|
2260
|
+
.catch((reason) => {
|
|
2261
|
+
if (reason !== 'miss') {
|
|
2262
|
+
Logger.debug(`RadarMarker: cache lookup for ${markerOptions.url}: ${reason}`);
|
|
2263
|
+
}
|
|
2264
|
+
loadImage();
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
// Radar hosted image
|
|
2268
|
+
if (markerOptions.marker) {
|
|
2269
|
+
const loadMarker = () => {
|
|
2270
|
+
Http.request({
|
|
2271
|
+
method: 'GET',
|
|
2272
|
+
version: 'maps',
|
|
2273
|
+
path: `markers/${markerOptions.marker}`,
|
|
2274
|
+
responseType: 'blob',
|
|
2275
|
+
})
|
|
2276
|
+
.then(({ data }) => {
|
|
2277
|
+
const url = URL.createObjectURL(data);
|
|
2278
|
+
IMAGE_CACHE.set(markerOptions.marker, url); // cache data
|
|
2279
|
+
onSuccess(url);
|
|
2280
|
+
})
|
|
2281
|
+
.catch(onError);
|
|
2282
|
+
};
|
|
2283
|
+
useCachedImage(markerOptions.marker)
|
|
2284
|
+
.then(onSuccess)
|
|
2285
|
+
.catch((reason) => {
|
|
2286
|
+
if (reason !== 'miss') {
|
|
2287
|
+
Logger.debug(`RadarMarker: cache lookup for ${markerOptions.marker} ${reason}`);
|
|
2288
|
+
}
|
|
2289
|
+
loadMarker();
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2264
2292
|
}
|
|
2265
2293
|
// handle deprecated popup options
|
|
2266
2294
|
if (markerOptions.text) {
|
|
@@ -2297,7 +2325,8 @@ class RadarMarker extends maplibregl.Marker {
|
|
|
2297
2325
|
if (this.getPopup()) {
|
|
2298
2326
|
// close any other open popups
|
|
2299
2327
|
(this._map.getMarkers() || []).forEach((otherMarker) => {
|
|
2300
|
-
|
|
2328
|
+
var _a;
|
|
2329
|
+
if ((_a = otherMarker.getPopup()) === null || _a === void 0 ? void 0 : _a.isOpen()) {
|
|
2301
2330
|
otherMarker.togglePopup();
|
|
2302
2331
|
}
|
|
2303
2332
|
});
|
|
@@ -2307,88 +2336,7 @@ class RadarMarker extends maplibregl.Marker {
|
|
|
2307
2336
|
});
|
|
2308
2337
|
}
|
|
2309
2338
|
}
|
|
2310
|
-
// load marker image from a URL or as a Radar asset (custom styles)
|
|
2311
|
-
getCustomImage(markerOptions) {
|
|
2312
|
-
const originalElement = this._element.cloneNode(true);
|
|
2313
|
-
this._element.childNodes.forEach((child) => {
|
|
2314
|
-
child.remove();
|
|
2315
|
-
});
|
|
2316
|
-
const onSuccess = (blob) => {
|
|
2317
|
-
const markerObject = URL.createObjectURL(blob);
|
|
2318
|
-
this._element.replaceChildren(createImageElement({
|
|
2319
|
-
width: markerOptions.width,
|
|
2320
|
-
height: markerOptions.height,
|
|
2321
|
-
url: markerObject,
|
|
2322
|
-
}));
|
|
2323
|
-
};
|
|
2324
|
-
const onError = (err) => {
|
|
2325
|
-
Logger.error(`Could not load marker: ${err.message} - falling back to default marker`);
|
|
2326
|
-
IMAGE_CACHE.set(markerOptions.url, 'failed'); // mark as failed
|
|
2327
|
-
this._element.replaceChildren(...Array.from(originalElement.childNodes));
|
|
2328
|
-
};
|
|
2329
|
-
// custom URL image
|
|
2330
|
-
if (markerOptions.url) {
|
|
2331
|
-
const loadImage = () => {
|
|
2332
|
-
fetch(markerOptions.url)
|
|
2333
|
-
.then(res => {
|
|
2334
|
-
if (res.status === 200) {
|
|
2335
|
-
res.blob()
|
|
2336
|
-
.then((data) => {
|
|
2337
|
-
IMAGE_CACHE.set(markerOptions.url, data); // cache data
|
|
2338
|
-
onSuccess(data);
|
|
2339
|
-
})
|
|
2340
|
-
.catch(onError);
|
|
2341
|
-
}
|
|
2342
|
-
else {
|
|
2343
|
-
onError(new Error(res.statusText));
|
|
2344
|
-
}
|
|
2345
|
-
})
|
|
2346
|
-
.catch(onError);
|
|
2347
|
-
};
|
|
2348
|
-
// attempt to use cached data, otherwise fetch marker image data from URL
|
|
2349
|
-
useCachedImage(markerOptions.url)
|
|
2350
|
-
.then(onSuccess)
|
|
2351
|
-
.catch((reason) => {
|
|
2352
|
-
if (reason !== 'miss') {
|
|
2353
|
-
Logger.debug(`RadarMarker: cache lookup for ${markerOptions.url}: ${reason}`);
|
|
2354
|
-
}
|
|
2355
|
-
loadImage();
|
|
2356
|
-
});
|
|
2357
|
-
}
|
|
2358
|
-
// Radar hosted image
|
|
2359
|
-
if (markerOptions.marker) {
|
|
2360
|
-
const loadMarker = () => {
|
|
2361
|
-
Http.request({
|
|
2362
|
-
method: 'GET',
|
|
2363
|
-
version: 'maps',
|
|
2364
|
-
path: `markers/${markerOptions.marker}`,
|
|
2365
|
-
responseType: 'blob',
|
|
2366
|
-
})
|
|
2367
|
-
.then(({ data }) => {
|
|
2368
|
-
IMAGE_CACHE.set(markerOptions.url, data); // cache data
|
|
2369
|
-
onSuccess(data);
|
|
2370
|
-
})
|
|
2371
|
-
.catch(onError);
|
|
2372
|
-
};
|
|
2373
|
-
useCachedImage(markerOptions.marker)
|
|
2374
|
-
.then(onSuccess)
|
|
2375
|
-
.catch((reason) => {
|
|
2376
|
-
if (reason !== 'miss') {
|
|
2377
|
-
Logger.debug(`RadarMarker: cache lookup for ${markerOptions.marker} ${reason}`);
|
|
2378
|
-
}
|
|
2379
|
-
loadMarker();
|
|
2380
|
-
});
|
|
2381
|
-
}
|
|
2382
|
-
}
|
|
2383
2339
|
addTo(map) {
|
|
2384
|
-
// use default marker associated with map style, if none is provided in options
|
|
2385
|
-
// (and custom style has an associated marker)
|
|
2386
|
-
const markerOptions = this._options;
|
|
2387
|
-
if (!markerOptions.url && !markerOptions.marker && !markerOptions.color) {
|
|
2388
|
-
if (map._defaultMarker) {
|
|
2389
|
-
this.getCustomImage(Object.assign(Object.assign({}, markerOptions), { marker: map._defaultMarker }));
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
2340
|
map.addMarker(this);
|
|
2393
2341
|
return super.addTo(map);
|
|
2394
2342
|
}
|
|
@@ -2579,7 +2527,7 @@ class AutocompleteUI {
|
|
|
2579
2527
|
if (this.config.hideResultsOnBlur) {
|
|
2580
2528
|
this.inputField.addEventListener('blur', this.close.bind(this), true);
|
|
2581
2529
|
}
|
|
2582
|
-
Logger.debug(
|
|
2530
|
+
Logger.debug('AutocompleteUI initialized with options', this.config);
|
|
2583
2531
|
}
|
|
2584
2532
|
handleInput() {
|
|
2585
2533
|
// Fetch autocomplete results and display them
|
|
@@ -2633,7 +2581,7 @@ class AutocompleteUI {
|
|
|
2633
2581
|
}
|
|
2634
2582
|
fetchResults(query) {
|
|
2635
2583
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2636
|
-
const { limit, layers, countryCode, expandUnits, mailable, onRequest } = this.config;
|
|
2584
|
+
const { limit, layers, countryCode, expandUnits, mailable, lang, postalCode, onRequest } = this.config;
|
|
2637
2585
|
const params = {
|
|
2638
2586
|
query,
|
|
2639
2587
|
limit,
|
|
@@ -2641,6 +2589,8 @@ class AutocompleteUI {
|
|
|
2641
2589
|
countryCode,
|
|
2642
2590
|
expandUnits,
|
|
2643
2591
|
mailable,
|
|
2592
|
+
lang,
|
|
2593
|
+
postalCode,
|
|
2644
2594
|
};
|
|
2645
2595
|
if (this.near) {
|
|
2646
2596
|
params.near = this.near;
|
|
@@ -2855,12 +2805,22 @@ class AutocompleteUI {
|
|
|
2855
2805
|
return this;
|
|
2856
2806
|
}
|
|
2857
2807
|
setWidth(width) {
|
|
2858
|
-
|
|
2808
|
+
if (width === null) {
|
|
2809
|
+
this.config.width = undefined;
|
|
2810
|
+
}
|
|
2811
|
+
else if (typeof width === 'string' || typeof width === 'number') {
|
|
2812
|
+
this.config.width = width;
|
|
2813
|
+
}
|
|
2859
2814
|
setWidth(this.wrapper, this.config);
|
|
2860
2815
|
return this;
|
|
2861
2816
|
}
|
|
2862
2817
|
setMaxHeight(height) {
|
|
2863
|
-
|
|
2818
|
+
if (height === null) {
|
|
2819
|
+
this.config.maxHeight = undefined;
|
|
2820
|
+
}
|
|
2821
|
+
else if (typeof height === 'string' || typeof height === 'number') {
|
|
2822
|
+
this.config.maxHeight = height;
|
|
2823
|
+
}
|
|
2864
2824
|
setHeight(this.resultsList, this.config);
|
|
2865
2825
|
return this;
|
|
2866
2826
|
}
|
|
@@ -2873,6 +2833,24 @@ class AutocompleteUI {
|
|
|
2873
2833
|
this.config.limit = limit;
|
|
2874
2834
|
return this;
|
|
2875
2835
|
}
|
|
2836
|
+
setLang(lang) {
|
|
2837
|
+
if (lang === null) {
|
|
2838
|
+
this.config.lang = undefined;
|
|
2839
|
+
}
|
|
2840
|
+
else if (typeof lang === 'string') {
|
|
2841
|
+
this.config.lang = lang;
|
|
2842
|
+
}
|
|
2843
|
+
return this;
|
|
2844
|
+
}
|
|
2845
|
+
setPostalCode(postalCode) {
|
|
2846
|
+
if (postalCode === null) {
|
|
2847
|
+
this.config.postalCode = undefined;
|
|
2848
|
+
}
|
|
2849
|
+
else if (typeof postalCode === 'string') {
|
|
2850
|
+
this.config.postalCode = postalCode;
|
|
2851
|
+
}
|
|
2852
|
+
return this;
|
|
2853
|
+
}
|
|
2876
2854
|
setShowMarkers(showMarkers) {
|
|
2877
2855
|
this.config.showMarkers = showMarkers;
|
|
2878
2856
|
if (showMarkers) {
|