@elliemae/pui-app-sdk 5.30.3 → 5.31.0-beta.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.
Files changed (32) hide show
  1. package/dist/cjs/utils/micro-frontend/guest.js +19 -4
  2. package/dist/cjs/utils/micro-frontend/host.js +15 -5
  3. package/dist/cjs/utils/micro-frontend/scripting-objects/analytics.js +2 -2
  4. package/dist/cjs/utils/micro-frontend/ssf-host.js +44 -0
  5. package/dist/cjs/view/guest-microapp.js +59 -29
  6. package/dist/cjs/view/tests/__snapshots__/guest-microapp.test.tsx.snap +16 -0
  7. package/dist/cjs/view/tests/app.config.json +11 -0
  8. package/dist/cjs/view/tests/constants.js +2 -0
  9. package/dist/cjs/view/tests/serverHandlers.js +15 -0
  10. package/dist/cjs/view/tests/ssfapp/index.html +14 -0
  11. package/dist/cjs/view/tests/ssfapp/latest/index.js +16 -0
  12. package/dist/cjs/view/tests/ssfapp/latest/manifest.json +3 -0
  13. package/dist/esm/utils/micro-frontend/guest.js +19 -4
  14. package/dist/esm/utils/micro-frontend/host.js +15 -5
  15. package/dist/esm/utils/micro-frontend/scripting-objects/analytics.js +2 -2
  16. package/dist/esm/utils/micro-frontend/ssf-host.js +24 -0
  17. package/dist/esm/view/guest-microapp.js +64 -31
  18. package/dist/esm/view/tests/__snapshots__/guest-microapp.test.tsx.snap +16 -0
  19. package/dist/esm/view/tests/app.config.json +11 -0
  20. package/dist/esm/view/tests/constants.js +2 -0
  21. package/dist/esm/view/tests/serverHandlers.js +15 -0
  22. package/dist/esm/view/tests/ssfapp/index.html +14 -0
  23. package/dist/esm/view/tests/ssfapp/latest/index.js +15 -0
  24. package/dist/esm/view/tests/ssfapp/latest/manifest.json +3 -0
  25. package/dist/types/lib/utils/micro-frontend/guest.d.ts +6 -3
  26. package/dist/types/lib/utils/micro-frontend/host.d.ts +1 -1
  27. package/dist/types/lib/utils/micro-frontend/ssf-host.d.ts +5 -0
  28. package/dist/types/lib/utils/micro-frontend/types.d.ts +4 -0
  29. package/dist/types/lib/view/tests/constants.d.ts +1 -0
  30. package/dist/types/lib/view/tests/ssfapp/latest/index.d.ts +2 -0
  31. package/dist/types/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +44 -44
@@ -46,6 +46,7 @@ var import_web_analytics = require("./scripting-objects/web-analytics.js");
46
46
  var import_logrocket = require("./scripting-objects/logrocket.js");
47
47
  var import_app_bridge = require("./app-bridge.js");
48
48
  var import_helpers = require("../helpers.js");
