npm package: @secondcloset/api-utils
Description: api utils is second closet's wrapper service of [axios library](https://github.com/axios/axios)
Author: Bryan Chan
Latest version: 1.4.20

# api-utils v2

api utils is second closet's wrapper service of [axios library](https://github.com/axios/axios)

## Setup

To use api functionality we first need to setup our api util locally. Create an api.ts/js file under lib/utils folder and add the following.

```js
import { setupAPI, getCancellableRequest } from "@secondcloset/api-utils";
import { reportAPI } from "./sentry";
import Cookie from "./cookie";

const { getAPIFromDomain } = setupAPI({
  baseURL: String(process.env.REACT_APP_API),
  getToken: Cookie.getUserToken,
  interceptors: {
    response: {
      onFulfilled: (response) => {
        // do something when a request is fulfilled
        return response;
      },
      onRejected: (error) => {
        // do something when a request fails
        reportAPI(error); // like reporting to sentry
        return error;
      },
    },
  },
});

export { getAPIFromDomain, getCancellableRequest };
export * from "@secondcloset/api-utils/dist/types"; // re-export types optional for ts
```

## Usage

You can now import `getAPIFromDomain` and `getCancellableRequest` from your local api util.

### Basics

`getAPIFromDomain` is a function that accepts a domain and returns an [axios instance](https://github.com/axios/axios#instance-methods)

```ts
export const fetchOrderDetails = async (
  key: string,
  orderID: string
): Promise<Fulfillment.Order> => {
  const api = getAPIFromDomain("fulfillment");
  const url = `/orders/${orderID}`;
  const { data: order } = await api.get(url);
  return order;
};
```

\*Note: main difference from v1 is instead of `const api = new API("fulfillment");` it's now `const api = getAPIFromDomain("fulfillment");`

### Cancellable Request

`getCancellableRequest` is a wrapper function that accepts an async function and returns that with a cancel method that react-query uses for [query cancellation](https://react-query.tanstack.com/docs/guides/query-cancellation) or you can manually invoke

#### React-Query

```ts
/* your api service file */
export const fetchOrderDetails = getCancellableRequest<Fulfillment.Order>(
  async (key: string, orderID: string, config: APIRequestConfig) => {
    const api = getAPIFromDomain("fulfillment");
    const url = `/orders/${orderID}`;
    const response = await api.get(url, config);
    return response.data;
  }
);

/* your component */
const orderDetails = useQuery(["order", orderID], fetchOrderDetails);
```

#### Legacy/Manual Cancellation

```ts
/* your api service file */
export const useOrderDetails = () => {
  const [data, setData] = useState<Fulfillment.Order>();
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  const fetchOrderDetails = (orderID: string) => {
    const url = `/orders/${orderID}`;
    const api = getAPIFromDomain("fulfillment");

    setError("");
    setLoading(true);

    return getCancellableRequest((config) => {
      return api
        .get(url, config)
        .then((res) => {
          const order = res.data;
          setData(order);
          return order;
        })
        .catch((error) => {
          setError(error);
          return error;
        })
        .finally(() => setLoading(false));
    })();
  };

  const orderDetails = { data, isLoading: loading, error };

  return { orderDetails, fetchOrderDetails };
};

/* your component */
const { orderDetails, fetchOrderDetails } = useOrderDetails();

// this example is cancelling request when component unmounts
useEffect(() => {
  const promise = fetchOrderDetails(orderID);
  return () => {
    //@ts-ignore
    promise.cancel();
  };
}, [orderID]);
```

### Custom config/headers

Because api is now an instance of axios we can now easily cusomize [request config](https://github.com/axios/axios#request-config)

```ts
const api = getAPIFromDomain("fulfillment");
const url = `/files/${fileID}`;
const config = {
  headers: {
    "Content-Type": "multipart/form-data",
  },
};
const response = await api.get(url, config);
```