@granite-js/micro-frontend 2.0.2 → 2.1.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 (56) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +124 -55
  3. package/dist/module/host/pendingHostComponentStore.js +33 -14
  4. package/dist/module/host/pendingHostComponentStore.js.map +1 -1
  5. package/dist/module/index.js.map +1 -1
  6. package/dist/module/plugin/disposeBabelPlugin.js +38 -0
  7. package/dist/module/plugin/disposeBabelPlugin.js.map +1 -0
  8. package/dist/module/plugin/disposeTransform.js +37 -0
  9. package/dist/module/plugin/disposeTransform.js.map +1 -0
  10. package/dist/module/plugin/globalContextScript.js +121 -0
  11. package/dist/module/plugin/globalContextScript.js.map +1 -0
  12. package/dist/module/plugin/microFrontendPlugin.js +12 -1
  13. package/dist/module/plugin/microFrontendPlugin.js.map +1 -1
  14. package/dist/module/plugin/prelude.js +4 -2
  15. package/dist/module/plugin/prelude.js.map +1 -1
  16. package/dist/module/plugin/resolver.js +1 -1
  17. package/dist/module/plugin/resolver.js.map +1 -1
  18. package/dist/module/runtime/containerModuleExposure.js +79 -0
  19. package/dist/module/runtime/containerModuleExposure.js.map +1 -0
  20. package/dist/module/runtime/containerPairing.js +86 -0
  21. package/dist/module/runtime/containerPairing.js.map +1 -0
  22. package/dist/module/runtime/containerRegistry.js +190 -0
  23. package/dist/module/runtime/containerRegistry.js.map +1 -0
  24. package/dist/module/runtime/createMicroFrontendRuntime.js +9 -6
  25. package/dist/module/runtime/createMicroFrontendRuntime.js.map +1 -1
  26. package/dist/module/runtime/globalContext.js +89 -0
  27. package/dist/module/runtime/globalContext.js.map +1 -0
  28. package/dist/module/runtime/registry.js +103 -45
  29. package/dist/module/runtime/registry.js.map +1 -1
  30. package/dist/module/session/useMicroFrontendSessions.js +23 -1
  31. package/dist/module/session/useMicroFrontendSessions.js.map +1 -1
  32. package/dist/typescript/index.d.ts +1 -0
  33. package/dist/typescript/plugin/disposeBabelPlugin.d.ts +8 -0
  34. package/dist/typescript/plugin/disposeTransform.d.ts +3 -0
  35. package/dist/typescript/plugin/globalContextScript.d.ts +1 -0
  36. package/dist/typescript/runtime/containerModuleExposure.d.ts +2 -0
  37. package/dist/typescript/runtime/containerPairing.d.ts +18 -0
  38. package/dist/typescript/runtime/containerRegistry.d.ts +6 -0
  39. package/dist/typescript/runtime/globalContext.d.ts +17 -0
  40. package/dist/typescript/runtime/registry.d.ts +10 -8
  41. package/package.json +7 -4
  42. package/src/host/pendingHostComponentStore.ts +58 -29
  43. package/src/index.ts +1 -0
  44. package/src/plugin/disposeBabelPlugin.ts +51 -0
  45. package/src/plugin/disposeTransform.ts +43 -0
  46. package/src/plugin/globalContextScript.ts +118 -0
  47. package/src/plugin/microFrontendPlugin.ts +13 -1
  48. package/src/plugin/prelude.ts +160 -20
  49. package/src/plugin/resolver.ts +1 -1
  50. package/src/runtime/containerModuleExposure.ts +92 -0
  51. package/src/runtime/containerPairing.ts +120 -0
  52. package/src/runtime/containerRegistry.ts +239 -0
  53. package/src/runtime/createMicroFrontendRuntime.ts +8 -2
  54. package/src/runtime/globalContext.ts +164 -0
  55. package/src/runtime/registry.ts +151 -58
  56. package/src/session/useMicroFrontendSessions.ts +26 -16
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @granite-js/micro-frontend
2
2
 
3
+ ## 2.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0d72b4d: Run retained remote app dispose callbacks when its last session closes without discarding its evaluated container.
8
+
9
+ ### Patch Changes
10
+
11
+ - 975c8cf: Document the canonical cross-version micro-frontend registry contract.
12
+ - @granite-js/utils@2.1.0
13
+
3
14
  ## 2.0.2
4
15
 
5
16
  ### Patch Changes
package/README.md CHANGED
@@ -62,6 +62,10 @@ Fabric components.
62
62
  The app name comes from `granite.config.ts`. Hosts do not maintain a separate
63
63
  remote-app list.
64
64
 
65
+ The generated runtime prelude uses a package-specific file name so this plugin
66
+ can coexist with the legacy `@granite-js/plugin-micro-frontend` plugin during a
67
+ gradual migration. This preserves both plugins' shared-module registrations.
68
+
65
69
  ```ts
66
70
  // Remote app
67
71
  import { microFrontend } from '@granite-js/micro-frontend/plugin';
@@ -101,6 +105,57 @@ export default defineConfig({
101
105
  When evaluated, a remote bundle registers its `appName` container and exposed
102
106
  modules in the shared runtime registry.
103
107
 
108
+ ## Registry migration contract
109
+
110
+ ### As-is
111
+
112
+ Older bundles use `global.__MICRO_FRONTEND__` with `__INSTANCES__` and
113
+ `__SHARED__`. A compatible bundle adds `__CONTAINERS__` to the same canonical
114
+ context. Neither shape is a product router: an `appName` is the identity of one
115
+ remote registration.
116
+
117
+ ### To-be
118
+
119
+ The durable owner is `global.__MICRO_FRONTEND__` with exactly this shape:
120
+
121
+ ```ts
122
+ {
123
+ __INSTANCES__,
124
+ __SHARED__,
125
+ __CONTAINERS__,
126
+ }
127
+ ```
128
+
129
+ - `__INSTANCES__` preserves the legacy container view; `__SHARED__` is the
130
+ shared-module registry; `__CONTAINERS__` is the current container registry.
131
+ - A current container registration creates paired legacy/current views for the
132
+ same app name. The pair is transparent across separately evaluated bundles:
133
+ it is one remote-owned registration, not two independently owned copies.
134
+ - The dispose callback registry and registrar live on the same canonical
135
+ context as non-enumerable properties. They are reused across separately
136
+ evaluated bundles without changing the three-key enumerable registry shape.
137
+
138
+ Bootstrap the canonical context before a compatible host evaluates a remote.
139
+ A compatible remote also installs the canonical bootstrap in its generated
140
+ prelude, so either compatible side can establish the three-store context before
141
+ the bundle registers its container.
142
+
143
+ The executable compatibility matrix is:
144
+
145
+ | Host | Remote | Required order | Status |
146
+ | ---------- | ---------- | -------------- | --------- |
147
+ | Legacy | Legacy | Remote first | Supported |
148
+ | Compatible | Compatible | Host first | Supported |
149
+ | Compatible | Legacy | Host first | Supported |
150
+ | Legacy | Compatible | Remote first | Supported |
151
+
152
+ Registration is duplicate-safe, not aliasing: an occupied app name, duplicate
153
+ exposed module, or incompatible duplicate shared module is rejected. Removal
154
+ clears both paired container views as a unit, after which a fresh same-name
155
+ remote may register. Missing exposes, malformed occupied names, and
156
+ product-specific app-name remapping are unsupported; resolve the requested
157
+ app name exactly rather than routing it to another remote.
158
+
104
159
  ## JavaScript runtime
105
160
 
106
161
  The adapter owns bundle selection, download, integrity verification, and
@@ -136,7 +191,7 @@ adapter.loadBundle({ appName: 'cart' })
136
191
  ```
137
192
 
138
193
  Concurrent preload/import calls for one app share an evaluation. A successful
139
- evaluation remains cached until its last native session closes. Failed
194
+ evaluation remains cached for the lifetime of the JavaScript runtime. Failed
140
195
  evaluation removes the partial container so a later request can retry.
141
196
  Native `preloadApp` events invoke `preloadApp()` inside the runtime and are not
142
197
  forwarded to session listeners. `onPreloadError` is optional and lets the host
@@ -144,12 +199,34 @@ route best-effort native preload failures to its observability provider.
144
199
 
145
200
  The public runtime API is:
146
201
 
147
- | API | Responsibility |
148
- | --- | --- |
149
- | `preloadApp(appName)` | Load and evaluate one app without importing an exposed module. |
150
- | `importApp(request)` | Ensure the app is evaluated and import `appName/exposedModule`. |
151
- | `evaluateScript(filePath)` | Evaluate an already-local bundle in the retained runtime. |
152
- | `onEvent(listener)` | Subscribe to native open, close, and visibility events. |
202
+ | API | Responsibility |
203
+ | -------------------------- | --------------------------------------------------------------- |
204
+ | `preloadApp(appName)` | Load and evaluate one app without importing an exposed module. |
205
+ | `importApp(request)` | Ensure the app is evaluated and import `appName/exposedModule`. |
206
+ | `evaluateScript(filePath)` | Evaluate an already-local bundle in the retained runtime. |
207
+ | `onEvent(listener)` | Subscribe to native open, close, and visibility events. |
208
+
209
+ Remote code can register an idempotent callback for explicit app-level resource
210
+ cleanup:
211
+
212
+ ```ts
213
+ globalThis.__MICRO_FRONTEND__.dispose(() => {
214
+ queryClient.clear();
215
+ });
216
+ ```
217
+
218
+ The micro-frontend plugin assigns the remote app name at build time through
219
+ Granite's common `transformer.transformSync` source path, which is used by both
220
+ Metro and Mpack. When `closeApp(sessionId)` removes an app's last live session,
221
+ the session owner invokes all callbacks registered for that app. Callbacks stay
222
+ registered, so a reopened app invokes them again on its next last close.
223
+ The `disposeAppResources` helper that runs those callbacks is internal lifecycle
224
+ machinery and is not part of this package's public exports. Closing a session
225
+ releases only its React state and native binding: the successful evaluation,
226
+ paired container, exposed modules, shared modules, and pending app routes remain
227
+ cached for the lifetime of the JavaScript runtime, so reopening the app does not
228
+ load or evaluate its bundle again. Failed evaluation still removes its partial
229
+ registration so a later request can retry.
153
230
 
154
231
  ## Session rendering
155
232
 
@@ -161,17 +238,11 @@ joins Granite's existing visibility context.
161
238
  const sessions = useMicroFrontendSessions(runtime);
162
239
 
