@elliemae/pui-app-bridge 2.28.6 → 2.29.0-alpha.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.
Files changed (61) hide show
  1. package/dist/cjs/appBridge.js +11 -14
  2. package/dist/cjs/config/app.js +2 -7
  3. package/dist/cjs/config/microFE.js +30 -28
  4. package/dist/cjs/eventManager.js +7 -6
  5. package/dist/cjs/frame.js +10 -7
  6. package/dist/cjs/loaders/manifest.js +1 -1
  7. package/dist/cjs/microfeHost.js +5 -2
  8. package/dist/cjs/tests/scriptingObjects/analytics.js +6 -21
  9. package/dist/cjs/tests/scriptingObjects/appraisalServiceModule.js +1 -4
  10. package/dist/cjs/tests/utils.js +76 -1
  11. package/dist/cjs/typings/window.js +1 -1
  12. package/dist/esm/appBridge.js +11 -14
  13. package/dist/esm/config/app.js +2 -7
  14. package/dist/esm/config/microFE.js +30 -28
  15. package/dist/esm/eventManager.js +7 -6
  16. package/dist/esm/frame.js +10 -7
  17. package/dist/esm/loaders/manifest.js +1 -1
  18. package/dist/esm/microfeHost.js +5 -2
  19. package/dist/esm/tests/scriptingObjects/analytics.js +6 -21
  20. package/dist/esm/tests/scriptingObjects/appraisalServiceModule.js +1 -4
  21. package/dist/esm/tests/serverHandlers.js +3 -1
  22. package/dist/esm/tests/utils.js +76 -1
  23. package/dist/esm/typings/window.js +1 -1
  24. package/dist/public/e2e-host.html +1 -1
  25. package/dist/public/e2e-index.html +1 -1
  26. package/dist/public/frame.html +1 -1
  27. package/dist/public/index.html +1 -1
  28. package/dist/public/js/emuiAppBridge.e4cfaa7d8c810b09c233.js +12 -0
  29. package/dist/public/js/emuiAppBridge.e4cfaa7d8c810b09c233.js.br +0 -0
  30. package/dist/public/js/emuiAppBridge.e4cfaa7d8c810b09c233.js.gz +0 -0
  31. package/dist/public/js/emuiAppBridge.e4cfaa7d8c810b09c233.js.map +1 -0
  32. package/dist/types/lib/appBridge.d.ts +6 -6
  33. package/dist/types/lib/appRegistry.d.ts +1 -1
  34. package/dist/types/lib/config/app.d.ts +1 -1
  35. package/dist/types/lib/config/microFE.d.ts +2 -2
  36. package/dist/types/lib/eventManager.d.ts +3 -3
  37. package/dist/types/lib/loaders/script.d.ts +1 -1
  38. package/dist/types/lib/loaders/style.d.ts +1 -1
  39. package/dist/types/lib/microfeHost.d.ts +5 -6
  40. package/dist/types/lib/tests/scriptingObjects/analytics.d.ts +5 -5
  41. package/dist/types/lib/tests/scriptingObjects/appraisalServiceModule.d.ts +8 -5
  42. package/dist/types/lib/tests/scriptingObjects/global.d.ts +1 -1
  43. package/dist/types/lib/tests/server.d.ts +1 -1
  44. package/dist/types/lib/tests/serverHandlers.d.ts +1 -1
  45. package/dist/types/lib/tests/utils.d.ts +64 -2
  46. package/dist/types/lib/typings/appInfo.d.ts +1 -1
  47. package/dist/types/lib/typings/common.d.ts +10 -0
  48. package/dist/types/lib/typings/guest.d.ts +6 -6
  49. package/dist/types/lib/typings/host.d.ts +4 -4
  50. package/dist/types/lib/typings/index.d.ts +1 -1
  51. package/dist/types/lib/typings/window.d.ts +4 -4
  52. package/dist/types/tsconfig.tsbuildinfo +1 -1
  53. package/dist/umd/index.js +9 -14
  54. package/dist/umd/index.js.br +0 -0
  55. package/dist/umd/index.js.gz +0 -0
  56. package/dist/umd/index.js.map +1 -1
  57. package/package.json +12 -11
  58. package/dist/public/js/emuiAppBridge.57ee9e3892a5a9c5af74.js +0 -17
  59. package/dist/public/js/emuiAppBridge.57ee9e3892a5a9c5af74.js.br +0 -0
  60. package/dist/public/js/emuiAppBridge.57ee9e3892a5a9c5af74.js.gz +0 -0
  61. package/dist/public/js/emuiAppBridge.57ee9e3892a5a9c5af74.js.map +0 -1
