radar-sdk-js 4.2.1-beta.0 → 4.2.1-beta.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.
- package/README.md +7 -7
- package/dist/api/verify.d.ts +2 -2
- package/dist/errors.d.ts +3 -3
- package/dist/http.d.ts +2 -1
- package/dist/index.d.ts +1 -2
- package/dist/radar.js +251 -74
- package/dist/radar.js.map +1 -1
- package/dist/types.d.ts +11 -3
- package/dist/util/jwt.d.ts +1 -0
- package/dist/util/net.d.ts +1 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/api/search.ts +4 -0
- package/src/api/track.ts +116 -4
- package/src/api/verify.ts +15 -16
- package/src/errors.ts +9 -9
- package/src/http.ts +20 -10
- package/src/index.ts +0 -4
- package/src/navigator.ts +6 -11
- package/src/types.ts +11 -5
- package/src/ui/autocomplete.ts +2 -1
- package/src/util/jwt.ts +28 -0
- package/src/util/net.ts +54 -0
- package/src/version.ts +1 -1
package/dist/radar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radar.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"radar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/types.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export interface RadarTrackParams {
|
|
|
52
52
|
metadata?: RadarMetadata;
|
|
53
53
|
tripOptions?: RadarTripOptions;
|
|
54
54
|
desiredAccuracy?: 'high' | 'medium' | 'low';
|
|
55
|
+
fraud?: boolean;
|
|
55
56
|
}
|
|
56
57
|
export declare enum RadarEventConfidence {
|
|
57
58
|
none = 0,
|
|
@@ -59,7 +60,7 @@ export declare enum RadarEventConfidence {
|
|
|
59
60
|
medium = 2,
|
|
60
61
|
high = 3
|
|
61
62
|
}
|
|
62
|
-
export type RadarEventType = 'unknown' | 'user.entered_geofence' | 'user.entered_home' | 'user.entered_office' | 'user.entered_place' | 'user.entered_region_country' | 'user.entered_region_dma' | 'user.entered_region_state' | 'user.exited_geofence' | 'user.exited_home' | 'user.exited_office' | 'user.exited_place' | 'user.exited_region_country' | 'user.exited_region_dma' | 'user.exited_region_state' | 'user.nearby_place_chain' | 'user.started_traveling' | 'user.stopped_traveling' | 'user.started_commuting' | 'user.stopped_commuting' | 'user.started_trip' | 'user.updated_trip' | 'user.approaching_trip_destination' | 'user.arrived_at_trip_destination' | 'user.stopped_trip';
|
|
63
|
+
export type RadarEventType = 'unknown' | 'user.entered_geofence' | 'user.entered_home' | 'user.entered_office' | 'user.entered_place' | 'user.entered_region_country' | 'user.entered_region_dma' | 'user.entered_region_state' | 'user.exited_geofence' | 'user.exited_home' | 'user.exited_office' | 'user.exited_place' | 'user.exited_region_country' | 'user.exited_region_dma' | 'user.exited_region_state' | 'user.nearby_place_chain' | 'user.started_traveling' | 'user.stopped_traveling' | 'user.started_commuting' | 'user.stopped_commuting' | 'user.started_trip' | 'user.updated_trip' | 'user.approaching_trip_destination' | 'user.arrived_at_trip_destination' | 'user.stopped_trip' | 'user.failed_fraud';
|
|
63
64
|
export interface RadarGeofence {
|
|
64
65
|
_id: string;
|
|
65
66
|
description: string;
|
|
@@ -142,8 +143,11 @@ export interface RadarTrackResponse extends RadarResponse {
|
|
|
142
143
|
user?: RadarUser;
|
|
143
144
|
events?: RadarEvent[];
|
|
144
145
|
}
|
|
145
|
-
export interface
|
|
146
|
+
export interface RadarTrackVerifiedResponse extends RadarTrackResponse {
|
|
146
147
|
token?: String;
|
|
148
|
+
expiresAt?: Date;
|
|
149
|
+
expiresIn?: number;
|
|
150
|
+
passed?: boolean;
|
|
147
151
|
}
|
|
148
152
|
export interface RadarContextResponse extends RadarResponse {
|
|
149
153
|
location?: Location;
|
|
@@ -179,7 +183,7 @@ export interface RadarCustomEvent {
|
|
|
179
183
|
export interface RadarConversionResponse extends RadarResponse {
|
|
180
184
|
event: RadarCustomEvent;
|
|
181
185
|
}
|
|
182
|
-
export type RadarGeocodeLayer = 'place' | 'address' | '
|
|
186
|
+
export type RadarGeocodeLayer = 'place' | 'address' | 'postalCode' | 'locality' | 'county' | 'state' | 'country' | 'coarse' | 'fine';
|
|
183
187
|
export interface RadarAddress {
|
|
184
188
|
addressLabel?: string;
|
|
185
189
|
borough?: string;
|
|
@@ -243,7 +247,9 @@ export interface RadarAutocompleteParams {
|
|
|
243
247
|
limit?: number;
|
|
244
248
|
layers?: RadarGeocodeLayer[];
|
|
245
249
|
countryCode?: string;
|
|
250
|
+
/** @deprecated this is always true, regardless of the value passed here */
|
|
246
251
|
expandUnits?: boolean;
|
|
252
|
+
mailable?: boolean;
|
|
247
253
|
}
|
|
248
254
|
export interface RadarAutocompleteResponse extends RadarResponse {
|
|
249
255
|
addresses: RadarAutocompleteAddress[];
|
|
@@ -333,6 +339,7 @@ export interface RadarSearchGeofencesParams {
|
|
|
333
339
|
tags?: string[] | string;
|
|
334
340
|
metadata?: RadarMetadata;
|
|
335
341
|
limit?: number;
|
|
342
|
+
includeGeometry?: boolean;
|
|
336
343
|
}
|
|
337
344
|
export interface RadarSearchGeofencesResponse extends RadarResponse {
|
|
338
345
|
geofences: RadarGeofence[];
|
|
@@ -357,6 +364,7 @@ export interface RadarAutocompleteUIOptions {
|
|
|
357
364
|
layers?: RadarGeocodeLayer[];
|
|
358
365
|
countryCode?: string;
|
|
359
366
|
expandUnits?: boolean;
|
|
367
|
+
mailable?: boolean;
|
|
360
368
|
placeholder?: string;
|
|
361
369
|
onSelection?: (selection: any) => void;
|
|
362
370
|
onRequest?: (params: RadarAutocompleteParams) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const signJWT: (payload: object, key: string) => Promise<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ping: (host: string) => Promise<any>;
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "4.2.1-beta.
|
|
1
|
+
declare const _default: "4.2.1-beta.2";
|
|
2
2
|
export default _default;
|
package/package.json
CHANGED
package/src/api/search.ts
CHANGED
|
@@ -22,6 +22,7 @@ class SearchAPI {
|
|
|
22
22
|
layers,
|
|
23
23
|
countryCode,
|
|
24
24
|
expandUnits,
|
|
25
|
+
mailable,
|
|
25
26
|
} = params;
|
|
26
27
|
|
|
27
28
|
// near can be provided as a string or Location object
|
|
@@ -42,6 +43,7 @@ class SearchAPI {
|
|
|
42
43
|
layers,
|
|
43
44
|
countryCode,
|
|
44
45
|
expandUnits,
|
|
46
|
+
mailable,
|
|
45
47
|
},
|
|
46
48
|
});
|
|
47
49
|
|
|
@@ -65,6 +67,7 @@ class SearchAPI {
|
|
|
65
67
|
tags,
|
|
66
68
|
metadata,
|
|
67
69
|
limit,
|
|
70
|
+
includeGeometry,
|
|
68
71
|
} = params;
|
|
69
72
|
|
|
70
73
|
// use browser location if "near" not provided
|
|
@@ -90,6 +93,7 @@ class SearchAPI {
|
|
|
90
93
|
tags,
|
|
91
94
|
metadata,
|
|
92
95
|
limit,
|
|
96
|
+
includeGeometry,
|
|
93
97
|
},
|
|
94
98
|
});
|
|
95
99
|
|
package/src/api/track.ts
CHANGED
|
@@ -6,16 +6,17 @@ import Logger from '../logger';
|
|
|
6
6
|
import Navigator from '../navigator';
|
|
7
7
|
import Session from '../session';
|
|
8
8
|
import Storage from '../storage';
|
|
9
|
-
|
|
10
9
|
import TripsAPI from './trips';
|
|
10
|
+
import { signJWT } from '../util/jwt';
|
|
11
|
+
import { ping } from '../util/net';
|
|
11
12
|
|
|
12
|
-
import type { RadarTrackParams, RadarTrackResponse } from '../types';
|
|
13
|
+
import type { RadarTrackParams, RadarTrackResponse, RadarTrackVerifiedResponse } from '../types';
|
|
13
14
|
|
|
14
15
|
class TrackAPI {
|
|
15
16
|
static async trackOnce(params: RadarTrackParams) {
|
|
16
17
|
const options = Config.get();
|
|
17
18
|
|
|
18
|
-
let { latitude, longitude, accuracy, desiredAccuracy } = params;
|
|
19
|
+
let { latitude, longitude, accuracy, desiredAccuracy, fraud } = params;
|
|
19
20
|
|
|
20
21
|
// if latitude & longitude are not provided,
|
|
21
22
|
// try and retrieve device location (will prompt for location permissions)
|
|
@@ -42,6 +43,13 @@ class TrackAPI {
|
|
|
42
43
|
const deviceType = params.deviceType || 'Web';
|
|
43
44
|
const description = params.description || Storage.getItem(Storage.DESCRIPTION);
|
|
44
45
|
|
|
46
|
+
let timeZone;
|
|
47
|
+
try {
|
|
48
|
+
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
49
|
+
} catch (err: any) {
|
|
50
|
+
Logger.warn(`Error getting time zone: ${err.message}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
45
53
|
// save userId for trip tracking
|
|
46
54
|
if (!userId) {
|
|
47
55
|
Logger.warn('userId not provided for trackOnce.');
|
|
@@ -75,9 +83,113 @@ class TrackAPI {
|
|
|
75
83
|
stopped: true,
|
|
76
84
|
userId,
|
|
77
85
|
tripOptions,
|
|
86
|
+
timeZone,
|
|
78
87
|
};
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
let response: any;
|
|
90
|
+
if (fraud) {
|
|
91
|
+
const host = 'https://api-verified.radar.io';
|
|
92
|
+
const pingHost = 'ping.radar-verify.com';
|
|
93
|
+
|
|
94
|
+
const lang = navigator.language;
|
|
95
|
+
const langs = navigator.languages;
|
|
96
|
+
|
|
97
|
+
const { dk }: any = await Http.request({
|
|
98
|
+
host,
|
|
99
|
+
method: 'GET',
|
|
100
|
+
path: 'config',
|
|
101
|
+
data: {
|
|
102
|
+
deviceId,
|
|
103
|
+
installId,
|
|
104
|
+
sessionId,
|
|
105
|
+
locationAuthorization,
|
|
106
|
+
},
|
|
107
|
+
headers: {
|
|
108
|
+
'X-Radar-Desktop-Device-Type': 'Web',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
let sclVal = -1;
|
|
113
|
+
let cslVal = -1;
|
|
114
|
+
try {
|
|
115
|
+
const [sclRes, csl] = await Promise.all([
|
|
116
|
+
Http.request({
|
|
117
|
+
host: `https://${pingHost}`,
|
|
118
|
+
method: 'GET',
|
|
119
|
+
path: 'ping',
|
|
120
|
+
}),
|
|
121
|
+
ping(`wss://${pingHost}`),
|
|
122
|
+
]);
|
|
123
|
+
const { scl }: any = sclRes;
|
|
124
|
+
sclVal = scl;
|
|
125
|
+
cslVal = csl;
|
|
126
|
+
} catch (err) {
|
|
127
|
+
// do nothing, send scl = -1 and csl = -1
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const payload = {
|
|
131
|
+
payload: JSON.stringify({
|
|
132
|
+
...body,
|
|
133
|
+
scl: sclVal,
|
|
134
|
+
csl: cslVal,
|
|
135
|
+
lang,
|
|
136
|
+
langs,
|
|
137
|
+
}),
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const reqToken = await signJWT(payload, dk);
|
|
141
|
+
|
|
142
|
+
response = await Http.request({
|
|
143
|
+
host,
|
|
144
|
+
method: 'POST',
|
|
145
|
+
path: 'track',
|
|
146
|
+
data: {
|
|
147
|
+
token: reqToken,
|
|
148
|
+
},
|
|
149
|
+
headers: {
|
|
150
|
+
'X-Radar-Body-Is-Token': 'true',
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (options.debug && response && response.user) {
|
|
155
|
+
if (!response.user.metadata) {
|
|
156
|
+
response.user.metadata = {};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
response.user.metadata['radar:debug'] = {
|
|
160
|
+
sclVal,
|
|
161
|
+
cslVal,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
let { user, events, token, expiresAt } = response;
|
|
166
|
+
const location = { latitude, longitude, accuracy };
|
|
167
|
+
let passed;
|
|
168
|
+
let expiresIn;
|
|
169
|
+
if (expiresAt) {
|
|
170
|
+
expiresAt = new Date(expiresAt);
|
|
171
|
+
passed = user?.fraud?.passed && user?.country?.passed && user?.state?.passed;
|
|
172
|
+
expiresIn = (expiresAt.getTime() - Date.now()) / 1000;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const trackRes = {
|
|
176
|
+
user,
|
|
177
|
+
events,
|
|
178
|
+
location,
|
|
179
|
+
token,
|
|
180
|
+
expiresAt,
|
|
181
|
+
expiresIn,
|
|
182
|
+
passed,
|
|
183
|
+
} as RadarTrackVerifiedResponse;
|
|
184
|
+
|
|
185
|
+
if (options.debug) {
|
|
186
|
+
trackRes.response = response;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return trackRes;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
response = await Http.request({
|
|
81
193
|
method: 'POST',
|
|
82
194
|
path: 'track',
|
|
83
195
|
data: body,
|
package/src/api/verify.ts
CHANGED
|
@@ -6,7 +6,7 @@ import Logger from '../logger';
|
|
|
6
6
|
import Session from '../session';
|
|
7
7
|
import Storage from '../storage';
|
|
8
8
|
|
|
9
|
-
import type { RadarTrackParams,
|
|
9
|
+
import type { RadarTrackParams, RadarTrackVerifiedResponse } from '../types';
|
|
10
10
|
|
|
11
11
|
class VerifyAPI {
|
|
12
12
|
static async trackVerified(params: RadarTrackParams, encrypted: Boolean = false) {
|
|
@@ -44,16 +44,16 @@ class VerifyAPI {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
let userAgent = navigator.userAgent;
|
|
47
|
-
const
|
|
47
|
+
const apple = userAgent && (userAgent.toLowerCase().includes('mac') || userAgent.toLowerCase().includes('iphone') || userAgent.toLowerCase().includes('ipod') || userAgent.toLowerCase().includes('ipad'));
|
|
48
48
|
|
|
49
49
|
const response: any = await Http.request({
|
|
50
50
|
method: 'GET',
|
|
51
51
|
path: 'verify',
|
|
52
52
|
data: body,
|
|
53
|
-
host:
|
|
53
|
+
host: apple ? 'https://radar-verify.com:52516' : 'http://localhost:52516',
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
let { user, events, token, expiresAt } = response;
|
|
57
57
|
let location;
|
|
58
58
|
if (user && user.location && user.location.coordinates && user.locationAccuracy) {
|
|
59
59
|
location = {
|
|
@@ -62,24 +62,23 @@ class VerifyAPI {
|
|
|
62
62
|
accuracy: user.locationAccuracy,
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (options.debug) {
|
|
72
|
-
trackTokenRes.response = response;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return trackTokenRes;
|
|
65
|
+
let passed;
|
|
66
|
+
let expiresIn;
|
|
67
|
+
if (expiresAt) {
|
|
68
|
+
expiresAt = new Date(expiresAt);
|
|
69
|
+
passed = user?.fraud?.passed && user?.country?.passed && user?.state?.passed;
|
|
70
|
+
expiresIn = (expiresAt.getTime() - Date.now()) / 1000;
|
|
76
71
|
}
|
|
77
72
|
|
|
78
73
|
const trackRes = {
|
|
79
74
|
user,
|
|
80
75
|
events,
|
|
81
76
|
location,
|
|
82
|
-
|
|
77
|
+
token,
|
|
78
|
+
expiresAt,
|
|
79
|
+
expiresIn,
|
|
80
|
+
passed,
|
|
81
|
+
} as RadarTrackVerifiedResponse;
|
|
83
82
|
|
|
84
83
|
if (options.debug) {
|
|
85
84
|
trackRes.response = response;
|
package/src/errors.ts
CHANGED
|
@@ -23,19 +23,19 @@ export class RadarLocationError extends RadarError {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export class
|
|
26
|
+
export class RadarPermissionsError extends RadarError {
|
|
27
27
|
constructor(message: string) {
|
|
28
28
|
super(message);
|
|
29
|
-
this.name = '
|
|
29
|
+
this.name = 'RadarPermissionsError';
|
|
30
30
|
this.status = 'ERROR_PERMISSIONS';
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export class
|
|
34
|
+
export class RadarVerifyAppError extends RadarError {
|
|
35
35
|
constructor() {
|
|
36
|
-
super('
|
|
37
|
-
this.name = '
|
|
38
|
-
this.status = '
|
|
36
|
+
super('Radar Verify app not running.');
|
|
37
|
+
this.name = 'RadarVerifyAppError';
|
|
38
|
+
this.status = 'ERROR_VERIFY_APP';
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -131,11 +131,11 @@ export class RadarServerError extends RadarError {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
export class
|
|
134
|
+
export class RadarNetworkError extends RadarError {
|
|
135
135
|
constructor() {
|
|
136
136
|
super('Request timed out.');
|
|
137
|
-
this.name = '
|
|
138
|
-
this.status = '
|
|
137
|
+
this.name = 'RadarNetworkError';
|
|
138
|
+
this.status = 'ERROR_NETWORK';
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
package/src/http.ts
CHANGED
|
@@ -4,18 +4,18 @@ import Logger from './logger';
|
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
RadarBadRequestError,
|
|
7
|
-
RadarDesktopAppError,
|
|
8
7
|
RadarForbiddenError,
|
|
9
8
|
RadarLocationError,
|
|
10
|
-
|
|
9
|
+
RadarNetworkError,
|
|
11
10
|
RadarNotFoundError,
|
|
12
11
|
RadarPaymentRequiredError,
|
|
12
|
+
RadarPermissionsError,
|
|
13
13
|
RadarPublishableKeyError,
|
|
14
14
|
RadarRateLimitError,
|
|
15
15
|
RadarServerError,
|
|
16
|
-
RadarTimeoutError,
|
|
17
16
|
RadarUnauthorizedError,
|
|
18
17
|
RadarUnknownError,
|
|
18
|
+
RadarVerifyAppError,
|
|
19
19
|
} from './errors';
|
|
20
20
|
|
|
21
21
|
export type HttpMethod = 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE';
|
|
@@ -31,11 +31,13 @@ class Http {
|
|
|
31
31
|
path,
|
|
32
32
|
data,
|
|
33
33
|
host,
|
|
34
|
+
headers,
|
|
34
35
|
}: {
|
|
35
36
|
method: HttpMethod;
|
|
36
37
|
path: string;
|
|
37
38
|
data?: any;
|
|
38
39
|
host?: string;
|
|
40
|
+
headers?: Record<string, string>;
|
|
39
41
|
}) {
|
|
40
42
|
return new Promise<HttpResponse>((resolve, reject) => {
|
|
41
43
|
const options = Config.get();
|
|
@@ -76,13 +78,21 @@ class Http {
|
|
|
76
78
|
const xhr = new XMLHttpRequest();
|
|
77
79
|
xhr.open(method, url, true);
|
|
78
80
|
|
|
79
|
-
// set headers
|
|
81
|
+
// set standard headers
|
|
80
82
|
xhr.setRequestHeader('Authorization', publishableKey);
|
|
81
83
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
82
84
|
xhr.setRequestHeader('X-Radar-Device-Type', 'Web');
|
|
83
85
|
xhr.setRequestHeader('X-Radar-SDK-Version', SDK_VERSION);
|
|
84
86
|
|
|
85
|
-
// set custom headers if present
|
|
87
|
+
// set passed custom headers if present
|
|
88
|
+
if (headers) {
|
|
89
|
+
Object.keys(headers).forEach(key => {
|
|
90
|
+
const val = headers[key];
|
|
91
|
+
xhr.setRequestHeader(key, val);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// set config custom headers if present
|
|
86
96
|
if (typeof options.getRequestHeaders === 'function') {
|
|
87
97
|
const headers: { [key: string]: string } = options.getRequestHeaders();
|
|
88
98
|
Object.keys(headers || {}).forEach((key) => {
|
|
@@ -100,11 +110,11 @@ class Http {
|
|
|
100
110
|
|
|
101
111
|
const error = response?.meta?.error;
|
|
102
112
|
if (error === 'ERROR_PERMISSIONS') {
|
|
103
|
-
return reject(new
|
|
113
|
+
return reject(new RadarPermissionsError('Location permissions not granted.'));
|
|
104
114
|
} else if (error === 'ERROR_LOCATION') {
|
|
105
115
|
return reject(new RadarLocationError('Could not determine location.'));
|
|
106
116
|
} else if (error === 'ERROR_NETWORK') {
|
|
107
|
-
return reject(new
|
|
117
|
+
return reject(new RadarNetworkError());
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
if (xhr.status == 200) {
|
|
@@ -143,15 +153,15 @@ class Http {
|
|
|
143
153
|
}
|
|
144
154
|
|
|
145
155
|
xhr.onerror = function() {
|
|
146
|
-
if (host && host === 'https://radar-verify.com:52516') {
|
|
147
|
-
reject(new
|
|
156
|
+
if (host && (host === 'http://localhost:52516' || host === 'https://radar-verify.com:52516')) {
|
|
157
|
+
reject(new RadarVerifyAppError());
|
|
148
158
|
} else {
|
|
149
159
|
reject(new RadarServerError());
|
|
150
160
|
}
|
|
151
161
|
}
|
|
152
162
|
|
|
153
163
|
xhr.ontimeout = function() {
|
|
154
|
-
reject(new
|
|
164
|
+
reject(new RadarVerifyAppError());
|
|
155
165
|
}
|
|
156
166
|
|
|
157
167
|
xhr.send(JSON.stringify(body));
|
package/src/index.ts
CHANGED
|
@@ -148,10 +148,6 @@ class Radar {
|
|
|
148
148
|
return VerifyAPI.trackVerified(params);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
public static trackVerifiedToken(params: RadarTrackParams = {}) {
|
|
152
|
-
return VerifyAPI.trackVerified(params, true);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
151
|
public static getContext(params: Location) {
|
|
156
152
|
return ContextAPI.getContext(params);
|
|
157
153
|
}
|
package/src/navigator.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Config from './config';
|
|
2
2
|
import Logger from './logger';
|
|
3
3
|
import Storage from './storage';
|
|
4
|
-
import { RadarLocationError,
|
|
4
|
+
import { RadarLocationError, RadarPermissionsError } from './errors';
|
|
5
5
|
|
|
6
6
|
import type { LocationAuthorization, NavigatorPosition } from './types';
|
|
7
7
|
|
|
@@ -9,13 +9,6 @@ interface PositionOptionOverrides {
|
|
|
9
9
|
desiredAccuracy?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError
|
|
13
|
-
const PERMISSION_ERROR_MESSAGES: any = {
|
|
14
|
-
1: 'Permission denied.',
|
|
15
|
-
2: 'Position unavailable.',
|
|
16
|
-
3: 'Timeout.',
|
|
17
|
-
};
|
|
18
|
-
|
|
19
12
|
const DEFAULT_POSITION_OPTIONS: PositionOptions = {
|
|
20
13
|
maximumAge: 0,
|
|
21
14
|
timeout: 1000 * 30, // 30 seconds
|
|
@@ -95,9 +88,11 @@ class Navigator {
|
|
|
95
88
|
return resolve({ latitude, longitude, accuracy });
|
|
96
89
|
},
|
|
97
90
|
(err: GeolocationPositionError) => { // location call failed or user did not grant permission
|
|
98
|
-
if (err && err.code) {
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
if (err && err.code === 1) {
|
|
92
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError
|
|
93
|
+
// code 1 means location permissions denied
|
|
94
|
+
// codes 2 and 3 mean location unavailable or timeout
|
|
95
|
+
return reject(new RadarPermissionsError('Location permissions denied.'));
|
|
101
96
|
}
|
|
102
97
|
return reject(new RadarLocationError('Could not determine location.'));
|
|
103
98
|
},
|
package/src/types.ts
CHANGED
|
@@ -73,6 +73,7 @@ export interface RadarTrackParams {
|
|
|
73
73
|
metadata?: RadarMetadata;
|
|
74
74
|
tripOptions?: RadarTripOptions;
|
|
75
75
|
desiredAccuracy?: 'high' | 'medium' | 'low';
|
|
76
|
+
fraud?: boolean;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export enum RadarEventConfidence {
|
|
@@ -107,7 +108,8 @@ export type RadarEventType =
|
|
|
107
108
|
| 'user.updated_trip'
|
|
108
109
|
| 'user.approaching_trip_destination'
|
|
109
110
|
| 'user.arrived_at_trip_destination'
|
|
110
|
-
| 'user.stopped_trip'
|
|
111
|
+
| 'user.stopped_trip'
|
|
112
|
+
| 'user.failed_fraud';
|
|
111
113
|
|
|
112
114
|
export interface RadarGeofence {
|
|
113
115
|
_id: string;
|
|
@@ -211,8 +213,11 @@ export interface RadarTrackResponse extends RadarResponse {
|
|
|
211
213
|
events?: RadarEvent[];
|
|
212
214
|
}
|
|
213
215
|
|
|
214
|
-
export interface
|
|
216
|
+
export interface RadarTrackVerifiedResponse extends RadarTrackResponse {
|
|
215
217
|
token?: String;
|
|
218
|
+
expiresAt?: Date;
|
|
219
|
+
expiresIn?: number;
|
|
220
|
+
passed?: boolean;
|
|
216
221
|
}
|
|
217
222
|
|
|
218
223
|
export interface RadarContextResponse extends RadarResponse {
|
|
@@ -257,9 +262,6 @@ export interface RadarConversionResponse extends RadarResponse {
|
|
|
257
262
|
export type RadarGeocodeLayer =
|
|
258
263
|
| 'place'
|
|
259
264
|
| 'address'
|
|
260
|
-
| 'intersection'
|
|
261
|
-
| 'street'
|
|
262
|
-
| 'neighborhood'
|
|
263
265
|
| 'postalCode'
|
|
264
266
|
| 'locality'
|
|
265
267
|
| 'county'
|
|
@@ -341,7 +343,9 @@ export interface RadarAutocompleteParams {
|
|
|
341
343
|
limit?: number;
|
|
342
344
|
layers?: RadarGeocodeLayer[];
|
|
343
345
|
countryCode?: string;
|
|
346
|
+
/** @deprecated this is always true, regardless of the value passed here */
|
|
344
347
|
expandUnits?: boolean;
|
|
348
|
+
mailable?: boolean;
|
|
345
349
|
}
|
|
346
350
|
|
|
347
351
|
export interface RadarAutocompleteResponse extends RadarResponse {
|
|
@@ -448,6 +452,7 @@ export interface RadarSearchGeofencesParams {
|
|
|
448
452
|
tags?: string[] | string;
|
|
449
453
|
metadata?: RadarMetadata;
|
|
450
454
|
limit?: number;
|
|
455
|
+
includeGeometry?: boolean;
|
|
451
456
|
}
|
|
452
457
|
|
|
453
458
|
export interface RadarSearchGeofencesResponse extends RadarResponse {
|
|
@@ -476,6 +481,7 @@ export interface RadarAutocompleteUIOptions {
|
|
|
476
481
|
layers?: RadarGeocodeLayer[];
|
|
477
482
|
countryCode?: string;
|
|
478
483
|
expandUnits?: boolean;
|
|
484
|
+
mailable?: boolean;
|
|
479
485
|
placeholder?: string, // Placeholder text for the input field
|
|
480
486
|
onSelection?: (selection: any) => void,
|
|
481
487
|
onRequest?: (params: RadarAutocompleteParams) => void,
|
package/src/ui/autocomplete.ts
CHANGED
|
@@ -236,7 +236,7 @@ class AutocompleteUI {
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
public async fetchResults(query: string) {
|
|
239
|
-
const { limit, layers, countryCode, expandUnits, onRequest } = this.config;
|
|
239
|
+
const { limit, layers, countryCode, expandUnits, mailable, onRequest } = this.config;
|
|
240
240
|
|
|
241
241
|
const params: RadarAutocompleteParams = {
|
|
242
242
|
query,
|
|
@@ -244,6 +244,7 @@ class AutocompleteUI {
|
|
|
244
244
|
layers,
|
|
245
245
|
countryCode,
|
|
246
246
|
expandUnits,
|
|
247
|
+
mailable,
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
if (this.near) {
|
package/src/util/jwt.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const base64Encode = (str: string): string =>
|
|
2
|
+
btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
3
|
+
|
|
4
|
+
export const signJWT = async (payload: object, key: string): Promise<string> => {
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
|
|
7
|
+
const encodedHeader = base64Encode(JSON.stringify({
|
|
8
|
+
alg: 'HS256',
|
|
9
|
+
typ: 'JWT',
|
|
10
|
+
}));
|
|
11
|
+
const encodedPayload = base64Encode(JSON.stringify(payload));
|
|
12
|
+
|
|
13
|
+
const keyData = encoder.encode(key);
|
|
14
|
+
const messageData = encoder.encode(`${encodedHeader}.${encodedPayload}`);
|
|
15
|
+
|
|
16
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
17
|
+
'raw',
|
|
18
|
+
keyData,
|
|
19
|
+
{ name: 'HMAC', hash: { name: 'SHA-256' } },
|
|
20
|
+
false,
|
|
21
|
+
['sign']
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const signatureArrayBuffer = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
|
|
25
|
+
const signature = base64Encode(String.fromCharCode(...Array.from(new Uint8Array(signatureArrayBuffer))));
|
|
26
|
+
|
|
27
|
+
return `${encodedHeader}.${encodedPayload}.${signature}`;
|
|
28
|
+
};
|