import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, ResponseType } from "axios"; import { QuerySimpleResponse } from "./types/ignite/planet/mars/mars"; import { QuerySimpleParamsResponse } from "./types/ignite/planet/mars/mars"; import { QueryWithPaginationResponse } from "./types/ignite/planet/mars/mars"; import { QueryWithQueryParamsResponse } from "./types/ignite/planet/mars/mars"; import { QueryWithQueryParamsWithPaginationResponse } from "./types/ignite/planet/mars/mars"; import { QuerySimpleRequest } from "./types/ignite/planet/mars/mars"; import { QuerySimpleParamsRequest } from "./types/ignite/planet/mars/mars"; import { QueryWithPaginationRequest } from "./types/ignite/planet/mars/mars"; import { QueryWithQueryParamsRequest } from "./types/ignite/planet/mars/mars"; import { QueryWithQueryParamsWithPaginationRequest } from "./types/ignite/planet/mars/mars"; import type {SnakeCasedPropertiesDeep} from 'type-fest'; export type QueryParamsType = Record; export type FlattenObject = CollapseEntries>; type Entry = { key: string; value: unknown }; type EmptyEntry = { key: ''; value: TValue }; type ExcludedTypes = Date | Set | Map; type ArrayEncoder = `[${bigint}]`; type EscapeArrayKey = TKey extends `${infer TKeyBefore}.${ArrayEncoder}${infer TKeyAfter}` ? EscapeArrayKey<`${TKeyBefore}${ArrayEncoder}${TKeyAfter}`> : TKey; // Transforms entries to one flattened type type CollapseEntries = { [E in TEntry as EscapeArrayKey]: E['value']; }; // Transforms array type to object type CreateArrayEntry = OmitItself< TValue extends unknown[] ? { [k: ArrayEncoder]: TValue[number] } : TValue, TValueInitial >; // Omit the type that references itself type OmitItself = TValue extends TValueInitial ? EmptyEntry : OmitExcludedTypes; // Omit the type that is listed in ExcludedTypes union type OmitExcludedTypes = TValue extends ExcludedTypes ? EmptyEntry : CreateObjectEntries; type CreateObjectEntries = TValue extends object ? { // Checks that Key is of type string [TKey in keyof TValue]-?: TKey extends string ? // Nested key can be an object, run recursively to the bottom CreateArrayEntry extends infer TNestedValue ? TNestedValue extends Entry ? TNestedValue['key'] extends '' ? { key: TKey; value: TNestedValue['value']; } : | { key: `${TKey}.${TNestedValue['key']}`; value: TNestedValue['value']; } | { key: TKey; value: TValue[TKey]; } : never : never : never; }[keyof TValue] // Builds entry for each key : EmptyEntry; export type ChangeProtoToJSPrimitives = { [key in keyof T]: T[key] extends Uint8Array | Date ? string : T[key] extends object ? ChangeProtoToJSPrimitives: T[key]; // ^^^^ This line is used to convert Uint8Array to string, if you want to keep Uint8Array as is, you can remove this line } export interface FullRequestParams extends Omit { /** 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; /** request body */ body?: unknown; } export type RequestParams = Omit; export interface ApiConfig extends Omit { securityWorker?: ( securityData: SecurityDataType | null, ) => Promise | 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 { public instance: AxiosInstance; private securityData: SecurityDataType | null = null; private securityWorker?: ApiConfig["securityWorker"]; private secure?: boolean; private format?: ResponseType; constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig = {}) { this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.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) || {}), }, } as AxiosRequestConfig; } private createFormData(input: Record): FormData { return Object.keys(input || {}).reduce((formData, key) => { const property = input[key]; formData.append( key, property instanceof Blob ? property : typeof property === "object" && property !== null ? JSON.stringify(property) : `${property}`, ); return formData; }, new FormData()); } public request = async ({ secure, path, type, query, format, body, ...params }: FullRequestParams): Promise> => { 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); } return this.instance.request({ ...requestParams, headers: { ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}), ...(requestParams.headers || {}), }, params: query, responseType: responseFormat, data: body, url: path, }); }; } /** * @title ignite.planet.mars */ export class Api extends HttpClient { /** * QueryQuerySimple * * @tags Query * @name queryQuerySimple * @request GET:/ignite/mars/query_simple */ queryQuerySimple = ( query?: Record, params: RequestParams = {}, ) => this.request>>({ path: `/ignite/mars/query_simple`, method: "GET", query: query, format: "json", ...params, }); /** * QueryQuerySimpleParams * * @tags Query * @name queryQuerySimpleParams * @request GET:/ignite/mars/query_simple/{mytypefield} */ queryQuerySimpleParams = (mytypefield: string, query?: Record, params: RequestParams = {}, ) => this.request>>({ path: `/ignite/mars/query_simple/${mytypefield}`, method: "GET", query: query, format: "json", ...params, }); /** * QueryQueryParamsWithPagination * * @tags Query * @name queryQueryParamsWithPagination * @request GET:/ignite/mars/query_with_params/{mytypefield} */ queryQueryParamsWithPagination = (mytypefield: string, query?: Omit>>,"mytypefield">, params: RequestParams = {}, ) => this.request>>({ path: `/ignite/mars/query_with_params/${mytypefield}`, method: "GET", query: query, format: "json", ...params, }); /** * QueryQueryWithQueryParams * * @tags Query * @name queryQueryWithQueryParams * @request GET:/ignite/mars/query_with_query_params/{mytypefield}/{mybool} */ queryQueryWithQueryParams = (mytypefield: string, mybool: string, query?: Omit>>,"mytypefield" | "mybool">, params: RequestParams = {}, ) => this.request>>({ path: `/ignite/mars/query_with_query_params/${mytypefield}/${mybool}`, method: "GET", query: query, format: "json", ...params, }); /** * QueryQueryWithQueryParamsWithPagination * * @tags Query * @name queryQueryWithQueryParamsWithPagination * @request GET:/ignite/mars/query_with_query_params/{mytypefield} */ queryQueryWithQueryParamsWithPagination = (mytypefield: string, query?: Omit>>,"mytypefield">, params: RequestParams = {}, ) => this.request>>({ path: `/ignite/mars/query_with_query_params/${mytypefield}`, method: "GET", query: query, format: "json", ...params, }); }