@elliemae/pui-app-sdk 5.40.4 → 5.41.0
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/demo/{8201.6a8c0542.iframe.bundle.js → 1080.519b1144.iframe.bundle.js} +317 -317
- package/demo/1080.519b1144.iframe.bundle.js.br +0 -0
- package/demo/1080.519b1144.iframe.bundle.js.gz +0 -0
- package/demo/docs/{8201.6a8c0542.iframe.bundle.js → 1080.519b1144.iframe.bundle.js} +317 -317
- package/demo/docs/1080.519b1144.iframe.bundle.js.br +0 -0
- package/demo/docs/1080.519b1144.iframe.bundle.js.gz +0 -0
- package/demo/docs/iframe.html +1 -1
- package/demo/docs/index.html +1 -1
- package/demo/docs/main.1bf7b965.iframe.bundle.js +5 -0
- package/demo/docs/main.1bf7b965.iframe.bundle.js.br +0 -0
- package/demo/docs/main.1bf7b965.iframe.bundle.js.gz +0 -0
- package/demo/docs/{main.4b26e7c4efd9fa564d80.manager.bundle.js → main.ba76a04bac90176acd00.manager.bundle.js} +1 -1
- package/demo/docs/main.ba76a04bac90176acd00.manager.bundle.js.br +0 -0
- package/demo/docs/{main.4b26e7c4efd9fa564d80.manager.bundle.js.gz → main.ba76a04bac90176acd00.manager.bundle.js.gz} +0 -0
- package/demo/docs/project.json +1 -1
- package/demo/iframe.html +1 -1
- package/demo/index.html +1 -1
- package/demo/main.1bf7b965.iframe.bundle.js +5 -0
- package/demo/main.1bf7b965.iframe.bundle.js.br +0 -0
- package/demo/main.1bf7b965.iframe.bundle.js.gz +0 -0
- package/demo/{main.4b26e7c4efd9fa564d80.manager.bundle.js → main.ba76a04bac90176acd00.manager.bundle.js} +1 -1
- package/demo/main.ba76a04bac90176acd00.manager.bundle.js.br +0 -0
- package/demo/{main.4b26e7c4efd9fa564d80.manager.bundle.js.gz → main.ba76a04bac90176acd00.manager.bundle.js.gz} +0 -0
- package/demo/project.json +1 -1
- package/dist/cjs/utils/micro-frontend/guest-host-context.js +47 -0
- package/dist/cjs/utils/micro-frontend/guest.js +48 -14
- package/dist/cjs/utils/micro-frontend/module-so.js +5 -1
- package/dist/cjs/utils/micro-frontend/tests/guest-test-utils.js +27 -0
- package/dist/cjs/view/guest-microapp.js +16 -4
- package/dist/cjs/view/tests/scriptingObjects/loan.js +4 -0
- package/dist/esm/utils/micro-frontend/guest-host-context.js +27 -0
- package/dist/esm/utils/micro-frontend/guest.js +48 -14
- package/dist/esm/utils/micro-frontend/module-so.js +5 -1
- package/dist/esm/utils/micro-frontend/tests/guest-test-utils.js +7 -0
- package/dist/esm/view/guest-microapp.js +19 -4
- package/dist/esm/view/tests/scriptingObjects/loan.js +4 -0
- package/dist/types/lib/utils/micro-frontend/guest-host-context.d.ts +40 -0
- package/dist/types/lib/utils/micro-frontend/guest.d.ts +6 -0
- package/dist/types/lib/utils/micro-frontend/module-so.d.ts +3 -1
- package/dist/types/lib/utils/micro-frontend/tests/guest-host-context.test.d.ts +1 -0
- package/dist/types/lib/utils/micro-frontend/tests/guest-test-utils.d.ts +2 -0
- package/dist/types/lib/view/guest-microapp.d.ts +4 -0
- package/dist/types/lib/view/tests/scriptingObjects/loan.d.ts +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/demo/8201.6a8c0542.iframe.bundle.js.br +0 -0
- package/demo/8201.6a8c0542.iframe.bundle.js.gz +0 -0
- package/demo/docs/8201.6a8c0542.iframe.bundle.js.br +0 -0
- package/demo/docs/8201.6a8c0542.iframe.bundle.js.gz +0 -0
- package/demo/docs/main.15fc50b1.iframe.bundle.js +0 -5
- package/demo/docs/main.15fc50b1.iframe.bundle.js.br +0 -0
- package/demo/docs/main.15fc50b1.iframe.bundle.js.gz +0 -0
- package/demo/docs/main.4b26e7c4efd9fa564d80.manager.bundle.js.br +0 -0
- package/demo/main.15fc50b1.iframe.bundle.js +0 -5
- package/demo/main.15fc50b1.iframe.bundle.js.br +0 -0
- package/demo/main.15fc50b1.iframe.bundle.js.gz +0 -0
- package/demo/main.4b26e7c4efd9fa564d80.manager.bundle.js.br +0 -0
package/demo/project.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"generatedAt":
|
|
1
|
+
{"generatedAt":1782148675244,"builder":{"name":"webpack5"},"hasCustomBabel":false,"hasCustomWebpack":true,"hasStaticDirs":false,"hasStorybookEslint":false,"refCount":0,"packageManager":{"type":"pnpm","version":"8.15.9"},"typescriptOptions":{"check":false,"checkOptions":{},"reactDocgen":false,"reactDocgenTypescriptOptions":{"shouldExtractLiteralValuesFromEnum":true,"compilerOptions":{"allowSyntheticDefaultImports":false,"esModuleInterop":false}}},"features":{"fastRefresh":true,"storyStoreV7":true},"language":"javascript","storybookPackages":{},"framework":{"options":{"fastRefresh":true,"strictMode":true,"legacyRootApi":true}},"addons":{"@storybook/addon-docs":{"options":{"sourceLoaderOptions":{"injectStoryParameters":false}},"version":"6.5.16"},"@storybook/addon-essentials":{"options":{"docs":false},"version":"6.5.16"},"@storybook/addon-storysource":{"version":"6.5.16"},"@storybook/addon-links":{"version":"6.5.16"},"@storybook/addon-events":{"version":"6.2.9"},"@storybook/addon-interactions":{"version":"6.5.16"},"@storybook/addon-a11y":{"version":"6.5.16"},"storybook-addon-turbo-build":{"options":{"optimizationLevel":2,"esbuildMinifyOptions":{"target":"es2022"}},"version":"1.1.0"}}}
|
|
@@ -0,0 +1,47 @@
|
|
|
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 guest_host_context_exports = {};
|
|
20
|
+
__export(guest_host_context_exports, {
|
|
21
|
+
resolveGuestOpenHistory: () => resolveGuestOpenHistory,
|
|
22
|
+
resolveNestedGuestFrameOptions: () => resolveNestedGuestFrameOptions
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(guest_host_context_exports);
|
|
25
|
+
var import_config = require("../app-config/config.js");
|
|
26
|
+
var import_history = require("../history.js");
|
|
27
|
+
var import_guest = require("./guest.js");
|
|
28
|
+
const resolveGuestOpenHistory = (explicitHistory) => {
|
|
29
|
+
const hostUsesParentHistory = (0, import_config.getAppConfigValue)(
|
|
30
|
+
"useParentHistory",
|
|
31
|
+
true
|
|
32
|
+
);
|
|
33
|
+
if (hostUsesParentHistory && typeof window !== "undefined" && window.self !== window.top && import_guest.CMicroAppGuest.isInitialized()) {
|
|
34
|
+
return import_guest.CMicroAppGuest.getInstance().getProps().history;
|
|
35
|
+
}
|
|
36
|
+
return explicitHistory ?? import_history.browserHistory;
|
|
37
|
+
};
|
|
38
|
+
const resolveNestedGuestFrameOptions = (userFrameOptions) => {
|
|
39
|
+
if (typeof window === "undefined" || window.self === window.top) {
|
|
40
|
+
return userFrameOptions;
|
|
41
|
+
}
|
|
42
|
+
const versionSegment = window.location.hostname === "localhost" ? "latest" : window.emui?.version?.match(/^(\d+\.\d+)/)?.[1] ?? "latest";
|
|
43
|
+
return {
|
|
44
|
+
src: `${window.location.origin}/${versionSegment}/frame.html`,
|
|
45
|
+
...userFrameOptions
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -83,6 +83,7 @@ class CMicroAppGuest {
|
|
|
83
83
|
*/
|
|
84
84
|
#useV2Guest;
|
|
85
85
|
#selfInitialize;
|
|
86
|
+
#embeddedWithoutHost;
|
|
86
87
|
/**
|
|
87
88
|
* AppBridge instance
|
|
88
89
|
*/
|
|
@@ -97,7 +98,7 @@ class CMicroAppGuest {
|
|
|
97
98
|
onMount;
|
|
98
99
|
onUnmount;
|
|
99
100
|
onGetRef;
|
|
100
|
-
// eslint-disable-next-line max-statements
|
|
101
|
+
// eslint-disable-next-line max-statements, complexity
|
|
101
102
|
constructor(params) {
|
|
102
103
|
window.emui.uuid = window.emui.uuid || (0, import_uuid.v4)();
|
|
103
104
|
this.appId = window.emui?.appId || (0, import_config.getAppConfigValue)("appId");
|
|
@@ -118,10 +119,16 @@ class CMicroAppGuest {
|
|
|
118
119
|
this.#ssfHostRef = (0, import_ssf_host2.getSSFHost)();
|
|
119
120
|
this.#useV2Guest = params?.useV2Guest !== false;
|
|
120
121
|
this.#selfInitialize = params?.selfInitialize ?? false;
|
|
122
|
+
this.#embeddedWithoutHost = params?.embeddedWithoutHost ?? false;
|
|
121
123
|
this.onInit = params?.onInit;
|
|
122
124
|
this.onMount = params?.onMount;
|
|
123
125
|
this.onUnmount = params?.onUnmount;
|
|
124
126
|
this.onGetRef = params?.onGetRef;
|
|
127
|
+
if (this.#embeddedWithoutHost && !this.#selfInitialize) {
|
|
128
|
+
this.logger.warn(
|
|
129
|
+
"embeddedWithoutHost requires selfInitialize: true \u2014 the flag only applies to initialize()"
|
|
130
|
+
);
|
|
131
|
+
}
|
|
125
132
|
this.getHost = this.getHost.bind(this);
|
|
126
133
|
this.getLogger = this.getLogger.bind(this);
|
|
127
134
|
this.getProps = this.getProps.bind(this);
|
|
@@ -317,6 +324,10 @@ class CMicroAppGuest {
|
|
|
317
324
|
if (window.emui?.__host) {
|
|
318
325
|
return window.emui.__host;
|
|
319
326
|
}
|
|
327
|
+
if (!isCrossDomain()) {
|
|
328
|
+
const legacyHost = window.parent?.emui?.MicroAppHost ?? null;
|
|
329
|
+
if (legacyHost) return legacyHost;
|
|
330
|
+
}
|
|
320
331
|
if (this.#useV2Guest) {
|
|
321
332
|
const ssfGuest = new import_ssf_guest.SSFGuest({ appLogger: this.logger });
|
|
322
333
|
const failed = await (0, import_helpers.abortPromise)({
|
|
@@ -370,6 +381,33 @@ class CMicroAppGuest {
|
|
|
370
381
|
const route = typeof params.initialRoute === "string" ? params.initialRoute : params.initialRoute.pathname;
|
|
371
382
|
if (route) this.props.history.push(route);
|
|
372
383
|
}
|
|
384
|
+
async #loadConfigAndBridge() {
|
|
385
|
+
await (0, import_app_config.loadAppConfig)();
|
|
386
|
+
await this.#initAppBridge();
|
|
387
|
+
}
|
|
388
|
+
#trackAnalyticsAndOnInit() {
|
|
389
|
+
const instanceId = this.getSessionStorageItem("instanceId") || "";
|
|
390
|
+
const userId = this.getSessionStorageItem("userId") || "";
|
|
391
|
+
(0, import_pui_analytics_so.updateBAEventParameters)({ appId: this.appId, instanceId, userId });
|
|
392
|
+
if (this.onInit) this.onInit(this.props);
|
|
393
|
+
}
|
|
394
|
+
#completeWithoutHost(mode) {
|
|
395
|
+
if (mode === "standalone") {
|
|
396
|
+
this.logger.info("Running in standalone mode \u2014 skipping host discovery");
|
|
397
|
+
this.#exposeGetHost();
|
|
398
|
+
this.#resolveHistory();
|
|
399
|
+
} else if (mode === "embeddedWithoutHost") {
|
|
400
|
+
this.logger.info("embeddedWithoutHost enabled \u2014 skipping host discovery");
|
|
401
|
+
this.#exposeGetHost();
|
|
402
|
+
} else {
|
|
403
|
+
this.logger.warn(
|
|
404
|
+
"Unable to discover host. Proceeding with app.config.json values. Host-provided parameters (history, theme, initialRoute) will not be available."
|
|
405
|
+
);
|
|
406
|
+
this.#exposeGetHost();
|
|
407
|
+
}
|
|
408
|
+
this.#trackAnalyticsAndOnInit();
|
|
409
|
+
return { moduleId: this.appId };
|
|
410
|
+
}
|
|
373
411
|
/**
|
|
374
412
|
* Guest-initiated lifecycle: discovers the host and applies module
|
|
375
413
|
* parameters if available. After this resolves the guest is ready to render.
|
|
@@ -385,20 +423,19 @@ class CMicroAppGuest {
|
|
|
385
423
|
(0, import_webpack_public_path.syncWebpackPublicPathFromAssetPath)();
|
|
386
424
|
const isStandalone = window.top === window.self && !window.opener;
|
|
387
425
|
if (isStandalone) {
|
|
388
|
-
await (
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
426
|
+
await this.#loadConfigAndBridge();
|
|
427
|
+
return this.#completeWithoutHost("standalone");
|
|
428
|
+
}
|
|
429
|
+
if (this.#embeddedWithoutHost) {
|
|
430
|
+
await this.#loadConfigAndBridge();
|
|
431
|
+
return this.#completeWithoutHost("embeddedWithoutHost");
|
|
393
432
|
}
|
|
394
433
|
const [host] = await Promise.all([
|
|
395
434
|
this.#discoverHost(),
|
|
396
|
-
|
|
435
|
+
this.#loadConfigAndBridge()
|
|
397
436
|
]);
|
|
398
437
|
if (!host) {
|
|
399
|
-
|
|
400
|
-
"Unable to discover host. Ensure the host uses an updated pui-app-sdk and pui-microfe, or use the host-initiated model (onInit/onMount)."
|
|
401
|
-
);
|
|
438
|
+
return this.#completeWithoutHost("discoveryFallback");
|
|
402
439
|
}
|
|
403
440
|
this.props.host = host;
|
|
404
441
|
this.#exposeGetHost();
|
|
@@ -418,10 +455,7 @@ class CMicroAppGuest {
|
|
|
418
455
|
`Failed to retrieve module parameters for "${this.appId}". Proceeding without host-provided parameters.`
|
|
419
456
|
);
|
|
420
457
|
}
|
|
421
|
-
|
|
422
|
-
const userId = this.getSessionStorageItem("userId") || "";
|
|
423
|
-
(0, import_pui_analytics_so.updateBAEventParameters)({ appId: this.appId, instanceId, userId });
|
|
424
|
-
if (this.onInit) this.onInit(this.props);
|
|
458
|
+
this.#trackAnalyticsAndOnInit();
|
|
425
459
|
return params;
|
|
426
460
|
}
|
|
427
461
|
async init(options) {
|
|
@@ -25,6 +25,7 @@ __export(module_so_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(module_so_exports);
|
|
26
26
|
var import_ssf_host = require("@elliemae/ssf-host");
|
|
27
27
|
var import_index = require("./index.js");
|
|
28
|
+
var import_guest_host_context = require("./guest-host-context.js");
|
|
28
29
|
var import_const = require("../../view/micro-app/const.js");
|
|
29
30
|
const LOG_LEVEL_METHOD = {
|
|
30
31
|
DEBUG: "debug",
|
|
@@ -84,7 +85,10 @@ class GuestModule extends import_ssf_host.ScriptingObject {
|
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
const createGuestModule = (guestId, params = {}, overrides = {}) => {
|
|
87
|
-
const mod = new GuestModule(guestId,
|
|
88
|
+
const mod = new GuestModule(guestId, {
|
|
89
|
+
...params,
|
|
90
|
+
history: (0, import_guest_host_context.resolveGuestOpenHistory)(params.history)
|
|
91
|
+
});
|
|
88
92
|
Object.assign(mod, overrides);
|
|
89
93
|
return mod;
|
|
90
94
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
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 guest_test_utils_exports = {};
|
|
20
|
+
__export(guest_test_utils_exports, {
|
|
21
|
+
resetCMicroAppGuestInstance: () => resetCMicroAppGuestInstance
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(guest_test_utils_exports);
|
|
24
|
+
var import_guest = require("../guest.js");
|
|
25
|
+
const resetCMicroAppGuestInstance = () => {
|
|
26
|
+
Reflect.set(import_guest.CMicroAppGuest, "instance", null);
|
|
27
|
+
};
|
|
@@ -41,6 +41,7 @@ var import_app_bridge = require("../utils/micro-frontend/app-bridge.js");
|
|
|
41
41
|
var import_ssf_host2 = require("../utils/micro-frontend/ssf-host.js");
|
|
42
42
|
var import_actions = require("../data/wait-message/actions.js");
|
|
43
43
|
var import_micro_frontend = require("../utils/micro-frontend/index.js");
|
|
44
|
+
var import_guest_host_context = require("../utils/micro-frontend/guest-host-context.js");
|
|
44
45
|
const Div = import_styled_components.default.div`
|
|
45
46
|
display: flex;
|
|
46
47
|
width: 100%;
|
|
@@ -59,13 +60,22 @@ const useAppRenderer = (props) => {
|
|
|
59
60
|
onUnloadComplete,
|
|
60
61
|
containerId,
|
|
61
62
|
ssfAppOptions,
|
|
62
|
-
disableWaitMessage = false
|
|
63
|
+
disableWaitMessage = false,
|
|
64
|
+
frameOptions: userFrameOptions
|
|
63
65
|
} = props;
|
|
64
66
|
const dispatch = (0, import_react_redux.useDispatch)();
|
|
65
67
|
const stableSsfAppOptions = (0, import_react.useMemo)(
|
|
66
68
|
() => ssfAppOptions ?? {},
|
|
67
69
|
[ssfAppOptions]
|
|
68
70
|
);
|
|
71
|
+
const guestHistory = (0, import_react.useMemo)(
|
|
72
|
+
() => (0, import_guest_host_context.resolveGuestOpenHistory)(history),
|
|
73
|
+
[history]
|
|
74
|
+
);
|
|
75
|
+
const resolvedFrameOptions = (0, import_react.useMemo)(
|
|
76
|
+
() => (0, import_guest_host_context.resolveNestedGuestFrameOptions)(userFrameOptions),
|
|
77
|
+
[userFrameOptions]
|
|
78
|
+
);
|
|
69
79
|
const getConfig = (0, import_react.useCallback)(
|
|
70
80
|
() => (0, import_micro_frontend.getMicroFrontEndAppConfig)({
|
|
71
81
|
id
|
|
@@ -141,11 +151,12 @@ const useAppRenderer = (props) => {
|
|
|
141
151
|
id,
|
|
142
152
|
selfInitialize: configSelfInitialize,
|
|
143
153
|
frameOptions: {
|
|
154
|
+
...resolvedFrameOptions,
|
|
144
155
|
containerId,
|
|
145
156
|
queryParams: (0, import_pui_logrocket.buildLogRocketQueryParams)(),
|
|
146
157
|
signal: abortController.signal
|
|
147
158
|
},
|
|
148
|
-
history,
|
|
159
|
+
history: guestHistory,
|
|
149
160
|
homeRoute,
|
|
150
161
|
initialRoute
|
|
151
162
|
});
|
|
@@ -213,7 +224,7 @@ const useAppRenderer = (props) => {
|
|
|
213
224
|
}, [
|
|
214
225
|
containerId,
|
|
215
226
|
dispatch,
|
|
216
|
-
|
|
227
|
+
guestHistory,
|
|
217
228
|
homeRoute,
|
|
218
229
|
initialRoute,
|
|
219
230
|
id,
|
|
@@ -221,7 +232,8 @@ const useAppRenderer = (props) => {
|
|
|
221
232
|
onUnloadComplete,
|
|
222
233
|
getConfig,
|
|
223
234
|
stableSsfAppOptions,
|
|
224
|
-
disableWaitMessage
|
|
235
|
+
disableWaitMessage,
|
|
236
|
+
resolvedFrameOptions
|
|
225
237
|
]);
|
|
226
238
|
};
|
|
227
239
|
const GuestMicroApp = (0, import_react.memo)(
|
|
@@ -61,6 +61,10 @@ class Loan extends import_pui_app_bridge.ScriptingObject {
|
|
|
61
61
|
name: "editmodechange",
|
|
62
62
|
objectId: "loan"
|
|
63
63
|
});
|
|
64
|
+
ExternallyModified = new import_pui_app_bridge.Event({
|
|
65
|
+
name: "externallyModified",
|
|
66
|
+
objectId: "loan"
|
|
67
|
+
});
|
|
64
68
|
FieldChangeSync = new import_pui_app_bridge.Event({
|
|
65
69
|
name: "fieldChangeSync",
|
|
66
70
|
objectId: "loan"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getAppConfigValue } from "../app-config/config.js";
|
|
2
|
+
import { browserHistory } from "../history.js";
|
|
3
|
+
import { CMicroAppGuest } from "./guest.js";
|
|
4
|
+
const resolveGuestOpenHistory = (explicitHistory) => {
|
|
5
|
+
const hostUsesParentHistory = getAppConfigValue(
|
|
6
|
+
"useParentHistory",
|
|
7
|
+
true
|
|
8
|
+
);
|
|
9
|
+
if (hostUsesParentHistory && typeof window !== "undefined" && window.self !== window.top && CMicroAppGuest.isInitialized()) {
|
|
10
|
+
return CMicroAppGuest.getInstance().getProps().history;
|
|
11
|
+
}
|
|
12
|
+
return explicitHistory ?? browserHistory;
|
|
13
|
+
};
|
|
14
|
+
const resolveNestedGuestFrameOptions = (userFrameOptions) => {
|
|
15
|
+
if (typeof window === "undefined" || window.self === window.top) {
|
|
16
|
+
return userFrameOptions;
|
|
17
|
+
}
|
|
18
|
+
const versionSegment = window.location.hostname === "localhost" ? "latest" : window.emui?.version?.match(/^(\d+\.\d+)/)?.[1] ?? "latest";
|
|
19
|
+
return {
|
|
20
|
+
src: `${window.location.origin}/${versionSegment}/frame.html`,
|
|
21
|
+
...userFrameOptions
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
resolveGuestOpenHistory,
|
|
26
|
+
resolveNestedGuestFrameOptions
|
|
27
|
+
};
|
|
@@ -50,6 +50,7 @@ class CMicroAppGuest {
|
|
|
50
50
|
*/
|
|
51
51
|
#useV2Guest;
|
|
52
52
|
#selfInitialize;
|
|
53
|
+
#embeddedWithoutHost;
|
|
53
54
|
/**
|
|
54
55
|
* AppBridge instance
|
|
55
56
|
*/
|
|
@@ -64,7 +65,7 @@ class CMicroAppGuest {
|
|
|
64
65
|
onMount;
|
|
65
66
|
onUnmount;
|
|
66
67
|
onGetRef;
|
|
67
|
-
// eslint-disable-next-line max-statements
|
|
68
|
+
// eslint-disable-next-line max-statements, complexity
|
|
68
69
|
constructor(params) {
|
|
69
70
|
window.emui.uuid = window.emui.uuid || uuidv4();
|
|
70
71
|
this.appId = window.emui?.appId || getAppConfigValue("appId");
|
|
@@ -85,10 +86,16 @@ class CMicroAppGuest {
|
|
|
85
86
|
this.#ssfHostRef = getSSFHost();
|
|
86
87
|
this.#useV2Guest = params?.useV2Guest !== false;
|
|
87
88
|
this.#selfInitialize = params?.selfInitialize ?? false;
|
|
89
|
+
this.#embeddedWithoutHost = params?.embeddedWithoutHost ?? false;
|
|
88
90
|
this.onInit = params?.onInit;
|
|
89
91
|
this.onMount = params?.onMount;
|
|
90
92
|
this.onUnmount = params?.onUnmount;
|
|
91
93
|
this.onGetRef = params?.onGetRef;
|
|
94
|
+
if (this.#embeddedWithoutHost && !this.#selfInitialize) {
|
|
95
|
+
this.logger.warn(
|
|
96
|
+
"embeddedWithoutHost requires selfInitialize: true \u2014 the flag only applies to initialize()"
|
|
97
|
+
);
|
|
98
|
+
}
|
|
92
99
|
this.getHost = this.getHost.bind(this);
|
|
93
100
|
this.getLogger = this.getLogger.bind(this);
|
|
94
101
|
this.getProps = this.getProps.bind(this);
|
|
@@ -284,6 +291,10 @@ class CMicroAppGuest {
|
|
|
284
291
|
if (window.emui?.__host) {
|
|
285
292
|
return window.emui.__host;
|
|
286
293
|
}
|
|
294
|
+
if (!isCrossDomain()) {
|
|
295
|
+
const legacyHost = window.parent?.emui?.MicroAppHost ?? null;
|
|
296
|
+
if (legacyHost) return legacyHost;
|
|
297
|
+
}
|
|
287
298
|
if (this.#useV2Guest) {
|
|
288
299
|
const ssfGuest = new SSFGuest({ appLogger: this.logger });
|
|
289
300
|
const failed = await abortPromise({
|
|
@@ -337,6 +348,33 @@ class CMicroAppGuest {
|
|
|
337
348
|
const route = typeof params.initialRoute === "string" ? params.initialRoute : params.initialRoute.pathname;
|
|
338
349
|
if (route) this.props.history.push(route);
|
|
339
350
|
}
|
|
351
|
+
async #loadConfigAndBridge() {
|
|
352
|
+
await loadAppConfig();
|
|
353
|
+
await this.#initAppBridge();
|
|
354
|
+
}
|
|
355
|
+
#trackAnalyticsAndOnInit() {
|
|
356
|
+
const instanceId = this.getSessionStorageItem("instanceId") || "";
|
|
357
|
+
const userId = this.getSessionStorageItem("userId") || "";
|
|
358
|
+
updateBAEventParameters({ appId: this.appId, instanceId, userId });
|
|
359
|
+
if (this.onInit) this.onInit(this.props);
|
|
360
|
+
}
|
|
361
|
+
#completeWithoutHost(mode) {
|
|
362
|
+
if (mode === "standalone") {
|
|
363
|
+
this.logger.info("Running in standalone mode \u2014 skipping host discovery");
|
|
364
|
+
this.#exposeGetHost();
|
|
365
|
+
this.#resolveHistory();
|
|
366
|
+
} else if (mode === "embeddedWithoutHost") {
|
|
367
|
+
this.logger.info("embeddedWithoutHost enabled \u2014 skipping host discovery");
|
|
368
|
+
this.#exposeGetHost();
|
|
369
|
+
} else {
|
|
370
|
+
this.logger.warn(
|
|
371
|
+
"Unable to discover host. Proceeding with app.config.json values. Host-provided parameters (history, theme, initialRoute) will not be available."
|
|
372
|
+
);
|
|
373
|
+
this.#exposeGetHost();
|
|
374
|
+
}
|
|
375
|
+
this.#trackAnalyticsAndOnInit();
|
|
376
|
+
return { moduleId: this.appId };
|
|
377
|
+
}
|
|
340
378
|
/**
|
|
341
379
|
* Guest-initiated lifecycle: discovers the host and applies module
|
|
342
380
|
* parameters if available. After this resolves the guest is ready to render.
|
|
@@ -352,20 +390,19 @@ class CMicroAppGuest {
|
|
|
352
390
|
syncWebpackPublicPathFromAssetPath();
|
|
353
391
|
const isStandalone = window.top === window.self && !window.opener;
|
|
354
392
|
if (isStandalone) {
|
|
355
|
-
await
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
393
|
+
await this.#loadConfigAndBridge();
|
|
394
|
+
return this.#completeWithoutHost("standalone");
|
|
395
|
+
}
|
|
396
|
+
if (this.#embeddedWithoutHost) {
|
|
397
|
+
await this.#loadConfigAndBridge();
|
|
398
|
+
return this.#completeWithoutHost("embeddedWithoutHost");
|
|
360
399
|
}
|
|
361
400
|
const [host] = await Promise.all([
|
|
362
401
|
this.#discoverHost(),
|
|
363
|
-
|
|
402
|
+
this.#loadConfigAndBridge()
|
|
364
403
|
]);
|
|
365
404
|
if (!host) {
|
|
366
|
-
|
|
367
|
-
"Unable to discover host. Ensure the host uses an updated pui-app-sdk and pui-microfe, or use the host-initiated model (onInit/onMount)."
|
|
368
|
-
);
|
|
405
|
+
return this.#completeWithoutHost("discoveryFallback");
|
|
369
406
|
}
|
|
370
407
|
this.props.host = host;
|
|
371
408
|
this.#exposeGetHost();
|
|
@@ -385,10 +422,7 @@ class CMicroAppGuest {
|
|
|
385
422
|
`Failed to retrieve module parameters for "${this.appId}". Proceeding without host-provided parameters.`
|
|
386
423
|
);
|
|
387
424
|
}
|
|
388
|
-
|
|
389
|
-
const userId = this.getSessionStorageItem("userId") || "";
|
|
390
|
-
updateBAEventParameters({ appId: this.appId, instanceId, userId });
|
|
391
|
-
if (this.onInit) this.onInit(this.props);
|
|
425
|
+
this.#trackAnalyticsAndOnInit();
|
|
392
426
|
return params;
|
|
393
427
|
}
|
|
394
428
|
async init(options) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ScriptingObject, Event } from "@elliemae/ssf-host";
|
|
2
2
|
import { getMicroFrontEndAppConfig } from "./index.js";
|
|
3
|
+
import { resolveGuestOpenHistory } from "./guest-host-context.js";
|
|
3
4
|
import { APP_CONTAINER_ID_PREFIX } from "../../view/micro-app/const.js";
|
|
4
5
|
const LOG_LEVEL_METHOD = {
|
|
5
6
|
DEBUG: "debug",
|
|
@@ -59,7 +60,10 @@ class GuestModule extends ScriptingObject {
|
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
const createGuestModule = (guestId, params = {}, overrides = {}) => {
|
|
62
|
-
const mod = new GuestModule(guestId,
|
|
63
|
+
const mod = new GuestModule(guestId, {
|
|
64
|
+
...params,
|
|
65
|
+
history: resolveGuestOpenHistory(params.history)
|
|
66
|
+
});
|
|
63
67
|
Object.assign(mod, overrides);
|
|
64
68
|
return mod;
|
|
65
69
|
};
|
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
getLogger,
|
|
14
14
|
getMicroFrontEndAppConfig
|
|
15
15
|
} from "../utils/micro-frontend/index.js";
|
|
16
|
+
import {
|
|
17
|
+
resolveGuestOpenHistory,
|
|
18
|
+
resolveNestedGuestFrameOptions
|
|
19
|
+
} from "../utils/micro-frontend/guest-host-context.js";
|
|
16
20
|
const Div = styled.div`
|
|
17
21
|
display: flex;
|
|
18
22
|
width: 100%;
|
|
@@ -31,13 +35,22 @@ const useAppRenderer = (props) => {
|
|
|
31
35
|
onUnloadComplete,
|
|
32
36
|
containerId,
|
|
33
37
|
ssfAppOptions,
|
|
34
|
-
disableWaitMessage = false
|
|
38
|
+
disableWaitMessage = false,
|
|
39
|
+
frameOptions: userFrameOptions
|
|
35
40
|
} = props;
|
|
36
41
|
const dispatch = useDispatch();
|
|
37
42
|
const stableSsfAppOptions = useMemo(
|
|
38
43
|
() => ssfAppOptions ?? {},
|
|
39
44
|
[ssfAppOptions]
|
|
40
45
|
);
|
|
46
|
+
const guestHistory = useMemo(
|
|
47
|
+
() => resolveGuestOpenHistory(history),
|
|
48
|
+
[history]
|
|
49
|
+
);
|
|
50
|
+
const resolvedFrameOptions = useMemo(
|
|
51
|
+
() => resolveNestedGuestFrameOptions(userFrameOptions),
|
|
52
|
+
[userFrameOptions]
|
|
53
|
+
);
|
|
41
54
|
const getConfig = useCallback(
|
|
42
55
|
() => getMicroFrontEndAppConfig({
|
|
43
56
|
id
|
|
@@ -113,11 +126,12 @@ const useAppRenderer = (props) => {
|
|
|
113
126
|
id,
|
|
114
127
|
selfInitialize: configSelfInitialize,
|
|
115
128
|
frameOptions: {
|
|
129
|
+
...resolvedFrameOptions,
|
|
116
130
|
containerId,
|
|
117
131
|
queryParams: buildLogRocketQueryParams(),
|
|
118
132
|
signal: abortController.signal
|
|
119
133
|
},
|
|
120
|
-
history,
|
|
134
|
+
history: guestHistory,
|
|
121
135
|
homeRoute,
|
|
122
136
|
initialRoute
|
|
123
137
|
});
|
|
@@ -185,7 +199,7 @@ const useAppRenderer = (props) => {
|
|
|
185
199
|
}, [
|
|
186
200
|
containerId,
|
|
187
201
|
dispatch,
|
|
188
|
-
|
|
202
|
+
guestHistory,
|
|
189
203
|
homeRoute,
|
|
190
204
|
initialRoute,
|
|
191
205
|
id,
|
|
@@ -193,7 +207,8 @@ const useAppRenderer = (props) => {
|
|
|
193
207
|
onUnloadComplete,
|
|
194
208
|
getConfig,
|
|
195
209
|
stableSsfAppOptions,
|
|
196
|
-
disableWaitMessage
|
|
210
|
+
disableWaitMessage,
|
|
211
|
+
resolvedFrameOptions
|
|
197
212
|
]);
|
|
198
213
|
};
|
|
199
214
|
const GuestMicroApp = memo(
|
|
@@ -38,6 +38,10 @@ class Loan extends ScriptingObject {
|
|
|
38
38
|
name: "editmodechange",
|
|
39
39
|
objectId: "loan"
|
|
40
40
|
});
|
|
41
|
+
ExternallyModified = new Event({
|
|
42
|
+
name: "externallyModified",
|
|
43
|
+
objectId: "loan"
|
|
44
|
+
});
|
|
41
45
|
FieldChangeSync = new Event({
|
|
42
46
|
name: "fieldChangeSync",
|
|
43
47
|
objectId: "loan"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { History } from 'history';
|
|
2
|
+
type NestedGuestFrameOptions = {
|
|
3
|
+
src?: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* History object to use when **opening** a child guest via {@link GuestMicroApp}.
|
|
7
|
+
* {@link createGuestModule} applies the same resolution for module scripting
|
|
8
|
+
* objects automatically.
|
|
9
|
+
*
|
|
10
|
+
* This only affects what the **host** passes into app-bridge `openApp`. The
|
|
11
|
+
* **child guest** still decides its final router history during
|
|
12
|
+
* {@link CMicroAppGuest.initialize} from **its own** `app.config.json`
|
|
13
|
+
* `useParentHistory` flag:
|
|
14
|
+
*
|
|
15
|
+
* - `useParentHistory: true` (default) — uses the history received from the host
|
|
16
|
+
* - `useParentHistory: false` — uses independent `memoryHistory` inside the
|
|
17
|
+
* iframe and ignores the host-provided history
|
|
18
|
+
*
|
|
19
|
+
* When this host runs inside a parent iframe and shares parent history itself
|
|
20
|
+
* (`useParentHistory: true`, the default), the exported `browserHistory`
|
|
21
|
+
* singleton tracks the iframe shell URL (e.g. `/latest/frame.html`), not the
|
|
22
|
+
* shared grandparent route (e.g. `/prospects/incomplete-apps`). In that case
|
|
23
|
+
* the history bound during {@link CMicroAppGuest.initialize} is returned
|
|
24
|
+
* automatically so shared-history children receive the correct object.
|
|
25
|
+
*
|
|
26
|
+
* Hosts with `useParentHistory: false` are unchanged: callers keep passing
|
|
27
|
+
* `explicitHistory ?? browserHistory`, and guests that want their own URL space
|
|
28
|
+
* opt out via their own config.
|
|
29
|
+
* @param explicitHistory
|
|
30
|
+
*/
|
|
31
|
+
export declare const resolveGuestOpenHistory: (explicitHistory?: History) => History;
|
|
32
|
+
/**
|
|
33
|
+
* Frame options for nested hosts whose bundled frame.html URL targets the
|
|
34
|
+
* guest dev-server origin while JS executes in the parent iframe document.
|
|
35
|
+
* App Bridge rewrites cross-origin frame shells; this supplies an explicit
|
|
36
|
+
* same-origin src when callers pass custom frameOptions.
|
|
37
|
+
* @param userFrameOptions
|
|
38
|
+
*/
|
|
39
|
+
export declare const resolveNestedGuestFrameOptions: (userFrameOptions?: NestedGuestFrameOptions) => NestedGuestFrameOptions | undefined;
|
|
40
|
+
export {};
|
|
@@ -40,6 +40,12 @@ interface ConstructorParams {
|
|
|
40
40
|
* the bridge will not call these methods.
|
|
41
41
|
*/
|
|
42
42
|
selfInitialize?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* When true, the guest is embedded in an iframe but not hosted by PUI app
|
|
45
|
+
* bridge or SSF. Skips host discovery and initializes from app.config.json
|
|
46
|
+
* with in-memory history. Ignored when running standalone (top-level window).
|
|
47
|
+
*/
|
|
48
|
+
embeddedWithoutHost?: boolean;
|
|
43
49
|
}
|
|
44
50
|
/**
|
|
45
51
|
* Micro-frontend guest application class (singleton).
|
|
@@ -73,7 +73,9 @@ export type ModuleOverrides = {
|
|
|
73
73
|
*
|
|
74
74
|
* Internally calls {@link buildModuleParams} to merge the app config
|
|
75
75
|
* values (hostUrl, manifestPath, homeRoute) with host-provided values
|
|
76
|
-
* (theme, history, initialRoute).
|
|
76
|
+
* (theme, history, initialRoute). When nested under a parent iframe,
|
|
77
|
+
* {@link resolveGuestOpenHistory} is applied to `params.history` automatically
|
|
78
|
+
* (same behavior as {@link GuestMicroApp}).
|
|
77
79
|
*
|
|
78
80
|
* Register the returned object via {@link CMicroApp.addScriptingObject}
|
|
79
81
|
* (not directly on the app bridge) so it is added to both the App Bridge
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -37,6 +37,10 @@ export type GuestMicroAppParams = OpenAppParams & {
|
|
|
37
37
|
* this component, and remove it on teardown. Host-provided `theme` and
|
|
38
38
|
* `history` for self-initializing guests belong on that module SO — not on
|
|
39
39
|
* {@link GuestMicroApp} / {@link OpenAppParams}.
|
|
40
|
+
*
|
|
41
|
+
* When this app is itself a nested guest (running inside a parent iframe),
|
|
42
|
+
* {@link GuestMicroApp} automatically forwards the shared grandparent history
|
|
43
|
+
* to child guests — callers do not need to pass `history` explicitly.
|
|
40
44
|
* @param props - The props for the MicroApp component.
|
|
41
45
|
*/
|
|
42
46
|
export declare const GuestMicroApp: import("react").NamedExoticComponent<Omit<GuestMicroAppParams, "containerId">>;
|
|
@@ -8,6 +8,7 @@ export declare class Loan extends ScriptingObject implements ILoan {
|
|
|
8
8
|
readonly Change: Event<Events>;
|
|
9
9
|
readonly Committed: Event<Events>;
|
|
10
10
|
readonly EditModeChange: Event<Events>;
|
|
11
|
+
readonly ExternallyModified: Event<Events>;
|
|
11
12
|
readonly FieldChangeSync: Event<Events>;
|
|
12
13
|
readonly MilestoneCompleted: Event<Events>;
|
|
13
14
|
readonly Open: Event<Events>;
|