repluggable-core 0.0.0-pr342.44 → 0.0.0-pr343.46

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 (39) hide show
  1. package/dist/debug/src/API.d.ts +1 -17
  2. package/dist/es/src/API.d.ts +1 -17
  3. package/dist/es/src/API.d.ts.map +1 -1
  4. package/dist/es/src/API.js.map +1 -1
  5. package/dist/es/src/appHost.d.ts.map +1 -1
  6. package/dist/es/src/appHost.js +5 -50
  7. package/dist/es/src/appHost.js.map +1 -1
  8. package/dist/es/src/appHostUtils.d.ts +0 -1
  9. package/dist/es/src/appHostUtils.d.ts.map +1 -1
  10. package/dist/es/src/appHostUtils.js +0 -3
  11. package/dist/es/src/appHostUtils.js.map +1 -1
  12. package/dist/es/test/appHost.spec.js +0 -483
  13. package/dist/es/test/appHost.spec.js.map +1 -1
  14. package/dist/es/testKit/mockPackage.d.ts +0 -1
  15. package/dist/es/testKit/mockPackage.d.ts.map +1 -1
  16. package/dist/es/testKit/mockPackage.js +0 -14
  17. package/dist/es/testKit/mockPackage.js.map +1 -1
  18. package/dist/src/API.d.ts +1 -17
  19. package/dist/src/API.d.ts.map +1 -1
  20. package/dist/src/API.js.map +1 -1
  21. package/dist/src/appHost.d.ts.map +1 -1
  22. package/dist/src/appHost.js +4 -49
  23. package/dist/src/appHost.js.map +1 -1
  24. package/dist/src/appHostUtils.d.ts +0 -1
  25. package/dist/src/appHostUtils.d.ts.map +1 -1
  26. package/dist/src/appHostUtils.js +1 -5
  27. package/dist/src/appHostUtils.js.map +1 -1
  28. package/dist/test/appHost.spec.js +0 -483
  29. package/dist/test/appHost.spec.js.map +1 -1
  30. package/dist/testKit/mockPackage.d.ts +0 -1
  31. package/dist/testKit/mockPackage.d.ts.map +1 -1
  32. package/dist/testKit/mockPackage.js +1 -15
  33. package/dist/testKit/mockPackage.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/API.ts +2 -18
  36. package/src/appHost.ts +6 -62
  37. package/src/appHostUtils.ts +0 -3
  38. package/test/appHost.spec.ts +0 -506
  39. package/testKit/mockPackage.ts +0 -15
@@ -31,7 +31,6 @@ import {
31
31
 
32
32
  import { AppHostAPI, AppHostServicesEntryPointName, AppHostServicesProvider } from '../src/appHostServices'
33
33
  import { ConsoleHostLogger } from '../src/loggers'
34
- import { mockPackageWithColdDependency } from '../testKit/mockPackage'
35
34
  import { createCircularEntryPoints, createDirectCircularEntryPoints } from './appHost.mock'
36
35
  import { createSignalItemsDataStructure } from './createSignalItemsDataStructure'
37
36
 
@@ -1876,509 +1875,4 @@ If the API is intended to be public, it should be declared as "public: true" in
1876
1875
  expect(itemsSpy).toBeCalledTimes(4)
1877
1876
  })
1878
1877
  })
