Skip to content

Commit

Permalink
Export more loading and error state from react-sdk (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
byn9826 authored Aug 1, 2024
1 parent 832c835 commit 300dcd6
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 92 deletions.
6 changes: 3 additions & 3 deletions admin-panel/app/Setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const AuthSetup = ({ children }: PropsWithChildren) => {

const {
isAuthenticating, isAuthenticated, acquireUserInfo,
loginRedirect, logoutRedirect, isLoading,
loginRedirect, logoutRedirect, isLoadingUserInfo, acquireUserInfoError,
} = useAuth()

const userInfo = useSignalValue(userInfoSignal)
Expand All @@ -44,7 +44,7 @@ const AuthSetup = ({ children }: PropsWithChildren) => {
[acquireUserInfo, isAuthenticated],
)

if (isAuthenticating || isLoading) {
if (isAuthenticating || isLoadingUserInfo) {
return (
<section className='flex flex-col justify-center items-center w-full h-screen'>
<Spinner size='lg' />
Expand All @@ -61,7 +61,7 @@ const AuthSetup = ({ children }: PropsWithChildren) => {
return (
<div className='w-full h-screen flex flex-col gap-8 items-center justify-center'>
<Alert color='failure'>
{t('layout.blocked')}
{acquireUserInfoError || t('layout.blocked')}
</Alert>
<Button
color='gray'
Expand Down
144 changes: 107 additions & 37 deletions docs/react-sdk.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
# React SDK

Melody Auth React SDK facilitates seamless interaction between React applications and the auth server. It silently handles authentication state management, redirect flows, token exchange, and authentication validation for you.

## Installation

```
npm install @melody-auth/react --save
```

## AuthProvider

Wrap your application inside AuthProvider component to provide the auth related context to your application components.
Expand Down Expand Up @@ -42,19 +34,6 @@ export default function RootLayout ({ children }: {
}
```

## isAuthenticating

Indicates whether the SDK is initializing and attempting to obtain the user's authentication state.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { isAuthenticating } = useAuth()
if (isAuthenticating) return <Spinner />
}
```

## isAuthenticated

Indicates if the current user is authenticated.
Expand Down Expand Up @@ -89,6 +68,30 @@ export default function Home () {
}
```

## logoutRedirect

Triggers the logout flow.

| Parameter | Type | Description | Default | Required |
|-----------|------|-------------|---------|----------|
| postLogoutRedirectUri | string | The URL to redirect users after logout | N/A | No |

```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { isAuthenticated, logoutRedirect } = useAuth()
const handleLogout = () => {
logoutRedirect({ postLogoutRedirectUri: 'http://localhost:3000/' })
}
if (isAuthenticated) {
return <Button onClick={handleLogout}>Logout</Button>
}
}
```

## acquireToken

Gets the user's accessToken, or refreshes it if expired.
Expand Down Expand Up @@ -132,39 +135,106 @@ export default function Home () {
}
```

## isLoading
## isAuthenticating

Indicates whether the SDK is fetching user info.
Indicates whether the SDK is initializing and attempting to obtain the user's authentication state.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { isLoading } = useAuth()
const { isAuthenticating } = useAuth()
if (isLoading) return <Spinner />
if (isAuthenticating) return <Spinner />
}
```

## logoutRedirect
## isLoadingToken

Triggers the logout flow.
Indicates whether the SDK is acquiring token.
```
import { useAuth } from '@melody-auth/react'
| Parameter | Type | Description | Default | Required |
|-----------|------|-------------|---------|----------|
| postLogoutRedirectUri | string | The URL to redirect users after logout | N/A | No |
export default function Home () {
const { isLoadingToken } = useAuth()
if (isLoadingToken) return <Spinner />
}
```

## isLoadingUserInfo

Indicates whether the SDK is acquiring user info.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { isAuthenticated, logoutRedirect } = useAuth()
const { isLoadingUserInfo } = useAuth()
const handleLogout = () => {
logoutRedirect({ postLogoutRedirectUri: 'http://localhost:3000/' })
}
if (isLoadingUserInfo) return <Spinner />
}
```

if (isAuthenticated) {
return <Button onClick={handleLogout}>Logout</Button>
}
## authenticationError

Indicates whether there is an authentication process related error.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { authenticationError } = useAuth()
if (authenticationError) return <Alert />
}
```

## acquireTokenError

Indicates whether there is an acquireToken process related error.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { acquireTokenError } = useAuth()
if (acquireTokenError) return <Alert />
}
```

## acquireUserInfoError

Indicates whether there is an acquireUserInfo process related error.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { acquireUserInfoError } = useAuth()
if (acquireUserInfoError) return <Alert />
}
```

## loginError

Indicates whether there is an login process related error.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { loginError } = useAuth()
if (loginError) return <Alert />
}
```

## logoutError

Indicates whether there is an login process related error.
```
import { useAuth } from '@melody-auth/react'
export default function Home () {
const { logoutError } = useAuth()
if (logoutError) return <Alert />
}
```
2 changes: 2 additions & 0 deletions react-sdk/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
src
9 changes: 9 additions & 0 deletions react-sdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# React SDK

Melody Auth React SDK facilitates seamless interaction between React applications and the melody auth server. It silently handles authentication state management, redirect flows, token exchange, and authentication validation for you.

## Installation

```
npm install @melody-auth/react --save
```
4 changes: 3 additions & 1 deletion react-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "@melody-auth/react",
"version": "0.0.1",
"main": "dist/index.js",
"dependencies": {
"web-sdk": "*"
Expand All @@ -12,6 +13,7 @@
},
"scripts": {
"build": "rm -rf ./dist && tsc --build",
"type:check": "tsc --noEmit"
"type:check": "tsc --noEmit",
"release": "rm -rf ./dist && npm run compile && npm publish"
}
}
59 changes: 51 additions & 8 deletions react-sdk/src/Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,67 @@ const reducer = (
accessTokenStorage: action.payload,
isAuthenticated: true,
isAuthenticating: false,
isLoadingToken: false,
acquireTokenError: '',
}
case 'setRefreshTokenStorage':
return {
...state,
refreshTokenStorage: action.payload,
checkedStorage: true,
}
case 'setIsAuthenticating':
return {
...state, isAuthenticating: action.payload,
}
case 'setAuthenticationError':
return {
...state,
authenticationError: action.payload,
isAuthenticating: false,
}
case 'setCheckedStorage':
return {
...state, checkedStorage: action.payload,
}
case 'setIsLoadingUserInfo':
return {
...state, isLoadingUserInfo: action.payload,
}
case 'setAcquireUserInfoError':
return {
...state,
acquireUserInfoError: action.payload,
isLoadingUserInfo: false,
}
case 'setUserInfo':
return {
...state,
userInfo: action.payload,
isLoading: false,
isLoadingUserInfo: false,
acquireUserInfoError: '',
}
case 'setIsAuthenticating':
case 'setAcquireTokenError':
return {
...state, isAuthenticating: action.payload,
...state,
acquireTokenError: action.payload,
isLoadingToken: false,
isAuthenticating: false,
}
case 'setCheckedStorage':
case 'setIsLoadingToken':
return {
...state, checkedStorage: action.payload,
...state,
isLoadingToken: true,
}
case 'setIsLoading':
case 'setLoginError':
return {
...state, isLoading: action.payload,
...state,
loginError: action.payload,
}
case 'setLogoutError':
return {
...state,
logoutError: action.payload,
}
}
}
Expand All @@ -59,13 +96,19 @@ export const AuthProvider = ({
reducer,
{
isAuthenticating: true,
authenticationError: '',
isAuthenticated: false,
isLoading: false,
config,
userInfo: null,
accessTokenStorage: null,
refreshTokenStorage: null,
checkedStorage: false,
isLoadingUserInfo: false,
acquireUserInfoError: '',
isLoadingToken: false,
acquireTokenError: '',
loginError: '',
logoutError: '',
},
)

Expand Down
15 changes: 10 additions & 5 deletions react-sdk/src/Setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
import { exchangeTokenByAuthCode } from 'web-sdk'
import { useAuth } from './useAuth'
import authContext, { AuthContext } from './context'
import {
ErrorType, handleError,
} from './utils'

const Setup = () => {
const { acquireToken } = useAuth()
Expand All @@ -24,9 +27,7 @@ const Setup = () => {
if (state.accessTokenStorage) return

if (state.refreshTokenStorage && !state.accessTokenStorage) {
acquireToken().catch(() => dispatch({
type: 'setIsAuthenticating', payload: false,
}))
acquireToken()
return
}

Expand All @@ -48,9 +49,13 @@ const Setup = () => {
})
}
})
.catch(() => {
.catch((e) => {
const msg = handleError(
e,
ErrorType.ObtainAccessToken,
)
dispatch({
type: 'setIsAuthenticating', payload: false,
type: 'setAuthenticationError', payload: msg,
})
})
}
Expand Down
Loading

0 comments on commit 300dcd6

Please sign in to comment.