mirror of
https://github.com/tiqi-group/pydase_service_base.git
synced 2025-04-22 01:00:03 +02:00
chore: formatting
This commit is contained in:
parent
2e9f95211f
commit
e84c19a4be
@ -4,4 +4,4 @@ export { ApiResult } from './src/ApiResult';
|
|||||||
export { CancelError, CancelablePromise, OnCancel } from './src/CancelablePromise';
|
export { CancelError, CancelablePromise, OnCancel } from './src/CancelablePromise';
|
||||||
export { OpenAPI } from './src/OpenAPI';
|
export { OpenAPI } from './src/OpenAPI';
|
||||||
export type { OpenAPIConfig } from './src/OpenAPI';
|
export type { OpenAPIConfig } from './src/OpenAPI';
|
||||||
export { request } from './src/request';
|
export { request } from './src/request';
|
||||||
|
@ -5,20 +5,20 @@ import type { ApiRequestOptions } from './ApiRequestOptions';
|
|||||||
import type { ApiResult } from './ApiResult';
|
import type { ApiResult } from './ApiResult';
|
||||||
|
|
||||||
export class ApiError extends Error {
|
export class ApiError extends Error {
|
||||||
public readonly url: string;
|
public readonly url: string;
|
||||||
public readonly status: number;
|
public readonly status: number;
|
||||||
public readonly statusText: string;
|
public readonly statusText: string;
|
||||||
public readonly body: any;
|
public readonly body: any;
|
||||||
public readonly request: ApiRequestOptions;
|
public readonly request: ApiRequestOptions;
|
||||||
|
|
||||||
constructor(request: ApiRequestOptions, response: ApiResult, message: string) {
|
constructor(request: ApiRequestOptions, response: ApiResult, message: string) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
||||||
this.name = 'ApiError';
|
this.name = 'ApiError';
|
||||||
this.url = response.url;
|
this.url = response.url;
|
||||||
this.status = response.status;
|
this.status = response.status;
|
||||||
this.statusText = response.statusText;
|
this.statusText = response.statusText;
|
||||||
this.body = response.body;
|
this.body = response.body;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
export type ApiRequestOptions = {
|
export type ApiRequestOptions = {
|
||||||
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
|
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
|
||||||
readonly url: string;
|
readonly url: string;
|
||||||
readonly path?: Record<string, any>;
|
readonly path?: Record<string, any>;
|
||||||
readonly cookies?: Record<string, any>;
|
readonly cookies?: Record<string, any>;
|
||||||
readonly headers?: Record<string, any>;
|
readonly headers?: Record<string, any>;
|
||||||
readonly query?: Record<string, any>;
|
readonly query?: Record<string, any>;
|
||||||
readonly formData?: Record<string, any>;
|
readonly formData?: Record<string, any>;
|
||||||
readonly body?: any;
|
readonly body?: any;
|
||||||
readonly mediaType?: string;
|
readonly mediaType?: string;
|
||||||
readonly responseHeader?: string;
|
readonly responseHeader?: string;
|
||||||
readonly errors?: Record<number, string>;
|
readonly errors?: Record<number, string>;
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
export type ApiResult = {
|
export type ApiResult = {
|
||||||
readonly url: string;
|
readonly url: string;
|
||||||
readonly ok: boolean;
|
readonly ok: boolean;
|
||||||
readonly status: number;
|
readonly status: number;
|
||||||
readonly statusText: string;
|
readonly statusText: string;
|
||||||
readonly body: any;
|
readonly body: any;
|
||||||
};
|
};
|
||||||
|
@ -2,127 +2,126 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
export class CancelError extends Error {
|
export class CancelError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'CancelError';
|
||||||
|
}
|
||||||
|
|
||||||
constructor(message: string) {
|
public get isCancelled(): boolean {
|
||||||
super(message);
|
return true;
|
||||||
this.name = 'CancelError';
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public get isCancelled(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OnCancel {
|
export interface OnCancel {
|
||||||
readonly isResolved: boolean;
|
readonly isResolved: boolean;
|
||||||
readonly isRejected: boolean;
|
readonly isRejected: boolean;
|
||||||
readonly isCancelled: boolean;
|
readonly isCancelled: boolean;
|
||||||
|
|
||||||
(cancelHandler: () => void): void;
|
(cancelHandler: () => void): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CancelablePromise<T> implements Promise<T> {
|
export class CancelablePromise<T> implements Promise<T> {
|
||||||
readonly [Symbol.toStringTag]!: string;
|
readonly [Symbol.toStringTag]!: string;
|
||||||
|
|
||||||
private _isResolved: boolean;
|
private _isResolved: boolean;
|
||||||
private _isRejected: boolean;
|
private _isRejected: boolean;
|
||||||
private _isCancelled: boolean;
|
private _isCancelled: boolean;
|
||||||
private readonly _cancelHandlers: (() => void)[];
|
private readonly _cancelHandlers: (() => void)[];
|
||||||
private readonly _promise: Promise<T>;
|
private readonly _promise: Promise<T>;
|
||||||
private _resolve?: (value: T | PromiseLike<T>) => void;
|
private _resolve?: (value: T | PromiseLike<T>) => void;
|
||||||
private _reject?: (reason?: any) => void;
|
private _reject?: (reason?: any) => void;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
executor: (
|
executor: (
|
||||||
resolve: (value: T | PromiseLike<T>) => void,
|
resolve: (value: T | PromiseLike<T>) => void,
|
||||||
reject: (reason?: any) => void,
|
reject: (reason?: any) => void,
|
||||||
onCancel: OnCancel
|
onCancel: OnCancel
|
||||||
) => void
|
) => void
|
||||||
) {
|
) {
|
||||||
this._isResolved = false;
|
this._isResolved = false;
|
||||||
this._isRejected = false;
|
this._isRejected = false;
|
||||||
this._isCancelled = false;
|
this._isCancelled = false;
|
||||||
this._cancelHandlers = [];
|
this._cancelHandlers = [];
|
||||||
this._promise = new Promise<T>((resolve, reject) => {
|
this._promise = new Promise<T>((resolve, reject) => {
|
||||||
this._resolve = resolve;
|
this._resolve = resolve;
|
||||||
this._reject = reject;
|
this._reject = reject;
|
||||||
|
|
||||||
const onResolve = (value: T | PromiseLike<T>): void => {
|
const onResolve = (value: T | PromiseLike<T>): void => {
|
||||||
if (this._isResolved || this._isRejected || this._isCancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._isResolved = true;
|
|
||||||
this._resolve?.(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onReject = (reason?: any): void => {
|
|
||||||
if (this._isResolved || this._isRejected || this._isCancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._isRejected = true;
|
|
||||||
this._reject?.(reason);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onCancel = (cancelHandler: () => void): void => {
|
|
||||||
if (this._isResolved || this._isRejected || this._isCancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._cancelHandlers.push(cancelHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(onCancel, 'isResolved', {
|
|
||||||
get: (): boolean => this._isResolved,
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(onCancel, 'isRejected', {
|
|
||||||
get: (): boolean => this._isRejected,
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(onCancel, 'isCancelled', {
|
|
||||||
get: (): boolean => this._isCancelled,
|
|
||||||
});
|
|
||||||
|
|
||||||
return executor(onResolve, onReject, onCancel as OnCancel);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public then<TResult1 = T, TResult2 = never>(
|
|
||||||
onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
|
|
||||||
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
||||||
): Promise<TResult1 | TResult2> {
|
|
||||||
return this._promise.then(onFulfilled, onRejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public catch<TResult = never>(
|
|
||||||
onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
||||||
): Promise<T | TResult> {
|
|
||||||
return this._promise.catch(onRejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public finally(onFinally?: (() => void) | null): Promise<T> {
|
|
||||||
return this._promise.finally(onFinally);
|
|
||||||
}
|
|
||||||
|
|
||||||
public cancel(): void {
|
|
||||||
if (this._isResolved || this._isRejected || this._isCancelled) {
|
if (this._isResolved || this._isRejected || this._isCancelled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._isCancelled = true;
|
this._isResolved = true;
|
||||||
if (this._cancelHandlers.length) {
|
this._resolve?.(value);
|
||||||
try {
|
};
|
||||||
for (const cancelHandler of this._cancelHandlers) {
|
|
||||||
cancelHandler();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Cancellation threw an error', error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._cancelHandlers.length = 0;
|
|
||||||
this._reject?.(new CancelError('Request aborted'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isCancelled(): boolean {
|
const onReject = (reason?: any): void => {
|
||||||
return this._isCancelled;
|
if (this._isResolved || this._isRejected || this._isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._isRejected = true;
|
||||||
|
this._reject?.(reason);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCancel = (cancelHandler: () => void): void => {
|
||||||
|
if (this._isResolved || this._isRejected || this._isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._cancelHandlers.push(cancelHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(onCancel, 'isResolved', {
|
||||||
|
get: (): boolean => this._isResolved
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(onCancel, 'isRejected', {
|
||||||
|
get: (): boolean => this._isRejected
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(onCancel, 'isCancelled', {
|
||||||
|
get: (): boolean => this._isCancelled
|
||||||
|
});
|
||||||
|
|
||||||
|
return executor(onResolve, onReject, onCancel as OnCancel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public then<TResult1 = T, TResult2 = never>(
|
||||||
|
onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
|
||||||
|
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
||||||
|
): Promise<TResult1 | TResult2> {
|
||||||
|
return this._promise.then(onFulfilled, onRejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public catch<TResult = never>(
|
||||||
|
onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
||||||
|
): Promise<T | TResult> {
|
||||||
|
return this._promise.catch(onRejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public finally(onFinally?: (() => void) | null): Promise<T> {
|
||||||
|
return this._promise.finally(onFinally);
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancel(): void {
|
||||||
|
if (this._isResolved || this._isRejected || this._isCancelled) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this._isCancelled = true;
|
||||||
|
if (this._cancelHandlers.length) {
|
||||||
|
try {
|
||||||
|
for (const cancelHandler of this._cancelHandlers) {
|
||||||
|
cancelHandler();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Cancellation threw an error', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._cancelHandlers.length = 0;
|
||||||
|
this._reject?.(new CancelError('Request aborted'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isCancelled(): boolean {
|
||||||
|
return this._isCancelled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,25 +7,25 @@ type Resolver<T> = (options: ApiRequestOptions) => Promise<T>;
|
|||||||
type Headers = Record<string, string>;
|
type Headers = Record<string, string>;
|
||||||
|
|
||||||
export type OpenAPIConfig = {
|
export type OpenAPIConfig = {
|
||||||
BASE: string;
|
BASE: string;
|
||||||
VERSION: string;
|
VERSION: string;
|
||||||
WITH_CREDENTIALS: boolean;
|
WITH_CREDENTIALS: boolean;
|
||||||
CREDENTIALS: 'include' | 'omit' | 'same-origin';
|
CREDENTIALS: 'include' | 'omit' | 'same-origin';
|
||||||
TOKEN?: string | Resolver<string>;
|
TOKEN?: string | Resolver<string>;
|
||||||
USERNAME?: string | Resolver<string>;
|
USERNAME?: string | Resolver<string>;
|
||||||
PASSWORD?: string | Resolver<string>;
|
PASSWORD?: string | Resolver<string>;
|
||||||
HEADERS?: Headers | Resolver<Headers>;
|
HEADERS?: Headers | Resolver<Headers>;
|
||||||
ENCODE_PATH?: (path: string) => string;
|
ENCODE_PATH?: (path: string) => string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const OpenAPI: OpenAPIConfig = {
|
export const OpenAPI: OpenAPIConfig = {
|
||||||
BASE: 'https://icon-api.qchub.ch',
|
BASE: 'https://icon-api.qchub.ch',
|
||||||
VERSION: '1.0',
|
VERSION: '1.0',
|
||||||
WITH_CREDENTIALS: false,
|
WITH_CREDENTIALS: false,
|
||||||
CREDENTIALS: 'include',
|
CREDENTIALS: 'include',
|
||||||
TOKEN: undefined,
|
TOKEN: undefined,
|
||||||
USERNAME: undefined,
|
USERNAME: undefined,
|
||||||
PASSWORD: undefined,
|
PASSWORD: undefined,
|
||||||
HEADERS: undefined,
|
HEADERS: undefined,
|
||||||
ENCODE_PATH: undefined,
|
ENCODE_PATH: undefined
|
||||||
};
|
};
|
||||||
|
@ -8,263 +8,281 @@ import { CancelablePromise } from './CancelablePromise';
|
|||||||
import type { OnCancel } from './CancelablePromise';
|
import type { OnCancel } from './CancelablePromise';
|
||||||
import type { OpenAPIConfig } from './OpenAPI';
|
import type { OpenAPIConfig } from './OpenAPI';
|
||||||
|
|
||||||
const isDefined = <T>(value: T | null | undefined): value is Exclude<T, null | undefined> => {
|
const isDefined = <T>(
|
||||||
return value !== undefined && value !== null;
|
value: T | null | undefined
|
||||||
|
): value is Exclude<T, null | undefined> => {
|
||||||
|
return value !== undefined && value !== null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isString = (value: any): value is string => {
|
const isString = (value: any): value is string => {
|
||||||
return typeof value === 'string';
|
return typeof value === 'string';
|
||||||
};
|
};
|
||||||
|
|
||||||
const isStringWithValue = (value: any): value is string => {
|
const isStringWithValue = (value: any): value is string => {
|
||||||
return isString(value) && value !== '';
|
return isString(value) && value !== '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const isBlob = (value: any): value is Blob => {
|
const isBlob = (value: any): value is Blob => {
|
||||||
return (
|
return (
|
||||||
typeof value === 'object' &&
|
typeof value === 'object' &&
|
||||||
typeof value.type === 'string' &&
|
typeof value.type === 'string' &&
|
||||||
typeof value.stream === 'function' &&
|
typeof value.stream === 'function' &&
|
||||||
typeof value.arrayBuffer === 'function' &&
|
typeof value.arrayBuffer === 'function' &&
|
||||||
typeof value.constructor === 'function' &&
|
typeof value.constructor === 'function' &&
|
||||||
typeof value.constructor.name === 'string' &&
|
typeof value.constructor.name === 'string' &&
|
||||||
/^(Blob|File)$/.test(value.constructor.name) &&
|
/^(Blob|File)$/.test(value.constructor.name) &&
|
||||||
/^(Blob|File)$/.test(value[Symbol.toStringTag])
|
/^(Blob|File)$/.test(value[Symbol.toStringTag])
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isFormData = (value: any): value is FormData => {
|
const isFormData = (value: any): value is FormData => {
|
||||||
return value instanceof FormData;
|
return value instanceof FormData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const base64 = (str: string): string => {
|
const base64 = (str: string): string => {
|
||||||
try {
|
try {
|
||||||
return btoa(str);
|
return btoa(str);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return Buffer.from(str).toString('base64');
|
return Buffer.from(str).toString('base64');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getQueryString = (params: Record<string, any>): string => {
|
const getQueryString = (params: Record<string, any>): string => {
|
||||||
const qs: string[] = [];
|
const qs: string[] = [];
|
||||||
|
|
||||||
const append = (key: string, value: any) => {
|
const append = (key: string, value: any) => {
|
||||||
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const process = (key: string, value: any) => {
|
const process = (key: string, value: any) => {
|
||||||
if (isDefined(value)) {
|
if (isDefined(value)) {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
value.forEach(v => {
|
value.forEach((v) => {
|
||||||
process(key, v);
|
process(key, v);
|
||||||
});
|
});
|
||||||
} else if (typeof value === 'object') {
|
} else if (typeof value === 'object') {
|
||||||
Object.entries(value).forEach(([k, v]) => {
|
Object.entries(value).forEach(([k, v]) => {
|
||||||
process(`${key}[${k}]`, v);
|
process(`${key}[${k}]`, v);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
append(key, value);
|
append(key, value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.entries(params).forEach(([key, value]) => {
|
|
||||||
process(key, value);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (qs.length > 0) {
|
|
||||||
return `?${qs.join('&')}`;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return '';
|
Object.entries(params).forEach(([key, value]) => {
|
||||||
|
process(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (qs.length > 0) {
|
||||||
|
return `?${qs.join('&')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => {
|
const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => {
|
||||||
const encoder = config.ENCODE_PATH || encodeURI;
|
const encoder = config.ENCODE_PATH || encodeURI;
|
||||||
|
|
||||||
const path = options.url
|
const path = options.url
|
||||||
.replace('{api-version}', config.VERSION)
|
.replace('{api-version}', config.VERSION)
|
||||||
.replace(/{(.*?)}/g, (substring: string, group: string) => {
|
.replace(/{(.*?)}/g, (substring: string, group: string) => {
|
||||||
if (options.path?.hasOwnProperty(group)) {
|
if (options.path?.hasOwnProperty(group)) {
|
||||||
return encoder(String(options.path[group]));
|
return encoder(String(options.path[group]));
|
||||||
}
|
}
|
||||||
return substring;
|
return substring;
|
||||||
});
|
});
|
||||||
|
|
||||||
const url = `${config.BASE}${path}`;
|
const url = `${config.BASE}${path}`;
|
||||||
if (options.query) {
|
if (options.query) {
|
||||||
return `${url}${getQueryString(options.query)}`;
|
return `${url}${getQueryString(options.query)}`;
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFormData = (options: ApiRequestOptions): FormData | undefined => {
|
const getFormData = (options: ApiRequestOptions): FormData | undefined => {
|
||||||
if (options.formData) {
|
if (options.formData) {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
const process = (key: string, value: any) => {
|
const process = (key: string, value: any) => {
|
||||||
if (isString(value) || isBlob(value)) {
|
if (isString(value) || isBlob(value)) {
|
||||||
formData.append(key, value);
|
formData.append(key, value);
|
||||||
} else {
|
} else {
|
||||||
formData.append(key, JSON.stringify(value));
|
formData.append(key, JSON.stringify(value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.entries(options.formData)
|
Object.entries(options.formData)
|
||||||
.filter(([_, value]) => isDefined(value))
|
.filter(([_, value]) => isDefined(value))
|
||||||
.forEach(([key, value]) => {
|
.forEach(([key, value]) => {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
value.forEach(v => process(key, v));
|
value.forEach((v) => process(key, v));
|
||||||
} else {
|
} else {
|
||||||
process(key, value);
|
process(key, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Resolver<T> = (options: ApiRequestOptions) => Promise<T>;
|
type Resolver<T> = (options: ApiRequestOptions) => Promise<T>;
|
||||||
|
|
||||||
const resolve = async <T>(options: ApiRequestOptions, resolver?: T | Resolver<T>): Promise<T | undefined> => {
|
const resolve = async <T>(
|
||||||
if (typeof resolver === 'function') {
|
options: ApiRequestOptions,
|
||||||
return (resolver as Resolver<T>)(options);
|
resolver?: T | Resolver<T>
|
||||||
}
|
): Promise<T | undefined> => {
|
||||||
return resolver;
|
if (typeof resolver === 'function') {
|
||||||
|
return (resolver as Resolver<T>)(options);
|
||||||
|
}
|
||||||
|
return resolver;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise<Headers> => {
|
const getHeaders = async (
|
||||||
const token = await resolve(options, config.TOKEN);
|
config: OpenAPIConfig,
|
||||||
const username = await resolve(options, config.USERNAME);
|
options: ApiRequestOptions
|
||||||
const password = await resolve(options, config.PASSWORD);
|
): Promise<Headers> => {
|
||||||
const additionalHeaders = await resolve(options, config.HEADERS);
|
const token = await resolve(options, config.TOKEN);
|
||||||
|
const username = await resolve(options, config.USERNAME);
|
||||||
|
const password = await resolve(options, config.PASSWORD);
|
||||||
|
const additionalHeaders = await resolve(options, config.HEADERS);
|
||||||
|
|
||||||
const headers = Object.entries({
|
const headers = Object.entries({
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
...additionalHeaders,
|
...additionalHeaders,
|
||||||
...options.headers,
|
...options.headers
|
||||||
})
|
})
|
||||||
.filter(([_, value]) => isDefined(value))
|
.filter(([_, value]) => isDefined(value))
|
||||||
.reduce((headers, [key, value]) => ({
|
.reduce(
|
||||||
...headers,
|
(headers, [key, value]) => ({
|
||||||
[key]: String(value),
|
...headers,
|
||||||
}), {} as Record<string, string>);
|
[key]: String(value)
|
||||||
|
}),
|
||||||
|
{} as Record<string, string>
|
||||||
|
);
|
||||||
|
|
||||||
if (isStringWithValue(token)) {
|
if (isStringWithValue(token)) {
|
||||||
headers['Authorization'] = `Bearer ${token}`;
|
headers['Authorization'] = `Bearer ${token}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStringWithValue(username) && isStringWithValue(password)) {
|
||||||
|
const credentials = base64(`${username}:${password}`);
|
||||||
|
headers['Authorization'] = `Basic ${credentials}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.body) {
|
||||||
|
if (options.mediaType) {
|
||||||
|
headers['Content-Type'] = options.mediaType;
|
||||||
|
} else if (isBlob(options.body)) {
|
||||||
|
headers['Content-Type'] = options.body.type || 'application/octet-stream';
|
||||||
|
} else if (isString(options.body)) {
|
||||||
|
headers['Content-Type'] = 'text/plain';
|
||||||
|
} else if (!isFormData(options.body)) {
|
||||||
|
headers['Content-Type'] = 'application/json';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isStringWithValue(username) && isStringWithValue(password)) {
|
return new Headers(headers);
|
||||||
const credentials = base64(`${username}:${password}`);
|
|
||||||
headers['Authorization'] = `Basic ${credentials}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.body) {
|
|
||||||
if (options.mediaType) {
|
|
||||||
headers['Content-Type'] = options.mediaType;
|
|
||||||
} else if (isBlob(options.body)) {
|
|
||||||
headers['Content-Type'] = options.body.type || 'application/octet-stream';
|
|
||||||
} else if (isString(options.body)) {
|
|
||||||
headers['Content-Type'] = 'text/plain';
|
|
||||||
} else if (!isFormData(options.body)) {
|
|
||||||
headers['Content-Type'] = 'application/json';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Headers(headers);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRequestBody = (options: ApiRequestOptions): any => {
|
const getRequestBody = (options: ApiRequestOptions): any => {
|
||||||
if (options.body) {
|
if (options.body) {
|
||||||
if (options.mediaType?.includes('/json')) {
|
if (options.mediaType?.includes('/json')) {
|
||||||
return JSON.stringify(options.body)
|
return JSON.stringify(options.body);
|
||||||
} else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) {
|
} else if (
|
||||||
return options.body;
|
isString(options.body) ||
|
||||||
} else {
|
isBlob(options.body) ||
|
||||||
return JSON.stringify(options.body);
|
isFormData(options.body)
|
||||||
}
|
) {
|
||||||
|
return options.body;
|
||||||
|
} else {
|
||||||
|
return JSON.stringify(options.body);
|
||||||
}
|
}
|
||||||
return undefined;
|
}
|
||||||
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sendRequest = async (
|
export const sendRequest = async (
|
||||||
config: OpenAPIConfig,
|
config: OpenAPIConfig,
|
||||||
options: ApiRequestOptions,
|
options: ApiRequestOptions,
|
||||||
url: string,
|
url: string,
|
||||||
body: any,
|
body: any,
|
||||||
formData: FormData | undefined,
|
formData: FormData | undefined,
|
||||||
headers: Headers,
|
headers: Headers,
|
||||||
onCancel: OnCancel
|
onCancel: OnCancel
|
||||||
): Promise<Response> => {
|
): Promise<Response> => {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
|
||||||
const request: RequestInit = {
|
const request: RequestInit = {
|
||||||
headers,
|
headers,
|
||||||
body: body ?? formData,
|
body: body ?? formData,
|
||||||
method: options.method,
|
method: options.method,
|
||||||
signal: controller.signal,
|
signal: controller.signal
|
||||||
};
|
};
|
||||||
|
|
||||||
if (config.WITH_CREDENTIALS) {
|
if (config.WITH_CREDENTIALS) {
|
||||||
request.credentials = config.CREDENTIALS;
|
request.credentials = config.CREDENTIALS;
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancel(() => controller.abort());
|
onCancel(() => controller.abort());
|
||||||
|
|
||||||
return await fetch(url, request);
|
return await fetch(url, request);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => {
|
const getResponseHeader = (
|
||||||
if (responseHeader) {
|
response: Response,
|
||||||
const content = response.headers.get(responseHeader);
|
responseHeader?: string
|
||||||
if (isString(content)) {
|
): string | undefined => {
|
||||||
return content;
|
if (responseHeader) {
|
||||||
}
|
const content = response.headers.get(responseHeader);
|
||||||
|
if (isString(content)) {
|
||||||
|
return content;
|
||||||
}
|
}
|
||||||
return undefined;
|
}
|
||||||
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getResponseBody = async (response: Response): Promise<any> => {
|
const getResponseBody = async (response: Response): Promise<any> => {
|
||||||
if (response.status !== 204) {
|
if (response.status !== 204) {
|
||||||
try {
|
try {
|
||||||
const contentType = response.headers.get('Content-Type');
|
const contentType = response.headers.get('Content-Type');
|
||||||
if (contentType) {
|
if (contentType) {
|
||||||
const isJSON = contentType.toLowerCase().startsWith('application/json');
|
const isJSON = contentType.toLowerCase().startsWith('application/json');
|
||||||
if (isJSON) {
|
if (isJSON) {
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} else {
|
} else {
|
||||||
return await response.text();
|
return await response.text();
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
return undefined;
|
}
|
||||||
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
|
const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
|
||||||
const errors: Record<number, string> = {
|
const errors: Record<number, string> = {
|
||||||
400: 'Bad Request',
|
400: 'Bad Request',
|
||||||
401: 'Unauthorized',
|
401: 'Unauthorized',
|
||||||
403: 'Forbidden',
|
403: 'Forbidden',
|
||||||
404: 'Not Found',
|
404: 'Not Found',
|
||||||
500: 'Internal Server Error',
|
500: 'Internal Server Error',
|
||||||
502: 'Bad Gateway',
|
502: 'Bad Gateway',
|
||||||
503: 'Service Unavailable',
|
503: 'Service Unavailable',
|
||||||
...options.errors,
|
...options.errors
|
||||||
}
|
};
|
||||||
|
|
||||||
const error = errors[result.status];
|
const error = errors[result.status];
|
||||||
if (error) {
|
if (error) {
|
||||||
throw new ApiError(options, result, error);
|
throw new ApiError(options, result, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.ok) {
|
if (!result.ok) {
|
||||||
throw new ApiError(options, result, 'Generic Error');
|
throw new ApiError(options, result, 'Generic Error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,33 +292,44 @@ const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void =>
|
|||||||
* @returns CancelablePromise<T>
|
* @returns CancelablePromise<T>
|
||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> => {
|
export const request = <T>(
|
||||||
return new CancelablePromise(async (resolve, reject, onCancel) => {
|
config: OpenAPIConfig,
|
||||||
try {
|
options: ApiRequestOptions
|
||||||
const url = getUrl(config, options);
|
): CancelablePromise<T> => {
|
||||||
const formData = getFormData(options);
|
return new CancelablePromise(async (resolve, reject, onCancel) => {
|
||||||
const body = getRequestBody(options);
|
try {
|
||||||
const headers = await getHeaders(config, options);
|
const url = getUrl(config, options);
|
||||||
|
const formData = getFormData(options);
|
||||||
|
const body = getRequestBody(options);
|
||||||
|
const headers = await getHeaders(config, options);
|
||||||
|
|
||||||
if (!onCancel.isCancelled) {
|
if (!onCancel.isCancelled) {
|
||||||
const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
|
const response = await sendRequest(
|
||||||
const responseBody = await getResponseBody(response);
|
config,
|
||||||
const responseHeader = getResponseHeader(response, options.responseHeader);
|
options,
|
||||||
|
url,
|
||||||
|
body,
|
||||||
|
formData,
|
||||||
|
headers,
|
||||||
|
onCancel
|
||||||
|
);
|
||||||
|
const responseBody = await getResponseBody(response);
|
||||||
|
const responseHeader = getResponseHeader(response, options.responseHeader);
|
||||||
|
|
||||||
const result: ApiResult = {
|
const result: ApiResult = {
|
||||||
url,
|
url,
|
||||||
ok: response.ok,
|
ok: response.ok,
|
||||||
status: response.status,
|
status: response.status,
|
||||||
statusText: response.statusText,
|
statusText: response.statusText,
|
||||||
body: responseHeader ?? responseBody,
|
body: responseHeader ?? responseBody
|
||||||
};
|
};
|
||||||
|
|
||||||
catchErrorCodes(options, result);
|
catchErrorCodes(options, result);
|
||||||
|
|
||||||
resolve(result.body);
|
resolve(result.body);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user