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.
Files changed (303) hide show
  1. package/__tests__/spec-setup.js +3 -0
  2. package/dist/es/{API.d.ts → src/API.d.ts} +46 -8
  3. package/dist/es/src/API.d.ts.map +1 -0
  4. package/dist/es/src/API.js +3 -0
  5. package/dist/es/src/API.js.map +1 -0
  6. package/dist/es/src/IterableWeakMap.d.ts +20 -0
  7. package/dist/es/src/IterableWeakMap.d.ts.map +1 -0
  8. package/dist/es/src/IterableWeakMap.js +92 -0
  9. package/dist/es/src/IterableWeakMap.js.map +1 -0
  10. package/dist/es/src/__internal.d.ts.map +1 -0
  11. package/dist/es/src/__internal.js +5 -0
  12. package/dist/es/src/__internal.js.map +1 -0
  13. package/dist/es/src/appHost.d.ts +7 -0
  14. package/dist/es/src/appHost.d.ts.map +1 -0
  15. package/dist/es/src/appHost.js +898 -0
  16. package/dist/es/src/appHost.js.map +1 -0
  17. package/dist/es/src/appHostServices.d.ts +12 -0
  18. package/dist/es/src/appHostServices.d.ts.map +1 -0
  19. package/dist/es/src/appHostServices.js +25 -0
  20. package/dist/es/src/appHostServices.js.map +1 -0
  21. package/dist/es/src/appHostUtils.d.ts +4 -0
  22. package/dist/es/src/appHostUtils.d.ts.map +1 -0
  23. package/dist/es/src/appHostUtils.js +8 -0
  24. package/dist/es/src/appHostUtils.js.map +1 -0
  25. package/dist/es/src/extensionSlot.d.ts +8 -0
  26. package/dist/es/src/extensionSlot.d.ts.map +1 -0
  27. package/dist/es/src/extensionSlot.js +59 -0
  28. package/dist/es/src/extensionSlot.js.map +1 -0
  29. package/dist/es/src/hot.d.ts +14 -0
  30. package/dist/es/src/hot.d.ts.map +1 -0
  31. package/dist/es/src/hot.js +52 -0
  32. package/dist/es/src/hot.js.map +1 -0
  33. package/dist/es/src/index.d.ts +11 -0
  34. package/dist/es/src/index.d.ts.map +1 -0
  35. package/dist/es/src/index.js +10 -0
  36. package/dist/es/src/index.js.map +1 -0
  37. package/dist/es/src/installedShellsState.d.ts +19 -0
  38. package/dist/es/src/installedShellsState.d.ts.map +1 -0
  39. package/dist/es/src/installedShellsState.js +30 -0
  40. package/dist/es/src/installedShellsState.js.map +1 -0
  41. package/dist/es/src/interceptAnyObject.d.ts +7 -0
  42. package/dist/es/src/interceptAnyObject.d.ts.map +1 -0
  43. package/dist/es/src/interceptAnyObject.js +21 -0
  44. package/dist/es/src/interceptAnyObject.js.map +1 -0
  45. package/dist/es/src/invokeSlotCallbacks.d.ts +3 -0
  46. package/dist/es/src/invokeSlotCallbacks.d.ts.map +1 -0
  47. package/dist/es/src/invokeSlotCallbacks.js +20 -0
  48. package/dist/es/src/invokeSlotCallbacks.js.map +1 -0
  49. package/dist/es/src/loggers.d.ts +4 -0
  50. package/dist/es/src/loggers.d.ts.map +1 -0
  51. package/dist/es/src/loggers.js +100 -0
  52. package/dist/es/src/loggers.js.map +1 -0
  53. package/dist/es/src/monitorAPI.d.ts +3 -0
  54. package/dist/es/src/monitorAPI.d.ts.map +1 -0
  55. package/dist/es/src/monitorAPI.js +53 -0
  56. package/dist/es/src/monitorAPI.js.map +1 -0
  57. package/dist/es/src/repluggableAppDebug/index.d.ts +2 -0
  58. package/dist/es/src/repluggableAppDebug/index.d.ts.map +1 -0
  59. package/dist/es/src/repluggableAppDebug/index.js +2 -0
  60. package/dist/es/src/repluggableAppDebug/index.js.map +1 -0
  61. package/dist/es/src/repluggableAppDebug/performanceDebugInfo.d.ts +15 -0
  62. package/dist/es/src/repluggableAppDebug/performanceDebugInfo.d.ts.map +1 -0
  63. package/dist/es/src/repluggableAppDebug/performanceDebugInfo.js +94 -0
  64. package/dist/es/src/repluggableAppDebug/performanceDebugInfo.js.map +1 -0
  65. package/dist/es/src/repluggableAppDebug/repluggableAppDebug.d.ts +24 -0
  66. package/dist/es/src/repluggableAppDebug/repluggableAppDebug.d.ts.map +1 -0
  67. package/dist/es/src/repluggableAppDebug/repluggableAppDebug.js +132 -0
  68. package/dist/es/src/repluggableAppDebug/repluggableAppDebug.js.map +1 -0
  69. package/dist/es/src/tarjanGraph.d.ts +27 -0
  70. package/dist/es/src/tarjanGraph.d.ts.map +1 -0
  71. package/dist/es/src/tarjanGraph.js +94 -0
  72. package/dist/es/src/tarjanGraph.js.map +1 -0
  73. package/dist/es/src/throttledStore.d.ts +32 -0
  74. package/dist/es/src/throttledStore.d.ts.map +1 -0
  75. package/dist/es/src/throttledStore.js +240 -0
  76. package/dist/es/src/throttledStore.js.map +1 -0
  77. package/dist/es/test/IterableWeakMap.spec.d.ts +2 -0
  78. package/dist/es/test/IterableWeakMap.spec.d.ts.map +1 -0
  79. package/dist/es/test/IterableWeakMap.spec.js +218 -0
  80. package/dist/es/test/IterableWeakMap.spec.js.map +1 -0
  81. package/dist/es/test/appHost.mock.d.ts +4 -0
  82. package/dist/es/test/appHost.mock.d.ts.map +1 -0
  83. package/dist/es/test/appHost.mock.js +54 -0
  84. package/dist/es/test/appHost.mock.js.map +1 -0
  85. package/dist/es/test/appHost.spec.d.ts +2 -0
  86. package/dist/es/test/appHost.spec.d.ts.map +1 -0
  87. package/dist/es/test/appHost.spec.js +1451 -0
  88. package/dist/es/test/appHost.spec.js.map +1 -0
  89. package/dist/es/test/installedShellsState.spec.d.ts +2 -0
  90. package/dist/es/test/installedShellsState.spec.d.ts.map +1 -0
  91. package/dist/es/test/installedShellsState.spec.js +28 -0
  92. package/dist/es/test/installedShellsState.spec.js.map +1 -0
  93. package/dist/es/test/interceptAnyObject.spec.d.ts +2 -0
  94. package/dist/es/test/interceptAnyObject.spec.d.ts.map +1 -0
  95. package/dist/es/test/interceptAnyObject.spec.js +166 -0
  96. package/dist/es/test/interceptAnyObject.spec.js.map +1 -0
  97. package/dist/es/test/loggers.spec.d.ts +2 -0
  98. package/dist/es/test/loggers.spec.d.ts.map +1 -0
  99. package/dist/es/test/loggers.spec.js +218 -0
  100. package/dist/es/test/loggers.spec.js.map +1 -0
  101. package/dist/es/test/repluggableAppDebug.spec.d.ts +2 -0
  102. package/dist/es/test/repluggableAppDebug.spec.d.ts.map +1 -0
  103. package/dist/es/test/repluggableAppDebug.spec.js +107 -0
  104. package/dist/es/test/repluggableAppDebug.spec.js.map +1 -0
  105. package/dist/es/test/testKit.spec.d.ts +2 -0
  106. package/dist/es/test/testKit.spec.d.ts.map +1 -0
  107. package/dist/es/test/testKit.spec.js +129 -0
  108. package/dist/es/test/testKit.spec.js.map +1 -0
  109. package/dist/es/testKit/emptyLoggerOptions.d.ts +3 -0
  110. package/dist/es/testKit/emptyLoggerOptions.d.ts.map +1 -0
  111. package/dist/es/testKit/emptyLoggerOptions.js +15 -0
  112. package/dist/es/testKit/emptyLoggerOptions.js.map +1 -0
  113. package/dist/es/testKit/index.d.ts +27 -0
  114. package/dist/es/testKit/index.d.ts.map +1 -0
  115. package/dist/es/testKit/index.js +132 -0
  116. package/dist/es/testKit/index.js.map +1 -0
  117. package/dist/es/testKit/mockPackage.d.ts +23 -0
  118. package/dist/es/testKit/mockPackage.d.ts.map +1 -0
  119. package/dist/es/testKit/mockPackage.js +95 -0
  120. package/dist/es/testKit/mockPackage.js.map +1 -0
  121. package/dist/es/testKit/withConsoleErrors.d.ts +2 -0
  122. package/dist/es/testKit/withConsoleErrors.d.ts.map +1 -0
  123. package/dist/es/testKit/withConsoleErrors.js +12 -0
  124. package/dist/es/testKit/withConsoleErrors.js.map +1 -0
  125. package/dist/es/testKit/withThrowOnError.d.ts +3 -0
  126. package/dist/es/testKit/withThrowOnError.d.ts.map +1 -0
  127. package/dist/es/testKit/withThrowOnError.js +27 -0
  128. package/dist/es/testKit/withThrowOnError.js.map +1 -0
  129. package/dist/src/API.d.ts +46 -8
  130. package/dist/src/API.d.ts.map +1 -1
  131. package/dist/src/API.js +4 -0
  132. package/dist/src/API.js.map +1 -1
  133. package/dist/src/IterableWeakMap.d.ts +20 -0
  134. package/dist/src/IterableWeakMap.d.ts.map +1 -0
  135. package/dist/src/IterableWeakMap.js +96 -0
  136. package/dist/src/IterableWeakMap.js.map +1 -0
  137. package/dist/src/__internal.d.ts.map +1 -1
  138. package/dist/src/__internal.js +1 -1
  139. package/dist/src/__internal.js.map +1 -1
  140. package/dist/src/appHost.d.ts +7 -0
  141. package/dist/src/appHost.d.ts.map +1 -0
  142. package/dist/src/appHost.js +906 -0
  143. package/dist/src/appHost.js.map +1 -0
  144. package/dist/src/appHostServices.d.ts +12 -0
  145. package/dist/src/appHostServices.d.ts.map +1 -0
  146. package/dist/src/appHostServices.js +29 -0
  147. package/dist/src/appHostServices.js.map +1 -0
  148. package/dist/src/appHostUtils.d.ts +4 -0
  149. package/dist/src/appHostUtils.d.ts.map +1 -0
  150. package/dist/src/appHostUtils.js +16 -0
  151. package/dist/src/appHostUtils.js.map +1 -0
  152. package/dist/src/extensionSlot.d.ts +8 -0
  153. package/dist/src/extensionSlot.d.ts.map +1 -0
  154. package/dist/src/extensionSlot.js +67 -0
  155. package/dist/src/extensionSlot.js.map +1 -0
  156. package/dist/src/hot.d.ts +14 -0
  157. package/dist/src/hot.d.ts.map +1 -0
  158. package/dist/src/hot.js +56 -0
  159. package/dist/src/hot.js.map +1 -0
  160. package/dist/src/index.d.ts +10 -2
  161. package/dist/src/index.d.ts.map +1 -1
  162. package/dist/src/index.js +22 -15
  163. package/dist/src/index.js.map +1 -1
  164. package/dist/src/installedShellsState.d.ts +19 -0
  165. package/dist/src/installedShellsState.d.ts.map +1 -0
  166. package/dist/src/installedShellsState.js +38 -0
  167. package/dist/src/installedShellsState.js.map +1 -0
  168. package/dist/src/interceptAnyObject.d.ts +7 -0
  169. package/dist/src/interceptAnyObject.d.ts.map +1 -0
  170. package/dist/src/interceptAnyObject.js +28 -0
  171. package/dist/src/interceptAnyObject.js.map +1 -0
  172. package/dist/src/invokeSlotCallbacks.d.ts +3 -0
  173. package/dist/src/invokeSlotCallbacks.d.ts.map +1 -0
  174. package/dist/src/invokeSlotCallbacks.js +24 -0
  175. package/dist/src/invokeSlotCallbacks.js.map +1 -0
  176. package/dist/src/loggers.d.ts +4 -0
  177. package/dist/src/loggers.d.ts.map +1 -0
  178. package/dist/src/loggers.js +104 -0
  179. package/dist/src/loggers.js.map +1 -0
  180. package/dist/src/monitorAPI.d.ts +3 -0
  181. package/dist/src/monitorAPI.d.ts.map +1 -0
  182. package/dist/src/monitorAPI.js +57 -0
  183. package/dist/src/monitorAPI.js.map +1 -0
  184. package/dist/src/repluggableAppDebug/index.d.ts +2 -0
  185. package/dist/src/repluggableAppDebug/index.d.ts.map +1 -0
  186. package/dist/src/repluggableAppDebug/index.js +6 -0
  187. package/dist/src/repluggableAppDebug/index.js.map +1 -0
  188. package/dist/src/repluggableAppDebug/performanceDebugInfo.d.ts +15 -0
  189. package/dist/src/repluggableAppDebug/performanceDebugInfo.d.ts.map +1 -0
  190. package/dist/src/repluggableAppDebug/performanceDebugInfo.js +101 -0
  191. package/dist/src/repluggableAppDebug/performanceDebugInfo.js.map +1 -0
  192. package/dist/src/repluggableAppDebug/repluggableAppDebug.d.ts +24 -0
  193. package/dist/src/repluggableAppDebug/repluggableAppDebug.d.ts.map +1 -0
  194. package/dist/src/repluggableAppDebug/repluggableAppDebug.js +139 -0
  195. package/dist/src/repluggableAppDebug/repluggableAppDebug.js.map +1 -0
  196. package/dist/src/tarjanGraph.d.ts +27 -0
  197. package/dist/src/tarjanGraph.d.ts.map +1 -0
  198. package/dist/src/tarjanGraph.js +100 -0
  199. package/dist/src/tarjanGraph.js.map +1 -0
  200. package/dist/src/throttledStore.d.ts +32 -0
  201. package/dist/src/throttledStore.d.ts.map +1 -0
  202. package/dist/src/throttledStore.js +249 -0
  203. package/dist/src/throttledStore.js.map +1 -0
  204. package/dist/test/IterableWeakMap.spec.d.ts +2 -0
  205. package/dist/test/IterableWeakMap.spec.d.ts.map +1 -0
  206. package/dist/test/IterableWeakMap.spec.js +220 -0
  207. package/dist/test/IterableWeakMap.spec.js.map +1 -0
  208. package/dist/test/appHost.mock.d.ts +4 -0
  209. package/dist/test/appHost.mock.d.ts.map +1 -0
  210. package/dist/test/appHost.mock.js +59 -0
  211. package/dist/test/appHost.mock.js.map +1 -0
  212. package/dist/test/appHost.spec.d.ts +2 -0
  213. package/dist/test/appHost.spec.d.ts.map +1 -0
  214. package/dist/test/appHost.spec.js +1456 -0
  215. package/dist/test/appHost.spec.js.map +1 -0
  216. package/dist/test/installedShellsState.spec.d.ts +2 -0
  217. package/dist/test/installedShellsState.spec.d.ts.map +1 -0
  218. package/dist/test/installedShellsState.spec.js +30 -0
  219. package/dist/test/installedShellsState.spec.js.map +1 -0
  220. package/dist/test/interceptAnyObject.spec.d.ts +2 -0
  221. package/dist/test/interceptAnyObject.spec.d.ts.map +1 -0
  222. package/dist/test/interceptAnyObject.spec.js +171 -0
  223. package/dist/test/interceptAnyObject.spec.js.map +1 -0
  224. package/dist/test/loggers.spec.d.ts +2 -0
  225. package/dist/test/loggers.spec.d.ts.map +1 -0
  226. package/dist/test/loggers.spec.js +220 -0
  227. package/dist/test/loggers.spec.js.map +1 -0
  228. package/dist/test/repluggableAppDebug.spec.d.ts +2 -0
  229. package/dist/test/repluggableAppDebug.spec.d.ts.map +1 -0
  230. package/dist/test/repluggableAppDebug.spec.js +109 -0
  231. package/dist/test/repluggableAppDebug.spec.js.map +1 -0
  232. package/dist/test/testKit.spec.d.ts +2 -0
  233. package/dist/test/testKit.spec.d.ts.map +1 -0
  234. package/dist/test/testKit.spec.js +134 -0
  235. package/dist/test/testKit.spec.js.map +1 -0
  236. package/dist/testKit/emptyLoggerOptions.d.ts +3 -0
  237. package/dist/testKit/emptyLoggerOptions.d.ts.map +1 -0
  238. package/dist/testKit/emptyLoggerOptions.js +18 -0
  239. package/dist/testKit/emptyLoggerOptions.js.map +1 -0
  240. package/dist/testKit/index.d.ts +27 -0
  241. package/dist/testKit/index.d.ts.map +1 -0
  242. package/dist/testKit/index.js +160 -0
  243. package/dist/testKit/index.js.map +1 -0
  244. package/dist/testKit/mockPackage.d.ts +23 -0
  245. package/dist/testKit/mockPackage.d.ts.map +1 -0
  246. package/dist/testKit/mockPackage.js +101 -0
  247. package/dist/testKit/mockPackage.js.map +1 -0
  248. package/dist/testKit/withConsoleErrors.d.ts +2 -0
  249. package/dist/testKit/withConsoleErrors.d.ts.map +1 -0
  250. package/dist/testKit/withConsoleErrors.js +16 -0
  251. package/dist/testKit/withConsoleErrors.js.map +1 -0
  252. package/dist/testKit/withThrowOnError.d.ts +3 -0
  253. package/dist/testKit/withThrowOnError.d.ts.map +1 -0
  254. package/dist/testKit/withThrowOnError.js +31 -0
  255. package/dist/testKit/withThrowOnError.js.map +1 -0
  256. package/jest.config.js +16 -0
  257. package/package.json +21 -3
  258. package/src/API.ts +47 -9
  259. package/src/IterableWeakMap.ts +123 -0
  260. package/src/__internal.ts +1 -1
  261. package/src/appHost.ts +1222 -0
  262. package/src/appHostServices.ts +42 -0
  263. package/src/appHostUtils.ts +11 -0
  264. package/src/extensionSlot.ts +96 -0
  265. package/src/hot.ts +53 -0
  266. package/src/index.ts +42 -2
  267. package/src/installedShellsState.ts +54 -0
  268. package/src/interceptAnyObject.ts +39 -0
  269. package/src/invokeSlotCallbacks.ts +20 -0
  270. package/src/loggers.ts +112 -0
  271. package/src/monitorAPI.ts +71 -0
  272. package/src/repluggableAppDebug/debug.d.ts +37 -0
  273. package/src/repluggableAppDebug/index.ts +1 -0
  274. package/src/repluggableAppDebug/performanceDebugInfo.ts +96 -0
  275. package/src/repluggableAppDebug/repluggableAppDebug.ts +192 -0
  276. package/src/tarjanGraph.ts +96 -0
  277. package/src/throttledStore.ts +355 -0
  278. package/test/IterableWeakMap.spec.ts +280 -0
  279. package/test/appHost.mock.ts +58 -0
  280. package/test/appHost.spec.ts +1765 -0
  281. package/test/installedShellsState.spec.ts +39 -0
  282. package/test/interceptAnyObject.spec.ts +217 -0
  283. package/test/loggers.spec.ts +288 -0
  284. package/test/repluggableAppDebug.spec.ts +118 -0
  285. package/test/testKit.spec.tsx +153 -0
  286. package/testKit/emptyLoggerOptions.ts +16 -0
  287. package/testKit/index.ts +170 -0
  288. package/testKit/mockPackage.ts +110 -0
  289. package/testKit/package.json +3 -0
  290. package/testKit/withConsoleErrors.ts +12 -0
  291. package/testKit/withThrowOnError.ts +34 -0
  292. package/tsconfig.json +9 -2
  293. package/dist/es/API.d.ts.map +0 -1
  294. package/dist/es/API.js +0 -2
  295. package/dist/es/API.js.map +0 -1
  296. package/dist/es/__internal.d.ts.map +0 -1
  297. package/dist/es/__internal.js +0 -5
  298. package/dist/es/__internal.js.map +0 -1
  299. package/dist/es/index.d.ts +0 -3
  300. package/dist/es/index.d.ts.map +0 -1
  301. package/dist/es/index.js +0 -2
  302. package/dist/es/index.js.map +0 -1
  303. /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
+ }