diff --git a/docs/docs/tutorial/chapter2/cells.md b/docs/docs/tutorial/chapter2/cells.md index 9d4b16f26109..61887845dda8 100644 --- a/docs/docs/tutorial/chapter2/cells.md +++ b/docs/docs/tutorial/chapter2/cells.md @@ -318,6 +318,24 @@ export const Success = ({ posts }: CellSuccessProps) => { + + +:::tip Using generated types + +At this point, you might see an error in your Cell while trying to import from `types/graphql`: "The type ArticlesQuery does not exist" + +When you have the dev server (via `yarn rw dev`) running, the CLI watches files for changes and triggers type generation automatically, but you can trigger it manually too by running: + +```bash +yarn rw g types +``` + +This looks at your Cell's `QUERY` and—as long as it's valid—tries to automatically create a TypeScript type for you to use in your code. + +::: + + + Let's plug this cell into our `HomePage` and see what happens: diff --git a/docs/docs/tutorial/chapter7/rbac.md b/docs/docs/tutorial/chapter7/rbac.md index 3d90bd0634c2..f20a4044dbeb 100644 --- a/docs/docs/tutorial/chapter7/rbac.md +++ b/docs/docs/tutorial/chapter7/rbac.md @@ -96,6 +96,66 @@ export const getCurrentUser = async (session) => { + + +### Fixing the hasRole function + +At this point, you might notice an error in your `api/src/lib/auth.ts` file, in the `hasRole` function. TypeScript is trying to help you here, by highlighting that roles can never be an array of strings: + +```ts title="api/src/lib/auth.ts" +export const hasRole = (roles: AllowedRoles): boolean => { + + // ... + + } else if (Array.isArray(currentUserRoles)) { + // 👇 TypeScript will now be telling you 'some' doesn't exist on type never: + // highlight-next-line + return currentUserRoles?.some((allowedRole) => roles === allowedRole) + } + } + ``` + +This is because we now know that the type of `currentUser.roles` is a `string` based on the type being returned from Prisma. So you can safely remove the block of code where it's checking if roles is an array: + +```diff title="api/src/lib/auth.ts" +export const hasRole = (roles: AllowedRoles): boolean => { + if (!isAuthenticated()) { + return false + } + + const currentUserRoles = context.currentUser?.roles + + if (typeof roles === 'string') { + if (typeof currentUserRoles === 'string') { + // roles to check is a string, currentUser.roles is a string + return currentUserRoles === roles +- } else if (Array.isArray(currentUserRoles)) { +- // roles to check is a string, currentUser.roles is an array +- return currentUserRoles?.some((allowedRole) => roles === allowedRole) + } + } + + if (Array.isArray(roles)) { + if (Array.isArray(currentUserRoles)) { + // roles to check is an array, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => + roles.includes(allowedRole) + ) + } else if (typeof context?.currentUser?.roles === 'string') { + // roles to check is an array, currentUser.roles is a string + return roles.some( + (allowedRole) => context.currentUser?.roles === allowedRole + ) + } + } + + // roles not found + return false +} +``` + + + ### Restricting Access via Routes The easiest way to prevent access to an entire URL is via the Router. The `` component takes a prop `roles` in which you can give a list of only those role(s) that should have access: diff --git a/docs/versioned_docs/version-2.2/tutorial/chapter2/cells.md b/docs/versioned_docs/version-2.2/tutorial/chapter2/cells.md index 2f2bdd506db2..3a66444461a0 100644 --- a/docs/versioned_docs/version-2.2/tutorial/chapter2/cells.md +++ b/docs/versioned_docs/version-2.2/tutorial/chapter2/cells.md @@ -318,6 +318,24 @@ export const Success = ({ posts }: CellSuccessProps) => { + + +:::tip Using generated types + +At this point, you might see an error in your Cell while trying to import from `types/graphql`: "The type ArticlesQuery does not exist" + +When you have the dev server (via `yarn rw dev`) running, the CLI watches files for changes and triggers type generation automatically, but you can trigger it manually too by running: + +```bash +yarn rw g types +``` + +This looks at your Cell's `QUERY` and—as long as it's valid—tries to automatically create a TypeScript type for you to use in your code. + +::: + + + Let's plug this cell into our `HomePage` and see what happens: diff --git a/docs/versioned_docs/version-2.2/tutorial/chapter7/rbac.md b/docs/versioned_docs/version-2.2/tutorial/chapter7/rbac.md index 3d90bd0634c2..f20a4044dbeb 100644 --- a/docs/versioned_docs/version-2.2/tutorial/chapter7/rbac.md +++ b/docs/versioned_docs/version-2.2/tutorial/chapter7/rbac.md @@ -96,6 +96,66 @@ export const getCurrentUser = async (session) => { + + +### Fixing the hasRole function + +At this point, you might notice an error in your `api/src/lib/auth.ts` file, in the `hasRole` function. TypeScript is trying to help you here, by highlighting that roles can never be an array of strings: + +```ts title="api/src/lib/auth.ts" +export const hasRole = (roles: AllowedRoles): boolean => { + + // ... + + } else if (Array.isArray(currentUserRoles)) { + // 👇 TypeScript will now be telling you 'some' doesn't exist on type never: + // highlight-next-line + return currentUserRoles?.some((allowedRole) => roles === allowedRole) + } + } + ``` + +This is because we now know that the type of `currentUser.roles` is a `string` based on the type being returned from Prisma. So you can safely remove the block of code where it's checking if roles is an array: + +```diff title="api/src/lib/auth.ts" +export const hasRole = (roles: AllowedRoles): boolean => { + if (!isAuthenticated()) { + return false + } + + const currentUserRoles = context.currentUser?.roles + + if (typeof roles === 'string') { + if (typeof currentUserRoles === 'string') { + // roles to check is a string, currentUser.roles is a string + return currentUserRoles === roles +- } else if (Array.isArray(currentUserRoles)) { +- // roles to check is a string, currentUser.roles is an array +- return currentUserRoles?.some((allowedRole) => roles === allowedRole) + } + } + + if (Array.isArray(roles)) { + if (Array.isArray(currentUserRoles)) { + // roles to check is an array, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => + roles.includes(allowedRole) + ) + } else if (typeof context?.currentUser?.roles === 'string') { + // roles to check is an array, currentUser.roles is a string + return roles.some( + (allowedRole) => context.currentUser?.roles === allowedRole + ) + } + } + + // roles not found + return false +} +``` + + + ### Restricting Access via Routes The easiest way to prevent access to an entire URL is via the Router. The `` component takes a prop `roles` in which you can give a list of only those role(s) that should have access: