@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.
- package/CHANGELOG.md +11 -0
- package/README.md +124 -55
- package/dist/module/host/pendingHostComponentStore.js +33 -14
- package/dist/module/host/pendingHostComponentStore.js.map +1 -1
- package/dist/module/index.js.map +1 -1
- package/dist/module/plugin/disposeBabelPlugin.js +38 -0
- package/dist/module/plugin/disposeBabelPlugin.js.map +1 -0
- package/dist/module/plugin/disposeTransform.js +37 -0
- package/dist/module/plugin/disposeTransform.js.map +1 -0
- package/dist/module/plugin/globalContextScript.js +121 -0
- package/dist/module/plugin/globalContextScript.js.map +1 -0
- package/dist/module/plugin/microFrontendPlugin.js +12 -1
- package/dist/module/plugin/microFrontendPlugin.js.map +1 -1
- package/dist/module/plugin/prelude.js +4 -2
- package/dist/module/plugin/prelude.js.map +1 -1
- package/dist/module/plugin/resolver.js +1 -1
- package/dist/module/plugin/resolver.js.map +1 -1
- package/dist/module/runtime/containerModuleExposure.js +79 -0
- package/dist/module/runtime/containerModuleExposure.js.map +1 -0
- package/dist/module/runtime/containerPairing.js +86 -0
- package/dist/module/runtime/containerPairing.js.map +1 -0
- package/dist/module/runtime/containerRegistry.js +190 -0
- package/dist/module/runtime/containerRegistry.js.map +1 -0
- package/dist/module/runtime/createMicroFrontendRuntime.js +9 -6
- package/dist/module/runtime/createMicroFrontendRuntime.js.map +1 -1
- package/dist/module/runtime/globalContext.js +89 -0
- package/dist/module/runtime/globalContext.js.map +1 -0
- package/dist/module/runtime/registry.js +103 -45
- package/dist/module/runtime/registry.js.map +1 -1
- package/dist/module/session/useMicroFrontendSessions.js +23 -1
- package/dist/module/session/useMicroFrontendSessions.js.map +1 -1
- package/dist/typescript/index.d.ts +1 -0
- package/dist/typescript/plugin/disposeBabelPlugin.d.ts +8 -0
- package/dist/typescript/plugin/disposeTransform.d.ts +3 -0
- package/dist/typescript/plugin/globalContextScript.d.ts +1 -0
- package/dist/typescript/runtime/containerModuleExposure.d.ts +2 -0
- package/dist/typescript/runtime/containerPairing.d.ts +18 -0
- package/dist/typescript/runtime/containerRegistry.d.ts +6 -0
- package/dist/typescript/runtime/globalContext.d.ts +17 -0
- package/dist/typescript/runtime/registry.d.ts +10 -8
- package/package.json +7 -4
- package/src/host/pendingHostComponentStore.ts +58 -29
- package/src/index.ts +1 -0
- package/src/plugin/disposeBabelPlugin.ts +51 -0
- package/src/plugin/disposeTransform.ts +43 -0
- package/src/plugin/globalContextScript.ts +118 -0
- package/src/plugin/microFrontendPlugin.ts +13 -1
- package/src/plugin/prelude.ts +160 -20
- package/src/plugin/resolver.ts +1 -1
- package/src/runtime/containerModuleExposure.ts +92 -0
- package/src/runtime/containerPairing.ts +120 -0
- package/src/runtime/containerRegistry.ts +239 -0
- package/src/runtime/createMicroFrontendRuntime.ts +8 -2
- package/src/runtime/globalContext.ts +164 -0
- package/src/runtime/registry.ts +151 -58
- package/src/session/useMicroFrontendSessions.ts +26 -16
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const CANONICAL_GLOBAL_KEY = '__MICRO_FRONTEND__';
|
|
4
|
+
export class MicroFrontendGlobalContextCompatibilityError extends Error {
|
|
5
|
+
constructor(reason) {
|
|
6
|
+
super(`Cannot establish the micro-frontend global context: ${reason}`);
|
|
7
|
+
this.name = 'MicroFrontendGlobalContextCompatibilityError';
|
|
8
|
+
this.reason = reason;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function assertCompatible(condition, reason) {
|
|
12
|
+
if (!condition) {
|
|
13
|
+
throw new MicroFrontendGlobalContextCompatibilityError(reason);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function getMicroFrontendGlobalContext(globalObject = globalThis) {
|
|
17
|
+
const canonicalValue = Reflect.get(globalObject, CANONICAL_GLOBAL_KEY);
|
|
18
|
+
assertCompatible(canonicalValue == null || isMicroFrontendGlobalContext(canonicalValue) || isLegacyGlobalContext(canonicalValue), 'canonical-global-is-not-adoptable');
|
|
19
|
+
if (isMicroFrontendGlobalContext(canonicalValue)) {
|
|
20
|
+
return canonicalValue;
|
|
21
|
+
}
|
|
22
|
+
const canonicalDescriptor = Object.getOwnPropertyDescriptor(globalObject, CANONICAL_GLOBAL_KEY);
|
|
23
|
+
const legacyHasCanonicalOrder = isLegacyGlobalContext(canonicalValue) && hasKeysInOrder(canonicalValue, ['__INSTANCES__', '__SHARED__']);
|
|
24
|
+
assertCompatible(canonicalDescriptor != null || Reflect.isExtensible(globalObject), 'global-object-is-not-extensible');
|
|
25
|
+
assertCompatible(canonicalDescriptor == null || legacyHasCanonicalOrder || canonicalDescriptor.configurable === true, 'canonical-global-is-locked');
|
|
26
|
+
if (legacyHasCanonicalOrder) {
|
|
27
|
+
return addContainersRegistry(canonicalValue);
|
|
28
|
+
}
|
|
29
|
+
const context = {
|
|
30
|
+
__INSTANCES__: canonicalValue?.__INSTANCES__ ?? [],
|
|
31
|
+
__SHARED__: canonicalValue?.__SHARED__ ?? {},
|
|
32
|
+
__CONTAINERS__: {}
|
|
33
|
+
};
|
|
34
|
+
try {
|
|
35
|
+
assertCompatible(Reflect.defineProperty(globalObject, CANONICAL_GLOBAL_KEY, {
|
|
36
|
+
configurable: true,
|
|
37
|
+
enumerable: true,
|
|
38
|
+
value: context,
|
|
39
|
+
writable: true
|
|
40
|
+
}), 'canonical-global-is-not-adoptable');
|
|
41
|
+
return context;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
restoreProperty(globalObject, CANONICAL_GLOBAL_KEY, canonicalDescriptor);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function addContainersRegistry(context) {
|
|
48
|
+
const containersDescriptor = Object.getOwnPropertyDescriptor(context, '__CONTAINERS__');
|
|
49
|
+
assertCompatible(Reflect.isExtensible(context), 'canonical-global-is-not-adoptable');
|
|
50
|
+
try {
|
|
51
|
+
assertCompatible(Reflect.defineProperty(context, '__CONTAINERS__', {
|
|
52
|
+
configurable: true,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
value: {},
|
|
55
|
+
writable: true
|
|
56
|
+
}), 'canonical-global-is-not-adoptable');
|
|
57
|
+
assertCompatible(isMicroFrontendGlobalContext(context), 'canonical-global-is-not-adoptable');
|
|
58
|
+
return context;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
restoreProperty(context, '__CONTAINERS__', containersDescriptor);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function restoreProperty(target, key, descriptor) {
|
|
65
|
+
const current = Object.getOwnPropertyDescriptor(target, key) ?? {};
|
|
66
|
+
const previous = descriptor ?? {};
|
|
67
|
+
const currentKeys = Object.keys(current);
|
|
68
|
+
const descriptorsMatch = currentKeys.length === Object.keys(previous).length && currentKeys.every(property => Object.is(Reflect.get(current, property), Reflect.get(previous, property)));
|
|
69
|
+
if (descriptorsMatch) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
assertCompatible(descriptor == null ? Reflect.deleteProperty(target, key) : Reflect.defineProperty(target, key, descriptor), 'canonical-global-is-not-adoptable');
|
|
73
|
+
}
|
|
74
|
+
function isMicroFrontendGlobalContext(value) {
|
|
75
|
+
return isObjectRecord(value) && hasKeysInOrder(value, ['__INSTANCES__', '__SHARED__', '__CONTAINERS__']) && Array.isArray(Reflect.get(value, '__INSTANCES__')) && isObjectRecord(Reflect.get(value, '__SHARED__')) && isObjectRecord(Reflect.get(value, '__CONTAINERS__'));
|
|
76
|
+
}
|
|
77
|
+
function isLegacyGlobalContext(value) {
|
|
78
|
+
return isObjectRecord(value) && hasExactKeySet(value, ['__INSTANCES__', '__SHARED__']) && Array.isArray(Reflect.get(value, '__INSTANCES__')) && isObjectRecord(Reflect.get(value, '__SHARED__'));
|
|
79
|
+
}
|
|
80
|
+
const isObjectRecord = value => typeof value === 'object' && value != null && !Array.isArray(value);
|
|
81
|
+
function hasExactKeySet(value, expectedKeys) {
|
|
82
|
+
const actualKeys = Object.keys(value);
|
|
83
|
+
return actualKeys.length === expectedKeys.length && expectedKeys.every(key => actualKeys.includes(key));
|
|
84
|
+
}
|
|
85
|
+
function hasKeysInOrder(value, expectedKeys) {
|
|
86
|
+
const actualKeys = Object.keys(value);
|
|
87
|
+
return actualKeys.length === expectedKeys.length && actualKeys.every((key, index) => key === expectedKeys[index]);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=globalContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["CANONICAL_GLOBAL_KEY","MicroFrontendGlobalContextCompatibilityError","Error","constructor","reason","name","assertCompatible","condition","getMicroFrontendGlobalContext","globalObject","globalThis","canonicalValue","Reflect","get","isMicroFrontendGlobalContext","isLegacyGlobalContext","canonicalDescriptor","Object","getOwnPropertyDescriptor","legacyHasCanonicalOrder","hasKeysInOrder","isExtensible","configurable","addContainersRegistry","context","__INSTANCES__","__SHARED__","__CONTAINERS__","defineProperty","enumerable","value","writable","error","restoreProperty","containersDescriptor","target","key","descriptor","current","previous","currentKeys","keys","descriptorsMatch","length","every","property","is","deleteProperty","isObjectRecord","Array","isArray","hasExactKeySet","expectedKeys","actualKeys","includes","index"],"sourceRoot":"../../../src","sources":["runtime/globalContext.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,44 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { createContainer, exposeModule, getContainer, getExposedModule, removeContainer } from "./containerRegistry.js";
|
|
4
|
+
import { ExposedModuleNotFoundError, SharedModuleAlreadyRegisteredError } from "./errors.js";
|
|
5
|
+
import { getMicroFrontendGlobalContext } from "./globalContext.js";
|
|
4
6
|
import { parseAppRequest } from "./parseAppRequest.js";
|
|
7
|
+
export { createContainer, exposeModule, getContainer, removeContainer };
|
|
5
8
|
export function getMicroFrontendRuntimeContext() {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
return existingContext;
|
|
9
|
-
}
|
|
10
|
-
const context = {
|
|
11
|
-
containers: {},
|
|
12
|
-
sharedModules: {}
|
|
13
|
-
};
|
|
14
|
-
globalThis._graniteMicroFrontend = context;
|
|
9
|
+
const context = getMicroFrontendGlobalContext();
|
|
10
|
+
ensureRuntimeContext(context);
|
|
15
11
|
return context;
|
|
16
12
|
}
|
|
17
|
-
export function createContainer(appName, config = {}) {
|
|
18
|
-
const containers = getMicroFrontendRuntimeContext().containers;
|
|
19
|
-
if (containers[appName] != null) {
|
|
20
|
-
throw new AppContainerAlreadyRegisteredError(appName);
|
|
21
|
-
}
|
|
22
|
-
const container = {
|
|
23
|
-
appName,
|
|
24
|
-
config,
|
|
25
|
-
exposedModules: {}
|
|
26
|
-
};
|
|
27
|
-
containers[appName] = container;
|
|
28
|
-
return container;
|
|
29
|
-
}
|
|
30
|
-
export function exposeModule(container, exposedModule, module) {
|
|
31
|
-
const normalizedModule = normalizeExposedModule(exposedModule);
|
|
32
|
-
if (container.exposedModules[normalizedModule] != null) {
|
|
33
|
-
throw new ExposedModuleAlreadyRegisteredError(container.appName, normalizedModule);
|
|
34
|
-
}
|
|
35
|
-
container.exposedModules[normalizedModule] = module;
|
|
36
|
-
}
|
|
37
13
|
export function registerShared(moduleName, module) {
|
|
38
|
-
const sharedModules =
|
|
14
|
+
const sharedModules = getMicroFrontendGlobalContext().__SHARED__;
|
|
39
15
|
const existingModule = sharedModules[moduleName];
|
|
40
16
|
if (existingModule != null) {
|
|
41
|
-
if (Object.is(existingModule.get(), module)) {
|
|
17
|
+
if (isSharedModule(existingModule) && Object.is(existingModule.get(), module)) {
|
|
42
18
|
return;
|
|
43
19
|
}
|
|
44
20
|
throw new SharedModuleAlreadyRegisteredError(moduleName);
|
|
@@ -48,19 +24,15 @@ export function registerShared(moduleName, module) {
|
|
|
48
24
|
loaded: true
|
|
49
25
|
};
|
|
50
26
|
}
|
|
51
|
-
|
|
52
|
-
return
|
|
27
|
+
function isSharedModule(value) {
|
|
28
|
+
return typeof value === 'object' && value != null && typeof Reflect.get(value, 'get') === 'function' && typeof Reflect.get(value, 'loaded') === 'boolean';
|
|
53
29
|
}
|
|
54
|
-
export function
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
if (container == null) {
|
|
30
|
+
export async function disposeAppResources(appName) {
|
|
31
|
+
const disposeCallbacks = getMicroFrontendRuntimeContext().disposeCallbacksByApp[appName];
|
|
32
|
+
if (disposeCallbacks == null) {
|
|
58
33
|
return;
|
|
59
34
|
}
|
|
60
|
-
|
|
61
|
-
Reflect.deleteProperty(container.exposedModules, exposedModule);
|
|
62
|
-
}
|
|
63
|
-
Reflect.deleteProperty(containers, appName);
|
|
35
|
+
await runAppDisposeCallbacks(disposeCallbacks);
|
|
64
36
|
}
|
|
65
37
|
export function hasContainer(appName) {
|
|
66
38
|
return getContainer(appName) != null;
|
|
@@ -70,14 +42,100 @@ export function importModule(request) {
|
|
|
70
42
|
appName,
|
|
71
43
|
exposedModule
|
|
72
44
|
} = parseAppRequest(request);
|
|
73
|
-
const
|
|
45
|
+
const container = getContainer(appName);
|
|
46
|
+
const module = container == null ? null : getExposedModule(container, exposedModule);
|
|
74
47
|
if (module == null) {
|
|
75
48
|
throw new ExposedModuleNotFoundError(appName, exposedModule);
|
|
76
49
|
}
|
|
77
50
|
return module;
|
|
78
51
|
}
|
|
79
|
-
function
|
|
80
|
-
|
|
52
|
+
function ensureRuntimeContext(context) {
|
|
53
|
+
const containers = context.__CONTAINERS__;
|
|
54
|
+
const sharedModules = context.__SHARED__;
|
|
55
|
+
const propertyDescriptors = new Map();
|
|
56
|
+
const runtimeProperties = {
|
|
57
|
+
containers,
|
|
58
|
+
dispose: isRegisterAppDispose(Reflect.get(context, 'dispose')) ? Reflect.get(context, 'dispose') : createRegisterAppDispose(),
|
|
59
|
+
disposeCallbacksByApp: isDisposeCallbackRegistry(Reflect.get(context, 'disposeCallbacksByApp')) ? Reflect.get(context, 'disposeCallbacksByApp') : {},
|
|
60
|
+
sharedModules
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
for (const property of Reflect.ownKeys(runtimeProperties)) {
|
|
64
|
+
propertyDescriptors.set(property, Reflect.getOwnPropertyDescriptor(context, property));
|
|
65
|
+
const value = Reflect.get(runtimeProperties, property);
|
|
66
|
+
if (!Reflect.defineProperty(context, property, {
|
|
67
|
+
configurable: true,
|
|
68
|
+
enumerable: false,
|
|
69
|
+
value,
|
|
70
|
+
writable: true
|
|
71
|
+
})) {
|
|
72
|
+
throw new Error(`Cannot install micro-frontend runtime property '${String(property)}'`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
for (const [property, descriptor] of Array.from(propertyDescriptors).reverse()) {
|
|
77
|
+
if (descriptor == null) {
|
|
78
|
+
Reflect.deleteProperty(context, property);
|
|
79
|
+
} else {
|
|
80
|
+
Reflect.defineProperty(context, property, descriptor);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function isObjectRecord(value) {
|
|
87
|
+
return typeof value === 'object' && value != null && !Array.isArray(value);
|
|
88
|
+
}
|
|
89
|
+
function isRegisterAppDispose(value) {
|
|
90
|
+
return typeof value === 'function';
|
|
91
|
+
}
|
|
92
|
+
function isDisposeCallbackRegistry(value) {
|
|
93
|
+
return isObjectRecord(value) && Object.values(value).every(isDisposeCallbackSet);
|
|
94
|
+
}
|
|
95
|
+
function isDisposeCallbackSet(value) {
|
|
96
|
+
return typeof value === 'object' && value != null && typeof Reflect.get(value, 'add') === 'function' && typeof Reflect.get(value, 'delete') === 'function' && typeof Reflect.get(value, 'has') === 'function' && typeof Reflect.get(value, Symbol.iterator) === 'function';
|
|
97
|
+
}
|
|
98
|
+
function createRegisterAppDispose() {
|
|
99
|
+
function dispose(appNameOrCallback, callback) {
|
|
100
|
+
if (typeof appNameOrCallback !== 'string' || callback == null) {
|
|
101
|
+
throw new Error('dispose() must be compiled with the microFrontend plugin');
|
|
102
|
+
}
|
|
103
|
+
return registerAppDisposeCallback(getMicroFrontendRuntimeContext(), appNameOrCallback, callback);
|
|
104
|
+
}
|
|
105
|
+
return dispose;
|
|
106
|
+
}
|
|
107
|
+
function registerAppDisposeCallback(context, appName, callback) {
|
|
108
|
+
if (typeof appName !== 'string' || typeof callback !== 'function') {
|
|
109
|
+
throw new Error('dispose() must be compiled with the microFrontend plugin');
|
|
110
|
+
}
|
|
111
|
+
const disposeCallbacks = context.disposeCallbacksByApp[appName] ??= new Set();
|
|
112
|
+
disposeCallbacks.add(callback);
|
|
113
|
+
let isRegistered = true;
|
|
114
|
+
return () => {
|
|
115
|
+
if (!isRegistered) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
isRegistered = false;
|
|
119
|
+
disposeCallbacks.delete(callback);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async function runAppDisposeCallbacks(disposeCallbacks) {
|
|
123
|
+
const callbacks = Array.from(disposeCallbacks).reverse();
|
|
124
|
+
let firstDisposeError;
|
|
125
|
+
let didDisposeFail = false;
|
|
126
|
+
for (const dispose of callbacks) {
|
|
127
|
+
try {
|
|
128
|
+
await dispose();
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (!didDisposeFail) {
|
|
131
|
+
firstDisposeError = error;
|
|
132
|
+
didDisposeFail = true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (didDisposeFail) {
|
|
137
|
+
throw firstDisposeError;
|
|
138
|
+
}
|
|
81
139
|
}
|
|
82
140
|
export const microFrontendModuleRegistry = {
|
|
83
141
|
hasContainer,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["createContainer","exposeModule","getContainer","getExposedModule","removeContainer","ExposedModuleNotFoundError","SharedModuleAlreadyRegisteredError","getMicroFrontendGlobalContext","parseAppRequest","getMicroFrontendRuntimeContext","context","ensureRuntimeContext","registerShared","moduleName","module","sharedModules","__SHARED__","existingModule","isSharedModule","Object","is","get","loaded","value","Reflect","disposeAppResources","appName","disposeCallbacks","disposeCallbacksByApp","runAppDisposeCallbacks","hasContainer","importModule","request","exposedModule","container","containers","__CONTAINERS__","propertyDescriptors","Map","runtimeProperties","dispose","isRegisterAppDispose","createRegisterAppDispose","isDisposeCallbackRegistry","property","ownKeys","set","getOwnPropertyDescriptor","defineProperty","configurable","enumerable","writable","Error","String","error","descriptor","Array","from","reverse","deleteProperty","isObjectRecord","isArray","values","every","isDisposeCallbackSet","Symbol","iterator","appNameOrCallback","callback","registerAppDisposeCallback","Set","add","isRegistered","delete","callbacks","firstDisposeError","didDisposeFail","microFrontendModuleRegistry"],"sourceRoot":"../../../src","sources":["runtime/registry.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { useLayoutEffect, useReducer } from 'react';
|
|
3
|
+
import { useEffect, useLayoutEffect, useReducer, useRef } from 'react';
|
|
4
4
|
import { installPendingHostComponentBridge, resetPendingHostComponent } from "../host/pendingHostComponentStore.js";
|
|
5
|
+
import { disposeAppResources } from "../runtime/registry.js";
|
|
5
6
|
const INITIAL_SESSIONS = [];
|
|
6
7
|
function reduceMicroFrontendSessions(sessions, event) {
|
|
7
8
|
switch (event.name) {
|
|
@@ -32,6 +33,27 @@ function reduceMicroFrontendSessions(sessions, event) {
|
|
|
32
33
|
}
|
|
33
34
|
export function useMicroFrontendSessions(runtime) {
|
|
34
35
|
const [sessions, dispatch] = useReducer(reduceMicroFrontendSessions, INITIAL_SESSIONS);
|
|
36
|
+
const previousSessionsRef = useRef(sessions);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const previousSessions = previousSessionsRef.current;
|
|
39
|
+
previousSessionsRef.current = sessions;
|
|
40
|
+
const activeSessionIds = new Set(sessions.map(({
|
|
41
|
+
sessionId
|
|
42
|
+
}) => sessionId));
|
|
43
|
+
const activeAppNames = new Set(sessions.map(({
|
|
44
|
+
appName
|
|
45
|
+
}) => appName));
|
|
46
|
+
const inactiveAppNames = new Set(previousSessions.filter(({
|
|
47
|
+
sessionId
|
|
48
|
+
}) => !activeSessionIds.has(sessionId)).map(({
|
|
49
|
+
appName
|
|
50
|
+
}) => appName).filter(appName => !activeAppNames.has(appName)));
|
|
51
|
+
inactiveAppNames.forEach(appName => {
|
|
52
|
+
void disposeAppResources(appName).catch(error => {
|
|
53
|
+
console.error(`Failed to dispose micro-frontend app resources for '${appName}'`, error);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}, [sessions]);
|
|
35
57
|
useLayoutEffect(() => {
|
|
36
58
|
installPendingHostComponentBridge();
|
|
37
59
|
const subscription = runtime.onEvent(event => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useLayoutEffect","useReducer","installPendingHostComponentBridge","resetPendingHostComponent","INITIAL_SESSIONS","reduceMicroFrontendSessions","sessions","event","name","some","sessionId","params","appName","scheme","isVisible","filter","map","session","exhaustiveEvent","useMicroFrontendSessions","runtime","dispatch","subscription","onEvent","remove"],"sourceRoot":"../../../src","sources":["session/useMicroFrontendSessions.ts"],"mappings":";;AAAA,SAASA,eAAe,EAAEC,UAAU,QAAQ,OAAO;
|
|
1
|
+
{"version":3,"names":["useEffect","useLayoutEffect","useReducer","useRef","installPendingHostComponentBridge","resetPendingHostComponent","disposeAppResources","INITIAL_SESSIONS","reduceMicroFrontendSessions","sessions","event","name","some","sessionId","params","appName","scheme","isVisible","filter","map","session","exhaustiveEvent","useMicroFrontendSessions","runtime","dispatch","previousSessionsRef","previousSessions","current","activeSessionIds","Set","activeAppNames","inactiveAppNames","has","forEach","catch","error","console","subscription","onEvent","remove"],"sourceRoot":"../../../src","sources":["session/useMicroFrontendSessions.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -11,6 +11,7 @@ export { MicroFrontendSessionProvider, MissingMicroFrontendSessionError, useMicr
|
|
|
11
11
|
export type { MicroFrontendSession, MicroFrontendSessionProviderProps } from './session/MicroFrontendSessionContext';
|
|
12
12
|
export { useMicroFrontendSessions } from './session/useMicroFrontendSessions';
|
|
13
13
|
export type { MicroFrontendSessionState } from './session/useMicroFrontendSessions';
|
|
14
|
+
export type { AppDisposeCallback, MicroFrontendRuntimeContext } from './runtime/registry';
|
|
14
15
|
export { default as Portal } from './specs/PortalViewNativeComponent';
|
|
15
16
|
export type { AppRequest, MicroFrontendAppProps, MicroFrontendAdapter, MicroFrontendBundle, MicroFrontendBundleRequest, MicroFrontendRuntimeApi, MicroFrontendRuntimeEvent, MicroFrontendRuntimeEventSubscription, MicroFrontendSessionEvent, } from './types';
|
|
16
17
|
export { AppContainerNotFoundError, ExposedModuleNotFoundError, InvalidAppNameError, InvalidAppRequestError, InvalidNativeRuntimeEventError, } from './runtime/errors';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PluginObj } from '@babel/core';
|
|
2
|
+
import type * as BabelTypes from '@babel/types';
|
|
3
|
+
export interface DisposeOwnershipPluginOptions {
|
|
4
|
+
appName?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function injectDisposeAppName({ types: babelTypes }: {
|
|
7
|
+
types: typeof BabelTypes;
|
|
8
|
+
}, options: DisposeOwnershipPluginOptions): PluginObj;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const globalContextScript: string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AppContainer } from './registry';
|
|
2
|
+
export declare const CONTAINER_PAIRING_KEY: "granite.micro-frontend.container-pair";
|
|
3
|
+
export interface LegacyAppContainer {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly config: unknown;
|
|
6
|
+
readonly exposeMap: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export declare function defineContainerPair(first: object, second: object): boolean;
|
|
9
|
+
export declare function isContainerPair(first: object, second: object): boolean;
|
|
10
|
+
export declare function getContainerPair(container: object): object | null;
|
|
11
|
+
export declare function clearContainerPair(first: object, second: object): void;
|
|
12
|
+
export declare function rememberContainerPair(modern: AppContainer, legacy: LegacyAppContainer): void;
|
|
13
|
+
export declare function rememberLegacyAdapterPair(modern: AppContainer, legacy: LegacyAppContainer): void;
|
|
14
|
+
export declare function getLegacyContainerPair(modern: AppContainer): LegacyAppContainer | undefined;
|
|
15
|
+
export declare function getModernContainerPair(legacy: LegacyAppContainer): AppContainer | undefined;
|
|
16
|
+
export declare function forgetContainerPair(modern: AppContainer | null, legacy: LegacyAppContainer | null): void;
|
|
17
|
+
export declare function isLegacyAppContainer(value: unknown): value is LegacyAppContainer;
|
|
18
|
+
export declare function isObjectRecord(value: unknown): value is Record<string, unknown>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AppContainer, AppContainerConfig } from './registry';
|
|
2
|
+
export { exposeContainerModule as exposeModule } from './containerModuleExposure';
|
|
3
|
+
export declare function createContainer(appName: string, config?: AppContainerConfig): AppContainer;
|
|
4
|
+
export declare function getContainer(appName: string): AppContainer | null;
|
|
5
|
+
export declare function getExposedModule(container: AppContainer, exposedModule: string): unknown;
|
|
6
|
+
export declare function removeContainer(appName: string): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AppContainer } from './registry';
|
|
2
|
+
type SharedModule = {
|
|
3
|
+
readonly get: () => unknown;
|
|
4
|
+
readonly loaded: boolean;
|
|
5
|
+
};
|
|
6
|
+
export type MicroFrontendGlobalContext = {
|
|
7
|
+
readonly __INSTANCES__: unknown[];
|
|
8
|
+
readonly __SHARED__: Record<string, SharedModule>;
|
|
9
|
+
readonly __CONTAINERS__: Record<string, AppContainer>;
|
|
10
|
+
};
|
|
11
|
+
type CompatibilityFailureReason = 'canonical-global-is-not-adoptable' | 'canonical-global-is-locked' | 'global-object-is-not-extensible' | 'registry-is-not-extensible';
|
|
12
|
+
export declare class MicroFrontendGlobalContextCompatibilityError extends Error {
|
|
13
|
+
readonly reason: CompatibilityFailureReason;
|
|
14
|
+
constructor(reason: CompatibilityFailureReason);
|
|
15
|
+
}
|
|
16
|
+
export declare function getMicroFrontendGlobalContext(globalObject?: object): MicroFrontendGlobalContext;
|
|
17
|
+
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { AppRequest } from '../types';
|
|
2
|
+
import { createContainer, exposeModule, getContainer, removeContainer } from './containerRegistry';
|
|
2
3
|
import type { MicroFrontendModuleRegistry } from './createMicroFrontendRuntime';
|
|
4
|
+
export { createContainer, exposeModule, getContainer, removeContainer };
|
|
3
5
|
export interface SharedModuleConfig {
|
|
4
6
|
readonly eager?: boolean;
|
|
5
7
|
}
|
|
@@ -12,24 +14,24 @@ export interface AppContainer {
|
|
|
12
14
|
readonly config: AppContainerConfig;
|
|
13
15
|
readonly exposedModules: Record<string, unknown>;
|
|
14
16
|
}
|
|
17
|
+
export type AppDisposeCallback = () => void | Promise<void>;
|
|
18
|
+
export interface RegisterAppDispose {
|
|
19
|
+
(callback: AppDisposeCallback): () => void;
|
|
20
|
+
(appName: string, callback: AppDisposeCallback): () => void;
|
|
21
|
+
}
|
|
15
22
|
interface SharedModule {
|
|
16
23
|
readonly get: () => unknown;
|
|
17
24
|
readonly loaded: boolean;
|
|
18
25
|
}
|
|
19
26
|
export interface MicroFrontendRuntimeContext {
|
|
20
27
|
readonly containers: Record<string, AppContainer>;
|
|
28
|
+
readonly dispose: RegisterAppDispose;
|
|
29
|
+
readonly disposeCallbacksByApp: Record<string, Set<AppDisposeCallback>>;
|
|
21
30
|
readonly sharedModules: Record<string, SharedModule>;
|
|
22
31
|
}
|
|
23
|
-
declare global {
|
|
24
|
-
var _graniteMicroFrontend: MicroFrontendRuntimeContext | undefined;
|
|
25
|
-
}
|
|
26
32
|
export declare function getMicroFrontendRuntimeContext(): MicroFrontendRuntimeContext;
|
|
27
|
-
export declare function createContainer(appName: string, config?: AppContainerConfig): AppContainer;
|
|
28
|
-
export declare function exposeModule(container: AppContainer, exposedModule: string, module: unknown): void;
|
|
29
33
|
export declare function registerShared(moduleName: string, module: unknown): void;
|
|
30
|
-
export declare function
|
|
31
|
-
export declare function removeContainer(appName: string): void;
|
|
34
|
+
export declare function disposeAppResources(appName: string): Promise<void>;
|
|
32
35
|
export declare function hasContainer(appName: string): boolean;
|
|
33
36
|
export declare function importModule<TModule>(request: AppRequest): TModule;
|
|
34
37
|
export declare const microFrontendModuleRegistry: MicroFrontendModuleRegistry;
|
|
35
|
-
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@granite-js/micro-frontend",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Micro-frontend build, runtime, session, and Portal contracts for Granite brownfield applications",
|
|
5
5
|
"main": "./dist/module/index.js",
|
|
6
6
|
"types": "./dist/typescript/index.d.ts",
|
|
@@ -55,7 +55,8 @@
|
|
|
55
55
|
"directory": "packages/micro-frontend"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@
|
|
58
|
+
"@babel/core": "7.28.5",
|
|
59
|
+
"@granite-js/utils": "2.1.0",
|
|
59
60
|
"@standard-schema/spec": "^1.0.0"
|
|
60
61
|
},
|
|
61
62
|
"peerDependencies": {
|
|
@@ -70,8 +71,10 @@
|
|
|
70
71
|
}
|
|
71
72
|
},
|
|
72
73
|
"devDependencies": {
|
|
73
|
-
"@
|
|
74
|
-
"@granite-js/
|
|
74
|
+
"@babel/types": "7.28.5",
|
|
75
|
+
"@granite-js/plugin-core": "2.1.0",
|
|
76
|
+
"@granite-js/react-native": "2.1.0",
|
|
77
|
+
"@types/babel__core": "^7.20.5",
|
|
75
78
|
"@types/node": "24.10.12",
|
|
76
79
|
"@types/react": "19.2.0",
|
|
77
80
|
"@types/react-test-renderer": "^19",
|