1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-09-19 05:47:17 +03:00

feat(bridge/nodejs): finish network implementation

This commit is contained in:
Divlo 2023-05-07 15:07:20 +02:00
parent 426c816ca4
commit 950985ca86
No known key found for this signature in database
GPG Key ID: 8F9478F220CE65E9
2 changed files with 105 additions and 9 deletions

View File

@ -1,10 +1,46 @@
import axios from 'axios'
import type { AxiosInstance } from 'axios'
export interface NetworkOptions {
interface NetworkOptions {
/** `baseURL` will be prepended to `url`. It can be convenient to set `baseURL` for an instance of `Network` to pass relative URLs. */
baseURL?: string
}
interface NetworkRequestOptions {
/** Server URL that will be used for the request. */
url: string
/** Request method to be used when making the request. */
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
/** Data to be sent as the request body. */
data?: Record<string, unknown>
/** Custom headers to be sent. */
headers?: Record<string, string>
}
interface NetworkResponse<ResponseData> {
/** Data provided by the server. */
data: ResponseData
/** HTTP status code from the server response. */
statusCode: number
/** Options that was provided for the request. */
options: NetworkRequestOptions & NetworkOptions
}
export class NetworkError<ResponseErrorData = unknown> extends Error {
public readonly response: NetworkResponse<ResponseErrorData>
public constructor(response: NetworkResponse<ResponseErrorData>) {
super(`[NetworkError]: ${response.statusCode}`)
this.response = response
Object.setPrototypeOf(this, NetworkError.prototype)
}
}
export class Network {
private options: NetworkOptions
private axios: AxiosInstance
@ -16,7 +52,45 @@ export class Network {
})
}
public async get<T>(url: string): Promise<T> {
return (await this.axios.get<T>(url)).data as T
public async request<ResponseData = unknown, ResponseErrorData = unknown>(
options: NetworkRequestOptions
): Promise<NetworkResponse<ResponseData>> {
try {
const response = await this.axios.request<ResponseData>({
url: options.url,
method: options.method.toLowerCase(),
data: options.data,
headers: options.headers
})
return {
data: response.data,
statusCode: response.status,
options: {
...this.options,
...options
}
}
} catch (error) {
let statusCode = 500
let data = {} as ResponseErrorData
if (axios.isAxiosError(error)) {
data = error?.response?.data
statusCode = error?.response?.status ?? 500
}
throw new NetworkError<ResponseErrorData>({
data,
statusCode,
options: {
...this.options,
...options
}
})
}
}
public isNetworkError<ResponseErrorData = unknown>(
error: unknown
): error is NetworkError<ResponseErrorData> {
return error instanceof NetworkError
}
}

View File

@ -30,11 +30,33 @@ export const run: ActionFunction = async function () {
const network = new Network({
baseURL: 'https://jsonplaceholder.typicode.com'
})
const data = await network.get<{ title: string }>('/todos/1')
await leon.answer({
key: 'answer',
data: {
answer: `Todo n°1: ${data.title}`
try {
const response = await network.request<{ title: string }>({
url: '/todos/1',
method: 'GET'
})
await leon.answer({
key: 'answer',
data: {
answer: `Todo: ${response.data.title}`
}
})
} catch (error) {
await leon.answer({
key: 'answer',
data: {
answer: 'Something went wrong...'
}
})
if (network.isNetworkError(error)) {
const errorData = JSON.stringify(error.response.data, null, 2)
await leon.answer({
key: 'answer',
data: {
answer: `${error.message}: ${errorData}`
}
})
}
})
}
}