diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-11-24 20:00:08 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-27 14:47:51 +0100 |
| commit | f111685c5886f3e77edfd3621c98d8ac1b9bcce4 (patch) | |
| tree | 62a541fe3afeb64bf745443706fbfb02e96c5230 /src/utils/helpers/graphql.ts | |
| parent | bee515641cb144be9a855ff2cac258d2fedab21d (diff) | |
refactor(services, types): reorganize GraphQL fetchers and data types
The Typescript mapped types was useful for autocompletion in fetchers
but their are harder to maintain. I think it's better to keep each
query close to its fetcher to have a better understanding of the
fetched data. So I:
* colocate queries with their own fetcher
* colocate mutations with their own mutator
* remove Typescript mapped types for queries and mutations
* move data convertors inside graphql services
* rename most of data types and fetchers
Diffstat (limited to 'src/utils/helpers/graphql.ts')
| -rw-r--r-- | src/utils/helpers/graphql.ts | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/utils/helpers/graphql.ts b/src/utils/helpers/graphql.ts new file mode 100644 index 0000000..e07b151 --- /dev/null +++ b/src/utils/helpers/graphql.ts @@ -0,0 +1,64 @@ +import type { Nullable } from '../../types'; +import { CONFIG } from '../config'; + +/** + * Retrieve the API url from settings. + * + * @returns {string} The API url. + */ +export const getGraphQLUrl = (): string => { + if (!CONFIG.api.url) throw new Error('You forgot to define the API url.'); + + return CONFIG.api.url; +}; + +export type GraphQLData<T> = Record<string, Nullable<T>>; + +type GraphQLResponse<T extends GraphQLData<unknown>> = { + data: T; + errors?: { message: string }[]; +}; + +export type FetchGraphQLConfig = { + query: string; + url: string; + variables?: Record<string, unknown>; +}; + +/** + * Retrieve GraphQL data using fetch. + * + * @template T - The expected data type. + * @param {FetchGraphQLConfig} config - A configuration object. + * @returns {Promise<T>} The data. + */ +export const fetchGraphQL = async < + T extends GraphQLData<unknown> = GraphQLData<unknown>, +>({ + query, + url, + variables, +}: FetchGraphQLConfig): Promise<T> => { + const response = await fetch(url, { + method: 'POST', + headers: { + 'content-type': 'application/json;charset=UTF-8', + }, + body: JSON.stringify({ + query, + variables, + }), + }); + + const { data, errors }: GraphQLResponse<T> = await response.json(); + + if (!response.ok) { + const error = new Error( + errors?.map((e) => e.message).join('\n') ?? 'Network response was not OK' + ); + + return Promise.reject(error); + } + + return data; +}; |
