Skip to main content
Glama
router.ts10.5 kB
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; import * as _ from "lodash-es"; import { nextTick } from "vue"; import { AxiosRequestConfig } from "axios"; import { posthog } from "@/utils/posthog"; import { push as pushBreadcrumb, query, } from "@/newhotness/logic_composables/navigation_stack"; import { tokensByWorkspacePk } from "@/newhotness/logic_composables/tokens"; import { useAuthStore } from "./store/auth.store"; import { useRouterStore } from "./store/router.store"; import { isDevMode } from "./utils/debug"; import { sdfApiInstance as sdf } from "./store/apis.web"; import { WorkspaceMetadata } from "./api/sdf/dal/workspace"; // Cannot use inside the template directly. const AUTH_PORTAL_URL = import.meta.env.VITE_AUTH_PORTAL_URL; const findChangeSetId = async (workspacePk: string | undefined) => { /** * PSA: this may throw a 401 if the tokens aren't yet stored from a new * successful login. The 401 is nothing to be alarmed about, it doesn't stop * the app from continuing to work, because we're not throwing an exception below * with the `validateStatus` */ const token = tokensByWorkspacePk[(workspacePk as string) || ""]; // eslint-disable-next-line @typescript-eslint/no-explicit-any const params: AxiosRequestConfig<any> = { method: "GET", url: `v2/workspaces/${workspacePk}/change-sets`, validateStatus: (_status) => true, // don't throw exception on 4/5xxx }; if (token) { params.headers = { Authorization: `Bearer ${token}`, }; } const resp = await sdf<WorkspaceMetadata>(params); return resp.data.defaultChangeSetId; }; const routes: RouteRecordRaw[] = [ { path: "/", name: "home", component: () => import("@/pages/HomePage.vue"), }, { path: "/hashes", name: "hashes", meta: { public: true }, component: () => import("@/pages/Hashes.vue"), }, { path: "/w", name: "workspace-index", redirect: { name: "home" }, }, { name: "new-hotness-workspace", path: "/n/:workspacePk", beforeEnter: async (loc) => { const changeSetId = await findChangeSetId( loc.params.workspacePk as string | undefined, ); const newloc = `/n/${loc.params.workspacePk}/${changeSetId}/h`; return newloc; }, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness-workspace-auto", path: "/n/:workspacePk/auto", beforeEnter: async (loc) => { const changeSetId = await findChangeSetId( loc.params.workspacePk as string | undefined, ); const newloc = `/n/${loc.params.workspacePk}/${changeSetId}/h`; return newloc; }, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness-head", path: "/n/:workspacePk/head/h", beforeEnter: async (loc) => { const changeSetId = await findChangeSetId( loc.params.workspacePk as string | undefined, ); const newloc = `/n/${loc.params.workspacePk}/${changeSetId}/h`; return newloc; }, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness", path: "/n/:workspacePk/:changeSetId/h", props: true, component: () => import("@/newhotness/Workspace.vue"), children: [ // { // name: "new-hotness-lobby", // path: "lobby", // component: () => import("@/newhotness/Workspace.vue"), // }, { name: "new-hotness-view", path: ":viewId/v/edit", props: true, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness-secrets-list", path: "secrets", props: true, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness-component", path: ":componentId/c", props: true, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness-func-run", path: ":funcRunId/r", props: true, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness-action", path: ":actionId/a", props: true, component: () => import("@/newhotness/Workspace.vue"), }, { name: "new-hotness-review", path: "r", props: true, component: () => import("@/newhotness/Workspace.vue"), }, ], }, { name: "workspace-single", path: "/w/:workspacePk", component: () => import("@/pages/WorkspaceSinglePage.vue"), // TODO: will probably want a workspace "home" page at some point redirect(to) { return { name: "change-set-home", params: { ...to.params, changeSetId: "auto" }, }; }, children: [ { path: ":changeSetId", name: "change-set-home", // TODO: will probably want a change set "home" page at some point redirect(to) { return { name: "workspace-compose", params: to.params, }; }, }, { path: ":changeSetId/c", name: "workspace-compose", redirect: { name: "new-hotness" }, children: [ { path: ":viewId/v/", name: "workspace-compose-view", redirect: { name: "new-hotness" }, }, ], }, { path: ":changeSetId/l", name: "workspace-lab", component: () => import("@/components/Workspace/WorkspaceCustomizeIndex.vue"), redirect(to) { return { name: "workspace-lab-assets", params: to.params, query: to.query, }; }, children: [ { path: "a/", name: "workspace-lab-assets", component: () => import("@/components/Workspace/WorkspaceCustomizeAssets.vue"), }, { path: "n/", name: "workspace-lab-newassets", component: () => import("@/components/Workspace/WorkspaceCustomizeAssets.vue"), }, { path: "m/:moduleSlug?", name: "workspace-lab-packages", component: () => import("@/components/Workspace/WorkspaceCustomizeModules.vue"), }, ], }, { path: ":changeSetId/a", name: "workspace-audit", component: () => import("@/components/Workspace/WorkspaceAuditLog.vue"), }, { path: "admin", name: "workspace-admin-dashboard", component: () => import("@/components/Workspace/WorkspaceAdminDashboard.vue"), }, ...(isDevMode ? [ { path: "dev", name: "workspace-dev-dashboard", component: () => import("@/components/Workspace/WorkspaceDevDashboard.vue"), }, ] : []), ], }, // Auth { path: "/auth-connect", name: "auth-connect", meta: { public: true }, component: () => import("@/pages/auth/AuthConnectPage.vue"), }, { path: "/refresh-auth", name: "refresh-auth", meta: { public: true }, component: () => import("@/pages/auth/RefreshAuthPage.vue"), }, { path: "/login", name: "login", meta: { public: true }, beforeEnter: (route) => { const query = route.query; const workspaceId = query.workspaceId; const queryString = query.redirect ? `redirect=${query.redirect}` : ""; if (workspaceId) { window.location.href = `${AUTH_PORTAL_URL}/workspace/${workspaceId}/go?${queryString}`; } else { window.location.href = `${AUTH_PORTAL_URL}/login?${queryString}`; } }, component: () => import("@/pages/auth/AuthConnectPage.vue"), }, { path: "/logout", name: "logout", beforeEnter: () => { const authStore = useAuthStore(); authStore.localLogout(); }, component: () => import("@/pages/auth/LogoutPage.vue"), // just need something here for TS, but guard always redirects }, { path: "/oops", name: "oops", meta: { public: true }, component: () => import("@/pages/OopsPage.vue"), }, ...(isDevMode ? [ // svg debug page, see all icons and svgs in the system in one place { path: "/w/:workspacePk/svg", name: "svg", meta: { public: true }, component: () => import("@/pages/DebugPage.vue"), }, ] : []), // 404 { path: "/:catchAll(.*)", meta: { public: true }, component: () => import("@/pages/NotFound.vue"), }, ]; const router = createRouter({ history: createWebHistory(), routes, }); router.beforeEach((to, _from) => { // check if meta info for route (or parent) requires auth or not // NOTE - this will not support a public parent with private children if (!to.matched.some((route) => route.meta.public)) { // check in auth store and redirect to login page if not logged in const authStore = useAuthStore(); if (!authStore.userIsLoggedIn) { const workspaceId = to.fullPath.match(/^\/(n|w)\/(?<workspaceId>\w*)\//) ?.groups?.workspaceId; return { name: "login", ...(to.fullPath !== "/" && { query: { redirect: to.fullPath, workspaceId, }, }), }; } } return true; }); // set current route in the pinia store // which is useful so we can set the currently selected workspace/change set from it router.beforeResolve((to) => { const routerStore = useRouterStore(); // setting the route we intend to navigate to routerStore.currentRoute = to; }); router.afterEach((to) => { let name = "unknown"; try { // NOTE: the `matched` array is least specific to most specific, so the one you want is the last one const _name = to.matched[to.matched.length - 1]?.name?.toString(); if (_name) name = _name; } catch (e) { // eslint-disable-next-line no-console console.error("can't find name in matched route", e); } try { pushBreadcrumb(to.path, name, { ...to.params }, { ...to.query } as query); } catch (e) { // eslint-disable-next-line no-console console.error("can't push breadcrumb", e); } nextTick(() => { posthog.capture("$pageview", { $current_url: to.fullPath, }); }); }); export default router;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server