coveo.analytics 2.23.10 → 2.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coveoua.browser.js +1 -1
- package/dist/coveoua.browser.js.map +1 -1
- package/dist/coveoua.debug.js +330 -56
- package/dist/coveoua.debug.js.map +1 -1
- package/dist/coveoua.js +1 -1
- package/dist/coveoua.js.map +1 -1
- package/dist/definitions/client/analytics.d.ts +3 -0
- package/dist/definitions/client/noopAnalytics.d.ts +1 -0
- package/dist/definitions/cookieutils.d.ts +1 -1
- package/dist/definitions/coveoua/simpleanalytics.d.ts +1 -0
- package/dist/definitions/plugins/BasePlugin.d.ts +1 -1
- package/dist/definitions/src/coveoua/simpleanalytics.d.ts +1 -0
- package/dist/definitions/storage.d.ts +1 -1
- package/dist/definitions/version.d.ts +1 -0
- package/dist/library.es.js +309 -53
- package/dist/library.js +324 -53
- package/dist/react-native.es.js +81819 -59
- package/package.json +5 -2
- package/src/client/analytics.spec.ts +42 -12
- package/src/client/analytics.ts +22 -1
- package/src/client/analyticsBeaconClient.spec.ts +1 -1
- package/src/client/noopAnalytics.ts +4 -0
- package/src/cookieutils.ts +21 -42
- package/src/coveoua/browser.ts +2 -2
- package/src/coveoua/plugins.ts +1 -1
- package/src/coveoua/simpleanalytics.spec.ts +11 -5
- package/src/coveoua/simpleanalytics.ts +6 -0
- package/src/plugins/BasePlugin.ts +3 -4
- package/src/plugins/ec.spec.ts +1 -1
- package/src/plugins/ec.ts +1 -1
- package/src/plugins/svc.spec.ts +1 -1
- package/src/plugins/svc.ts +1 -1
- package/src/react-native/react-native-runtime.ts +1 -1
- package/src/storage.spec.ts +8 -0
- package/src/storage.ts +3 -3
- package/src/version.ts +1 -0
- package/dist/definitions/client/crypto.d.ts +0 -1
- package/src/client/crypto.ts +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coveo.analytics",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.25.1",
|
|
4
4
|
"description": "📈 Coveo analytics client (node and browser compatible) ",
|
|
5
5
|
"main": "dist/library.js",
|
|
6
6
|
"module": "dist/library.es.js",
|
|
@@ -23,18 +23,21 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"cross-fetch": "^3.1.5"
|
|
26
|
+
"cross-fetch": "^3.1.5",
|
|
27
|
+
"uuid": "^9.0.0"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"@rollup/plugin-alias": "^3.1.2",
|
|
30
31
|
"@rollup/plugin-commonjs": "^19.0.0",
|
|
31
32
|
"@rollup/plugin-json": "^4.1.0",
|
|
32
33
|
"@rollup/plugin-node-resolve": "^13.0.0",
|
|
34
|
+
"@rollup/plugin-replace": "^5.0.2",
|
|
33
35
|
"@types/fetch-mock": "^7.3.2",
|
|
34
36
|
"@types/jest": "^25.1.1",
|
|
35
37
|
"@types/jsdom": "^12.2.4",
|
|
36
38
|
"@types/mime": "0.0.29",
|
|
37
39
|
"@types/node": "^6.0.45",
|
|
40
|
+
"@types/uuid": "^9.0.0",
|
|
38
41
|
"babel-core": "^6.17.0",
|
|
39
42
|
"babel-loader": "^7.1.4",
|
|
40
43
|
"babel-preset-es2015": "^6.16.0",
|
|
@@ -9,10 +9,10 @@ import * as doNotTrack from '../donottrack';
|
|
|
9
9
|
import {Cookie} from '../cookieutils';
|
|
10
10
|
|
|
11
11
|
const aVisitorId = '123';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
jest.
|
|
15
|
-
|
|
12
|
+
jest.mock('uuid', () => ({
|
|
13
|
+
v4: () => aVisitorId,
|
|
14
|
+
validate: jest.requireActual('uuid').validate,
|
|
15
|
+
v5: jest.requireActual('uuid').v5,
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
18
|
const {fetchMock, fetchMockBeforeEach} = mockFetch();
|
|
@@ -49,7 +49,6 @@ describe('Analytics', () => {
|
|
|
49
49
|
new CookieStorage().removeItem('visitorId');
|
|
50
50
|
localStorage.clear();
|
|
51
51
|
fetchMock.reset();
|
|
52
|
-
uuidv4Mock.mockImplementationOnce(() => aVisitorId);
|
|
53
52
|
|
|
54
53
|
client = new CoveoAnalyticsClient({
|
|
55
54
|
token: aToken,
|
|
@@ -66,7 +65,7 @@ describe('Analytics', () => {
|
|
|
66
65
|
|
|
67
66
|
expect(fetchMock.called()).toBe(true);
|
|
68
67
|
|
|
69
|
-
const [path, {headers, body}] = fetchMock.lastCall();
|
|
68
|
+
const [path, {headers, body}]: any = fetchMock.lastCall();
|
|
70
69
|
expect(path).toBe(endpointForEventType(EventType.view));
|
|
71
70
|
|
|
72
71
|
const h = headers as Record<string, string>;
|
|
@@ -115,8 +114,8 @@ describe('Analytics', () => {
|
|
|
115
114
|
|
|
116
115
|
await Promise.all([firstRequest, secondRequest, thirdRequest]);
|
|
117
116
|
|
|
118
|
-
const assertResponseHasCustomDataWithIndex = (response: RequestInit, index: number) => {
|
|
119
|
-
const parsedBody = JSON.parse(response
|
|
117
|
+
const assertResponseHasCustomDataWithIndex = (response: RequestInit | undefined, index: number) => {
|
|
118
|
+
const parsedBody = JSON.parse(response!.body!.toString());
|
|
120
119
|
expect(parsedBody.customData.index).toBe(index);
|
|
121
120
|
};
|
|
122
121
|
const [[, firstResponse], [, secondResponse], [, thirdResponse]] = fetchMock.calls();
|
|
@@ -170,7 +169,7 @@ describe('Analytics', () => {
|
|
|
170
169
|
it('should properly parse empty arguments', async () => {
|
|
171
170
|
await client.sendEvent(specialEventType);
|
|
172
171
|
|
|
173
|
-
const [path, {body}] = fetchMock.lastCall();
|
|
172
|
+
const [path, {body}]: any = fetchMock.lastCall();
|
|
174
173
|
expect(path).toBe(endpointForEventType(EventType.custom));
|
|
175
174
|
|
|
176
175
|
const parsedBody = JSON.parse(body.toString());
|
|
@@ -409,16 +408,16 @@ describe('Analytics', () => {
|
|
|
409
408
|
|
|
410
409
|
const call = fetchMock.calls()[0];
|
|
411
410
|
const url = call[0];
|
|
412
|
-
const options: RequestInit = call[1];
|
|
411
|
+
const options: RequestInit | undefined = call[1];
|
|
413
412
|
|
|
414
413
|
const {url: expectedUrl, ...expectedOptions} = processedRequest;
|
|
415
|
-
expect(clientOrigin).toBe('analyticsFetch');
|
|
414
|
+
expect(clientOrigin!).toBe('analyticsFetch');
|
|
416
415
|
expect(url).toBe(expectedUrl);
|
|
417
416
|
expect(options).toEqual(expectedOptions);
|
|
418
417
|
});
|
|
419
418
|
|
|
420
419
|
const getParsedBodyCalls = (): any[] => {
|
|
421
|
-
return fetchMock.calls().map(([, {body}]) => {
|
|
420
|
+
return fetchMock.calls().map(([, {body}]: any) => {
|
|
422
421
|
return JSON.parse(body.toString());
|
|
423
422
|
});
|
|
424
423
|
};
|
|
@@ -453,3 +452,34 @@ describe('doNotTrack', () => {
|
|
|
453
452
|
expect(Cookie.get('coveo_visitorId')).not.toBe(aVisitorId);
|
|
454
453
|
});
|
|
455
454
|
});
|
|
455
|
+
|
|
456
|
+
describe('custom clientId', () => {
|
|
457
|
+
it('allows setting of a custom clientId', async () => {
|
|
458
|
+
const client = new CoveoAnalyticsClient({});
|
|
459
|
+
client.setClientId('c7d57b22-4aa8-487a-a106-be5243885f0a');
|
|
460
|
+
expect(await client.getCurrentVisitorId()).toBe('c7d57b22-4aa8-487a-a106-be5243885f0a');
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
it('allows setting a custom consistent clientId given a string', async () => {
|
|
464
|
+
const client = new CoveoAnalyticsClient({});
|
|
465
|
+
client.setClientId('somestring', 'testNameSpace');
|
|
466
|
+
//uuid v5 specific uuid generation
|
|
467
|
+
expect(await client.getCurrentVisitorId()).toBe('2c356915-8223-5773-acb8-e2a34404a559');
|
|
468
|
+
//check for consistent ids
|
|
469
|
+
client.setClientId('somestring', 'testNameSpace');
|
|
470
|
+
expect(await client.getCurrentVisitorId()).toBe('2c356915-8223-5773-acb8-e2a34404a559');
|
|
471
|
+
client.setClientId('otherstring', 'testNameSpace');
|
|
472
|
+
expect(await client.getCurrentVisitorId()).not.toBe('2c356915-8223-5773-acb8-e2a34404a559');
|
|
473
|
+
client.setClientId('somestring', 'otherNameSpace');
|
|
474
|
+
expect(await client.getCurrentVisitorId()).not.toBe('2c356915-8223-5773-acb8-e2a34404a559');
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('errors when not providing a namespace', async () => {
|
|
478
|
+
const client = new CoveoAnalyticsClient({});
|
|
479
|
+
expect.assertions(1);
|
|
480
|
+
await expect(client.setClientId('somestring')).rejects.toEqual(
|
|
481
|
+
Error('Cannot generate uuid client id without a specific namespace string.')
|
|
482
|
+
);
|
|
483
|
+
//uuid v5 specific uuid generation
|
|
484
|
+
});
|
|
485
|
+
});
|
package/src/client/analytics.ts
CHANGED
|
@@ -22,7 +22,8 @@ import {IAnalyticsClientOptions, PreprocessAnalyticsRequest, VisitorIdProvider}
|
|
|
22
22
|
import {hasWindow, hasDocument} from '../detector';
|
|
23
23
|
import {addDefaultValues} from '../hook/addDefaultValues';
|
|
24
24
|
import {enhanceViewEvent} from '../hook/enhanceViewEvent';
|
|
25
|
-
import {uuidv4} from '
|
|
25
|
+
import {v4 as uuidv4, v5 as uuidv5, validate as uuidValidate} from 'uuid';
|
|
26
|
+
import {libVersion} from '../version';
|
|
26
27
|
import {
|
|
27
28
|
convertKeysToMeasurementProtocol,
|
|
28
29
|
isMeasurementProtocolKey,
|
|
@@ -98,6 +99,7 @@ export interface AnalyticsClient {
|
|
|
98
99
|
registerAfterSendEventHook(hook: AnalyticsClientSendEventHook): void;
|
|
99
100
|
addEventTypeMapping(eventType: string, eventConfig: EventTypeConfig): void;
|
|
100
101
|
runtime: IRuntimeEnvironment;
|
|
102
|
+
version: string;
|
|
101
103
|
/**
|
|
102
104
|
* @deprecated
|
|
103
105
|
*/
|
|
@@ -118,6 +120,11 @@ export function buildBaseUrl(endpoint = Endpoints.default, apiVersion = Version)
|
|
|
118
120
|
return `${endpoint}${endpointIsCoveoProxy ? '' : '/rest'}/${apiVersion}`;
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
// Note: Changing this value will destroy the mapping from tracking string to clientId for all customers
|
|
124
|
+
// using the setClientId() api. It will have the same effect as every visitor for those customers clearing
|
|
125
|
+
// their cookie store at the same time, with corresponding downstream effects.
|
|
126
|
+
const COVEO_NAMESPACE = '38824e1f-37f5-42d3-8372-a4b8fa9df946';
|
|
127
|
+
|
|
121
128
|
export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider {
|
|
122
129
|
private get defaultOptions(): ClientOptions {
|
|
123
130
|
return {
|
|
@@ -130,6 +137,9 @@ export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider
|
|
|
130
137
|
}
|
|
131
138
|
|
|
132
139
|
public runtime: IRuntimeEnvironment;
|
|
140
|
+
public get version(): string {
|
|
141
|
+
return libVersion;
|
|
142
|
+
}
|
|
133
143
|
private visitorId: string;
|
|
134
144
|
private bufferedRequests: BufferedRequest[];
|
|
135
145
|
private beforeSendHooks: AnalyticsClientSendEventHook[];
|
|
@@ -209,6 +219,17 @@ export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider
|
|
|
209
219
|
await this.storage.setItem('visitorId', visitorId);
|
|
210
220
|
}
|
|
211
221
|
|
|
222
|
+
async setClientId(value: string, namespace?: string) {
|
|
223
|
+
if (uuidValidate(value)) {
|
|
224
|
+
this.setCurrentVisitorId(value);
|
|
225
|
+
} else {
|
|
226
|
+
if (!namespace) {
|
|
227
|
+
throw Error('Cannot generate uuid client id without a specific namespace string.');
|
|
228
|
+
}
|
|
229
|
+
this.setCurrentVisitorId(uuidv5(value, uuidv5(namespace, COVEO_NAMESPACE)));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
212
233
|
async getParameters(eventType: EventType | string, ...payload: VariableArgumentsPayload) {
|
|
213
234
|
return await this.resolveParameters(eventType, ...payload);
|
|
214
235
|
}
|
|
@@ -124,7 +124,7 @@ describe('AnalyticsBeaconClient', () => {
|
|
|
124
124
|
|
|
125
125
|
await client.sendEvent(EventType.collect, {});
|
|
126
126
|
|
|
127
|
-
expect(clientOrigin).toBe('analyticsBeacon');
|
|
127
|
+
expect(clientOrigin!).toBe('analyticsBeacon');
|
|
128
128
|
expect(sendBeaconMock).toHaveBeenCalledWith(processedRequest.url, processedRequest.body);
|
|
129
129
|
});
|
|
130
130
|
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
PreparedViewEventRequest,
|
|
18
18
|
ViewEventRequest,
|
|
19
19
|
} from '../events';
|
|
20
|
+
import {libVersion} from '../version';
|
|
20
21
|
import {NoopRuntime} from './runtimeEnvironment';
|
|
21
22
|
|
|
22
23
|
export class NoopAnalytics implements AnalyticsClient {
|
|
@@ -68,5 +69,8 @@ export class NoopAnalytics implements AnalyticsClient {
|
|
|
68
69
|
registerAfterSendEventHook(): void {}
|
|
69
70
|
addEventTypeMapping(): void {}
|
|
70
71
|
runtime = new NoopRuntime();
|
|
72
|
+
public get version(): string {
|
|
73
|
+
return libVersion;
|
|
74
|
+
}
|
|
71
75
|
currentVisitorId = '';
|
|
72
76
|
}
|
package/src/cookieutils.ts
CHANGED
|
@@ -1,50 +1,27 @@
|
|
|
1
1
|
interface CookieDetails {
|
|
2
2
|
name: string;
|
|
3
3
|
value: string;
|
|
4
|
-
|
|
5
|
-
domain
|
|
4
|
+
expirationDate?: Date;
|
|
5
|
+
domain?: string;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
// Code originally
|
|
8
|
+
// Code originally modified from : https://developers.livechatinc.com/blog/setting-cookies-to-subdomains-in-javascript/
|
|
9
9
|
export class Cookie {
|
|
10
|
-
static set(name: string, value: string,
|
|
11
|
-
var domain: string,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
date.setTime(date.getTime() + expiration);
|
|
16
|
-
expires = '; expires=' + date.toGMTString();
|
|
17
|
-
} else {
|
|
18
|
-
expires = '';
|
|
10
|
+
static set(name: string, value: string, expire?: number) {
|
|
11
|
+
var domain: string, expirationDate: Date | undefined, domainParts: string[], host: string;
|
|
12
|
+
if (expire) {
|
|
13
|
+
expirationDate = new Date();
|
|
14
|
+
expirationDate.setTime(expirationDate.getTime() + expire);
|
|
19
15
|
}
|
|
20
|
-
|
|
21
16
|
host = window.location.hostname;
|
|
22
17
|
if (host.indexOf('.') === -1) {
|
|
23
|
-
// no "." in a domain - it's localhost or something similar
|
|
24
|
-
|
|
18
|
+
// no "." in a domain - single domain name, it's localhost or something similar
|
|
19
|
+
writeCookie(name, value, expirationDate);
|
|
25
20
|
} else {
|
|
26
|
-
// Remember the cookie on all subdomains.
|
|
27
|
-
//
|
|
28
|
-
// Start with trying to set cookie to the top domain.
|
|
29
|
-
// (example: if user is on foo.com, try to set
|
|
30
|
-
// cookie to domain ".com")
|
|
31
|
-
//
|
|
32
|
-
// If the cookie will not be set, it means ".com"
|
|
33
|
-
// is a top level domain and we need to
|
|
34
|
-
// set the cookie to ".foo.com"
|
|
35
21
|
domainParts = host.split('.');
|
|
36
|
-
|
|
37
|
-
domain = '.' + domainParts.
|
|
38
|
-
|
|
39
|
-
writeCookie({name, value, expires, domain});
|
|
40
|
-
|
|
41
|
-
// check if cookie was successfuly set to the given domain
|
|
42
|
-
// (otherwise it was a Top-Level Domain)
|
|
43
|
-
if (Cookie.get(name) == null || Cookie.get(name) != value) {
|
|
44
|
-
// append "." to current domain
|
|
45
|
-
domain = '.' + host;
|
|
46
|
-
writeCookie({name, value, expires, domain});
|
|
47
|
-
}
|
|
22
|
+
// we always have at least 2 domain parts
|
|
23
|
+
domain = domainParts[domainParts.length - 2] + '.' + domainParts[domainParts.length - 1];
|
|
24
|
+
writeCookie(name, value, expirationDate, domain);
|
|
48
25
|
}
|
|
49
26
|
}
|
|
50
27
|
|
|
@@ -53,9 +30,8 @@ export class Cookie {
|
|
|
53
30
|
var cookieArray = document.cookie.split(';');
|
|
54
31
|
for (var i = 0; i < cookieArray.length; i++) {
|
|
55
32
|
var cookie = cookieArray[i];
|
|
56
|
-
cookie = cookie.replace(/^\s+/, '');
|
|
57
|
-
|
|
58
|
-
if (cookie.indexOf(cookiePrefix) == 0) {
|
|
33
|
+
cookie = cookie.replace(/^\s+/, ''); //strip whitespace from front of cookie only
|
|
34
|
+
if (cookie.lastIndexOf(cookiePrefix, 0) === 0) {
|
|
59
35
|
return cookie.substring(cookiePrefix.length, cookie.length);
|
|
60
36
|
}
|
|
61
37
|
}
|
|
@@ -67,7 +43,10 @@ export class Cookie {
|
|
|
67
43
|
}
|
|
68
44
|
}
|
|
69
45
|
|
|
70
|
-
function writeCookie(
|
|
71
|
-
|
|
72
|
-
|
|
46
|
+
function writeCookie(name: string, value: string, expirationDate?: Date, domain?: string) {
|
|
47
|
+
document.cookie =
|
|
48
|
+
`${name}=${value}` +
|
|
49
|
+
(expirationDate ? `;expires=${expirationDate.toUTCString()}` : '') +
|
|
50
|
+
(domain ? `;domain=${domain}` : '') +
|
|
51
|
+
';SameSite=Lax';
|
|
73
52
|
}
|
package/src/coveoua/browser.ts
CHANGED
|
@@ -4,13 +4,13 @@ import handleOneAnalyticsEvent from './simpleanalytics';
|
|
|
4
4
|
declare const self: any;
|
|
5
5
|
|
|
6
6
|
const promise = (window as any)['Promise'];
|
|
7
|
-
if (!(promise instanceof Function)) {
|
|
7
|
+
if (!(promise instanceof Function) && !global) {
|
|
8
8
|
console.error(
|
|
9
9
|
`This script uses window.Promise which is not supported in your browser. Consider adding a polyfill like "es6-promise".`
|
|
10
10
|
);
|
|
11
11
|
}
|
|
12
12
|
const fetch = (window as any)['fetch'];
|
|
13
|
-
if (!(fetch instanceof Function)) {
|
|
13
|
+
if (!(fetch instanceof Function) && !global) {
|
|
14
14
|
console.error(
|
|
15
15
|
`This script uses window.fetch which is not supported in your browser. Consider adding a polyfill like "fetch".`
|
|
16
16
|
);
|
package/src/coveoua/plugins.ts
CHANGED
|
@@ -20,7 +20,7 @@ export class Plugins {
|
|
|
20
20
|
`No plugin named "${name}" is currently registered. If you use a custom plugin, use 'provide' first.`
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
|
-
this.requiredPlugins[name] = new pluginClass(options);
|
|
23
|
+
this.requiredPlugins[name] = new (pluginClass as any)(options);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
provide(name: string, plugin: PluginClass) {
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import coveoua from './simpleanalytics';
|
|
2
2
|
import {createAnalyticsClientMock, visitorIdMock} from '../../tests/analyticsClientMock';
|
|
3
3
|
import {TestPlugin} from '../../tests/pluginMock';
|
|
4
|
-
import {uuidv4} from '
|
|
4
|
+
import {v4 as uuidv4} from 'uuid';
|
|
5
5
|
import {PluginOptions} from '../plugins/BasePlugin';
|
|
6
6
|
import {mockFetch} from '../../tests/fetchMock';
|
|
7
7
|
import {CookieStorage} from '../storage';
|
|
8
|
+
import {libVersion} from '../version';
|
|
8
9
|
|
|
9
10
|
const uuidv4Mock = jest.fn();
|
|
10
|
-
jest.mock('
|
|
11
|
-
uuidv4: () => uuidv4Mock(),
|
|
12
|
-
}));
|
|
11
|
+
jest.mock('uuid', () => ({v4: () => uuidv4Mock()}));
|
|
13
12
|
|
|
14
13
|
const {fetchMock, fetchMockBeforeEach} = mockFetch();
|
|
15
14
|
|
|
@@ -376,6 +375,13 @@ describe('simpleanalytics', () => {
|
|
|
376
375
|
});
|
|
377
376
|
});
|
|
378
377
|
|
|
378
|
+
describe('version', () => {
|
|
379
|
+
it('returns the current version string', () => {
|
|
380
|
+
coveoua('init', 'MYTOKEN');
|
|
381
|
+
expect(coveoua('version')).toBe(libVersion);
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
|
|
379
385
|
describe('callPlugin', () => {
|
|
380
386
|
it('resolves properly plugin actions', () => {
|
|
381
387
|
coveoua('provide', 'test', TestPluginWithSpy);
|
|
@@ -468,7 +474,7 @@ describe('simpleanalytics', () => {
|
|
|
468
474
|
coveoua('init', 'SOME TOKEN', {plugins: ['svc']});
|
|
469
475
|
|
|
470
476
|
expect(() => coveoua('potato')).toThrow(
|
|
471
|
-
`The action "potato" does not exist. Available actions: init, set, send, onLoad, callPlugin, reset, require, provide.`
|
|
477
|
+
`The action "potato" does not exist. Available actions: init, set, send, onLoad, callPlugin, reset, require, provide, version.`
|
|
472
478
|
);
|
|
473
479
|
});
|
|
474
480
|
|
|
@@ -3,6 +3,7 @@ import {AnalyticsClient, CoveoAnalyticsClient, Endpoints} from '../client/analyt
|
|
|
3
3
|
import {Plugins} from './plugins';
|
|
4
4
|
import {PluginOptions} from '../plugins/BasePlugin';
|
|
5
5
|
import {PluginClass} from '../plugins/BasePlugin';
|
|
6
|
+
import {libVersion} from '../version';
|
|
6
7
|
|
|
7
8
|
export type AvailableActions = keyof CoveoUA;
|
|
8
9
|
|
|
@@ -137,6 +138,10 @@ export class CoveoUA {
|
|
|
137
138
|
this.plugins = new Plugins();
|
|
138
139
|
this.params = {};
|
|
139
140
|
}
|
|
141
|
+
|
|
142
|
+
version(): string {
|
|
143
|
+
return libVersion;
|
|
144
|
+
}
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
export const coveoua = new CoveoUA();
|
|
@@ -160,6 +165,7 @@ export const handleOneAnalyticsEvent = (command: string, ...params: any[]) => {
|
|
|
160
165
|
'reset',
|
|
161
166
|
'require',
|
|
162
167
|
'provide',
|
|
168
|
+
'version',
|
|
163
169
|
];
|
|
164
170
|
throw new Error(`The action "${command}" does not exist. Available actions: ${actions.join(', ')}.`);
|
|
165
171
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {AnalyticsClient} from '../client/analytics';
|
|
2
|
-
import {uuidv4} from '
|
|
2
|
+
import {v4 as uuidv4} from 'uuid';
|
|
3
3
|
import {getFormattedLocation} from '../client/location';
|
|
4
|
-
import {UAPluginOptions} from '../coveoua/plugins';
|
|
5
4
|
import {hasDocument} from '../detector';
|
|
6
5
|
|
|
7
6
|
type PluginWithId = {
|
|
@@ -67,7 +66,7 @@ export abstract class BasePlugin {
|
|
|
67
66
|
public getDefaultContextInformation(eventType: string) {
|
|
68
67
|
const documentContext = {
|
|
69
68
|
title: hasDocument() ? document.title : '',
|
|
70
|
-
encoding: hasDocument() ? document.characterSet :'UTF-8',
|
|
69
|
+
encoding: hasDocument() ? document.characterSet : 'UTF-8',
|
|
71
70
|
};
|
|
72
71
|
const screenContext = {
|
|
73
72
|
screenResolution: `${screen.width}x${screen.height}`,
|
|
@@ -103,7 +102,7 @@ export abstract class BasePlugin {
|
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
/*
|
|
106
|
-
When calling getPayload or getParameters, we need to return what would be sent by the API without updating our internal reference.
|
|
105
|
+
When calling getPayload or getParameters, we need to return what would be sent by the API without updating our internal reference.
|
|
107
106
|
For instance, if you getPayload("pageview"), we want to return the same payload as if you did coveoua("send", "pageview").
|
|
108
107
|
*/
|
|
109
108
|
private getNextValues(eventType: string, payload: any) {
|
package/src/plugins/ec.spec.ts
CHANGED
|
@@ -25,7 +25,7 @@ describe('EC plugin', () => {
|
|
|
25
25
|
beforeEach(() => {
|
|
26
26
|
jest.clearAllMocks();
|
|
27
27
|
client = createAnalyticsClientMock();
|
|
28
|
-
ec = new ECPlugin({client, uuidGenerator: someUUIDGenerator});
|
|
28
|
+
ec = new ECPlugin({client, uuidGenerator: someUUIDGenerator as any});
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('should register a hook in the client', () => {
|
package/src/plugins/ec.ts
CHANGED
package/src/plugins/svc.spec.ts
CHANGED
|
@@ -25,7 +25,7 @@ describe('SVC plugin', () => {
|
|
|
25
25
|
beforeEach(() => {
|
|
26
26
|
jest.clearAllMocks();
|
|
27
27
|
client = createAnalyticsClientMock();
|
|
28
|
-
svc = new SVCPlugin({client, uuidGenerator: someUUIDGenerator});
|
|
28
|
+
svc = new SVCPlugin({client, uuidGenerator: someUUIDGenerator as any});
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('should register a hook in the client', () => {
|
package/src/plugins/svc.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {EventType} from '../events';
|
|
2
|
-
import {uuidv4} from '
|
|
2
|
+
import {v4 as uuidv4} from 'uuid';
|
|
3
3
|
import {convertTicketToMeasurementProtocol} from '../client/measurementProtocolMapping/serviceMeasurementProtocolMapper';
|
|
4
4
|
import {BasePlugin, BasePluginEventTypes, PluginClass, PluginOptions} from './BasePlugin';
|
|
5
5
|
|
|
@@ -2,7 +2,7 @@ import {WebStorage} from '../storage';
|
|
|
2
2
|
import {AnalyticsFetchClient} from '../client/analyticsFetchClient';
|
|
3
3
|
import {IRuntimeEnvironment} from '../client/runtimeEnvironment';
|
|
4
4
|
import {PreprocessAnalyticsRequest} from '../client/analyticsRequestClient';
|
|
5
|
-
import {uuidv4} from '
|
|
5
|
+
import {v4 as uuidv4} from 'uuid';
|
|
6
6
|
import {buildBaseUrl} from '../client/analytics';
|
|
7
7
|
|
|
8
8
|
export type ReactNativeStorage = WebStorage;
|
package/src/storage.spec.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {CookieStorage, CookieAndLocalStorage} from './storage';
|
|
2
|
+
import {Cookie} from './cookieutils';
|
|
2
3
|
|
|
3
4
|
describe('CookieStorage', () => {
|
|
4
5
|
const key = 'wow';
|
|
@@ -16,6 +17,13 @@ describe('CookieStorage', () => {
|
|
|
16
17
|
storage.removeItem(key);
|
|
17
18
|
expect(storage.getItem(key)).toBe(null);
|
|
18
19
|
});
|
|
20
|
+
|
|
21
|
+
it('honors expiration date', async () => {
|
|
22
|
+
const storage = new CookieStorage();
|
|
23
|
+
storage.setItem(key, someData, 1000);
|
|
24
|
+
await new Promise((res) => setTimeout(res, 1000)); // wait for 1 sec
|
|
25
|
+
expect(storage.getItem(key)).toBe(null);
|
|
26
|
+
});
|
|
19
27
|
});
|
|
20
28
|
|
|
21
29
|
describe('CookieAndLocalStorage', () => {
|
package/src/storage.ts
CHANGED
|
@@ -33,8 +33,8 @@ export class CookieStorage implements WebStorage {
|
|
|
33
33
|
removeItem(key: string) {
|
|
34
34
|
Cookie.erase(`${CookieStorage.prefix}${key}`);
|
|
35
35
|
}
|
|
36
|
-
setItem(key: string, data: string): void {
|
|
37
|
-
Cookie.set(`${CookieStorage.prefix}${key}`, data);
|
|
36
|
+
setItem(key: string, data: string, expire?: number): void {
|
|
37
|
+
Cookie.set(`${CookieStorage.prefix}${key}`, data, expire);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -52,7 +52,7 @@ export class CookieAndLocalStorage implements WebStorage {
|
|
|
52
52
|
|
|
53
53
|
setItem(key: string, data: string): void {
|
|
54
54
|
localStorage.setItem(key, data);
|
|
55
|
-
this.cookieStorage.setItem(key, data);
|
|
55
|
+
this.cookieStorage.setItem(key, data, 31556926000); // 1 year first party cookie
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
package/src/version.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const libVersion = process.env.PKG_VERSION || 'local'; // processed by @rollup/plugin-replace
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const uuidv4: (a?: string | number | undefined) => string;
|
package/src/client/crypto.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {hasCryptoRandomValues} from '../detector';
|
|
2
|
-
|
|
3
|
-
export const uuidv4 = (a?: number | string): string => {
|
|
4
|
-
if (!!a) {
|
|
5
|
-
return (Number(a) ^ (getRandomValues(new Uint8Array(1))[0] % 16 >> (Number(a) / 4))).toString(16);
|
|
6
|
-
}
|
|
7
|
-
return (`${1e7}` + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuidv4);
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const getRandomValues = (rnds: Uint8Array) => {
|
|
11
|
-
if (hasCryptoRandomValues()) {
|
|
12
|
-
return crypto.getRandomValues(rnds);
|
|
13
|
-
}
|
|
14
|
-
for (var i = 0, r = 0; i < rnds.length; i++) {
|
|
15
|
-
if ((i & 0x03) === 0) {
|
|
16
|
-
r = Math.random() * 0x100000000;
|
|
17
|
-
}
|
|
18
|
-
rnds[i] = (r >>> ((i & 0x03) << 3)) & 0xff;
|
|
19
|
-
}
|
|
20
|
-
return rnds;
|
|
21
|
-
};
|