@kontent-ai/management-sdk
Version:
Official Kontent.ai management SDK
296 lines (268 loc) • 9.79 kB
text/typescript
import {
headerHelper,
IResponse,
IHeader,
IHttpService,
IQueryParameter,
ISDKInfo,
urlHelper
} from '@kontent-ai/core-sdk';
import { AxiosError } from 'axios';
import { IManagementClientConfig } from '../config/imanagement-client-config.interface';
import { SharedContracts } from '../contracts';
import { IContentManagementInternalQueryConfig, IContentManagementQueryConfig, SharedModels } from '../models';
import { getType } from 'mime';
export abstract class BaseManagementQueryService<TCancelToken> {
/**
* Default base url for content management API
*/
private readonly defaultBaseCMUrl: string = 'https://manage.kontent.ai/v2';
constructor(
protected readonly config: IManagementClientConfig,
protected readonly httpService: IHttpService<TCancelToken>,
protected readonly sdkInfo: ISDKInfo
) {}
/**
* Gets url based on the action, query configuration and options (parameters)
* @param action Action (= url part) that will be hit
* @param options Query options
* @param addSlash Indicates if slash is added to query
*/
getFullUrl(action: string, options?: IQueryParameter[], addSlash: boolean = true): string {
return urlHelper.addOptionsToUrl(this.getBaseUrl() + (addSlash ? '/' : '') + action, options);
}
/**
* Gets proper set of headers for given request.
* @param config Query config
*/
getHeaders(config: IContentManagementQueryConfig): IHeader[] {
const headers: IHeader[] = [
// sdk tracking header
headerHelper.getSdkIdHeader({
host: this.sdkInfo.host,
name: this.sdkInfo.name,
version: this.sdkInfo.version
}),
// add authorization header
this.getAuthorizationHeader()
];
// add query headers
headers.push(...config.headers);
return headers;
}
/**
* Http PATCH response
* @param url Url of request
* @param config Query configuration
*/
protected async patchResponseAsync<TRawData>(
url: string,
body: any,
internalConfig: IContentManagementInternalQueryConfig,
config: IContentManagementQueryConfig
): Promise<IResponse<TRawData>> {
try {
return await this.httpService.patchAsync<TRawData>(
{
url: url,
body: body
},
{
cancelToken: config.cancelTokenRequest,
retryStrategy: this.config.retryStrategy,
headers: this.getHeaders(config),
responseType:
internalConfig && internalConfig.responseType ? internalConfig.responseType : undefined
}
);
} catch (error) {
throw this.mapContentManagementError(error);
}
}
/**
* Http GET response
* @param url Url of request
* @param config Query configuration
*/
protected async getResponseAsync<TRawData>(
url: string,
internalConfig: IContentManagementInternalQueryConfig,
config: IContentManagementQueryConfig
): Promise<IResponse<TRawData>> {
try {
return await this.httpService.getAsync<TRawData>(
{
url: url
},
{
cancelToken: config.cancelTokenRequest,
retryStrategy: this.config.retryStrategy,
headers: this.getHeaders(config),
responseType:
internalConfig && internalConfig.responseType ? internalConfig.responseType : undefined
}
);
} catch (err) {
throw this.mapContentManagementError(err);
}
}
/**
* Http POST response
* @param url Url of request
* @param body Body of the request (names and values)
* @param config Query configuration
*/
protected async postResponseAsync<TRawData>(
url: string,
body: any,
internalConfig: IContentManagementInternalQueryConfig,
config: IContentManagementQueryConfig
): Promise<IResponse<TRawData>> {
try {
return await this.httpService.postAsync<TRawData>(
{
url: url,
body: body
},
{
cancelToken: config.cancelTokenRequest,
retryStrategy: this.config.retryStrategy,
headers: this.getHeaders(config),
responseType:
internalConfig && internalConfig.responseType ? internalConfig.responseType : undefined
}
);
} catch (err) {
throw this.mapContentManagementError(err);
}
}
/**
* Http PUT response
* @param url Url of request
* @param body Body of the request (names and values)
* @param config Query configuration
*/
protected async putResponseAsync<TRawData>(
url: string,
body: any,
internalConfig: IContentManagementInternalQueryConfig,
config: IContentManagementQueryConfig
): Promise<IResponse<TRawData>> {
try {
return await this.httpService.putAsync<TRawData>(
{
url: url,
body: body
},
{
cancelToken: config.cancelTokenRequest,
retryStrategy: this.config.retryStrategy,
headers: this.getHeaders(config),
responseType:
internalConfig && internalConfig.responseType ? internalConfig.responseType : undefined
}
);
} catch (err) {
throw this.mapContentManagementError(err);
}
}
/**
* Http Delete response
* @param url Url of request
* @param body Body of the request (names and values)
* @param config Query configuration
*/
protected async deleteResponseAsync<TRawData>(
url: string,
internalConfig: IContentManagementInternalQueryConfig,
config: IContentManagementQueryConfig
): Promise<IResponse<TRawData>> {
try {
return await this.httpService.deleteAsync<TRawData>(
{
url: url
},
{
cancelToken: config.cancelTokenRequest,
retryStrategy: this.config.retryStrategy,
headers: this.getHeaders(config),
responseType:
internalConfig && internalConfig.responseType ? internalConfig.responseType : undefined
}
);
} catch (err) {
throw this.mapContentManagementError(err);
}
}
protected async getBinaryDataFromUrlAsync(url: string): Promise<ArrayBuffer> {
// temp fix for repository not validating url
url = url.replace('#', '%23');
const response = await this.httpService.getAsync<ArrayBuffer>(
{
url: url
},
{
responseType: 'arraybuffer'
}
);
return response.data;
}
protected getMimeTypeFromFilename(filename: string): string | null {
return getType(filename);
}
private mapContentManagementError(error: any): any {
let axiosError: AxiosError | undefined;
if (error.error) {
axiosError = error.error;
} else {
axiosError = error;
}
if (!axiosError || !axiosError.isAxiosError) {
return error;
}
const cmError = axiosError.response?.data as SharedContracts.IContentManagementError;
if (cmError?.error_code || cmError?.request_id) {
const validationErrors: SharedModels.ValidationError[] = [];
if (cmError.validation_errors) {
validationErrors.push(
...cmError.validation_errors.map(
(validationErrorRaw) =>
new SharedModels.ValidationError({
message: validationErrorRaw.message
})
)
);
}
return new SharedModels.ContentManagementBaseKontentError({
errorCode: cmError.error_code,
message: cmError.message,
originalError: error,
requestId: cmError.request_id,
validationErrors: validationErrors
});
}
return error;
}
/**
* Gets authorization header
*/
private getAuthorizationHeader(): IHeader {
const key: string = this.config.apiKey;
if (!key) {
throw Error(`Cannot get authorization header for query type because API Key is undefined`);
}
return {
header: 'authorization',
value: `bearer ${key}`
};
}
/**
* Gets base URL of the request including the project Id
*/
private getBaseUrl(): string {
if (this.config.baseUrl) {
return this.config.baseUrl;
}
return this.defaultBaseCMUrl;
}
}