@asteby/metacore-runtime-react 9.2.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +139 -0
- package/dist/addon-layout-context.d.ts +49 -0
- package/dist/addon-layout-context.d.ts.map +1 -0
- package/dist/addon-layout-context.js +94 -0
- package/dist/addon-loader.d.ts +14 -2
- package/dist/addon-loader.d.ts.map +1 -1
- package/dist/addon-loader.js +7 -1
- package/dist/hotswap-reload-policy.d.ts +155 -0
- package/dist/hotswap-reload-policy.d.ts.map +1 -0
- package/dist/hotswap-reload-policy.js +227 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/manifest-hotswap-subscriber.d.ts +83 -0
- package/dist/manifest-hotswap-subscriber.d.ts.map +1 -0
- package/dist/manifest-hotswap-subscriber.js +104 -0
- package/dist/metadata-cache.d.ts +35 -0
- package/dist/metadata-cache.d.ts.map +1 -1
- package/dist/metadata-cache.js +55 -0
- package/package.json +3 -3
- package/src/__tests__/hotswap-reload-policy.test.ts +249 -0
- package/src/__tests__/manifest-hotswap-subscriber.test.ts +179 -0
- package/src/__tests__/wasm-client-sri.test.ts +82 -0
- package/src/addon-layout-context.tsx +137 -0
- package/src/addon-loader.tsx +21 -1
- package/src/hotswap-reload-policy.ts +360 -0
- package/src/index.ts +28 -0
- package/src/manifest-hotswap-subscriber.ts +164 -0
- package/src/metadata-cache.ts +86 -0
package/src/metadata-cache.ts
CHANGED
|
@@ -14,6 +14,31 @@ export interface MetadataApiClient {
|
|
|
14
14
|
get: (url: string, config?: any) => Promise<{ data: any }>
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Predicate matching a cache key against an addon. The default
|
|
19
|
+
* implementation (see {@link defaultAddonKeyMatcher}) treats `addonKey`
|
|
20
|
+
* itself plus any key beginning with `${addonKey}.`, `${addonKey}:` or
|
|
21
|
+
* `${addonKey}/` as belonging to the addon. Hosts that namespace their
|
|
22
|
+
* `model` strings differently can pass a custom matcher to
|
|
23
|
+
* {@link MetadataCacheState.invalidateAddon}.
|
|
24
|
+
*/
|
|
25
|
+
export type AddonKeyMatcher = (cacheKey: string, addonKey: string) => boolean
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Default matcher used by {@link MetadataCacheState.invalidateAddon}.
|
|
29
|
+
* Mirrors the convention used by the kernel installer when it scopes
|
|
30
|
+
* model metadata under an addon's key.
|
|
31
|
+
*/
|
|
32
|
+
export function defaultAddonKeyMatcher(cacheKey: string, addonKey: string): boolean {
|
|
33
|
+
if (!addonKey) return false
|
|
34
|
+
if (cacheKey === addonKey) return true
|
|
35
|
+
return (
|
|
36
|
+
cacheKey.startsWith(`${addonKey}.`) ||
|
|
37
|
+
cacheKey.startsWith(`${addonKey}:`) ||
|
|
38
|
+
cacheKey.startsWith(`${addonKey}/`)
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
17
42
|
interface MetadataCacheState {
|
|
18
43
|
cache: Record<string, TableMetadata>
|
|
19
44
|
modalCache: Record<string, TableMetadata>
|
|
@@ -26,6 +51,26 @@ interface MetadataCacheState {
|
|
|
26
51
|
hasMetadata: (key: string) => boolean
|
|
27
52
|
hasModalMetadata: (key: string) => boolean
|
|
28
53
|
prefetchAll: (api: MetadataApiClient) => Promise<void>
|
|
54
|
+
/**
|
|
55
|
+
* Remove cached entries belonging to a specific addon. Used by the
|
|
56
|
+
* hot-swap subscriber when the kernel announces a manifest change.
|
|
57
|
+
*
|
|
58
|
+
* Returns the number of entries removed across both caches, which is
|
|
59
|
+
* useful for tests and observability — `0` means the cache had nothing
|
|
60
|
+
* to flush (the addon either hadn't been hit yet or uses a key
|
|
61
|
+
* convention the default matcher doesn't recognise; pass a custom
|
|
62
|
+
* `matcher` if your host namespaces differently).
|
|
63
|
+
*
|
|
64
|
+
* Also resets `prefetched` to `false` so the next mount re-runs
|
|
65
|
+
* `prefetchAll()` and the `metadataVersion` is allowed to advance to
|
|
66
|
+
* the kernel's freshly-bumped hash.
|
|
67
|
+
*/
|
|
68
|
+
invalidateAddon: (addonKey: string, matcher?: AddonKeyMatcher) => number
|
|
69
|
+
/**
|
|
70
|
+
* Remove every cached entry. Heavier hammer for hosts that prefer a
|
|
71
|
+
* blanket flush on hot-swap rather than per-addon scoping.
|
|
72
|
+
*/
|
|
73
|
+
clearAll: () => void
|
|
29
74
|
}
|
|
30
75
|
|
|
31
76
|
export const useMetadataCache = create<MetadataCacheState>()(
|
|
@@ -54,6 +99,47 @@ export const useMetadataCache = create<MetadataCacheState>()(
|
|
|
54
99
|
hasMetadata: (key: string) => key in get().cache,
|
|
55
100
|
hasModalMetadata: (key: string) => key in get().modalCache,
|
|
56
101
|
|
|
102
|
+
invalidateAddon: (addonKey: string, matcher = defaultAddonKeyMatcher) => {
|
|
103
|
+
if (!addonKey) return 0
|
|
104
|
+
let removed = 0
|
|
105
|
+
const state = get()
|
|
106
|
+
const nextCache: Record<string, TableMetadata> = {}
|
|
107
|
+
for (const [key, value] of Object.entries(state.cache)) {
|
|
108
|
+
if (matcher(key, addonKey)) {
|
|
109
|
+
removed += 1
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
nextCache[key] = value
|
|
113
|
+
}
|
|
114
|
+
const nextModalCache: Record<string, TableMetadata> = {}
|
|
115
|
+
for (const [key, value] of Object.entries(state.modalCache)) {
|
|
116
|
+
if (matcher(key, addonKey)) {
|
|
117
|
+
removed += 1
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
nextModalCache[key] = value
|
|
121
|
+
}
|
|
122
|
+
if (removed === 0) return 0
|
|
123
|
+
set({
|
|
124
|
+
cache: nextCache,
|
|
125
|
+
modalCache: nextModalCache,
|
|
126
|
+
// Allow prefetchAll() to re-run so we pick up the new
|
|
127
|
+
// metadataVersion the kernel emits alongside the
|
|
128
|
+
// bumped manifest.
|
|
129
|
+
prefetched: false,
|
|
130
|
+
})
|
|
131
|
+
return removed
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
clearAll: () => {
|
|
135
|
+
set({
|
|
136
|
+
cache: {},
|
|
137
|
+
modalCache: {},
|
|
138
|
+
metadataVersion: '',
|
|
139
|
+
prefetched: false,
|
|
140
|
+
})
|
|
141
|
+
},
|
|
142
|
+
|
|
57
143
|
prefetchAll: async (api: MetadataApiClient) => {
|
|
58
144
|
if (get().prefetched) return
|
|
59
145
|
try {
|