-
-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
callback to allow manipulating generated routes #43
Comments
Do you want access to the addPage, updatePage, removePage functions that exists in context.ts? What kind of manipulations do you need to do? Is it to create routes based on files located else where or are they going to be non readable files? Since right now, these functions read from the file, they would need some changes if this isn't enough Edit: this is already possible with
|
Currently we use Per-route callbackWe use it to simplify our For example we put common well-known metadata at the top level and it's moved to the <route lang="yaml">
title: Open tickets
auth: Operators
</route> Another example is defining some macros, where a simple property or value is expanded/transformed into a more complex This is just about convenience, of course we could write the Route table callbackWe use this to remove routes at build-time. Our source code is actually deployed as multiple distinct applications that have some shared, and some app-specific modules. So our pages look like this: <route lang="yaml">
title: Invoices
app: Accounting
</route> The routes callback drops pages whose |
Do you parse this yourselves in a custom plugin? Right now you can extend routes at runtime with https://github.com/posva/unplugin-vue-router#extendroutes but this one should be built time. It wouldn't receive an array though, it would receive a Tree, so a bit low level I think but at the same time it reflects much better the routing structure. I think that with both functions, it should cover both cases. In the end, having the callback to modify just one route is convenience or more than that?
Real nice! |
All the parsing is done by
I don't see a situation where there's something you couldn't do by iterating a modifying the complete route table. It also does less work in case of HMR. You only get called for the routes that have been modified, whereas otherwise you'd have to go through the whole routing table (and you wouldn't know which routes are already modified and which aren't...). |
I have a different use case that is similar. I use the vite-plugin-pages onRoutesGenerated build time function that uses the routes array to parse the actual files and generate metadata for the routes and generate some index files. I think most of the other functionality that I use in their extendRoute build option I could move to the extendRoutes runtime option, but I do need some sort of build time function on the list of routes before I can convert over. |
One of the use-cases we have for using a build-time It would be super handy to have build-time access to the generated routes (or each individual route) for this use-case. |
I published a new version with an experimental I think that to make this better, it would be useful to have examples of your current |
Thanks @posva! You're a legend! Here's a gist with an example of how I am using the https://gist.github.com/andrewcourtice/748a6cb52e75b58a63727d712bb3b817 One of the pain points of the pages plugin Thanks again 😄 |
I see. The vite-plugin-pages-sitemap will require a different plugin as that one relies on the array of routes in the format of vite-plugin-pages and this format is different but everything should be available. In the current version you already have access to the absolute paths with |
@posva I don't have time right now to look at the new functions, but it's great news! To answer your request, here are functions I use in a real project with pages({
// ...most config removed for brievety...
routeBlockLang: "yaml",
extendRoute(route) {
// nav is written as a path in <route>, but it should be an array of segments:
if (route.nav) route.nav = route.nav.split("/");
// For convenience, we set meta-properties directly in <route> but they should be under `meta`
if (!route.meta) route.meta = {};
moveToMeta(route, "nav");
moveToMeta(route, "auth");
moveToMeta(route, "order");
},
onRoutesGenerated(routes) {
// We filter routes included in app at build-time, based on their `env` and current build "mode" (basically target app).
routes = routes.filter(r => !r.env || r.env === mode);
// Hack to read an automatically generated list of roles (auth/security), used in loop below.
const rolesTs = readFileSync("./Services/roles.ts", "utf8");
const roles = new Map(
Array.from(rolesTs.matchAll(/^\s*(\w+)\s*=\s*"([^"]+)"/gm), r => [
r[1],
r[2],
]),
);
for (const r of routes) {
// Remove from runtime properties that were only required for build-time filtering above
delete r.env;
if (r.meta?.auth) {
const roleValue = roles.get(r.meta.auth);
// Validate role exists (no typo, <route> is not type checked)
if (!roleValue)
logger.warn(`Unknown auth ${r.meta.auth} in route ${r.meta.nav}`);
// Translate string into role id
r.meta.auth = roleValue;
}
}
return routes;
},
}), |
Thanks for the feedback. I think this one should be easy to migrate: VueRouter({
// ...most config removed for brievety...
routeBlockLang: 'yaml',
extendRoute(route) {
// TODO: probably let user to access the overrides directly with a type override? or host it somewhere
const overrides: Record<string, unknown> = route.node.value
.overrides as any
// We filter routes included in app at build-time, based on their `env` and current build "mode" (basically target app).
if (overrides.env !== mode) {
// also removes the children
route.delete()
return
// Another possibility to implement this would be to change the `exclude` option depending on the mode but this only work if pages are organized in folders.
}
if (overrides.nav) {
// nav is written as a path in <route>, but it should be an array of segments:
route.addToMeta({ nav: overrides.nav.split('/') })
}
// For convenience, we set meta-properties directly in <route> but they should be under `meta`
route.addToMeta({
auth: overrides.auth,
order: overrides.order,
})
},
beforeWriteFiles(routes) {
// Hack to read an automatically generated list of roles (auth/security), used in loop below.
const rolesTs = readFileSync('./Services/roles.ts', 'utf8')
const roles = new Map(
Array.from(rolesTs.matchAll(/^\s*(\w+)\s*=\s*"([^"]+)"/gm), (r) => [
r[1],
r[2],
])
)
for (const r of routes) {
if (r.meta?.auth) {
const roleValue = roles.get(r.meta.auth)
// Validate role exists (no typo, <route> is not type checked)
if (!roleValue)
logger.warn(`Unknown auth ${r.meta.auth} in route ${r.meta.nav}`)
// Translate string into role id
r.addToMeta({ auth: roleValue })
}
}
},
}), There are some improvements to make like allow access to the overrides without using the private |
I'm adding here our use case: ContextWe are using Our issueWe have pages that are available on multiple "product"s, but that use the same component. For example a list of transport lines is available on:
Behind this:
What we tried, to define a single page for those 3 urls:
Our needBeing able to define multiple routes for the same page component, at build time.
<script lang="ts" setup>
definePage({
name: 'PUrbanLineList',
path: '/p_urban/p_urban_lines/index/:networkId',
meta: {
acl: 'p_urban_list_lines',
icon: 'alt_route',
},
})
</script>
<template>
<LinesList />
</template> Possible solutions
definePage([
{
name: 'MainLineList',
path: '/network/network_lines',
meta: {
acl: 'main_list_lines',
icon: 'alt_route',
},
{
name: 'PUrbanLineList',
path: '/p_urban/p_urban_lines/index/:networkId',
meta: {
acl: 'p_urban_list_lines',
icon: 'alt_route',
},
])
|
@gduliscouet-ubitransport Regarding the possible solutions, you can already use A simpler alternative is to create two different page components that render the same component |
Thank you for the response @posva !
So this is what we do today, it is just a bit messy because in our case we have to create a lot of With |
Tracking the docs updates in https://github.com/users/posva/projects/2/views/1?query=is%3Aopen+sort%3Aupdated-desc&pane=issue&itemId=64673200 @gduliscouet-ubitransport |
would be nice to pass a custom function to the unplugin that receives the scanned routes and allows manipulation, e.g. creating new routes, removing or modifying existing ones.
The text was updated successfully, but these errors were encountered: