Skip to content

Commit

Permalink
feat: allow extending routes with extendRoutes
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Jun 28, 2022
1 parent 7df92b2 commit da4db97
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ VueRouter({

## Routes folder structure

By default, this plugins checks the folder at `src/routes` for any `.vue` files and generates the corresponding routing structure basing itself in the file name. This way, you no longer need to maintain a `routes` array when adding routes to your application, **instead just add the new `.vue` component to the routes folder and let this plugin do the rest!**.
By default, this plugins checks the folder at `src/routes` for any `.vue` files and generates the corresponding routing structure basing itself in the file name. This way, you no longer need to maintain a `routes` array when adding routes to your application, **instead just add the new `.vue` component to the routes folder and let this plugin do the rest!**

Let's take a look at a simple example:

Expand Down Expand Up @@ -284,6 +284,29 @@ The `RouterTyped` type gives you access to the typed version of the router insta
import type { RouterTyped } from '@vue-router'
```

## Extending existing routes

You can extend existing routes by passing an `extendRoutes` function to `createRouter()`. **This should be uses as a last resort** (or until a feature is natively available here):

```js
import { createWebHistory, createRouter } from '@vue-router'

const router = createRouter({
extendRoutes: (routes) => {
const adminRoute = routes.find((r) => r.name === '/admin')
if (!adminRoute) {
adminRoute.meta ??= {}
adminRoute.meta.requiresAuth = true
}
// completely optional since we are modifying the routes in place
return routes
},
history: createWebHistory(),
})
```
As this plugin evolves, this function should be used less and less and only become necessary in unique edge cases.
## Rationale
This project idea came from trying [to type the router directly using Typescript](https://github.com/vuejs/router/pull/1397/commits/c577998f3edaa6a1eb9474c27ab6c58f6e2d7c8a), finding out it's not fast enough to be pleasant to use and, ending up using build-based tools, taking some inspiration from other projects like:
Expand Down
17 changes: 15 additions & 2 deletions client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,20 @@ declare module '@vue-router/routes' {
}

declare module '@vue-router' {
import type { RouterOptions, Router } from 'vue-router'
import type { RouterOptions, Router, RouteRecordRaw } from 'vue-router'
export * from 'vue-router'
export function createRouter(options: Omit<RouterOptions, 'routes'>): Router

/**
* unplugin-vue-router version of `RouterOptions`.
*/
export interface _RouterOptions extends Omit<RouterOptions, 'routes'> {
/**
* Allows modifying the routes before they are passed to the router. You can modify the existing array or return a
* new one.
*
* @param routes - The routes generated by this plugin and exposed by `@vue-router/routes`
*/
extendRoutes?: (routes: RouteRecordRaw[]) => RouteRecordRaw[] | void
}
export function createRouter(options: _RouterOptions): Router
}
4 changes: 4 additions & 0 deletions playground/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { createWebHistory, createRouter } from '@vue-router'
import type { Route, RouteParams, RouteParamsRaw } from '@vue-router'

const router = createRouter({
extendRoutes: (routes) => {
routes.find((r) => r.name === 'home')!.meta = {}
return routes
},
history: createWebHistory(),
})

Expand Down
9 changes: 8 additions & 1 deletion src/core/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ declare module '@vue/runtime-core' {
`
}

// NOTE: this code needs to be generated because otherwise it doesn't go through transforms and `@vue-router/routes`
// cannot be resolved.
function generateVueRouterProxy() {
return `
import { routes } from '@vue-router/routes'
Expand All @@ -169,9 +171,14 @@ import { createRouter as _createRouter } from 'vue-router'
export * from 'vue-router'
export function createRouter(options) {
const { extendRoutes } = options
if (typeof extendRoutes === 'function') {
routes = extendRoutes(routes) || routes
}
return _createRouter({
routes,
...options,
routes,
})
}
`
Expand Down

0 comments on commit da4db97

Please sign in to comment.