Skip to content

Commit

Permalink
[Router][TS] Auto-complete route names for unauthenticated prop (#11756)
Browse files Browse the repository at this point in the history
Co-authored-by: Tobbe Lundberg <tobbe@tlundberg.com>
  • Loading branch information
Philzen and Tobbe authored Dec 11, 2024
1 parent 74c3933 commit 6cfc992
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 21 deletions.
8 changes: 8 additions & 0 deletions .changesets/11756.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- [Router][TS] Auto-complete route names for unauthenticated prop (#11756) by @Philzen

- auto-suggests available route names
- will highlight invalid values

This depends on type generation, so either you'll have to run `yarn rw g types` manually, or you'll have to have the dev server running (which regenerates types when required).

This PR is a little breaking, b/c the `<Set>`s generic typing has changed and also the `WrapperType<P>` type has been removed.
35 changes: 14 additions & 21 deletions packages/router/src/Set.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import type { ReactElement, ReactNode } from 'react'
import React from 'react'

export type WrapperType<WTProps> = (
props: Omit<WTProps, 'wrap' | 'children'> & {
children: ReactNode
},
) => ReactElement | null
import type { routes } from '@redwoodjs/router'

type SetProps<P> = P & {
type SetProps<P> = (P extends React.FC ? React.ComponentProps<P> : unknown) & {
/**
* P is the interface for the props that are forwarded to the wrapper
* components. TypeScript will most likely infer this for you, but if you
* need to you can specify it yourself in your JSX like so:
* <Set<{theme: string}> wrap={ThemableLayout} theme="dark">
* A react component that the children of the Set will be wrapped
* in (typically a Layout component)
*/
wrap?: WrapperType<P> | WrapperType<P>[]
wrap?: P | P[]
/**
*`Routes` nested in a `<Set>` with `private` specified require
* authentication. When a user is not authenticated and attempts to visit
Expand All @@ -28,7 +22,7 @@ type SetProps<P> = P & {
*
* @deprecated Please use `<PrivateSet>` instead and specify this prop there
*/
unauthenticated?: string
unauthenticated?: keyof typeof routes
/**
* Route is permitted when authenticated and user has any of the provided
* roles such as "admin" or ["admin", "editor"]
Expand All @@ -43,22 +37,18 @@ type SetProps<P> = P & {
}

/**
* TypeScript will often infer the type of the props you can forward to the
* wrappers for you, but if you need to you can specify it yourself in your
* JSX like so:
* <Set<{theme: string}> wrap={ThemeableLayout} theme="dark">
* A set containing public `<Route />`s
*/
export function Set<WrapperProps>(props: SetProps<WrapperProps>) {
// @MARK: Virtual Component, this is actually never rendered
// See analyzeRoutes in utils.tsx, inside the isSetNode block
return <>{props.children}</>
}

type PrivateSetProps<P> = P &
Omit<SetProps<P>, 'private' | 'unauthenticated'> & {
/** The page name where a user will be redirected when not authenticated */
unauthenticated: string
}
type PrivateSetProps<P> = Omit<SetProps<P>, 'private' | 'unauthenticated'> & {
/** The page name where a user will be redirected when not authenticated */
unauthenticated: keyof typeof routes
}

/** @deprecated Please use `<PrivateSet>` instead */
export function Private<WrapperProps>(props: PrivateSetProps<WrapperProps>) {
Expand All @@ -67,6 +57,9 @@ export function Private<WrapperProps>(props: PrivateSetProps<WrapperProps>) {
return <>{props.children}</>
}

/**
* A set containing private `<Route />`s that require authentication to access
*/
export function PrivateSet<WrapperProps>(props: PrivateSetProps<WrapperProps>) {
// @MARK Virtual Component, this is actually never rendered
// See analyzeRoutes in utils.tsx, inside the isSetNode block
Expand Down

0 comments on commit 6cfc992

Please sign in to comment.