Manual API handling
Opened this issue · 0 comments
API Handling
Handling requests to the Spotify API ourselves gives us greater flexibility to handle data received by the API.
This issue serves as a first design outline for manual API request functionality.
This issue is closely related to #10.
Design
The API is represented by a class that is accessible through a context. This means that all components that want to use API hooks need to be wrapped inside a <SpotifyWebAPI />
component. This component wraps its children in a context provider which provides the instance of the API to all children.
The class is responsible for storing API related data such as client id, scopes, etc. It does not store things like access token etc. as that is always stored in localStorage.
Auth
User authorization also needs to be handled by us. This is done through the useAuth()
hook.
It provides methods for allowing the user to grant Reactify access to their Spotify account.
useAuth()
interface useAuthReturnType {
setupAuth: (clientId: string, redirectUrl: string, scopes: string[]) => void; // Is stored in the API Class instance to be accessed by other components.
requestAuthentication: () => Promise<AuthorizationResponse>;
requestAccessToken: (authenticationCode: string) => Promise<AccessTokenResponse>;
getAccessToken: () => AccessToken | null;
logout: () => void;
}
// For convenience
interface AuthorizationResponse {
code: string;
state: string;
}
interface AccessTokenResponse {
access_token: string;
token_type: 'Bearer';
scope: string;
expires_in: number;
refresh_token: string;
}
interface AccessToken {
token: string;
expires: number;
expires_in: number;
token_type: string;
refresh_token: string;
}
API
Data is retrieved through custom hooks for each endpoint group of the Spotify Web API. E.g. useAlbums()
.
Each endpoint hook returns an object with functions to send a request to an endpoint. E.g. getAlbum(id)
.
The actual request is handled by a useFetch()
hook which handles caching, URL formatting etc.
All hooks are named after the endpoint group they handle.
Types
Generic hook structure
All hooks are of the following type:
type EndpointGroupHook = () => { retrieveDataFunction_one, retrieveDataFunction_two, ... }
Generic function structure
All functions returned by endpoint group hooks are of type:
type EndpointGroupHookFunction = (endpointParams: unknown) => {
staleData: (StaleData<ReturnType> | null),
freshData: Promise<FreshData<ReturnType>>
}
staleData
This property is returned synchronously and directly from cache to provide the component with something to render. If the cache doesn't contain any data this will be null
.
freshData
Property contains the fresh data. If the cached data is still fresh (meaning this and staleData
are equal) this will be a resolved promise. Otherwise it is a pending promise that will resolve once the data is fetched.
ReturnType
ReturnType
is the actual data like a Playlist
object, etc.
Special Hooks
use_internal_fetch()
This hook is used to create requests to the API. It handles the cache as well as URL formatting, etc.
As the name suggests this hook should only be used internally. By other API hooks that is.
use_internal_cache()
This hook is used to manage the caching behavior like automatically flushing content to disk, invalidating stale data, etc.
As the name suggests this hook should only be used internally. By other API hooks that is.
use_internal_spotifyAPIContext()
This hooks is used to get the SpotifyAPIContext. It either returns the context or throws an error if the context is undefined
which indicates that the calling hook is executed outside the <SpotifyWebAPI />
wrapper component.
As the name suggests this hook should only be used internally. By other API hooks that is.
useCache()
This hook provides functions to interact with the cache. It is indented to be used by components to clear and flush the cache.
useCurrentUser()
This hook provides simpler access to the Current User
endpoints. To be compliant with the documentation all endpoint group hooks also provide functions for their respective Current User
endpoints.