163
240
  function SessionRoot({ session }: { readonly session: MicroFrontendSessionState }) {
164
- const App = useMemo(
165
- () => lazy(() => runtime.importApp(`${session.appName}/App`)),
166
- [session.appName]
167
- );
241
+ const App = useMemo(() => lazy(() => runtime.importApp(`${session.appName}/App`)), [session.appName]);
168
242
 
169
243
  return (
170
244
  <Portal hostName={session.sessionId}>
171
- <MicroFrontendSessionProvider
172
- sessionId={session.sessionId}
173
- presentationVisibility={session.isVisible}
174
- >
245
+ <MicroFrontendSessionProvider sessionId={session.sessionId} presentationVisibility={session.isVisible}>
175
246
  <App scheme={session.scheme} />
176
247
  </MicroFrontendSessionProvider>
177
248
  </Portal>
@@ -204,9 +275,7 @@ import { useEffect } from 'react';
204
275
  export const Route = createRoute('/products/:productId', {
205
276
  component: ProductPage,
206
277
  validateParams: parseProductParams,
207
- hostPendingComponent: ({ thumbnailUrl }) => (
208
- <ProductPendingComponent thumbnailUrl={thumbnailUrl} />
209
- ),
278
+ hostPendingComponent: ({ thumbnailUrl }) => <ProductPendingComponent thumbnailUrl={thumbnailUrl} />,
210
279
  });
211
280
 
212
281
  function ProductPage() {
@@ -241,12 +310,12 @@ is internal runtime plumbing.
241
310
 
242
311
  Native emits the following events:
243
312
 
244
- | Event | Required params | Meaning |
245
- | --- | --- | --- |
246
- | `preloadApp` | `appName` | Warm an app. |
247
- | `openApp` | `sessionId`, `appName`, `scheme` | Create the session's React tree. |
248
- | `sessionVisibilityChanged` | `sessionId`, `isVisible` | Update presentation visibility from native lifecycle. |
249
- | `closeApp` | `sessionId` | Unmount the tree and release the app when its last session closes. |
313
+ | Event | Required params | Meaning |
314
+ | -------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
315
+ | `preloadApp` | `appName` | Warm an app. |
316
+ | `openApp` | `sessionId`, `appName`, `scheme` | Create the session's React tree. |
317
+ | `sessionVisibilityChanged` | `sessionId`, `isVisible` | Update presentation visibility from native lifecycle. |
318
+ | `closeApp` | `sessionId` | Remove the session tree and binding. If this was the app's last live session, run its registered dispose callbacks while retaining the evaluated app, registry entries, shared modules, and pending app routes. |
250
319
 
251
320
  Events emitted before JavaScript subscribes are queued. Event delivery starts
252
321
  after the runtime installs its first listener.
@@ -280,22 +349,22 @@ destination views in `com.teleport.host`.
280
349
 
281
350
  ### Session APIs
282
351
 
283
- | API | Lifetime / behavior |
284
- | --- | --- |
352
+ | API | Lifetime / behavior |
353
+ | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
285
354
  | `ActivitySessionBinding.bind(activity, sessionId, appName, scheme)` | Convenience binding for an `Activity`. Emits open, derives visibility from start/stop, and emits close on destroy. Bindings are keyed by `sessionId`, so a destroy caused by a configuration change keeps the session open and the next `bind()` with the same id rebinds the recreated instance instead of opening a second session. Use a `sessionId` that identifies the destination, not the Activity instance. Retain it for the Activity lifetime. |
286
- | `GraniteMicroFrontendRuntimeHost.registerSession(sessionId)` | Register a custom native container and return a `GraniteMicroFrontendSessionRegistration`. `sessionId` must be unique for every live destination; reuse only after the previous registration is closed/invalidated. |
287
- | `GraniteMicroFrontendSessionRegistration.openApp(appName, scheme)` | Emit `openApp` once. |
288
- | `GraniteMicroFrontendSessionRegistration.setVisible(isVisible)` | Emit a visibility event only when the value changes. |
289
- | `GraniteMicroFrontendSessionRegistration.closeApp()` | Emit `closeApp` once after open. |
290
- | `GraniteMicroFrontendSessionRegistration.close()` | Unregister the native session. Call after `closeApp()`. |
291
- | `GraniteMicroFrontendRuntimeHost.emitPreloadApp(appName)` | Fire-and-forget preload. |
355
+ | `GraniteMicroFrontendRuntimeHost.registerSession(sessionId)` | Register a custom native container and return a `GraniteMicroFrontendSessionRegistration`. `sessionId` must be unique for every live destination; reuse only after the previous registration is closed/invalidated. |
356
+ | `GraniteMicroFrontendSessionRegistration.openApp(appName, scheme)` | Emit `openApp` once. |
357
+ | `GraniteMicroFrontendSessionRegistration.setVisible(isVisible)` | Emit a visibility event only when the value changes. |
358
+ | `GraniteMicroFrontendSessionRegistration.closeApp()` | Emit `closeApp` once after open. |
359
+ | `GraniteMicroFrontendSessionRegistration.close()` | Unregister the native session. Call after `closeApp()`. |
360
+ | `GraniteMicroFrontendRuntimeHost.emitPreloadApp(appName)` | Fire-and-forget preload. |
292
361
 
293
362
  ### Portal destination APIs
294
363
 
295
- | API | Lifetime / behavior |
296
- | --- | --- |
297
- | `PortalHostView.setName(name)` | Register/unregister the destination name. Use `sessionId`. |
298
- | `PortalHostView.cleanup()` | Permanently unregister the destination during teardown. |
364
+ | API | Lifetime / behavior |
365
+ | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
366
+ | `PortalHostView.setName(name)` | Register/unregister the destination name. Use `sessionId`. |
367
+ | `PortalHostView.cleanup()` | Permanently unregister the destination during teardown. |
299
368
  | `PortalReactRootView(context, reactHost, surfaceId, moduleName)` | Detached Fabric root that forwards touch/pointer events through the retained `ReactHost`; it does not start another runtime or surface. |
300
369
 
301
370
  `PortalHostView` also re-registers on window attachment and temporarily
@@ -411,29 +480,29 @@ Import public APIs from `GraniteMicroFrontendRuntime`.
411
480
 
412
481
  ### Session APIs
413
482
 
414
- | API | Lifetime / behavior |
415
- | --- | --- |
483
+ | API | Lifetime / behavior |
484
+ | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
416
485
  | `+[GraniteMicroFrontendViewControllerSessionBinding bindViewController:sessionId:appName:scheme:]` | Convenience binding for a `UIViewController`. Emits open and derives visibility from `viewWillAppear` / `viewWillDisappear` combined with app foreground and background transitions. Returns `nil` if `sessionId` is already registered. Retain until teardown. |
417
- | `-[GraniteMicroFrontendViewControllerSessionBinding invalidate]` | Emit close and detach lifecycle observation. |
418
- | `+[GraniteMicroFrontendRuntimeHost registerSession:]` | Register a custom container and return a session registration, or `nil` if `sessionId` is already registered. Use a unique id per destination and call `invalidate` before reuse. |
419
- | `-[GraniteMicroFrontendSessionRegistration openAppWithAppName:scheme:]` | Emit `openApp` once. |
420
- | `-[GraniteMicroFrontendSessionRegistration setVisible:]` | Emit visibility only when it changes. |
421
- | `-[GraniteMicroFrontendSessionRegistration closeApp]` | Emit `closeApp` once after open. |
422
- | `-[GraniteMicroFrontendSessionRegistration invalidate]` | Unregister the session. Call after `closeApp`. |
423
- | `+[GraniteMicroFrontendRuntimeHost emitPreloadApp:]` | Fire-and-forget preload. |
486
+ | `-[GraniteMicroFrontendViewControllerSessionBinding invalidate]` | Emit close and detach lifecycle observation. |
487
+ | `+[GraniteMicroFrontendRuntimeHost registerSession:]` | Register a custom container and return a session registration, or `nil` if `sessionId` is already registered. Use a unique id per destination and call `invalidate` before reuse. |
488
+ | `-[GraniteMicroFrontendSessionRegistration openAppWithAppName:scheme:]` | Emit `openApp` once. |
489
+ | `-[GraniteMicroFrontendSessionRegistration setVisible:]` | Emit visibility only when it changes. |
490
+ | `-[GraniteMicroFrontendSessionRegistration closeApp]` | Emit `closeApp` once after open. |
491
+ | `-[GraniteMicroFrontendSessionRegistration invalidate]` | Unregister the session. Call after `closeApp`. |
492
+ | `+[GraniteMicroFrontendRuntimeHost emitPreloadApp:]` | Fire-and-forget preload. |
424
493
 
425
494
  ### Portal destination APIs
426
495
 
427
- | API | Lifetime / behavior |
428
- | --- | --- |
429
- | `-initWithFrame:` | Create and immediately activate a UIKit-owned Portal destination after React has booted. |
430
- | `-initWithFrame:deferredActivation:` | Create before React boot without reading React feature flags. |
431
- | `-setName:` | Register/unregister the destination name. Use `sessionId`. |
432
- | `-activateIfNeeded` | Create the Fabric host, attach its touch handler, and apply the pending name. Main thread only, after React boot. |
433
- | `isActivated` | Whether the underlying Fabric host exists. |
434
- | `hasAttachedContent` | Whether teleported content is currently attached. This is readiness, not presentation visibility. |
435
- | `onContentDidAttach` / `onContentDidDetach` | Main-thread readiness callbacks for the first attach and last detach. |
436
- | `-invalidate` | Unregister the host and clear callbacks during teardown. |
496
+ | API | Lifetime / behavior |
497
+ | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
498
+ | `-initWithFrame:` | Create and immediately activate a UIKit-owned Portal destination after React has booted. |
499
+ | `-initWithFrame:deferredActivation:` | Create before React boot without reading React feature flags. |
500
+ | `-setName:` | Register/unregister the destination name. Use `sessionId`. |
501
+ | `-activateIfNeeded` | Create the Fabric host, attach its touch handler, and apply the pending name. Main thread only, after React boot. |
502
+ | `isActivated` | Whether the underlying Fabric host exists. |
503
+ | `hasAttachedContent` | Whether teleported content is currently attached. This is readiness, not presentation visibility. |
504
+ | `onContentDidAttach` / `onContentDidDetach` | Main-thread readiness callbacks for the first attach and last detach. |
505
+ | `-invalidate` | Unregister the host and clear callbacks during teardown. |
437
506
 
438
507
  ### UIViewController example
439
508
 
@@ -2,20 +2,39 @@
2
2
 
3
3
  import { resolvePendingHostComponentParams } from "./resolveParams.js";
4
4
  import { createPendingHostComponentRoutePrefix, getQueryParamsFromUrl, getRoutePathFromUrl, matchRoutePath, normalizePendingHostComponentAppName, normalizeRoutePath } from "./routeMatcher.js";
5
- function getGlobalObject() {
6
- return globalThis;
7
- }
5
+ import { getMicroFrontendGlobalContext, MicroFrontendGlobalContextCompatibilityError } from "../runtime/globalContext.js";
6
+ const PENDING_STORE_KEY = 'pendingHostComponentStore';
7
+ const HIDE_SHARED_PENDING_HOST_COMPONENT_KEY = 'hideSharedPendingHostComponent';
8
8
  function getPendingHostComponentStore() {
9
- const globalObject = getGlobalObject();
10
- if (globalObject.__graniteMicroFrontendPendingHostComponentStore == null) {
11
- globalObject.__graniteMicroFrontendPendingHostComponentStore = {
12
- entries: [],
13
- hidden: false,
14
- listeners: new Set(),
15
- version: 0
16
- };
9
+ const context = getMicroFrontendGlobalContext();
10
+ const descriptor = Reflect.getOwnPropertyDescriptor(context, PENDING_STORE_KEY);
11
+ if (descriptor != null) {
12
+ if (!isPendingHostComponentStore(descriptor.value)) {
13
+ throw new MicroFrontendGlobalContextCompatibilityError('canonical-global-is-not-adoptable');
14
+ }
15
+ return descriptor.value;
16
+ }
17
+ const store = createPendingHostComponentStore();
18
+ if (!Reflect.defineProperty(context, PENDING_STORE_KEY, {
19
+ configurable: true,
20
+ enumerable: false,
21
+ value: store,
22
+ writable: true
23
+ })) {
24
+ throw new MicroFrontendGlobalContextCompatibilityError('canonical-global-is-not-adoptable');
17
25
  }
18
- return globalObject.__graniteMicroFrontendPendingHostComponentStore;
26
+ return store;
27
+ }
28
+ function createPendingHostComponentStore() {
29
+ return {
30
+ entries: [],
31
+ hidden: false,
32
+ listeners: new Set(),
33
+ version: 0
34
+ };
35
+ }
36
+ function isPendingHostComponentStore(value) {
37
+ return typeof value === 'object' && value != null && Array.isArray(Reflect.get(value, 'entries')) && typeof Reflect.get(value, 'hidden') === 'boolean' && Reflect.get(value, 'listeners') instanceof Set && typeof Reflect.get(value, 'version') === 'number';
19
38
  }
20
39
  function emitPendingHostComponentStoreChange() {
21
40
  const store = getPendingHostComponentStore();
@@ -43,7 +62,7 @@ function setPendingHostComponentHidden(hidden) {
43
62
  }
44
63
  export function hidePendingHostComponent() {
45
64
  setPendingHostComponentHidden(true);
46
- const hideSharedPendingHostComponent = getGlobalObject().hideSharedPendingHostComponent;
65
+ const hideSharedPendingHostComponent = Reflect.get(globalThis, HIDE_SHARED_PENDING_HOST_COMPONENT_KEY);
47
66
  if (typeof hideSharedPendingHostComponent === 'function' && hideSharedPendingHostComponent !== hidePendingHostComponent) {
48
67
  hideSharedPendingHostComponent();
49
68
  }
@@ -52,7 +71,7 @@ export function resetPendingHostComponent() {
52
71
  setPendingHostComponentHidden(false);
53
72
  }
54
73
  export function installPendingHostComponentBridge() {
55
- getGlobalObject().hideSharedPendingHostComponent = hidePendingHostComponent;
74
+ Reflect.set(globalThis, HIDE_SHARED_PENDING_HOST_COMPONENT_KEY, hidePendingHostComponent);
56
75
  }
57
76
  export function registerPendingHostComponentRoute(routePath, options) {
58
77
  const store = getPendingHostComponentStore();
@@ -1 +1 @@
1
- {"version":3,"names":["resolvePendingHostComponentParams","createPendingHostComponentRoutePrefix","getQueryParamsFromUrl","getRoutePathFromUrl","matchRoutePath","normalizePendingHostComponentAppName","normalizeRoutePath","getGlobalObject","globalThis","getPendingHostComponentStore","globalObject","__graniteMicroFrontendPendingHostComponentStore","entries","hidden","listeners","Set","version","emitPendingHostComponentStoreChange","store","forEach","listener","subscribePendingHostComponentStore","add","delete","getPendingHostComponentStoreVersion","getIsPendingHostComponentHidden","setPendingHostComponentHidden","hidePendingHostComponent","hideSharedPendingHostComponent","resetPendingHostComponent","installPendingHostComponentBridge","registerPendingHostComponentRoute","routePath","options","normalizedRoutePath","appName","app","name","routePrefix","id","entry","component","parserParams","validateParams","existingIndex","findIndex","item","push","removePendingHostComponentRoutes","normalizedAppName","remainingEntries","filter","length","resolvePendingHostComponent","request","matched","findRouteByUrl","findRouteByRequest","resolveMatchedPendingHostComponent","params","pathParams","status","value","url","index","resetPendingHostComponentStoreForTest"],"sourceRoot":"../../../src","sources":["host/pendingHostComponentStore.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["resolvePendingHostComponentParams","createPendingHostComponentRoutePrefix","getQueryParamsFromUrl","getRoutePathFromUrl","matchRoutePath","normalizePendingHostComponentAppName","normalizeRoutePath","getMicroFrontendGlobalContext","MicroFrontendGlobalContextCompatibilityError","PENDING_STORE_KEY","HIDE_SHARED_PENDING_HOST_COMPONENT_KEY","getPendingHostComponentStore","context","descriptor","Reflect","getOwnPropertyDescriptor","isPendingHostComponentStore","value","store","createPendingHostComponentStore","defineProperty","configurable","enumerable","writable","entries","hidden","listeners","Set","version","Array","isArray","get","emitPendingHostComponentStoreChange","forEach","listener","subscribePendingHostComponentStore","add","delete","getPendingHostComponentStoreVersion","getIsPendingHostComponentHidden","setPendingHostComponentHidden","hidePendingHostComponent","hideSharedPendingHostComponent","globalThis","resetPendingHostComponent","installPendingHostComponentBridge","set","registerPendingHostComponentRoute","routePath","options","normalizedRoutePath","appName","app","name","routePrefix","id","entry","component","parserParams","validateParams","existingIndex","findIndex","item","push","removePendingHostComponentRoutes","normalizedAppName","remainingEntries","filter","length","resolvePendingHostComponent","request","matched","findRouteByUrl","findRouteByRequest","resolveMatchedPendingHostComponent","params","pathParams","status","url","index","resetPendingHostComponentStoreForTest"],"sourceRoot":"../../../src","sources":["host/pendingHostComponentStore.ts"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["createMicroFrontendRuntime","createRoute","PendingHostComponent","usePendingHostComponentController","useIsPendingHostComponentHidden","useResolvedPendingHostComponent","createPendingHostComponentRoutePrefix","normalizeRoutePath","hidePendingHostComponent","installPendingHostComponentBridge","registerPendingHostComponentRoute","resetPendingHostComponent","resolvePendingHostComponent","MicroFrontendSessionProvider","MissingMicroFrontendSessionError","useMicroFrontendSession","useMicroFrontendSessions","default","Portal","AppContainerNotFoundError","ExposedModuleNotFoundError","InvalidAppNameError","InvalidAppRequestError","InvalidNativeRuntimeEventError"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,0BAA0B,QAAQ,iCAA8B;AAEzE,SAASC,WAAW,QAAQ,kBAAe;AAG3C,SACEC,oBAAoB,EACpBC,iCAAiC,EACjCC,+BAA+B,EAC/BC,+BAA+B,QAC1B,gCAA6B;AASpC,SACEC,qCAAqC,EACrCC,kBAAkB,QACb,wBAAqB;AAC5B,SACEC,wBAAwB,EACxBC,iCAAiC,EACjCC,iCAAiC,EACjCC,yBAAyB,EACzBC,2BAA2B,QACtB,qCAAkC;AACzC,SACEC,4BAA4B,EAC5BC,gCAAgC,EAChCC,uBAAuB,QAClB,0CAAuC;AAE9C,SAASC,wBAAwB,QAAQ,uCAAoC;AAE7E,SAASC,OAAO,IAAIC,MAAM,QAAQ,mCAAmC;AAYrE,SACEC,yBAAyB,EACzBC,0BAA0B,EAC1BC,mBAAmB,EACnBC,sBAAsB,EACtBC,8BAA8B,QACzB,qBAAkB","ignoreList":[]}
1
+ {"version":3,"names":["createMicroFrontendRuntime","createRoute","PendingHostComponent","usePendingHostComponentController","useIsPendingHostComponentHidden","useResolvedPendingHostComponent","createPendingHostComponentRoutePrefix","normalizeRoutePath","hidePendingHostComponent","installPendingHostComponentBridge","registerPendingHostComponentRoute","resetPendingHostComponent","resolvePendingHostComponent","MicroFrontendSessionProvider","MissingMicroFrontendSessionError","useMicroFrontendSession","useMicroFrontendSessions","default","Portal","AppContainerNotFoundError","ExposedModuleNotFoundError","InvalidAppNameError","InvalidAppRequestError","InvalidNativeRuntimeEventError"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,0BAA0B,QAAQ,iCAA8B;AAEzE,SAASC,WAAW,QAAQ,kBAAe;AAG3C,SACEC,oBAAoB,EACpBC,iCAAiC,EACjCC,+BAA+B,EAC/BC,+BAA+B,QAC1B,gCAA6B;AASpC,SACEC,qCAAqC,EACrCC,kBAAkB,QACb,wBAAqB;AAC5B,SACEC,wBAAwB,EACxBC,iCAAiC,EACjCC,iCAAiC,EACjCC,yBAAyB,EACzBC,2BAA2B,QACtB,qCAAkC;AACzC,SACEC,4BAA4B,EAC5BC,gCAAgC,EAChCC,uBAAuB,QAClB,0CAAuC;AAE9C,SAASC,wBAAwB,QAAQ,uCAAoC;AAG7E,SAASC,OAAO,IAAIC,MAAM,QAAQ,mCAAmC;AAYrE,SACEC,yBAAyB,EACzBC,0BAA0B,EAC1BC,mBAAmB,EACnBC,sBAAsB,EACtBC,8BAA8B,QACzB,qBAAkB","ignoreList":[]}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ export function injectDisposeAppName({
4
+ types: babelTypes
5
+ }, options) {
6
+ return {
7
+ name: 'inject-micro-frontend-dispose-app-name',
8
+ visitor: {
9
+ CallExpression(path) {
10
+ if (options.appName == null || path.node.arguments.length !== 1) {
11
+ return;
12
+ }
13
+ const runtimeIdentifier = getRuntimeIdentifier(path.node.callee, babelTypes);
14
+ if (runtimeIdentifier == null || path.scope.getBinding(runtimeIdentifier) != null) {
15
+ return;
16
+ }
17
+ path.node.arguments.unshift(babelTypes.stringLiteral(options.appName));
18
+ }
19
+ }
20
+ };
21
+ }
22
+ function getRuntimeIdentifier(callee, babelTypes) {
23
+ // - `global.__MICRO_FRONTEND__.dispose()`
24
+ // - `globalThis.__MICRO_FRONTEND__.dispose()`
25
+ if (!babelTypes.isMemberExpression(callee) || callee.computed || !babelTypes.isIdentifier(callee.property, {
26
+ name: 'dispose'
27
+ }) || !babelTypes.isMemberExpression(callee.object) || callee.object.computed || !babelTypes.isIdentifier(callee.object.property, {
28
+ name: '__MICRO_FRONTEND__'
29
+ }) || !babelTypes.isIdentifier(callee.object.object, {
30
+ name: 'global'
31
+ }) && !babelTypes.isIdentifier(callee.object.object, {
32
+ name: 'globalThis'
33
+ })) {
34
+ return null;
35
+ }
36
+ return callee.object.object.name;
37
+ }
38
+ //# sourceMappingURL=disposeBabelPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["injectDisposeAppName","types","babelTypes","options","name","visitor","CallExpression","path","appName","node","arguments","length","runtimeIdentifier","getRuntimeIdentifier","callee","scope","getBinding","unshift","stringLiteral","isMemberExpression","computed","isIdentifier","property","object"],"sourceRoot":"../../../src","sources":["plugin/disposeBabelPlugin.ts"],"mappings":";;AAOA,OAAO,SAASA,oBAAoBA,CAClC;EAAEC,KAAK,EAAEC;AAAyC,CAAC,EACnDC,OAAsC,EAC3B;EACX,OAAO;IACLC,IAAI,EAAE,wCAAwC;IAC9CC,OAAO,EAAE;MACPC,cAAcA,CAACC,IAAI,EAAE;QACnB,IAAIJ,OAAO,CAACK,OAAO,IAAI,IAAI,IAAID,IAAI,CAACE,IAAI,CAACC,SAAS,CAACC,MAAM,KAAK,CAAC,EAAE;UAC/D;QACF;QAEA,MAAMC,iBAAiB,GAAGC,oBAAoB,CAACN,IAAI,CAACE,IAAI,CAACK,MAAM,EAAEZ,UAAU,CAAC;QAC5E,IAAIU,iBAAiB,IAAI,IAAI,IAAIL,IAAI,CAACQ,KAAK,CAACC,UAAU,CAACJ,iBAAiB,CAAC,IAAI,IAAI,EAAE;UACjF;QACF;QAEAL,IAAI,CAACE,IAAI,CAACC,SAAS,CAACO,OAAO,CAACf,UAAU,CAACgB,aAAa,CAACf,OAAO,CAACK,OAAO,CAAC,CAAC;MACxE;IACF;EACF,CAAC;AACH;AAEA,SAASK,oBAAoBA,CAC3BC,MAAgE,EAChEZ,UAA6B,EACd;EACf;EACA;EACA,IACE,CAACA,UAAU,CAACiB,kBAAkB,CAACL,MAAM,CAAC,IACtCA,MAAM,CAACM,QAAQ,IACf,CAAClB,UAAU,CAACmB,YAAY,CAACP,MAAM,CAACQ,QAAQ,EAAE;IAAElB,IAAI,EAAE;EAAU,CAAC,CAAC,IAC9D,CAACF,UAAU,CAACiB,kBAAkB,CAACL,MAAM,CAACS,MAAM,CAAC,IAC7CT,MAAM,CAACS,MAAM,CAACH,QAAQ,IACtB,CAAClB,UAAU,CAACmB,YAAY,CAACP,MAAM,CAACS,MAAM,CAACD,QAAQ,EAAE;IAAElB,IAAI,EAAE;EAAqB,CAAC,CAAC,IAC/E,CAACF,UAAU,CAACmB,YAAY,CAACP,MAAM,CAACS,MAAM,CAACA,MAAM,EAAE;IAAEnB,IAAI,EAAE;EAAS,CAAC,CAAC,IACjE,CAACF,UAAU,CAACmB,YAAY,CAACP,MAAM,CAACS,MAAM,CAACA,MAAM,EAAE;IAAEnB,IAAI,EAAE;EAAa,CAAC,CAAE,EACzE;IACA,OAAO,IAAI;EACb;EAEA,OAAOU,MAAM,CAACS,MAAM,CAACA,MAAM,CAACnB,IAAI;AAClC","ignoreList":[]}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ import * as babel from '@babel/core';
4
+ import { injectDisposeAppName } from "./disposeBabelPlugin.js";
5
+ export function shouldTransformDispose(code) {
6
+ return code.includes('globalThis.__MICRO_FRONTEND__.dispose') || code.includes('global.__MICRO_FRONTEND__.dispose');
7
+ }
8
+ export function transformDisposeOwnership(id, code, options) {
9
+ if (options.appName == null || !shouldTransformDispose(code)) {
10
+ return code;
11
+ }
12
+ return babel.transformSync(code, {
13
+ ast: false,
14
+ babelrc: false,
15
+ configFile: false,
16
+ filename: id,
17
+ parserOpts: {
18
+ plugins: getParserPlugins(id),
19
+ sourceType: 'unambiguous'
20
+ },
21
+ plugins: [[injectDisposeAppName, options]],
22
+ retainLines: true
23
+ })?.code ?? code;
24
+ }
25
+ function getParserPlugins(id) {
26
+ const plugins = [];
27
+ if (/\.[cm]?tsx?$/.test(id)) {
28
+ plugins.push('typescript');
29
+ } else if (/\.[cm]?jsx?$/.test(id)) {
30
+ plugins.push('flow');
31
+ }
32
+ if (/\.[cm]?[jt]sx$/.test(id)) {
33
+ plugins.push('jsx');
34
+ }
35
+ return plugins;
36
+ }
37
+ //# sourceMappingURL=disposeTransform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["babel","injectDisposeAppName","shouldTransformDispose","code","includes","transformDisposeOwnership","id","options","appName","transformSync","ast","babelrc","configFile","filename","parserOpts","plugins","getParserPlugins","sourceType","retainLines","test","push"],"sourceRoot":"../../../src","sources":["plugin/disposeTransform.ts"],"mappings":";;AAAA,OAAO,KAAKA,KAAK,MAAM,aAAa;AACpC,SAASC,oBAAoB,QAA4C,yBAAsB;AAE/F,OAAO,SAASC,sBAAsBA,CAACC,IAAY,EAAW;EAC5D,OAAOA,IAAI,CAACC,QAAQ,CAAC,uCAAuC,CAAC,IAAID,IAAI,CAACC,QAAQ,CAAC,mCAAmC,CAAC;AACrH;AAEA,OAAO,SAASC,yBAAyBA,CAACC,EAAU,EAAEH,IAAY,EAAEI,OAAsC,EAAU;EAClH,IAAIA,OAAO,CAACC,OAAO,IAAI,IAAI,IAAI,CAACN,sBAAsB,CAACC,IAAI,CAAC,EAAE;IAC5D,OAAOA,IAAI;EACb;EAEA,OACEH,KAAK,CAACS,aAAa,CAACN,IAAI,EAAE;IACxBO,GAAG,EAAE,KAAK;IACVC,OAAO,EAAE,KAAK;IACdC,UAAU,EAAE,KAAK;IACjBC,QAAQ,EAAEP,EAAE;IACZQ,UAAU,EAAE;MACVC,OAAO,EAAEC,gBAAgB,CAACV,EAAE,CAAC;MAC7BW,UAAU,EAAE;IACd,CAAC;IACDF,OAAO,EAAE,CAAC,CAACd,oBAAoB,EAAEM,OAAO,CAAC,CAAC;IAC1CW,WAAW,EAAE;EACf,CAAC,CAAC,EAAEf,IAAI,IAAIA,IAAI;AAEpB;AAEA,SAASa,gBAAgBA,CAACV,EAAU,EAAkC;EACpE,MAAMS,OAAuC,GAAG,EAAE;EAElD,IAAI,cAAc,CAACI,IAAI,CAACb,EAAE,CAAC,EAAE;IAC3BS,OAAO,CAACK,IAAI,CAAC,YAAY,CAAC;EAC5B,CAAC,MAAM,IAAI,cAAc,CAACD,IAAI,CAACb,EAAE,CAAC,EAAE;IAClCS,OAAO,CAACK,IAAI,CAAC,MAAM,CAAC;EACtB;EAEA,IAAI,gBAAgB,CAACD,IAAI,CAACb,EAAE,CAAC,EAAE;IAC7BS,OAAO,CAACK,IAAI,CAAC,KAAK,CAAC;EACrB;EAEA,OAAOL,OAAO;AAChB","ignoreList":[]}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+
3
+ export const globalContextScript = String.raw`
4
+ (function bootstrapMicroFrontendGlobal(globalObject) {
5
+ var canonicalKey = '__MICRO_FRONTEND__';
6
+ var instancesKey = '__INSTANCES__';
7
+ var sharedKey = '__SHARED__';
8
+ var containersKey = '__CONTAINERS__';
9
+
10
+ function failure(reason) {
11
+ return new Error('Cannot establish the micro-frontend global context: ' + reason);
12
+ }
13
+
14
+ function isRecord(value) {
15
+ return typeof value === 'object' && value != null && !Array.isArray(value);
16
+ }
17
+
18
+ function hasKeysInOrder(value, expectedKeys) {
19
+ var actualKeys = Object.keys(value);
20
+ return actualKeys.length === expectedKeys.length && actualKeys.every(function (key, index) {
21
+ return key === expectedKeys[index];
22
+ });
23
+ }
24
+
25
+ function hasExactKeySet(value, expectedKeys) {
26
+ var actualKeys = Object.keys(value);
27
+ return actualKeys.length === expectedKeys.length && expectedKeys.every(function (key) {
28
+ return actualKeys.indexOf(key) !== -1;
29
+ });
30
+ }
31
+
32
+ function isCanonicalContext(value) {
33
+ return isRecord(value) &&
34
+ hasKeysInOrder(value, [instancesKey, sharedKey, containersKey]) &&
35
+ Array.isArray(value[instancesKey]) &&
36
+ isRecord(value[sharedKey]) &&
37
+ isRecord(value[containersKey]);
38
+ }
39
+
40
+ function isLegacyContext(value) {
41
+ return isRecord(value) &&
42
+ hasExactKeySet(value, [instancesKey, sharedKey]) &&
43
+ Array.isArray(value[instancesKey]) &&
44
+ isRecord(value[sharedKey]);
45
+ }
46
+
47
+ function restoreProperty(target, key, descriptor) {
48
+ var current = Object.getOwnPropertyDescriptor(target, key) || {};
49
+ var previous = descriptor || {};
50
+ var currentKeys = Object.keys(current);
51
+ var descriptorsMatch = currentKeys.length === Object.keys(previous).length && currentKeys.every(function (property) {
52
+ return Object.is(Reflect.get(current, property), Reflect.get(previous, property));
53
+ });
54
+ if (descriptorsMatch) {
55
+ return;
56
+ }
57
+ if (!(descriptor == null ? Reflect.deleteProperty(target, key) : Reflect.defineProperty(target, key, descriptor))) {
58
+ throw failure('canonical-global-is-not-adoptable');
59
+ }
60
+ }
61
+
62
+ var canonicalValue = globalObject[canonicalKey];
63
+ if (canonicalValue != null && !isCanonicalContext(canonicalValue) && !isLegacyContext(canonicalValue)) {
64
+ throw failure('canonical-global-is-not-adoptable');
65
+ }
66
+ if (isCanonicalContext(canonicalValue)) {
67
+ return;
68
+ }
69
+
70
+ var canonicalDescriptor = Object.getOwnPropertyDescriptor(globalObject, canonicalKey);
71
+ var legacyHasCanonicalOrder = isLegacyContext(canonicalValue) &&
72
+ hasKeysInOrder(canonicalValue, [instancesKey, sharedKey]);
73
+ if (canonicalDescriptor == null && !Object.isExtensible(globalObject)) {
74
+ throw failure('global-object-is-not-extensible');
75
+ }
76
+ if (canonicalDescriptor != null && !legacyHasCanonicalOrder && canonicalDescriptor.configurable !== true) {
77
+ throw failure('canonical-global-is-locked');
78
+ }
79
+
80
+ if (legacyHasCanonicalOrder) {
81
+ var containersDescriptor = Object.getOwnPropertyDescriptor(canonicalValue, containersKey);
82
+ if (!Object.isExtensible(canonicalValue)) {
83
+ throw failure('canonical-global-is-not-adoptable');
84
+ }
85
+ try {
86
+ if (!Reflect.defineProperty(canonicalValue, containersKey, {
87
+ configurable: true,
88
+ enumerable: true,
89
+ value: {},
90
+ writable: true,
91
+ }) || !isCanonicalContext(canonicalValue)) {
92
+ throw failure('canonical-global-is-not-adoptable');
93
+ }
94
+ return;
95
+ } catch (error) {
96
+ restoreProperty(canonicalValue, containersKey, containersDescriptor);
97
+ throw error;
98
+ }
99
+ }
100
+
101
+ var context = {
102
+ __INSTANCES__: canonicalValue == null ? [] : canonicalValue[instancesKey],
103
+ __SHARED__: canonicalValue == null ? {} : canonicalValue[sharedKey],
104
+ __CONTAINERS__: {},
105
+ };
106
+ try {
107
+ if (!Reflect.defineProperty(globalObject, canonicalKey, {
108
+ configurable: true,
109
+ enumerable: true,
110
+ value: context,
111
+ writable: true,
112
+ })) {
113
+ throw failure('canonical-global-is-not-adoptable');
114
+ }
115
+ } catch (error) {
116
+ restoreProperty(globalObject, canonicalKey, canonicalDescriptor);
117
+ throw error;
118
+ }
119
+ })(global);
120
+ `;
121
+ //# sourceMappingURL=globalContextScript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["globalContextScript","String","raw"],"sourceRoot":"../../../src","sources":["plugin/globalContextScript.ts"],"mappings":";;AAAA,OAAO,MAAMA,mBAAmB,GAAGC,MAAM,CAACC,GAAG;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}