@@ -123,12 +123,13 @@ class CAppBridge {
123
123
  * @param value
124
124
  * @returns
125
125
  */
126
- #isProxyEvent = (value) => (
127
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
128
- value instanceof import_microfe_common.ProxyEvent || // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
129
- typeof value?.subscribe === "function"
130
- );
131
- // support v1 scripting objects
126
+ #isProxyEvent = (value) => {
127
+ if (value instanceof import_microfe_common.ProxyEvent) return true;
128
+ if (typeof value === "object" && value !== null && "subscribe" in value) {
129
+ return typeof value.subscribe === "function";
130
+ }
131
+ return false;
132
+ };
132
133
  /**
133
134
  * format error message for app not found
134
135
  * @param id app id
@@ -267,7 +268,7 @@ class CAppBridge {
267
268
  appId: options.id,
268
269
  exception: err
269
270
  });
270
- throw new Error(message);
271
+ throw new Error(message, { cause: err });
271
272
  }
272
273
  };
273
274
  #unloadApp = ({ id, instanceId, hostUrl, documentEle }) => {
@@ -463,9 +464,7 @@ class CAppBridge {
463
464
  eventOptions
464
465
  }) => this.dispatchEvent({
465
466
  event,
466
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
467
467
  eventParams,
468
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
469
468
  eventOptions
470
469
  });
471
470
  const token = propValue.subscribe(listener);
@@ -475,7 +474,8 @@ class CAppBridge {
475
474
  } else if (this.#isFunction(propValue)) {
476
475
  Object.defineProperty(so, propName, {
477
476
  value: async (...args) => {
478
- const callerCtx = so[propName]?.callContext;
477
+ const soMethod = so[propName];
478
+ const callerCtx = soMethod?.callContext;
479
479
  if (callerCtx?.guest) {
480
480
  const existingChain = callerCtx.callChain ?? [];
481
481
  const guestId = callerCtx.guest.id;
@@ -681,10 +681,7 @@ class CAppBridge {
681
681
  if (iframeWindow) {
682
682
  iframeWindow.emui = iframeWindow.emui ?? {};
683
683
  iframeWindow.emui.__host = microFEHost;
684
- iframeWindow.emui.getHost = () => (
685
- // eslint-disable-next-line no-underscore-dangle
686
- iframeWindow.emui?.__host ?? null
687
- );
684
+ iframeWindow.emui.getHost = () => iframeWindow.emui?.__host ?? null;
688
685
  }
689
686
  const preconnect = frameDoc.createElement("link");
690
687
  preconnect.rel = "preconnect";
@@ -123,9 +123,7 @@ class CAppConfig {
123
123
  await this.load(`${this.#baseUrl}latest/app.config.json`);
124
124
  return;
125
125
  }
126
- throw new Error("Failed to fetch app config", {
127
- cause: err
128
- });
126
+ throw new Error("Failed to fetch app config", { cause: err });
129
127
  }
130
128
  if (response.ok) {
131
129
  try {
@@ -134,10 +132,7 @@ class CAppConfig {
134
132
  } catch (err) {
135
133
  if (!configUrl && this.#version !== import_constant.LATEST_VERSION) {
136
134
  await this.load(`${this.#baseUrl}latest/app.config.json`);
137
- } else
138
- throw new Error("Failed to parse app config", {
139
- cause: err
140
- });
135
+ } else throw new Error("Failed to parse app config", { cause: err });
141
136
  }
142
137
  } else {
143
138
  if (!configUrl && this.#version !== import_constant.LATEST_VERSION) {
@@ -59,36 +59,38 @@ const isFileListValid = (files) => {
59
59
  if (!files || !files.length) return false;
60
60
  return files.every((file) => typeof file === "string");
61
61
  };
62
+ const isLaunchMode = (mode, expected) => String(mode).toLowerCase() === expected.toLowerCase();
63
+ const isAppSdkManager = (manager) => String(manager).toLowerCase() === import_app.MicroAppManager.APPSDK.toLowerCase();
64
+ const validateMode = (id, mode) => {
65
+ if (!isLaunchMode(mode, import_app.LaunchMode.PRODUCTION) && !isLaunchMode(mode, import_app.LaunchMode.DEVELOPMENT)) {
66
+ throw new Error(`invalid mode '${String(mode)}' for ${id}`);
67
+ }
68
+ };
69
+ const validateAppSdkEnvFiles = (id, envSection, envName) => {
70
+ if (!envSection) {
71
+ throw new Error(
72
+ `microFrontendApps.${id} is missing ${envName} section in app.config.json`
73
+ );
74
+ }
75
+ if (!isFileListValid(envSection.files)) {
76
+ throw new Error(`invalid value for ${envName}.files`);
77
+ }
78
+ };
79
+ const validateAppSdkConfig = (id, mode, mfeConfig) => {
80
+ const { production, development } = mfeConfig;
81
+ if (isLaunchMode(mode, import_app.LaunchMode.PRODUCTION)) {
82
+ validateAppSdkEnvFiles(id, production, "production");
83
+ }
84
+ if (isLaunchMode(mode, import_app.LaunchMode.DEVELOPMENT)) {
85
+ validateAppSdkEnvFiles(id, development, "development");
86
+ }
87
+ };
62
88
  const validate = (id, mfeConfig) => {
63
89
  const { mode = import_app.LaunchMode.PRODUCTION } = mfeConfig;
64
- if (String(mode).toLowerCase() !== import_app.LaunchMode.PRODUCTION.toLowerCase() && String(mode).toLowerCase() !== import_app.LaunchMode.DEVELOPMENT.toLowerCase())
65
- throw new Error(`invalid mode '${String(mode)}' for ${id}`);
66
- const {
67
- production,
68
- development,
69
- microappManager = import_app.MicroAppManager.APPSDK
70
- } = mfeConfig;
71
- if (String(microappManager).toLowerCase() === import_app.MicroAppManager.APPSDK.toLowerCase()) {
72
- if (String(mode).toLowerCase() === import_app.LaunchMode.PRODUCTION.toLowerCase()) {
73
- if (!production) {
74
- throw new Error(
75
- `microFrontendApps.${id} is missing production section in app.config.json`
76
- );
77
- }
78
- if (!isFileListValid(production.files)) {
79
- throw new Error(`invalid value for production.files`);
80
- }
81
- }
82
- if (String(mode).toLowerCase() === import_app.LaunchMode.DEVELOPMENT.toLowerCase()) {
83
- if (!development) {
84
- throw new Error(
85
- `microFrontendApps.${id} is missing development section in app.config.json`
86
- );
87
- }
88
- if (!isFileListValid(development.files)) {
89
- throw new Error(`invalid value for development.files`);
90
- }
91
- }
90
+ validateMode(id, mode);
91
+ const { microappManager = import_app.MicroAppManager.APPSDK } = mfeConfig;
92
+ if (isAppSdkManager(microappManager)) {
93
+ validateAppSdkConfig(id, mode, mfeConfig);
92
94
  }
93
95
  };
94
96
  const getConfig = ({
@@ -94,12 +94,13 @@ class EventManager {
94
94
  }
95
95
  }
96
96
  return this.#asyncCallwithTimeout(
97
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
98
- listener.callback({
99
- obj: scriptingObject,
100
- eventName,
101
- eventParams
102
- }),
97
+ Promise.resolve(
98
+ listener.callback({
99
+ obj: scriptingObject,
100
+ eventName,
101
+ eventParams
102
+ })
103
+ ),
103
104
  feedbackWaitTime
104
105
  );
105
106
  });
package/dist/cjs/frame.js CHANGED
@@ -99,11 +99,14 @@ const create = ({
99
99
  frame.setAttribute("src", buildFrameSrc(options));
100
100
  const FRAME_LOAD_TIMEOUT_MS = 1e4;
101
101
  let settled = false;
102
- let timeoutId;
103
- let onAbort;
102
+ const frameLoadRefs = {
103
+ timeoutId: void 0,
104
+ onAbort: (() => {
105
+ })
106
+ };
104
107
  const cleanup = () => {
105
- clearTimeout(timeoutId);
106
- signal?.removeEventListener("abort", onAbort);
108
+ if (frameLoadRefs.timeoutId) clearTimeout(frameLoadRefs.timeoutId);
109
+ signal?.removeEventListener("abort", frameLoadRefs.onAbort);
107
110
  };
108
111
  const rejectIfAborted = () => {
109
112
  if (!signal?.aborted) return false;
@@ -115,12 +118,12 @@ const create = ({
115
118
  }
116
119
  return true;
117
120
  };
118
- onAbort = () => {
121
+ frameLoadRefs.onAbort = () => {
119
122
  rejectIfAborted();
120
123
  };
121
124
  if (rejectIfAborted()) return;
122
- signal?.addEventListener("abort", onAbort);
123
- timeoutId = setTimeout(() => {
125
+ signal?.addEventListener("abort", frameLoadRefs.onAbort);
126
+ frameLoadRefs.timeoutId = setTimeout(() => {
124
127
  if (!settled) {
125
128
  settled = true;
126
129
  cleanup();
@@ -27,7 +27,7 @@ const isValidHttpUrl = (fileName) => {
27
27
  let url;
28
28
  try {
29
29
  url = new URL(fileName);
30
- } catch (_) {
30
+ } catch {
31
31
  return false;
32
32
  }
33
33
  return url.protocol === "http:" || url.protocol === "https:";
@@ -74,7 +74,8 @@ class CMicroFEHost {
74
74
  } else if ((0, import_microfe_common.isPublicFunction)(propValue, propName)) {
75
75
  Object.defineProperty(proxy, propName, {
76
76
  value: (...args) => {
77
- const existingCallChain = proxy[propName]?.callContext?.callChain;
77
+ const proxyMethod = proxy[propName];
78
+ const existingCallChain = proxyMethod?.callContext?.callChain;
78
79
  Object.defineProperty(propValue, "callContext", {
79
80
  value: {
80
81
  guest: this.#guest,
@@ -94,7 +95,9 @@ class CMicroFEHost {
94
95
  });
95
96
  return Promise.resolve(proxy);
96
97
  } catch (err) {
97
- return Promise.reject(err);
98
+ return Promise.reject(
99
+ err instanceof Error ? err : new Error(String(err))
100
+ );
98
101
  }
99
102
  };
100
103
  /**
@@ -26,31 +26,16 @@ class Analytics extends import_microfe_common.ScriptingObject {
26
26
  constructor() {
27
27
  super("analytics");
28
28
  }
29
- deleteTimingEventSamplingRatio = (names) => {
30
- console.log("Analytics.deleteTimingEventSamplingRatio", names);
29
+ deleteTimingEventSamplingRatio = (_names) => {
31
30
  };
32
- getAllTimingEventSamplingRatios = () => {
33
- console.log("Analytics.getAllTimingEventSamplingRatios");
34
- return {};
35
- };
36
- getTimingEventSamplingRatio = (names) => {
37
- console.log("Analytics.getTimingEventSamplingRatio", names);
38
- return {};
39
- };
40
- setTimingEventSamplingRatio = (ratios) => {
41
- console.log("Analytics.setTimingEventSamplingRatio", ratios);
42
- };
43
- sendBAEvent = (event) => {
44
- console.log("Analytics.sendBAEvent", event);
45
- return Promise.resolve();
46
- };
47
- startTiming = (name, options) => {
48
- console.log("Analytics.perfMarkStart", name);
49
- return Promise.resolve(performance.mark(name, { detail: options }));
31
+ getAllTimingEventSamplingRatios = () => ({});
32
+ getTimingEventSamplingRatio = (_names) => ({});
33
+ setTimingEventSamplingRatio = (_ratios) => {
50
34
  };
35
+ sendBAEvent = (_event) => Promise.resolve();
36
+ startTiming = (name, options) => Promise.resolve(performance.mark(name, { detail: options }));
51
37
  endTiming = (start, options) => {
52
38
  const name = typeof start === "string" ? start : start.name;
53
- console.log("Analytics.perfMarkEnd", name);
54
39
  performance.measure(name, {
55
40
  detail: options,
56
41
  start: name
@@ -72,10 +72,7 @@ class AppraisalService extends import_microfe_common.ScriptingObject {
72
72
  delete = () => {
73
73
  throw new Error("Not implemented");
74
74
  };
75
- log = async (message, level) => {
76
- console.log(message, level);
77
- return Promise.resolve();
78
- };
75
+ log = async (_message, _level) => Promise.resolve();
79
76
  unload = async () => {
80
77
  };
81
78
  }
@@ -28,16 +28,91 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var utils_exports = {};
30
30
  __export(utils_exports, {
31
+ clearWindowEmui: () => clearWindowEmui,
32
+ createTestModuleSO: () => createTestModuleSO,
33
+ expectInitHistoryShape: () => expectInitHistoryShape,
34
+ expectInitLoggerShape: () => expectInitLoggerShape,
35
+ expectInitThemeShape: () => expectInitThemeShape,
36
+ getEmuiApps: () => getEmuiApps,
37
+ getIframeWindow: () => getIframeWindow,
31
38
  getMajorMinorVersion: () => getMajorMinorVersion,
32
39
  logger: () => logger,
33
40
  releaseJSThread: () => releaseJSThread,
34
41
  sendJS: () => sendJS,
35
- sendJSText: () => sendJSText
42
+ sendJSText: () => sendJSText,
43
+ setEmuiAppEntry: () => setEmuiAppEntry,
44
+ snapshotInitOptionsPayload: () => snapshotInitOptionsPayload
36
45
  });
37
46
  module.exports = __toCommonJS(utils_exports);
38
47
  var import_promises = require("fs/promises");
39
48
  var import_node_path = __toESM(require("node:path"), 1);
40
49
  var import_pui_diagnostics = require("@elliemae/pui-diagnostics");
50
+ var import_microfe_common = require("@elliemae/microfe-common");
51
+ const getIframeWindow = (frame) => {
52
+ const view = frame.contentDocument?.defaultView;
53
+ if (!view) {
54
+ throw new Error("iframe content window is not available");
55
+ }
56
+ return view;
57
+ };
58
+ const getEmuiApps = (emui, appId) => {
59
+ const entry = emui[appId];
60
+ if (Array.isArray(entry)) return entry;
61
+ return entry ? [entry] : [];
62
+ };
63
+ const setEmuiAppEntry = (emui, appId, entry) => {
64
+ emui[appId] = entry;
65
+ };
66
+ const clearWindowEmui = () => {
67
+ Reflect.deleteProperty(window, "emui");
68
+ };
69
+ const createTestModuleSO = () => {
70
+ const moduleSO = new import_microfe_common.ScriptingObject("module");
71
+ Object.defineProperty(moduleSO, "getParameters", {
72
+ value: () => Promise.resolve({ moduleId: "urn:test", homeRoute: "/test" }),
73
+ enumerable: true
74
+ });
75
+ return moduleSO;
76
+ };
77
+ const expectInitHistoryShape = (history) => {
78
+ expect(history).toBeDefined();
79
+ expect(history?.action).toBe("POP");
80
+ expect(typeof history?.push).toBe("function");
81
+ expect(typeof history?.replace).toBe("function");
82
+ };
83
+ const expectInitThemeShape = (theme) => {
84
+ expect(theme).toBeDefined();
85
+ expect(theme?.breakpoints).toBeDefined();
86
+ expect(theme?.colors).toBeDefined();
87
+ expect(typeof theme?.media.large).toBe("function");
88
+ expect(typeof theme?.media.medium).toBe("function");
89
+ };
90
+ const expectInitLoggerShape = (initLogger) => {
91
+ expect(initLogger).toBeDefined();
92
+ expect(typeof initLogger?.audit).toBe("function");
93
+ expect(typeof initLogger?.debug).toBe("function");
94
+ expect(typeof initLogger?.error).toBe("function");
95
+ };
96
+ const snapshotInitOptionsPayload = (initOptions) => ({
97
+ ...initOptions,
98
+ logger: void 0,
99
+ history: initOptions.history ? {
100
+ action: initOptions.history.action,
101
+ location: initOptions.history.location
102
+ } : void 0,
103
+ theme: initOptions.theme ? {
104
+ breakpoints: initOptions.theme.breakpoints,
105
+ colors: initOptions.theme.colors,
106
+ fontSizes: initOptions.theme.fontSizes,
107
+ fontWeights: initOptions.theme.fontWeights,
108
+ fonts: initOptions.theme.fonts,
109
+ letterSpacings: initOptions.theme.letterSpacings,
110
+ lineHeights: initOptions.theme.lineHeights,
111
+ shadows: initOptions.theme.shadows,
112
+ space: initOptions.theme.space,
113
+ zIndex: initOptions.theme.zIndex
114
+ } : void 0
115
+ });
41
116
  const getMajorMinorVersion = (version) => version.split(".").slice(0, 2).join(".");
42
117
  const sendJS = async (res, ctx, filePath) => {
43
118
  const fileContent = await (0, import_promises.readFile)(import_node_path.default.join(__dirname, filePath), "utf-8");
@@ -28,7 +28,7 @@ const getWindow = () => {
28
28
  try {
29
29
  window.parent.document;
30
30
  return window.parent;
31
- } catch (err) {
31
+ } catch {
32
32
  return window;
33
33
  }
34
34
  };
@@ -98,12 +98,13 @@ class CAppBridge {
98
98
  * @param value
99
99
  * @returns
100
100
  */
