Skip to content

Instantly share code, notes, and snippets.

@josippapez
Last active September 17, 2024 19:28
Show Gist options
  • Select an option

  • Save josippapez/c83c4517fd92bc00b9267555e2a53a6e to your computer and use it in GitHub Desktop.

Select an option

Save josippapez/c83c4517fd92bc00b9267555e2a53a6e to your computer and use it in GitHub Desktop.
Tanstack
import Axios, { AxiosError, AxiosHeaders, AxiosRequestConfig } from 'axios';
import { getAuth, getIdToken, signOut } from 'firebase/auth';
export const AXIOS_INSTANCE = Axios.create({
baseURL: process.env.NEXT_PUBLIC_BACKEND_API,
}); // use your own URL here or environment variable
// add a second `options` argument here if you want to pass extra options to each generated query
export const customClient = async <T>(
config: AxiosRequestConfig,
options?: AxiosRequestConfig,
): Promise<T> => {
const headers = new AxiosHeaders();
// This is an example of how you can add firebase AUTH token to the request
// const auth = getAuth();
// const user = auth.currentUser;
// let token: undefined | string = undefined;
// if (user) {
// token = await getIdToken(user);
// headers.set('Authorization', `Bearer ${token}`);
// }
const source = Axios.CancelToken.source();
const promise = AXIOS_INSTANCE({
...config,
...options,
cancelToken: source.token,
headers: {
...config.headers,
...headers,
},
}).then(({ data }) => data);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
promise.cancel = () => {
source.cancel('Query was cancelled');
};
return promise;
};
AXIOS_INSTANCE.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (error.response?.status === 401) {
const auth = getAuth();
signOut(auth);
}
return Promise.reject(error);
},
);
// In some case with react-query and swr you want to be able to override the return error type so you can also do it here like this
export type ErrorType<Error> = AxiosError<Error>;
export type BodyType<BodyData> = BodyData;
// custom client with proxy to server actions
// export const customClient = async <T>(
// config: AxiosRequestConfig,
// options?: AxiosRequestConfig,
// ): Promise<T> => {
// // Singla needs to be deleted since intance of class cannot be passed to server side function, only pain objects
// delete config.signal;
// return serverFetch(config, options);
// };
// server side function to for proxy
// 'use server';
// import Axios, { AxiosHeaders, AxiosRequestConfig, AxiosResponse } from 'axios';
// export const AXIOS_INSTANCE = Axios.create({
// baseURL: process.env.NEXT_PUBLIC_BACKEND_API,
// });
// export const serverFetch = async <T>(
// config: AxiosRequestConfig,
// options?: AxiosRequestConfig,
// ) => {
// const headers = new AxiosHeaders();
// // let clientId = '';
// // /** hardcoded for dev. Should be passed as a postMessage() on iframe. */
// // clientId = localStorage.getItem('fehr-client-id') || '';
// const clientId = '8dd218c8-3ccd-45fb-8456-f4995fc1cff6';
// headers.set('client-id', clientId);
// return AXIOS_INSTANCE({
// ...config,
// ...options,
// headers: {
// ...config.headers,
// ...headers,
// },
// })
// .then((response: AxiosResponse<T>) => response.data)
// .catch((err) => err);
// };
openapi:
curl http://localhost:3000/api-docs-json > ./libs/api/src/openapi.json
rm -rf ./libs/api/src/openapi-config
rm -rf ./libs/api/src/openapi-schemas
npx orval --config ./libs/api/orval.config.ts
npx prettier --write ./libs/api/src
rm ./libs/api/src/openapi.json
import { defineConfig } from "orval";
const defaultQueryOverride = {
useQuery: true,
signal: true,
useSuspenseQuery: true,
};
// USE Makefile or npm scripts to run orval
// makefile: make -f ./Makefile
// OR
// script: curl http://localhost:[port]/api-json > ./api/openapi.json && rm -rf ./api/openapi-config && rm -rf ./api/openapi-schemas && npx orval --config ./apps/fe/orval.config.ts && npx prettier --write ./api/ && rm ./api/openapi.json
export default defineConfig({
backOffice: {
input: {
target: "./src/openapi.json",
filters: {
// match all strings that don't contain healthcheck
//@ts-ignore-next-line
tags: [/^(?!.*healthcheck).*$/],
},
},
output: {
mode: "tags-split",
target: "./openapi-config",
schemas: "./openapi-schemas",
workspace: "./src/",
indexFiles: true,
client: "react-query",
prettier: true,
mock: false,
override: {
query: {
useQuery: true,
signal: true,
useSuspenseQuery: true,
},
operations: {
// GuideController_findAll: {
// query: {
// ...defaultQueryOverride,
// useInfinite: true,
// useInfiniteQueryParam: 'page',
// },
// },
},
mutator: {
path: "./custom-client.ts",
name: "customClient",
},
},
},
},
});
'use client';
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister';
import { QueryClient } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
import { PropsWithChildren } from 'react';
import 'react-toastify/dist/ReactToastify.css';
const isServer = typeof window === 'undefined';
const persister = createSyncStoragePersister({
storage: isServer ? null : window?.localStorage,
});
// remove queryMounted information on first render
const storage = !isServer ? localStorage : null;
storage?.removeItem('queryMounted');
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnMount(query) {
const queryMounted: Record<string, boolean> = JSON.parse(
storage?.getItem('queryMounted') ?? '{}',
);
// on first mount invalidate the query (refetch the data)
if (!queryMounted[query.queryHash]) {
// Mark the query as mounted
storage?.setItem(
'queryMounted',
JSON.stringify({ ...queryMounted, [query.queryHash]: true }),
);
query.invalidate();
}
return true;
},
gcTime: 1000 * 60 * 60 * 24, // 24 hours
staleTime: 1000 * 20, // 20 seconds
},
mutations: {
gcTime: 1000 * 60,
},
},
});
export const TanstackQueryProvider: React.FC<PropsWithChildren> = ({
children,
}) => {
return (
<PersistQueryClientProvider
client={queryClient}
persistOptions={{ persister }}
>
{children}
{process.env.NODE_ENV === 'development' && (
<ReactQueryDevtools initialIsOpen={false} />
)}
</PersistQueryClientProvider>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment