mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
4.7 KiB
142 lines
4.7 KiB
<% |
|
const { apiConfig, generateResponses, config } = it; |
|
%> |
|
|
|
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, ResponseType } from "axios"; |
|
|
|
export type QueryParamsType = Record<string | number, any>; |
|
|
|
export interface FullRequestParams extends Omit<AxiosRequestConfig, "data" | "params" | "url" | "responseType"> { |
|
/** set parameter to `true` for call `securityWorker` for this request */ |
|
secure?: boolean; |
|
/** request path */ |
|
path: string; |
|
/** content type of request body */ |
|
type?: ContentType; |
|
/** query params */ |
|
query?: QueryParamsType; |
|
/** format of response (i.e. response.json() -> format: "json") */ |
|
format?: ResponseType; |
|
/** wrapped response */ |
|
wrapped?: boolean; |
|
/** request body */ |
|
body?: unknown; |
|
} |
|
|
|
export type RequestParams = Omit<FullRequestParams, "body" | "method" | "path">; |
|
|
|
export interface ApiConfig<SecurityDataType = unknown> extends Omit<AxiosRequestConfig, "data" | "cancelToken"> { |
|
securityWorker?: (securityData: SecurityDataType | null) => Promise<AxiosRequestConfig | void> | AxiosRequestConfig | void; |
|
secure?: boolean; |
|
format?: ResponseType; |
|
} |
|
|
|
export enum ContentType { |
|
Json = "application/json", |
|
FormData = "multipart/form-data", |
|
UrlEncoded = "application/x-www-form-urlencoded", |
|
} |
|
|
|
export class HttpClient<SecurityDataType = unknown> { |
|
public instance: AxiosInstance; |
|
private securityData: SecurityDataType | null = null; |
|
private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"]; |
|
private secure?: boolean; |
|
private format?: ResponseType; |
|
|
|
constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig<SecurityDataType> = {}) { |
|
this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.baseURL || "<%~ apiConfig.baseUrl %>" }) |
|
this.secure = secure; |
|
this.format = format; |
|
this.securityWorker = securityWorker; |
|
} |
|
|
|
public setSecurityData = (data: SecurityDataType | null) => { |
|
this.securityData = data |
|
} |
|
|
|
private mergeRequestParams(params1: AxiosRequestConfig, params2?: AxiosRequestConfig): AxiosRequestConfig { |
|
return { |
|
...this.instance.defaults, |
|
...params1, |
|
...(params2 || {}), |
|
headers: { |
|
...(this.instance.defaults.headers || {}), |
|
...(params1.headers || {}), |
|
...((params2 && params2.headers) || {}), |
|
}, |
|
}; |
|
} |
|
|
|
|
|
protected createFormData(input: Record<string, unknown>): FormData { |
|
if (input instanceof FormData) { |
|
return input; |
|
} |
|
return Object.keys(input || {}).reduce((formData, key) => { |
|
const property = input[key]; |
|
|
|
if (property instanceof Blob) { |
|
formData.append(key, property) |
|
} else if (typeof property === 'object' && property !== null) { |
|
if (Array.isArray(property)) { |
|
// eslint-disable-next-line functional/no-loop-statement |
|
for (const prop of property) { |
|
formData.append(`${key}[]`, prop) |
|
} |
|
} else { |
|
formData.append(key, JSON.stringify(property)) |
|
} |
|
} else { |
|
formData.append(key, `${property}`) |
|
} |
|
return formData; |
|
}, new FormData()); |
|
} |
|
|
|
public request = async <T = any, _E = any>({ |
|
secure, |
|
path, |
|
type, |
|
query, |
|
format, |
|
wrapped, |
|
body, |
|
...params |
|
<% if (config.unwrapResponseData) { %> |
|
}: FullRequestParams): Promise<T> => { |
|
<% } else { %> |
|
}: FullRequestParams): Promise<AxiosResponse<T>> => { |
|
<% } %> |
|
const secureParams = ((typeof secure === 'boolean' ? secure : this.secure) && this.securityWorker && (await this.securityWorker(this.securityData))) || {}; |
|
const requestParams = this.mergeRequestParams(params, secureParams); |
|
const responseFormat = (format && this.format) || void 0; |
|
|
|
if (type === ContentType.FormData && body && body !== null && typeof body === "object") { |
|
requestParams.headers.common = { Accept: "*/*" }; |
|
requestParams.headers.post = {}; |
|
requestParams.headers.put = {}; |
|
|
|
body = this.createFormData(body as Record<string, unknown>); |
|
} |
|
|
|
return this.instance.request({ |
|
...requestParams, |
|
headers: { |
|
...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}), |
|
...(requestParams.headers || {}), |
|
}, |
|
params: query, |
|
responseType: responseFormat, |
|
data: body, |
|
url: path, |
|
<% if (config.unwrapResponseData) { %> |
|
}).then(response => { |
|
if(wrapped) return response; |
|
return response.data; |
|
}); |
|
<% } else { %> |
|
}); |
|
<% } %> |
|
}; |
|
}
|
|
|