import { RuntimeError } from '@botpress/client' import axios, { Axios, AxiosResponse } from 'axios' import { CreateCommentInput, CreateCommentOutput } from './sub-schemas' import * as bp from '.botpress' type Actions = bp.actions.Actions type Input = Actions[K]['input'] export type ErrorResponse = { code: number message: string } type Output = Actions[K]['output'] type ApiOutput = Output | ErrorResponse type PagedApiOutput = | ErrorResponse | (Omit, 'nextToken'> & { page: number limit: number totalResults: number }) export class FeatureBaseClient { private _client: Axios public constructor(apiKey: string) { this._client = axios.create({ baseURL: 'https://do.featurebase.app', headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json', }, }) } private _unwrapPagedResponse(response: PagedApiOutput): Output { if ('message' in response) { throw new RuntimeError(response.message) } const { limit, page, totalResults, ...result } = response let nextToken: string | undefined = undefined if (limit * page < totalResults) { nextToken = String(page + 1) } return { ...result, nextToken, } } private _parsePagedParams( params: Input ): Omit, 'nextToken'> & { page?: number } { if (!('nextToken' in params)) { return params } let page: number | undefined = undefined if (params.nextToken && !isNaN(Number(params.nextToken))) { page = Number(params.nextToken) } return { ...params, page, } } private _unwrapResponse(response: ApiOutput): Output { if ('message' in response) { throw new RuntimeError(response.message) } return response } private _handleAxiosError(thrown: unknown): never { if (axios.isAxiosError(thrown)) { throw new RuntimeError(thrown.response?.data?.message || thrown.message) } else { const error = thrown instanceof Error ? thrown : new Error(String(thrown)) throw new RuntimeError(error.message) } } public async listBoards(): Promise> { const response: AxiosResponse> = await this._client .get('/v2/boards') .catch(this._handleAxiosError) return this._unwrapResponse(response.data) } public async getBoard(params: Input<'getBoard'>): Promise> { const response: AxiosResponse> = await this._client .get(`/v2/boards/${params.id}`) .catch(this._handleAxiosError) return this._unwrapResponse(response.data) } public async listPosts(params: Input<'listPosts'>): Promise> { const response: AxiosResponse> = await this._client .get('/v2/posts', { params: this._parsePagedParams(params), }) .catch(this._handleAxiosError) return this._unwrapPagedResponse(response.data) } public async createPost(params: Input<'createPost'>): Promise> { const response: AxiosResponse> = await this._client .post('/v2/posts', params) .catch(this._handleAxiosError) return this._unwrapResponse(response.data) } public async deletePost(params: Input<'deletePost'>): Promise> { const response: AxiosResponse> = await this._client .delete('/v2/posts', { data: params }) .catch(this._handleAxiosError) return this._unwrapResponse(response.data) } public async updatePost(params: Input<'updatePost'>): Promise> { const response: AxiosResponse> = await this._client .patch('/v2/posts', params) .catch(this._handleAxiosError) return this._unwrapResponse(response.data) } public async createComment(params: CreateCommentInput): Promise { const response: AxiosResponse = await this._client .post('/v2/comment', params) .catch(this._handleAxiosError) if ('message' in response.data) { throw new RuntimeError(response.data.message) } return response.data } public async getComments(params: Input<'getComments'>): Promise> { const response: AxiosResponse> = await this._client .get('/v2/comment', { params: this._parsePagedParams(params), }) .catch(this._handleAxiosError) return this._unwrapPagedResponse(response.data) } }