UNPKG

cdek-ts-api

Version:

CDEK API client

116 lines (97 loc) 3.46 kB
import { ApiError } from "../errors/api"; import { AuthError } from "../errors/auth"; import { HttpError } from "../errors/http"; import axios from 'axios'; import type { ApiResponse } from "../types/api"; import type { InitOptions, RequestInit, RequestMethod } from "../types/lib"; export class RestClient { private _token?: ApiResponse.OAuth; private _token_expire?: number; private account: string; private password: string; private grant_type: string; private url_base: string; private on_error?: (error: Error | ApiError | AuthError | HttpError) => void | Promise<void>; constructor(options: InitOptions) { this.account = options.account; this.password = options.password; this.grant_type = options.grant_type ?? "client_credentials"; this.url_base = options.url_base ?? "https://api.cdek.ru/v2"; this.on_error = options.on_error; } get token() { return this._token; } get token_expire() { return this._token_expire; } async auth(): Promise<void> { try { const res = await axios.post<any>(`${this.url_base}/oauth/token`, null, { params: { grant_type: 'client_credentials', client_id: this.account, client_secret: this.password, }, headers: { 'Accept': 'application/json', 'X-App-Name': 'shildikOnline', }, }); if (res.status !== 200) { throw new AuthError('Произошла ошибка'); } this._token = res.data; this._token_expire = Date.now() + (this.token?.expires_in ?? 3600) * 1000; } catch (err: any) { throw new AuthError('Authentication failed'); } } private async request<T>(init: RequestInit & { method: RequestMethod }): Promise<{ data: T; headers: any }> { try { if (!this.token || this.token_expire === undefined || Date.now() > this.token_expire) { await this.auth(); } const url = `${this.url_base}${init.url}${init.query ? "?" + this.params(init.query) : ""}`; const headers = { "Authorization": `Bearer ${this.token?.access_token}`, "Content-Type": "application/json", }; const res = await axios({ url, method: init.method, headers, params: init.query, data: init.payload ? JSON.stringify(init.payload) : undefined, }); return { data: res.data as T, headers: res.headers }; } catch (err: any) { if (this.on_error) { await this.on_error(err); return { data: null as T, headers: {} }; } else { throw err; } } } get<T>(init: RequestInit): Promise<{ data: T; headers: any }> { return this.request<T>({ ...init, method: "GET" }); } post<T>(init: RequestInit): Promise<{ data: T; headers: any }> { return this.request<T>({ ...init, method: "POST" }); } put<T>(init: RequestInit): Promise<{ data: T; headers: any }> { return this.request<T>({ ...init, method: "PUT" }); } patch<T>(init: RequestInit): Promise<{ data: T; headers: any }> { return this.request<T>({ ...init, method: "PATCH" }); } delete<T>(init: RequestInit): Promise<{ data: T; headers: any }> { return this.request<T>({ ...init, method: "DELETE" }); } private params(query: Record<string, any>): URLSearchParams { return new URLSearchParams( Object.entries(query).map<string[]>((item) => [item[0], item[1].toString()]) ); } }