Bug 37911: (follow-up) Move store initialisation into hydrate's idle callback

- Additionally:
    - Use a type instead of an interface.
        - Add JSDoc to it.
    - Use optional chaining when checking for existence and length of config.

Signed-off-by: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
This commit is contained in:
Paul Derscheid 2024-09-16 12:17:55 +00:00 committed by Katrin Fischer
parent b430fe4802
commit c8281eb8a7
No known key found for this signature in database
GPG Key ID: 0EF6E2C03357A834
1 changed files with 49 additions and 46 deletions

View File

@ -4,61 +4,64 @@ import { useMainStore } from "../stores/main";
import { useNavigationStore } from "../stores/navigation";
/**
* A registry for Vue components.
* @type {Map<string, () => Promise<Component>>}
* Represents a web component with an import function and optional configuration.
* @typedef {Object} WebComponentDynamicImport
* @property {function(): Promise<Component>} importFn - A function that imports the component dynamically.
* @property {Object} [config] - An optional configuration object for the web component.
* @property {Array<string>} [config.stores] - An optional array of strings representing store names associated with the component.
*/
interface WebComponent {
type WebComponentDynamicImport = {
importFn: () => Promise<Component>;
config?: {
stores: string[];
};
}
export const componentRegistry: Map<string, WebComponent> = new Map([
[
"hello-islands",
{
importFn: async () => {
const module = await import(
/* webpackChunkName: "hello-islands" */
"../components/HelloIslands.vue"
);
return module.default;
},
config: {
stores: ["mainStore", "navigationStore"],
},
},
],
[
"hello-world",
{
importFn: async () => {
const module = await import(
/* webpackChunkName: "hello-world" */
"../components/HelloWorld.vue"
);
return module.default;
},
},
],
]);
const pinia = createPinia();
const mainStore = useMainStore(pinia);
const navigationStore = useNavigationStore(pinia);
const storesMatrix = {
mainStore,
navigationStore,
config?: Record<"stores", Array<string>>;
};
/**
* A registry for Vue components.
* @type {Map<string, WebComponentDynamicImport>}
*/
export const componentRegistry: Map<string, WebComponentDynamicImport> =
new Map([
[
"hello-islands",
{
importFn: async () => {
const module = await import(
/* webpackChunkName: "hello-islands" */
"../components/HelloIslands.vue"
);
return module.default;
},
config: {
stores: ["mainStore", "navigationStore"],
},
},
],
[
"hello-world",
{
importFn: async () => {
const module = await import(
/* webpackChunkName: "hello-world" */
"../components/HelloWorld.vue"
);
return module.default;
},
},
],
]);
/**
* Hydrates custom elements by scanning the document and loading only necessary components.
* @returns {void}
*/
export function hydrate(): void {
window.requestIdleCallback(async () => {
const pinia = createPinia();
const storesMatrix = {
mainStore: useMainStore(pinia),
navigationStore: useNavigationStore(pinia),
};
const islandTagNames = Array.from(componentRegistry.keys()).join(", ");
const requestedIslands = new Set(
Array.from(document.querySelectorAll(islandTagNames)).map(element =>
@ -79,7 +82,7 @@ export function hydrate(): void {
shadowRoot: false,
...(config && {
configureApp(app) {
if (config.stores && config.stores.length > 0) {
if (config.stores?.length > 0) {
app.use(pinia);
config.stores.forEach(store => {
app.provide(store, storesMatrix[store]);