npm package: @opengeoweb/api
Description: GeoWeb API library for the opengeoweb project
Latest version: 17.0.1

![current version](https://img.shields.io/badge/dynamic/json?color=blue&label=version&query=version&url=https://gitlab.com/opengeoweb/opengeoweb/raw/master/libs/api/package.json)
![coverage](https://gitlab.com/opengeoweb/opengeoweb/badges/master/coverage.svg?job=test-api)

# content

- [api](#api)
  - [Running unit tests](#running-unit-tests)
  - [Setup the api](#setup-the-api)
    - [1. Define a type for the api.](#1-define-a-type-for-the-api)
    - [2. Define routes for your api.](#2-define-routes-for-your-api)
    - [3. Create a createApi method to initiate the api](#3-create-a-createapi-method-to-initiate-the-api)
    - [4. Define a baseURL inside config.json](#4-define-a-baseurl-inside-configjson)
    - [5. Define a `fakeApi`.](#5-define-a--fakeapi-)
  - [How to use the api](#how-to-use-the-api)
    - [Use api inside app for production (api.ts)](#use-api-inside-app-for-production--apits-)
    - [Use (fake)api inside libs for storybook](#use--fake-api-inside-libs-for-storybook)
    - [Use the `useApiContext` to access the api or fakeApi](#use-the--useapicontext--to-access-the-api-or-fakeapi)

<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>

# Api

This library was generated with [Nx](https://nx.dev). The api lib makes it possible to use `ApiProvider` to wrap your components and make the `api` accessible by using the `useApiContext` hook.

## Running unit tests

Run `nx test api` to execute the unit tests via [Jest](https://jestjs.io).

## Setup the api

### 1. Define a type for the api.

Create a file called `api`, and create a type for the api. This should be a type that returns promises. Example:

```
// api.ts
export type AppApi = {
  getInitialPresets: (
    config: ConfigType,
  ) => Promise<{ data: InitialAppPreset }>;
  getScreenPresets: (
    config: ConfigType,
  ) => Promise<{ data: WorkspacePreset[] }>;
  getBeVersion: () => Promise<{ data: { version: string } }>;
};
```

### 2. Define routes for your api.

This should be a method that returns the routes. Example:

```
// api.ts
const getApiRoutes = (axiosInstance: AxiosInstance): AppApi => ({
  getInitialPresets: (
    formData: FormData,
  ): Promise<{ data: InitialAppPreset }> => {
    return axiosInstance.get('/getInitialPresetsUrl', formData);
  },
  getScreenPresets: (
    formData: FormData,
  ): Promise<{ data: WorkspacePreset[] }> => {
    return axiosInstance.get('/getScreenPresets', formData);
  },
  getBeVersion: (): Promise<{ data: { version: string } }> => {
    return axiosInstance.get('/version');
  },
});
```

### 3. Create a createApi method to initiate the api

At GeoWeb we use `axios` to do request to apis. Since we also need authentication, we can't use our defined api directly, so create a small helper method to combine the axiosInstance with our api:

```
// api.ts
import { createApiInstance } from '@opengeoweb/api';

export const createApi = ({
  url: string,
  appURL: string,
  auth: Credentials,
  setAuth: (cred: Credentials) => void,
  authTokenURL: string,
  authClientId: string,
}): AppApi => {
  const axiosInstance = createApiInstance(
    url,
    appURL,
    auth,
    setAuth,
    authTokenURL,
    authClientId,
  );

  return getApiRoutes(axiosInstance);
};

```

### 4. Define a baseURL inside config.json

Your api needs a baseURL in order to work. Add this key to the config.json. Be aware, this involves more changes in other repositories. Example:

```
// config.json
{
   ...
  "GW_MY_NEW_TEST_API_URL": 'https://mynewapi.com/v3'
}
```

### 5. Define a `fakeApi`.

Since storybook can't handle authenthication we need to mock the api with dummy data locally. It's also nice for testing functionality out without to have the geoweb app running. Create a new file called `fakeApi`, and add the same apiRoutes but let it return dummy data. Example:

```
// fakeApi.ts
export const createFakeApi = (): AppApi => {
  const api = {
    // dummy calls
    getInitialPresets: (): Promise<{ data: InitialAppPreset }> =>
      Promise.resolve({
        data: defaultInitialPresets as InitialAppPreset,
      }),
    getScreenPresets: (): Promise<{
      data: WorkspacePreset[];
    }> =>
      Promise.resolve({
        data: defaultScreenPresets as WorkspacePreset[],
      }),
    getBeVersion: (): Promise<{ data: { version: string } }> =>
      Promise.resolve({ data: { version: 'version 1.0.1' } }),
  };

  return api;
};
```

Also create a `createApi` method. Since we're not doing real requests with axios with this, we won't need it and use the `fakeAxiosInstance`. Example:

```
// fakeApi.ts
import { createFakeApiInstance } from '@opengeoweb/api';
export const createApi = (): TafApi => {
  const instance = createFakeApiInstance();
  return getApiRoutes(instance);
};
```

## How to use the api

If you follow the steps above, you end up with 2 new files (api.ts and fakeApi.ts) and a new config key for the json.

#### Use api inside app for production (api.ts)

If you want to try the api out with real data, you should do this inside the `app`. First, wrap the component which needs the api with the ApiProvider, and pass the `createApi` method from the api:

```
// app/geoweb/components/MyNewModule
  <ApiProvider
      baseURL={config.GW_MY_NEW_TEST_API_URL}
      appURL={config.GW_APP_URL}
      auth={auth}
      onSetAuth={onSetAuth}
      createApi={createApi} // coming fron api.ts
      authTokenURL={config.GW_AUTH_TOKEN_URL}
      authClientId={config.GW_AUTH_CLIENT_ID}
    >
      <ErrorBoundary>
        <MyNewModule />
      </ErrorBoundary>
    </ApiProvider>
```

The `baseURL` should get the url you've defined earlier. The `createApi` should pass the `createApi` method we've defined. The rest of the props you can pass from the props of geoweb.

#### Use (fake)api inside libs for storybook

If you want to try the api out with fake data, you should do this inside storybook. First, wrap the component which needs the api with the ApiProvider. and pass the `createApi` method from the fakeApi:

```
// libs/myNewLib/src/lib/MyNewLibDemo.stories.tsx
  <ApiProvider
      createApi={createApi} // coming fron fakeApi.ts
    >
      <ErrorBoundary>
        <MyNewModule />
      </ErrorBoundary>
    </ApiProvider>
```

#### Use the `useApiContext` inside a component to access the api or fakeApi

Inside your component you can use the `useApiContext` to access the defined routes. Please note that the `ApiProvider` needs to be used around one of the parent components for this to work. Any story or tests should therefore also be wrapped:

```
const MyComponent: React.FC = () => {
  const { api } = useApiContext<AppApi>();
  const [initialPresets, setInitialPresets] = React.useState<InitialAppPreset>([]);

  React.useEffect(()=> {
    const intitialPresets = await api.getInitialPresets(myFormvalues);
    setInitialAppPresets(intitialPresets);
  }, []);

  return <>initialPresets.map(preset => preset.name)</>
};

export const StoryBookExample = (): React.ReactElement => (
  <ApiProvider
    createApi={createApi} // coming fron fakeApi.ts
  >
      <ErrorBoundary>
        <MyComponent />
      </ErrorBoundary>
  </ApiProvider>
);

```

### TypeScript Documentation

- [TypeScript Docs](https://opengeoweb.gitlab.io/opengeoweb/typescript-docs/api/)