49
+ var import_ssf_host2 = require("./ssf-host.js");
49
50
  const isCrossDomain = () => {
50
51
  try {
51
52
  window.parent.document;
@@ -77,6 +78,10 @@ class CMicroAppGuest {
77
78
  * communication method used between microapps
78
79
  */
79
80
  #communicationMethod;
81
+ /**
82
+ * reference to SSFHost instance
83
+ */
84
+ #ssfHostRef;
80
85
  /**
81
86
  * AppBridge instance
82
87
  */
@@ -104,6 +109,8 @@ class CMicroAppGuest {
104
109
  (0, import_logger.setLogger)(this.logger);
105
110
  this.#logRocket = params?.logRocket ?? window.emui?.logRocket;
106
111
  (0, import_logrocket.setLogRocket)(this.#logRocket);
112
+ if (params?.ssfHostRef) (0, import_ssf_host2.setSSFHost)(params.ssfHostRef);
113
+ this.#ssfHostRef = (0, import_ssf_host2.getSSFHost)();
107
114
  this.onInit = params?.onInit;
108
115
  this.onMount = params?.onMount;
109
116
  this.onUnmount = params?.onUnmount;
@@ -317,15 +324,22 @@ class CMicroAppGuest {
317
324
  if (this.#appBridge) {
318
325
  this.#appBridge.addScriptingObject(so, params);
319
326
  }
327
+ this.#ssfHostRef.addScriptingObject(so, params);
320
328
  }
321
329
  /**
322
- * dispatch event to child microapp
323
- * @param {DispatchEventParams<EventId, Params>} params - event parameters
330
+ * Dispatches an event to the child microapp.
331
+ * @param {DispatchEventParam<EventId, Params, Options>} params - Event parameters.
332
+ * @returns {Promise<any[]>} A promise that resolves with the combined results of dispatched events.
324
333
  */
325
334
  async dispatchEvent(params) {
326
- if (this.#appBridge) {
327
- await this.#appBridge.dispatchEvent(params);
335
+ const [appBridgeResult, ssfResult] = await Promise.all([
336
+ this.#appBridge ? this.#appBridge.dispatchEvent(params) : Promise.resolve(null),
337
+ this.#ssfHostRef.dispatchEvent(params)
338
+ ]);
339
+ if (Array.isArray(appBridgeResult) && Array.isArray(ssfResult)) {
340
+ return appBridgeResult.concat(ssfResult);
328
341
  }
342
+ return Promise.resolve();
329
343
  }
330
344
  /**
331
345
  * removes scripting object from child microapp use
@@ -335,5 +349,6 @@ class CMicroAppGuest {
335
349
  if (this.#appBridge) {
336
350
  this.#appBridge.removeScriptingObject(objectId);
337
351
  }
352
+ this.#ssfHostRef.removeScriptingObject(objectId);
338
353
  }
339
354
  }
@@ -40,6 +40,7 @@ var import_analytics = require("./scripting-objects/analytics.js");
40
40
  var import_web_analytics = require("./scripting-objects/web-analytics.js");
41
41
  var import_session = require("../session.js");
42
42
  var import_app_bridge = require("./app-bridge.js");
43
+ var import_ssf_host2 = require("./ssf-host.js");
43
44
  class CMicroAppHost {
44
45
  static instance;
45
46
  logger;
@@ -71,14 +72,16 @@ class CMicroAppHost {
71
72
  theme: params?.theme ?? (0, import_pui_theme.getDefaultTheme)()
72
73
  };
73
74
  this.activeGuests = {};
74
- this.#ssfHostRef = params?.ssfHostRef || null;
75
+ if (params?.ssfHostRef) (0, import_ssf_host2.setSSFHost)(params.ssfHostRef);
76
+ this.#ssfHostRef = (0, import_ssf_host2.getSSFHost)();
75
77
  const analyticsObj = params?.analytics ?? new import_analytics.Analytics({ logger: this.logger });
76
78
  this.scriptingObjects = {
77
79
  analytics: analyticsObj,
78
80
  ...params?.scriptingObjects ?? {}
79
81
  };
80
- this.#ssfHostRef?.publish?.(analyticsObj);
81
- this.#ssfHostRef?.addScriptingObject?.(analyticsObj);
82
+ this.#ssfHostRef.addScriptingObject(
83
+ analyticsObj
84
+ );
82
85
  this.getProps = this.getProps.bind(this);
83
86
  this.getLogger = this.getLogger.bind(this);
84
87
  this.getGuests = this.getGuests.bind(this);
@@ -213,15 +216,21 @@ class CMicroAppHost {
213
216
  if (this.#appBridge) {
214
217
  this.#appBridge.addScriptingObject(so, params);
215
218
  }
219
+ this.#ssfHostRef.addScriptingObject(so, params);
216
220
  }
217
221
  /**
218
222
  * dispatch event to child microapp
219
223
  * @param {DispatchEventParams<EventId, Params>} params - event parameters
220
224
  */
221
225
  async dispatchEvent(params) {
222
- if (this.#appBridge) {
223
- await this.#appBridge.dispatchEvent(params);
226
+ const [appBridgeResult, ssfResult] = await Promise.all([
227
+ this.#appBridge ? this.#appBridge.dispatchEvent(params) : Promise.resolve(null),
228
+ this.#ssfHostRef.dispatchEvent(params)
229
+ ]);
230
+ if (Array.isArray(appBridgeResult) && Array.isArray(ssfResult)) {
231
+ return appBridgeResult.concat(ssfResult);
224
232
  }
233
+ return Promise.resolve();
225
234
  }
226
235
  /**
227
236
  * removes scripting object from child microapp use
@@ -231,5 +240,6 @@ class CMicroAppHost {
231
240
  if (this.#appBridge) {
232
241
  this.#appBridge.removeScriptingObject(objectId);
233
242
  }
243
+ this.#ssfHostRef.removeScriptingObject(objectId);
234
244
  }
235
245
  }
@@ -140,8 +140,8 @@ class Analytics extends import_ssf_host.ScriptingObject {
140
140
  throw new Error("parameter options is required");
141
141
  const startMark = performance.mark(name, { detail: options });
142
142
  return Promise.resolve({
143
- name: startMark.name,
144
- startTime: startMark.startTime
143
+ name: startMark?.name,
144
+ startTime: startMark?.startTime
145
145
  });
146
146
  };
147
147
  /**
@@ -0,0 +1,44 @@
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 ssf_host_exports = {};
20
+ __export(ssf_host_exports, {
21
+ getSSFHost: () => getSSFHost,
22
+ setSSFHost: () => setSSFHost
23
+ });
24
+ module.exports = __toCommonJS(ssf_host_exports);
25
+ var import_ssf_host = require("@elliemae/ssf-host");
26
+ var import_logger = require("../logger.js");
27
+ var import_config = require("../app-config/config.js");
28
+ var import_analytics = require("./scripting-objects/analytics.js");
29
+ let ssfHost = null;
30
+ const getSSFHost = () => {
31
+ if (!ssfHost) {
32
+ const logger = (0, import_logger.getLogger)();
33
+ ssfHost = new import_ssf_host.SSFHost((0, import_config.getAppConfigValue)("appId"), {
34
+ logger,
35
+ analyticsObj: new import_analytics.Analytics({ logger })
36
+ });
37
+ }
38
+ return ssfHost;
39
+ };
40
+ const setSSFHost = (host) => {
41
+ if (!ssfHost) {
42
+ ssfHost = host;
43
+ }
44
+ };
@@ -36,6 +36,7 @@ var import_react = require("react");
36
36
  var import_styled_components = __toESM(require("styled-components"));
37
37
  var import_react_redux = require("react-redux");
38
38
  var import_app_bridge = require("../utils/micro-frontend/app-bridge.js");
39
+ var import_ssf_host2 = require("../utils/micro-frontend/ssf-host.js");
39
40
  var import_actions = require("../data/wait-message/actions.js");
40
41
  var import_micro_frontend = require("../utils/micro-frontend/index.js");
41
42
  const Div = import_styled_components.default.div`
@@ -56,32 +57,56 @@ const useAppRenderer = (props) => {
56
57
  containerId
57
58
  } = props;
58
59
  const dispatch = (0, import_react_redux.useDispatch)();
60
+ const getConfig = (0, import_react.useCallback)(
61
+ () => (0, import_micro_frontend.getMicroFrontEndAppConfig)({
62
+ id
63
+ }),
64
+ [id]
65
+ );
59
66
  (0, import_react.useLayoutEffect)(() => {
60
67
  let isMounted = true;
61
68
  let appBridge = null;
69
+ let ssfHost = null;
62
70
  let unloadInProgress = Promise.resolve();
63
71
  let instanceId = null;
64
72
  (async () => {
65
73
  await unloadInProgress;
66
74
  dispatch(import_actions.waitMessage.open());
67
75
  try {
68
- appBridge = await (0, import_app_bridge.getAppBridge)();
69
- if (!appBridge)
70
- throw new Error(`Failed to load ${id}, AppBridge not initialized`);
71
- if (isMounted) {
72
- instanceId = await appBridge.openApp({
73
- id,
74
- frameOptions: { containerId },
75
- history,
76
- homeRoute,
77
- initialRoute
78
- });
79
- setTimeout(() => {
80
- try {
81
- onLoadComplete?.(instanceId);
82
- } catch (ex) {
83
- }
84
- }, 0);
76
+ const { ssfOnly, hostUrl, name } = getConfig();
77
+ if (ssfOnly) {
78
+ ssfHost = (0, import_ssf_host2.getSSFHost)();
79
+ if (!ssfHost)
80
+ throw new Error(`Failed to load ${id}, SSFHost not initialized`);
81
+ if (isMounted) {
82
+ const guest = ssfHost.loadGuest({
83
+ id,
84
+ url: hostUrl,
85
+ title: name,
86
+ targetElement: document.getElementById(containerId),
87
+ onLoad: onLoadComplete
88
+ });
89
+ instanceId = guest.id;
90
+ }
91
+ } else {
92
+ appBridge = await (0, import_app_bridge.getAppBridge)();
93
+ if (!appBridge)
94
+ throw new Error(`Failed to load ${id}, AppBridge not initialized`);
95
+ if (isMounted) {
96
+ instanceId = await appBridge.openApp({
97
+ id,
98
+ frameOptions: { containerId },
99
+ history,
100
+ homeRoute,
101
+ initialRoute
102
+ });
103
+ setTimeout(() => {
104
+ try {
105
+ onLoadComplete?.(instanceId);
106
+ } catch (ex) {
107
+ }
108
+ }, 0);
109
+ }
85
110
  }
86
111
  } catch (ex) {
87
112
  (0, import_micro_frontend.getLogger)().error({
@@ -91,6 +116,8 @@ const useAppRenderer = (props) => {
91
116
  isMounted = false;
92
117
  if (appBridge && instanceId)
93
118
  unloadInProgress = appBridge.closeApp(instanceId);
119
+ if (ssfHost && instanceId)
120
+ unloadInProgress = Promise.resolve(ssfHost.unloadGuest(instanceId));
94
121
  throw ex;
95
122
  } finally {
96
123
  dispatch(import_actions.waitMessage.close());
@@ -98,19 +125,21 @@ const useAppRenderer = (props) => {
98
125
  })();
99
126
  return () => {
100
127
  isMounted = false;
101
- if (appBridge) {
128
+ if (ssfHost) {
129
+ unloadInProgress = Promise.resolve(ssfHost.unloadGuest(instanceId));
130
+ } else if (appBridge) {
102
131
  unloadInProgress = appBridge.closeApp(instanceId);
103
- unloadInProgress.then(() => {
104
- instanceId = null;
105
- setTimeout(() => {
106
- try {
107
- onUnloadComplete?.();
108
- } catch (ex) {
109
- }
110
- }, 0);
111
- }).catch(() => {
112
- });
113
132
  }
133
+ unloadInProgress.then(() => {
134
+ instanceId = null;
135
+ setTimeout(() => {
136
+ try {
137
+ onUnloadComplete?.();
138
+ } catch (ex) {
139
+ }
140
+ }, 0);
141
+ }).catch(() => {
142
+ });
114
143
  };
115
144
  }, [
116
145
  containerId,
@@ -120,7 +149,8 @@ const useAppRenderer = (props) => {
120
149
  initialRoute,
121
150
  id,
122
151
  onLoadComplete,
123
- onUnloadComplete
152
+ onUnloadComplete,
153
+ getConfig
124
154
  ]);
125
155
  };
126
156
  const GuestMicroApp = (0, import_react.memo)(
@@ -1,5 +1,21 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`GuestMicroApp with SSFHost should open ssfapp 1`] = `
4
+ "<html lang="en"><head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>SSFApp</title>
8
+ <!-- <script src="https://cdn.mortgagetech.q1.ice.com/ssf-guest"></script> -->
9
+ </head>
10
+ <body>
11
+ <h1>SSF App</h1>
12
+ <output id="output">ssfapp starting
13
+ ssfapp loaded</output>
14
+ <script src="./latest/index.js"></script>
15
+
16
+ </body></html>"
17
+ `;
18
+
3
19
  exports[`MicroAppV2 should open loanapp and call init and mount methods 1`] = `
4
20
  Document {
5
21
  "location": Location {
@@ -15,6 +15,17 @@
15
15
  "files": ["index.js"]
16
16
  }
17
17
  },
18
+ "ssfapp": {
19
+ "name": "SSF App",
20
+ "hostUrl": "./ssfapp",
21
+ "ssfOnly": true,
22
+ "development": {
23
+ "files": ["index.js"]
24
+ },
25
+ "production": {
26
+ "files": ["index.js"]
27
+ }
28
+ },
18
29
  "taskapp": {
19
30
  "name": "Task",
20
31
  "hostUrl": "./task",
@@ -28,12 +28,14 @@ __export(constants_exports, {
28
28
  LOAN_SAVED_EVENT: () => LOAN_SAVED_EVENT,
29
29
  PRE_COMMIT_EVENT: () => PRE_COMMIT_EVENT,
30
30
  RELEASE_VERSION: () => RELEASE_VERSION,
31
+ SSF_APP_ID: () => SSF_APP_ID,
31
32
  TASK_APP_ID: () => TASK_APP_ID
32
33
  });
33
34
  module.exports = __toCommonJS(constants_exports);
34
35
  const LATEST_VERSION = "latest";
35
36
  const RELEASE_VERSION = "23.1.0";
36
37
  const LOAN_APP_ID = "loanapp";
38
+ const SSF_APP_ID = "ssfapp";
37
39
  const TASK_APP_ID = "taskapp";
38
40
  const FLIGHTS_APP_ID = "flights";
39
41
  const HOTELS_APP_ID = "hotels";
@@ -206,5 +206,20 @@ const serverHandlers = [
206
206
  "/loan/latest/manifest.json",
207
207
  (req, res, ctx) => res(ctx.json(import_manifest.default))
208
208
  ),
209
+ import_msw.rest.get("/ssfapp/", async (req, res, ctx) => {
210
+ const fileContent = await (0, import_promises.readFile)(
211
+ import_node_path.default.join(__dirname, "ssfapp/index.html"),
212
+ "utf-8"
213
+ );
214
+ return res(
215
+ ctx.status(200),
216
+ ctx.set("Content-Type", "text/html"),
217
+ ctx.body(fileContent)
218
+ );
219
+ }),
220
+ import_msw.rest.get("/ssfapp/latest/index.js", async (req, res, ctx) => {
221
+ const newRes = await sendJS(res, ctx, "./ssfapp/latest/index.js");
222
+ return newRes;
223
+ }),
209
224
  ...getServerHandlers()
210
225
  ];
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SSFApp</title>
7
+ <!-- <script src="https://cdn.mortgagetech.q1.ice.com/ssf-guest"></script> -->
8
+ </head>
9
+ <body>
10
+ <h1>SSF App</h1>
11
+ <output id="output"></output>
12
+ <script src="./latest/index.js"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ const appId = "ssfapp";
3
+ const output = document.getElementById("output");
4
+ output.textContent = `${appId} starting`;
5
+ window.addEventListener("beforeunload", () => {
6
+ if (output) {
7
+ output.textContent += `
8
+ ${appId} unloading`;
9
+ }
10
+ });
11
+ document.addEventListener("load", () => {
12
+ if (output) {
13
+ output.textContent += `
14
+ ${appId} loaded`;
15
+ }
16
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "index.js": "latest/index.js"
3
+ }
@@ -13,6 +13,7 @@ import { updateBAEventParameters } from "./scripting-objects/web-analytics.js";
13
13
  import { setLogRocket } from "./scripting-objects/logrocket.js";
14
14
  import { getAppBridge } from "./app-bridge.js";
15
15
  import { abortPromise } from "../helpers.js";
16
+ import { getSSFHost, setSSFHost } from "./ssf-host.js";
16
17
  const isCrossDomain = () => {
17
18
  try {
18
19
  window.parent.document;
@@ -44,6 +45,10 @@ class CMicroAppGuest {
44
45
  * communication method used between microapps
45
46
  */
46
47
  #communicationMethod;
48
+ /**
49
+ * reference to SSFHost instance
50
+ */
51
+ #ssfHostRef;
47
52
  /**
48
53
  * AppBridge instance
49
54
  */
@@ -71,6 +76,8 @@ class CMicroAppGuest {
71
76
  setLogger(this.logger);
72
77
  this.#logRocket = params?.logRocket ?? window.emui?.logRocket;
73
78
  setLogRocket(this.#logRocket);
79
+ if (params?.ssfHostRef) setSSFHost(params.ssfHostRef);
80
+ this.#ssfHostRef = getSSFHost();
74
81
  this.onInit = params?.onInit;
75
82
  this.onMount = params?.onMount;
76
83
  this.onUnmount = params?.onUnmount;
@@ -284,15 +291,22 @@ class CMicroAppGuest {
284
291
  if (this.#appBridge) {
285
292
  this.#appBridge.addScriptingObject(so, params);
286
293
  }
294
+ this.#ssfHostRef.addScriptingObject(so, params);
287
295
  }
288
296
  /**
289
- * dispatch event to child microapp
290
- * @param {DispatchEventParams<EventId, Params>} params - event parameters
297
+ * Dispatches an event to the child microapp.
298
+ * @param {DispatchEventParam<EventId, Params, Options>} params - Event parameters.
299
+ * @returns {Promise<any[]>} A promise that resolves with the combined results of dispatched events.
291
300
  */
292
301
  async dispatchEvent(params) {
293
- if (this.#appBridge) {
294
- await this.#appBridge.dispatchEvent(params);
302
+ const [appBridgeResult, ssfResult] = await Promise.all([
303
+ this.#appBridge ? this.#appBridge.dispatchEvent(params) : Promise.resolve(null),
304
+ this.#ssfHostRef.dispatchEvent(params)
305
+ ]);
306
+ if (Array.isArray(appBridgeResult) && Array.isArray(ssfResult)) {
307
+ return appBridgeResult.concat(ssfResult);
295
308
  }
309
+ return Promise.resolve();
296
310
  }
297
311
  /**
298
312
  * removes scripting object from child microapp use
@@ -302,6 +316,7 @@ class CMicroAppGuest {
302
316
  if (this.#appBridge) {
303
317
  this.#appBridge.removeScriptingObject(objectId);
304
318
  }
319
+ this.#ssfHostRef.removeScriptingObject(objectId);
305
320
  }
306
321
  }
307
322
  export {
@@ -25,6 +25,7 @@ import { Analytics } from "./scripting-objects/analytics.js";
25
25
  import { updateBAEventParameters } from "./scripting-objects/web-analytics.js";
26
26
  import { renewSession } from "../session.js";
27
27
  import { getAppBridge } from "./app-bridge.js";
28
+ import { getSSFHost, setSSFHost } from "./ssf-host.js";
28
29
  class CMicroAppHost {
29
30
  static instance;
30
31
  logger;
@@ -56,14 +57,16 @@ class CMicroAppHost {
56
57
  theme: params?.theme ?? getDefaultTheme()
57
58
  };
58
59
  this.activeGuests = {};
59
- this.#ssfHostRef = params?.ssfHostRef || null;
60
+ if (params?.ssfHostRef) setSSFHost(params.ssfHostRef);
61
+ this.#ssfHostRef = getSSFHost();
60
62
  const analyticsObj = params?.analytics ?? new Analytics({ logger: this.logger });
61
63
  this.scriptingObjects = {
62
64
  analytics: analyticsObj,
63
65
  ...params?.scriptingObjects ?? {}
64
66
  };
65
- this.#ssfHostRef?.publish?.(analyticsObj);
66
- this.#ssfHostRef?.addScriptingObject?.(analyticsObj);
67
+ this.#ssfHostRef.addScriptingObject(
68
+ analyticsObj
69
+ );
67
70
  this.getProps = this.getProps.bind(this);
68
71
  this.getLogger = this.getLogger.bind(this);
69
72
  this.getGuests = this.getGuests.bind(this);
@@ -198,15 +201,21 @@ class CMicroAppHost {
198
201
  if (this.#appBridge) {
199
202
  this.#appBridge.addScriptingObject(so, params);
200
203
  }
204
+ this.#ssfHostRef.addScriptingObject(so, params);
201
205
  }
202
206
  /**
203
207
  * dispatch event to child microapp
204
208
  * @param {DispatchEventParams<EventId, Params>} params - event parameters
205
209
  */
206
210
  async dispatchEvent(params) {
207
- if (this.#appBridge) {
208
- await this.#appBridge.dispatchEvent(params);
211
+ const [appBridgeResult, ssfResult] = await Promise.all([
212
+ this.#appBridge ? this.#appBridge.dispatchEvent(params) : Promise.resolve(null),
213
+ this.#ssfHostRef.dispatchEvent(params)
214
+ ]);
215
+ if (Array.isArray(appBridgeResult) && Array.isArray(ssfResult)) {
216
+ return appBridgeResult.concat(ssfResult);
209
217
  }
218
+ return Promise.resolve();
210
219
  }
211
220
  /**
212
221
  * removes scripting object from child microapp use
@@ -216,6 +225,7 @@ class CMicroAppHost {
216
225
  if (this.#appBridge) {
217
226
  this.#appBridge.removeScriptingObject(objectId);
218
227
  }
228
+ this.#ssfHostRef.removeScriptingObject(objectId);
219
229
  }
220
230
  }
221
231
  export {
@@ -117,8 +117,8 @@ class Analytics extends ScriptingObject {
117
117
  throw new Error("parameter options is required");
118
118
  const startMark = performance.mark(name, { detail: options });
119
119
  return Promise.resolve({
120
- name: startMark.name,
121
- startTime: startMark.startTime
120
+ name: startMark?.name,
121
+ startTime: startMark?.startTime
122
122
  });
123
123
  };
124
124
  /**
@@ -0,0 +1,24 @@
1
+ import { SSFHost } from "@elliemae/ssf-host";
2
+ import { getLogger } from "../logger.js";
3
+ import { getAppConfigValue } from "../app-config/config.js";
4
+ import { Analytics } from "./scripting-objects/analytics.js";
5
+ let ssfHost = null;
6
+ const getSSFHost = () => {
7
+ if (!ssfHost) {
8
+ const logger = getLogger();
9
+ ssfHost = new SSFHost(getAppConfigValue("appId"), {
10
+ logger,
11
+ analyticsObj: new Analytics({ logger })
12
+ });
13
+ }
14
+ return ssfHost;
15
+ };
16
+ const setSSFHost = (host) => {
17
+ if (!ssfHost) {
18
+ ssfHost = host;
19
+ }
20
+ };
21
+ export {
22
+ getSSFHost,
23
+ setSSFHost
24
+ };