publicGraphQLClient, privateGraphQLClient -> graphQLClient (#336)

* publicGraphQLClient, privateGraphQLClient -> graphQLClient

* ssr fix

---------

Co-authored-by: Igor Lobanov <igor.lobanov@onetwotrip.com>
This commit is contained in:
Igor Lobanov 2023-12-16 14:57:08 +01:00 committed by GitHub
parent d2977b9b21
commit 63494e9d04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 76 deletions

View File

@ -12,7 +12,7 @@ import {
useContext, useContext,
} from 'solid-js' } from 'solid-js'
import { resetToken, setToken } from '../graphql/privateGraphQLClient' import { resetToken, setToken } from '../graphql/graphQLClient'
import { showModal } from '../stores/ui' import { showModal } from '../stores/ui'
import { apiClient } from '../utils/apiClient' import { apiClient } from '../utils/apiClient'

View File

@ -1,23 +1,24 @@
import { ClientOptions, dedupExchange, fetchExchange, Exchange, createClient } from '@urql/core' import { ClientOptions, dedupExchange, fetchExchange, Exchange, createClient } from '@urql/core'
import { devtoolsExchange } from '@urql/devtools' import { devtoolsExchange } from '@urql/devtools'
import { isServer } from 'solid-js/web'
import { isDev, apiBaseUrl } from '../utils/config' import { isDev, apiBaseUrl } from '../utils/config'
const TOKEN_LOCAL_STORAGE_KEY = 'token'
const exchanges: Exchange[] = [dedupExchange, fetchExchange] const exchanges: Exchange[] = [dedupExchange, fetchExchange]
if (isDev) { if (isDev) {
exchanges.unshift(devtoolsExchange) exchanges.unshift(devtoolsExchange)
} }
const TOKEN_LOCAL_STORAGE_KEY = 'token'
export const getToken = (): string => { export const getToken = (): string => {
return localStorage.getItem(TOKEN_LOCAL_STORAGE_KEY) return localStorage.getItem(TOKEN_LOCAL_STORAGE_KEY)
} }
export const setToken = (token: string) => { export const setToken = (token: string) => {
if (!token) { if (!token) {
console.error('[privateGraphQLClient] setToken: token is null!') console.error('[graphQLClient] setToken: token is null!')
} }
localStorage.setItem(TOKEN_LOCAL_STORAGE_KEY, token) localStorage.setItem(TOKEN_LOCAL_STORAGE_KEY, token)
@ -32,16 +33,20 @@ const options: ClientOptions = {
maskTypename: true, maskTypename: true,
requestPolicy: 'cache-and-network', requestPolicy: 'cache-and-network',
fetchOptions: () => { fetchOptions: () => {
if (isServer) {
return {}
}
// localStorage is the source of truth for now // localStorage is the source of truth for now
// to change token call setToken, for example after login // to change token call setToken, for example after login
const token = localStorage.getItem(TOKEN_LOCAL_STORAGE_KEY) const token = getToken()
if (!token) { if (!token) {
console.error('[privateGraphQLClient] fetchOptions: token is null!') return {}
} }
const headers = { Authorization: token } const headers = { Authorization: token }
return { headers } return { headers }
}, },
exchanges, exchanges,
} }
export const privateGraphQLClient = createClient(options) export const graphQLClient = createClient(options)

View File

@ -1,20 +0,0 @@
import { ClientOptions, dedupExchange, fetchExchange, Exchange, createClient } from '@urql/core'
import { devtoolsExchange } from '@urql/devtools'
import { isDev, apiBaseUrl } from '../utils/config'
// import { cache } from './cache'
const exchanges: Exchange[] = [dedupExchange, fetchExchange] //, cache]
if (isDev) {
exchanges.unshift(devtoolsExchange)
}
const options: ClientOptions = {
url: apiBaseUrl,
maskTypename: true,
requestPolicy: 'cache-and-network',
exchanges,
}
export const publicGraphQLClient = createClient(options)

View File

@ -22,6 +22,7 @@ import type {
LoadRandomTopShoutsParams, LoadRandomTopShoutsParams,
} from '../graphql/types.gen' } from '../graphql/types.gen'
import { getToken, graphQLClient } from '../graphql/graphQLClient'
import createArticle from '../graphql/mutation/article-create' import createArticle from '../graphql/mutation/article-create'
import deleteShout from '../graphql/mutation/article-delete' import deleteShout from '../graphql/mutation/article-delete'
import updateArticle from '../graphql/mutation/article-update' import updateArticle from '../graphql/mutation/article-update'
@ -40,8 +41,6 @@ import reactionDestroy from '../graphql/mutation/reaction-destroy'
import reactionUpdate from '../graphql/mutation/reaction-update' import reactionUpdate from '../graphql/mutation/reaction-update'
import unfollowMutation from '../graphql/mutation/unfollow' import unfollowMutation from '../graphql/mutation/unfollow'
import updateProfile from '../graphql/mutation/update-profile' import updateProfile from '../graphql/mutation/update-profile'
import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient'
import { publicGraphQLClient } from '../graphql/publicGraphQLClient'
import shoutLoad from '../graphql/query/article-load' import shoutLoad from '../graphql/query/article-load'
import shoutsLoadBy from '../graphql/query/articles-load-by' import shoutsLoadBy from '../graphql/query/articles-load-by'
import articlesLoadRandomTop from '../graphql/query/articles-load-random-top' import articlesLoadRandomTop from '../graphql/query/articles-load-random-top'
@ -86,7 +85,7 @@ export class ApiError extends Error {
export const apiClient = { export const apiClient = {
authLogin: async ({ email, password }: { email: string; password: string }): Promise<AuthResult> => { authLogin: async ({ email, password }: { email: string; password: string }): Promise<AuthResult> => {
const response = await publicGraphQLClient.query(authLoginQuery, { email, password }).toPromise() const response = await graphQLClient.query(authLoginQuery, { email, password }).toPromise()
// console.debug('[api-client] authLogin', { response }) // console.debug('[api-client] authLogin', { response })
if (response.error) { if (response.error) {
if ( if (
@ -118,7 +117,7 @@ export const apiClient = {
password: string password: string
name: string name: string
}): Promise<void> => { }): Promise<void> => {
const response = await publicGraphQLClient const response = await graphQLClient
.mutation(authRegisterMutation, { email, password, name }) .mutation(authRegisterMutation, { email, password, name })
.toPromise() .toPromise()
@ -131,17 +130,17 @@ export const apiClient = {
} }
}, },
authSignOut: async () => { authSignOut: async () => {
const response = await publicGraphQLClient.query(authLogoutQuery, {}).toPromise() const response = await graphQLClient.query(authLogoutQuery, {}).toPromise()
return response.data.signOut return response.data.signOut
}, },
authCheckEmail: async ({ email }) => { authCheckEmail: async ({ email }) => {
// check if email is used // check if email is used
const response = await publicGraphQLClient.query(authCheckEmailQuery, { email }).toPromise() const response = await graphQLClient.query(authCheckEmailQuery, { email }).toPromise()
return response.data.isEmailUsed return response.data.isEmailUsed
}, },
authSendLink: async ({ email, lang, template }) => { authSendLink: async ({ email, lang, template }) => {
// send link with code on email // send link with code on email
const response = await publicGraphQLClient const response = await graphQLClient
.mutation(authSendLinkMutation, { email, lang, template }) .mutation(authSendLinkMutation, { email, lang, template })
.toPromise() .toPromise()
@ -161,7 +160,7 @@ export const apiClient = {
}, },
confirmEmail: async ({ token }: { token: string }) => { confirmEmail: async ({ token }: { token: string }) => {
// confirm email with code from link // confirm email with code from link
const response = await publicGraphQLClient.mutation(authConfirmEmailMutation, { token }).toPromise() const response = await graphQLClient.mutation(authConfirmEmailMutation, { token }).toPromise()
if (response.error) { if (response.error) {
// TODO: better error communication // TODO: better error communication
if (response.error.message === '[GraphQL] check token lifetime') { if (response.error.message === '[GraphQL] check token lifetime') {
@ -183,7 +182,7 @@ export const apiClient = {
}, },
getRandomTopics: async ({ amount }: { amount: number }) => { getRandomTopics: async ({ amount }: { amount: number }) => {
const response = await publicGraphQLClient.query(topicsRandomQuery, { amount }).toPromise() const response = await graphQLClient.query(topicsRandomQuery, { amount }).toPromise()
if (!response.data) { if (!response.data) {
console.error('[api-client] getRandomTopics', response.error) console.error('[api-client] getRandomTopics', response.error)
@ -195,11 +194,11 @@ export const apiClient = {
// subscribe // subscribe
follow: async ({ what, slug }: { what: FollowingEntity; slug: string }) => { follow: async ({ what, slug }: { what: FollowingEntity; slug: string }) => {
const response = await privateGraphQLClient.mutation(followMutation, { what, slug }).toPromise() const response = await graphQLClient.mutation(followMutation, { what, slug }).toPromise()
return response.data.follow return response.data.follow
}, },
unfollow: async ({ what, slug }: { what: FollowingEntity; slug: string }) => { unfollow: async ({ what, slug }: { what: FollowingEntity; slug: string }) => {
const response = await privateGraphQLClient.mutation(unfollowMutation, { what, slug }).toPromise() const response = await graphQLClient.mutation(unfollowMutation, { what, slug }).toPromise()
return response.data.unfollow return response.data.unfollow
}, },
@ -209,7 +208,7 @@ export const apiClient = {
} }
// renew session with auth token in header (!) // renew session with auth token in header (!)
const response = await privateGraphQLClient.mutation(mySession, {}).toPromise() const response = await graphQLClient.mutation(mySession, {}).toPromise()
if (response.error) { if (response.error) {
throw new ApiError('unknown', response.error.message) throw new ApiError('unknown', response.error.message)
@ -222,37 +221,37 @@ export const apiClient = {
return response.data.getSession return response.data.getSession
}, },
getAllTopics: async () => { getAllTopics: async () => {
const response = await publicGraphQLClient.query(topicsAll, {}).toPromise() const response = await graphQLClient.query(topicsAll, {}).toPromise()
if (response.error) { if (response.error) {
console.debug('[api-client] getAllTopics', response.error) console.debug('[api-client] getAllTopics', response.error)
} }
return response.data.topicsAll return response.data.topicsAll
}, },
getAllAuthors: async () => { getAllAuthors: async () => {
const response = await publicGraphQLClient.query(authorsAll, {}).toPromise() const response = await graphQLClient.query(authorsAll, {}).toPromise()
if (response.error) { if (response.error) {
console.debug('[api-client] getAllAuthors', response.error) console.debug('[api-client] getAllAuthors', response.error)
} }
return response.data.authorsAll return response.data.authorsAll
}, },
getAuthor: async ({ slug }: { slug: string }): Promise<Author> => { getAuthor: async ({ slug }: { slug: string }): Promise<Author> => {
const response = await publicGraphQLClient.query(authorBySlug, { slug }).toPromise() const response = await graphQLClient.query(authorBySlug, { slug }).toPromise()
return response.data.getAuthor return response.data.getAuthor
}, },
getAuthorFollowers: async ({ slug }: { slug: string }): Promise<Author[]> => { getAuthorFollowers: async ({ slug }: { slug: string }): Promise<Author[]> => {
const response = await publicGraphQLClient.query(userSubscribers, { slug }).toPromise() const response = await graphQLClient.query(userSubscribers, { slug }).toPromise()
return response.data.userFollowers return response.data.userFollowers
}, },
getAuthorFollowingUsers: async ({ slug }: { slug: string }): Promise<Author[]> => { getAuthorFollowingUsers: async ({ slug }: { slug: string }): Promise<Author[]> => {
const response = await publicGraphQLClient.query(userFollowedAuthors, { slug }).toPromise() const response = await graphQLClient.query(userFollowedAuthors, { slug }).toPromise()
return response.data.userFollowedAuthors return response.data.userFollowedAuthors
}, },
getAuthorFollowingTopics: async ({ slug }: { slug: string }): Promise<Topic[]> => { getAuthorFollowingTopics: async ({ slug }: { slug: string }): Promise<Topic[]> => {
const response = await publicGraphQLClient.query(userFollowedTopics, { slug }).toPromise() const response = await graphQLClient.query(userFollowedTopics, { slug }).toPromise()
return response.data.userFollowedTopics return response.data.userFollowedTopics
}, },
updateProfile: async (input: ProfileInput) => { updateProfile: async (input: ProfileInput) => {
const response = await privateGraphQLClient.mutation(updateProfile, { profile: input }).toPromise() const response = await graphQLClient.mutation(updateProfile, { profile: input }).toPromise()
if (response.error) { if (response.error) {
if ( if (
response.error.message.includes('duplicate key value violates unique constraint "user_slug_key"') response.error.message.includes('duplicate key value violates unique constraint "user_slug_key"')
@ -265,11 +264,11 @@ export const apiClient = {
return response.data.updateProfile return response.data.updateProfile
}, },
getTopic: async ({ slug }: { slug: string }): Promise<Topic> => { getTopic: async ({ slug }: { slug: string }): Promise<Topic> => {
const response = await publicGraphQLClient.query(topicBySlug, { slug }).toPromise() const response = await graphQLClient.query(topicBySlug, { slug }).toPromise()
return response.data.getTopic return response.data.getTopic
}, },
createArticle: async ({ article }: { article: ShoutInput }): Promise<Shout> => { createArticle: async ({ article }: { article: ShoutInput }): Promise<Shout> => {
const response = await privateGraphQLClient.mutation(createArticle, { shout: article }).toPromise() const response = await graphQLClient.mutation(createArticle, { shout: article }).toPromise()
return response.data.createShout.shout return response.data.createShout.shout
}, },
updateArticle: async ({ updateArticle: async ({
@ -281,57 +280,55 @@ export const apiClient = {
shoutInput?: ShoutInput shoutInput?: ShoutInput
publish: boolean publish: boolean
}): Promise<Shout> => { }): Promise<Shout> => {
const response = await privateGraphQLClient const response = await graphQLClient
.mutation(updateArticle, { shoutId, shoutInput, publish }) .mutation(updateArticle, { shoutId, shoutInput, publish })
.toPromise() .toPromise()
console.debug('[updateArticle]:', response.data) console.debug('[updateArticle]:', response.data)
return response.data.updateShout.shout return response.data.updateShout.shout
}, },
deleteShout: async ({ shoutId }: { shoutId: number }): Promise<void> => { deleteShout: async ({ shoutId }: { shoutId: number }): Promise<void> => {
const response = await privateGraphQLClient.mutation(deleteShout, { shoutId }).toPromise() const response = await graphQLClient.mutation(deleteShout, { shoutId }).toPromise()
console.debug('[deleteShout]:', response) console.debug('[deleteShout]:', response)
}, },
getDrafts: async (): Promise<Shout[]> => { getDrafts: async (): Promise<Shout[]> => {
const response = await privateGraphQLClient.query(draftsLoad, {}).toPromise() const response = await graphQLClient.query(draftsLoad, {}).toPromise()
console.debug('[getDrafts]:', response) console.debug('[getDrafts]:', response)
return response.data.loadDrafts return response.data.loadDrafts
}, },
createReaction: async (input: ReactionInput) => { createReaction: async (input: ReactionInput) => {
const response = await privateGraphQLClient.mutation(reactionCreate, { reaction: input }).toPromise() const response = await graphQLClient.mutation(reactionCreate, { reaction: input }).toPromise()
console.debug('[createReaction]:', response) console.debug('[createReaction]:', response)
return response.data.createReaction.reaction return response.data.createReaction.reaction
}, },
destroyReaction: async (id: number) => { destroyReaction: async (id: number) => {
const response = await privateGraphQLClient.mutation(reactionDestroy, { id: id }).toPromise() const response = await graphQLClient.mutation(reactionDestroy, { id: id }).toPromise()
console.debug('[destroyReaction]:', response) console.debug('[destroyReaction]:', response)
return response.data.deleteReaction.reaction return response.data.deleteReaction.reaction
}, },
updateReaction: async (id: number, input: ReactionInput) => { updateReaction: async (id: number, input: ReactionInput) => {
const response = await privateGraphQLClient const response = await graphQLClient.mutation(reactionUpdate, { id: id, reaction: input }).toPromise()
.mutation(reactionUpdate, { id: id, reaction: input })
.toPromise()
console.debug('[updateReaction]:', response) console.debug('[updateReaction]:', response)
return response.data.updateReaction.reaction return response.data.updateReaction.reaction
}, },
getAuthorsBy: async (options: QueryLoadAuthorsByArgs) => { getAuthorsBy: async (options: QueryLoadAuthorsByArgs) => {
const resp = await publicGraphQLClient.query(authorsLoadBy, options).toPromise() const resp = await graphQLClient.query(authorsLoadBy, options).toPromise()
return resp.data.loadAuthorsBy return resp.data.loadAuthorsBy
}, },
getShoutBySlug: async (slug: string) => { getShoutBySlug: async (slug: string) => {
const resp = await publicGraphQLClient const resp = await graphQLClient
.query(shoutLoad, { .query(shoutLoad, {
slug, slug,
}) })
.toPromise() .toPromise()
// if (resp.error) { if (resp.error) {
// console.error(resp) console.error(resp)
// } }
return resp.data.loadShout return resp.data.loadShout
}, },
getShoutById: async (shoutId: number) => { getShoutById: async (shoutId: number) => {
const resp = await publicGraphQLClient const resp = await graphQLClient
.query(shoutLoad, { .query(shoutLoad, {
shoutId, shoutId,
}) })
@ -345,7 +342,7 @@ export const apiClient = {
}, },
getShouts: async (options: LoadShoutsOptions) => { getShouts: async (options: LoadShoutsOptions) => {
const resp = await publicGraphQLClient.query(shoutsLoadBy, { options }).toPromise() const resp = await graphQLClient.query(shoutsLoadBy, { options }).toPromise()
if (resp.error) { if (resp.error) {
console.error(resp) console.error(resp)
} }
@ -354,7 +351,7 @@ export const apiClient = {
}, },
getRandomTopShouts: async (params: LoadRandomTopShoutsParams): Promise<Shout[]> => { getRandomTopShouts: async (params: LoadRandomTopShoutsParams): Promise<Shout[]> => {
const resp = await publicGraphQLClient.query(articlesLoadRandomTop, { params }).toPromise() const resp = await graphQLClient.query(articlesLoadRandomTop, { params }).toPromise()
if (resp.error) { if (resp.error) {
console.error(resp) console.error(resp)
} }
@ -363,7 +360,7 @@ export const apiClient = {
}, },
getUnratedShouts: async (limit: number): Promise<Shout[]> => { getUnratedShouts: async (limit: number): Promise<Shout[]> => {
const resp = await publicGraphQLClient.query(articlesLoadUnrated, { limit }).toPromise() const resp = await graphQLClient.query(articlesLoadUnrated, { limit }).toPromise()
if (resp.error) { if (resp.error) {
console.error(resp) console.error(resp)
} }
@ -372,7 +369,7 @@ export const apiClient = {
}, },
getMyFeed: async (options: LoadShoutsOptions) => { getMyFeed: async (options: LoadShoutsOptions) => {
const resp = await privateGraphQLClient.query(myFeed, { options }).toPromise() const resp = await graphQLClient.query(myFeed, { options }).toPromise()
if (resp.error) { if (resp.error) {
console.error(resp) console.error(resp)
@ -382,17 +379,17 @@ export const apiClient = {
}, },
getReactionsBy: async ({ by, limit }: { by: ReactionBy; limit?: number }) => { getReactionsBy: async ({ by, limit }: { by: ReactionBy; limit?: number }) => {
const resp = await publicGraphQLClient const resp = await graphQLClient
.query(reactionsLoadBy, { by, limit: limit ?? 1000, offset: 0 }) .query(reactionsLoadBy, { by, limit: limit ?? 1000, offset: 0 })
.toPromise() .toPromise()
return resp.data.loadReactionsBy return resp.data.loadReactionsBy
}, },
getNotifications: async (params: NotificationsQueryParams): Promise<NotificationsQueryResult> => { getNotifications: async (params: NotificationsQueryParams): Promise<NotificationsQueryResult> => {
const resp = await privateGraphQLClient.query(notifications, { params }).toPromise() const resp = await graphQLClient.query(notifications, { params }).toPromise()
return resp.data.loadNotifications return resp.data.loadNotifications
}, },
markNotificationAsRead: async (notificationId: number): Promise<void> => { markNotificationAsRead: async (notificationId: number): Promise<void> => {
await privateGraphQLClient await graphQLClient
.mutation(markNotificationAsRead, { .mutation(markNotificationAsRead, {
notificationId, notificationId,
}) })
@ -400,37 +397,37 @@ export const apiClient = {
}, },
markAllNotificationsAsRead: async (): Promise<void> => { markAllNotificationsAsRead: async (): Promise<void> => {
await privateGraphQLClient.mutation(markAllNotificationsAsRead, {}).toPromise() await graphQLClient.mutation(markAllNotificationsAsRead, {}).toPromise()
}, },
getMySubscriptions: async (): Promise<MySubscriptionsQueryResult> => { getMySubscriptions: async (): Promise<MySubscriptionsQueryResult> => {
const resp = await privateGraphQLClient.query(mySubscriptions, {}).toPromise() const resp = await graphQLClient.query(mySubscriptions, {}).toPromise()
// console.debug(resp.data) // console.debug(resp.data)
return resp.data.loadMySubscriptions return resp.data.loadMySubscriptions
}, },
// inbox // inbox
getChats: async (options: QueryLoadChatsArgs): Promise<Chat[]> => { getChats: async (options: QueryLoadChatsArgs): Promise<Chat[]> => {
const resp = await privateGraphQLClient.query(myChats, options).toPromise() const resp = await graphQLClient.query(myChats, options).toPromise()
return resp.data.loadChats.chats return resp.data.loadChats.chats
}, },
createChat: async (options: MutationCreateChatArgs) => { createChat: async (options: MutationCreateChatArgs) => {
const resp = await privateGraphQLClient.mutation(createChat, options).toPromise() const resp = await graphQLClient.mutation(createChat, options).toPromise()
return resp.data.createChat return resp.data.createChat
}, },
createMessage: async (options: MutationCreateMessageArgs) => { createMessage: async (options: MutationCreateMessageArgs) => {
const resp = await privateGraphQLClient.mutation(createMessage, options).toPromise() const resp = await graphQLClient.mutation(createMessage, options).toPromise()
return resp.data.createMessage.message return resp.data.createMessage.message
}, },
getChatMessages: async (options: QueryLoadMessagesByArgs) => { getChatMessages: async (options: QueryLoadMessagesByArgs) => {
const resp = await privateGraphQLClient.query(chatMessagesLoadBy, options).toPromise() const resp = await graphQLClient.query(chatMessagesLoadBy, options).toPromise()
return resp.data.loadMessagesBy.messages return resp.data.loadMessagesBy.messages
}, },
getRecipients: async (options: QueryLoadRecipientsArgs) => { getRecipients: async (options: QueryLoadRecipientsArgs) => {
const resp = await privateGraphQLClient.query(loadRecipients, options).toPromise() const resp = await graphQLClient.query(loadRecipients, options).toPromise()
return resp.data.loadRecipients.members return resp.data.loadRecipients.members
}, },
} }