101
- #isProxyEvent = (value) => (
102
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
103
- value instanceof ProxyEvent || // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
104
- typeof value?.subscribe === "function"
105
- );
106
- // support v1 scripting objects
101
+ #isProxyEvent = (value) => {
102
+ if (value instanceof ProxyEvent) return true;
103
+ if (typeof value === "object" && value !== null && "subscribe" in value) {
104
+ return typeof value.subscribe === "function";
105
+ }
106
+ return false;
107
+ };
107
108
  /**
108
109
  * format error message for app not found
109
110
  * @param id app id
@@ -242,7 +243,7 @@ class CAppBridge {
242
243
  appId: options.id,
243
244
  exception: err
244
245
  });
245
- throw new Error(message);
246
+ throw new Error(message, { cause: err });
246
247
  }
247
248
  };
248
249
  #unloadApp = ({ id, instanceId, hostUrl, documentEle }) => {
@@ -438,9 +439,7 @@ class CAppBridge {
438
439
  eventOptions
439
440
  }) => this.dispatchEvent({
440
441
  event,
441
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
442
442
  eventParams,
443
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
444
443
  eventOptions
445
444
  });
446
445
  const token = propValue.subscribe(listener);
@@ -450,7 +449,8 @@ class CAppBridge {
450
449
  } else if (this.#isFunction(propValue)) {
451
450
  Object.defineProperty(so, propName, {
452
451
  value: async (...args) => {
453
- const callerCtx = so[propName]?.callContext;
452
+ const soMethod = so[propName];
453
+ const callerCtx = soMethod?.callContext;
454
454
  if (callerCtx?.guest) {
455
455
  const existingChain = callerCtx.callChain ?? [];
456
456
  const guestId = callerCtx.guest.id;
@@ -656,10 +656,7 @@ class CAppBridge {
656
656
  if (iframeWindow) {
657
657
  iframeWindow.emui = iframeWindow.emui ?? {};
658
658
  iframeWindow.emui.__host = microFEHost;
659
- iframeWindow.emui.getHost = () => (
660
- // eslint-disable-next-line no-underscore-dangle
661
- iframeWindow.emui?.__host ?? null
662
- );
659
+ iframeWindow.emui.getHost = () => iframeWindow.emui?.__host ?? null;
663
660
  }
664
661
  const preconnect = frameDoc.createElement("link");
665
662
  preconnect.rel = "preconnect";
@@ -88,9 +88,7 @@ class CAppConfig {
88
88
  await this.load(`${this.#baseUrl}latest/app.config.json`);
89
89
  return;
90
90
  }
91
- throw new Error("Failed to fetch app config", {
92
- cause: err
93
- });
91
+ throw new Error("Failed to fetch app config", { cause: err });
94
92
  }
95
93
  if (response.ok) {
96
94
  try {
@@ -99,10 +97,7 @@ class CAppConfig {
99
97
  } catch (err) {
100
98
  if (!configUrl && this.#version !== LATEST_VERSION) {
101
99
  await this.load(`${this.#baseUrl}latest/app.config.json`);
102
- } else
103
- throw new Error("Failed to parse app config", {
104
- cause: err
105
- });
100
+ } else throw new Error("Failed to parse app config", { cause: err });
106
101
  }
107
102
  } else {
108
103
  if (!configUrl && this.#version !== LATEST_VERSION) {
@@ -29,36 +29,38 @@ const isFileListValid = (files) => {
29
29
  if (!files || !files.length) return false;
30
30
  return files.every((file) => typeof file === "string");
31
31
  };
32
+ const isLaunchMode = (mode, expected) => String(mode).toLowerCase() === expected.toLowerCase();
33
+ const isAppSdkManager = (manager) => String(manager).toLowerCase() === MicroAppManager.APPSDK.toLowerCase();
34
+ const validateMode = (id, mode) => {
35
+ if (!isLaunchMode(mode, LaunchMode.PRODUCTION) && !isLaunchMode(mode, LaunchMode.DEVELOPMENT)) {
36
+ throw new Error(`invalid mode '${String(mode)}' for ${id}`);
37
+ }
38
+ };
39
+ const validateAppSdkEnvFiles = (id, envSection, envName) => {
40
+ if (!envSection) {
41
+ throw new Error(
42
+ `microFrontendApps.${id} is missing ${envName} section in app.config.json`
43
+ );
44
+ }
45
+ if (!isFileListValid(envSection.files)) {
46
+ throw new Error(`invalid value for ${envName}.files`);
47
+ }
48
+ };
49
+ const validateAppSdkConfig = (id, mode, mfeConfig) => {
50
+ const { production, development } = mfeConfig;
51
+ if (isLaunchMode(mode, LaunchMode.PRODUCTION)) {
52
+ validateAppSdkEnvFiles(id, production, "production");
53
+ }
54
+ if (isLaunchMode(mode, LaunchMode.DEVELOPMENT)) {
55
+ validateAppSdkEnvFiles(id, development, "development");
56
+ }
57
+ };
32
58
  const validate = (id, mfeConfig) => {
33
59
  const { mode = LaunchMode.PRODUCTION } = mfeConfig;
34
- if (String(mode).toLowerCase() !== LaunchMode.PRODUCTION.toLowerCase() && String(mode).toLowerCase() !== LaunchMode.DEVELOPMENT.toLowerCase())
35
- throw new Error(`invalid mode '${String(mode)}' for ${id}`);
36
- const {
37
- production,
38
- development,
39
- microappManager = MicroAppManager.APPSDK
40
- } = mfeConfig;
41
- if (String(microappManager).toLowerCase() === MicroAppManager.APPSDK.toLowerCase()) {
42
- if (String(mode).toLowerCase() === LaunchMode.PRODUCTION.toLowerCase()) {
43
- if (!production) {
44
- throw new Error(
45
- `microFrontendApps.${id} is missing production section in app.config.json`
46
- );
47
- }
48
- if (!isFileListValid(production.files)) {
49
- throw new Error(`invalid value for production.files`);
50
- }
51
- }
52
- if (String(mode).toLowerCase() === LaunchMode.DEVELOPMENT.toLowerCase()) {
53
- if (!development) {
54
- throw new Error(
55
- `microFrontendApps.${id} is missing development section in app.config.json`
56
- );
57
- }
58
- if (!isFileListValid(development.files)) {
59
- throw new Error(`invalid value for development.files`);
60
- }
61
- }
60
+ validateMode(id, mode);
61
+ const { microappManager = MicroAppManager.APPSDK } = mfeConfig;
62
+ if (isAppSdkManager(microappManager)) {
63
+ validateAppSdkConfig(id, mode, mfeConfig);
62
64
  }
63
65
  };
64
66
  const getConfig = ({
@@ -71,12 +71,13 @@ class EventManager {
71
71
  }
72
72
  }
73
73
  return this.#asyncCallwithTimeout(
74
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
75
- listener.callback({
76
- obj: scriptingObject,
77
- eventName,
78
- eventParams
79
- }),
74
+ Promise.resolve(
75
+ listener.callback({
76
+ obj: scriptingObject,
77
+ eventName,
78
+ eventParams
79
+ })
80
+ ),
80
81
  feedbackWaitTime
81
82
  );
82
83
  });
package/dist/esm/frame.js CHANGED
@@ -65,11 +65,14 @@ const create = ({
65
65
  frame.setAttribute("src", buildFrameSrc(options));
66
66
  const FRAME_LOAD_TIMEOUT_MS = 1e4;
67
67
  let settled = false;
68
- let timeoutId;
69
- let onAbort;
68
+ const frameLoadRefs = {
69
+ timeoutId: void 0,
70
+ onAbort: (() => {
71
+ })
72
+ };
70
73
  const cleanup = () => {
71
- clearTimeout(timeoutId);
72
- signal?.removeEventListener("abort", onAbort);
74
+ if (frameLoadRefs.timeoutId) clearTimeout(frameLoadRefs.timeoutId);
75
+ signal?.removeEventListener("abort", frameLoadRefs.onAbort);
73
76
  };
74
77
  const rejectIfAborted = () => {
75
78
  if (!signal?.aborted) return false;
@@ -81,12 +84,12 @@ const create = ({
81
84
  }
82
85
  return true;
83
86
  };
84
- onAbort = () => {
87
+ frameLoadRefs.onAbort = () => {
85
88
  rejectIfAborted();
86
89
  };
87
90
  if (rejectIfAborted()) return;
88
- signal?.addEventListener("abort", onAbort);
89
- timeoutId = setTimeout(() => {
91
+ signal?.addEventListener("abort", frameLoadRefs.onAbort);
92
+ frameLoadRefs.timeoutId = setTimeout(() => {
90
93
  if (!settled) {
91
94
  settled = true;
92
95
  cleanup();
@@ -4,7 +4,7 @@ const isValidHttpUrl = (fileName) => {
4
4
  let url;
5
5
  try {
6
6
  url = new URL(fileName);
7
- } catch (_) {
7
+ } catch {
8
8
  return false;
9
9
  }
10
10
  return url.protocol === "http:" || url.protocol === "https:";
@@ -55,7 +55,8 @@ class CMicroFEHost {
55
55
  } else if (isPublicFunction(propValue, propName)) {
56
56
  Object.defineProperty(proxy, propName, {
57
57
  value: (...args) => {
58
- const existingCallChain = proxy[propName]?.callContext?.callChain;
58
+ const proxyMethod = proxy[propName];
59
+ const existingCallChain = proxyMethod?.callContext?.callChain;
59
60
  Object.defineProperty(propValue, "callContext", {
60
61
  value: {
61
62
  guest: this.#guest,
@@ -75,7 +76,9 @@ class CMicroFEHost {
75
76
  });
76
77
  return Promise.resolve(proxy);
77
78
  } catch (err) {
78
- return Promise.reject(err);
79
+ return Promise.reject(
80
+ err instanceof Error ? err : new Error(String(err))
81
+ );
79
82
  }
80
83
  };
81
84
  /**