From 0ea3eb8b07d1c160b52ee07f8a0db7c21c085a6c Mon Sep 17 00:00:00 2001 From: Kichiyaki Date: Sun, 7 Mar 2021 14:46:37 +0100 Subject: [PATCH] add two libs: graphql and tokenstorage --- src/config/api.ts | 2 ++ src/libs/graphql/createClient.ts | 39 ++++++++++++++++++++++++ src/libs/graphql/links/authMiddleware.ts | 17 +++++++++++ src/libs/tokenstorage/TokenStorage.ts | 29 ++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 src/config/api.ts create mode 100644 src/libs/graphql/createClient.ts create mode 100644 src/libs/graphql/links/authMiddleware.ts create mode 100644 src/libs/tokenstorage/TokenStorage.ts diff --git a/src/config/api.ts b/src/config/api.ts new file mode 100644 index 0000000..0190cf1 --- /dev/null +++ b/src/config/api.ts @@ -0,0 +1,2 @@ +export const API_URI = + process.env.REACT_APP_API_URI ?? "http://localhost:8080/graphql"; diff --git a/src/libs/graphql/createClient.ts b/src/libs/graphql/createClient.ts new file mode 100644 index 0000000..dd86adc --- /dev/null +++ b/src/libs/graphql/createClient.ts @@ -0,0 +1,39 @@ +import { + ApolloClient, + InMemoryCache, + NormalizedCacheObject, + ApolloLink, +} from "@apollo/client"; +import { createUploadLink } from "apollo-upload-client"; +import { onError } from "@apollo/client/link/error"; +import createAuthMiddleware from "./links/authMiddleware"; +import TokenStorage from "libs/tokenstorage/TokenStorage"; + +const createClient = ( + uri: string, + tokenStorage: TokenStorage +): ApolloClient => { + return new ApolloClient({ + queryDeduplication: true, + cache: new InMemoryCache(), + link: ApolloLink.from([ + createAuthMiddleware(tokenStorage), + onError(({ graphQLErrors, networkError }) => { + if (process.env.NODE_ENV === "development") { + if (graphQLErrors) + graphQLErrors.map(({ message, locations, path }) => + console.log( + `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}` + ) + ); + if (networkError) console.log(`[Network error]: ${networkError}`); + } + }), + createUploadLink({ + uri, + }), + ]), + }); +}; + +export default createClient; diff --git a/src/libs/graphql/links/authMiddleware.ts b/src/libs/graphql/links/authMiddleware.ts new file mode 100644 index 0000000..576d03f --- /dev/null +++ b/src/libs/graphql/links/authMiddleware.ts @@ -0,0 +1,17 @@ +import { ApolloLink, NextLink, Operation } from "@apollo/client"; +import TokenStorage from "libs/tokenstorage/TokenStorage"; + +const createAuthMiddleware = (tokenStorage: TokenStorage) => { + return new ApolloLink((operation: Operation, forward: NextLink) => { + if (tokenStorage.token) { + operation.setContext({ + headers: { + Authorization: "Bearer " + tokenStorage.token, + }, + }); + } + return forward(operation); + }); +}; + +export default createAuthMiddleware; diff --git a/src/libs/tokenstorage/TokenStorage.ts b/src/libs/tokenstorage/TokenStorage.ts new file mode 100644 index 0000000..20db173 --- /dev/null +++ b/src/libs/tokenstorage/TokenStorage.ts @@ -0,0 +1,29 @@ +import { isString } from "lodash"; + +export const DEFAULT_STORAGE_KEY = "token"; + +export interface TokenStorageOptions { + key?: string; +} + +export default class TokenStorage { + public key: string; + public token: string | null; + constructor({ key }: TokenStorageOptions = {}) { + this.key = isString(key) ? key : DEFAULT_STORAGE_KEY; + this.token = this.loadToken(); + } + + private loadToken() { + return localStorage.getItem(this.key); + } + + private saveToken(token: string) { + return localStorage.setItem(this.key, token); + } + + public setToken(newToken: string) { + this.token = newToken; + this.saveToken(newToken); + } +}