Skip to content

Commit

Permalink
docs(tutorial): Adds more TS hints in the toturial (#6115)
Browse files Browse the repository at this point in the history
* docs(tutorial): Adds more TS hints in the toturial

* Simplify the diff

* edits

* Apply suggestions from code review

Co-authored-by: Dominic Saadi <[email protected]>
  • Loading branch information
dac09 and jtoar authored Aug 9, 2022
1 parent e40ba15 commit eecfaa4
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 0 deletions.
18 changes: 18 additions & 0 deletions docs/docs/tutorial/chapter2/cells.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,24 @@ export const Success = ({ posts }: CellSuccessProps<ArticlesQuery>) => {
</TabItem>
</Tabs>

<ShowForTs>

:::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.

:::

</ShowForTs>

Let's plug this cell into our `HomePage` and see what happens:

<Tabs groupId="js-ts">
Expand Down
60 changes: 60 additions & 0 deletions docs/docs/tutorial/chapter7/rbac.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,66 @@ export const getCurrentUser = async (session) => {
</TabItem>
</Tabs>
<ShowForTs>
### 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
}
```
</ShowForTs>
### Restricting Access via Routes
The easiest way to prevent access to an entire URL is via the Router. The `<Private>` component takes a prop `roles` in which you can give a list of only those role(s) that should have access:
Expand Down
18 changes: 18 additions & 0 deletions docs/versioned_docs/version-2.2/tutorial/chapter2/cells.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,24 @@ export const Success = ({ posts }: CellSuccessProps<ArticlesQuery>) => {
</TabItem>
</Tabs>

<ShowForTs>

:::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.

:::

</ShowForTs>

Let's plug this cell into our `HomePage` and see what happens:

<Tabs groupId="js-ts">
Expand Down
60 changes: 60 additions & 0 deletions docs/versioned_docs/version-2.2/tutorial/chapter7/rbac.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,66 @@ export const getCurrentUser = async (session) => {
</TabItem>
</Tabs>
<ShowForTs>
### 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
}
```
</ShowForTs>
### Restricting Access via Routes
The easiest way to prevent access to an entire URL is via the Router. The `<Private>` component takes a prop `roles` in which you can give a list of only those role(s) that should have access:
Expand Down

0 comments on commit eecfaa4

Please sign in to comment.