dashboard/shell/initialize/app-extended.js

113 lines
3.0 KiB
JavaScript

import { setContext, getRouteData } from '@shell/initialize/entry-helpers';
import { extendRouter } from '@shell/config/router';
import { extendStore } from '@shell/config/store';
import { installInjectedPlugins } from '@shell/initialize/install-plugins.js';
import { normalizeURL } from 'ufo';
/**
* Imported from vue-router
* @param {*} base
* @param {*} mode
* @returns
*/
export const getLocation = (base, mode) => {
if (mode === 'hash') {
return window.location.hash.replace(/^#\//, '');
}
base = decodeURI(base).slice(0, -1); // consideration is base is normalized with trailing slash
let path = decodeURI(window.location.pathname);
if (base && path.startsWith(base)) {
path = path.slice(base.length);
}
const fullPath = (path || '/') + window.location.search + window.location.hash;
return normalizeURL(fullPath);
};
/**
* Bundle Vue app component and configuration to be executed on entry
* @param {*} vueApp Vue instance
* @returns
*/
async function extendApp(vueApp) {
const config = { rancherEnv: process.env.rancherEnv, dashboardVersion: process.env.version };
const store = extendStore();
const router = extendRouter(config, { store });
// Add this.$router into store actions/mutations
store.$router = router;
// Create Root instance
// here we inject the router and store to all child components,
// making them available everywhere as `this.$router` and `this.$store`.
const appPartials = {
store,
router,
};
// Make app available into store via this.app
store.app = appPartials;
const next = (location) => appPartials.router.push(location);
// Resolve route
const path = getLocation(router.options.base, router.options.mode);
const route = router.resolve(path);
// Set context to app.context
await setContext(
appPartials,
{
store,
route,
next,
payload: undefined,
req: undefined,
res: undefined
},
);
await installInjectedPlugins(appPartials, vueApp);
// Wait for async component to be resolved first
await new Promise((resolve, reject) => {
// Ignore 404s rather than blindly replacing URL in browser
const route = router.resolve(appPartials.context.route.fullPath);
if (!route.matched.length) {
return resolve();
}
router.replace(appPartials.context.route.fullPath).then(resolve, (err) => {
// https://github.com/vuejs/vue-router/blob/v3.4.3/src/util/errors.js
if (!err._isRouter) {
return reject(err);
}
if (err.type !== 2 /* NavigationFailureType.redirected */) {
return resolve();
}
// navigated to a different route in router guard
const unregister = router.afterEach(async(to, from) => {
appPartials.context.route = await getRouteData(to);
appPartials.context.params = to.params || {};
appPartials.context.query = to.query || {};
unregister();
resolve();
});
});
});
return {
store,
app: appPartials,
router
};
}
export { extendApp };