@elliemae/pui-app-bridge 2.9.9 → 2.17.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/dist/cjs/appBridge.js +380 -93
- package/dist/cjs/appRegistry.js +136 -0
- package/dist/cjs/config/app.js +15 -2
- package/dist/cjs/config/microFE.js +3 -3
- package/dist/cjs/eventManager.js +16 -16
- package/dist/cjs/frame.html +2 -2
- package/dist/cjs/frame.js +39 -14
- package/dist/cjs/index.html +1 -1
- package/dist/cjs/loaders/script.js +5 -5
- package/dist/cjs/loaders/style.js +1 -0
- package/dist/cjs/microfeHost.js +51 -31
- package/dist/cjs/tests/flights/23.1/app.checksum1.js +25 -24
- package/dist/cjs/tests/flights/latest/app.checksum.js +25 -24
- package/dist/cjs/tests/hotels/23.1/app.checksum.js +27 -24
- package/dist/cjs/tests/hotels/latest/app.checksum.js +27 -24
- package/dist/cjs/tests/loan/latest/index.js +49 -57
- package/dist/cjs/tests/scriptingObjects/analytics.js +7 -7
- package/dist/cjs/tests/scriptingObjects/appraisalServiceModule.js +8 -8
- package/dist/cjs/tests/scriptingObjects/global.js +1 -2
- package/dist/cjs/tests/task/latest/index.dev.js +29 -28
- package/dist/cjs/tests/task/latest/index.js +29 -28
- package/dist/cjs/tests/travelhub/23.1/app.checksum.js +24 -26
- package/dist/cjs/tests/travelhub/23.1/landing.checksum1.js +5 -7
- package/dist/cjs/utils.js +31 -1
- package/dist/esm/appBridge.js +390 -95
- package/dist/esm/appRegistry.js +116 -0
- package/dist/esm/config/app.js +15 -2
- package/dist/esm/config/microFE.js +3 -3
- package/dist/esm/eventManager.js +16 -16
- package/dist/esm/frame.html +2 -2
- package/dist/esm/frame.js +29 -14
- package/dist/esm/index.html +1 -1
- package/dist/esm/loaders/script.js +5 -5
- package/dist/esm/loaders/style.js +1 -0
- package/dist/esm/microfeHost.js +55 -31
- package/dist/esm/tests/flights/23.1/app.checksum1.js +25 -24
- package/dist/esm/tests/flights/latest/app.checksum.js +25 -24
- package/dist/esm/tests/hotels/23.1/app.checksum.js +27 -24
- package/dist/esm/tests/hotels/latest/app.checksum.js +27 -24
- package/dist/esm/tests/loan/latest/index.js +49 -57
- package/dist/esm/tests/scriptingObjects/analytics.js +7 -7
- package/dist/esm/tests/scriptingObjects/appraisalServiceModule.js +8 -8
- package/dist/esm/tests/scriptingObjects/global.js +1 -2
- package/dist/esm/tests/task/latest/index.dev.js +29 -28
- package/dist/esm/tests/task/latest/index.js +29 -28
- package/dist/esm/tests/travelhub/23.1/app.checksum.js +24 -26
- package/dist/esm/tests/travelhub/23.1/landing.checksum1.js +5 -7
- package/dist/esm/utils.js +31 -1
- package/dist/public/assets/frame.671d9de68be598da64ca.html +47 -0
- package/dist/public/creditService/latest/creditService.checksum.js.gz +0 -0
- package/dist/public/frame.html +1 -1
- package/dist/public/guest/businessObjects.js.gz +0 -0
- package/dist/public/guest/util.js.gz +0 -0
- package/dist/public/index.html +1 -1
- package/dist/public/init.js.gz +0 -0
- package/dist/public/js/emuiAppBridge.2993b666256d6dd7148d.js +51 -0
- package/dist/public/js/emuiAppBridge.2993b666256d6dd7148d.js.br +0 -0
- package/dist/public/js/emuiAppBridge.2993b666256d6dd7148d.js.gz +0 -0
- package/dist/public/js/emuiAppBridge.2993b666256d6dd7148d.js.map +1 -0
- package/dist/public/loan-object.js +1 -1
- package/dist/public/loan-object.js.br +0 -0
- package/dist/public/loan-object.js.gz +0 -0
- package/dist/public/loan-object.js.map +1 -1
- package/dist/public/loanValidation/latest/loanValidation.checksum.js.gz +0 -0
- package/dist/public/pricingService/latest/pricingService.checksum.js.gz +0 -0
- package/dist/public/utils.js.gz +0 -0
- package/dist/types/lib/appBridge.d.ts +38 -28
- package/dist/types/lib/appRegistry.d.ts +41 -0
- package/dist/types/lib/eventManager.d.ts +4 -4
- package/dist/types/lib/frame.d.ts +45 -4
- package/dist/types/lib/index.d.ts +3 -3
- package/dist/types/lib/loaders/script.d.ts +2 -1
- package/dist/types/lib/microfeHost.d.ts +15 -25
- package/dist/types/lib/tests/flights/23.1/app.checksum1.d.ts +7 -0
- package/dist/types/lib/tests/flights/latest/app.checksum.d.ts +7 -0
- package/dist/types/lib/tests/hotels/23.1/app.checksum.d.ts +7 -0
- package/dist/types/lib/tests/hotels/latest/app.checksum.d.ts +7 -0
- package/dist/types/lib/tests/loan/latest/index.d.ts +11 -0
- package/dist/types/lib/tests/scriptingObjects/analytics.d.ts +3 -3
- package/dist/types/lib/tests/scriptingObjects/appraisalServiceModule.d.ts +2 -1
- package/dist/types/lib/tests/task/latest/index.d.ts +10 -0
- package/dist/types/lib/tests/task/latest/index.dev.d.ts +10 -0
- package/dist/types/lib/tests/travelhub/23.1/app.checksum.d.ts +7 -0
- package/dist/types/lib/tests/travelhub/23.1/landing.checksum1.d.ts +2 -0
- package/dist/types/lib/typings/appInfo.d.ts +1 -0
- package/dist/types/lib/typings/common.d.ts +0 -66
- package/dist/types/lib/typings/guest.d.ts +10 -3
- package/dist/types/lib/typings/host.d.ts +32 -32
- package/dist/types/lib/typings/window.d.ts +6 -1
- package/dist/types/lib/utils.d.ts +7 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/umd/671d9de68be598da64ca.html +47 -0
- package/dist/umd/creditService/latest/creditService.checksum.js.gz +0 -0
- package/dist/umd/frame.html +1 -1
- package/dist/umd/guest/businessObjects.js.gz +0 -0
- package/dist/umd/guest/util.js.gz +0 -0
- package/dist/umd/index.html +1 -1
- package/dist/umd/index.js +35 -9
- package/dist/umd/index.js.br +0 -0
- package/dist/umd/index.js.gz +0 -0
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/init.js.gz +0 -0
- package/dist/umd/loan-object.js +1 -1
- package/dist/umd/loan-object.js.br +0 -0
- package/dist/umd/loan-object.js.gz +0 -0
- package/dist/umd/loan-object.js.map +1 -1
- package/dist/umd/loanValidation/latest/loanValidation.checksum.js.gz +0 -0
- package/dist/umd/pricingService/latest/pricingService.checksum.js.gz +0 -0
- package/dist/umd/utils.js.gz +0 -0
- package/package.json +9 -12
- package/dist/public/js/emuiAppBridge.530390c3bb03f32357f7.js +0 -25
- package/dist/public/js/emuiAppBridge.530390c3bb03f32357f7.js.br +0 -0
- package/dist/public/js/emuiAppBridge.530390c3bb03f32357f7.js.gz +0 -0
- package/dist/public/js/emuiAppBridge.530390c3bb03f32357f7.js.map +0 -1
- package/dist/types/lib/tests/pubsubAPI.test.d.ts +0 -1
package/dist/cjs/appBridge.js
CHANGED
|
@@ -21,7 +21,9 @@ __export(appBridge_exports, {
|
|
|
21
21
|
CAppBridge: () => CAppBridge
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(appBridge_exports);
|
|
24
|
-
var
|
|
24
|
+
var import_lodash = require("lodash");
|
|
25
|
+
var import_uuid = require("uuid");
|
|
26
|
+
var import_pui_scripting_object = require("@elliemae/pui-scripting-object");
|
|
25
27
|
var import_microfe_common = require("@elliemae/microfe-common");
|
|
26
28
|
var import_eventManager = require("./eventManager.js");
|
|
27
29
|
var import_frame = require("./frame.js");
|
|
@@ -30,39 +32,104 @@ var import_app = require("./config/app.js");
|
|
|
30
32
|
var import_microFE = require("./config/microFE.js");
|
|
31
33
|
var import_loaders = require("./loaders/index.js");
|
|
32
34
|
var import_microfeHost = require("./microfeHost.js");
|
|
33
|
-
|
|
35
|
+
var import_appRegistry = require("./appRegistry.js");
|
|
36
|
+
const KEEP_ALIVE_INTERVAL = 12e4;
|
|
37
|
+
const userInteractionEvents = ["click", "scroll", "keypress", "touchstart"];
|
|
34
38
|
const cssType = /\.css$/;
|
|
35
39
|
const isCss = (fileName) => cssType.test(fileName);
|
|
36
40
|
class CAppBridge {
|
|
41
|
+
/**
|
|
42
|
+
* instance of the pui diagnostics logger
|
|
43
|
+
*/
|
|
37
44
|
#logger;
|
|
45
|
+
/**
|
|
46
|
+
* release version of the product
|
|
47
|
+
*/
|
|
38
48
|
#version;
|
|
49
|
+
/**
|
|
50
|
+
* instance of the script loader
|
|
51
|
+
*/
|
|
39
52
|
#scriptLoader;
|
|
53
|
+
/**
|
|
54
|
+
* instance of the style loader
|
|
55
|
+
*/
|
|
40
56
|
#styleLoader;
|
|
57
|
+
/**
|
|
58
|
+
* instance of the app config
|
|
59
|
+
*/
|
|
41
60
|
#appConfig;
|
|
61
|
+
/**
|
|
62
|
+
* instance of the micro frontend config
|
|
63
|
+
*/
|
|
42
64
|
#microFEConfig = new import_microFE.CMicroFEConfig();
|
|
65
|
+
/**
|
|
66
|
+
* instance of the scripting object manager
|
|
67
|
+
*/
|
|
43
68
|
#soManager;
|
|
69
|
+
/**
|
|
70
|
+
* instance of the event manager
|
|
71
|
+
*/
|
|
44
72
|
#eventManager;
|
|
73
|
+
/**
|
|
74
|
+
* list of active apps
|
|
75
|
+
*/
|
|
45
76
|
#activeApps = /* @__PURE__ */ new Map();
|
|
77
|
+
/**
|
|
78
|
+
* instance of the app registry
|
|
79
|
+
*/
|
|
80
|
+
#appRegistry = new import_appRegistry.CAppRegistry();
|
|
81
|
+
/**
|
|
82
|
+
* flag to extend parent session when user interacts with the guest application
|
|
83
|
+
*/
|
|
84
|
+
#extendSession = true;
|
|
46
85
|
/**
|
|
47
86
|
* Create a new instance of the AppBridge
|
|
48
|
-
* @param {AppBridgeParams}
|
|
87
|
+
* @param {AppBridgeParams} options - App Bridge constructor parameters
|
|
49
88
|
*/
|
|
50
|
-
constructor(
|
|
51
|
-
const { logger } =
|
|
89
|
+
constructor(options) {
|
|
90
|
+
const { logger } = options;
|
|
52
91
|
if (!logger) throw new Error("logger is required");
|
|
53
|
-
this.#logger =
|
|
54
|
-
this.#version =
|
|
92
|
+
this.#logger = options.logger;
|
|
93
|
+
this.#version = options.version;
|
|
94
|
+
this.#extendSession = options.extendSession ?? true;
|
|
55
95
|
this.#appConfig = new import_app.CAppConfig({
|
|
56
|
-
version:
|
|
57
|
-
baseUrl:
|
|
96
|
+
version: options.version,
|
|
97
|
+
baseUrl: options.appConfigBaseUrl
|
|
58
98
|
});
|
|
59
99
|
this.#scriptLoader = new import_loaders.ScriptLoader(logger);
|
|
60
100
|
this.#styleLoader = new import_loaders.StyleLoader(logger);
|
|
61
101
|
this.#soManager = new import_microfe_common.ScriptingObjectManager();
|
|
62
102
|
this.#eventManager = new import_eventManager.EventManager();
|
|
63
103
|
}
|
|
64
|
-
#
|
|
65
|
-
|
|
104
|
+
#isFunction(value) {
|
|
105
|
+
return typeof value === "function";
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* check if the value is a proxy event
|
|
109
|
+
* @param value
|
|
110
|
+
* @returns
|
|
111
|
+
*/
|
|
112
|
+
#isProxyEvent = (value) => (
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
114
|
+
value instanceof import_microfe_common.ProxyEvent || // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
115
|
+
typeof value?.subscribe === "function"
|
|
116
|
+
);
|
|
117
|
+
// support v1 scripting objects
|
|
118
|
+
/**
|
|
119
|
+
* format error message for app not found
|
|
120
|
+
* @param id app id
|
|
121
|
+
* @param instanceId unique instance id
|
|
122
|
+
* @returns error message
|
|
123
|
+
*/
|
|
124
|
+
#getAppNotFoundError = (id, instanceId) => `Application ${id} with instance id ${instanceId} is not found. Most probably the appId property of app.config.json is not set to ${id}`;
|
|
125
|
+
/**
|
|
126
|
+
* remove assets from DOM
|
|
127
|
+
* @param instanceId unique instance id of the app
|
|
128
|
+
* @param documentEle document element of the app
|
|
129
|
+
* @returns void
|
|
130
|
+
*/
|
|
131
|
+
#removeAssetsFromDOM = (instanceId, documentEle = document) => {
|
|
132
|
+
const { elementIds } = this.#activeApps.get(instanceId) || {};
|
|
66
133
|
if (elementIds) {
|
|
67
134
|
elementIds.forEach((elementId) => {
|
|
68
135
|
const ele = documentEle.getElementById(elementId);
|
|
@@ -70,9 +137,26 @@ class CAppBridge {
|
|
|
70
137
|
});
|
|
71
138
|
}
|
|
72
139
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
140
|
+
/**
|
|
141
|
+
* add app to active app list
|
|
142
|
+
* @param param0
|
|
143
|
+
* @param param0.id
|
|
144
|
+
* @param param0.instanceId
|
|
145
|
+
* @param elementIds
|
|
146
|
+
* @param param0.documentEle
|
|
147
|
+
*/
|
|
148
|
+
#addAppToActiveAppList = ({
|
|
149
|
+
id,
|
|
150
|
+
instanceId,
|
|
151
|
+
documentEle
|
|
152
|
+
}, elementIds) => {
|
|
153
|
+
const app = this.#appRegistry.get({ id, instanceId });
|
|
154
|
+
if (!app) {
|
|
155
|
+
throw new Error(this.#getAppNotFoundError(id, instanceId));
|
|
156
|
+
}
|
|
157
|
+
this.#activeApps.set(instanceId, {
|
|
158
|
+
id,
|
|
159
|
+
instanceId,
|
|
76
160
|
elementIds,
|
|
77
161
|
guest: {
|
|
78
162
|
guestWindow: documentEle?.defaultView,
|
|
@@ -83,29 +167,37 @@ class CAppBridge {
|
|
|
83
167
|
#waitAndInitApplication = (options, requests) => {
|
|
84
168
|
const {
|
|
85
169
|
id,
|
|
170
|
+
instanceId,
|
|
171
|
+
containerId,
|
|
86
172
|
name,
|
|
87
173
|
hostUrl,
|
|
88
174
|
manifestPath,
|
|
89
175
|
homeRoute,
|
|
176
|
+
initialRoute,
|
|
90
177
|
history,
|
|
91
178
|
theme,
|
|
92
179
|
documentEle
|
|
93
180
|
} = options;
|
|
94
|
-
return Promise.all(requests).then(
|
|
181
|
+
return Promise.all(requests).then(
|
|
182
|
+
this.#addAppToActiveAppList.bind(null, { id, instanceId, documentEle })
|
|
183
|
+
).then(
|
|
95
184
|
this.#initApplication.bind(null, {
|
|
96
185
|
id,
|
|
186
|
+
instanceId,
|
|
187
|
+
containerId,
|
|
97
188
|
name,
|
|
98
189
|
hostUrl,
|
|
99
190
|
manifestPath,
|
|
100
191
|
homeRoute,
|
|
192
|
+
initialRoute,
|
|
101
193
|
history,
|
|
102
194
|
theme
|
|
103
195
|
})
|
|
104
196
|
).catch((err) => {
|
|
105
|
-
const message = `Application load failed. Unable to load one or more resources for
|
|
197
|
+
const message = `Application load failed. Unable to load one or more resources for ${options.id} with instance id ${instanceId}. ${err.message}`;
|
|
106
198
|
this.#logger.error({
|
|
107
199
|
message,
|
|
108
|
-
appId:
|
|
200
|
+
appId: id,
|
|
109
201
|
exception: err
|
|
110
202
|
});
|
|
111
203
|
throw new Error(message);
|
|
@@ -113,28 +205,31 @@ class CAppBridge {
|
|
|
113
205
|
};
|
|
114
206
|
#initApplication = async ({
|
|
115
207
|
id,
|
|
116
|
-
|
|
208
|
+
instanceId,
|
|
209
|
+
containerId,
|
|
117
210
|
hostUrl,
|
|
118
211
|
manifestPath,
|
|
119
212
|
homeRoute,
|
|
213
|
+
initialRoute,
|
|
120
214
|
history,
|
|
121
215
|
theme
|
|
122
216
|
}) => {
|
|
123
|
-
const app =
|
|
217
|
+
const app = this.#appRegistry.get({ id, instanceId });
|
|
124
218
|
if (!app) {
|
|
125
219
|
throw new Error(
|
|
126
|
-
`Application ${
|
|
220
|
+
`Application ${id} with instance id ${instanceId} is not found. Most probably the appId property of app.config.json is not set to ${id}`
|
|
127
221
|
);
|
|
128
222
|
}
|
|
129
223
|
if (!app.init || typeof app.init !== "function")
|
|
130
224
|
throw new Error(
|
|
131
|
-
`Application ${
|
|
225
|
+
`Application ${id} with instance id ${instanceId} doesn't expose init method`
|
|
132
226
|
);
|
|
133
227
|
const host = new import_microfeHost.CMicroFEHost({
|
|
134
228
|
guest: {
|
|
135
229
|
id
|
|
136
230
|
},
|
|
137
231
|
version: this.#version,
|
|
232
|
+
containerId,
|
|
138
233
|
logger: this.#logger,
|
|
139
234
|
soManager: this.#soManager,
|
|
140
235
|
eventManager: this.#eventManager
|
|
@@ -144,6 +239,7 @@ class CAppBridge {
|
|
|
144
239
|
hostUrl,
|
|
145
240
|
manifestPath,
|
|
146
241
|
homeRoute,
|
|
242
|
+
initialRoute,
|
|
147
243
|
prevState: null,
|
|
148
244
|
history,
|
|
149
245
|
theme,
|
|
@@ -153,8 +249,10 @@ class CAppBridge {
|
|
|
153
249
|
});
|
|
154
250
|
};
|
|
155
251
|
#loadApp = async (options) => {
|
|
156
|
-
const { id, files, name, hostUrl, documentEle } = options;
|
|
157
|
-
this.#logger.debug(
|
|
252
|
+
const { id, instanceId, files, name, hostUrl, documentEle, isJsModule } = options;
|
|
253
|
+
this.#logger.debug(
|
|
254
|
+
`Application ${id} with instance id ${instanceId} is loading...`
|
|
255
|
+
);
|
|
158
256
|
let assets = files;
|
|
159
257
|
const manifest = await import_loaders.ManifestLoader.get(options);
|
|
160
258
|
assets = import_loaders.ManifestLoader.getFullFileNameofAssets(manifest, files);
|
|
@@ -166,55 +264,191 @@ class CAppBridge {
|
|
|
166
264
|
hostUrl,
|
|
167
265
|
documentEle,
|
|
168
266
|
fileName,
|
|
169
|
-
index: counter
|
|
267
|
+
index: counter,
|
|
268
|
+
isJsModule
|
|
170
269
|
};
|
|
171
270
|
return !isCss(fileName) ? this.#scriptLoader.add(resourceOptions) : this.#styleLoader.add(resourceOptions);
|
|
172
271
|
});
|
|
173
272
|
await this.#waitAndInitApplication(options, requests);
|
|
174
|
-
this.#logger.audit(
|
|
273
|
+
this.#logger.audit(
|
|
274
|
+
`Application ${id} with instance id ${instanceId} loaded`
|
|
275
|
+
);
|
|
175
276
|
};
|
|
176
|
-
#unloadApp = ({ id, hostUrl, documentEle }) => {
|
|
177
|
-
this.#logger.debug(
|
|
178
|
-
|
|
277
|
+
#unloadApp = ({ id, instanceId, hostUrl, documentEle }) => {
|
|
278
|
+
this.#logger.debug(
|
|
279
|
+
`Application ${id} with instance id ${instanceId} unloading...`
|
|
280
|
+
);
|
|
281
|
+
const app = this.#appRegistry.get({
|
|
282
|
+
id,
|
|
283
|
+
instanceId
|
|
284
|
+
});
|
|
179
285
|
if (!app) return;
|
|
180
|
-
this.#removeAssetsFromDOM(
|
|
286
|
+
this.#removeAssetsFromDOM(instanceId, documentEle);
|
|
181
287
|
this.#scriptLoader.removeDynamicImportedScripts(hostUrl, documentEle);
|
|
182
288
|
this.#scriptLoader.removePrefetchLinks(hostUrl, documentEle);
|
|
183
289
|
this.#styleLoader.removeDynamicImportedStyles(hostUrl, documentEle);
|
|
184
|
-
|
|
185
|
-
this.#
|
|
186
|
-
|
|
290
|
+
this.#appRegistry.delete({ id, instanceId });
|
|
291
|
+
this.#logger.audit(
|
|
292
|
+
`Application ${id} with instance id ${instanceId} unloaded`
|
|
293
|
+
);
|
|
187
294
|
};
|
|
188
|
-
#mountApp = async ({ id,
|
|
189
|
-
const app =
|
|
295
|
+
#mountApp = async ({ id, instanceId }) => {
|
|
296
|
+
const app = this.#appRegistry.get({ id, instanceId });
|
|
190
297
|
if (!app?.mount || typeof app?.mount !== "function")
|
|
191
298
|
throw new Error(
|
|
192
|
-
`Application ${
|
|
299
|
+
`Application ${id} with instance id ${instanceId} doesn't expose mount method`
|
|
193
300
|
);
|
|
194
301
|
return app.mount({
|
|
195
|
-
containerId: `${
|
|
302
|
+
containerId: `${import_frame.FRAME_APP_CONTAINER_ID_PREFIX}${id}`,
|
|
196
303
|
hostBreakpoint: (0, import_window.getCurrentBreakpoint)(),
|
|
197
304
|
hostViewportSize: (0, import_window.getViewportSize)()
|
|
198
305
|
});
|
|
199
306
|
};
|
|
200
|
-
#unmountApp = ({ id,
|
|
201
|
-
const app =
|
|
307
|
+
#unmountApp = ({ id, instanceId }) => {
|
|
308
|
+
const app = this.#appRegistry.get({ id, instanceId });
|
|
202
309
|
if (!app?.unmount) return null;
|
|
203
310
|
if (typeof app.unmount !== "function")
|
|
204
311
|
throw new Error(
|
|
205
|
-
`Application ${
|
|
312
|
+
`Application ${id} with instance id ${instanceId} doesn't expose unmount method`
|
|
206
313
|
);
|
|
207
314
|
return app.unmount({
|
|
208
|
-
containerId: `${
|
|
315
|
+
containerId: `${import_frame.FRAME_APP_CONTAINER_ID_PREFIX}${id}`
|
|
209
316
|
});
|
|
210
317
|
};
|
|
318
|
+
/**
|
|
319
|
+
* manage session for the guest application by calling the keepSessionAlive method exposed by parent
|
|
320
|
+
* @param root0
|
|
321
|
+
* @param root0.id
|
|
322
|
+
* @param root0.instanceId
|
|
323
|
+
*/
|
|
324
|
+
#manageSession = ({ id, instanceId }) => {
|
|
325
|
+
if (!this.#extendSession) return;
|
|
326
|
+
try {
|
|
327
|
+
const appObj = this.#soManager.getObject(
|
|
328
|
+
import_pui_scripting_object.ScriptingObjectNames.Application
|
|
329
|
+
);
|
|
330
|
+
if (!appObj) {
|
|
331
|
+
this.#logger.warn({
|
|
332
|
+
message: `Application scripting object not available for ${id} to manage session`
|
|
333
|
+
});
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const app = this.#activeApps.get(instanceId);
|
|
337
|
+
if (!app) return;
|
|
338
|
+
app.keepAlive = (0, import_lodash.throttle)(
|
|
339
|
+
async () => {
|
|
340
|
+
try {
|
|
341
|
+
await appObj.keepSessionAlive();
|
|
342
|
+
} catch (e) {
|
|
343
|
+
this.#logger.error(
|
|
344
|
+
`Error keeping session alive. ${e.message}`
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
KEEP_ALIVE_INTERVAL
|
|
349
|
+
// throttle time
|
|
350
|
+
);
|
|
351
|
+
const frameEle = import_frame.Frame.get(instanceId);
|
|
352
|
+
userInteractionEvents.forEach((eventType) => {
|
|
353
|
+
frameEle?.contentDocument?.addEventListener(eventType, app.keepAlive);
|
|
354
|
+
});
|
|
355
|
+
} catch (err) {
|
|
356
|
+
this.#logger.warn({
|
|
357
|
+
message: `Application scripting object not available for ${id} to manage session`,
|
|
358
|
+
exception: err
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
/**
|
|
363
|
+
* clear session management for the guest application
|
|
364
|
+
* @param instanceId unique instance id of the application
|
|
365
|
+
* @param app
|
|
366
|
+
* @returns
|
|
367
|
+
*/
|
|
368
|
+
#clearSession = (app) => {
|
|
369
|
+
if (!this.#extendSession || !app) return;
|
|
370
|
+
const { keepAlive } = app;
|
|
371
|
+
if (keepAlive) {
|
|
372
|
+
userInteractionEvents.forEach((eventType) => {
|
|
373
|
+
document.removeEventListener(eventType, keepAlive);
|
|
374
|
+
});
|
|
375
|
+
app.keepAlive?.cancel();
|
|
376
|
+
}
|
|
377
|
+
};
|
|
211
378
|
/**
|
|
212
379
|
* registers scripting object to the host
|
|
213
380
|
* @param {ValueOf<AppObjects>} so scripting object
|
|
214
381
|
* @param {AddScriptingObjectParams} params params to add scripting object
|
|
215
382
|
*/
|
|
216
383
|
addScriptingObject = (so, params) => {
|
|
217
|
-
|
|
384
|
+
if ((0, import_microfe_common.isScriptingObjectProxy)(so)) {
|
|
385
|
+
const clonedSo = this.cloneScriptingObject(so);
|
|
386
|
+
this.#soManager.addScriptingObject(clonedSo, params);
|
|
387
|
+
} else {
|
|
388
|
+
this.#soManager.addScriptingObject(so, params);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
/**
|
|
392
|
+
* Create new Scripting Object from SSF scripting object proxy
|
|
393
|
+
* @param proxy - reference to the scripting object obtained through getObject method
|
|
394
|
+
* @returns cloned version of the scripting object
|
|
395
|
+
*/
|
|
396
|
+
cloneScriptingObject = (proxy) => {
|
|
397
|
+
if (!proxy) throw new Error("proxy is required");
|
|
398
|
+
const so = new import_microfe_common.ScriptingObject(proxy.id, proxy.objectType);
|
|
399
|
+
let unsubscribers = [];
|
|
400
|
+
Object.keys(proxy).forEach((propName) => {
|
|
401
|
+
const propValue = proxy[propName];
|
|
402
|
+
if (this.#isProxyEvent(propValue)) {
|
|
403
|
+
const event = new import_microfe_common.Event({
|
|
404
|
+
name: propValue.name || propName,
|
|
405
|
+
objectId: so.id
|
|
406
|
+
});
|
|
407
|
+
Object.defineProperty(so, propName, {
|
|
408
|
+
value: event,
|
|
409
|
+
enumerable: true
|
|
410
|
+
});
|
|
411
|
+
const listener = ({
|
|
412
|
+
eventParams,
|
|
413
|
+
eventOptions
|
|
414
|
+
}) => this.dispatchEvent({
|
|
415
|
+
event,
|
|
416
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
417
|
+
eventParams,
|
|
418
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
419
|
+
eventOptions
|
|
420
|
+
});
|
|
421
|
+
const token = propValue.subscribe(listener);
|
|
422
|
+
unsubscribers.push(() => {
|
|
423
|
+
propValue.unsubscribe(token);
|
|
424
|
+
});
|
|
425
|
+
} else if (this.#isFunction(propValue)) {
|
|
426
|
+
Object.defineProperty(so, propName, {
|
|
427
|
+
value: async (...args) => {
|
|
428
|
+
const retVal = await propValue(...args);
|
|
429
|
+
return (0, import_microfe_common.isScriptingObjectProxy)(retVal) ? this.cloneScriptingObject(retVal) : retVal;
|
|
430
|
+
},
|
|
431
|
+
enumerable: true
|
|
432
|
+
});
|
|
433
|
+
if (propName === "dispose") {
|
|
434
|
+
const defaultImpl = so.dispose;
|
|
435
|
+
Object.defineProperty(so, propName, {
|
|
436
|
+
value: () => {
|
|
437
|
+
so._dispose();
|
|
438
|
+
return defaultImpl.apply(so);
|
|
439
|
+
},
|
|
440
|
+
enumerable: true
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
so._dispose = () => {
|
|
446
|
+
unsubscribers.forEach((unsub) => {
|
|
447
|
+
unsub?.();
|
|
448
|
+
});
|
|
449
|
+
unsubscribers = [];
|
|
450
|
+
};
|
|
451
|
+
return so;
|
|
218
452
|
};
|
|
219
453
|
/**
|
|
220
454
|
* Close all active guest micro frontend applications
|
|
@@ -224,43 +458,68 @@ class CAppBridge {
|
|
|
224
458
|
};
|
|
225
459
|
/**
|
|
226
460
|
* Close guest micro frontend application
|
|
227
|
-
* @param
|
|
461
|
+
* @param instanceId unique instance id of the application
|
|
228
462
|
*/
|
|
229
|
-
closeApp = async (
|
|
230
|
-
if (!
|
|
231
|
-
const
|
|
232
|
-
if (!
|
|
233
|
-
|
|
463
|
+
closeApp = async (instanceId) => {
|
|
464
|
+
if (!instanceId) throw new Error("instanceId is required");
|
|
465
|
+
const app = this.#activeApps.get(instanceId);
|
|
466
|
+
if (!app) {
|
|
467
|
+
this.#logger.warn(
|
|
468
|
+
`Application with instance id ${instanceId} is not found`
|
|
469
|
+
);
|
|
470
|
+
return;
|
|
234
471
|
}
|
|
235
|
-
|
|
472
|
+
this.#activeApps.delete(instanceId);
|
|
473
|
+
const { id } = app;
|
|
474
|
+
const appConfig = this.#microFEConfig.getConfigById(id);
|
|
475
|
+
const { hostUrl } = appConfig;
|
|
236
476
|
try {
|
|
237
|
-
|
|
477
|
+
this.#clearSession(app);
|
|
478
|
+
await this.#unmountApp({ id, instanceId });
|
|
238
479
|
} finally {
|
|
239
|
-
const frameEle = import_frame.Frame.get(
|
|
240
|
-
if (
|
|
241
|
-
|
|
480
|
+
const frameEle = import_frame.Frame.get(instanceId);
|
|
481
|
+
if (frameEle?.contentDocument) {
|
|
482
|
+
this.#unloadApp({
|
|
483
|
+
id,
|
|
484
|
+
instanceId,
|
|
485
|
+
hostUrl,
|
|
486
|
+
documentEle: frameEle.contentDocument
|
|
487
|
+
});
|
|
242
488
|
}
|
|
243
|
-
|
|
244
|
-
this.#soManager.removeAllScriptingObjects(id);
|
|
245
|
-
import_frame.Frame.remove(id);
|
|
489
|
+
import_frame.Frame.remove(instanceId);
|
|
246
490
|
}
|
|
247
491
|
};
|
|
248
492
|
/**
|
|
249
493
|
* dispatch event to guest microfrontend application
|
|
250
|
-
* @param {DispatchEventParams<EventId, Params>} params - event parameters
|
|
494
|
+
* @param {DispatchEventParams<EventId, Params, Options>} params - event parameters
|
|
251
495
|
*/
|
|
252
|
-
dispatchEvent = async (params) =>
|
|
496
|
+
dispatchEvent = async (params) => {
|
|
497
|
+
const {
|
|
498
|
+
event: { id, name }
|
|
499
|
+
} = params;
|
|
500
|
+
if (!id) throw new Error("Event Id is required");
|
|
501
|
+
const objectId = id.split(".")?.[0];
|
|
502
|
+
const scriptingObject = this.#soManager.getObject(objectId);
|
|
503
|
+
if (!scriptingObject) {
|
|
504
|
+
this.#logger.warn(
|
|
505
|
+
`Attempt to dispatch event ${name} on unknown object ${objectId}`
|
|
506
|
+
);
|
|
507
|
+
return Promise.resolve();
|
|
508
|
+
}
|
|
509
|
+
return this.#eventManager.dispatchEvent(scriptingObject, params);
|
|
510
|
+
};
|
|
253
511
|
/**
|
|
254
|
-
* Get
|
|
512
|
+
* Get App by instanceId
|
|
255
513
|
* @param id unique id of guest
|
|
514
|
+
* @param instanceId
|
|
256
515
|
* @returns guest instance
|
|
257
516
|
*/
|
|
258
|
-
|
|
517
|
+
getApp = (instanceId) => this.#activeApps.get(instanceId)?.guest;
|
|
259
518
|
/**
|
|
260
|
-
* Get list of active
|
|
519
|
+
* Get list of active apps
|
|
261
520
|
* @returns list of active guests
|
|
262
521
|
*/
|
|
263
|
-
|
|
522
|
+
getApps = () => [...this.#activeApps.values()].map((app) => app.guest);
|
|
264
523
|
/**
|
|
265
524
|
* Initialize appBridge
|
|
266
525
|
*/
|
|
@@ -273,86 +532,114 @@ class CAppBridge {
|
|
|
273
532
|
};
|
|
274
533
|
/**
|
|
275
534
|
* Mount guest micro frontend application into DOM
|
|
276
|
-
* @param
|
|
277
|
-
* @throws Error if application with given id is not found in configuration
|
|
535
|
+
* @param instanceId unique instance id of guest micro frontend application
|
|
536
|
+
* @throws Error if application with given instance id is not found in configuration
|
|
278
537
|
*/
|
|
279
|
-
mountApp = async (
|
|
280
|
-
if (!
|
|
538
|
+
mountApp = async (instanceId) => {
|
|
539
|
+
if (!instanceId) throw new Error("instanceId is required");
|
|
540
|
+
const { id } = this.#activeApps.get(instanceId) || {};
|
|
541
|
+
if (!id) {
|
|
542
|
+
throw new Error(
|
|
543
|
+
`Application with instance id ${instanceId} is not found`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
281
546
|
const appConfig = this.#microFEConfig.getConfigById(id);
|
|
282
547
|
if (!appConfig) {
|
|
283
548
|
throw new Error(`Application with id ${id} is not found`);
|
|
284
549
|
}
|
|
285
|
-
await this.#mountApp(appConfig);
|
|
550
|
+
await this.#mountApp({ ...appConfig, instanceId });
|
|
286
551
|
};
|
|
287
552
|
/**
|
|
288
553
|
* Open guest micro frontend application
|
|
289
554
|
* @param {OpenAppParams} params - options to open guest application
|
|
290
555
|
*/
|
|
291
556
|
openApp = async (params) => {
|
|
292
|
-
const { id, frameOptions, history, theme } = params;
|
|
557
|
+
const { id, frameOptions, history, theme, homeRoute, initialRoute } = params;
|
|
558
|
+
const instanceId = (0, import_uuid.v4)();
|
|
293
559
|
const appConfig = this.#microFEConfig.getConfigById(id);
|
|
294
560
|
if (!appConfig) {
|
|
295
|
-
throw new Error(`Application
|
|
561
|
+
throw new Error(`Application ${id} is not found in app config`);
|
|
296
562
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
563
|
+
const frameEle = await import_frame.Frame.create({
|
|
564
|
+
id,
|
|
565
|
+
instanceId,
|
|
566
|
+
manifestPath: appConfig.manifestPath,
|
|
567
|
+
hostUrl: appConfig.hostUrl,
|
|
568
|
+
options: {
|
|
569
|
+
title: appConfig.name,
|
|
570
|
+
...frameOptions
|
|
571
|
+
}
|
|
302
572
|
});
|
|
303
573
|
if (!frameEle?.contentDocument)
|
|
304
574
|
throw new Error("unable to create iframe for the microapp");
|
|
305
575
|
try {
|
|
576
|
+
this.#appRegistry.add({
|
|
577
|
+
id,
|
|
578
|
+
instanceId,
|
|
579
|
+
documentEle: frameEle.contentDocument
|
|
580
|
+
});
|
|
306
581
|
await this.#loadApp({
|
|
307
|
-
|
|
582
|
+
instanceId,
|
|
308
583
|
history,
|
|
309
584
|
theme,
|
|
310
|
-
documentEle: frameEle.contentDocument
|
|
585
|
+
documentEle: frameEle.contentDocument,
|
|
586
|
+
containerId: frameOptions?.containerId,
|
|
587
|
+
...appConfig,
|
|
588
|
+
homeRoute: homeRoute ?? appConfig.homeRoute,
|
|
589
|
+
initialRoute
|
|
311
590
|
});
|
|
312
|
-
await this.#mountApp(appConfig);
|
|
313
|
-
|
|
591
|
+
await this.#mountApp({ instanceId, ...appConfig });
|
|
592
|
+
this.#manageSession({ id, instanceId });
|
|
593
|
+
return instanceId;
|
|
314
594
|
} catch (err) {
|
|
315
595
|
this.#unloadApp({
|
|
316
596
|
id,
|
|
597
|
+
instanceId,
|
|
317
598
|
hostUrl: appConfig.hostUrl,
|
|
318
599
|
documentEle: frameEle.contentDocument
|
|
319
600
|
});
|
|
320
|
-
import_frame.Frame.remove(
|
|
601
|
+
import_frame.Frame.remove(instanceId);
|
|
321
602
|
throw err;
|
|
322
603
|
}
|
|
323
604
|
};
|
|
324
|
-
/**
|
|
325
|
-
* emit event to all subscribers (deprecated)
|
|
326
|
-
* @deprecated use dispatchEvent instead
|
|
327
|
-
* @param eventId unique id of the event. The format is [scripting object name].[event name]
|
|
328
|
-
* @param data data to be sent to the subscribers of the event
|
|
329
|
-
* @returns true if event is published successfully
|
|
330
|
-
*/
|
|
331
|
-
publish = (eventId, data) => (0, import_pubsub_js.publish)(eventId, data);
|
|
332
605
|
/**
|
|
333
606
|
* remove all listeners
|
|
334
607
|
*/
|
|
335
|
-
|
|
608
|
+
removeAllEventSubscriptions = () => {
|
|
336
609
|
this.#eventManager.unsubscribeAll();
|
|
337
610
|
};
|
|
611
|
+
/**
|
|
612
|
+
* removes all scripting objects from host
|
|
613
|
+
* @param guestId unique id of the guest application
|
|
614
|
+
*/
|
|
615
|
+
removeAllScriptingObjects = (guestId) => {
|
|
616
|
+
this.#soManager.removeAllScriptingObjects(guestId);
|
|
617
|
+
};
|
|
338
618
|
/**
|
|
339
619
|
* removes scripting object from the host
|
|
340
620
|
* @param objectId unique id of the scripting object
|
|
621
|
+
* @param guestId
|
|
341
622
|
*/
|
|
342
|
-
removeScriptingObject = (objectId) => {
|
|
343
|
-
this.#soManager.removeScriptingObject(objectId);
|
|
623
|
+
removeScriptingObject = (objectId, guestId) => {
|
|
624
|
+
this.#soManager.removeScriptingObject(objectId, guestId);
|
|
344
625
|
};
|
|
345
626
|
/**
|
|
346
627
|
* Unmount guest micro frontend application from DOM
|
|
347
|
-
* @param
|
|
628
|
+
* @param instanceId unique instance id of guest micro frontend application
|
|
348
629
|
* @throws Error if application with given id is not found in configuration
|
|
349
630
|
*/
|
|
350
|
-
unmountApp = async (
|
|
351
|
-
if (!
|
|
631
|
+
unmountApp = async (instanceId) => {
|
|
632
|
+
if (!instanceId) throw new Error("instanceId is required");
|
|
633
|
+
const { id } = this.#activeApps.get(instanceId) || {};
|
|
634
|
+
if (!id) {
|
|
635
|
+
throw new Error(
|
|
636
|
+
`Application with instance id ${instanceId} is not found`
|
|
637
|
+
);
|
|
638
|
+
}
|
|
352
639
|
const appConfig = this.#microFEConfig.getConfigById(id);
|
|
353
640
|
if (!appConfig) {
|
|
354
641
|
throw new Error(`Application with id ${id} is not found`);
|
|
355
642
|
}
|
|
356
|
-
await this.#unmountApp(appConfig);
|
|
643
|
+
await this.#unmountApp({ ...appConfig, instanceId });
|
|
357
644
|
};
|
|
358
645
|
}
|