mfe-runtime-z 1.1.0 → 1.2.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/README.md CHANGED
@@ -6,7 +6,6 @@
6
6
 
7
7
  ---
8
8
 
9
-
10
9
  [![NPM](https://img.shields.io/npm/v/mfe-runtime-z.svg)](https://www.npmjs.com/package/mfe-runtime-z)
11
10
  [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
12
11
  ![Downloads](https://img.shields.io/npm/dt/mfe-runtime-z.svg)
@@ -38,6 +37,7 @@ This library focuses on **application-level integration**, not component sharing
38
37
  npm install mfe-runtime-z
39
38
  # or
40
39
  yarn add mfe-runtime-z
40
+
41
41
  ```
42
42
 
43
43
  ---
@@ -71,7 +71,7 @@ window.myRemoteApp = { mount(el, ctx), unmount(el) }
71
71
  import { MFEHost, createSharedStore } from "mfe-runtime-z"
72
72
 
73
73
  // shared store example
74
- const authStore = createSharedStore({ user: null })
74
+ const authStore = createSharedStore({ user: { name: 'name' } })
75
75
 
76
76
  // create host with isolate: true for Shadow DOM + error isolation
77
77
  const host = new MFEHost({
@@ -81,19 +81,22 @@ const host = new MFEHost({
81
81
  onRemoteError: (err) => console.error("Remote error:", err)
82
82
  })
83
83
 
84
- // load remote apps
85
- const productRemote = await host.load("http://localhost:3001/remote.js", "productApp")
86
- const cartRemote = await host.load("http://localhost:3002/remote.js", "cartApp")
84
+ async function init() {
85
+ // load remote apps
86
+ const productRemote = await host.load("http://localhost:3001/remote.js", "productApp")
87
+ const cartRemote = await host.load("http://localhost:3002/remote.js", "cartApp")
87
88
 
88
- // mount remotes into host container divs
89
- host.mount(productRemote, document.getElementById("product-root")!, "productApp", { isolate: true }) // shadow
90
- host.mount(cartRemote, document.getElementById("cart-root")!, "cartApp")
89
+ // mount remotes into host container divs
90
+ host.mount(productRemote, document.getElementById("product-root")!, "productApp", { isolate: false }) // shadow
91
+ host.mount(cartRemote, document.getElementById("cart-root")!, "cartApp")
91
92
 
92
- // // Unmount Shadow DOM remote
93
- // host.unmount(productRemote, document.getElementById("product-root")!, "productApp")
94
- // // Unmount normal remote
95
- // host.unmount(cartRemote, document.getElementById("cart-root")!, "cartApp")
93
+ // // Unmount Shadow DOM remote
94
+ // host.unmount(productRemote, document.getElementById("product-root")!, "productApp")
95
+ // // Unmount normal remote
96
+ // host.unmount(cartRemote, document.getElementById("cart-root")!, "cartApp")
97
+ }
96
98
 
99
+ init()
97
100
  ```
98
101
 
99
102
  ##### Remote application (framework-agnostic)
@@ -119,45 +122,65 @@ export function unmount(el: ShadowRoot) {
119
122
  ;(window as any).cartApp = { mount, unmount }
120
123
  ```
121
124
 
122
- ##### Remote app (framework-react-library)
125
+ ##### Remote application (framework-react-library)
123
126
 
124
127
  ```ts
125
128
  import React from "react"
126
129
  import ReactDOM from "react-dom/client"
130
+ import { createSharedStore } from "mfe-runtime-z"
127
131
 
128
- type AuthStore = {
129
- user: { id: string; name: string } | null
130
- subscribe: (cb: (state:any)=>void)=>void
131
- setState: (s:any)=>void
132
- }
132
+ export const authStore = createSharedStore<{ user: { id: string; name: string } | null }>({
133
+ user: null,
134
+ })
135
+
136
+ export default function App() {
137
+ const [user, setUser] = React.useState(authStore.getState().user)
133
138
 
134
- function App({ store }: { store: AuthStore }) {
135
- const [user, setUser] = React.useState(store.user)
136
139
  React.useEffect(() => {
137
- const unsub = store.subscribe((state:any) => setUser(state.user))
138
- return () => unsub?.()
139
- }, [store])
140
+ const unsubscribe = authStore.subscribe((state) => setUser(state.user))
141
+ return () => unsubscribe()
142
+ }, [])
143
+
144
+ const handleLogin = () => {
145
+ authStore.setState({ user: { id: "1", name: "Alice" } })
146
+ }
147
+
148
+ const handleLogout = () => {
149
+ authStore.setState({ user: null })
150
+ }
151
+
140
152
  return (
141
153
  <div>
142
- {user ? <span>Hello {user.name}</span> : <button onClick={()=>store.setState({user:{id:"1",name:"Alice"}})}>Login</button>}
154
+ {user ? (
155
+ <>
156
+ <span>Hello {user.name}</span>
157
+ <button onClick={handleLogout}>Logout</button>
158
+ </>
159
+ ) : (
160
+ <button onClick={handleLogin}>Login</button>
161
+ )}
143
162
  </div>
144
163
  )
145
164
  }
146
165
 
147
- // mount/unmount compatible with Shadow DOM
148
- export function mount(el: HTMLElement | ShadowRoot, ctx: { stores: { auth: AuthStore } }) {
149
- const root = ReactDOM.createRoot(el as unknown as HTMLElement)
166
+ // mount function
167
+ export function mount(el: HTMLElement, ctx: any) {
168
+ const root = ReactDOM.createRoot(el)
150
169
  ;(el as any)._reactRoot = root
151
- root.render(<App store={ctx.stores.auth} />)
170
+ // @ts-ignore
171
+ root.render(<App />) // <- ctx.stores.auth
152
172
  }
153
173
 
154
- export function unmount(el: HTMLElement | ShadowRoot) {
174
+ // unmount function
175
+ export function unmount(el: HTMLElement) {
155
176
  const root = (el as any)._reactRoot
156
- if (root) root.unmount()
177
+ root?.unmount()
157
178
  el.innerHTML = ""
158
179
  }
159
180
 
181
+ // expose to window
160
182
  ;(window as any).productApp = { mount, unmount }
183
+
161
184
  ```
162
185
 
163
186
  ---
@@ -165,9 +188,17 @@ export function unmount(el: HTMLElement | ShadowRoot) {
165
188
  ### Shared State
166
189
 
167
190
  ```ts
168
- const store = createSharedStore({ count: 0 })
169
- store.subscribe((state) => console.log(state.count))
170
- store.setState({ count: 1 })
191
+ import { createSharedStore } from "mfe-runtime-z"
192
+
193
+ export const store = createSharedStore({
194
+ auth: { user: null }
195
+ })
196
+
197
+ // Subscribe
198
+ store.subscribe((state) => console.log("New state:", state))
199
+
200
+ // Update
201
+ store.setState({ auth: { user: { id: 1, name: "Alice" } } })
171
202
  ```
172
203
 
173
204
  - Push-based, no Redux, no shared framework state
@@ -179,10 +210,20 @@ store.setState({ count: 1 })
179
210
  ```ts
180
211
  import { createSharedRouter } from "mfe-runtime-z"
181
212
 
182
- const router = createSharedRouter(ctx)
213
+ // Remote app context
214
+ const router = createSharedRouter({ eventBus, name: "productApp" })
215
+
183
216
  router.go("/cart")
184
217
  router.onChange((path) => console.log("navigated to", path))
185
218
 
219
+ // Listen route changes from host or other remotes
220
+ router.onRouteChange((path) => {
221
+ console.log("Remote route changed:", path)
222
+ })
223
+
224
+ // Notify other remotes of route change
225
+ router.emitRouteChange("/checkout")
226
+
186
227
  ```
187
228
 
188
229
  - Intent-based navigation
@@ -252,6 +293,7 @@ if (process.env.NODE_ENV === "development") {
252
293
  ```
253
294
 
254
295
  ###### Remote dev notify.
296
+
255
297
  ```ts
256
298
  // Only run in development
257
299
  if (import.meta.env.DEV) {
@@ -266,13 +308,20 @@ if (import.meta.env.DEV) {
266
308
  }
267
309
  ```
268
310
 
269
- ✅ Summary of Comments
311
+ ---
270
312
 
271
- - Host side: sets up a WebSocket-based dev reload server that listens for changes from remotes and automatically reloads them without refreshing the host page.
313
+ ### Plugin API Summary
272
314
 
273
- - Remote side: connects to host WebSocket and sends a message when HMR triggers (code changed), so the host can remount the updated remote.
315
+ | Method | Description |
316
+ | ------------------------------------------------- | ---------------------------------------------------------------------------------------- |
317
+ | `MFEHost.load(url, global)` | Load a remote JS bundle from URL. |
318
+ | `MFEHost.mount(remote, el, name, options?)` | Mount remote app into a container element, optionally in shadow DOM. |
319
+ | `MFEHost.unmount(remote, el)` | Unmount a remote app. |
320
+ | `MFEHost.reloadRemote({ name, url, global, el })` | Reload a remote app (unmount + reload script + mount). |
321
+ | `MFEHost.getEventBus()` | Access central event bus for custom events. |
322
+ | `createSharedStore(initial)` | Create a shared state store with `getState()`, `setState()`, `subscribe()`. |
323
+ | `createSharedRouter({ eventBus, name })` | Router helper: `go(path)`, `onChange(cb)`, `emitRouteChange(path)`, `onRouteChange(cb)`. |
274
324
 
275
- - Purpose: smooth dev experience for micro-frontends, framework-agnostic, avoids full page reload.
276
325
 
277
326
  ---
278
327
 
@@ -314,6 +363,38 @@ if (import.meta.env.DEV) {
314
363
 
315
364
  ---
316
365
 
366
+ #### Flowchart
367
+
368
+ ```css
369
+ ┌────────────────────┐
370
+ │ Host │
371
+ │--------------------│
372
+ │ - stores │
373
+ │ - eventBus │
374
+ │ - navigate() │
375
+ └────────────────────┘
376
+
377
+
378
+ ┌─────────────┴─────────────┐
379
+ │ │
380
+ ROUTER / EVENTS SHARED STORE
381
+ │ │
382
+ ▼ ▼
383
+ ┌────────────────────┐ ┌────────────────────┐
384
+ │ Remote App A │ │ Remote App B │
385
+ │--------------------│ │--------------------│
386
+ │ - mount(container)│ │ - mount(container)│
387
+ │ - unmount() │ │ - unmount() │
388
+ │ - emit events │ │ - emit events │
389
+ │ - go(path) │ │ - go(path) │
390
+ │ - onChange(cb) │ │ - onChange(cb) │
391
+ │ - onRouteChange() │ │ - onRouteChange() │
392
+ │ - use shared store│ │ - use shared store│
393
+ └────────────────────┘ └────────────────────┘
394
+ ```
395
+
396
+ ---
397
+
317
398
  ### License
318
399
 
319
400
  MIT
@@ -1,340 +1 @@
1
- /******************************************************************************
2
- Copyright (c) Microsoft Corporation.
3
-
4
- Permission to use, copy, modify, and/or distribute this software for any
5
- purpose with or without fee is hereby granted.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
- PERFORMANCE OF THIS SOFTWARE.
14
- ***************************************************************************** */
15
-
16
- var __assign = function() {
17
- __assign = Object.assign || function __assign(t) {
18
- for (var s, i = 1, n = arguments.length; i < n; i++) {
19
- s = arguments[i];
20
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21
- }
22
- return t;
23
- };
24
- return __assign.apply(this, arguments);
25
- };
26
-
27
- function __awaiter(thisArg, _arguments, P, generator) {
28
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
29
- return new (P || (P = Promise))(function (resolve, reject) {
30
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
31
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
32
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
33
- step((generator = generator.apply(thisArg, _arguments || [])).next());
34
- });
35
- }
36
-
37
- function __generator(thisArg, body) {
38
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
39
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
40
- function verb(n) { return function (v) { return step([n, v]); }; }
41
- function step(op) {
42
- if (f) throw new TypeError("Generator is already executing.");
43
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
44
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
45
- if (y = 0, t) op = [op[0] & 2, t.value];
46
- switch (op[0]) {
47
- case 0: case 1: t = op; break;
48
- case 4: _.label++; return { value: op[1], done: false };
49
- case 5: _.label++; y = op[1]; op = [0]; continue;
50
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
51
- default:
52
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
53
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
54
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
55
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
56
- if (t[2]) _.ops.pop();
57
- _.trys.pop(); continue;
58
- }
59
- op = body.call(thisArg, _);
60
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
61
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
62
- }
63
- }
64
-
65
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
66
- var e = new Error(message);
67
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
68
- };
69
-
70
- // loader/loadScript.ts
71
- var loaded = new Set();
72
- function loadScript(url, options) {
73
- if (options === void 0) { options = {}; }
74
- return __awaiter(this, void 0, void 0, function () {
75
- var _a, timeout, _b, retries, attempt, err_1;
76
- return __generator(this, function (_c) {
77
- switch (_c.label) {
78
- case 0:
79
- _a = options.timeout, timeout = _a === void 0 ? 15000 : _a, _b = options.retries, retries = _b === void 0 ? 1 : _b;
80
- if (loaded.has(url))
81
- return [2 /*return*/];
82
- attempt = 0;
83
- _c.label = 1;
84
- case 1:
85
- if (!(attempt <= retries)) return [3 /*break*/, 6];
86
- _c.label = 2;
87
- case 2:
88
- _c.trys.push([2, 4, , 5]);
89
- return [4 /*yield*/, loadOnce(url, timeout)];
90
- case 3:
91
- _c.sent();
92
- loaded.add(url);
93
- return [2 /*return*/];
94
- case 4:
95
- err_1 = _c.sent();
96
- if (attempt === retries) {
97
- throw err_1;
98
- }
99
- return [3 /*break*/, 5];
100
- case 5:
101
- attempt++;
102
- return [3 /*break*/, 1];
103
- case 6: return [2 /*return*/];
104
- }
105
- });
106
- });
107
- }
108
- function loadOnce(url, timeout) {
109
- return new Promise(function (resolve, reject) {
110
- var script = document.createElement("script");
111
- script.src = url;
112
- script.async = true;
113
- var timer = setTimeout(function () {
114
- cleanup();
115
- reject(new Error("Timeout loading ".concat(url)));
116
- }, timeout);
117
- function cleanup() {
118
- clearTimeout(timer);
119
- script.remove();
120
- }
121
- script.onload = function () {
122
- cleanup();
123
- resolve();
124
- };
125
- script.onerror = function () {
126
- cleanup();
127
- reject(new Error("Failed to load ".concat(url)));
128
- };
129
- document.body.appendChild(script);
130
- });
131
- }
132
-
133
- var EventBus = /** @class */ (function () {
134
- function EventBus() {
135
- this.map = new Map();
136
- }
137
- EventBus.prototype.on = function (event, handler) {
138
- if (!this.map.has(event)) {
139
- this.map.set(event, new Set());
140
- }
141
- this.map.get(event).add(handler);
142
- };
143
- EventBus.prototype.off = function (event, handler) {
144
- var _a;
145
- (_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.delete(handler);
146
- };
147
- EventBus.prototype.emit = function (event, payload) {
148
- var _a;
149
- (_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.forEach(function (fn) { return fn(payload); });
150
- };
151
- return EventBus;
152
- }());
153
-
154
- var ROUTER_EVENTS = {
155
- REQUEST_NAVIGATE: "ROUTER:REQUEST_NAVIGATE",
156
- NAVIGATE: "ROUTER:NAVIGATE",
157
- };
158
-
159
- function enableRouterSync(eventBus, navigate) {
160
- eventBus.on(ROUTER_EVENTS.REQUEST_NAVIGATE, function (_a) {
161
- var path = _a.path;
162
- navigate(path);
163
- eventBus.emit(ROUTER_EVENTS.NAVIGATE, { path: path });
164
- });
165
- }
166
-
167
- var MFEHost = /** @class */ (function () {
168
- function MFEHost(options) {
169
- if (options === void 0) { options = {}; }
170
- var _a, _b;
171
- this.eventBus = new EventBus();
172
- this.isolate = false;
173
- this.stores = (_a = options.stores) !== null && _a !== void 0 ? _a : {};
174
- this.navigate = options.navigate;
175
- this.onRemoteError = options.onRemoteError;
176
- this.fallback = options.fallback;
177
- this.isolate = (_b = options.isolate) !== null && _b !== void 0 ? _b : false;
178
- if (this.navigate) {
179
- enableRouterSync(this.eventBus, this.navigate);
180
- }
181
- }
182
- /** Load remote JS only */
183
- MFEHost.prototype.load = function (url, global) {
184
- var _a, _b;
185
- return __awaiter(this, void 0, void 0, function () {
186
- var err_1, remote, err;
187
- return __generator(this, function (_c) {
188
- switch (_c.label) {
189
- case 0:
190
- _c.trys.push([0, 2, , 3]);
191
- return [4 /*yield*/, loadScript(url, { retries: 1 })];
192
- case 1:
193
- _c.sent();
194
- return [3 /*break*/, 3];
195
- case 2:
196
- err_1 = _c.sent();
197
- (_a = this.onRemoteError) === null || _a === void 0 ? void 0 : _a.call(this, err_1);
198
- throw err_1;
199
- case 3:
200
- remote = window[global];
201
- if (!(remote === null || remote === void 0 ? void 0 : remote.mount)) {
202
- err = new Error("Remote \"".concat(global, "\" not found"));
203
- (_b = this.onRemoteError) === null || _b === void 0 ? void 0 : _b.call(this, err);
204
- throw err;
205
- }
206
- return [2 /*return*/, remote];
207
- }
208
- });
209
- });
210
- };
211
- /** Mount remote with optional Shadow DOM isolation */
212
- MFEHost.prototype.mount = function (remote, el, name, options) {
213
- var _a, _b;
214
- var isolate = (_a = options === null || options === void 0 ? void 0 : options.isolate) !== null && _a !== void 0 ? _a : this.isolate;
215
- var mountEl = el;
216
- // Shadow DOM isolation
217
- if (isolate) {
218
- if (el._shadowRoot)
219
- el._shadowRoot.innerHTML = "";
220
- var mode = (_b = options === null || options === void 0 ? void 0 : options.shadowMode) !== null && _b !== void 0 ? _b : "open";
221
- // @ts-ignore
222
- var shadow = el.attachShadow({ mode: mode })(el)._shadowRoot = shadow;
223
- // For React/Vue remotes, create container div
224
- var container = document.createElement("div");
225
- shadow.appendChild(container);
226
- // @ts-ignore
227
- mountEl = container(el)._mountEl = container;
228
- }
229
- var ctx = {
230
- name: name,
231
- stores: this.stores,
232
- eventBus: this.eventBus,
233
- host: { navigate: this.navigate },
234
- };
235
- try {
236
- remote.mount(mountEl, ctx);
237
- console.log("[MFE] mounted ".concat(name, " ").concat(isolate ? "(shadow)" : ""));
238
- }
239
- catch (err) {
240
- var error = err;
241
- console.error("[MFE] remote ".concat(name, " mount failed:"), error);
242
- if (this.onRemoteError)
243
- this.onRemoteError(error);
244
- if (this.fallback) {
245
- this.fallback(mountEl, name, error, ctx);
246
- }
247
- else {
248
- mountEl.innerHTML = "<div style=\"color:red\">Failed to load ".concat(name, "</div>");
249
- }
250
- }
251
- };
252
- /** Unmount remote */
253
- MFEHost.prototype.unmount = function (remote, el, name) {
254
- var _a, _b, _c, _d;
255
- try {
256
- var mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : (this.isolate ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
257
- (_c = remote.unmount) === null || _c === void 0 ? void 0 : _c.call(remote, mountEl);
258
- delete el._mountEl;
259
- if (name)
260
- console.log("[MFE] unmounted ".concat(name));
261
- }
262
- catch (err) {
263
- (_d = this.onRemoteError) === null || _d === void 0 ? void 0 : _d.call(this, err);
264
- }
265
- };
266
- /** Get central event bus */
267
- MFEHost.prototype.getEventBus = function () {
268
- return this.eventBus;
269
- };
270
- /** Reload remote: unmount + reload script + mount again */
271
- MFEHost.prototype.reloadRemote = function (options) {
272
- var _a, _b, _c;
273
- return __awaiter(this, void 0, void 0, function () {
274
- var name, url, global, el, isolate, oldRemote, mountEl, newRemote;
275
- return __generator(this, function (_d) {
276
- switch (_d.label) {
277
- case 0:
278
- name = options.name, url = options.url, global = options.global, el = options.el, isolate = options.isolate;
279
- try {
280
- oldRemote = window[global];
281
- mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : ((isolate !== null && isolate !== void 0 ? isolate : this.isolate) ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
282
- (_c = oldRemote === null || oldRemote === void 0 ? void 0 : oldRemote.unmount) === null || _c === void 0 ? void 0 : _c.call(oldRemote, mountEl);
283
- }
284
- catch (_e) { }
285
- delete window[global];
286
- return [4 /*yield*/, this.load("".concat(url, "?t=").concat(Date.now()), global)];
287
- case 1:
288
- newRemote = _d.sent();
289
- this.mount(newRemote, el, name, { isolate: isolate });
290
- return [2 /*return*/];
291
- }
292
- });
293
- });
294
- };
295
- return MFEHost;
296
- }());
297
-
298
- function createSharedStore(initial) {
299
- var state = initial;
300
- var listeners = new Set();
301
- return {
302
- getState: function () {
303
- return state;
304
- },
305
- /** Update state (shallow merge) */
306
- setState: function (partial) {
307
- state = __assign(__assign({}, state), partial);
308
- listeners.forEach(function (listener) { return listener(state); });
309
- },
310
- /** Subscribe to state changes */
311
- subscribe: function (fn, callImmediately) {
312
- if (callImmediately === void 0) { callImmediately = true; }
313
- listeners.add(fn);
314
- if (callImmediately)
315
- fn(state); // Immediately call listener with current state
316
- return function () { return listeners.delete(fn); };
317
- },
318
- };
319
- }
320
-
321
- function createSharedRouter(ctx) {
322
- var eventBus = ctx.eventBus, name = ctx.name;
323
- return {
324
- /** Remote → Host */
325
- go: function (path) {
326
- eventBus.emit(ROUTER_EVENTS.REQUEST_NAVIGATE, {
327
- from: name,
328
- path: path,
329
- });
330
- },
331
- /** Host → Remote */
332
- onChange: function (cb) {
333
- return eventBus.on(ROUTER_EVENTS.NAVIGATE, function (payload) {
334
- cb(payload.path);
335
- });
336
- },
337
- };
338
- }
339
-
340
- export { EventBus, MFEHost, createSharedRouter, createSharedStore, enableRouterSync, loadScript };
1
+ var t=function(){return t=Object.assign||function(t){for(var n,o=1,e=arguments.length;o<e;o++)for(var r in n=arguments[o])Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r]);return t},t.apply(this,arguments)};function n(t,n,o,e){return new(o||(o=Promise))(function(r,i){function a(t){try{l(e.next(t))}catch(t){i(t)}}function u(t){try{l(e.throw(t))}catch(t){i(t)}}function l(t){var n;t.done?r(t.value):(n=t.value,n instanceof o?n:new o(function(t){t(n)})).then(a,u)}l((e=e.apply(t,n||[])).next())})}function o(t,n){var o,e,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(o)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(o=1,e&&(r=2&u[0]?e.return:u[0]?e.throw||((r=e.return)&&r.call(e),0):e.next)&&!(r=r.call(e,u[1])).done)return r;switch(e=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,e=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=n.call(t,i)}catch(t){u=[6,t],e=0}finally{o=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}"function"==typeof SuppressedError&&SuppressedError;var e=new Set;function r(t,r){return void 0===r&&(r={}),n(this,void 0,void 0,function(){var n,a,u,l,c,s;return o(this,function(o){switch(o.label){case 0:if(n=r.timeout,a=void 0===n?15e3:n,u=r.retries,l=void 0===u?1:u,e.has(t))return[2];c=0,o.label=1;case 1:if(!(c<=l))return[3,6];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,i(t,a)];case 3:return o.sent(),e.add(t),[2];case 4:if(s=o.sent(),c===l)throw s;return[3,5];case 5:return c++,[3,1];case 6:return[2]}})})}function i(t,n){return new Promise(function(o,e){var r=document.createElement("script");r.src=t,r.async=!0;var i=setTimeout(function(){a(),e(new Error("Timeout loading ".concat(t)))},n);function a(){clearTimeout(i),r.remove()}r.onload=function(){a(),o()},r.onerror=function(){a(),e(new Error("Failed to load ".concat(t)))},document.body.appendChild(r)})}var a=function(){function t(){this.map=new Map}return t.prototype.on=function(t,n){this.map.has(t)||this.map.set(t,new Set),this.map.get(t).add(n)},t.prototype.off=function(t,n){var o;null===(o=this.map.get(t))||void 0===o||o.delete(n)},t.prototype.emit=function(t,n){var o;null===(o=this.map.get(t))||void 0===o||o.forEach(function(t){return t(n)})},t}(),u="ROUTER:REQUEST_NAVIGATE",l="ROUTER:NAVIGATE",c="ROUTER:ON_CHANGE";function s(t,n){t.on(u,function(o){var e=o.path;n(e),t.emit(l,{path:e})})}var h=function(){function t(t){void 0===t&&(t={});var n,o,e=this;this.eventBus=new a,this.isolate=!1,this.cache={},this.stores=null!==(n=t.stores)&&void 0!==n?n:{},this.navigate=t.navigate,this.onRemoteError=t.onRemoteError,this.fallback=t.fallback,this.isolate=null!==(o=t.isolate)&&void 0!==o&&o,this.onMountStart=t.onMountStart,this.onMountEnd=t.onMountEnd,this.onUnmountStart=t.onUnmountStart,this.onUnmountEnd=t.onUnmountEnd,this.navigate&&s(this.eventBus,this.navigate),this.eventBus.on(c,function(t){var n;null===(n=e.navigate)||void 0===n||n.call(e,t)})}return t.prototype.load=function(t,e){var i,a;return n(this,void 0,void 0,function(){var n,u,l;return o(this,function(o){switch(o.label){case 0:if(this.cache[e])return[2,this.cache[e]];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,r(t,{retries:1})];case 2:return o.sent(),[3,4];case 3:throw n=o.sent(),null===(i=this.onRemoteError)||void 0===i||i.call(this,n),n;case 4:if(!(null==(u=window[e])?void 0:u.mount))throw l=new Error('Remote "'.concat(e,'" not found')),null===(a=this.onRemoteError)||void 0===a||a.call(this,l),l;return this.cache[e]=u,[2,u]}})})},t.prototype.preload=function(t,e){return n(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return[4,this.load(t,e)];case 1:return n.sent(),[2]}})})},t.prototype.mount=function(t,n,o,e){var r,i,a,u,l,c=null!==(r=null==e?void 0:e.isolate)&&void 0!==r?r:this.isolate,s=null;if(n._shadowRoot&&(n._shadowRoot.innerHTML=""),c&&"function"==typeof n.attachShadow)try{s=n.attachShadow({mode:null!==(i=null==e?void 0:e.shadowMode)&&void 0!==i?i:"open"})(n)._shadowRoot=s}catch(t){s=null}var h=document.createElement("div");s?s.appendChild(h):n.appendChild(h),n._mountEl=h;var d={name:o,stores:this.stores,eventBus:this.eventBus,host:{navigate:this.navigate}};try{null===(a=this.onMountStart)||void 0===a||a.call(this,o),t.mount(h,d),null===(u=this.onMountEnd)||void 0===u||u.call(this,o),console.log("[MFE] mounted ".concat(o," ").concat(c?"(shadow/fallback)":""))}catch(t){var f=t;console.error("[MFE] remote ".concat(o," mount failed:"),f),null===(l=this.onRemoteError)||void 0===l||l.call(this,f),this.fallback?this.fallback(h,o,f,d):h.innerHTML='<div style="color:red">Failed to load '.concat(o,"</div>")}},t.prototype.unmount=function(t,n,o){var e,r,i,a,u,l;try{null===(e=this.onUnmountStart)||void 0===e||e.call(this,null!=o?o:"");var c=null!==(r=n._mountEl)&&void 0!==r?r:this.isolate&&null!==(i=n.shadowRoot)&&void 0!==i?i:n;null===(a=t.unmount)||void 0===a||a.call(t,c),delete n._mountEl,null===(u=this.onUnmountEnd)||void 0===u||u.call(this,null!=o?o:""),o&&console.log("[MFE] unmounted ".concat(o))}catch(t){null===(l=this.onRemoteError)||void 0===l||l.call(this,t)}},t.prototype.getEventBus=function(){return this.eventBus},t.prototype.reloadRemote=function(t){var e,r,i;return n(this,void 0,void 0,function(){var n,a,u,l,c,s,h,d;return o(this,function(o){switch(o.label){case 0:n=t.name,a=t.url,u=t.global,l=t.el,c=t.isolate;try{s=window[u],h=null!==(e=l._mountEl)&&void 0!==e?e:(null!=c?c:this.isolate)&&null!==(r=l.shadowRoot)&&void 0!==r?r:l,null===(i=null==s?void 0:s.unmount)||void 0===i||i.call(s,h)}catch(t){}return delete window[u],delete this.cache[u],[4,this.load("".concat(a,"?t=").concat(Date.now()),u)];case 1:return d=o.sent(),this.mount(d,l,n,{isolate:c}),[2]}})})},t}();function d(n){var o=n,e=new Set;return{getState:function(){return o},setState:function(n){o=t(t({},o),n),e.forEach(function(t){return t(o)})},subscribe:function(t,n){return void 0===n&&(n=!0),e.add(t),n&&t(o),function(){return e.delete(t)}}}}function f(t){var n=t.eventBus,o=t.name;return{go:function(t){n.emit(u,{from:o,path:t})},onChange:function(t){return n.on(l,function(n){t(n.path)})},emitRouteChange:function(t){n.emit(c,{from:o,path:t})},onRouteChange:function(t){return n.on(c,function(n){n.from!==o&&t(n.path)})}}}export{a as EventBus,h as MFEHost,f as createSharedRouter,d as createSharedStore,s as enableRouterSync,r as loadScript};
package/build/index.js CHANGED
@@ -1,355 +1 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MFERuntimeZ = {}));
5
- })(this, (function (exports) { 'use strict';
6
-
7
- /******************************************************************************
8
- Copyright (c) Microsoft Corporation.
9
-
10
- Permission to use, copy, modify, and/or distribute this software for any
11
- purpose with or without fee is hereby granted.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
- PERFORMANCE OF THIS SOFTWARE.
20
- ***************************************************************************** */
21
-
22
- var __assign = function() {
23
- __assign = Object.assign || function __assign(t) {
24
- for (var s, i = 1, n = arguments.length; i < n; i++) {
25
- s = arguments[i];
26
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
27
- }
28
- return t;
29
- };
30
- return __assign.apply(this, arguments);
31
- };
32
-
33
- function __awaiter(thisArg, _arguments, P, generator) {
34
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
35
- return new (P || (P = Promise))(function (resolve, reject) {
36
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
37
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
38
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
39
- step((generator = generator.apply(thisArg, _arguments || [])).next());
40
- });
41
- }
42
-
43
- function __generator(thisArg, body) {
44
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
45
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
46
- function verb(n) { return function (v) { return step([n, v]); }; }
47
- function step(op) {
48
- if (f) throw new TypeError("Generator is already executing.");
49
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
50
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
51
- if (y = 0, t) op = [op[0] & 2, t.value];
52
- switch (op[0]) {
53
- case 0: case 1: t = op; break;
54
- case 4: _.label++; return { value: op[1], done: false };
55
- case 5: _.label++; y = op[1]; op = [0]; continue;
56
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
57
- default:
58
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
59
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
60
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
61
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
62
- if (t[2]) _.ops.pop();
63
- _.trys.pop(); continue;
64
- }
65
- op = body.call(thisArg, _);
66
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
67
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
68
- }
69
- }
70
-
71
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
72
- var e = new Error(message);
73
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
74
- };
75
-
76
- // loader/loadScript.ts
77
- var loaded = new Set();
78
- function loadScript(url, options) {
79
- if (options === void 0) { options = {}; }
80
- return __awaiter(this, void 0, void 0, function () {
81
- var _a, timeout, _b, retries, attempt, err_1;
82
- return __generator(this, function (_c) {
83
- switch (_c.label) {
84
- case 0:
85
- _a = options.timeout, timeout = _a === void 0 ? 15000 : _a, _b = options.retries, retries = _b === void 0 ? 1 : _b;
86
- if (loaded.has(url))
87
- return [2 /*return*/];
88
- attempt = 0;
89
- _c.label = 1;
90
- case 1:
91
- if (!(attempt <= retries)) return [3 /*break*/, 6];
92
- _c.label = 2;
93
- case 2:
94
- _c.trys.push([2, 4, , 5]);
95
- return [4 /*yield*/, loadOnce(url, timeout)];
96
- case 3:
97
- _c.sent();
98
- loaded.add(url);
99
- return [2 /*return*/];
100
- case 4:
101
- err_1 = _c.sent();
102
- if (attempt === retries) {
103
- throw err_1;
104
- }
105
- return [3 /*break*/, 5];
106
- case 5:
107
- attempt++;
108
- return [3 /*break*/, 1];
109
- case 6: return [2 /*return*/];
110
- }
111
- });
112
- });
113
- }
114
- function loadOnce(url, timeout) {
115
- return new Promise(function (resolve, reject) {
116
- var script = document.createElement("script");
117
- script.src = url;
118
- script.async = true;
119
- var timer = setTimeout(function () {
120
- cleanup();
121
- reject(new Error("Timeout loading ".concat(url)));
122
- }, timeout);
123
- function cleanup() {
124
- clearTimeout(timer);
125
- script.remove();
126
- }
127
- script.onload = function () {
128
- cleanup();
129
- resolve();
130
- };
131
- script.onerror = function () {
132
- cleanup();
133
- reject(new Error("Failed to load ".concat(url)));
134
- };
135
- document.body.appendChild(script);
136
- });
137
- }
138
-
139
- var EventBus = /** @class */ (function () {
140
- function EventBus() {
141
- this.map = new Map();
142
- }
143
- EventBus.prototype.on = function (event, handler) {
144
- if (!this.map.has(event)) {
145
- this.map.set(event, new Set());
146
- }
147
- this.map.get(event).add(handler);
148
- };
149
- EventBus.prototype.off = function (event, handler) {
150
- var _a;
151
- (_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.delete(handler);
152
- };
153
- EventBus.prototype.emit = function (event, payload) {
154
- var _a;
155
- (_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.forEach(function (fn) { return fn(payload); });
156
- };
157
- return EventBus;
158
- }());
159
-
160
- var ROUTER_EVENTS = {
161
- REQUEST_NAVIGATE: "ROUTER:REQUEST_NAVIGATE",
162
- NAVIGATE: "ROUTER:NAVIGATE",
163
- };
164
-
165
- function enableRouterSync(eventBus, navigate) {
166
- eventBus.on(ROUTER_EVENTS.REQUEST_NAVIGATE, function (_a) {
167
- var path = _a.path;
168
- navigate(path);
169
- eventBus.emit(ROUTER_EVENTS.NAVIGATE, { path: path });
170
- });
171
- }
172
-
173
- var MFEHost = /** @class */ (function () {
174
- function MFEHost(options) {
175
- if (options === void 0) { options = {}; }
176
- var _a, _b;
177
- this.eventBus = new EventBus();
178
- this.isolate = false;
179
- this.stores = (_a = options.stores) !== null && _a !== void 0 ? _a : {};
180
- this.navigate = options.navigate;
181
- this.onRemoteError = options.onRemoteError;
182
- this.fallback = options.fallback;
183
- this.isolate = (_b = options.isolate) !== null && _b !== void 0 ? _b : false;
184
- if (this.navigate) {
185
- enableRouterSync(this.eventBus, this.navigate);
186
- }
187
- }
188
- /** Load remote JS only */
189
- MFEHost.prototype.load = function (url, global) {
190
- var _a, _b;
191
- return __awaiter(this, void 0, void 0, function () {
192
- var err_1, remote, err;
193
- return __generator(this, function (_c) {
194
- switch (_c.label) {
195
- case 0:
196
- _c.trys.push([0, 2, , 3]);
197
- return [4 /*yield*/, loadScript(url, { retries: 1 })];
198
- case 1:
199
- _c.sent();
200
- return [3 /*break*/, 3];
201
- case 2:
202
- err_1 = _c.sent();
203
- (_a = this.onRemoteError) === null || _a === void 0 ? void 0 : _a.call(this, err_1);
204
- throw err_1;
205
- case 3:
206
- remote = window[global];
207
- if (!(remote === null || remote === void 0 ? void 0 : remote.mount)) {
208
- err = new Error("Remote \"".concat(global, "\" not found"));
209
- (_b = this.onRemoteError) === null || _b === void 0 ? void 0 : _b.call(this, err);
210
- throw err;
211
- }
212
- return [2 /*return*/, remote];
213
- }
214
- });
215
- });
216
- };
217
- /** Mount remote with optional Shadow DOM isolation */
218
- MFEHost.prototype.mount = function (remote, el, name, options) {
219
- var _a, _b;
220
- var isolate = (_a = options === null || options === void 0 ? void 0 : options.isolate) !== null && _a !== void 0 ? _a : this.isolate;
221
- var mountEl = el;
222
- // Shadow DOM isolation
223
- if (isolate) {
224
- if (el._shadowRoot)
225
- el._shadowRoot.innerHTML = "";
226
- var mode = (_b = options === null || options === void 0 ? void 0 : options.shadowMode) !== null && _b !== void 0 ? _b : "open";
227
- // @ts-ignore
228
- var shadow = el.attachShadow({ mode: mode })(el)._shadowRoot = shadow;
229
- // For React/Vue remotes, create container div
230
- var container = document.createElement("div");
231
- shadow.appendChild(container);
232
- // @ts-ignore
233
- mountEl = container(el)._mountEl = container;
234
- }
235
- var ctx = {
236
- name: name,
237
- stores: this.stores,
238
- eventBus: this.eventBus,
239
- host: { navigate: this.navigate },
240
- };
241
- try {
242
- remote.mount(mountEl, ctx);
243
- console.log("[MFE] mounted ".concat(name, " ").concat(isolate ? "(shadow)" : ""));
244
- }
245
- catch (err) {
246
- var error = err;
247
- console.error("[MFE] remote ".concat(name, " mount failed:"), error);
248
- if (this.onRemoteError)
249
- this.onRemoteError(error);
250
- if (this.fallback) {
251
- this.fallback(mountEl, name, error, ctx);
252
- }
253
- else {
254
- mountEl.innerHTML = "<div style=\"color:red\">Failed to load ".concat(name, "</div>");
255
- }
256
- }
257
- };
258
- /** Unmount remote */
259
- MFEHost.prototype.unmount = function (remote, el, name) {
260
- var _a, _b, _c, _d;
261
- try {
262
- var mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : (this.isolate ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
263
- (_c = remote.unmount) === null || _c === void 0 ? void 0 : _c.call(remote, mountEl);
264
- delete el._mountEl;
265
- if (name)
266
- console.log("[MFE] unmounted ".concat(name));
267
- }
268
- catch (err) {
269
- (_d = this.onRemoteError) === null || _d === void 0 ? void 0 : _d.call(this, err);
270
- }
271
- };
272
- /** Get central event bus */
273
- MFEHost.prototype.getEventBus = function () {
274
- return this.eventBus;
275
- };
276
- /** Reload remote: unmount + reload script + mount again */
277
- MFEHost.prototype.reloadRemote = function (options) {
278
- var _a, _b, _c;
279
- return __awaiter(this, void 0, void 0, function () {
280
- var name, url, global, el, isolate, oldRemote, mountEl, newRemote;
281
- return __generator(this, function (_d) {
282
- switch (_d.label) {
283
- case 0:
284
- name = options.name, url = options.url, global = options.global, el = options.el, isolate = options.isolate;
285
- try {
286
- oldRemote = window[global];
287
- mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : ((isolate !== null && isolate !== void 0 ? isolate : this.isolate) ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
288
- (_c = oldRemote === null || oldRemote === void 0 ? void 0 : oldRemote.unmount) === null || _c === void 0 ? void 0 : _c.call(oldRemote, mountEl);
289
- }
290
- catch (_e) { }
291
- delete window[global];
292
- return [4 /*yield*/, this.load("".concat(url, "?t=").concat(Date.now()), global)];
293
- case 1:
294
- newRemote = _d.sent();
295
- this.mount(newRemote, el, name, { isolate: isolate });
296
- return [2 /*return*/];
297
- }
298
- });
299
- });
300
- };
301
- return MFEHost;
302
- }());
303
-
304
- function createSharedStore(initial) {
305
- var state = initial;
306
- var listeners = new Set();
307
- return {
308
- getState: function () {
309
- return state;
310
- },
311
- /** Update state (shallow merge) */
312
- setState: function (partial) {
313
- state = __assign(__assign({}, state), partial);
314
- listeners.forEach(function (listener) { return listener(state); });
315
- },
316
- /** Subscribe to state changes */
317
- subscribe: function (fn, callImmediately) {
318
- if (callImmediately === void 0) { callImmediately = true; }
319
- listeners.add(fn);
320
- if (callImmediately)
321
- fn(state); // Immediately call listener with current state
322
- return function () { return listeners.delete(fn); };
323
- },
324
- };
325
- }
326
-
327
- function createSharedRouter(ctx) {
328
- var eventBus = ctx.eventBus, name = ctx.name;
329
- return {
330
- /** Remote → Host */
331
- go: function (path) {
332
- eventBus.emit(ROUTER_EVENTS.REQUEST_NAVIGATE, {
333
- from: name,
334
- path: path,
335
- });
336
- },
337
- /** Host → Remote */
338
- onChange: function (cb) {
339
- return eventBus.on(ROUTER_EVENTS.NAVIGATE, function (payload) {
340
- cb(payload.path);
341
- });
342
- },
343
- };
344
- }
345
-
346
- exports.EventBus = EventBus;
347
- exports.MFEHost = MFEHost;
348
- exports.createSharedRouter = createSharedRouter;
349
- exports.createSharedStore = createSharedStore;
350
- exports.enableRouterSync = enableRouterSync;
351
- exports.loadScript = loadScript;
352
-
353
- Object.defineProperty(exports, '__esModule', { value: true });
354
-
355
- }));
1
+ !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).MFERuntimeZ={})}(this,function(t){"use strict";var n=function(){return n=Object.assign||function(t){for(var n,e=1,o=arguments.length;e<o;e++)for(var r in n=arguments[e])Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r]);return t},n.apply(this,arguments)};function e(t,n,e,o){return new(e||(e=Promise))(function(r,i){function a(t){try{l(o.next(t))}catch(t){i(t)}}function u(t){try{l(o.throw(t))}catch(t){i(t)}}function l(t){var n;t.done?r(t.value):(n=t.value,n instanceof e?n:new e(function(t){t(n)})).then(a,u)}l((o=o.apply(t,n||[])).next())})}function o(t,n){var e,o,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(e)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(e=1,o&&(r=2&u[0]?o.return:u[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,u[1])).done)return r;switch(o=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,o=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=n.call(t,i)}catch(t){u=[6,t],o=0}finally{e=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}"function"==typeof SuppressedError&&SuppressedError;var r=new Set;function i(t,n){return void 0===n&&(n={}),e(this,void 0,void 0,function(){var e,i,u,l,c,s;return o(this,function(o){switch(o.label){case 0:if(e=n.timeout,i=void 0===e?15e3:e,u=n.retries,l=void 0===u?1:u,r.has(t))return[2];c=0,o.label=1;case 1:if(!(c<=l))return[3,6];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,a(t,i)];case 3:return o.sent(),r.add(t),[2];case 4:if(s=o.sent(),c===l)throw s;return[3,5];case 5:return c++,[3,1];case 6:return[2]}})})}function a(t,n){return new Promise(function(e,o){var r=document.createElement("script");r.src=t,r.async=!0;var i=setTimeout(function(){a(),o(new Error("Timeout loading ".concat(t)))},n);function a(){clearTimeout(i),r.remove()}r.onload=function(){a(),e()},r.onerror=function(){a(),o(new Error("Failed to load ".concat(t)))},document.body.appendChild(r)})}var u=function(){function t(){this.map=new Map}return t.prototype.on=function(t,n){this.map.has(t)||this.map.set(t,new Set),this.map.get(t).add(n)},t.prototype.off=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.delete(n)},t.prototype.emit=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.forEach(function(t){return t(n)})},t}(),l="ROUTER:REQUEST_NAVIGATE",c="ROUTER:NAVIGATE",s="ROUTER:ON_CHANGE";function h(t,n){t.on(l,function(e){var o=e.path;n(o),t.emit(c,{path:o})})}var d=function(){function t(t){void 0===t&&(t={});var n,e,o=this;this.eventBus=new u,this.isolate=!1,this.cache={},this.stores=null!==(n=t.stores)&&void 0!==n?n:{},this.navigate=t.navigate,this.onRemoteError=t.onRemoteError,this.fallback=t.fallback,this.isolate=null!==(e=t.isolate)&&void 0!==e&&e,this.onMountStart=t.onMountStart,this.onMountEnd=t.onMountEnd,this.onUnmountStart=t.onUnmountStart,this.onUnmountEnd=t.onUnmountEnd,this.navigate&&h(this.eventBus,this.navigate),this.eventBus.on(s,function(t){var n;null===(n=o.navigate)||void 0===n||n.call(o,t)})}return t.prototype.load=function(t,n){var r,a;return e(this,void 0,void 0,function(){var e,u,l;return o(this,function(o){switch(o.label){case 0:if(this.cache[n])return[2,this.cache[n]];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,i(t,{retries:1})];case 2:return o.sent(),[3,4];case 3:throw e=o.sent(),null===(r=this.onRemoteError)||void 0===r||r.call(this,e),e;case 4:if(!(null==(u=window[n])?void 0:u.mount))throw l=new Error('Remote "'.concat(n,'" not found')),null===(a=this.onRemoteError)||void 0===a||a.call(this,l),l;return this.cache[n]=u,[2,u]}})})},t.prototype.preload=function(t,n){return e(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,this.load(t,n)];case 1:return e.sent(),[2]}})})},t.prototype.mount=function(t,n,e,o){var r,i,a,u,l,c=null!==(r=null==o?void 0:o.isolate)&&void 0!==r?r:this.isolate,s=null;if(n._shadowRoot&&(n._shadowRoot.innerHTML=""),c&&"function"==typeof n.attachShadow)try{s=n.attachShadow({mode:null!==(i=null==o?void 0:o.shadowMode)&&void 0!==i?i:"open"})(n)._shadowRoot=s}catch(t){s=null}var h=document.createElement("div");s?s.appendChild(h):n.appendChild(h),n._mountEl=h;var d={name:e,stores:this.stores,eventBus:this.eventBus,host:{navigate:this.navigate}};try{null===(a=this.onMountStart)||void 0===a||a.call(this,e),t.mount(h,d),null===(u=this.onMountEnd)||void 0===u||u.call(this,e),console.log("[MFE] mounted ".concat(e," ").concat(c?"(shadow/fallback)":""))}catch(t){var f=t;console.error("[MFE] remote ".concat(e," mount failed:"),f),null===(l=this.onRemoteError)||void 0===l||l.call(this,f),this.fallback?this.fallback(h,e,f,d):h.innerHTML='<div style="color:red">Failed to load '.concat(e,"</div>")}},t.prototype.unmount=function(t,n,e){var o,r,i,a,u,l;try{null===(o=this.onUnmountStart)||void 0===o||o.call(this,null!=e?e:"");var c=null!==(r=n._mountEl)&&void 0!==r?r:this.isolate&&null!==(i=n.shadowRoot)&&void 0!==i?i:n;null===(a=t.unmount)||void 0===a||a.call(t,c),delete n._mountEl,null===(u=this.onUnmountEnd)||void 0===u||u.call(this,null!=e?e:""),e&&console.log("[MFE] unmounted ".concat(e))}catch(t){null===(l=this.onRemoteError)||void 0===l||l.call(this,t)}},t.prototype.getEventBus=function(){return this.eventBus},t.prototype.reloadRemote=function(t){var n,r,i;return e(this,void 0,void 0,function(){var e,a,u,l,c,s,h,d;return o(this,function(o){switch(o.label){case 0:e=t.name,a=t.url,u=t.global,l=t.el,c=t.isolate;try{s=window[u],h=null!==(n=l._mountEl)&&void 0!==n?n:(null!=c?c:this.isolate)&&null!==(r=l.shadowRoot)&&void 0!==r?r:l,null===(i=null==s?void 0:s.unmount)||void 0===i||i.call(s,h)}catch(t){}return delete window[u],delete this.cache[u],[4,this.load("".concat(a,"?t=").concat(Date.now()),u)];case 1:return d=o.sent(),this.mount(d,l,e,{isolate:c}),[2]}})})},t}();t.EventBus=u,t.MFEHost=d,t.createSharedRouter=function(t){var n=t.eventBus,e=t.name;return{go:function(t){n.emit(l,{from:e,path:t})},onChange:function(t){return n.on(c,function(n){t(n.path)})},emitRouteChange:function(t){n.emit(s,{from:e,path:t})},onRouteChange:function(t){return n.on(s,function(n){n.from!==e&&t(n.path)})}}},t.createSharedStore=function(t){var e=t,o=new Set;return{getState:function(){return e},setState:function(t){e=n(n({},e),t),o.forEach(function(t){return t(e)})},subscribe:function(t,n){return void 0===n&&(n=!0),o.add(t),n&&t(e),function(){return o.delete(t)}}}},t.enableRouterSync=h,t.loadScript=i,Object.defineProperty(t,"__esModule",{value:!0})});
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).MFERuntimeZ={})}(this,function(t){"use strict";var e=function(){return e=Object.assign||function(t){for(var e,n=1,o=arguments.length;n<o;n++)for(var r in e=arguments[n])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t},e.apply(this,arguments)};function n(t,e,n,o){return new(n||(n=Promise))(function(r,i){function a(t){try{l(o.next(t))}catch(t){i(t)}}function u(t){try{l(o.throw(t))}catch(t){i(t)}}function l(t){var e;t.done?r(t.value):(e=t.value,e instanceof n?e:new n(function(t){t(e)})).then(a,u)}l((o=o.apply(t,e||[])).next())})}function o(t,e){var n,o,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(n)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(n=1,o&&(r=2&u[0]?o.return:u[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,u[1])).done)return r;switch(o=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,o=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=e.call(t,i)}catch(t){u=[6,t],o=0}finally{n=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}"function"==typeof SuppressedError&&SuppressedError;var r=new Set;function i(t,e){return void 0===e&&(e={}),n(this,void 0,void 0,function(){var n,i,u,l,c,s;return o(this,function(o){switch(o.label){case 0:if(n=e.timeout,i=void 0===n?15e3:n,u=e.retries,l=void 0===u?1:u,r.has(t))return[2];c=0,o.label=1;case 1:if(!(c<=l))return[3,6];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,a(t,i)];case 3:return o.sent(),r.add(t),[2];case 4:if(s=o.sent(),c===l)throw s;return[3,5];case 5:return c++,[3,1];case 6:return[2]}})})}function a(t,e){return new Promise(function(n,o){var r=document.createElement("script");r.src=t,r.async=!0;var i=setTimeout(function(){a(),o(new Error("Timeout loading ".concat(t)))},e);function a(){clearTimeout(i),r.remove()}r.onload=function(){a(),n()},r.onerror=function(){a(),o(new Error("Failed to load ".concat(t)))},document.body.appendChild(r)})}var u=function(){function t(){this.map=new Map}return t.prototype.on=function(t,e){this.map.has(t)||this.map.set(t,new Set),this.map.get(t).add(e)},t.prototype.off=function(t,e){var n;null===(n=this.map.get(t))||void 0===n||n.delete(e)},t.prototype.emit=function(t,e){var n;null===(n=this.map.get(t))||void 0===n||n.forEach(function(t){return t(e)})},t}(),l="ROUTER:REQUEST_NAVIGATE",c="ROUTER:NAVIGATE";function s(t,e){t.on(l,function(n){var o=n.path;e(o),t.emit(c,{path:o})})}var f=function(){function t(t){var e,n;void 0===t&&(t={}),this.eventBus=new u,this.isolate=!1,this.stores=null!==(e=t.stores)&&void 0!==e?e:{},this.navigate=t.navigate,this.onRemoteError=t.onRemoteError,this.fallback=t.fallback,this.isolate=null!==(n=t.isolate)&&void 0!==n&&n,this.navigate&&s(this.eventBus,this.navigate)}return t.prototype.load=function(t,e){var r,a;return n(this,void 0,void 0,function(){var n,u,l;return o(this,function(o){switch(o.label){case 0:return o.trys.push([0,2,,3]),[4,i(t,{retries:1})];case 1:return o.sent(),[3,3];case 2:throw n=o.sent(),null===(r=this.onRemoteError)||void 0===r||r.call(this,n),n;case 3:if(!(null==(u=window[e])?void 0:u.mount))throw l=new Error('Remote "'.concat(e,'" not found')),null===(a=this.onRemoteError)||void 0===a||a.call(this,l),l;return[2,u]}})})},t.prototype.mount=function(t,e,n,o){var r,i,a=null!==(r=null==o?void 0:o.isolate)&&void 0!==r?r:this.isolate,u=e;if(a){e._shadowRoot&&(e._shadowRoot.innerHTML="");var l=null!==(i=null==o?void 0:o.shadowMode)&&void 0!==i?i:"open",c=e.attachShadow({mode:l})(e)._shadowRoot=c,s=document.createElement("div");c.appendChild(s),u=s(e)._mountEl=s}var f={name:n,stores:this.stores,eventBus:this.eventBus,host:{navigate:this.navigate}};try{t.mount(u,f),console.log("[MFE] mounted ".concat(n," ").concat(a?"(shadow)":""))}catch(t){var d=t;console.error("[MFE] remote ".concat(n," mount failed:"),d),this.onRemoteError&&this.onRemoteError(d),this.fallback?this.fallback(u,n,d,f):u.innerHTML='<div style="color:red">Failed to load '.concat(n,"</div>")}},t.prototype.unmount=function(t,e,n){var o,r,i,a;try{var u=null!==(o=e._mountEl)&&void 0!==o?o:this.isolate&&null!==(r=e.shadowRoot)&&void 0!==r?r:e;null===(i=t.unmount)||void 0===i||i.call(t,u),delete e._mountEl,n&&console.log("[MFE] unmounted ".concat(n))}catch(t){null===(a=this.onRemoteError)||void 0===a||a.call(this,t)}},t.prototype.getEventBus=function(){return this.eventBus},t.prototype.reloadRemote=function(t){var e,r,i;return n(this,void 0,void 0,function(){var n,a,u,l,c,s,f,d;return o(this,function(o){switch(o.label){case 0:n=t.name,a=t.url,u=t.global,l=t.el,c=t.isolate;try{s=window[u],f=null!==(e=l._mountEl)&&void 0!==e?e:(null!=c?c:this.isolate)&&null!==(r=l.shadowRoot)&&void 0!==r?r:l,null===(i=null==s?void 0:s.unmount)||void 0===i||i.call(s,f)}catch(t){}return delete window[u],[4,this.load("".concat(a,"?t=").concat(Date.now()),u)];case 1:return d=o.sent(),this.mount(d,l,n,{isolate:c}),[2]}})})},t}();t.EventBus=u,t.MFEHost=f,t.createSharedRouter=function(t){var e=t.eventBus,n=t.name;return{go:function(t){e.emit(l,{from:n,path:t})},onChange:function(t){return e.on(c,function(e){t(e.path)})}}},t.createSharedStore=function(t){var n=t,o=new Set;return{getState:function(){return n},setState:function(t){n=e(e({},n),t),o.forEach(function(t){return t(n)})},subscribe:function(t,e){return void 0===e&&(e=!0),o.add(t),e&&t(n),function(){return o.delete(t)}}}},t.enableRouterSync=s,t.loadScript=i,Object.defineProperty(t,"__esModule",{value:!0})});
1
+ !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).MFERuntimeZ={})}(this,function(t){"use strict";var n=function(){return n=Object.assign||function(t){for(var n,e=1,o=arguments.length;e<o;e++)for(var r in n=arguments[e])Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r]);return t},n.apply(this,arguments)};function e(t,n,e,o){return new(e||(e=Promise))(function(r,i){function a(t){try{l(o.next(t))}catch(t){i(t)}}function u(t){try{l(o.throw(t))}catch(t){i(t)}}function l(t){var n;t.done?r(t.value):(n=t.value,n instanceof e?n:new e(function(t){t(n)})).then(a,u)}l((o=o.apply(t,n||[])).next())})}function o(t,n){var e,o,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(e)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(e=1,o&&(r=2&u[0]?o.return:u[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,u[1])).done)return r;switch(o=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,o=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=n.call(t,i)}catch(t){u=[6,t],o=0}finally{e=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}"function"==typeof SuppressedError&&SuppressedError;var r=new Set;function i(t,n){return void 0===n&&(n={}),e(this,void 0,void 0,function(){var e,i,u,l,c,s;return o(this,function(o){switch(o.label){case 0:if(e=n.timeout,i=void 0===e?15e3:e,u=n.retries,l=void 0===u?1:u,r.has(t))return[2];c=0,o.label=1;case 1:if(!(c<=l))return[3,6];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,a(t,i)];case 3:return o.sent(),r.add(t),[2];case 4:if(s=o.sent(),c===l)throw s;return[3,5];case 5:return c++,[3,1];case 6:return[2]}})})}function a(t,n){return new Promise(function(e,o){var r=document.createElement("script");r.src=t,r.async=!0;var i=setTimeout(function(){a(),o(new Error("Timeout loading ".concat(t)))},n);function a(){clearTimeout(i),r.remove()}r.onload=function(){a(),e()},r.onerror=function(){a(),o(new Error("Failed to load ".concat(t)))},document.body.appendChild(r)})}var u=function(){function t(){this.map=new Map}return t.prototype.on=function(t,n){this.map.has(t)||this.map.set(t,new Set),this.map.get(t).add(n)},t.prototype.off=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.delete(n)},t.prototype.emit=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.forEach(function(t){return t(n)})},t}(),l="ROUTER:REQUEST_NAVIGATE",c="ROUTER:NAVIGATE",s="ROUTER:ON_CHANGE";function h(t,n){t.on(l,function(e){var o=e.path;n(o),t.emit(c,{path:o})})}var d=function(){function t(t){void 0===t&&(t={});var n,e,o=this;this.eventBus=new u,this.isolate=!1,this.cache={},this.stores=null!==(n=t.stores)&&void 0!==n?n:{},this.navigate=t.navigate,this.onRemoteError=t.onRemoteError,this.fallback=t.fallback,this.isolate=null!==(e=t.isolate)&&void 0!==e&&e,this.onMountStart=t.onMountStart,this.onMountEnd=t.onMountEnd,this.onUnmountStart=t.onUnmountStart,this.onUnmountEnd=t.onUnmountEnd,this.navigate&&h(this.eventBus,this.navigate),this.eventBus.on(s,function(t){var n;null===(n=o.navigate)||void 0===n||n.call(o,t)})}return t.prototype.load=function(t,n){var r,a;return e(this,void 0,void 0,function(){var e,u,l;return o(this,function(o){switch(o.label){case 0:if(this.cache[n])return[2,this.cache[n]];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,i(t,{retries:1})];case 2:return o.sent(),[3,4];case 3:throw e=o.sent(),null===(r=this.onRemoteError)||void 0===r||r.call(this,e),e;case 4:if(!(null==(u=window[n])?void 0:u.mount))throw l=new Error('Remote "'.concat(n,'" not found')),null===(a=this.onRemoteError)||void 0===a||a.call(this,l),l;return this.cache[n]=u,[2,u]}})})},t.prototype.preload=function(t,n){return e(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,this.load(t,n)];case 1:return e.sent(),[2]}})})},t.prototype.mount=function(t,n,e,o){var r,i,a,u,l,c=null!==(r=null==o?void 0:o.isolate)&&void 0!==r?r:this.isolate,s=null;if(n._shadowRoot&&(n._shadowRoot.innerHTML=""),c&&"function"==typeof n.attachShadow)try{s=n.attachShadow({mode:null!==(i=null==o?void 0:o.shadowMode)&&void 0!==i?i:"open"})(n)._shadowRoot=s}catch(t){s=null}var h=document.createElement("div");s?s.appendChild(h):n.appendChild(h),n._mountEl=h;var d={name:e,stores:this.stores,eventBus:this.eventBus,host:{navigate:this.navigate}};try{null===(a=this.onMountStart)||void 0===a||a.call(this,e),t.mount(h,d),null===(u=this.onMountEnd)||void 0===u||u.call(this,e),console.log("[MFE] mounted ".concat(e," ").concat(c?"(shadow/fallback)":""))}catch(t){var f=t;console.error("[MFE] remote ".concat(e," mount failed:"),f),null===(l=this.onRemoteError)||void 0===l||l.call(this,f),this.fallback?this.fallback(h,e,f,d):h.innerHTML='<div style="color:red">Failed to load '.concat(e,"</div>")}},t.prototype.unmount=function(t,n,e){var o,r,i,a,u,l;try{null===(o=this.onUnmountStart)||void 0===o||o.call(this,null!=e?e:"");var c=null!==(r=n._mountEl)&&void 0!==r?r:this.isolate&&null!==(i=n.shadowRoot)&&void 0!==i?i:n;null===(a=t.unmount)||void 0===a||a.call(t,c),delete n._mountEl,null===(u=this.onUnmountEnd)||void 0===u||u.call(this,null!=e?e:""),e&&console.log("[MFE] unmounted ".concat(e))}catch(t){null===(l=this.onRemoteError)||void 0===l||l.call(this,t)}},t.prototype.getEventBus=function(){return this.eventBus},t.prototype.reloadRemote=function(t){var n,r,i;return e(this,void 0,void 0,function(){var e,a,u,l,c,s,h,d;return o(this,function(o){switch(o.label){case 0:e=t.name,a=t.url,u=t.global,l=t.el,c=t.isolate;try{s=window[u],h=null!==(n=l._mountEl)&&void 0!==n?n:(null!=c?c:this.isolate)&&null!==(r=l.shadowRoot)&&void 0!==r?r:l,null===(i=null==s?void 0:s.unmount)||void 0===i||i.call(s,h)}catch(t){}return delete window[u],delete this.cache[u],[4,this.load("".concat(a,"?t=").concat(Date.now()),u)];case 1:return d=o.sent(),this.mount(d,l,e,{isolate:c}),[2]}})})},t}();t.EventBus=u,t.MFEHost=d,t.createSharedRouter=function(t){var n=t.eventBus,e=t.name;return{go:function(t){n.emit(l,{from:e,path:t})},onChange:function(t){return n.on(c,function(n){t(n.path)})},emitRouteChange:function(t){n.emit(s,{from:e,path:t})},onRouteChange:function(t){return n.on(s,function(n){n.from!==e&&t(n.path)})}}},t.createSharedStore=function(t){var e=t,o=new Set;return{getState:function(){return e},setState:function(t){e=n(n({},e),t),o.forEach(function(t){return t(e)})},subscribe:function(t,n){return void 0===n&&(n=!0),o.add(t),n&&t(e),function(){return o.delete(t)}}}},t.enableRouterSync=h,t.loadScript=i,Object.defineProperty(t,"__esModule",{value:!0})});
@@ -7,6 +7,10 @@ type HostOptions<S extends Record<string, any> = any> = {
7
7
  onRemoteError?: (error: Error) => void;
8
8
  isolate?: boolean;
9
9
  fallback?: (el: HTMLElement, name: string, error: Error, ctx: MFEContext<S>) => void;
10
+ onMountStart?: (name: string) => void;
11
+ onMountEnd?: (name: string) => void;
12
+ onUnmountStart?: (name: string) => void;
13
+ onUnmountEnd?: (name: string) => void;
10
14
  };
