import { AxisProvider } from './internal/axios/axiosProvider' ; import { FetchClient } from './internal/fetch/fetchClient' ; import { RetryConfig , RetryService } from './internal/retry' ; export interface RequestConfig { headers ? : any ; mode ? : string ; } export interface HttpClient { get < T > ( url , config ? ) : Promise < T > ; delete < T > ( url , config ? ) : Promise < T > ; head < T > ( url , config ? ) : Promise < T > ; post < T > ( url , data ? , config ? ) : Promise < T > ; put < T > ( url , data ? , config ? ) : Promise < T > ; patch < T > ( url , data ? , config ? ) : Promise < T > ; } export enum HttpClientType { AXIOS = 'axios' , FETCH = 'fetch' } export interface Credentials { token : string ; organization ? : string ; baseUrl ? : string ; } export interface ClientConfig { httpClientType ? : HttpClientType ; httpClient ? : HttpClient ; userAgent ? : string ; integrationUserAgent ? : string ; retryConfig ? : RetryConfig ; } export interface ResponseList < T > { data : ResponseObject < T > [ ] ; pagination : Pagination ; } export interface ResponseObject < T > { data : T ; } export interface Pagination { offset : number ; limit : number ; } export interface ValidationErrorResponse { errors : ErrorHolder [ ] ; } export interface CommonErrorResponse { error : Error ; } export interface ErrorHolder { error : ErrorKey ; } export interface ErrorKey { key : string ; errors : Error [ ] ; } export interface Error { code : string ; message : string ; } export interface PatchRequest { value ? : any ; op : PatchOperation ; path : string ; } export enum PatchOperation { ADD = 'add' , REMOVE = 'remove' , REPLACE = 'replace' , MOVE = 'move' , copy = 'copy' , TEST = 'test' } export interface DownloadLink { url : string ; expireIn : string ; } export enum BooleanInt { TRUE = 1 , FALSE = 0 } export interface Status < T > { identifier : string ; status : string ; progress : number ; attributes : T ; createdAt : string ; updatedAt : string ; startedAt : string ; finishedAt : string ; } export interface Attribute { [ key ] : string ; } export abstract class CrowdinApi { private static readonly CROWDIN_URL_SUFFIX : string = 'api.crowdin.com/api/v2' ; private static readonly AXIOS_INSTANCE = new AxisProvider ( ) . axios ; private static readonly FETCH_INSTANCE = new FetchClient ( ) ; readonly token : string ; readonly organization ? : string ; readonly url : string ; readonly config : ClientConfig | undefined ; readonly retryService : RetryService ; protected fetchAllFlag = false ; protected maxLimit : number | undefined ; param credentials param config constructor ( credentials , config ? ) { this . token = credentials . token ; this . organization = credentials . organization ; if ( ! ! credentials . baseUrl ) { this . url = credentials . baseUrl ; } else { if ( ! ! this . organization ) { this . url = `https://${ this . organization }.${ CrowdinApi . CROWDIN_URL_SUFFIX }` ; } else { this . url = `https://${ CrowdinApi . CROWDIN_URL_SUFFIX }` ; } } let retryConfig ; if ( ! ! config && ! ! config . retryConfig ) { retryConfig = config . retryConfig ; } else { retryConfig = { waitInterval : 0 , retries : 0 , conditions : [ ] , } ; } this . retryService = new RetryService ( retryConfig ) ; this . config = config ; } protected addQueryParam ( url , name , value ? ) { if ( ! ! value ) { url += new RegExp ( /\?.+=.*/g ) . test ( url ) ? '&' : '?' ; url += `${ name }=${ value }` ; } return url ; } protected defaultConfig ( ) { const config = { headers : { Authorization : `Bearer ${ this . token }` , } , } ; if ( ! ! this . config ) { if ( ! ! this . config . userAgent ) { config . headers [ 'User-Agent' ] = this . config . userAgent ; } if ( ! ! this . config . integrationUserAgent ) { config . headers [ 'X-Crowdin-Integrations-User-Agent' ] = this . config . integrationUserAgent ; } } return config ; } get httpClient ( ) : HttpClient { if ( ! ! this . config ) { if ( ! ! this . config . httpClient ) { return this . config . httpClient ; } if ( ! ! this . config . httpClientType ) { switch ( this . config . httpClientType ) { case HttpClientType . AXIOS : return CrowdinApi . AXIOS_INSTANCE ; case HttpClientType . FETCH : return CrowdinApi . FETCH_INSTANCE ; default : return CrowdinApi . AXIOS_INSTANCE ; } } } return CrowdinApi . AXIOS_INSTANCE ; } public withFetchAll ( maxLimit ? ) { this . fetchAllFlag = true ; this . maxLimit = maxLimit ; return this ; } protected async getList < T = any > ( url , limit ? , offset ? , config ? ) { const conf = config || this . defaultConfig ( ) ; if ( this . fetchAllFlag ) { this . fetchAllFlag = false ; const maxAmount = this . maxLimit ; this . maxLimit = undefined ; return await this . fetchAll ( url , conf , maxAmount ) ; } else { url = this . addQueryParam ( url , 'limit' , limit ) ; url = this . addQueryParam ( url , 'offset' , offset ) ; return this . get ( url , conf ) ; } } protected async fetchAll < T = any > ( url , config , maxAmount ? ) { let limit = 500 ; if ( ! ! maxAmount && maxAmount < limit ) { limit = maxAmount ; } let offset = 0 ; let resp ; for ( ; ; ) { let urlWithPagination = this . addQueryParam ( url , 'limit' , limit ) ; urlWithPagination = this . addQueryParam ( urlWithPagination , 'offset' , offset ) ; const e = await this . get ( urlWithPagination , config ) ; if ( ! resp ) { resp = e ; } else { resp . data = resp . data . concat ( e . data ) ; resp . pagination . limit += e . data . length ; } if ( e . data . length < limit || ( ! ! maxAmount && resp . data . length >= maxAmount ) ) { break ; } else { offset += limit ; } if ( ! ! maxAmount ) { if ( maxAmount < resp . data . length + limit ) { limit = maxAmount - resp . data . length ; } } } return resp ; } protected get < T > ( url , config ? ) { return this . retryService . executeAsyncFunc ( ( ) => this . httpClient . get ( url , config ) ) ; } protected delete < T > ( url , config ? ) { return this . retryService . executeAsyncFunc ( ( ) => this . httpClient . delete ( url , config ) ) ; } protected head < T > ( url , config ? ) { return this . retryService . executeAsyncFunc ( ( ) => this . httpClient . head ( url , config ) ) ; } protected post < T > ( url , data ? , config ? ) { return this . retryService . executeAsyncFunc ( ( ) => this . httpClient . post ( url , data , config ) ) ; } protected put < T > ( url , data ? , config ? ) { return this . retryService . executeAsyncFunc ( ( ) => this . httpClient . put ( url , data , config ) ) ; } protected patch < T > ( url , data ? , config ? ) { return this . retryService . executeAsyncFunc ( ( ) => this . httpClient . patch ( url , data , config ) ) ; } }