1879
- describe('Cold Dependencies', () => {
1880
- it('should allow entry point to load without waiting for cold dependencies', async () => {
1881
- const host = createAppHost([], testHostOptions)
1882
- host.addShells([mockPackageWithColdDependency])
1883
- expect(host.hasShell(mockPackageWithColdDependency.name)).toBe(true)
1884
- })
1885
- it('should return false for hasAPI when cold dependency is not ready', async () => {
1886
- const host = createAppHost([], testHostOptions)
1887
- host.addShells([mockPackageWithColdDependency])
1888
- expect(host.hasAPI(MockAPI)).toBe(false)
1889
- })
1890
- it('should throw when accessing cold dependency that is not ready', async () => {
1891
- const host = createAppHost([], testHostOptions)
1892
- host.addShells([mockPackageWithColdDependency])
1893
- expect(() => host.getAPI(MockAPI)).toThrow()
1894
- })
1895
- it('should throw when accessing cold dependency during entry point attach', async () => {
1896
- const coldDependencyEntryPoint: EntryPoint = {
1897
- name: 'COLD_DEPENDENCY_ENTRY_POINT',
1898
- getColdDependencyAPIs() {
1899
- return [MockAPI]
1900
- },
1901
- declareAPIs() {
1902
- return [MockPublicAPI]
1903
- },
1904
- attach(shell: Shell) {
1905
- shell.contributeAPI(MockPublicAPI, () => {
1906
- const mockAPI = shell.getAPI(MockAPI)
1907
- return {
1908
- stubTrue: () => mockAPI.stubTrue()
1909
- }
1910
- })
1911
- }
1912
- }
1913
- const host = createAppHost([], testHostOptions)
1914
- expect(() => host.addShells([coldDependencyEntryPoint])).toThrow()
1915
- })
1916
- it('should throw when accessing cold dependency during entry point extend', async () => {
1917
- const coldDependencyEntryPoint: EntryPoint = {
1918
- name: 'COLD_DEPENDENCY_ENTRY_POINT',
1919
- getColdDependencyAPIs() {
1920
- return [MockAPI]
1921
- },
1922
- extend(shell: Shell) {
1923
- shell.getAPI(MockAPI).stubTrue()
1924
- }
1925
- }
1926
- const host = createAppHost([], testHostOptions)
1927
- expect(() => host.addShells([coldDependencyEntryPoint])).toThrow()
1928
- })
1929
- it('should allow accessing cold dependency via getAPI after initialization completes', async () => {
1930
- const host = createAppHost([mockPackage], testHostOptions)
1931
- const shell = addMockShell(host, {
1932
- getColdDependencyAPIs: () => [MockAPI]
1933
- })
1934
-
1935
- expect(() => shell.getAPI(MockAPI)).not.toThrow()
1936
- expect(shell.getAPI(MockAPI).stubTrue()).toBe(true)
1937
- })
1938
- describe('getColdAPI', () => {
1939
- it('should allow using getColdAPI inside contributeAPI factory', async () => {
1940
- // Problem: You can't call getAPI(coldDep) inside contributeAPI factory because init hasn't completed
1941
- // Solution: getColdAPI returns a lazy wrapper that defers resolution until the method is actually called
1942
- const host = createAppHost([mockPackage], testHostOptions)
1943
-
1944
- addMockShell(host, {
1945
- getColdDependencyAPIs: () => [MockAPI],
1946
- declareAPIs: () => [MockPublicAPI],
1947
- attach(shell) {
1948
- const mockAPI = shell.getColdAPI(MockAPI)
1949
-
1950
- shell.contributeAPI(MockPublicAPI, () => ({
1951
- stubTrue: () => mockAPI.get().stubTrue()
1952
- }))
1953
- }
1954
- })
1955
-
1956
- expect(host.getAPI(MockPublicAPI).stubTrue()).toBe(true)
1957
- })
1958
- it('should resolve cold dependency when get() is called after initialization', async () => {
1959
- const host = createAppHost([mockPackage], testHostOptions)
1960
- const shell = addMockShell(host, {
1961
- getColdDependencyAPIs: () => [MockAPI]
1962
- })
1963
-
1964
- const lazyAPI = shell.getColdAPI(MockAPI)
1965
- expect(lazyAPI.get().stubTrue()).toBe(true)
1966
- })
1967
- it('should throw when get() is called and cold dependency is not ready', async () => {
1968
- const host = createAppHost([], testHostOptions)
1969
- const shell = addMockShell(host, {
1970
- getColdDependencyAPIs: () => [MockAPI]
1971
- })
1972
-
1973
- const lazyAPI = shell.getColdAPI(MockAPI)
1974
- expect(() => lazyAPI.get()).toThrow()
1975
- })
1976
- it('should cache the API after first get() call', async () => {
1977
- const host = createAppHost([mockPackage], testHostOptions)
1978
- const shell = addMockShell(host, {
1979
- getColdDependencyAPIs: () => [MockAPI]
1980
- })
1981
-
1982
- const lazyAPI = shell.getColdAPI(MockAPI)
1983
- const first = lazyAPI.get()
1984
- const second = lazyAPI.get()
1985
- expect(first).toBe(second)
1986
- })
1987
- })
1988
- describe('Cyclic Cold Dependencies', () => {
1989
- it('should load entry point with cyclic cold dependencies', async () => {
1990
- /**
1991
- * (A)───cold───>(B)
1992
- * ^ │
1993
- * │ │
1994
- * └────cold─────┘
1995
- *
1996
- * A declares APIA, has cold dep on APIB
1997
- * B declares APIB, has cold dep on APIA
1998
- */
1999
- const APIA: SlotKey<{}> = { name: 'API_A' }
2000
- const APIB: SlotKey<{}> = { name: 'API_B' }
2001
- const declaringAWithColdDepOnB: EntryPoint = {
2002
- name: 'ENTRY_POINT_A',
2003
- getColdDependencyAPIs() {
2004
- return [APIB]
2005
- },
2006
- declareAPIs() {
2007
- return [APIA]
2008
- },
2009
- attach(shell: Shell) {
2010
- shell.contributeAPI(APIA, () => ({
2011
- stubTrue: () => true
2012
- }))
2013
- }
2014
- }
2015
- const declaringBWithColdDepOnA: EntryPoint = {
2016
- name: 'ENTRY_POINT_B',
2017
- getColdDependencyAPIs() {
2018
- return [APIA]
2019
- },
2020
- declareAPIs() {
2021
- return [APIB]
2022
- },
2023
- attach(shell: Shell) {
2024
- shell.contributeAPI(APIB, () => ({
2025
- stubTrue: () => true
2026
- }))
2027
- }
2028
- }
2029
- const host = createAppHost([declaringAWithColdDepOnB, declaringBWithColdDepOnA], testHostOptions)
2030
- expect(host.hasShell(declaringAWithColdDepOnB.name)).toBe(true)
2031
- expect(host.hasShell(declaringBWithColdDepOnA.name)).toBe(true)
2032
- })
2033
- it('should load entry points with cyclic cold and regular dependencies', async () => {
2034
- /**
2035
- * (A)───cold───>(B)───cold───>(C)
2036
- * ^ │
2037
- * │ │
2038
- * └─────────regular────────────┘
2039
- *
2040
- * A declares APIA, has cold dep on APIB
2041
- * B declares APIB, has cold dep on APIC
2042
- * C declares APIC, has regular dep on APIA
2043
- */
2044
- const APIA: SlotKey<{}> = { name: 'API_A' }
2045
- const APIB: SlotKey<{}> = { name: 'API_B' }
2046
- const APIC: SlotKey<{}> = { name: 'API_C' }
2047
- const declaringA: EntryPoint = {
2048
- name: 'ENTRY_POINT_A',
2049
- getColdDependencyAPIs() {
2050
- return [APIB]
2051
- },
2052
- declareAPIs() {
2053
- return [APIA]
2054
- },
2055
- attach(shell: Shell) {
2056
- shell.contributeAPI(APIA, () => ({
2057
- stubTrue: () => true
2058
- }))
2059
- }
2060
- }
2061
- const declaringB: EntryPoint = {
2062
- name: 'ENTRY_POINT_B',
2063
- getColdDependencyAPIs() {
2064
- return [APIC]
2065
- },
2066
- declareAPIs() {
2067
- return [APIB]
2068
- },
2069
- attach(shell: Shell) {
2070
- shell.contributeAPI(APIB, () => ({
2071
- stubTrue: () => true
2072
- }))
2073
- }
2074
- }
2075
- const declaringC: EntryPoint = {
2076
- name: 'ENTRY_POINT_C',
2077
- getDependencyAPIs() {
2078
- return [APIA]
2079
- },
2080
- declareAPIs() {
2081
- return [APIC]
2082
- },
2083
- attach(shell: Shell) {
2084
- shell.contributeAPI(APIC, () => ({
2085
- stubTrue: () => true
2086
- }))
2087
- }
2088
- }
2089
- const host = createAppHost([declaringA, declaringB, declaringC], testHostOptions)
2090
- expect(host.hasShell(declaringA.name)).toBe(true)
2091
- expect(host.hasShell(declaringB.name)).toBe(true)
2092
- expect(host.hasShell(declaringC.name)).toBe(true)
2093
- })
2094
- })
2095
- describe('Cold dependency promotion', () => {
2096
- it('should promote transitive cold dependencies to regular dependencies when there is a real direct dependency', async () => {
2097
- const APIA: SlotKey<{}> = { name: 'API_A' }
2098
- const APIB: SlotKey<{}> = { name: 'API_B' }
2099
- const APIC: SlotKey<{}> = { name: 'API_C' }
2100
- const declaringA: EntryPoint = {
2101
- name: 'ENTRY_POINT_A',
2102
- declareAPIs() {
2103
- return [APIA]
2104
- },
2105
- attach(shell: Shell) {
2106
- shell.contributeAPI(APIA, () => ({
2107
- stubTrue: () => true
2108
- }))
2109
- }
2110
- }
2111
- const declaringBWithColdDepOnA: EntryPoint = {
2112
- name: 'ENTRY_POINT_B',
2113
- getColdDependencyAPIs() {
2114
- return [APIA]
2115
- },
2116
- declareAPIs() {
2117
- return [APIB]
2118
- },
2119
- attach(shell: Shell) {
2120
- shell.contributeAPI(APIB, () => ({
2121
- stubTrue: () => true
2122
- }))
2123
- }
2124
- }
2125
- const declaringCWithRegularDepOnB: EntryPoint = {
2126
- name: 'ENTRY_POINT_C',
2127
- getDependencyAPIs() {
2128
- return [APIB]
2129
- },
2130
- declareAPIs() {
2131
- return [APIC]
2132
- },
2133
- attach(shell: Shell) {
2134
- shell.contributeAPI(APIC, () => ({
2135
- stubTrue: () => true
2136
- }))
2137
- }
2138
- }
2139
- // no APIA in the host
2140
- const host = createAppHost([declaringBWithColdDepOnA, declaringCWithRegularDepOnB], testHostOptions)
2141
- expect(host.hasShell(declaringBWithColdDepOnA.name)).toBe(true)
2142
- expect(host.hasShell(declaringCWithRegularDepOnB.name)).toBe(false)
2143
- await host.addShells([declaringA])
2144
- expect(host.hasShell(declaringCWithRegularDepOnB.name)).toBe(true)
2145
- })
2146
- it('should promote cold dependencies from unready entry points added in previous batches', async () => {
2147
- const APIA: SlotKey<{}> = { name: 'API_A' }
2148
- const APIB: SlotKey<{}> = { name: 'API_B' }
2149
- const APIC: SlotKey<{}> = { name: 'API_C' }
2150
- const APIX: SlotKey<{}> = { name: 'API_X' }
2151
-
2152
- // B declares APIB, depends on APIX (keeps B unready), has cold dep on APIA
2153
- const declaringB: EntryPoint = {
2154
- name: 'ENTRY_POINT_B',
2155
- getDependencyAPIs() {
2156
- return [APIX]
2157
- },
2158
- getColdDependencyAPIs() {
2159
- return [APIA]
2160
- },
2161
- declareAPIs() {
2162
- return [APIB]
2163
- },
2164
- attach(shell: Shell) {
2165
- shell.contributeAPI(APIB, () => ({ stubTrue: () => true }))
2166
- }
2167
- }
2168
-
2169
- // C depends on APIB (from unready B)
2170
- const declaringC: EntryPoint = {
2171
- name: 'ENTRY_POINT_C',
2172
- getDependencyAPIs() {
2173
- return [APIB]
2174
- },
2175
- declareAPIs() {
2176
- return [APIC]
2177
- },
2178
- attach(shell: Shell) {
2179
- shell.contributeAPI(APIC, () => ({ stubTrue: () => true }))
2180
- }
2181
- }
2182
-
2183
- const declaringA: EntryPoint = {
2184
- name: 'ENTRY_POINT_A',
2185
- declareAPIs() {
2186
- return [APIA]
2187
- },
2188
- attach(shell: Shell) {
2189
- shell.contributeAPI(APIA, () => ({ stubTrue: () => true }))
2190
- }
2191
- }
2192
-
2193
- const declaringX: EntryPoint = {
2194
- name: 'ENTRY_POINT_X',
2195
- declareAPIs() {
2196
- return [APIX]
2197
- },
2198
- attach(shell: Shell) {
2199
- shell.contributeAPI(APIX, () => ({ stubTrue: () => true }))
2200
- }
2201
- }
2202
-
2203
- const host = createAppHost([], testHostOptions)
2204
-
2205
- // Batch 1: Add B (stays unready - needs APIX)
2206
- await host.addShells([declaringB])
2207
- expect(host.hasShell(declaringB.name)).toBe(false)
2208
-
2209
- // Batch 2: Add C (depends on APIB from unready B)
2210
- // Even though B is unready, C's effective deps should include B's cold dep on APIA
2211
- await host.addShells([declaringC])
2212
- expect(host.hasShell(declaringC.name)).toBe(false)
2213
-
2214
- // Add X only (provides APIX for B)
2215
- // B can now load and contribute APIB
2216
- // But C should still wait because B's cold dep (APIA) is promoted to C
2217
- await host.addShells([declaringX])
2218
- expect(host.hasShell(declaringB.name)).toBe(true)
2219
- expect(host.hasShell(declaringC.name)).toBe(false)
2220
-
2221
- // Add A (provides APIA)
2222
- await host.addShells([declaringA])
2223
- expect(host.hasShell(declaringC.name)).toBe(true)
2224
- })
2225
- it('should promote cold dependencies through deep regular dependency chains', async () => {
2226
- /**
2227
- * (A)───regular───>(B)───regular───>(C)───regular───>(D)
2228
- * │
2229
- * cold
2230
- * │
2231
- * v
2232
- * (E)
2233
- *
2234
- * A depends on B, B depends on C, C depends on D, D has cold dep on E
2235
- * A should wait for E (cold dep promoted through entire chain)
2236
- */
2237
- const APIA: SlotKey<{}> = { name: 'API_A' }
2238
- const APIB: SlotKey<{}> = { name: 'API_B' }
2239
- const APIC: SlotKey<{}> = { name: 'API_C' }
2240
- const APID: SlotKey<{}> = { name: 'API_D' }
2241
- const APIE: SlotKey<{}> = { name: 'API_E' }
2242
-
2243
- const declaringE: EntryPoint = {
2244
- name: 'ENTRY_POINT_E',
2245
- declareAPIs() {
2246
- return [APIE]
2247
- },
2248
- attach(shell: Shell) {
2249
- shell.contributeAPI(APIE, () => ({ stubTrue: () => true }))
2250
- }
2251
- }
2252
-
2253
- const declaringD: EntryPoint = {
2254
- name: 'ENTRY_POINT_D',
2255
- getColdDependencyAPIs() {
2256
- return [APIE]
2257
- },
2258
- declareAPIs() {
2259
- return [APID]
2260
- },
2261
- attach(shell: Shell) {
2262
- shell.contributeAPI(APID, () => ({ stubTrue: () => true }))
2263
- }
2264
- }
2265
-
2266
- const declaringC: EntryPoint = {
2267
- name: 'ENTRY_POINT_C',
2268
- getDependencyAPIs() {
2269
- return [APID]
2270
- },
2271
- declareAPIs() {
2272
- return [APIC]
2273
- },
2274
- attach(shell: Shell) {
2275
- shell.contributeAPI(APIC, () => ({ stubTrue: () => true }))
2276
- }
2277
- }
2278
-
2279
- const declaringB: EntryPoint = {
2280
- name: 'ENTRY_POINT_B',
2281
- getDependencyAPIs() {
2282
- return [APIC]
2283
- },
2284
- declareAPIs() {
2285
- return [APIB]
2286
- },
2287
- attach(shell: Shell) {
2288
- shell.contributeAPI(APIB, () => ({ stubTrue: () => true }))
2289
- }
2290
- }
2291
-
2292
- const declaringA: EntryPoint = {
2293
- name: 'ENTRY_POINT_A',
2294
- getDependencyAPIs() {
2295
- return [APIB]
2296
- },
2297
- declareAPIs() {
2298
- return [APIA]
2299
- },
2300
- attach(shell: Shell) {
2301
- shell.contributeAPI(APIA, () => ({ stubTrue: () => true }))
2302
- }
2303
- }
2304
-
2305
- // Without E, D loads (cold dep doesn't block), but A, B, C should wait
2306
- const host = createAppHost([declaringA, declaringB, declaringC, declaringD], testHostOptions)
2307
- expect(host.hasShell(declaringD.name)).toBe(true)
2308
- expect(host.hasShell(declaringC.name)).toBe(false)
2309
- expect(host.hasShell(declaringB.name)).toBe(false)
2310
- expect(host.hasShell(declaringA.name)).toBe(false)
2311
-
2312
- // Add E, now everyone can load
2313
- await host.addShells([declaringE])
2314
- expect(host.hasShell(declaringC.name)).toBe(true)
2315
- expect(host.hasShell(declaringB.name)).toBe(true)
2316
- expect(host.hasShell(declaringA.name)).toBe(true)
2317
- })
2318
- })
2319
- it('should not promote transitive cold dependencies to regular dependencies when there is no real direct dependency', async () => {
2320
- const APIA: SlotKey<{}> = { name: 'API_A' }
2321
- const APIB: SlotKey<{}> = { name: 'API_B' }
2322
- const APIC: SlotKey<{}> = { name: 'API_C' }
2323
- const APID: SlotKey<{}> = { name: 'API_D' }
2324
- const declaringA: EntryPoint = {
2325
- name: 'ENTRY_POINT_A',
2326
- declareAPIs() {
2327
- return [APIA]
2328
- },
2329
- attach(shell: Shell) {
2330
- shell.contributeAPI(APIA, () => ({
2331
- stubTrue: () => true
2332
- }))
2333
- }
2334
- }
2335
- const declaringBWithColdDepOnA: EntryPoint = {
2336
- name: 'ENTRY_POINT_B',
2337
- getColdDependencyAPIs() {
2338
- return [APIA]
2339
- },
2340
- declareAPIs() {
2341
- return [APIB]
2342
- },
2343
- attach(shell: Shell) {
2344
- shell.contributeAPI(APIB, () => ({
2345
- stubTrue: () => true
2346
- }))
2347
- }
2348
- }
2349
- const declaringCWithRegularDepOnB: EntryPoint = {
2350
- name: 'ENTRY_POINT_C',
2351
- getDependencyAPIs() {
2352
- return [APIB]
2353
- },
2354
- declareAPIs() {
2355
- return [APIC]
2356
- },
2357
- attach(shell: Shell) {
2358
- shell.contributeAPI(APIC, () => ({
2359
- stubTrue: () => true
2360
- }))
2361
- }
2362
- }
2363
- const declaringDWithColdDepOnC: EntryPoint = {
2364
- name: 'ENTRY_POINT_D',
2365
- getColdDependencyAPIs() {
2366
- return [APIC]
2367
- },
2368
- declareAPIs() {
2369
- return [APID]
2370
- },
2371
- attach(shell: Shell) {
2372
- shell.contributeAPI(APID, () => ({
2373
- stubTrue: () => true
2374
- }))
2375
- }
2376
- }
2377
- const host = createAppHost([declaringBWithColdDepOnA, declaringCWithRegularDepOnB, declaringDWithColdDepOnC], testHostOptions)
2378
- expect(host.hasShell(declaringDWithColdDepOnC.name)).toBe(true)
2379
- expect(host.hasShell(declaringCWithRegularDepOnB.name)).toBe(false)
2380
- await host.addShells([declaringA])
2381
- expect(host.hasShell(declaringCWithRegularDepOnB.name)).toBe(true)
2382
- })
2383
- })
2384
1878
  })
@@ -108,18 +108,3 @@ export const mockPackageWithSlot: EntryPoint = {
108
108
  shell.declareSlot(MockSlot)
109
109
  }
110
110
  }
111
-
112
- export const mockPackageWithColdDependency: EntryPoint = {
113
- name: 'MOCK_PACKAGE_WITH_COLD_DEPENDENCY',
114
- getColdDependencyAPIs() {
115
- return [MockAPI]
116
- },
117
- declareAPIs() {
118
- return [MockPublicAPI]
119
- },
120
- attach(shell: Shell) {
121
- shell.contributeAPI(MockPublicAPI, () => ({
122
- stubTrue: () => true
123
- }))
124
- }
125
- }