11
15
  interface MountOptions {
12
16
  isolate?: boolean;
@@ -19,9 +23,16 @@ export declare class MFEHost<S extends Record<string, any> = any> {
19
23
  private onRemoteError?;
20
24
  private fallback?;
21
25
  private isolate;
26
+ private onMountStart?;
27
+ private onMountEnd?;
28
+ private onUnmountStart?;
29
+ private onUnmountEnd?;
30
+ private cache;
22
31
  constructor(options?: HostOptions<S>);
23
32
  /** Load remote JS only */
24
33
  load(url: string, global: string): Promise<RemoteApp>;
34
+ /** Preload remote script */
35
+ preload(url: string, global: string): Promise<void>;
25
36
  /** Mount remote with optional Shadow DOM isolation */
26
37
  mount(remote: RemoteApp, el: HTMLElement, name: string, options?: MountOptions): void;
27
38
  /** Unmount remote */
@@ -2,8 +2,12 @@ export declare function createSharedRouter(ctx: {
2
2
  eventBus: any;
3
3
  name: string;
4
4
  }): {
5
- /** Remote → Host */
5
+ /** Remote → Host: request host navigation */
6
6
  go(path: string): void;
7
- /** Host → Remote */
7
+ /** Host → Remote: register callback when host navigates */
8
8
  onChange(cb: (path: string) => void): any;
9
+ /** Remote → all: notify route change */
10
+ emitRouteChange(path: string): void;
11
+ /** Remote → Remote: register listener for route changes (excluding self) */
12
+ onRouteChange(cb: (path: string) => void): any;
9
13
  };
@@ -1,4 +1,5 @@
1
1
  export declare const ROUTER_EVENTS: {
2
2
  readonly REQUEST_NAVIGATE: "ROUTER:REQUEST_NAVIGATE";
3
3
  readonly NAVIGATE: "ROUTER:NAVIGATE";
4
+ readonly ROUTER_CHANGE: "ROUTER:ON_CHANGE";
4
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mfe-runtime-z",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Framework-agnostic micro-frontend runtime (host, event bus, shared state, router sync)",
5
5
  "main": "build/index.js",
6
6
  "module": "build/index.esm.js",
@@ -33,14 +33,60 @@
33
33
  "homepage": "https://github.com/delpikye-v/mfe-runtime-z#readme",
34
34
  "keywords": [
35
35
  "micro-frontend",
36
+ "microfrontend",
36
37
  "mfe",
38
+ "micro-fe",
39
+
40
+ "module-federation",
41
+ "webpack-module-federation",
42
+ "vite-federation",
43
+
37
44
  "runtime",
45
+ "runtime-loader",
46
+ "dynamic-runtime",
47
+ "micro-frontend-runtime",
48
+ "mfe-runtime",
49
+
50
+ "framework-agnostic",
51
+ "framework-independent",
52
+ "cross-framework",
53
+
54
+ "react",
55
+ "vue",
56
+ "angular",
57
+ "svelte",
58
+
38
59
  "event-bus",
60
+ "global-event-bus",
61
+ "cross-app-events",
62
+
39
63
  "shared-state",
64
+ "global-state",
65
+ "state-sync",
66
+ "state-sharing",
67
+
40
68
  "router-sync",
41
- "framework-agnostic",
42
- "micro-frontend-runtime",
43
- "mfe-runtime"
69
+ "route-sync",
70
+ "cross-app-routing",
71
+
72
+ "isolation",
73
+ "sandbox",
74
+ "js-sandbox",
75
+
76
+ "lazy-load",
77
+ "dynamic-import",
78
+ "remote-module",
79
+
80
+ "frontend-architecture",
81
+ "frontend-platform",
82
+ "frontend-infrastructure",
83
+
84
+ "monorepo",
85
+ "polyrepo",
86
+
87
+ "enterprise-frontend",
88
+ "scalable-frontend",
89
+ "large-scale-app"
44
90
  ],
45
91
  "author": "Delpi.Kye",
46
92
  "license": "MIT",