Skip to content

Instantly share code, notes, and snippets.

@alveshelio
Last active February 25, 2023 06:26
Show Gist options
  • Save alveshelio/5d04ad7f3bf303b5e823ac2ad60b2a9a to your computer and use it in GitHub Desktop.
Save alveshelio/5d04ad7f3bf303b5e823ac2ad60b2a9a to your computer and use it in GitHub Desktop.
import { Authorizer } from '@authorizerdev/authorizer-js';
import { createContext, createEffect, createMemo, onCleanup, useContext } from 'solid-js';
import type { ParentComponent } from 'solid-js';
import { createStore } from 'solid-js/store';
import type { User, AuthToken } from '@authorizerdev/authorizer-js';
import type { Context, AuthorizerState } from '@/types';
const AuthorizerContext = createContext<Context>([
{
config: {
...
},
user: null,
token: null,
loading: false,
},
{
setLoading: () => {},
setToken: () => {},
setUser: () => {},
setAuthData: () => {},
authorizer: new Authorizer({
authorizerURL: 'http://localhost:8080',
redirectURL: 'http://localhost:8080',
clientID: '',
}),
logout: async () => {},
},
]);
type AuthorizerProviderProps = {
authorizerURL: string;
redirectURL: string;
clientID: string;
onStateChangeCallback?: (stateData: AuthorizerState) => void;
};
export const AuthorizerProvider: ParentComponent<AuthorizerProviderProps> = (props) => {
const [state, setState] = createStore<AuthorizerState>({
user: null,
token: null,
loading: false,
config: {
...
},
});
const authorizer = createMemo(
() =>
new Authorizer({
authorizerURL: props.authorizerURL,
redirectURL: props.redirectURL,
clientID: props.clientID,
})
);
let interval: NodeJS.Timeout | null = null;
const getToken = async () => {
setState('loading', true);
const metaRes = await authorizer().getMetaData();
try {
const res = await authorizer().getSession();
if (res.access_token && res.user) {
setState((prev) => ({
...prev,
token: {
...
},
user: res.user,
}));
if (interval) {
clearInterval(interval);
}
interval = setInterval(() => {
getToken();
}, res.expires_in * 1000);
} else {
setState((prev) => ({ ...prev, user: null, token: null }));
}
} catch (e) {
setState((prev) => ({ ...prev, user: null, token: null }));
} finally {
setState('config', (config) => ({ ...config, ...metaRes }));
setState('loading', false);
}
};
createEffect(() => {
if (props.onStateChangeCallback) {
props.onStateChangeCallback(state);
}
});
const setLoading = (loading: boolean) => {
setState('loading', loading);
};
const handleTokenChange = (token: AuthToken | null) => {
setState('token', token);
if (token?.access_token) {
if (interval) {
clearInterval(interval);
}
interval = setInterval(() => {
getToken();
}, token.expires_in * 1000);
}
};
const setUser = (user: User | null) => {
setState('user', user);
};
const setAuthData = (data: AuthorizerState) => {
setState(data);
};
const logout = async () => {
setState('loading', false);
setState('user', null);
};
createEffect(() => {
getToken();
});
onCleanup(() => {
if (interval) {
clearInterval(interval);
}
});
return (
<AuthorizerContext.Provider
value={[
state,
{
setUser,
setLoading,
setToken: handleTokenChange,
setAuthData,
authorizer: authorizer(),
logout,
},
]}
>
{props.children}
</AuthorizerContext.Provider>
);
};
export const getAuthorizer = () => useContext(AuthorizerContext);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment