repluggable-core 1.302.65 → 1.302.67
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/__tests__/spec-setup.js +3 -0
- package/dist/es/{API.d.ts → src/API.d.ts} +46 -8
- package/dist/es/src/API.d.ts.map +1 -0
- package/dist/es/src/API.js +3 -0
- package/dist/es/src/API.js.map +1 -0
- package/dist/es/src/IterableWeakMap.d.ts +20 -0
- package/dist/es/src/IterableWeakMap.d.ts.map +1 -0
- package/dist/es/src/IterableWeakMap.js +92 -0
- package/dist/es/src/IterableWeakMap.js.map +1 -0
- package/dist/es/src/__internal.d.ts.map +1 -0
- package/dist/es/src/__internal.js +5 -0
- package/dist/es/src/__internal.js.map +1 -0
- package/dist/es/src/appHost.d.ts +7 -0
- package/dist/es/src/appHost.d.ts.map +1 -0
- package/dist/es/src/appHost.js +898 -0
- package/dist/es/src/appHost.js.map +1 -0
- package/dist/es/src/appHostServices.d.ts +12 -0
- package/dist/es/src/appHostServices.d.ts.map +1 -0
- package/dist/es/src/appHostServices.js +25 -0
- package/dist/es/src/appHostServices.js.map +1 -0
- package/dist/es/src/appHostUtils.d.ts +4 -0
- package/dist/es/src/appHostUtils.d.ts.map +1 -0
- package/dist/es/src/appHostUtils.js +8 -0
- package/dist/es/src/appHostUtils.js.map +1 -0
- package/dist/es/src/extensionSlot.d.ts +8 -0
- package/dist/es/src/extensionSlot.d.ts.map +1 -0
- package/dist/es/src/extensionSlot.js +59 -0
- package/dist/es/src/extensionSlot.js.map +1 -0
- package/dist/es/src/hot.d.ts +14 -0
- package/dist/es/src/hot.d.ts.map +1 -0
- package/dist/es/src/hot.js +52 -0
- package/dist/es/src/hot.js.map +1 -0
- package/dist/es/src/index.d.ts +11 -0
- package/dist/es/src/index.d.ts.map +1 -0
- package/dist/es/src/index.js +10 -0
- package/dist/es/src/index.js.map +1 -0
- package/dist/es/src/installedShellsState.d.ts +19 -0
- package/dist/es/src/installedShellsState.d.ts.map +1 -0
- package/dist/es/src/installedShellsState.js +30 -0
- package/dist/es/src/installedShellsState.js.map +1 -0
- package/dist/es/src/interceptAnyObject.d.ts +7 -0
- package/dist/es/src/interceptAnyObject.d.ts.map +1 -0
- package/dist/es/src/interceptAnyObject.js +21 -0
- package/dist/es/src/interceptAnyObject.js.map +1 -0
- package/dist/es/src/invokeSlotCallbacks.d.ts +3 -0
- package/dist/es/src/invokeSlotCallbacks.d.ts.map +1 -0
- package/dist/es/src/invokeSlotCallbacks.js +20 -0
- package/dist/es/src/invokeSlotCallbacks.js.map +1 -0
- package/dist/es/src/loggers.d.ts +4 -0
- package/dist/es/src/loggers.d.ts.map +1 -0
- package/dist/es/src/loggers.js +100 -0
- package/dist/es/src/loggers.js.map +1 -0
- package/dist/es/src/monitorAPI.d.ts +3 -0
- package/dist/es/src/monitorAPI.d.ts.map +1 -0
- package/dist/es/src/monitorAPI.js +53 -0
- package/dist/es/src/monitorAPI.js.map +1 -0
- package/dist/es/src/repluggableAppDebug/index.d.ts +2 -0
- package/dist/es/src/repluggableAppDebug/index.d.ts.map +1 -0
- package/dist/es/src/repluggableAppDebug/index.js +2 -0
- package/dist/es/src/repluggableAppDebug/index.js.map +1 -0
- package/dist/es/src/repluggableAppDebug/performanceDebugInfo.d.ts +15 -0
- package/dist/es/src/repluggableAppDebug/performanceDebugInfo.d.ts.map +1 -0
- package/dist/es/src/repluggableAppDebug/performanceDebugInfo.js +94 -0
- package/dist/es/src/repluggableAppDebug/performanceDebugInfo.js.map +1 -0
- package/dist/es/src/repluggableAppDebug/repluggableAppDebug.d.ts +24 -0
- package/dist/es/src/repluggableAppDebug/repluggableAppDebug.d.ts.map +1 -0
- package/dist/es/src/repluggableAppDebug/repluggableAppDebug.js +132 -0
- package/dist/es/src/repluggableAppDebug/repluggableAppDebug.js.map +1 -0
- package/dist/es/src/tarjanGraph.d.ts +27 -0
- package/dist/es/src/tarjanGraph.d.ts.map +1 -0
- package/dist/es/src/tarjanGraph.js +94 -0
- package/dist/es/src/tarjanGraph.js.map +1 -0
- package/dist/es/src/throttledStore.d.ts +32 -0
- package/dist/es/src/throttledStore.d.ts.map +1 -0
- package/dist/es/src/throttledStore.js +240 -0
- package/dist/es/src/throttledStore.js.map +1 -0
- package/dist/es/test/IterableWeakMap.spec.d.ts +2 -0
- package/dist/es/test/IterableWeakMap.spec.d.ts.map +1 -0
- package/dist/es/test/IterableWeakMap.spec.js +218 -0
- package/dist/es/test/IterableWeakMap.spec.js.map +1 -0
- package/dist/es/test/appHost.mock.d.ts +4 -0
- package/dist/es/test/appHost.mock.d.ts.map +1 -0
- package/dist/es/test/appHost.mock.js +54 -0
- package/dist/es/test/appHost.mock.js.map +1 -0
- package/dist/es/test/appHost.spec.d.ts +2 -0
- package/dist/es/test/appHost.spec.d.ts.map +1 -0
- package/dist/es/test/appHost.spec.js +1451 -0
- package/dist/es/test/appHost.spec.js.map +1 -0
- package/dist/es/test/installedShellsState.spec.d.ts +2 -0
- package/dist/es/test/installedShellsState.spec.d.ts.map +1 -0
- package/dist/es/test/installedShellsState.spec.js +28 -0
- package/dist/es/test/installedShellsState.spec.js.map +1 -0
- package/dist/es/test/interceptAnyObject.spec.d.ts +2 -0
- package/dist/es/test/interceptAnyObject.spec.d.ts.map +1 -0
- package/dist/es/test/interceptAnyObject.spec.js +166 -0
- package/dist/es/test/interceptAnyObject.spec.js.map +1 -0
- package/dist/es/test/loggers.spec.d.ts +2 -0
- package/dist/es/test/loggers.spec.d.ts.map +1 -0
- package/dist/es/test/loggers.spec.js +218 -0
- package/dist/es/test/loggers.spec.js.map +1 -0
- package/dist/es/test/repluggableAppDebug.spec.d.ts +2 -0
- package/dist/es/test/repluggableAppDebug.spec.d.ts.map +1 -0
- package/dist/es/test/repluggableAppDebug.spec.js +107 -0
- package/dist/es/test/repluggableAppDebug.spec.js.map +1 -0
- package/dist/es/test/testKit.spec.d.ts +2 -0
- package/dist/es/test/testKit.spec.d.ts.map +1 -0
- package/dist/es/test/testKit.spec.js +129 -0
- package/dist/es/test/testKit.spec.js.map +1 -0
- package/dist/es/testKit/emptyLoggerOptions.d.ts +3 -0
- package/dist/es/testKit/emptyLoggerOptions.d.ts.map +1 -0
- package/dist/es/testKit/emptyLoggerOptions.js +15 -0
- package/dist/es/testKit/emptyLoggerOptions.js.map +1 -0
- package/dist/es/testKit/index.d.ts +27 -0
- package/dist/es/testKit/index.d.ts.map +1 -0
- package/dist/es/testKit/index.js +132 -0
- package/dist/es/testKit/index.js.map +1 -0
- package/dist/es/testKit/mockPackage.d.ts +23 -0
- package/dist/es/testKit/mockPackage.d.ts.map +1 -0
- package/dist/es/testKit/mockPackage.js +95 -0
- package/dist/es/testKit/mockPackage.js.map +1 -0
- package/dist/es/testKit/withConsoleErrors.d.ts +2 -0
- package/dist/es/testKit/withConsoleErrors.d.ts.map +1 -0
- package/dist/es/testKit/withConsoleErrors.js +12 -0
- package/dist/es/testKit/withConsoleErrors.js.map +1 -0
- package/dist/es/testKit/withThrowOnError.d.ts +3 -0
- package/dist/es/testKit/withThrowOnError.d.ts.map +1 -0
- package/dist/es/testKit/withThrowOnError.js +27 -0
- package/dist/es/testKit/withThrowOnError.js.map +1 -0
- package/dist/src/API.d.ts +46 -8
- package/dist/src/API.d.ts.map +1 -1
- package/dist/src/API.js +4 -0
- package/dist/src/API.js.map +1 -1
- package/dist/src/IterableWeakMap.d.ts +20 -0
- package/dist/src/IterableWeakMap.d.ts.map +1 -0
- package/dist/src/IterableWeakMap.js +96 -0
- package/dist/src/IterableWeakMap.js.map +1 -0
- package/dist/src/__internal.d.ts.map +1 -1
- package/dist/src/__internal.js +1 -1
- package/dist/src/__internal.js.map +1 -1
- package/dist/src/appHost.d.ts +7 -0
- package/dist/src/appHost.d.ts.map +1 -0
- package/dist/src/appHost.js +906 -0
- package/dist/src/appHost.js.map +1 -0
- package/dist/src/appHostServices.d.ts +12 -0
- package/dist/src/appHostServices.d.ts.map +1 -0
- package/dist/src/appHostServices.js +29 -0
- package/dist/src/appHostServices.js.map +1 -0
- package/dist/src/appHostUtils.d.ts +4 -0
- package/dist/src/appHostUtils.d.ts.map +1 -0
- package/dist/src/appHostUtils.js +16 -0
- package/dist/src/appHostUtils.js.map +1 -0
- package/dist/src/extensionSlot.d.ts +8 -0
- package/dist/src/extensionSlot.d.ts.map +1 -0
- package/dist/src/extensionSlot.js +67 -0
- package/dist/src/extensionSlot.js.map +1 -0
- package/dist/src/hot.d.ts +14 -0
- package/dist/src/hot.d.ts.map +1 -0
- package/dist/src/hot.js +56 -0
- package/dist/src/hot.js.map +1 -0
- package/dist/src/index.d.ts +10 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +22 -15
- package/dist/src/index.js.map +1 -1
- package/dist/src/installedShellsState.d.ts +19 -0
- package/dist/src/installedShellsState.d.ts.map +1 -0
- package/dist/src/installedShellsState.js +38 -0
- package/dist/src/installedShellsState.js.map +1 -0
- package/dist/src/interceptAnyObject.d.ts +7 -0
- package/dist/src/interceptAnyObject.d.ts.map +1 -0
- package/dist/src/interceptAnyObject.js +28 -0
- package/dist/src/interceptAnyObject.js.map +1 -0
- package/dist/src/invokeSlotCallbacks.d.ts +3 -0
- package/dist/src/invokeSlotCallbacks.d.ts.map +1 -0
- package/dist/src/invokeSlotCallbacks.js +24 -0
- package/dist/src/invokeSlotCallbacks.js.map +1 -0
- package/dist/src/loggers.d.ts +4 -0
- package/dist/src/loggers.d.ts.map +1 -0
- package/dist/src/loggers.js +104 -0
- package/dist/src/loggers.js.map +1 -0
- package/dist/src/monitorAPI.d.ts +3 -0
- package/dist/src/monitorAPI.d.ts.map +1 -0
- package/dist/src/monitorAPI.js +57 -0
- package/dist/src/monitorAPI.js.map +1 -0
- package/dist/src/repluggableAppDebug/index.d.ts +2 -0
- package/dist/src/repluggableAppDebug/index.d.ts.map +1 -0
- package/dist/src/repluggableAppDebug/index.js +6 -0
- package/dist/src/repluggableAppDebug/index.js.map +1 -0
- package/dist/src/repluggableAppDebug/performanceDebugInfo.d.ts +15 -0
- package/dist/src/repluggableAppDebug/performanceDebugInfo.d.ts.map +1 -0
- package/dist/src/repluggableAppDebug/performanceDebugInfo.js +101 -0
- package/dist/src/repluggableAppDebug/performanceDebugInfo.js.map +1 -0
- package/dist/src/repluggableAppDebug/repluggableAppDebug.d.ts +24 -0
- package/dist/src/repluggableAppDebug/repluggableAppDebug.d.ts.map +1 -0
- package/dist/src/repluggableAppDebug/repluggableAppDebug.js +139 -0
- package/dist/src/repluggableAppDebug/repluggableAppDebug.js.map +1 -0
- package/dist/src/tarjanGraph.d.ts +27 -0
- package/dist/src/tarjanGraph.d.ts.map +1 -0
- package/dist/src/tarjanGraph.js +100 -0
- package/dist/src/tarjanGraph.js.map +1 -0
- package/dist/src/throttledStore.d.ts +32 -0
- package/dist/src/throttledStore.d.ts.map +1 -0
- package/dist/src/throttledStore.js +249 -0
- package/dist/src/throttledStore.js.map +1 -0
- package/dist/test/IterableWeakMap.spec.d.ts +2 -0
- package/dist/test/IterableWeakMap.spec.d.ts.map +1 -0
- package/dist/test/IterableWeakMap.spec.js +220 -0
- package/dist/test/IterableWeakMap.spec.js.map +1 -0
- package/dist/test/appHost.mock.d.ts +4 -0
- package/dist/test/appHost.mock.d.ts.map +1 -0
- package/dist/test/appHost.mock.js +59 -0
- package/dist/test/appHost.mock.js.map +1 -0
- package/dist/test/appHost.spec.d.ts +2 -0
- package/dist/test/appHost.spec.d.ts.map +1 -0
- package/dist/test/appHost.spec.js +1456 -0
- package/dist/test/appHost.spec.js.map +1 -0
- package/dist/test/installedShellsState.spec.d.ts +2 -0
- package/dist/test/installedShellsState.spec.d.ts.map +1 -0
- package/dist/test/installedShellsState.spec.js +30 -0
- package/dist/test/installedShellsState.spec.js.map +1 -0
- package/dist/test/interceptAnyObject.spec.d.ts +2 -0
- package/dist/test/interceptAnyObject.spec.d.ts.map +1 -0
- package/dist/test/interceptAnyObject.spec.js +171 -0
- package/dist/test/interceptAnyObject.spec.js.map +1 -0
- package/dist/test/loggers.spec.d.ts +2 -0
- package/dist/test/loggers.spec.d.ts.map +1 -0
- package/dist/test/loggers.spec.js +220 -0
- package/dist/test/loggers.spec.js.map +1 -0
- package/dist/test/repluggableAppDebug.spec.d.ts +2 -0
- package/dist/test/repluggableAppDebug.spec.d.ts.map +1 -0
- package/dist/test/repluggableAppDebug.spec.js +109 -0
- package/dist/test/repluggableAppDebug.spec.js.map +1 -0
- package/dist/test/testKit.spec.d.ts +2 -0
- package/dist/test/testKit.spec.d.ts.map +1 -0
- package/dist/test/testKit.spec.js +134 -0
- package/dist/test/testKit.spec.js.map +1 -0
- package/dist/testKit/emptyLoggerOptions.d.ts +3 -0
- package/dist/testKit/emptyLoggerOptions.d.ts.map +1 -0
- package/dist/testKit/emptyLoggerOptions.js +18 -0
- package/dist/testKit/emptyLoggerOptions.js.map +1 -0
- package/dist/testKit/index.d.ts +27 -0
- package/dist/testKit/index.d.ts.map +1 -0
- package/dist/testKit/index.js +160 -0
- package/dist/testKit/index.js.map +1 -0
- package/dist/testKit/mockPackage.d.ts +23 -0
- package/dist/testKit/mockPackage.d.ts.map +1 -0
- package/dist/testKit/mockPackage.js +101 -0
- package/dist/testKit/mockPackage.js.map +1 -0
- package/dist/testKit/withConsoleErrors.d.ts +2 -0
- package/dist/testKit/withConsoleErrors.d.ts.map +1 -0
- package/dist/testKit/withConsoleErrors.js +16 -0
- package/dist/testKit/withConsoleErrors.js.map +1 -0
- package/dist/testKit/withThrowOnError.d.ts +3 -0
- package/dist/testKit/withThrowOnError.d.ts.map +1 -0
- package/dist/testKit/withThrowOnError.js +31 -0
- package/dist/testKit/withThrowOnError.js.map +1 -0
- package/jest.config.js +16 -0
- package/package.json +21 -3
- package/src/API.ts +47 -9
- package/src/IterableWeakMap.ts +123 -0
- package/src/__internal.ts +1 -1
- package/src/appHost.ts +1222 -0
- package/src/appHostServices.ts +42 -0
- package/src/appHostUtils.ts +11 -0
- package/src/extensionSlot.ts +96 -0
- package/src/hot.ts +53 -0
- package/src/index.ts +42 -2
- package/src/installedShellsState.ts +54 -0
- package/src/interceptAnyObject.ts +39 -0
- package/src/invokeSlotCallbacks.ts +20 -0
- package/src/loggers.ts +112 -0
- package/src/monitorAPI.ts +71 -0
- package/src/repluggableAppDebug/debug.d.ts +37 -0
- package/src/repluggableAppDebug/index.ts +1 -0
- package/src/repluggableAppDebug/performanceDebugInfo.ts +96 -0
- package/src/repluggableAppDebug/repluggableAppDebug.ts +192 -0
- package/src/tarjanGraph.ts +96 -0
- package/src/throttledStore.ts +355 -0
- package/test/IterableWeakMap.spec.ts +280 -0
- package/test/appHost.mock.ts +58 -0
- package/test/appHost.spec.ts +1765 -0
- package/test/installedShellsState.spec.ts +39 -0
- package/test/interceptAnyObject.spec.ts +217 -0
- package/test/loggers.spec.ts +288 -0
- package/test/repluggableAppDebug.spec.ts +118 -0
- package/test/testKit.spec.tsx +153 -0
- package/testKit/emptyLoggerOptions.ts +16 -0
- package/testKit/index.ts +170 -0
- package/testKit/mockPackage.ts +110 -0
- package/testKit/package.json +3 -0
- package/testKit/withConsoleErrors.ts +12 -0
- package/testKit/withThrowOnError.ts +34 -0
- package/tsconfig.json +9 -2
- package/dist/es/API.d.ts.map +0 -1
- package/dist/es/API.js +0 -2
- package/dist/es/API.js.map +0 -1
- package/dist/es/__internal.d.ts.map +0 -1
- package/dist/es/__internal.js +0 -5
- package/dist/es/__internal.js.map +0 -1
- package/dist/es/index.d.ts +0 -3
- package/dist/es/index.d.ts.map +0 -1
- package/dist/es/index.js +0 -2
- package/dist/es/index.js.map +0 -1
- /package/dist/es/{__internal.d.ts → src/__internal.d.ts} +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { getPerformanceDebug } from './performanceDebugInfo'
|
|
2
|
+
import { AnySlotKey, AppHost, EntryPoint, LazyEntryPointFactory, PrivateShell, SlotKey, StatisticsMemoization, Trace } from '../API'
|
|
3
|
+
import _ from 'lodash'
|
|
4
|
+
import { hot } from '../hot'
|
|
5
|
+
import { AppHostServicesProvider } from '../appHostServices'
|
|
6
|
+
import { AnyExtensionSlot } from '../extensionSlot'
|
|
7
|
+
|
|
8
|
+
interface PerformanceDebugParams {
|
|
9
|
+
options: AppHost['options']
|
|
10
|
+
trace: Trace[]
|
|
11
|
+
memoizedArr: StatisticsMemoization[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface SetupDebugInfoParams {
|
|
15
|
+
readyAPIs: Set<AnySlotKey>
|
|
16
|
+
host: AppHost & AppHostServicesProvider
|
|
17
|
+
uniqueShellNames: Set<string>
|
|
18
|
+
extensionSlots: Map<AnySlotKey, AnyExtensionSlot>
|
|
19
|
+
addedShells: Map<string, PrivateShell>
|
|
20
|
+
shellInstallers: WeakMap<PrivateShell, string[]>
|
|
21
|
+
lazyShells: Map<string, LazyEntryPointFactory>
|
|
22
|
+
|
|
23
|
+
performance: PerformanceDebugParams
|
|
24
|
+
|
|
25
|
+
getUnreadyEntryPoints(): EntryPoint[]
|
|
26
|
+
getOwnSlotKey(key: SlotKey<any>): SlotKey<any>
|
|
27
|
+
getAPI: AppHost['getAPI']
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function mapApiToEntryPoint(allPackages: EntryPoint[]) {
|
|
31
|
+
const apiToEntryPoint = new Map<string, EntryPoint | undefined>()
|
|
32
|
+
_.forEach(allPackages, (entryPoint: EntryPoint) => {
|
|
33
|
+
_.forEach(entryPoint.declareAPIs ? entryPoint.declareAPIs() : [], dependency => {
|
|
34
|
+
apiToEntryPoint.set(dependency.name, entryPoint)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
return apiToEntryPoint
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* a function that returns all the entry points in the system with their declared APIs and dependencies
|
|
42
|
+
*/
|
|
43
|
+
const getAllEntryPoints = () => {
|
|
44
|
+
return [
|
|
45
|
+
...globalThis.repluggableAppDebug.utils.unReadyEntryPoints(),
|
|
46
|
+
...[...globalThis.repluggableAppDebug.addedShells].map(([_, shell]) => shell.entryPoint)
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* this function is used to get the root unready API in case there are too many to understand.
|
|
52
|
+
* for example if you have 200 unready entry points, running this function will give you the first unready API that
|
|
53
|
+
* will unblock the rest of the entry point (note that there might be more than one)
|
|
54
|
+
*
|
|
55
|
+
* this function basically takes the first unready entry point, get its dependencies and iterates over them to find an API that is not ready
|
|
56
|
+
* at this point it follows the same process recursively until it reaced the target API.
|
|
57
|
+
*/
|
|
58
|
+
const getRootUnreadyAPI = (host: AppHost) => {
|
|
59
|
+
return () => {
|
|
60
|
+
// get all unready entry points
|
|
61
|
+
const allEntryPoints = getAllEntryPoints()
|
|
62
|
+
const unReadyAPIsArray = []
|
|
63
|
+
// get the depdenencies of the first unready entry point
|
|
64
|
+
let dependenciesOfUnreadyEntryPoint = allEntryPoints?.[0]?.getDependencyAPIs?.()
|
|
65
|
+
|
|
66
|
+
while (dependenciesOfUnreadyEntryPoint?.length) {
|
|
67
|
+
const currentAPI = dependenciesOfUnreadyEntryPoint.pop()
|
|
68
|
+
|
|
69
|
+
if (!currentAPI) {
|
|
70
|
+
continue
|
|
71
|
+
}
|
|
72
|
+
// try to get the API from this host, we are looking for an API that is not ready
|
|
73
|
+
try {
|
|
74
|
+
const api = host.getAPI(currentAPI as SlotKey<any>)
|
|
75
|
+
if (api) {
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
unReadyAPIsArray.push(currentAPI)
|
|
80
|
+
// we found an API that is unready, lets find which entry point declares it
|
|
81
|
+
const declarer = allEntryPoints.find(entryPointData =>
|
|
82
|
+
entryPointData.declareAPIs?.().some(api => currentAPI?.name === api.name)
|
|
83
|
+
)
|
|
84
|
+
dependenciesOfUnreadyEntryPoint = declarer?.getDependencyAPIs?.()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return unReadyAPIsArray.reverse()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const getAPIOrEntryPointsDependencies = (
|
|
92
|
+
apisOrEntryPointsNames: string[],
|
|
93
|
+
entryPoints: EntryPoint[]
|
|
94
|
+
): { entryPoints: EntryPoint[]; apis: AnySlotKey[] } => {
|
|
95
|
+
const apiToEntryPoint = mapApiToEntryPoint(entryPoints)
|
|
96
|
+
|
|
97
|
+
const loadedEntryPoints = new Set<string>()
|
|
98
|
+
const packagesList: EntryPoint[] = []
|
|
99
|
+
const allDependencies = new Set<AnySlotKey>()
|
|
100
|
+
const apisOrEntryPointsSet = new Set(apisOrEntryPointsNames)
|
|
101
|
+
const entryPointsQueue: EntryPoint[] = entryPoints.filter(x => apisOrEntryPointsSet.has(x.name))
|
|
102
|
+
|
|
103
|
+
apisOrEntryPointsNames.forEach(x => {
|
|
104
|
+
const ep = apiToEntryPoint.get(x)
|
|
105
|
+
ep && entryPointsQueue.push(ep)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
while (entryPointsQueue.length) {
|
|
109
|
+
const currEntryPoint = entryPointsQueue.shift()
|
|
110
|
+
if (!currEntryPoint || loadedEntryPoints.has(currEntryPoint.name)) {
|
|
111
|
+
continue
|
|
112
|
+
}
|
|
113
|
+
loadedEntryPoints.add(currEntryPoint.name)
|
|
114
|
+
packagesList.push(currEntryPoint)
|
|
115
|
+
const dependencies = currEntryPoint.getDependencyAPIs ? currEntryPoint.getDependencyAPIs() : []
|
|
116
|
+
dependencies.forEach(x => allDependencies.add(x))
|
|
117
|
+
const dependencyEntryPoints = dependencies.map((API: AnySlotKey) => apiToEntryPoint.get(API.name))
|
|
118
|
+
entryPointsQueue.push(..._.compact(dependencyEntryPoints))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
entryPoints: packagesList,
|
|
123
|
+
apis: [...allDependencies]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function setupDebugInfo({
|
|
128
|
+
host,
|
|
129
|
+
uniqueShellNames,
|
|
130
|
+
readyAPIs,
|
|
131
|
+
getAPI,
|
|
132
|
+
getOwnSlotKey,
|
|
133
|
+
getUnreadyEntryPoints,
|
|
134
|
+
extensionSlots,
|
|
135
|
+
addedShells,
|
|
136
|
+
lazyShells,
|
|
137
|
+
shellInstallers,
|
|
138
|
+
performance: { options, trace, memoizedArr }
|
|
139
|
+
}: SetupDebugInfoParams) {
|
|
140
|
+
const utils = {
|
|
141
|
+
apis: () => {
|
|
142
|
+
return Array.from(readyAPIs).map((apiKey: AnySlotKey) => {
|
|
143
|
+
return {
|
|
144
|
+
key: apiKey,
|
|
145
|
+
impl: () => getAPI(apiKey)
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
},
|
|
149
|
+
getRootUnreadyAPI: getRootUnreadyAPI(host),
|
|
150
|
+
unReadyEntryPoints: (): EntryPoint[] => getUnreadyEntryPoints(),
|
|
151
|
+
whyEntryPointUnready: (name: string) => {
|
|
152
|
+
const unreadyEntryPoint = _.find(
|
|
153
|
+
utils.unReadyEntryPoints(),
|
|
154
|
+
(entryPoint: EntryPoint) => entryPoint.name.toLowerCase() === name.toLowerCase()
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const dependencies = _.invoke(unreadyEntryPoint, 'getDependencyAPIs')
|
|
158
|
+
|
|
159
|
+
const unreadyDependencies = _.filter(dependencies, key => !readyAPIs.has(getOwnSlotKey(key)))
|
|
160
|
+
if (!_.isEmpty(unreadyDependencies)) {
|
|
161
|
+
const unreadyDependenciesNames = _(unreadyDependencies).map('name').join(',')
|
|
162
|
+
console.log(`There are unready dependencies for ${name}: ${unreadyDependenciesNames}`)
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
findAPI: (name: string) => {
|
|
166
|
+
return _.filter(utils.apis(), (api: any) => api.key.name.toLowerCase().indexOf(name.toLowerCase()) !== -1)
|
|
167
|
+
},
|
|
168
|
+
getAPIOrEntryPointsDependencies: (
|
|
169
|
+
apisOrEntryPointsNames: string[],
|
|
170
|
+
entryPoints = [...addedShells.values()].map(x => x.entryPoint)
|
|
171
|
+
) => getAPIOrEntryPointsDependencies(apisOrEntryPointsNames, entryPoints),
|
|
172
|
+
performance: getPerformanceDebug(options, trace, memoizedArr)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (typeof globalThis === 'undefined') {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
globalThis.repluggableAppDebug = {
|
|
180
|
+
host,
|
|
181
|
+
uniqueShellNames,
|
|
182
|
+
extensionSlots,
|
|
183
|
+
addedShells,
|
|
184
|
+
lazyShells,
|
|
185
|
+
readyAPIs,
|
|
186
|
+
shellInstallers,
|
|
187
|
+
utils,
|
|
188
|
+
hmr: {
|
|
189
|
+
hot
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Based on:
|
|
3
|
+
https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
|
|
4
|
+
https://gist.github.com/chadhutchins/1440602
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export class Graph {
|
|
8
|
+
private readonly map = new Map<string, Vertex>()
|
|
9
|
+
private addOrGetVertex(value: string) {
|
|
10
|
+
let vertex = this.map.get(value)
|
|
11
|
+
if (!vertex) {
|
|
12
|
+
vertex = new Vertex(value)
|
|
13
|
+
this.map.set(value, vertex)
|
|
14
|
+
}
|
|
15
|
+
return vertex
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getVertices() {
|
|
19
|
+
return this.map.values()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
addConnection(source: string, target: string) {
|
|
23
|
+
this.addOrGetVertex(source).connections.push(this.addOrGetVertex(target))
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class Vertex {
|
|
28
|
+
connections: Vertex[] = []
|
|
29
|
+
index = -1
|
|
30
|
+
lowLink = -1
|
|
31
|
+
constructor(public name: string) {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getCycle(dependentGraph: { [key: string]: string[] }) {
|
|
35
|
+
let queue = Object.keys(dependentGraph).map(node => [node])
|
|
36
|
+
while (queue.length) {
|
|
37
|
+
const batch = []
|
|
38
|
+
for (const path of queue) {
|
|
39
|
+
const parents = dependentGraph[path[0]] || []
|
|
40
|
+
for (const node of parents) {
|
|
41
|
+
if (node === path[path.length - 1]) {
|
|
42
|
+
return [node, ...path]
|
|
43
|
+
}
|
|
44
|
+
batch.push([node, ...path])
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
queue = batch
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class Tarjan {
|
|
52
|
+
private index = 0
|
|
53
|
+
private readonly stack: Vertex[] = []
|
|
54
|
+
private readonly scc: Vertex[][] = []
|
|
55
|
+
constructor(private readonly graph: Graph) {}
|
|
56
|
+
|
|
57
|
+
run() {
|
|
58
|
+
for (const v of this.graph.getVertices()) {
|
|
59
|
+
if (v.index < 0) {
|
|
60
|
+
this.strongConnect(v)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return this.scc
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private strongConnect(vertex: Vertex) {
|
|
67
|
+
vertex.index = this.index
|
|
68
|
+
vertex.lowLink = this.index
|
|
69
|
+
this.index = this.index + 1
|
|
70
|
+
this.stack.push(vertex)
|
|
71
|
+
|
|
72
|
+
for (const w of vertex.connections) {
|
|
73
|
+
const v = vertex
|
|
74
|
+
if (w.index < 0) {
|
|
75
|
+
this.strongConnect(w)
|
|
76
|
+
v.lowLink = Math.min(v.lowLink, w.lowLink)
|
|
77
|
+
} else if (this.stack.some(x => x.name === w.name)) {
|
|
78
|
+
v.lowLink = Math.min(v.lowLink, w.index)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (vertex.lowLink === vertex.index) {
|
|
83
|
+
const vertices = []
|
|
84
|
+
let w = null
|
|
85
|
+
if (this.stack.length > 0) {
|
|
86
|
+
do {
|
|
87
|
+
w = this.stack.pop()
|
|
88
|
+
w && vertices.push(w)
|
|
89
|
+
} while (vertex.name !== w?.name)
|
|
90
|
+
}
|
|
91
|
+
if (vertices.length > 0) {
|
|
92
|
+
this.scc.push(vertices)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { Action, AnyAction, Dispatch, Reducer, ReducersMapObject, Store, Unsubscribe, combineReducers, createStore } from 'redux'
|
|
3
|
+
import { devToolsEnhancer } from 'redux-devtools-extension'
|
|
4
|
+
import { AppHost, ExtensionSlot, ObservableState, ReducersMapObjectContributor, Shell, SlotKey, StateObserver } from './API'
|
|
5
|
+
import { AppHostServicesProvider } from './appHostServices'
|
|
6
|
+
import { contributeInstalledShellsState } from './installedShellsState'
|
|
7
|
+
import { interceptAnyObject } from './interceptAnyObject'
|
|
8
|
+
import { invokeSlotCallbacks } from './invokeSlotCallbacks'
|
|
9
|
+
|
|
10
|
+
type ReducerNotificationScope = 'broadcasting' | 'observable'
|
|
11
|
+
interface ShellsReducersMap {
|
|
12
|
+
[shellName: string]: ReducersMapObject
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface AnyShellAction extends AnyAction {
|
|
16
|
+
__shellName?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
function createTimeOutPublisher ( notify: () => void) {
|
|
21
|
+
let id : undefined | NodeJS.Timeout = undefined
|
|
22
|
+
return () => {
|
|
23
|
+
if (id === undefined) {
|
|
24
|
+
id = setTimeout(() => {
|
|
25
|
+
id = undefined
|
|
26
|
+
notify()
|
|
27
|
+
},0)
|
|
28
|
+
}
|
|
29
|
+
return () => {
|
|
30
|
+
if(id === undefined) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
clearTimeout(id)
|
|
34
|
+
id = undefined
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function createAnimationFramePublisher ( notify: () => void) {
|
|
40
|
+
let id : undefined | number = undefined
|
|
41
|
+
return () => {
|
|
42
|
+
if (id === undefined) {
|
|
43
|
+
id = requestAnimationFrame(() => {
|
|
44
|
+
id = undefined
|
|
45
|
+
notify()
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
return () => {
|
|
49
|
+
if(id === undefined) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
cancelAnimationFrame(id)
|
|
53
|
+
id = undefined
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
type Subscriber = () => void
|
|
62
|
+
|
|
63
|
+
export interface StateContribution<TState = {}, TAction extends AnyAction = AnyAction> {
|
|
64
|
+
reducerFactory: ReducersMapObjectContributor<TState, TAction>
|
|
65
|
+
notificationScope: ReducerNotificationScope
|
|
66
|
+
observable?: AnyPrivateObservableState
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ThrottledStore<T = any> extends Store<T> {
|
|
70
|
+
hasPendingSubscribers(): boolean
|
|
71
|
+
flush(config?: { excecutionType: 'scheduled' | 'immediate' | 'default' }): void
|
|
72
|
+
deferSubscriberNotifications<K>(action: () => K | Promise<K>, shouldDispatchClearCache?: boolean): Promise<K>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface PrivateThrottledStore<T = any> extends ThrottledStore<T> {
|
|
76
|
+
broadcastNotify(): void
|
|
77
|
+
observableNotify(observer: AnyPrivateObservableState): void
|
|
78
|
+
resetPendingNotifications(): void
|
|
79
|
+
syncSubscribe(listener: () => void): Unsubscribe
|
|
80
|
+
dispatchWithShell(shell: Shell): Dispatch
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface PrivateObservableState<TState, TSelector> extends ObservableState<TSelector> {
|
|
84
|
+
notify(): void
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type AnyPrivateObservableState = PrivateObservableState<any, any>
|
|
88
|
+
|
|
89
|
+
const buildStoreReducer = (
|
|
90
|
+
contributedState: ExtensionSlot<StateContribution>,
|
|
91
|
+
broadcastNotify: PrivateThrottledStore['broadcastNotify'],
|
|
92
|
+
observableNotify: PrivateThrottledStore['observableNotify'],
|
|
93
|
+
shouldScopeReducers?: boolean
|
|
94
|
+
): Reducer => {
|
|
95
|
+
function withNotifyAction(
|
|
96
|
+
originalReducersMap: ReducersMapObject,
|
|
97
|
+
notifyAction: () => void,
|
|
98
|
+
storeShellName?: string
|
|
99
|
+
): ReducersMapObject {
|
|
100
|
+
const decorateReducer = (originalReducer: Reducer): Reducer => {
|
|
101
|
+
return (state0, action: AnyShellAction) => {
|
|
102
|
+
if (shouldScopeReducers && state0 && storeShellName && action.__shellName && storeShellName !== action.__shellName) {
|
|
103
|
+
return state0
|
|
104
|
+
}
|
|
105
|
+
const state1 = originalReducer(state0, action)
|
|
106
|
+
if (state1 !== state0) {
|
|
107
|
+
notifyAction()
|
|
108
|
+
}
|
|
109
|
+
return state1
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const wrapper = interceptAnyObject(originalReducersMap, (name, func) => {
|
|
113
|
+
const originalReducer = func as Reducer
|
|
114
|
+
return decorateReducer(originalReducer)
|
|
115
|
+
})
|
|
116
|
+
return wrapper
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function withBroadcastOrObservableNotify(
|
|
120
|
+
{ notificationScope, reducerFactory, observable }: StateContribution,
|
|
121
|
+
storeShellName: string
|
|
122
|
+
): ReducersMapObject {
|
|
123
|
+
const originalReducersMap = reducerFactory()
|
|
124
|
+
if (notificationScope === 'broadcasting') {
|
|
125
|
+
return withNotifyAction(originalReducersMap, broadcastNotify, storeShellName)
|
|
126
|
+
}
|
|
127
|
+
if (!observable) {
|
|
128
|
+
// should never happen; would be an internal bug
|
|
129
|
+
throw new Error(
|
|
130
|
+
`getPerShellReducersMapObject: notificationScope=observable but 'observable' is falsy, in shell '${storeShellName}'`
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
return withNotifyAction(originalReducersMap, () => observableNotify(observable))
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function getPerShellReducersMapObject(): ShellsReducersMap {
|
|
137
|
+
return contributedState.getItems().reduce((map: ShellsReducersMap, item) => {
|
|
138
|
+
const shellName = item.shell.name
|
|
139
|
+
map[shellName] = {
|
|
140
|
+
...map[shellName],
|
|
141
|
+
...withBroadcastOrObservableNotify(item.contribution, shellName)
|
|
142
|
+
}
|
|
143
|
+
return map
|
|
144
|
+
}, {})
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function getCombinedShellReducers(): ReducersMapObject {
|
|
148
|
+
const shellsReducerMaps = getPerShellReducersMapObject()
|
|
149
|
+
const combinedReducersMap = _.mapValues(shellsReducerMaps, singleMap => combineReducers(singleMap))
|
|
150
|
+
return combinedReducersMap
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function buildReducersMapObject(): ReducersMapObject {
|
|
154
|
+
// TODO: get rid of builtInReducersMaps
|
|
155
|
+
const builtInReducersMaps: ReducersMapObject = {
|
|
156
|
+
...contributeInstalledShellsState()
|
|
157
|
+
}
|
|
158
|
+
return { ...builtInReducersMaps, ...getCombinedShellReducers() }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const reducersMap = buildReducersMapObject()
|
|
162
|
+
const combinedReducer = combineReducers(reducersMap)
|
|
163
|
+
return combinedReducer
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export const updateThrottledStore = (
|
|
167
|
+
host: AppHost & AppHostServicesProvider,
|
|
168
|
+
store: PrivateThrottledStore,
|
|
169
|
+
contributedState: ExtensionSlot<StateContribution>
|
|
170
|
+
): void => {
|
|
171
|
+
const newReducer = buildStoreReducer(contributedState, store.broadcastNotify, store.observableNotify, host.options.shouldScopeReducers)
|
|
172
|
+
store.replaceReducer(newReducer)
|
|
173
|
+
store.resetPendingNotifications()
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export const createThrottledStore = (
|
|
177
|
+
host: AppHost & AppHostServicesProvider,
|
|
178
|
+
contributedState: ExtensionSlot<StateContribution>,
|
|
179
|
+
updateIsSubscriptionNotifyInProgress: (isSubscriptionNotifyInProgress: boolean) => void,
|
|
180
|
+
updateIsObserversNotifyInProgress: (isObserversNotifyInProgress: boolean) => void,
|
|
181
|
+
updateShouldFlushMemoizationSync: (shouldFlushMemoizationSync: boolean) => void
|
|
182
|
+
): PrivateThrottledStore => {
|
|
183
|
+
let pendingBroadcastNotification = false
|
|
184
|
+
let pendingObservableNotifications: Set<AnyPrivateObservableState> | undefined
|
|
185
|
+
let isDeferrringNotifications = false
|
|
186
|
+
let pendingFlush = false
|
|
187
|
+
|
|
188
|
+
const onBroadcastNotify = () => {
|
|
189
|
+
pendingBroadcastNotification = true
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const onObservableNotify = (observable: AnyPrivateObservableState) => {
|
|
193
|
+
if (!pendingObservableNotifications) {
|
|
194
|
+
pendingObservableNotifications = new Set<AnyPrivateObservableState>()
|
|
195
|
+
}
|
|
196
|
+
pendingObservableNotifications.add(observable)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const resetAllPendingNotifications = () => {
|
|
200
|
+
pendingBroadcastNotification = false
|
|
201
|
+
pendingObservableNotifications = undefined
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const reducer = buildStoreReducer(contributedState, onBroadcastNotify, onObservableNotify, host.options.shouldScopeReducers)
|
|
205
|
+
const store: Store = host.options.enableReduxDevtoolsExtension
|
|
206
|
+
? createStore(reducer, devToolsEnhancer({ name: 'repluggable' }))
|
|
207
|
+
: createStore(reducer)
|
|
208
|
+
const invoke = (f: Subscriber) => f()
|
|
209
|
+
|
|
210
|
+
let broadcastSubscribers: Subscriber[] = []
|
|
211
|
+
|
|
212
|
+
const subscribe = (subscriber: Subscriber) => {
|
|
213
|
+
broadcastSubscribers = _.concat(broadcastSubscribers, subscriber)
|
|
214
|
+
return () => {
|
|
215
|
+
broadcastSubscribers = _.without(broadcastSubscribers, subscriber)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const notifySubscribers = () => {
|
|
220
|
+
if (pendingBroadcastNotification || !pendingObservableNotifications) {
|
|
221
|
+
host.getAppHostServicesShell().log.monitor('ThrottledStore.notifySubscribers', {}, () =>
|
|
222
|
+
_.forEach(broadcastSubscribers, invoke)
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const notifyObservers = () => {
|
|
228
|
+
if (pendingObservableNotifications) {
|
|
229
|
+
pendingObservableNotifications.forEach(observable => {
|
|
230
|
+
observable.notify()
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const notifyAll = () => {
|
|
236
|
+
try {
|
|
237
|
+
updateIsObserversNotifyInProgress(true)
|
|
238
|
+
notifyObservers()
|
|
239
|
+
updateIsSubscriptionNotifyInProgress(true)
|
|
240
|
+
notifySubscribers()
|
|
241
|
+
} finally {
|
|
242
|
+
resetAllPendingNotifications()
|
|
243
|
+
updateIsSubscriptionNotifyInProgress(false)
|
|
244
|
+
updateIsObserversNotifyInProgress(false)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const scheduledNotifyAll = () => {
|
|
249
|
+
if (isDeferrringNotifications) {
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
notifyAll()
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
const notifyAllOnPublish = typeof window === 'undefined' ? createTimeOutPublisher(scheduledNotifyAll) : createAnimationFramePublisher(scheduledNotifyAll)
|
|
259
|
+
|
|
260
|
+
let cancelRender = _.noop
|
|
261
|
+
|
|
262
|
+
store.subscribe(() => {
|
|
263
|
+
cancelRender = notifyAllOnPublish()
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
const flush = (config = { excecutionType: 'default' }) => {
|
|
267
|
+
if (isDeferrringNotifications && config.excecutionType !== 'immediate') {
|
|
268
|
+
pendingFlush = true
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
if (config.excecutionType !== 'scheduled') {
|
|
272
|
+
cancelRender()
|
|
273
|
+
}
|
|
274
|
+
notifyAll()
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const dispatch: Dispatch<AnyAction> = action => {
|
|
278
|
+
return store.dispatch(action)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const toShellAction = <T extends Action>(shell: Shell, action: T): T => ({
|
|
282
|
+
...action,
|
|
283
|
+
__shellName: shell.name
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
const executePendingActions = () => {
|
|
287
|
+
if (pendingFlush) {
|
|
288
|
+
pendingFlush = false
|
|
289
|
+
flush()
|
|
290
|
+
} else if (pendingBroadcastNotification || pendingObservableNotifications) {
|
|
291
|
+
notifyAll()
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const result: PrivateThrottledStore = {
|
|
296
|
+
...store,
|
|
297
|
+
subscribe,
|
|
298
|
+
syncSubscribe: store.subscribe,
|
|
299
|
+
dispatch,
|
|
300
|
+
dispatchWithShell: shell => action => dispatch(toShellAction(shell, action)),
|
|
301
|
+
flush,
|
|
302
|
+
broadcastNotify: onBroadcastNotify,
|
|
303
|
+
observableNotify: onObservableNotify,
|
|
304
|
+
resetPendingNotifications: resetAllPendingNotifications,
|
|
305
|
+
hasPendingSubscribers: () => pendingBroadcastNotification,
|
|
306
|
+
deferSubscriberNotifications: async (action, shouldDispatchClearCache) => {
|
|
307
|
+
if (isDeferrringNotifications) {
|
|
308
|
+
return action()
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
executePendingActions()
|
|
312
|
+
isDeferrringNotifications = true
|
|
313
|
+
shouldDispatchClearCache && updateShouldFlushMemoizationSync(isDeferrringNotifications)
|
|
314
|
+
const functionResult = await action()
|
|
315
|
+
return functionResult
|
|
316
|
+
} finally {
|
|
317
|
+
isDeferrringNotifications = false
|
|
318
|
+
shouldDispatchClearCache && updateShouldFlushMemoizationSync(isDeferrringNotifications)
|
|
319
|
+
executePendingActions()
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
resetAllPendingNotifications()
|
|
325
|
+
return result
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export const createObservable = <TState, TSelector>(
|
|
329
|
+
shell: Shell,
|
|
330
|
+
uniqueName: string,
|
|
331
|
+
selectorFactory: (state: TState) => TSelector
|
|
332
|
+
): PrivateObservableState<TState, TSelector> => {
|
|
333
|
+
const subscribersSlotKey: SlotKey<StateObserver<TSelector>> = {
|
|
334
|
+
name: uniqueName
|
|
335
|
+
}
|
|
336
|
+
const observersSlot = shell.declareSlot(subscribersSlotKey)
|
|
337
|
+
|
|
338
|
+
const createSelector = (): TSelector => {
|
|
339
|
+
return selectorFactory(shell.getStore<TState>().getState())
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
subscribe(fromShell, callback) {
|
|
344
|
+
observersSlot.contribute(fromShell, callback)
|
|
345
|
+
return () => {
|
|
346
|
+
observersSlot.discardBy(item => item.contribution === callback)
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
notify() {
|
|
350
|
+
const newSelector = createSelector()
|
|
351
|
+
invokeSlotCallbacks(observersSlot, newSelector)
|
|
352
|
+
},
|
|
353
|
+
current: createSelector
|
|
354
|
+
}
|
|
355
|
+
}
|