@elliemae/ssf-guest 2.22.0 → 2.23.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/guest.js +97 -73
- package/dist/cjs/utils.js +24 -14
- package/dist/cjs/v1-adapter.js +11 -7
- package/dist/esm/guest.js +86 -73
- package/dist/esm/utils.js +24 -14
- package/dist/esm/v1-adapter.js +11 -7
- package/dist/public/creditService.html +1 -1
- package/dist/public/index.html +1 -1
- package/dist/public/js/emuiSsfGuest.47c94d8a6fa51e37cd64.js +3 -0
- package/dist/public/js/emuiSsfGuest.47c94d8a6fa51e37cd64.js.br +0 -0
- package/dist/public/js/emuiSsfGuest.47c94d8a6fa51e37cd64.js.gz +0 -0
- package/dist/public/js/emuiSsfGuest.47c94d8a6fa51e37cd64.js.map +1 -0
- package/dist/public/loanValidation.html +1 -1
- package/dist/public/pricingService.html +1 -1
- package/dist/public/pricingService.js +1 -1
- package/dist/public/pricingService.js.br +0 -0
- package/dist/public/pricingService.js.gz +0 -0
- package/dist/public/pricingService.js.map +1 -1
- package/dist/public/titleService.html +1 -1
- package/dist/public/v2-guest.html +1 -1
- package/dist/types/lib/guest.d.ts +1 -1
- package/dist/types/lib/tests/utils.test.d.ts +1 -0
- package/dist/types/lib/typings/window.d.ts +4 -3
- package/dist/types/lib/utils.d.ts +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/umd/index.js +1 -27
- 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/pricingService.js +1 -1
- package/dist/umd/pricingService.js.br +0 -0
- package/dist/umd/pricingService.js.gz +0 -0
- package/dist/umd/pricingService.js.map +1 -1
- package/package.json +18 -19
- package/dist/public/js/emuiSsfGuest.60315897b4b299913718.js +0 -29
- package/dist/public/js/emuiSsfGuest.60315897b4b299913718.js.br +0 -0
- package/dist/public/js/emuiSsfGuest.60315897b4b299913718.js.gz +0 -0
- package/dist/public/js/emuiSsfGuest.60315897b4b299913718.js.map +0 -1
package/dist/cjs/guest.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
var guest_exports = {};
|
|
20
30
|
__export(guest_exports, {
|
|
@@ -22,7 +32,7 @@ __export(guest_exports, {
|
|
|
22
32
|
});
|
|
23
33
|
module.exports = __toCommonJS(guest_exports);
|
|
24
34
|
var import_uuid = require("uuid");
|
|
25
|
-
var
|
|
35
|
+
var import_throttle = __toESM(require("lodash/throttle"), 1);
|
|
26
36
|
var import_microfe_common = require("@elliemae/microfe-common");
|
|
27
37
|
var import_pui_diagnostics = require("@elliemae/pui-diagnostics");
|
|
28
38
|
var import_utils = require("./utils.js");
|
|
@@ -92,6 +102,17 @@ class SSFGuest {
|
|
|
92
102
|
#url = null;
|
|
93
103
|
#hostOrigin = null;
|
|
94
104
|
#hostWindow = null;
|
|
105
|
+
#parentCloseMonitor = null;
|
|
106
|
+
#regexCache = /* @__PURE__ */ new Map();
|
|
107
|
+
/** Returns non-null host references or throws a descriptive error. */
|
|
108
|
+
#requireHost() {
|
|
109
|
+
if (!this.#hostWindow || !this.#hostOrigin) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
"Guest is not connected to a host. Call connect() first."
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return { hostWindow: this.#hostWindow, hostOrigin: this.#hostOrigin };
|
|
115
|
+
}
|
|
95
116
|
/**
|
|
96
117
|
* get bearer token to access api during connect operation
|
|
97
118
|
*/
|
|
@@ -184,7 +205,8 @@ class SSFGuest {
|
|
|
184
205
|
value: async (...args) => this.#invoke({
|
|
185
206
|
objectId: ctrl.id,
|
|
186
207
|
functionName,
|
|
187
|
-
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
209
|
+
functionParams: [...args]
|
|
188
210
|
}),
|
|
189
211
|
enumerable: true
|
|
190
212
|
});
|
|
@@ -237,9 +259,10 @@ class SSFGuest {
|
|
|
237
259
|
}
|
|
238
260
|
}
|
|
239
261
|
await Promise.all(promises);
|
|
262
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
240
263
|
const response = await this.#remoting.invoke({
|
|
241
|
-
targetWin:
|
|
242
|
-
targetOrigin:
|
|
264
|
+
targetWin: hostWindow,
|
|
265
|
+
targetOrigin: hostOrigin,
|
|
243
266
|
messageType: import_microfe_common.MessageType.ObjectInvoke,
|
|
244
267
|
messageBody: {
|
|
245
268
|
objectId,
|
|
@@ -289,7 +312,11 @@ class SSFGuest {
|
|
|
289
312
|
}
|
|
290
313
|
if ("regex" in condition) {
|
|
291
314
|
try {
|
|
292
|
-
|
|
315
|
+
let regex = this.#regexCache.get(condition.regex);
|
|
316
|
+
if (!regex) {
|
|
317
|
+
regex = new RegExp(condition.regex);
|
|
318
|
+
this.#regexCache.set(condition.regex, regex);
|
|
319
|
+
}
|
|
293
320
|
return typeof value === "string" && regex.test(value);
|
|
294
321
|
} catch {
|
|
295
322
|
return false;
|
|
@@ -348,7 +375,7 @@ class SSFGuest {
|
|
|
348
375
|
*/
|
|
349
376
|
#handleParentClose = () => {
|
|
350
377
|
if (!(0, import_utils.isEmbedded)()) {
|
|
351
|
-
setInterval(() => {
|
|
378
|
+
this.#parentCloseMonitor = setInterval(() => {
|
|
352
379
|
if (this.#hostWindow?.closed) {
|
|
353
380
|
this.close().then(() => {
|
|
354
381
|
window.close();
|
|
@@ -453,18 +480,24 @@ class SSFGuest {
|
|
|
453
480
|
*/
|
|
454
481
|
#extendTokenLifetime = async () => {
|
|
455
482
|
if (!this.#authToken || !this.#authClientId || !this.#hostDomain) return;
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
token
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
483
|
+
try {
|
|
484
|
+
await fetch(
|
|
485
|
+
`${this.#hostDomain}/oauth2/v1/token/introspection?${new URLSearchParams({
|
|
486
|
+
token: this.#authToken,
|
|
487
|
+
client_id: this.#authClientId
|
|
488
|
+
}).toString()}`,
|
|
489
|
+
{
|
|
490
|
+
headers: {
|
|
491
|
+
"content-type": "application/x-www-form-urlencoded;charset=UTF-8"
|
|
492
|
+
},
|
|
493
|
+
method: "POST"
|
|
494
|
+
}
|
|
495
|
+
);
|
|
496
|
+
} catch (e) {
|
|
497
|
+
this.#logger.warn(
|
|
498
|
+
`Failed to extend token lifetime: ${e.message}`
|
|
499
|
+
);
|
|
500
|
+
}
|
|
468
501
|
};
|
|
469
502
|
/**
|
|
470
503
|
* revoke token
|
|
@@ -499,7 +532,7 @@ class SSFGuest {
|
|
|
499
532
|
try {
|
|
500
533
|
const appObj = await this.getObject("application");
|
|
501
534
|
if (appObj) {
|
|
502
|
-
this.#throttledKeepAlive = (0,
|
|
535
|
+
this.#throttledKeepAlive = (0, import_throttle.default)(
|
|
503
536
|
async () => {
|
|
504
537
|
try {
|
|
505
538
|
await appObj.keepSessionAlive();
|
|
@@ -529,35 +562,6 @@ class SSFGuest {
|
|
|
529
562
|
}
|
|
530
563
|
}
|
|
531
564
|
};
|
|
532
|
-
/**
|
|
533
|
-
* send all log messages to parent
|
|
534
|
-
*/
|
|
535
|
-
#useParentApplicationLogger = async () => {
|
|
536
|
-
try {
|
|
537
|
-
const moduleObj = await this.getObject("module");
|
|
538
|
-
if (moduleObj?.log && !this.#loggerOptions.console) {
|
|
539
|
-
const {
|
|
540
|
-
index = "",
|
|
541
|
-
team = "",
|
|
542
|
-
appName = ""
|
|
543
|
-
} = this.#loggerOptions || {};
|
|
544
|
-
if (!index || !team || !appName)
|
|
545
|
-
throw new Error(
|
|
546
|
-
"Missing one of required logger options: index, team, appName"
|
|
547
|
-
);
|
|
548
|
-
this.#logger = (0, import_pui_diagnostics.logger)({
|
|
549
|
-
transport: (0, import_pui_diagnostics.parentApp)(moduleObj),
|
|
550
|
-
index,
|
|
551
|
-
team,
|
|
552
|
-
appName
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
} catch (e) {
|
|
556
|
-
this.#logger.info(
|
|
557
|
-
`Module object not exposed from hosting application. using local logger instance. ${e.message}`
|
|
558
|
-
);
|
|
559
|
-
}
|
|
560
|
-
};
|
|
561
565
|
/**
|
|
562
566
|
* Initialize guest using script
|
|
563
567
|
* @param {string} scriptUri uri of the script
|
|
@@ -569,14 +573,25 @@ class SSFGuest {
|
|
|
569
573
|
const scriptEle = document.createElement("script");
|
|
570
574
|
scriptEle.setAttribute("src", scriptUri);
|
|
571
575
|
scriptEle.setAttribute("type", "module");
|
|
572
|
-
await new Promise((resolve) => {
|
|
573
|
-
|
|
574
|
-
|
|
576
|
+
await new Promise((resolve, reject) => {
|
|
577
|
+
let onScriptLoad;
|
|
578
|
+
let onScriptError;
|
|
579
|
+
const cleanup = () => {
|
|
580
|
+
scriptEle.removeEventListener("load", onScriptLoad);
|
|
581
|
+
scriptEle.removeEventListener("error", onScriptError);
|
|
582
|
+
};
|
|
583
|
+
onScriptLoad = () => {
|
|
584
|
+
cleanup();
|
|
575
585
|
this.#created = true;
|
|
576
586
|
(0, import_v1_adapter.setScriptOnlyGuest)(true);
|
|
577
587
|
resolve();
|
|
578
588
|
};
|
|
589
|
+
onScriptError = () => {
|
|
590
|
+
cleanup();
|
|
591
|
+
reject(new Error(`Failed to load script: ${scriptUri}`));
|
|
592
|
+
};
|
|
579
593
|
scriptEle.addEventListener("load", onScriptLoad);
|
|
594
|
+
scriptEle.addEventListener("error", onScriptError);
|
|
580
595
|
this.#scriptElement = containerElement.appendChild(scriptEle);
|
|
581
596
|
});
|
|
582
597
|
}
|
|
@@ -586,17 +601,23 @@ class SSFGuest {
|
|
|
586
601
|
*/
|
|
587
602
|
close = async () => {
|
|
588
603
|
if (!this.#isConnected) return;
|
|
589
|
-
this.#
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
604
|
+
if (this.#hostWindow && this.#hostOrigin) {
|
|
605
|
+
this.#remoting.send({
|
|
606
|
+
targetWin: this.#hostWindow,
|
|
607
|
+
targetOrigin: this.#hostOrigin,
|
|
608
|
+
messageType: import_microfe_common.MessageType.GuestClose,
|
|
609
|
+
messageBody: {}
|
|
610
|
+
});
|
|
611
|
+
this.#remoting.removeSender({
|
|
612
|
+
origin: this.#hostOrigin,
|
|
613
|
+
window: this.#hostWindow
|
|
614
|
+
});
|
|
615
|
+
}
|
|
599
616
|
this.#remoting.close();
|
|
617
|
+
if (this.#parentCloseMonitor) {
|
|
618
|
+
clearInterval(this.#parentCloseMonitor);
|
|
619
|
+
this.#parentCloseMonitor = null;
|
|
620
|
+
}
|
|
600
621
|
if (this.#throttledKeepAlive) {
|
|
601
622
|
userInteractionEvents.forEach((eventType) => {
|
|
602
623
|
document.removeEventListener(eventType, this.#throttledKeepAlive);
|
|
@@ -623,10 +644,9 @@ class SSFGuest {
|
|
|
623
644
|
let guestWindow = window;
|
|
624
645
|
let guestOptions = { ...capabilities };
|
|
625
646
|
if (param) {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
guestOptions = Object.assign(guestOptions, clonedOptions);
|
|
647
|
+
const { window: paramWindow, ...restOptions } = param;
|
|
648
|
+
if (paramWindow) guestWindow = paramWindow;
|
|
649
|
+
guestOptions = { ...guestOptions, ...restOptions };
|
|
630
650
|
}
|
|
631
651
|
const hostDetails = await (0, import_utils.getHostDetails)();
|
|
632
652
|
this.#hostOrigin = hostDetails.origin;
|
|
@@ -706,9 +726,10 @@ class SSFGuest {
|
|
|
706
726
|
`Retrieving scripting object "${objectId}" from host...`
|
|
707
727
|
);
|
|
708
728
|
if (!this.#isConnected) throw new Error("Not connected to host");
|
|
729
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
709
730
|
const response = await this.#remoting.invoke({
|
|
710
|
-
targetWin:
|
|
711
|
-
targetOrigin:
|
|
731
|
+
targetWin: hostWindow,
|
|
732
|
+
targetOrigin: hostOrigin,
|
|
712
733
|
messageType: import_microfe_common.MessageType.ObjectGet,
|
|
713
734
|
messageBody: {
|
|
714
735
|
objectId
|
|
@@ -731,9 +752,10 @@ class SSFGuest {
|
|
|
731
752
|
`Retrieving names of scripting objects exposed by host...`
|
|
732
753
|
);
|
|
733
754
|
if (!this.#isConnected) throw new Error("Not connected to host");
|
|
755
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
734
756
|
const objects = await this.#remoting.invoke({
|
|
735
|
-
targetWin:
|
|
736
|
-
targetOrigin:
|
|
757
|
+
targetWin: hostWindow,
|
|
758
|
+
targetOrigin: hostOrigin,
|
|
737
759
|
messageType: import_microfe_common.MessageType.ListObjects,
|
|
738
760
|
messageBody: {}
|
|
739
761
|
});
|
|
@@ -774,9 +796,10 @@ class SSFGuest {
|
|
|
774
796
|
const token = (0, import_uuid.v4)();
|
|
775
797
|
listeners.push({ callback, token, criteria });
|
|
776
798
|
this.#eventListeners.set(eventId.toLowerCase(), listeners);
|
|
799
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
777
800
|
this.#remoting.send({
|
|
778
|
-
targetWin:
|
|
779
|
-
targetOrigin:
|
|
801
|
+
targetWin: hostWindow,
|
|
802
|
+
targetOrigin: hostOrigin,
|
|
780
803
|
messageType: import_microfe_common.MessageType.GuestEventSubscribe,
|
|
781
804
|
messageBody: {
|
|
782
805
|
eventId,
|
|
@@ -801,9 +824,10 @@ class SSFGuest {
|
|
|
801
824
|
);
|
|
802
825
|
if (filteredListeners.length < originalLength) {
|
|
803
826
|
this.#eventListeners.set(eventId.toLowerCase(), filteredListeners);
|
|
827
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
804
828
|
this.#remoting.send({
|
|
805
|
-
targetWin:
|
|
806
|
-
targetOrigin:
|
|
829
|
+
targetWin: hostWindow,
|
|
830
|
+
targetOrigin: hostOrigin,
|
|
807
831
|
messageType: import_microfe_common.MessageType.GuestEventUnsubscribe,
|
|
808
832
|
messageBody: {
|
|
809
833
|
eventId,
|
package/dist/cjs/utils.js
CHANGED
|
@@ -38,44 +38,54 @@ const getOrigin = (url) => {
|
|
|
38
38
|
if (!url || url === "about:blank") return "*";
|
|
39
39
|
try {
|
|
40
40
|
const { origin } = new URL(url);
|
|
41
|
-
return origin === "null" || !origin ?
|
|
42
|
-
} catch
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
return origin === "null" || !origin ? "*" : origin;
|
|
42
|
+
} catch {
|
|
43
|
+
try {
|
|
44
|
+
const { origin } = new URL(url, document.baseURI);
|
|
45
|
+
return origin === "null" || !origin ? "*" : origin;
|
|
46
|
+
} catch {
|
|
47
|
+
return "*";
|
|
48
|
+
}
|
|
45
49
|
}
|
|
46
50
|
};
|
|
47
51
|
const isEmbedded = () => window.self !== window.parent;
|
|
48
52
|
const getComputedStyle = (prop, el) => {
|
|
49
|
-
const
|
|
50
|
-
const retVal = document.defaultView?.getComputedStyle?.(
|
|
53
|
+
const element = el || document.body;
|
|
54
|
+
const retVal = document.defaultView?.getComputedStyle?.(element, null);
|
|
51
55
|
const propValue = retVal ? retVal[prop] : "0";
|
|
52
56
|
return parseInt(propValue, 10);
|
|
53
57
|
};
|
|
54
|
-
const originsRegex =
|
|
55
|
-
`^https?://(.*.elliemae.io|.*.ellielabs.com|.*.ellieservices.com|.*.encompassloconnect.com|.*.ice.com|localhost:[0-9]+)`,
|
|
56
|
-
"i"
|
|
57
|
-
);
|
|
58
|
+
const originsRegex = /^https?:\/\/([a-z0-9-]+\.)*(?:elliemae\.io|ellielabs\.com|ellieservices\.com|encompassloconnect\.com|ice\.com|localhost:[0-9]+)$/i;
|
|
58
59
|
const MESSAGE_SOURCE = "elli:remoting";
|
|
59
|
-
const
|
|
60
|
+
const HANDSHAKE_TIMEOUT_MS = 3e4;
|
|
61
|
+
const getHostDetails = () => new Promise((resolve, reject) => {
|
|
60
62
|
if (!isEmbedded()) {
|
|
61
63
|
const currentWindow = window;
|
|
64
|
+
let timer;
|
|
62
65
|
const onMessage = (event) => {
|
|
63
66
|
if (originsRegex.test(event.origin)) {
|
|
64
67
|
const { source, type } = event.data || {};
|
|
65
68
|
if (source === MESSAGE_SOURCE && type === import_microfe_common.MessageType.HandShake) {
|
|
66
69
|
const { origin } = event;
|
|
67
|
-
const
|
|
70
|
+
const hostWindow = event.source;
|
|
71
|
+
clearTimeout(timer);
|
|
68
72
|
(0, import_microfe_common.sendMessage)({
|
|
69
|
-
targetWin:
|
|
73
|
+
targetWin: hostWindow,
|
|
70
74
|
targetOrigin: origin,
|
|
71
75
|
messageType: import_microfe_common.MessageType.HandShakeAck,
|
|
72
76
|
messageBody: {}
|
|
73
77
|
});
|
|
74
78
|
currentWindow.removeEventListener("message", onMessage);
|
|
75
|
-
resolve({ origin, window:
|
|
79
|
+
resolve({ origin, window: hostWindow });
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
};
|
|
83
|
+
timer = setTimeout(() => {
|
|
84
|
+
currentWindow.removeEventListener("message", onMessage);
|
|
85
|
+
reject(
|
|
86
|
+
new Error(`Host handshake timed out after ${HANDSHAKE_TIMEOUT_MS}ms`)
|
|
87
|
+
);
|
|
88
|
+
}, HANDSHAKE_TIMEOUT_MS);
|
|
79
89
|
currentWindow.addEventListener("message", onMessage);
|
|
80
90
|
} else {
|
|
81
91
|
resolve({
|
package/dist/cjs/v1-adapter.js
CHANGED
|
@@ -40,15 +40,16 @@ const setupV1Adapter = (guestV2 = null) => {
|
|
|
40
40
|
window.elli = window.elli ?? {};
|
|
41
41
|
window.elli.script = {
|
|
42
42
|
guest: {
|
|
43
|
-
create:
|
|
43
|
+
create: (scriptUri, element) => getGuest().addScript(scriptUri, element)
|
|
44
44
|
},
|
|
45
|
-
connect:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
connect: (params) => {
|
|
46
|
+
if (!scriptOnlyGuest)
|
|
47
|
+
console.warn(
|
|
48
|
+
"elli.script.connect is deprecated. Please use connect method of SSFGuest class instead, const guest = new ice.guest.SSFGuest(); await guest.connect(params);"
|
|
49
|
+
);
|
|
49
50
|
return getGuest().connect(params);
|
|
50
51
|
},
|
|
51
|
-
getObject:
|
|
52
|
+
getObject: (objectName) => {
|
|
52
53
|
if (!scriptOnlyGuest)
|
|
53
54
|
console.warn(
|
|
54
55
|
"elli.script.getObject is deprecated. Please use getObject method of SSFGuest class instead, const guest = new ice.guest.SSFGuest(); await guest.getObject(objectName);"
|
|
@@ -91,4 +92,7 @@ const setupV1Adapter = (guestV2 = null) => {
|
|
|
91
92
|
}
|
|
92
93
|
};
|
|
93
94
|
};
|
|
94
|
-
|
|
95
|
+
try {
|
|
96
|
+
setupV1Adapter();
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
package/dist/esm/guest.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from "uuid";
|
|
2
|
-
import
|
|
2
|
+
import throttle from "lodash/throttle";
|
|
3
3
|
import {
|
|
4
4
|
Remoting,
|
|
5
5
|
sendMessage,
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
logger as puiLogger,
|
|
13
13
|
Console,
|
|
14
14
|
http,
|
|
15
|
-
parentApp,
|
|
16
15
|
webvitals,
|
|
17
16
|
logUnhandledErrors
|
|
18
17
|
} from "@elliemae/pui-diagnostics";
|
|
@@ -88,6 +87,17 @@ class SSFGuest {
|
|
|
88
87
|
#url = null;
|
|
89
88
|
#hostOrigin = null;
|
|
90
89
|
#hostWindow = null;
|
|
90
|
+
#parentCloseMonitor = null;
|
|
91
|
+
#regexCache = /* @__PURE__ */ new Map();
|
|
92
|
+
/** Returns non-null host references or throws a descriptive error. */
|
|
93
|
+
#requireHost() {
|
|
94
|
+
if (!this.#hostWindow || !this.#hostOrigin) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
"Guest is not connected to a host. Call connect() first."
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return { hostWindow: this.#hostWindow, hostOrigin: this.#hostOrigin };
|
|
100
|
+
}
|
|
91
101
|
/**
|
|
92
102
|
* get bearer token to access api during connect operation
|
|
93
103
|
*/
|
|
@@ -180,7 +190,8 @@ class SSFGuest {
|
|
|
180
190
|
value: async (...args) => this.#invoke({
|
|
181
191
|
objectId: ctrl.id,
|
|
182
192
|
functionName,
|
|
183
|
-
|
|
193
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
194
|
+
functionParams: [...args]
|
|
184
195
|
}),
|
|
185
196
|
enumerable: true
|
|
186
197
|
});
|
|
@@ -233,9 +244,10 @@ class SSFGuest {
|
|
|
233
244
|
}
|
|
234
245
|
}
|
|
235
246
|
await Promise.all(promises);
|
|
247
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
236
248
|
const response = await this.#remoting.invoke({
|
|
237
|
-
targetWin:
|
|
238
|
-
targetOrigin:
|
|
249
|
+
targetWin: hostWindow,
|
|
250
|
+
targetOrigin: hostOrigin,
|
|
239
251
|
messageType: MessageType.ObjectInvoke,
|
|
240
252
|
messageBody: {
|
|
241
253
|
objectId,
|
|
@@ -285,7 +297,11 @@ class SSFGuest {
|
|
|
285
297
|
}
|
|
286
298
|
if ("regex" in condition) {
|
|
287
299
|
try {
|
|
288
|
-
|
|
300
|
+
let regex = this.#regexCache.get(condition.regex);
|
|
301
|
+
if (!regex) {
|
|
302
|
+
regex = new RegExp(condition.regex);
|
|
303
|
+
this.#regexCache.set(condition.regex, regex);
|
|
304
|
+
}
|
|
289
305
|
return typeof value === "string" && regex.test(value);
|
|
290
306
|
} catch {
|
|
291
307
|
return false;
|
|
@@ -344,7 +360,7 @@ class SSFGuest {
|
|
|
344
360
|
*/
|
|
345
361
|
#handleParentClose = () => {
|
|
346
362
|
if (!isEmbedded()) {
|
|
347
|
-
setInterval(() => {
|
|
363
|
+
this.#parentCloseMonitor = setInterval(() => {
|
|
348
364
|
if (this.#hostWindow?.closed) {
|
|
349
365
|
this.close().then(() => {
|
|
350
366
|
window.close();
|
|
@@ -449,18 +465,24 @@ class SSFGuest {
|
|
|
449
465
|
*/
|
|
450
466
|
#extendTokenLifetime = async () => {
|
|
451
467
|
if (!this.#authToken || !this.#authClientId || !this.#hostDomain) return;
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
token
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
468
|
+
try {
|
|
469
|
+
await fetch(
|
|
470
|
+
`${this.#hostDomain}/oauth2/v1/token/introspection?${new URLSearchParams({
|
|
471
|
+
token: this.#authToken,
|
|
472
|
+
client_id: this.#authClientId
|
|
473
|
+
}).toString()}`,
|
|
474
|
+
{
|
|
475
|
+
headers: {
|
|
476
|
+
"content-type": "application/x-www-form-urlencoded;charset=UTF-8"
|
|
477
|
+
},
|
|
478
|
+
method: "POST"
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
} catch (e) {
|
|
482
|
+
this.#logger.warn(
|
|
483
|
+
`Failed to extend token lifetime: ${e.message}`
|
|
484
|
+
);
|
|
485
|
+
}
|
|
464
486
|
};
|
|
465
487
|
/**
|
|
466
488
|
* revoke token
|
|
@@ -525,35 +547,6 @@ class SSFGuest {
|
|
|
525
547
|
}
|
|
526
548
|
}
|
|
527
549
|
};
|
|
528
|
-
/**
|
|
529
|
-
* send all log messages to parent
|
|
530
|
-
*/
|
|
531
|
-
#useParentApplicationLogger = async () => {
|
|
532
|
-
try {
|
|
533
|
-
const moduleObj = await this.getObject("module");
|
|
534
|
-
if (moduleObj?.log && !this.#loggerOptions.console) {
|
|
535
|
-
const {
|
|
536
|
-
index = "",
|
|
537
|
-
team = "",
|
|
538
|
-
appName = ""
|
|
539
|
-
} = this.#loggerOptions || {};
|
|
540
|
-
if (!index || !team || !appName)
|
|
541
|
-
throw new Error(
|
|
542
|
-
"Missing one of required logger options: index, team, appName"
|
|
543
|
-
);
|
|
544
|
-
this.#logger = puiLogger({
|
|
545
|
-
transport: parentApp(moduleObj),
|
|
546
|
-
index,
|
|
547
|
-
team,
|
|
548
|
-
appName
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
} catch (e) {
|
|
552
|
-
this.#logger.info(
|
|
553
|
-
`Module object not exposed from hosting application. using local logger instance. ${e.message}`
|
|
554
|
-
);
|
|
555
|
-
}
|
|
556
|
-
};
|
|
557
550
|
/**
|
|
558
551
|
* Initialize guest using script
|
|
559
552
|
* @param {string} scriptUri uri of the script
|
|
@@ -565,14 +558,25 @@ class SSFGuest {
|
|
|
565
558
|
const scriptEle = document.createElement("script");
|
|
566
559
|
scriptEle.setAttribute("src", scriptUri);
|
|
567
560
|
scriptEle.setAttribute("type", "module");
|
|
568
|
-
await new Promise((resolve) => {
|
|
569
|
-
|
|
570
|
-
|
|
561
|
+
await new Promise((resolve, reject) => {
|
|
562
|
+
let onScriptLoad;
|
|
563
|
+
let onScriptError;
|
|
564
|
+
const cleanup = () => {
|
|
565
|
+
scriptEle.removeEventListener("load", onScriptLoad);
|
|
566
|
+
scriptEle.removeEventListener("error", onScriptError);
|
|
567
|
+
};
|
|
568
|
+
onScriptLoad = () => {
|
|
569
|
+
cleanup();
|
|
571
570
|
this.#created = true;
|
|
572
571
|
setScriptOnlyGuest(true);
|
|
573
572
|
resolve();
|
|
574
573
|
};
|
|
574
|
+
onScriptError = () => {
|
|
575
|
+
cleanup();
|
|
576
|
+
reject(new Error(`Failed to load script: ${scriptUri}`));
|
|
577
|
+
};
|
|
575
578
|
scriptEle.addEventListener("load", onScriptLoad);
|
|
579
|
+
scriptEle.addEventListener("error", onScriptError);
|
|
576
580
|
this.#scriptElement = containerElement.appendChild(scriptEle);
|
|
577
581
|
});
|
|
578
582
|
}
|
|
@@ -582,17 +586,23 @@ class SSFGuest {
|
|
|
582
586
|
*/
|
|
583
587
|
close = async () => {
|
|
584
588
|
if (!this.#isConnected) return;
|
|
585
|
-
this.#
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
589
|
+
if (this.#hostWindow && this.#hostOrigin) {
|
|
590
|
+
this.#remoting.send({
|
|
591
|
+
targetWin: this.#hostWindow,
|
|
592
|
+
targetOrigin: this.#hostOrigin,
|
|
593
|
+
messageType: MessageType.GuestClose,
|
|
594
|
+
messageBody: {}
|
|
595
|
+
});
|
|
596
|
+
this.#remoting.removeSender({
|
|
597
|
+
origin: this.#hostOrigin,
|
|
598
|
+
window: this.#hostWindow
|
|
599
|
+
});
|
|
600
|
+
}
|
|
595
601
|
this.#remoting.close();
|
|
602
|
+
if (this.#parentCloseMonitor) {
|
|
603
|
+
clearInterval(this.#parentCloseMonitor);
|
|
604
|
+
this.#parentCloseMonitor = null;
|
|
605
|
+
}
|
|
596
606
|
if (this.#throttledKeepAlive) {
|
|
597
607
|
userInteractionEvents.forEach((eventType) => {
|
|
598
608
|
document.removeEventListener(eventType, this.#throttledKeepAlive);
|
|
@@ -619,10 +629,9 @@ class SSFGuest {
|
|
|
619
629
|
let guestWindow = window;
|
|
620
630
|
let guestOptions = { ...capabilities };
|
|
621
631
|
if (param) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
guestOptions = Object.assign(guestOptions, clonedOptions);
|
|
632
|
+
const { window: paramWindow, ...restOptions } = param;
|
|
633
|
+
if (paramWindow) guestWindow = paramWindow;
|
|
634
|
+
guestOptions = { ...guestOptions, ...restOptions };
|
|
626
635
|
}
|
|
627
636
|
const hostDetails = await getHostDetails();
|
|
628
637
|
this.#hostOrigin = hostDetails.origin;
|
|
@@ -702,9 +711,10 @@ class SSFGuest {
|
|
|
702
711
|
`Retrieving scripting object "${objectId}" from host...`
|
|
703
712
|
);
|
|
704
713
|
if (!this.#isConnected) throw new Error("Not connected to host");
|
|
714
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
705
715
|
const response = await this.#remoting.invoke({
|
|
706
|
-
targetWin:
|
|
707
|
-
targetOrigin:
|
|
716
|
+
targetWin: hostWindow,
|
|
717
|
+
targetOrigin: hostOrigin,
|
|
708
718
|
messageType: MessageType.ObjectGet,
|
|
709
719
|
messageBody: {
|
|
710
720
|
objectId
|
|
@@ -727,9 +737,10 @@ class SSFGuest {
|
|
|
727
737
|
`Retrieving names of scripting objects exposed by host...`
|
|
728
738
|
);
|
|
729
739
|
if (!this.#isConnected) throw new Error("Not connected to host");
|
|
740
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
730
741
|
const objects = await this.#remoting.invoke({
|
|
731
|
-
targetWin:
|
|
732
|
-
targetOrigin:
|
|
742
|
+
targetWin: hostWindow,
|
|
743
|
+
targetOrigin: hostOrigin,
|
|
733
744
|
messageType: MessageType.ListObjects,
|
|
734
745
|
messageBody: {}
|
|
735
746
|
});
|
|
@@ -770,9 +781,10 @@ class SSFGuest {
|
|
|
770
781
|
const token = uuidv4();
|
|
771
782
|
listeners.push({ callback, token, criteria });
|
|
772
783
|
this.#eventListeners.set(eventId.toLowerCase(), listeners);
|
|
784
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
773
785
|
this.#remoting.send({
|
|
774
|
-
targetWin:
|
|
775
|
-
targetOrigin:
|
|
786
|
+
targetWin: hostWindow,
|
|
787
|
+
targetOrigin: hostOrigin,
|
|
776
788
|
messageType: MessageType.GuestEventSubscribe,
|
|
777
789
|
messageBody: {
|
|
778
790
|
eventId,
|
|
@@ -797,9 +809,10 @@ class SSFGuest {
|
|
|
797
809
|
);
|
|
798
810
|
if (filteredListeners.length < originalLength) {
|
|
799
811
|
this.#eventListeners.set(eventId.toLowerCase(), filteredListeners);
|
|
812
|
+
const { hostWindow, hostOrigin } = this.#requireHost();
|
|
800
813
|
this.#remoting.send({
|
|
801
|
-
targetWin:
|
|
802
|
-
targetOrigin:
|
|
814
|
+
targetWin: hostWindow,
|
|
815
|
+
targetOrigin: hostOrigin,
|
|
803
816
|
messageType: MessageType.GuestEventUnsubscribe,
|
|
804
817
|
messageBody: {
|
|
805
818
|
eventId,
|