From 714abd71789cf9abf58d1fb5f7765332a3069141 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Sat, 16 May 2026 09:30:33 +0200 Subject: [PATCH] feat(router): mount pages-v2 at /v2/* with v2- name prefix Adds a second routesFolder (src/pages-v2 -> /v2/) and extends getRouteName so v2 routes get a v2- NAME prefix, preventing collisions with same-named v1 pages. getPascalCaseRouteName already folds the v2/ URL segment into the base name, so the leading v2- is stripped before v2RouteName re-adds the canonical prefix (avoids v2-v2-dashboard). Includes the regenerated typed-router.d.ts and a boot-proof pages-v2/dashboard.vue placeholder. Co-Authored-By: Claude Opus 4.7 --- apps/app/src/pages-v2/dashboard.vue | 9 ++++++++ apps/app/typed-router.d.ts | 1 + apps/app/vite.config.ts | 34 ++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 apps/app/src/pages-v2/dashboard.vue diff --git a/apps/app/src/pages-v2/dashboard.vue b/apps/app/src/pages-v2/dashboard.vue new file mode 100644 index 00000000..4a82305b --- /dev/null +++ b/apps/app/src/pages-v2/dashboard.vue @@ -0,0 +1,9 @@ + + + diff --git a/apps/app/typed-router.d.ts b/apps/app/typed-router.d.ts index 32b7549d..0126b155 100644 --- a/apps/app/typed-router.d.ts +++ b/apps/app/typed-router.d.ts @@ -63,6 +63,7 @@ declare module 'vue-router/auto-routes' { 'register-success': RouteRecordInfo<'register-success', '/register/success', Record, Record>, 'reset-password': RouteRecordInfo<'reset-password', '/reset-password', Record, Record>, 'select-organisation': RouteRecordInfo<'select-organisation', '/select-organisation', Record, Record>, + 'v2-dashboard': RouteRecordInfo<'v2-dashboard', '/v2/dashboard', Record, Record>, 'verify-email-change': RouteRecordInfo<'verify-email-change', '/verify-email-change', Record, Record>, } } diff --git a/apps/app/vite.config.ts b/apps/app/vite.config.ts index 26b954d6..9030c602 100644 --- a/apps/app/vite.config.ts +++ b/apps/app/vite.config.ts @@ -14,6 +14,7 @@ import MetaLayouts from 'vite-plugin-vue-meta-layouts' import vuetify from 'vite-plugin-vuetify' import tailwindcss from '@tailwindcss/vite' import svgLoader from 'vite-svg-loader' +import { v2RouteName } from './src/plugins/1.router/v2RouteName' // https://vitejs.dev/config/ export default defineConfig({ @@ -21,11 +22,42 @@ export default defineConfig({ // Docs: https://github.com/posva/unplugin-vue-router // ℹ️ This plugin should be placed before vue plugin VueRouter({ + // Parallel /v2/* tree (RFC-WS-GUI-REDESIGN AD-G1). The second + // routesFolder prefixes every v2 URL with /v2/; v2RouteName then + // prefixes the route NAME with `v2-` so file-name twins across + // pages/ and pages-v2/ cannot collide. Reverted at final cutover. + routesFolder: [ + { src: 'src/pages' }, + { src: 'src/pages-v2', path: 'v2/' }, + ], getRouteName: routeNode => { // Convert pascal case to kebab case - return getPascalCaseRouteName(routeNode) + const raw = getPascalCaseRouteName(routeNode) .replace(/([a-z\d])([A-Z])/g, '$1-$2') .toLowerCase() + + // Defensive path read: unplugin-vue-router 0.8.8 TreeNode exposes + // `.fullPath`; fall back to `.value.path` then '' so a future + // plugin bump can't silently drop the v2- prefix. Step 5 below + // empirically verifies the emitted name. + const nodePath + = (routeNode.fullPath + ?? routeNode.value?.path + ?? '') as string + + // getPascalCaseRouteName includes the 'v2' segment from the URL + // path prefix set by routesFolder (e.g. 'v2/dashboard' → 'v2-dashboard'). + // Strip that prefix before v2RouteName re-adds the canonical `v2-` + // so we get 'v2-dashboard' not 'v2-v2-dashboard'. + const isV2 + = nodePath === '/v2' + || nodePath === 'v2' + || nodePath.startsWith('/v2/') + || nodePath.startsWith('v2/') + + const base = isV2 && raw.startsWith('v2-') ? raw.slice(3) : raw + + return v2RouteName(base, nodePath) }, }), vue(),