@bapp/auto-api-client
Version:
Client to consume BAPP auto API, based on content types with type inference
229 lines (160 loc) • 7.25 kB
Markdown
# @bapp/auto-api-client
Generic API to request data from and trigger actions in the Bapp API.
## Roadmap
- [x] Functions for the generic endpoints
- [ ] Generate Zod schemas for client-side validation
- [ ] Type inference for filters, payload and response
## Installation
Install the package using one of the following commands:
```sh
npm i @bapp/auto-api-client axios
yarn add @bapp/auto-api-client axios
pnpm i @bapp/auto-api-client axios
```
Optionally, install `@tanstack/react-query` for query option getters:
```sh
npm i @tanstack/react-query
yarn add @tanstack/react-query
pnpm i @tanstack/react-query
```
## Types
### Type generation
The package includes a bin script to generate the types from a host. Rerun it everytime you want to sync client types with server types. At the moment it only generates types for `contentType` and `taskCode`.
Use it by running:
```sh
npx auto-api-client <API_HOST> <path/to/generated/file.ts>
yarn auto-api-client <API_HOST> <path/to/generated/file.ts>
pnpm auto-api-client <API_HOST> <path/to/generated/file.ts>
```
**Example:** `npx auto-api-client https://panel.bapp.ro/api src/auto-api-generated.ts`
### Registering types
Add the following somewhere in your project, ideally before the place where you instantiate `BappAutoApi`.
```ts
import { Mapping } from "./auto-api-generated";
declare module "@bapp/auto-api-client" {
interface Register {
mapping: Mapping;
}
}
```
## API
### Core
#### BappAutoApi methods
Name|Interface|Description
-|-|-
getMe|`(options) => Me`|Gets current user's profile
getApp|`(appSlug, options) => App`|Gets app config from slug
getEntityListIntrospect|`(contentType, options) => ListIntrospect`|Gets entity list introspect based on contentType
getEntityDetailIntrospect|`(contentType, pk?, options) => DetailIntrospect`|Gets entity detail introspect based on contentType
listEntities|`(contentType, options) => PagedResponse`| Gets entity list based on contentType
getEntity|`(contentType, pk, options) => Entity`|Gets specific entity based on contentType and pk
createEntity|`(contentType, payload, options) => Entity`|Cretes entity based on contentType
updateEntity|`(contentType, pk, payload, options) => Entity`|Updates specific entity based on contentType and pk
updatePartialEntity|`(contentType, pk, payload, options) => Entity`|Updates specific fields of an entity based on contentType and pk
deleteEntity|`(contentType, pk, options) => Entity`|Deletes specific entity based on contentType and pk
listTasks|`(options) => string[]`|Gets list of task codes
detailTask|`(code, options) => TaskConfig`|Gets the config of a task
runTask|`(code, payload, options) => TaskResponse`|Runs a task and returns the response
listWidgets|`(code, options) => string[]`|Gets list of widget codes
detailWidget|`(code, options) => WidgetConfig`|Gets the config of a widget
renderWidget|`(code, payload, options) => WidgetData`|Requests a widget render and gets the render data to show
#### Components
Name|Interface|Description
-|-|-
BappAutoApiConfigProvider|`(props: HookRequestConfig) => React.ReactNode`|Provides values for the useBappAutoApiConfig hook, useful for providing `tenantId`, `appSlug` or for changing the `BappAutoApi` instance used for making requests
#### Hooks
Name|Interface|Description
-|-|-
useBappAutoApiConfig|`() => HookRequestConfig`|Gets current hook request config, it contains the current `BappAutoApi` instance, `tenantId` and `appSlug`
#### Utils
Name|Interface|Description
-|-|-
getPageParam|`(url) => number \| undefined`|Gets and parses `page` query param out of url from `next`/`previous` field of PagedResponse
### React Query
#### Option getters
Name|Interface
-|-
getMeQueryOptions|`(options) => QueryOptions`
getAppQueryOptions|`(appSlug, options) => QueryOptions`
getEntityListIntrospectQueryOptions|`(contentType, options)=> QueryOptions`
getEntityDetailIntrospectQueryOptions|`(contentType, pk?, options) => QueryOptions`
getEntityListQueryOptions|`(contentType, options) => QueryOptions`
getEntityInfiniteListQueryOptions|`(contentType, options) => InfiniteQueryOptions`
getEntityDetailQueryOptions|`(contentType, pk, options) => QueryOptions`
getTaskListQueryOptions|`(options) => QueryOptions`
getTaskDetailQueryOptions|`(code, options) => QueryOptions`
getTaskRunQueryOptions|`(code, payload, options) => QueryOptions`
getWidgetListQueryOptions|`(options) => QueryOptions`
getWidgetDetailQueryOptions|`(code, options) => QueryOptions`
getWidgetRenderQueryOptions|`(code, payload, options) => QueryOptions`
## Using another host
```js
import _axios from "axios";
const axios = _axios.create({ baseURL: /* API Host here */ });
const bappAutoApi = new BappAutoApi({ axiosInstance: axios });
```
## Authentication
Authentication can be done through axios options or interceptors.
### Using axios initial options
```js
import _axios from "axios";
const axios = _axios.create({ baseURL: /* API Host here */, headers: {
Authorization: `Token ${/* Static token here */}`
} });
const bappAutoApi = new BappAutoApi({ axiosInstance: axios });
```
### Using axios interceptors
```js
const bappAutoApi = new BappAutoApi({ axiosInstance: axios });
bappAutoApi.axiosInstance.interceptors.request.use(async (config) => {
const token = await getToken();
if (!token) return config;
config.headers.set(
"Authorization",
`Bearer ${token}`
);
return config;
})
```
## Using the provider
The provider is useful for changing part or all of the config used to make requests. It can be used to change the `tenantId` or `appSlug` for part of the React component tree. If you are correctly passing the config to TanStack Query getters using `useBappAutoApiConfig`, then you can just add the provider somewhere above the component with the query to change how the request is being done.
**Example:**
```jsx
<BappAutoApiConfigProvider bappAutoApi={bappAutoApi} tenantId="37" appSlug="erp">
{children}
</BappAutoApiConfigProvider>
```
## Integrating with TanStack Router
To integreat with TanStack Router, you can use the TanStack Router context API to provide the bappAutoApiConfig, then using it through `Route.useRouteContext()` or passing it to the `BappAutoApiProvider` and using it with `useBappAutoApiConfig()`.
More documentation on this topic is to come.
## Example usage
### Vanilla
```ts
import BappAutoApi, { getEntityListQueryOptions } from "@bapp/auto-api-client";
import { Mapping } from "./auto-api-generated";
declare module "@bapp/auto-api-client" {
interface Register {
mapping: Mapping;
}
}
const bappAutoApi = new BappAutoApi(); // Defaults to https://panels.bapp.ro/api
bappAutoApi.listEntities("core.country", {
filter: { someQueryParam: "value" },
});
```
### React w/ TanStack Query
It is recommened to use this with the `BappAutoApiConfigProvider`, see [Using the provider](#using-the-provider).
```js
import {
getEntityListQueryOptions,
useBappAutoApiConfig,
} from "@bapp/auto-api-client";
const bappAutoApiConfig = useBappAutoApiConfig();
const listQuery = useQuery({
...getEntityListQueryOptions(contentType, {
config: bappAutoConfig,
filter: { someQueryParam: "value" },
})},
// Other query options
);
```