@elliemae/pui-app-sdk 5.13.5 → 5.14.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/cjs/index.js CHANGED
@@ -80,6 +80,7 @@ __export(lib_exports, {
80
80
  createManager: () => import_redux_injectors.createManager,
81
81
  createSideEffect: () => import_listenerMiddleware.createSideEffect,
82
82
  enableReactAppForHostIntegration: () => import_react2.enableReactAppForHostIntegration,
83
+ endSession: () => import_auth.endSession,
83
84
  error: () => import_error.actions,
84
85
  errorMiddleware: () => import_errorMiddleware.errorMiddleware,
85
86
  fetchHostAppData: () => import_fetch_host_app_data.fetchHostAppData,
@@ -98,6 +99,7 @@ __export(lib_exports, {
98
99
  getStore: () => import_store3.getStore,
99
100
  globalConstants: () => import_constants.default,
100
101
  history: () => import_history.browserHistory,
102
+ httpClientProps: () => import_props.httpClientProps,
101
103
  initServiceWorker: () => import_service_worker.initServiceWorker,
102
104
  isCIBuild: () => import_helpers.isCIBuild,
103
105
  isProd: () => import_helpers.isProd,
@@ -151,6 +153,7 @@ module.exports = __toCommonJS(lib_exports);
151
153
  var import_auth = require("./utils/auth/index.js");
152
154
  var import_loginParams = require("./utils/auth/loginParams.js");
153
155
  var import_http_client = require("./communication/http-client/index.js");
156
+ var import_props = require("./communication/http-client/props.js");
154
157
  var import_baseQuery = require("./communication/http-client/baseQuery.js");
155
158
  var import_response_interceptor = require("./communication/http-client/response-interceptor.js");
156
159
  var import_actions = require("./data/auth/actions.js");
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var headSampler_exports = {};
20
+ __export(headSampler_exports, {
21
+ HeadSampler: () => HeadSampler
22
+ });
23
+ module.exports = __toCommonJS(headSampler_exports);
24
+ const normalize = (percent) => {
25
+ if (typeof percent !== "number" || Number.isNaN(percent)) return 0;
26
+ if (percent >= 100) return 100;
27
+ if (percent <= 0) return 0;
28
+ return percent;
29
+ };
30
+ const convertToDivisibleBy5 = (percent) => Math.round(normalize(percent) / 5) * 5;
31
+ const percentToFraction = (percent) => {
32
+ const numerator = percent;
33
+ const denominator = 100;
34
+ const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
35
+ const divisor = gcd(numerator, denominator);
36
+ return { numerator: numerator / divisor, denominator: denominator / divisor };
37
+ };
38
+ class HeadSampler {
39
+ /**
40
+ * Upper bound of the sampling size
41
+ */
42
+ #upperBound = 0;
43
+ /**
44
+ * Total size of the sampling
45
+ */
46
+ #totalSize = 0;
47
+ /**
48
+ * Number of events sampled
49
+ */
50
+ #sampled = 0;
51
+ /**
52
+ * Creates new instance of HeadSampler
53
+ * @param samplingPercent sampling percentage
54
+ */
55
+ constructor(samplingPercent) {
56
+ const value = percentToFraction(convertToDivisibleBy5(samplingPercent));
57
+ this.#upperBound = value.numerator;
58
+ this.#totalSize = value.denominator;
59
+ }
60
+ /**
61
+ * check if the event should be sampled
62
+ * @returns true if the event should be sampled
63
+ */
64
+ shouldSample = () => {
65
+ this.#sampled += 1;
66
+ if (this.#sampled <= this.#upperBound) return true;
67
+ if (this.#sampled === this.#totalSize) this.#sampled = 0;
68
+ return false;
69
+ };
70
+ }
@@ -62,7 +62,7 @@ class CMicroAppHost {
62
62
  };
63
63
  this.activeGuests = {};
64
64
  this.#ssfHostRef = params?.ssfHostRef || null;
65
- const analyticsObj = params?.analytics ?? new import_analytics.Analytics(this.logger);
65
+ const analyticsObj = params?.analytics ?? new import_analytics.Analytics({ logger: this.logger });
66
66
  this.scriptingObjects = {
67
67
  analytics: analyticsObj,
68
68
  ...params?.scriptingObjects ?? {}
@@ -34,20 +34,41 @@ module.exports = __toCommonJS(analytics_exports);
34
34
  var import_em_ssf_host = __toESM(require("@elliemae/em-ssf-host"));
35
35
  var import_web_analytics = require("./web-analytics.js");
36
36
  var import_helpers = require("../../helpers.js");
37
+ var import_headSampler = require("../../headSampler.js");
37
38
  class Analytics extends import_em_ssf_host.default.ScriptingObject {
38
39
  /**
39
40
  * logger instance
40
41
  */
41
42
  #logger;
43
+ /**
44
+ * sampling size for different events
45
+ */
46
+ #samplingSizes = {};
42
47
  /**
43
48
  * Creates new instance of Analytics scripting object
44
- * @param logger instance of PUI Diagnostics logger
49
+ * @param params Analytics constructor parameters
45
50
  */
46
- constructor(logger) {
51
+ constructor(params) {
47
52
  super("analytics");
48
- this.#logger = logger;
53
+ this.#logger = params.logger;
54
+ this.#setupSampling(params.samplingRatios);
49
55
  this.#monitorPerformance();
50
56
  }
57
+ /**
58
+ * setup sampling size for different events
59
+ * @param samplingSizes sampling sizes for different events
60
+ */
61
+ #setupSampling = (samplingSizes = {}) => {
62
+ Object.keys(samplingSizes).forEach((key) => {
63
+ this.#samplingSizes[key] = new import_headSampler.HeadSampler(samplingSizes[key]);
64
+ });
65
+ };
66
+ /**
67
+ * check if the event should be sampled and recorded
68
+ * @param name name of the event
69
+ * @returns true if the event should be sampled and recorded
70
+ */
71
+ #shouldSampleandRecord = (name) => this.#samplingSizes[name] ? this.#samplingSizes[name].shouldSample() : true;
51
72
  /**
52
73
  * monitor performance and report to GTM
53
74
  */
@@ -57,18 +78,28 @@ class Analytics extends import_em_ssf_host.default.ScriptingObject {
57
78
  for (const entry of list.getEntries()) {
58
79
  switch (entry.entryType) {
59
80
  case "measure": {
81
+ if (!this.#shouldSampleandRecord(entry.name)) return;
60
82
  const detail = entry.detail ?? {};
83
+ const duration = entry.duration.toString();
84
+ const startTime = new Date(
85
+ performance.timeOrigin + entry.startTime
86
+ ).toISOString();
61
87
  this.sendBAEvent({
62
88
  event: "timing",
63
89
  name: entry.name,
64
- duration: entry.duration.toString(),
65
- startTime: new Date(
66
- performance.timeOrigin + entry.startTime
67
- ).toISOString(),
90
+ duration,
91
+ startTime,
68
92
  ...(0, import_web_analytics.getBAEventParameters)(),
69
93
  ...detail
70
94
  }).catch(() => {
71
95
  });
96
+ this.#logger.info({
97
+ message: "timing",
98
+ event: entry.name,
99
+ duration,
100
+ startTime,
101
+ detail
102
+ });
72
103
  break;
73
104
  }
74
105
  default:
package/dist/esm/index.js CHANGED
@@ -1,9 +1,15 @@
1
- import { isUserAuthorized, login, authorize } from "./utils/auth/index.js";
1
+ import {
2
+ isUserAuthorized,
3
+ login,
4
+ authorize,
5
+ endSession
6
+ } from "./utils/auth/index.js";
2
7
  import { setLoginParams } from "./utils/auth/loginParams.js";
3
8
  import {
4
9
  getHTTPClient,
5
10
  getAuthHTTPClient
6
11
  } from "./communication/http-client/index.js";
12
+ import { httpClientProps } from "./communication/http-client/props.js";
7
13
  import { sdkBaseQuery } from "./communication/http-client/baseQuery.js";
8
14
  import { onAuthorizationFailure } from "./communication/http-client/response-interceptor.js";
9
15
  import { auth } from "./data/auth/actions.js";
@@ -186,6 +192,7 @@ export {
186
192
  createManager,
187
193
  createSideEffect,
188
194
  enableReactAppForHostIntegration,
195
+ endSession,
189
196
  actions2 as error,
190
197
  errorMiddleware,
191
198
  fetchHostAppData,
@@ -204,6 +211,7 @@ export {
204
211
  getStore,
205
212
  default2 as globalConstants,
206
213
  browserHistory as history,
214
+ httpClientProps,
207
215
  initServiceWorker,
208
216
  isCIBuild,
209
217
  isProd,
@@ -0,0 +1,50 @@
1
+ const normalize = (percent) => {
2
+ if (typeof percent !== "number" || Number.isNaN(percent)) return 0;
3
+ if (percent >= 100) return 100;
4
+ if (percent <= 0) return 0;
5
+ return percent;
6
+ };
7
+ const convertToDivisibleBy5 = (percent) => Math.round(normalize(percent) / 5) * 5;
8
+ const percentToFraction = (percent) => {
9
+ const numerator = percent;
10
+ const denominator = 100;
11
+ const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
12
+ const divisor = gcd(numerator, denominator);
13
+ return { numerator: numerator / divisor, denominator: denominator / divisor };
14
+ };
15
+ class HeadSampler {
16
+ /**
17
+ * Upper bound of the sampling size
18
+ */
19
+ #upperBound = 0;
20
+ /**
21
+ * Total size of the sampling
22
+ */
23
+ #totalSize = 0;
24
+ /**
25
+ * Number of events sampled
26
+ */
27
+ #sampled = 0;
28
+ /**
29
+ * Creates new instance of HeadSampler
30
+ * @param samplingPercent sampling percentage
31
+ */
32
+ constructor(samplingPercent) {
33
+ const value = percentToFraction(convertToDivisibleBy5(samplingPercent));
34
+ this.#upperBound = value.numerator;
35
+ this.#totalSize = value.denominator;
36
+ }
37
+ /**
38
+ * check if the event should be sampled
39
+ * @returns true if the event should be sampled
40
+ */
41
+ shouldSample = () => {
42
+ this.#sampled += 1;
43
+ if (this.#sampled <= this.#upperBound) return true;
44
+ if (this.#sampled === this.#totalSize) this.#sampled = 0;
45
+ return false;
46
+ };
47
+ }
48
+ export {
49
+ HeadSampler
50
+ };
@@ -46,7 +46,7 @@ class CMicroAppHost {
46
46
  };
47
47
  this.activeGuests = {};
48
48
  this.#ssfHostRef = params?.ssfHostRef || null;
49
- const analyticsObj = params?.analytics ?? new Analytics(this.logger);
49
+ const analyticsObj = params?.analytics ?? new Analytics({ logger: this.logger });
50
50
  this.scriptingObjects = {
51
51
  analytics: analyticsObj,
52
52
  ...params?.scriptingObjects ?? {}
@@ -1,20 +1,41 @@
1
1
  import ssfHost from "@elliemae/em-ssf-host";
2
2
  import { getBAEventParameters } from "./web-analytics.js";
3
3
  import { getProductAppDetails } from "../../helpers.js";
4
+ import { HeadSampler } from "../../headSampler.js";
4
5
  class Analytics extends ssfHost.ScriptingObject {
5
6
  /**
6
7
  * logger instance
7
8
  */
8
9
  #logger;
10
+ /**
11
+ * sampling size for different events
12
+ */
13
+ #samplingSizes = {};
9
14
  /**
10
15
  * Creates new instance of Analytics scripting object
11
- * @param logger instance of PUI Diagnostics logger
16
+ * @param params Analytics constructor parameters
12
17
  */
13
- constructor(logger) {
18
+ constructor(params) {
14
19
  super("analytics");
15
- this.#logger = logger;
20
+ this.#logger = params.logger;
21
+ this.#setupSampling(params.samplingRatios);
16
22
  this.#monitorPerformance();
17
23
  }
24
+ /**
25
+ * setup sampling size for different events
26
+ * @param samplingSizes sampling sizes for different events
27
+ */
28
+ #setupSampling = (samplingSizes = {}) => {
29
+ Object.keys(samplingSizes).forEach((key) => {
30
+ this.#samplingSizes[key] = new HeadSampler(samplingSizes[key]);
31
+ });
32
+ };
33
+ /**
34
+ * check if the event should be sampled and recorded
35
+ * @param name name of the event
36
+ * @returns true if the event should be sampled and recorded
37
+ */
38
+ #shouldSampleandRecord = (name) => this.#samplingSizes[name] ? this.#samplingSizes[name].shouldSample() : true;
18
39
  /**
19
40
  * monitor performance and report to GTM
20
41
  */
@@ -24,18 +45,28 @@ class Analytics extends ssfHost.ScriptingObject {
24
45
  for (const entry of list.getEntries()) {
25
46
  switch (entry.entryType) {
26
47
  case "measure": {
48
+ if (!this.#shouldSampleandRecord(entry.name)) return;
27
49
  const detail = entry.detail ?? {};
50
+ const duration = entry.duration.toString();
51
+ const startTime = new Date(
52
+ performance.timeOrigin + entry.startTime
53
+ ).toISOString();
28
54
  this.sendBAEvent({
29
55
  event: "timing",
30
56
  name: entry.name,
31
- duration: entry.duration.toString(),
32
- startTime: new Date(
33
- performance.timeOrigin + entry.startTime
34
- ).toISOString(),
57
+ duration,
58
+ startTime,
35
59
  ...getBAEventParameters(),
36
60
  ...detail
37
61
  }).catch(() => {
38
62
  });
63
+ this.#logger.info({
64
+ message: "timing",
65
+ event: entry.name,
66
+ duration,
67
+ startTime,
68
+ detail
69
+ });
39
70
  break;
40
71
  }
41
72
  default:
@@ -1,6 +1,7 @@
1
- export { isUserAuthorized, login, authorize } from './utils/auth/index.js';
1
+ export { isUserAuthorized, login, authorize, endSession, } from './utils/auth/index.js';
2
2
  export { setLoginParams } from './utils/auth/loginParams.js';
3
3
  export { getHTTPClient, getAuthHTTPClient, } from './communication/http-client/index.js';
4
+ export { httpClientProps } from './communication/http-client/props.js';
4
5
  export { sdkBaseQuery } from './communication/http-client/baseQuery.js';
5
6
  export { onAuthorizationFailure } from './communication/http-client/response-interceptor.js';
6
7
  export { auth } from './data/auth/actions.js';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Samples events based on the sampling size
3
+ */
4
+ export declare class HeadSampler {
5
+ #private;
6
+ /**
7
+ * Creates new instance of HeadSampler
8
+ * @param samplingPercent sampling percentage
9
+ */
10
+ constructor(samplingPercent: number);
11
+ /**
12
+ * check if the event should be sampled
13
+ * @returns true if the event should be sampled
14
+ */
15
+ shouldSample: () => boolean;
16
+ }
@@ -2,8 +2,9 @@ import { History, To } from 'history';
2
2
  import { DefaultTheme } from 'styled-components';
3
3
  import { IMicroAppHost, ResizeEventHandler, BreakpointChangeEventHandler, SubscriptionListener } from '@elliemae/pui-micro-frontend-base';
4
4
  import ssfHost from '@elliemae/em-ssf-host';
5
- import { BAEvent, IAnalytics } from '@elliemae/pui-scripting-object';
5
+ import { BAEvent } from '@elliemae/pui-scripting-object';
6
6
  import { MicroFrontEndLogger } from '../types.js';
7
+ import { Analytics } from './scripting-objects/analytics.js';
7
8
  type HostOptions = {
8
9
  systemVersion: string;
9
10
  history: History;
@@ -19,7 +20,7 @@ type ConstructorParams = {
19
20
  onRenewSessionTimer?: () => void;
20
21
  onInit?: OnInitCallback;
21
22
  ssfHostRef?: typeof ssfHost.Host;
22
- analytics?: IAnalytics;
23
+ analytics?: Analytics;
23
24
  };
24
25
  export declare class CMicroAppHost implements IMicroAppHost {
25
26
  #private;
@@ -1,6 +1,21 @@
1
1
  import ssfHost from '@elliemae/em-ssf-host';
2
2
  import { IAnalytics, BAEvent, TimingOptions } from '@elliemae/pui-scripting-object';
3
3
  import { MicroFrontEndLogger } from '../../types.js';
4
+ /**
5
+ * Analytics constructor parameters
6
+ */
7
+ type AnalyticsParams = {
8
+ /**
9
+ * logger instance
10
+ */
11
+ logger: MicroFrontEndLogger;
12
+ /**
13
+ * sampling ratios for different events
14
+ * ratio is a number between 0 and 1
15
+ * @example { 'event1': 0.1, 'event2': 0.5 }
16
+ */
17
+ samplingRatios?: Record<string, number>;
18
+ };
4
19
  /**
5
20
  * Analytics scripting object
6
21
  */
@@ -8,9 +23,9 @@ export declare class Analytics extends ssfHost.ScriptingObject implements IAnaly
8
23
  #private;
9
24
  /**
10
25
  * Creates new instance of Analytics scripting object
11
- * @param logger instance of PUI Diagnostics logger
26
+ * @param params Analytics constructor parameters
12
27
  */
13
- constructor(logger: MicroFrontEndLogger);
28
+ constructor(params: AnalyticsParams);
14
29
  /**
15
30
  * send business analytics event
16
31
  * @param event business analytics event
@@ -43,3 +58,4 @@ export declare class Analytics extends ssfHost.ScriptingObject implements IAnaly
43
58
  */
44
59
  endTiming: (start: string | PerformanceMeasure, options: TimingOptions) => Promise<void>;
45
60
  }
61
+ export {};