From e4818f576e48bf7837d928fa3f520137dbbe5965 Mon Sep 17 00:00:00 2001 From: Paul Derscheid Date: Mon, 16 Sep 2024 12:17:55 +0000 Subject: [PATCH] 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. --- .../prog/js/vue/modules/islands.ts | 93 ++++++++++--------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts index 1571d2ced6..c5e04a183a 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/islands.ts @@ -4,54 +4,51 @@ import { useMainStore } from "../stores/main"; import { useNavigationStore } from "../stores/navigation"; /** - * A registry for Vue components. - * @type {Map Promise>} + * Represents a web component with an import function and optional configuration. + * @typedef {Object} WebComponentDynamicImport + * @property {function(): Promise} importFn - A function that imports the component dynamically. + * @property {Object} [config] - An optional configuration object for the web component. + * @property {Array} [config.stores] - An optional array of strings representing store names associated with the component. */ -interface WebComponent { +type WebComponentDynamicImport = { importFn: () => Promise; - config?: { - stores: string[]; - }; -} -export const componentRegistry: Map = new Map([ - [ - "hello-islands", - { - importFn: async () => { - const module = await import( - /* webpackChunkName: "hello-islands" */ - "../components/HelloIslands.vue" - ); - return module.default; - }, - config: { - stores: ["mainStore", "navigationStore"], + config?: Record<"stores", Array>; +}; + +/** + * A registry for Vue components. + * @type {Map} + */ +export const componentRegistry: Map = + 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; + ], + [ + "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, -}; + ], + ]); /** * Hydrates custom elements by scanning the document and loading only necessary components. @@ -59,6 +56,12 @@ const storesMatrix = { */ 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]); -- 2.46.1