coveo.analytics 2.23.7 → 2.23.9

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.
@@ -99,6 +99,7 @@ export declare class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdP
99
99
  private removeEmptyPayloadValues;
100
100
  private removeUnknownParameters;
101
101
  private processCustomParameters;
102
+ private mapCustomParametersToCustomData;
102
103
  private lowercaseKeys;
103
104
  private validateParams;
104
105
  private ensureAnonymousUserWhenUsingApiKey;
@@ -1 +1,2 @@
1
1
  export declare const keysOf: <T>(o: T) => Extract<keyof T, string>[];
2
+ export declare function isObject(o: any): boolean;
@@ -50,6 +50,8 @@ export declare class CoveoInsightClient {
50
50
  logDocumentOpen(info: PartialDocumentInformation, identifier: DocumentIdentifier, metadata?: CaseMetadata): Promise<void | import("../events").ClickEventResponse>;
51
51
  logCopyToClipboard(info: PartialDocumentInformation, identifier: DocumentIdentifier, metadata?: CaseMetadata): Promise<void | import("../events").ClickEventResponse>;
52
52
  logDocumentQuickview(info: PartialDocumentInformation, identifier: DocumentIdentifier, caseMetadata?: CaseMetadata): Promise<void | import("../events").ClickEventResponse>;
53
+ logCaseAttach(info: PartialDocumentInformation, identifier: DocumentIdentifier, caseMetadata?: CaseMetadata): Promise<void | import("../events").ClickEventResponse>;
54
+ logCaseDetach(resultUriHash: string, metadata?: CaseMetadata): Promise<void | import("../events").CustomEventResponse>;
53
55
  logCustomEvent(event: SearchPageEvents | InsightEvents, metadata?: Record<string, any>): Promise<void | import("../events").CustomEventResponse>;
54
56
  logSearchEvent(event: SearchPageEvents | InsightEvents, metadata?: Record<string, any>): Promise<void | import("../events").SearchEventResponse>;
55
57
  logClickEvent(event: SearchPageEvents, info: PartialDocumentInformation, identifier: DocumentIdentifier, metadata?: Record<string, any>): Promise<void | import("../events").ClickEventResponse>;
@@ -68,7 +68,9 @@ export declare enum SearchPageEvents {
68
68
  noResultsBack = "noResultsBack",
69
69
  showMoreFoldedResults = "showMoreFoldedResults",
70
70
  showLessFoldedResults = "showLessFoldedResults",
71
- copyToClipboard = "copyToClipboard"
71
+ copyToClipboard = "copyToClipboard",
72
+ caseAttach = "caseAttach",
73
+ caseDetach = "caseDetach"
72
74
  }
73
75
  export declare const CustomEventsTypes: Partial<Record<SearchPageEvents | InsightEvents, string>>;
74
76
  export interface StaticFilterMetadata {
@@ -359,7 +359,10 @@ const getRandomValues = (rnds) => {
359
359
  return rnds;
360
360
  };
361
361
 
362
- const keysOf = Object.keys;
362
+ const keysOf = Object.keys;
363
+ function isObject(o) {
364
+ return o !== null && typeof o === 'object' && !Array.isArray(o);
365
+ }
363
366
 
364
367
  const ticketKeysMapping = {
365
368
  id: 'svc_ticket_id',
@@ -912,7 +915,9 @@ class CoveoAnalyticsClient {
912
915
  const validateParams = (currentPayload) => this.validateParams(currentPayload);
913
916
  const processMeasurementProtocolConversionStep = (currentPayload) => usesMeasurementProtocol ? convertKeysToMeasurementProtocol(currentPayload) : currentPayload;
914
917
  const removeUnknownParameters = (currentPayload) => usesMeasurementProtocol ? this.removeUnknownParameters(currentPayload) : currentPayload;
915
- const processCustomParameters = (currentPayload) => usesMeasurementProtocol ? this.processCustomParameters(currentPayload) : currentPayload;
918
+ const processCustomParameters = (currentPayload) => usesMeasurementProtocol
919
+ ? this.processCustomParameters(currentPayload)
920
+ : this.mapCustomParametersToCustomData(currentPayload);
916
921
  const payloadToSend = yield [
917
922
  cleanPayloadStep,
918
923
  validateParams,
@@ -1078,13 +1083,30 @@ class CoveoAnalyticsClient {
1078
1083
  }
1079
1084
  processCustomParameters(payload) {
1080
1085
  const { custom } = payload, rest = __rest(payload, ["custom"]);
1081
- const lowercasedCustom = this.lowercaseKeys(custom);
1086
+ let lowercasedCustom = {};
1087
+ if (custom && isObject(custom)) {
1088
+ lowercasedCustom = this.lowercaseKeys(custom);
1089
+ }
1082
1090
  const newPayload = convertCustomMeasurementProtocolKeys(rest);
1083
1091
  return Object.assign(Object.assign({}, lowercasedCustom), newPayload);
1084
1092
  }
1093
+ mapCustomParametersToCustomData(payload) {
1094
+ const { custom } = payload, rest = __rest(payload, ["custom"]);
1095
+ if (custom && isObject(custom)) {
1096
+ const lowercasedCustom = this.lowercaseKeys(custom);
1097
+ return Object.assign(Object.assign({}, rest), { customData: Object.assign(Object.assign({}, lowercasedCustom), payload.customData) });
1098
+ }
1099
+ else {
1100
+ return payload;
1101
+ }
1102
+ }
1085
1103
  lowercaseKeys(custom) {
1086
- const keys = Object.keys(custom || {});
1087
- return keys.reduce((all, key) => (Object.assign(Object.assign({}, all), { [key.toLowerCase()]: custom[key] })), {});
1104
+ const keys = Object.keys(custom);
1105
+ let result = {};
1106
+ keys.forEach((key) => {
1107
+ result[key.toLowerCase()] = custom[key];
1108
+ });
1109
+ return result;
1088
1110
  }
1089
1111
  validateParams(payload) {
1090
1112
  const { anonymizeIp } = payload, rest = __rest(payload, ["anonymizeIp"]);
@@ -1186,6 +1208,8 @@ var SearchPageEvents;
1186
1208
  SearchPageEvents["showMoreFoldedResults"] = "showMoreFoldedResults";
1187
1209
  SearchPageEvents["showLessFoldedResults"] = "showLessFoldedResults";
1188
1210
  SearchPageEvents["copyToClipboard"] = "copyToClipboard";
1211
+ SearchPageEvents["caseAttach"] = "caseAttach";
1212
+ SearchPageEvents["caseDetach"] = "caseDetach";
1189
1213
  })(SearchPageEvents || (SearchPageEvents = {}));
1190
1214
  const CustomEventsTypes = {
1191
1215
  [SearchPageEvents.triggerNotify]: 'queryPipelineTriggers',
@@ -1221,6 +1245,7 @@ const CustomEventsTypes = {
1221
1245
  [SearchPageEvents.clearRecentResults]: 'recentlyClickedDocuments',
1222
1246
  [SearchPageEvents.showLessFoldedResults]: 'folding',
1223
1247
  [InsightEvents.expandToFullUI]: 'interface',
1248
+ [SearchPageEvents.caseDetach]: 'case',
1224
1249
  };
1225
1250
 
1226
1251
  class NoopAnalytics {
@@ -2429,6 +2454,17 @@ class CoveoInsightClient {
2429
2454
  };
2430
2455
  return this.logClickEvent(SearchPageEvents.documentQuickview, info, identifier, caseMetadata ? Object.assign(Object.assign({}, generateMetadataToSend(caseMetadata, false)), metadata) : metadata);
2431
2456
  }
2457
+ logCaseAttach(info, identifier, caseMetadata) {
2458
+ const metadata = {
2459
+ documentTitle: info.documentTitle,
2460
+ documentURL: info.documentUrl,
2461
+ resultUriHash: info.documentUriHash,
2462
+ };
2463
+ return this.logClickEvent(SearchPageEvents.caseAttach, info, identifier, caseMetadata ? Object.assign(Object.assign({}, generateMetadataToSend(caseMetadata, false)), metadata) : metadata);
2464
+ }
2465
+ logCaseDetach(resultUriHash, metadata) {
2466
+ return this.logCustomEvent(SearchPageEvents.caseDetach, metadata ? Object.assign(Object.assign({}, generateMetadataToSend(metadata, false)), { resultUriHash }) : { resultUriHash });
2467
+ }
2432
2468
  logCustomEvent(event, metadata) {
2433
2469
  return __awaiter(this, void 0, void 0, function* () {
2434
2470
  const customData = Object.assign(Object.assign({}, this.provider.getBaseMetadata()), metadata);
package/dist/library.js CHANGED
@@ -506,7 +506,10 @@ var getRandomValues = function (rnds) {
506
506
  return rnds;
507
507
  };
508
508
 
509
- var keysOf = Object.keys;
509
+ var keysOf = Object.keys;
510
+ function isObject(o) {
511
+ return o !== null && typeof o === 'object' && !Array.isArray(o);
512
+ }
510
513
 
511
514
  var ticketKeysMapping = {
512
515
  id: 'svc_ticket_id',
@@ -82808,7 +82811,9 @@ var CoveoAnalyticsClient = (function () {
82808
82811
  return usesMeasurementProtocol ? _this.removeUnknownParameters(currentPayload) : currentPayload;
82809
82812
  };
82810
82813
  processCustomParameters = function (currentPayload) {
82811
- return usesMeasurementProtocol ? _this.processCustomParameters(currentPayload) : currentPayload;
82814
+ return usesMeasurementProtocol
82815
+ ? _this.processCustomParameters(currentPayload)
82816
+ : _this.mapCustomParametersToCustomData(currentPayload);
82812
82817
  };
82813
82818
  return [4, [
82814
82819
  cleanPayloadStep,
@@ -83078,16 +83083,30 @@ var CoveoAnalyticsClient = (function () {
83078
83083
  };
83079
83084
  CoveoAnalyticsClient.prototype.processCustomParameters = function (payload) {
83080
83085
  var custom = payload.custom, rest = __rest(payload, ["custom"]);
83081
- var lowercasedCustom = this.lowercaseKeys(custom);
83086
+ var lowercasedCustom = {};
83087
+ if (custom && isObject(custom)) {
83088
+ lowercasedCustom = this.lowercaseKeys(custom);
83089
+ }
83082
83090
  var newPayload = convertCustomMeasurementProtocolKeys(rest);
83083
83091
  return __assign(__assign({}, lowercasedCustom), newPayload);
83084
83092
  };
83093
+ CoveoAnalyticsClient.prototype.mapCustomParametersToCustomData = function (payload) {
83094
+ var custom = payload.custom, rest = __rest(payload, ["custom"]);
83095
+ if (custom && isObject(custom)) {
83096
+ var lowercasedCustom = this.lowercaseKeys(custom);
83097
+ return __assign(__assign({}, rest), { customData: __assign(__assign({}, lowercasedCustom), payload.customData) });
83098
+ }
83099
+ else {
83100
+ return payload;
83101
+ }
83102
+ };
83085
83103
  CoveoAnalyticsClient.prototype.lowercaseKeys = function (custom) {
83086
- var keys = Object.keys(custom || {});
83087
- return keys.reduce(function (all, key) {
83088
- var _a;
83089
- return (__assign(__assign({}, all), (_a = {}, _a[key.toLowerCase()] = custom[key], _a)));
83090
- }, {});
83104
+ var keys = Object.keys(custom);
83105
+ var result = {};
83106
+ keys.forEach(function (key) {
83107
+ result[key.toLowerCase()] = custom[key];
83108
+ });
83109
+ return result;
83091
83110
  };
83092
83111
  CoveoAnalyticsClient.prototype.validateParams = function (payload) {
83093
83112
  var anonymizeIp = payload.anonymizeIp, rest = __rest(payload, ["anonymizeIp"]);
@@ -83450,7 +83469,7 @@ var Plugins = (function () {
83450
83469
  }
83451
83470
  var actionFunction = plugin[fn];
83452
83471
  if (!actionFunction) {
83453
- throw new Error("The function \"" + fn + "\" does not exists on the plugin \"" + name + "\".");
83472
+ throw new Error("The function \"" + fn + "\" does not exist on the plugin \"" + name + "\".");
83454
83473
  }
83455
83474
  if (typeof actionFunction !== 'function') {
83456
83475
  throw new Error("\"" + fn + "\" of the plugin \"" + name + "\" is not a function.");
@@ -83694,6 +83713,8 @@ var SearchPageEvents;
83694
83713
  SearchPageEvents["showMoreFoldedResults"] = "showMoreFoldedResults";
83695
83714
  SearchPageEvents["showLessFoldedResults"] = "showLessFoldedResults";
83696
83715
  SearchPageEvents["copyToClipboard"] = "copyToClipboard";
83716
+ SearchPageEvents["caseAttach"] = "caseAttach";
83717
+ SearchPageEvents["caseDetach"] = "caseDetach";
83697
83718
  })(SearchPageEvents || (SearchPageEvents = {}));
83698
83719
  var CustomEventsTypes = (_a = {},
83699
83720
  _a[SearchPageEvents.triggerNotify] = 'queryPipelineTriggers',
@@ -83729,6 +83750,7 @@ var CustomEventsTypes = (_a = {},
83729
83750
  _a[SearchPageEvents.clearRecentResults] = 'recentlyClickedDocuments',
83730
83751
  _a[SearchPageEvents.showLessFoldedResults] = 'folding',
83731
83752
  _a[InsightEvents.expandToFullUI] = 'interface',
83753
+ _a[SearchPageEvents.caseDetach] = 'case',
83732
83754
  _a);
83733
83755
 
83734
83756
  var NoopAnalytics = (function () {
@@ -85279,6 +85301,17 @@ var CoveoInsightClient = (function () {
85279
85301
  };
85280
85302
  return this.logClickEvent(SearchPageEvents.documentQuickview, info, identifier, caseMetadata ? __assign(__assign({}, generateMetadataToSend(caseMetadata, false)), metadata) : metadata);
85281
85303
  };
85304
+ CoveoInsightClient.prototype.logCaseAttach = function (info, identifier, caseMetadata) {
85305
+ var metadata = {
85306
+ documentTitle: info.documentTitle,
85307
+ documentURL: info.documentUrl,
85308
+ resultUriHash: info.documentUriHash,
85309
+ };
85310
+ return this.logClickEvent(SearchPageEvents.caseAttach, info, identifier, caseMetadata ? __assign(__assign({}, generateMetadataToSend(caseMetadata, false)), metadata) : metadata);
85311
+ };
85312
+ CoveoInsightClient.prototype.logCaseDetach = function (resultUriHash, metadata) {
85313
+ return this.logCustomEvent(SearchPageEvents.caseDetach, metadata ? __assign(__assign({}, generateMetadataToSend(metadata, false)), { resultUriHash: resultUriHash }) : { resultUriHash: resultUriHash });
85314
+ };
85282
85315
  CoveoInsightClient.prototype.logCustomEvent = function (event, metadata) {
85283
85316
  return __awaiter(this, void 0, void 0, function () {
85284
85317
  var customData, payload, _a;
@@ -420,7 +420,10 @@ const addPageViewToHistory = (pageViewValue) => __awaiter(void 0, void 0, void 0
420
420
  yield store.addElementAsync(historyElement);
421
421
  });
422
422
 
423
- const keysOf = Object.keys;
423
+ const keysOf = Object.keys;
424
+ function isObject(o) {
425
+ return o !== null && typeof o === 'object' && !Array.isArray(o);
426
+ }
424
427
 
425
428
  const ticketKeysMapping = {
426
429
  id: 'svc_ticket_id',
@@ -912,7 +915,9 @@ class CoveoAnalyticsClient {
912
915
  const validateParams = (currentPayload) => this.validateParams(currentPayload);
913
916
  const processMeasurementProtocolConversionStep = (currentPayload) => usesMeasurementProtocol ? convertKeysToMeasurementProtocol(currentPayload) : currentPayload;
914
917
  const removeUnknownParameters = (currentPayload) => usesMeasurementProtocol ? this.removeUnknownParameters(currentPayload) : currentPayload;
915
- const processCustomParameters = (currentPayload) => usesMeasurementProtocol ? this.processCustomParameters(currentPayload) : currentPayload;
918
+ const processCustomParameters = (currentPayload) => usesMeasurementProtocol
919
+ ? this.processCustomParameters(currentPayload)
920
+ : this.mapCustomParametersToCustomData(currentPayload);
916
921
  const payloadToSend = yield [
917
922
  cleanPayloadStep,
918
923
  validateParams,
@@ -1078,13 +1083,30 @@ class CoveoAnalyticsClient {
1078
1083
  }
1079
1084
  processCustomParameters(payload) {
1080
1085
  const { custom } = payload, rest = __rest(payload, ["custom"]);
1081
- const lowercasedCustom = this.lowercaseKeys(custom);
1086
+ let lowercasedCustom = {};
1087
+ if (custom && isObject(custom)) {
1088
+ lowercasedCustom = this.lowercaseKeys(custom);
1089
+ }
1082
1090
  const newPayload = convertCustomMeasurementProtocolKeys(rest);
1083
1091
  return Object.assign(Object.assign({}, lowercasedCustom), newPayload);
1084
1092
  }
1093
+ mapCustomParametersToCustomData(payload) {
1094
+ const { custom } = payload, rest = __rest(payload, ["custom"]);
1095
+ if (custom && isObject(custom)) {
1096
+ const lowercasedCustom = this.lowercaseKeys(custom);
1097
+ return Object.assign(Object.assign({}, rest), { customData: Object.assign(Object.assign({}, lowercasedCustom), payload.customData) });
1098
+ }
1099
+ else {
1100
+ return payload;
1101
+ }
1102
+ }
1085
1103
  lowercaseKeys(custom) {
1086
- const keys = Object.keys(custom || {});
1087
- return keys.reduce((all, key) => (Object.assign(Object.assign({}, all), { [key.toLowerCase()]: custom[key] })), {});
1104
+ const keys = Object.keys(custom);
1105
+ let result = {};
1106
+ keys.forEach((key) => {
1107
+ result[key.toLowerCase()] = custom[key];
1108
+ });
1109
+ return result;
1088
1110
  }
1089
1111
  validateParams(payload) {
1090
1112
  const { anonymizeIp } = payload, rest = __rest(payload, ["anonymizeIp"]);
@@ -1203,6 +1225,8 @@ var SearchPageEvents;
1203
1225
  SearchPageEvents["showMoreFoldedResults"] = "showMoreFoldedResults";
1204
1226
  SearchPageEvents["showLessFoldedResults"] = "showLessFoldedResults";
1205
1227
  SearchPageEvents["copyToClipboard"] = "copyToClipboard";
1228
+ SearchPageEvents["caseAttach"] = "caseAttach";
1229
+ SearchPageEvents["caseDetach"] = "caseDetach";
1206
1230
  })(SearchPageEvents || (SearchPageEvents = {}));
1207
1231
  const CustomEventsTypes = {
1208
1232
  [SearchPageEvents.triggerNotify]: 'queryPipelineTriggers',
@@ -1238,6 +1262,7 @@ const CustomEventsTypes = {
1238
1262
  [SearchPageEvents.clearRecentResults]: 'recentlyClickedDocuments',
1239
1263
  [SearchPageEvents.showLessFoldedResults]: 'folding',
1240
1264
  [InsightEvents.expandToFullUI]: 'interface',
1265
+ [SearchPageEvents.caseDetach]: 'case',
1241
1266
  };
1242
1267
 
1243
1268
  class NoopAnalytics {
@@ -2446,6 +2471,17 @@ class CoveoInsightClient {
2446
2471
  };
2447
2472
  return this.logClickEvent(SearchPageEvents.documentQuickview, info, identifier, caseMetadata ? Object.assign(Object.assign({}, generateMetadataToSend(caseMetadata, false)), metadata) : metadata);
2448
2473
  }
2474
+ logCaseAttach(info, identifier, caseMetadata) {
2475
+ const metadata = {
2476
+ documentTitle: info.documentTitle,
2477
+ documentURL: info.documentUrl,
2478
+ resultUriHash: info.documentUriHash,
2479
+ };
2480
+ return this.logClickEvent(SearchPageEvents.caseAttach, info, identifier, caseMetadata ? Object.assign(Object.assign({}, generateMetadataToSend(caseMetadata, false)), metadata) : metadata);
2481
+ }
2482
+ logCaseDetach(resultUriHash, metadata) {
2483
+ return this.logCustomEvent(SearchPageEvents.caseDetach, metadata ? Object.assign(Object.assign({}, generateMetadataToSend(metadata, false)), { resultUriHash }) : { resultUriHash });
2484
+ }
2449
2485
  logCustomEvent(event, metadata) {
2450
2486
  return __awaiter(this, void 0, void 0, function* () {
2451
2487
  const customData = Object.assign(Object.assign({}, this.provider.getBaseMetadata()), metadata);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coveo.analytics",
3
- "version": "2.23.7",
3
+ "version": "2.23.9",
4
4
  "description": "📈 Coveo analytics client (node and browser compatible) ",
5
5
  "main": "dist/library.js",
6
6
  "module": "dist/library.es.js",
@@ -34,6 +34,7 @@ import {isApiKey} from './token';
34
34
  import {isReactNative, ReactNativeRuntimeWarning} from '../react-native/react-native-utils';
35
35
  import {doNotTrack} from '../donottrack';
36
36
  import {NullStorage} from '../storage';
37
+ import {isObject} from './utils';
37
38
 
38
39
  export const Version = 'v15';
39
40
 
@@ -294,7 +295,9 @@ export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider
294
295
  const removeUnknownParameters: ProcessPayloadStep = (currentPayload) =>
295
296
  usesMeasurementProtocol ? this.removeUnknownParameters(currentPayload) : currentPayload;
296
297
  const processCustomParameters: ProcessPayloadStep = (currentPayload) =>
297
- usesMeasurementProtocol ? this.processCustomParameters(currentPayload) : currentPayload;
298
+ usesMeasurementProtocol
299
+ ? this.processCustomParameters(currentPayload)
300
+ : this.mapCustomParametersToCustomData(currentPayload);
298
301
 
299
302
  const payloadToSend = await [
300
303
  cleanPayloadStep,
@@ -489,8 +492,10 @@ export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider
489
492
 
490
493
  private processCustomParameters(payload: IRequestPayload): IRequestPayload {
491
494
  const {custom, ...rest} = payload;
492
-
493
- const lowercasedCustom = this.lowercaseKeys(custom);
495
+ let lowercasedCustom = {};
496
+ if (custom && isObject(custom)) {
497
+ lowercasedCustom = this.lowercaseKeys(custom);
498
+ }
494
499
 
495
500
  const newPayload = convertCustomMeasurementProtocolKeys(rest);
496
501
 
@@ -500,16 +505,23 @@ export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider
500
505
  };
501
506
  }
502
507
 
503
- private lowercaseKeys(custom: any) {
504
- const keys = Object.keys(custom || {});
508
+ private mapCustomParametersToCustomData(payload: IRequestPayload): IRequestPayload {
509
+ const {custom, ...rest} = payload;
510
+ if (custom && isObject(custom)) {
511
+ const lowercasedCustom = this.lowercaseKeys(custom);
512
+ return {...rest, customData: {...lowercasedCustom, ...payload.customData}};
513
+ } else {
514
+ return payload;
515
+ }
516
+ }
505
517
 
506
- return keys.reduce(
507
- (all, key) => ({
508
- ...all,
509
- [key.toLowerCase()]: custom[key],
510
- }),
511
- {}
512
- );
518
+ private lowercaseKeys(custom: Record<string, unknown>) {
519
+ const keys = Object.keys(custom);
520
+ let result: Record<string, unknown> = {};
521
+ keys.forEach((key) => {
522
+ result[key.toLowerCase() as string] = custom[key];
523
+ });
524
+ return result;
513
525
  }
514
526
 
515
527
  private validateParams(payload: IRequestPayload): IRequestPayload {
@@ -1,3 +1,6 @@
1
1
  // Object.keys returns `string[]` this adds types
2
2
  // see https://github.com/microsoft/TypeScript/pull/12253#issuecomment-393954723
3
3
  export const keysOf = Object.keys as <T>(o: T) => Extract<keyof T, string>[];
4
+ export function isObject(o: any): boolean {
5
+ return o !== null && typeof o === 'object' && !Array.isArray(o);
6
+ }
@@ -38,7 +38,7 @@ export class Plugins {
38
38
  }
39
39
  const actionFunction = plugin[fn];
40
40
  if (!actionFunction) {
41
- throw new Error(`The function "${fn}" does not exists on the plugin "${name}".`);
41
+ throw new Error(`The function "${fn}" does not exist on the plugin "${name}".`);
42
42
  }
43
43
  if (typeof actionFunction !== 'function') {
44
44
  throw new Error(`"${fn}" of the plugin "${name}" is not a function.`);