repluggable-core 0.0.0-pr340.39 → 0.0.0-pr342.44
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/dist/debug/src/API.d.ts +17 -1
- package/dist/es/src/API.d.ts +17 -1
- package/dist/es/src/API.d.ts.map +1 -1
- package/dist/es/src/API.js.map +1 -1
- package/dist/es/src/appHost.d.ts.map +1 -1
- package/dist/es/src/appHost.js +50 -5
- package/dist/es/src/appHost.js.map +1 -1
- package/dist/es/src/appHostUtils.d.ts +1 -0
- package/dist/es/src/appHostUtils.d.ts.map +1 -1
- package/dist/es/src/appHostUtils.js +3 -0
- package/dist/es/src/appHostUtils.js.map +1 -1
- package/dist/es/test/appHost.spec.js +483 -0
- package/dist/es/test/appHost.spec.js.map +1 -1
- package/dist/es/testKit/mockPackage.d.ts +1 -0
- package/dist/es/testKit/mockPackage.d.ts.map +1 -1
- package/dist/es/testKit/mockPackage.js +14 -0
- package/dist/es/testKit/mockPackage.js.map +1 -1
- package/dist/src/API.d.ts +17 -1
- package/dist/src/API.d.ts.map +1 -1
- package/dist/src/API.js.map +1 -1
- package/dist/src/appHost.d.ts.map +1 -1
- package/dist/src/appHost.js +49 -4
- package/dist/src/appHost.js.map +1 -1
- package/dist/src/appHostUtils.d.ts +1 -0
- package/dist/src/appHostUtils.d.ts.map +1 -1
- package/dist/src/appHostUtils.js +5 -1
- package/dist/src/appHostUtils.js.map +1 -1
- package/dist/test/appHost.spec.js +483 -0
- package/dist/test/appHost.spec.js.map +1 -1
- package/dist/testKit/mockPackage.d.ts +1 -0
- package/dist/testKit/mockPackage.d.ts.map +1 -1
- package/dist/testKit/mockPackage.js +15 -1
- package/dist/testKit/mockPackage.js.map +1 -1
- package/package.json +2 -2
- package/src/API.ts +18 -2
- package/src/appHost.ts +62 -6
- package/src/appHostUtils.ts +3 -0
- package/test/appHost.spec.ts +506 -0
- package/testKit/mockPackage.ts +15 -0
package/test/appHost.spec.ts
CHANGED
|
@@ -31,6 +31,7 @@ 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'
|
|
34
35
|
import { createCircularEntryPoints, createDirectCircularEntryPoints } from './appHost.mock'
|
|
35
36
|
import { createSignalItemsDataStructure } from './createSignalItemsDataStructure'
|
|
36
37
|
|
|
@@ -1875,4 +1876,509 @@ If the API is intended to be public, it should be declared as "public: true" in
|
|
|
1875
1876
|
expect(itemsSpy).toBeCalledTimes(4)
|
|
1876
1877
|
})
|
|
1877
1878
|
})
|
|
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
|
+
})
|
|
1878
2384
|
})
|
package/testKit/mockPackage.ts
CHANGED
|
@@ -108,3 +108,18 @@ 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
|
+
}
|