aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/helpers/graphql.ts
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-11-24 20:00:08 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-27 14:47:51 +0100
commitf111685c5886f3e77edfd3621c98d8ac1b9bcce4 (patch)
tree62a541fe3afeb64bf745443706fbfb02e96c5230 /src/utils/helpers/graphql.ts
parentbee515641cb144be9a855ff2cac258d2fedab21d (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.ts64
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;
+};