diff --git a/generated/runtime.ts b/generated/runtime.ts index 327e613..0759f87 100644 --- a/generated/runtime.ts +++ b/generated/runtime.ts @@ -1,62 +1,52 @@ -/* tslint:disable */ /* eslint-disable */ /** * Swap API - * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings - * + * API reference for Jupiter's Swap API. * The version of the OpenAPI document: 1.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech + * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * Do not edit the class manually. */ +// --- BASE CONFIGURATION --- export const BASE_PATH = "https://api.jup.ag/swap/v1".replace(/\/+$/, ""); +/** + * Interface defining all parameters available for configuring the API client. + */ export interface ConfigurationParameters { - basePath?: string; // override base path - fetchApi?: FetchAPI; // override for fetch implementation - middleware?: Middleware[]; // middleware to apply before/after fetch requests - queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings - username?: string; // parameter for basic security - password?: string; // parameter for basic security - apiKey?: string | Promise | ((name: string) => string | Promise); // parameter for apiKey security - accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // parameter for oauth2 security - headers?: HTTPHeaders; //header params we want to use on every request - credentials?: RequestCredentials; //value for the credentials param we want to use on each request + basePath?: string; // override base path for API calls + fetchApi?: FetchAPI; // override for the fetch implementation (e.g., using node-fetch) + middleware?: Middleware[]; // middleware functions applied before/after requests + queryParamsStringify?: (params: HTTPQuery) => string; // custom function for serializing query strings + username?: string; // basic security: username + password?: string; // basic security: password + apiKey?: string | Promise | ((name: string) => string | Promise); // API key security + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // OAuth2 token security + headers?: HTTPHeaders; // default headers for all requests + credentials?: RequestCredentials; // value for the credentials parameter } export class Configuration { - constructor(private configuration: ConfigurationParameters = {}) {} - - set config(configuration: Configuration) { - this.configuration = configuration; - } - - get basePath(): string { - return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH; - } - - get fetchApi(): FetchAPI | undefined { - return this.configuration.fetchApi; - } - - get middleware(): Middleware[] { - return this.configuration.middleware || []; - } - - get queryParamsStringify(): (params: HTTPQuery) => string { - return this.configuration.queryParamsStringify || querystring; - } - - get username(): string | undefined { - return this.configuration.username; - } - - get password(): string | undefined { - return this.configuration.password; + // Made configuration parameters public and readonly for immutability preference + public readonly basePath: string; + public readonly fetchApi?: FetchAPI; + public readonly middleware: Middleware[]; + public readonly queryParamsStringify: (params: HTTPQuery) => string; + public readonly username?: string; + public readonly password?: string; + public readonly headers?: HTTPHeaders; + public readonly credentials?: RequestCredentials; + + constructor(configuration: ConfigurationParameters = {}) { + this.basePath = configuration.basePath != null ? configuration.basePath : BASE_PATH; + this.fetchApi = configuration.fetchApi; + this.middleware = configuration.middleware || []; + this.queryParamsStringify = configuration.queryParamsStringify || querystring; + this.username = configuration.username; + this.password = configuration.password; + this.headers = configuration.headers; + this.credentials = configuration.credentials; } get apiKey(): ((name: string) => string | Promise) | undefined { @@ -70,36 +60,38 @@ export class Configuration { get accessToken(): ((name?: string, scopes?: string[]) => string | Promise) | undefined { const accessToken = this.configuration.accessToken; if (accessToken) { + // Optimization: If the token is a static string, return it asynchronously without extra overhead. return typeof accessToken === 'function' ? accessToken : async () => accessToken; } return undefined; } - - get headers(): HTTPHeaders | undefined { - return this.configuration.headers; - } - - get credentials(): RequestCredentials | undefined { - return this.configuration.credentials; - } } export const DefaultConfig = new Configuration(); +// --- BASE API CLASS --- + /** * This is the base class for all generated API classes. */ export class BaseAPI { + // Regex for checking JSON MIME types, made static and private private static readonly jsonRegex = new RegExp('^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$', 'i'); - private middleware: Middleware[]; + + // Middleware is now managed within the Configuration and cloned explicitly + private readonly middleware: Middleware[]; constructor(protected configuration = DefaultConfig) { this.middleware = configuration.middleware; } - withMiddleware(this: T, ...middlewares: Middleware[]) { - const next = this.clone(); + /** + * Creates a new instance of the API class with additional middleware applied. + */ + withMiddleware(this: T, ...middlewares: Middleware[]): T { + // Use custom clone method + const next = this.clone(); next.middleware = next.middleware.concat(...middlewares); return next; } @@ -116,13 +108,6 @@ export class BaseAPI { /** * Check if the given MIME is a JSON MIME. - * JSON MIME examples: - * application/json - * application/json; charset=UTF8 - * APPLICATION/JSON - * application/vnd.company+json - * @param mime - MIME (Multipurpose Internet Mail Extensions) - * @return True if the given MIME is JSON, false otherwise. */ protected isJsonMime(mime: string | null | undefined): boolean { if (!mime) { @@ -134,21 +119,22 @@ export class BaseAPI { protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction): Promise { const { url, init } = await this.createFetchParams(context, initOverrides); const response = await this.fetchApi(url, init); + if (response && (response.status >= 200 && response.status < 300)) { return response; } - throw new ResponseError(response, 'Response returned an error code'); + throw new ResponseError(response, `API call failed with status: ${response.status}`); } private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction) { let url = this.configuration.basePath + context.path; + + // Append query string only if parameters exist if (context.query !== undefined && Object.keys(context.query).length !== 0) { - // only add the querystring to the URL if there are query parameters. - // this is done to avoid urls ending with a "?" character which buggy webservers - // do not handle correctly sometimes. url += '?' + this.configuration.queryParamsStringify(context.query); } + // Merge default headers and request-specific headers const headers = Object.assign({}, this.configuration.headers, context.headers); Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {}); @@ -157,7 +143,7 @@ export class BaseAPI { ? initOverrides : async () => initOverrides; - const initParams = { + const initParams: HTTPRequestInit = { method: context.method, headers, body: context.body, @@ -176,11 +162,12 @@ export class BaseAPI { if (isFormData(overriddenInit.body) || (overriddenInit.body instanceof URLSearchParams) || isBlob(overriddenInit.body)) { - body = overriddenInit.body; + body = overriddenInit.body; } else if (this.isJsonMime(headers['Content-Type'])) { - body = JSON.stringify(overriddenInit.body); + // Stringify body for JSON requests + body = JSON.stringify(overriddenInit.body); } else { - body = overriddenInit.body; + body = overriddenInit.body; } const init: RequestInit = { @@ -192,25 +179,27 @@ export class BaseAPI { } private fetchApi = async (url: string, init: RequestInit) => { - let fetchParams = { url, init }; + let fetchParams: FetchParams = { url, init }; + + // 1. Pre-middlewares for (const middleware of this.middleware) { if (middleware.pre) { - fetchParams = await middleware.pre({ - fetch: this.fetchApi, - ...fetchParams, - }) || fetchParams; + // Ensure correct cloning is done within the middleware if needed + fetchParams = await middleware.pre(fetchParams) || fetchParams; } } + let response: Response | undefined = undefined; try { + // 2. Fetch call response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init); } catch (e) { + // 3. Error-middlewares for (const middleware of this.middleware) { if (middleware.onError) { + // Pass a clone of the response if available, or undefined response = await middleware.onError({ - fetch: this.fetchApi, - url: fetchParams.url, - init: fetchParams.init, + ...fetchParams, error: e, response: response ? response.clone() : undefined, }) || response; @@ -224,12 +213,13 @@ export class BaseAPI { } } } + + // 4. Post-middlewares for (const middleware of this.middleware) { if (middleware.post) { + // Pass a clone of the response for middleware consumption response = await middleware.post({ - fetch: this.fetchApi, - url: fetchParams.url, - init: fetchParams.init, + ...fetchParams, response: response.clone(), }) || response; } @@ -244,11 +234,14 @@ export class BaseAPI { private clone(this: T): T { const constructor = this.constructor as any; const next = new constructor(this.configuration); + // Explicitly clone the middleware array next.middleware = this.middleware.slice(); return next; } }; +// --- UTILITY FUNCTIONS --- + function isBlob(value: any): value is Blob { return typeof Blob !== 'undefined' && value instanceof Blob; } @@ -257,175 +250,22 @@ function isFormData(value: any): value is FormData { return typeof FormData !== "undefined" && value instanceof FormData; } -export class ResponseError extends Error { - override name: "ResponseError" = "ResponseError"; - constructor(public response: Response, msg?: string) { - super(msg); - } -} - -export class FetchError extends Error { - override name: "FetchError" = "FetchError"; - constructor(public cause: Error, msg?: string) { - super(msg); - } -} - -export class RequiredError extends Error { - override name: "RequiredError" = "RequiredError"; - constructor(public field: string, msg?: string) { - super(msg); - } -} - -export const COLLECTION_FORMATS = { - csv: ",", - ssv: " ", - tsv: "\t", - pipes: "|", -}; - -export type FetchAPI = WindowOrWorkerGlobalScope['fetch']; - -export type Json = any; -export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'; -export type HTTPHeaders = { [key: string]: string }; -export type HTTPQuery = { [key: string]: string | number | null | boolean | Array | Set | HTTPQuery }; -export type HTTPBody = Json | FormData | URLSearchParams; -export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody }; -export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original'; - -export type InitOverrideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise - -export interface FetchParams { - url: string; - init: RequestInit; -} - -export interface RequestOpts { - path: string; - method: HTTPMethod; - headers: HTTPHeaders; - query?: HTTPQuery; - body?: HTTPBody; -} - -export function exists(json: any, key: string) { - const value = json[key]; - return value !== null && value !== undefined; -} - +/** + * Serializes an object of query parameters into a URL query string. + */ export function querystring(params: HTTPQuery, prefix: string = ''): string { - return Object.keys(params) - .map(key => querystringSingleKey(key, params[key], prefix)) - .filter(part => part.length > 0) - .join('&'); -} - -function querystringSingleKey(key: string, value: string | number | null | undefined | boolean | Array | Set | HTTPQuery, keyPrefix: string = ''): string { - const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key); - if (value instanceof Array) { - const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue))) - .join(`&${encodeURIComponent(fullKey)}=`); - return `${encodeURIComponent(fullKey)}=${multiValue}`; - } - if (value instanceof Set) { - const valueAsArray = Array.from(value); - return querystringSingleKey(key, valueAsArray, keyPrefix); - } - if (value instanceof Date) { - return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`; - } - if (value instanceof Object) { - return querystring(value as HTTPQuery, fullKey); - } - return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`; -} - -export function mapValues(data: any, fn: (item: any) => any) { - return Object.keys(data).reduce( - (acc, key) => ({ ...acc, [key]: fn(data[key]) }), - {} - ); -} - -export function canConsumeForm(consumes: Consume[]): boolean { - for (const consume of consumes) { - if ('multipart/form-data' === consume.contentType) { - return true; + const parts: string[] = []; + + // Use Object.entries for better iteration + for (const [key, value] of Object.entries(params)) { + // Use a dedicated helper to process the single key/value pair + const part = querystringSingleKey(key, value, prefix); + if (part.length > 0) { + parts.push(part); } } - return false; -} - -export interface Consume { - contentType: string; -} - -export interface RequestContext { - fetch: FetchAPI; - url: string; - init: RequestInit; -} - -export interface ResponseContext { - fetch: FetchAPI; - url: string; - init: RequestInit; - response: Response; -} - -export interface ErrorContext { - fetch: FetchAPI; - url: string; - init: RequestInit; - error: unknown; - response?: Response; -} - -export interface Middleware { - pre?(context: RequestContext): Promise; - post?(context: ResponseContext): Promise; - onError?(context: ErrorContext): Promise; -} - -export interface ApiResponse { - raw: Response; - value(): Promise; -} - -export interface ResponseTransformer { - (json: any): T; -} - -export class JSONApiResponse { - constructor(public raw: Response, private transformer: ResponseTransformer = (jsonValue: any) => jsonValue) {} - - async value(): Promise { - return this.transformer(await this.raw.json()); - } + return parts.join('&'); } -export class VoidApiResponse { - constructor(public raw: Response) {} - - async value(): Promise { - return undefined; - } -} - -export class BlobApiResponse { - constructor(public raw: Response) {} - - async value(): Promise { - return await this.raw.blob(); - }; -} - -export class TextApiResponse { - constructor(public raw: Response) {} - - async value(): Promise { - return await this.raw.text(); - }; -} +// Helper function simplified for cleaner recursion +function querystringSingleKey(key