Skip to content
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

definePageMeta is not aware of augmented RouteMeta types #97

Closed
luc122c opened this issue Jun 5, 2023 · 3 comments
Closed

definePageMeta is not aware of augmented RouteMeta types #97

luc122c opened this issue Jun 5, 2023 · 3 comments

Comments

@luc122c
Copy link

luc122c commented Jun 5, 2023

Describe the bug
When augmenting the types of RouteMeta, this type information is not available in definePageMeta. I have created a minimal example here: https://stackblitz.com/edit/nuxt-typed-router-issue?file=middleware%2Froles.global.ts

In this example, we want to use global middleware to restrict page access based on a user's role. To do this, we define the required roles using definePageMeta, and compare this to the current user's role.

First, in our middleware (middleware/roles.global.ts) we augment the type RouteMeta to define the possible options:

declare module 'vue-router' {
  interface RouteMeta {
    allowedRoles?: 'admin' | 'user';
  }
}

Next, we pull the user data; in this case:

const user = {
  name: 'Mr Test',
  role: 'admin',
};

Then, allow access if the user role matches the allowed role

const allowedRoles = to.meta.allowedRoles;
//       ^?  const allowedRoles: 'admin' | 'user' | undefined
if (allowedRoles === undefined || allowedRoles === user.role) return;

Note that this comparison is type safe:

 if (allowedRoles === undefined || allowedRoles === 0) return;
 //  ERROR: This comparison appears to be unintentional because the types 'string' and 'number' have no overlap.

To protect a page, we can place the following code in a script setup block:

definePageMeta({
  allowedRoles: 'admin',
});

However, this is NOT type safe:

definePageMeta({
  allowedRoles: 0, // No type error, but fails at runtime.
});

Expected behavior
definePageMeta should pull in the types from RouteMeta

Environnement infos

Example Environment

https://stackblitz.com/edit/nuxt-typed-router-issue?file=pages%2Fadmin.vue,pages%2Fuser.vue,middleware%2Froles.global.ts

------------------------------
- Operating System: Linux
- Node Version:     v16.14.2
- Nuxt Version:     3.5.2
- Nitro Version:    2.4.1
- Package Manager:  npm@7.17.0
- Builder:          vite
- User Config:      modules
- Runtime Modules:  nuxt-typed-router@3.2.2
- Build Modules:    -
------------------------------

Your nuxt.config.ts

export default defineNuxtConfig({
  modules: ['nuxt-typed-router'],
});

Related: #79

@victorgarciaesgi
Copy link
Owner

Hi! Nuxt do not use RouteMeta but PageMeta, you have to augment both of them to have typings :)

@luc122c
Copy link
Author

luc122c commented Jun 7, 2023

Thanks for your reply! :) I have tried the following code in the linked Stackblitz:

declare module 'vue-router' {
  interface RouteMeta {
    allowedRoles?: 'admin' | 'user';
  }
}

declare module 'nuxt' {
  interface PageMeta {
    allowedRoles?: 'admin' | 'user';
  }
}

However, definePageMeta still seems to be inferring the type from the value?

definePageMeta({
  allowedRoles: 0,
  //  ^? (propery) allowedRoles: number 
});

@victorgarciaesgi
Copy link
Owner

It's a little tricky, the way we do it at my company is like this:

declare module 'nuxt/dist/pages/runtime/composables' {
    interface PageMeta {
   // stuff
   }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants