mirror of
https://github.com/C9Glax/tranga-website.git
synced 2025-09-10 11:58:20 +02:00
Custom loadanimations for custom components
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Button, CircularProgress } from '@mui/joy'
|
||||
import { Button } from '@mui/joy'
|
||||
import TProps, { TColor, TDisabled, TState } from './TProps.ts'
|
||||
import { MouseEventHandler, ReactNode, useState } from 'react'
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function TButton(props: TButtonProps) {
|
||||
disabled={props.disabled ?? TDisabled(state)}
|
||||
aria-disabled={props.disabled ?? TDisabled(state)}
|
||||
onClick={clicked}
|
||||
startDecorator={TDisabled(state) ? <CircularProgress /> : null}
|
||||
className={'t-loadable'}
|
||||
>
|
||||
{props.children}
|
||||
</Button>
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import { Button, CircularProgress, Input } from '@mui/joy'
|
||||
import { Button, Input } from '@mui/joy'
|
||||
import { MouseEventHandler, useEffect, useState } from 'react'
|
||||
import * as React from 'react'
|
||||
import TProps, { TColor, TDisabled, TState } from './TProps.ts'
|
||||
import './loadingBorder.css'
|
||||
|
||||
export default function TInput(props: TInputProps) {
|
||||
const [state, setState] = useState<TState>(TState.clean)
|
||||
@@ -63,7 +64,7 @@ export default function TInput(props: TInputProps) {
|
||||
value={value}
|
||||
onChange={inputValueChanged}
|
||||
onKeyDown={keyDownHandler}
|
||||
startDecorator={TDisabled(state) ? <CircularProgress /> : null}
|
||||
className={'t-loadable'}
|
||||
endDecorator={
|
||||
props.submitButtonHidden ? null : (
|
||||
<Button
|
||||
|
56
tranga-website/src/Components/Inputs/loadingBorder.css
Normal file
56
tranga-website/src/Components/Inputs/loadingBorder.css
Normal file
@@ -0,0 +1,56 @@
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
100% {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
.t-loadable {
|
||||
position: relative;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute !important;
|
||||
z-index: -2 !important;
|
||||
transform-origin: 50% 50%;
|
||||
left: -100vw !important;
|
||||
top: -100vh !important;
|
||||
width: 200vw !important;
|
||||
height: 200vh !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-image: linear-gradient(
|
||||
var(--joy-palette-primary-200),
|
||||
var(--joy-palette-primary-200)
|
||||
);
|
||||
animation: rotate 4s linear infinite;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
width: calc(100% - 4px);
|
||||
height: calc(100% - 4px);
|
||||
background: black;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.t-loadable[aria-disabled='true'] {
|
||||
&::before {
|
||||
background-image: linear-gradient(
|
||||
var(--joy-palette-danger-300),
|
||||
var(--joy-palette-success-600)
|
||||
);
|
||||
}
|
||||
}
|
1411
tranga-website/src/api/V2.ts
Normal file
1411
tranga-website/src/api/V2.ts
Normal file
File diff suppressed because it is too large
Load Diff
405
tranga-website/src/api/data-contracts.ts
Normal file
405
tranga-website/src/api/data-contracts.ts
Normal file
@@ -0,0 +1,405 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
export enum WorkerExecutionState {
|
||||
Failed = 'Failed',
|
||||
Cancelled = 'Cancelled',
|
||||
Created = 'Created',
|
||||
Waiting = 'Waiting',
|
||||
Running = 'Running',
|
||||
Completed = 'Completed',
|
||||
}
|
||||
|
||||
export enum RequestType {
|
||||
Default = 'Default',
|
||||
MangaDexFeed = 'MangaDexFeed',
|
||||
MangaImage = 'MangaImage',
|
||||
MangaCover = 'MangaCover',
|
||||
MangaDexImage = 'MangaDexImage',
|
||||
MangaInfo = 'MangaInfo',
|
||||
}
|
||||
|
||||
export enum MangaReleaseStatus {
|
||||
Continuing = 'Continuing',
|
||||
Completed = 'Completed',
|
||||
OnHiatus = 'OnHiatus',
|
||||
Cancelled = 'Cancelled',
|
||||
Unreleased = 'Unreleased',
|
||||
}
|
||||
|
||||
export enum LibraryType {
|
||||
Komga = 'Komga',
|
||||
Kavita = 'Kavita',
|
||||
}
|
||||
|
||||
/** API.Schema.MangaContext.AltTitle DTO */
|
||||
export interface AltTitle {
|
||||
/**
|
||||
* Language of the Title
|
||||
* @minLength 1
|
||||
*/
|
||||
language: string
|
||||
/**
|
||||
* Title
|
||||
* @minLength 1
|
||||
*/
|
||||
title: string
|
||||
}
|
||||
|
||||
/** The API.Schema.MangaContext.Author DTO */
|
||||
export interface Author {
|
||||
/**
|
||||
* Name of the Author.
|
||||
* @minLength 1
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
/** API.Schema.MangaContext.Chapter DTO */
|
||||
export interface Chapter {
|
||||
/**
|
||||
* Identifier of the Manga this Chapter belongs to
|
||||
* @minLength 1
|
||||
*/
|
||||
mangaId: string
|
||||
/**
|
||||
* Volume number
|
||||
* @format int32
|
||||
*/
|
||||
volume: number
|
||||
/**
|
||||
* Chapter number
|
||||
* @minLength 1
|
||||
*/
|
||||
chapterNumber: string
|
||||
/**
|
||||
* Title of the Chapter
|
||||
* @minLength 1
|
||||
*/
|
||||
title: string
|
||||
/** Whether Chapter is Downloaded (on disk) */
|
||||
downloaded: boolean
|
||||
/** Ids of the Manga on MangaConnectors */
|
||||
mangaConnectorIds: MangaConnectorId[]
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface FileLibrary {
|
||||
/**
|
||||
* @minLength 0
|
||||
* @maxLength 256
|
||||
*/
|
||||
basePath: string
|
||||
/**
|
||||
* @minLength 0
|
||||
* @maxLength 512
|
||||
*/
|
||||
libraryName: string
|
||||
/**
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface GotifyRecord {
|
||||
name?: string | null
|
||||
endpoint?: string | null
|
||||
appToken?: string | null
|
||||
/** @format int32 */
|
||||
priority?: number
|
||||
}
|
||||
|
||||
export interface LibraryConnector {
|
||||
libraryType: LibraryType
|
||||
/**
|
||||
* @format uri
|
||||
* @minLength 0
|
||||
* @maxLength 256
|
||||
*/
|
||||
baseUrl: string
|
||||
/**
|
||||
* @minLength 0
|
||||
* @maxLength 256
|
||||
*/
|
||||
auth: string
|
||||
/**
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
/** API.Schema.MangaContext.Link DTO */
|
||||
export interface Link {
|
||||
/**
|
||||
* Name of the Provider
|
||||
* @minLength 1
|
||||
*/
|
||||
provider: string
|
||||
/**
|
||||
* Url
|
||||
* @minLength 1
|
||||
*/
|
||||
url: string
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
/** API.Schema.MangaContext.Manga DTO */
|
||||
export interface Manga {
|
||||
/**
|
||||
* Chapter cutoff for Downloads (Chapters before this will not be downloaded)
|
||||
* @format float
|
||||
*/
|
||||
ignoreChaptersBefore: number
|
||||
/**
|
||||
* Release Year
|
||||
* @format int32
|
||||
*/
|
||||
year?: number | null
|
||||
/** Release Language */
|
||||
originalLanguage?: string | null
|
||||
/** Keys of ChapterDTOs */
|
||||
chapterIds: string[]
|
||||
/** Author-names */
|
||||
authors: Author[]
|
||||
/** Manga Tags */
|
||||
tags: string[]
|
||||
/** Links for more Metadata */
|
||||
links: Link[]
|
||||
/** Alt Titles of Manga */
|
||||
altTitles: AltTitle[]
|
||||
/**
|
||||
* Name of the Manga
|
||||
* @minLength 1
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* Description of the Manga
|
||||
* @minLength 1
|
||||
*/
|
||||
description: string
|
||||
releaseStatus: MangaReleaseStatus
|
||||
/** Ids of the Manga on MangaConnectors */
|
||||
mangaConnectorIds: MangaConnectorId[]
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface MangaConnector {
|
||||
name?: string | null
|
||||
/** Whether Connector is used for Searches and Downloads */
|
||||
enabled: boolean
|
||||
/** Languages supported by the Connector */
|
||||
supportedLanguages: string[]
|
||||
/**
|
||||
* Url of the Website Icon
|
||||
* @minLength 1
|
||||
*/
|
||||
iconUrl: string
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
/** API.Schema.MangaContext.MangaConnectorId`1 DTO */
|
||||
export interface MangaConnectorId {
|
||||
/**
|
||||
* Name of the Connector
|
||||
* @minLength 1
|
||||
*/
|
||||
mangaConnectorName: string
|
||||
/**
|
||||
* Key of the referenced DTO
|
||||
* @minLength 1
|
||||
*/
|
||||
foreignKey: string
|
||||
/** Website Link for reference, if any */
|
||||
websiteUrl?: string | null
|
||||
/** Whether this Link is used for downloads */
|
||||
useForDownload: boolean
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface MetadataEntry {
|
||||
mangaId?: string | null
|
||||
metadataFetcherName?: string | null
|
||||
identifier?: string | null
|
||||
}
|
||||
|
||||
export interface MetadataSearchResult {
|
||||
identifier?: string | null
|
||||
name?: string | null
|
||||
url?: string | null
|
||||
description?: string | null
|
||||
coverUrl?: string | null
|
||||
}
|
||||
|
||||
/** Shortened Version of API.Controllers.DTOs.Manga */
|
||||
export interface MinimalManga {
|
||||
/**
|
||||
* Name of the Manga
|
||||
* @minLength 1
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* Description of the Manga
|
||||
* @minLength 1
|
||||
*/
|
||||
description: string
|
||||
releaseStatus: MangaReleaseStatus
|
||||
/** Ids of the Manga on MangaConnectors */
|
||||
mangaConnectorIds: MangaConnectorId[]
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface NotificationConnector {
|
||||
/**
|
||||
* @minLength 0
|
||||
* @maxLength 64
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* @format uri
|
||||
* @minLength 0
|
||||
* @maxLength 2048
|
||||
*/
|
||||
url: string
|
||||
headers: Record<string, string>
|
||||
/**
|
||||
* @minLength 0
|
||||
* @maxLength 8
|
||||
*/
|
||||
httpMethod: string
|
||||
/**
|
||||
* @minLength 0
|
||||
* @maxLength 4096
|
||||
*/
|
||||
body: string
|
||||
}
|
||||
|
||||
export interface NtfyRecord {
|
||||
name?: string | null
|
||||
endpoint?: string | null
|
||||
username?: string | null
|
||||
password?: string | null
|
||||
topic?: string | null
|
||||
/** @format int32 */
|
||||
priority?: number
|
||||
}
|
||||
|
||||
export interface ProblemDetails {
|
||||
type?: string | null
|
||||
title?: string | null
|
||||
/** @format int32 */
|
||||
status?: number | null
|
||||
detail?: string | null
|
||||
instance?: string | null
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface PushoverRecord {
|
||||
name?: string | null
|
||||
appToken?: string | null
|
||||
user?: string | null
|
||||
}
|
||||
|
||||
export interface TrangaSettings {
|
||||
downloadLocation?: string | null
|
||||
userAgent?: string | null
|
||||
/** @format int32 */
|
||||
imageCompression?: number
|
||||
blackWhiteImages?: boolean
|
||||
flareSolverrUrl?: string | null
|
||||
/**
|
||||
* Placeholders:
|
||||
* %M Obj Name
|
||||
* %V Volume
|
||||
* %C Chapter
|
||||
* %T Title
|
||||
* %A Author (first in list)
|
||||
* %I Chapter Internal ID
|
||||
* %i Obj Internal ID
|
||||
* %Y Year (Obj)
|
||||
*
|
||||
* ?_(...) replace _ with a value from above:
|
||||
* Everything inside the braces will only be added if the value of %_ is not null
|
||||
*/
|
||||
chapterNamingScheme?: string | null
|
||||
/** @format int32 */
|
||||
workCycleTimeoutMs?: number
|
||||
requestLimits?: {
|
||||
/** @format int32 */
|
||||
Default?: number
|
||||
/** @format int32 */
|
||||
MangaDexFeed?: number
|
||||
/** @format int32 */
|
||||
MangaImage?: number
|
||||
/** @format int32 */
|
||||
MangaCover?: number
|
||||
/** @format int32 */
|
||||
MangaDexImage?: number
|
||||
/** @format int32 */
|
||||
MangaInfo?: number
|
||||
} | null
|
||||
downloadLanguage?: string | null
|
||||
}
|
||||
|
||||
/** API.Workers.BaseWorker DTO */
|
||||
export interface Worker {
|
||||
/** Workers this worker depends on having ran. */
|
||||
dependencies: string[]
|
||||
/** Workers that have not yet ran, that need to run for this Worker to run. */
|
||||
missingDependencies: string[]
|
||||
/** Worker can run. */
|
||||
dependenciesFulfilled: boolean
|
||||
state: WorkerExecutionState
|
||||
/**
|
||||
* Unique Identifier of the DTO
|
||||
* @minLength 16
|
||||
* @maxLength 64
|
||||
*/
|
||||
key: string
|
||||
}
|
265
tranga-website/src/api/http-client.ts
Normal file
265
tranga-website/src/api/http-client.ts
Normal file
@@ -0,0 +1,265 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* ---------------------------------------------------------------
|
||||
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
|
||||
* ## ##
|
||||
* ## AUTHOR: acacode ##
|
||||
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
export type QueryParamsType = Record<string | number, any>
|
||||
export type ResponseFormat = keyof Omit<Body, 'body' | 'bodyUsed'>
|
||||
|
||||
export interface FullRequestParams extends Omit<RequestInit, 'body'> {
|
||||
/** set parameter to `true` for call `securityWorker` for this request */
|
||||
secure?: boolean
|
||||
/** request path */
|
||||
path: string
|
||||
/** content type of request body */
|
||||
type?: ContentType
|
||||
/** query params */
|
||||
query?: QueryParamsType
|
||||
/** format of response (i.e. response.json() -> format: "json") */
|
||||
format?: ResponseFormat
|
||||
/** request body */
|
||||
body?: unknown
|
||||
/** base url */
|
||||
baseUrl?: string
|
||||
/** request cancellation token */
|
||||
cancelToken?: CancelToken
|
||||
}
|
||||
|
||||
export type RequestParams = Omit<
|
||||
FullRequestParams,
|
||||
'body' | 'method' | 'query' | 'path'
|
||||
>
|
||||
|
||||
export interface ApiConfig<SecurityDataType = unknown> {
|
||||
baseUrl?: string
|
||||
baseApiParams?: Omit<RequestParams, 'baseUrl' | 'cancelToken' | 'signal'>
|
||||
securityWorker?: (
|
||||
securityData: SecurityDataType | null
|
||||
) => Promise<RequestParams | void> | RequestParams | void
|
||||
customFetch?: typeof fetch
|
||||
}
|
||||
|
||||
export interface HttpResponse<D extends unknown, E extends unknown = unknown>
|
||||
extends Response {
|
||||
data: D
|
||||
error: E
|
||||
}
|
||||
|
||||
type CancelToken = Symbol | string | number
|
||||
|
||||
export enum ContentType {
|
||||
Json = 'application/json',
|
||||
JsonApi = 'application/vnd.api+json',
|
||||
FormData = 'multipart/form-data',
|
||||
UrlEncoded = 'application/x-www-form-urlencoded',
|
||||
Text = 'text/plain',
|
||||
}
|
||||
|
||||
export class HttpClient<SecurityDataType = unknown> {
|
||||
public baseUrl: string = ''
|
||||
private securityData: SecurityDataType | null = null
|
||||
private securityWorker?: ApiConfig<SecurityDataType>['securityWorker']
|
||||
private abortControllers = new Map<CancelToken, AbortController>()
|
||||
private customFetch = (...fetchParams: Parameters<typeof fetch>) =>
|
||||
fetch(...fetchParams)
|
||||
|
||||
private baseApiParams: RequestParams = {
|
||||
credentials: 'same-origin',
|
||||
headers: {},
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
}
|
||||
|
||||
constructor(apiConfig: ApiConfig<SecurityDataType> = {}) {
|
||||
Object.assign(this, apiConfig)
|
||||
}
|
||||
|
||||
public setSecurityData = (data: SecurityDataType | null) => {
|
||||
this.securityData = data
|
||||
}
|
||||
|
||||
protected encodeQueryParam(key: string, value: any) {
|
||||
const encodedKey = encodeURIComponent(key)
|
||||
return `${encodedKey}=${encodeURIComponent(typeof value === 'number' ? value : `${value}`)}`
|
||||
}
|
||||
|
||||
protected addQueryParam(query: QueryParamsType, key: string) {
|
||||
return this.encodeQueryParam(key, query[key])
|
||||
}
|
||||
|
||||
protected addArrayQueryParam(query: QueryParamsType, key: string) {
|
||||
const value = query[key]
|
||||
return value.map((v: any) => this.encodeQueryParam(key, v)).join('&')
|
||||
}
|
||||
|
||||
protected toQueryString(rawQuery?: QueryParamsType): string {
|
||||
const query = rawQuery || {}
|
||||
const keys = Object.keys(query).filter(
|
||||
(key) => 'undefined' !== typeof query[key]
|
||||
)
|
||||
return keys
|
||||
.map((key) =>
|
||||
Array.isArray(query[key])
|
||||
? this.addArrayQueryParam(query, key)
|
||||
: this.addQueryParam(query, key)
|
||||
)
|
||||
.join('&')
|
||||
}
|
||||
|
||||
protected addQueryParams(rawQuery?: QueryParamsType): string {
|
||||
const queryString = this.toQueryString(rawQuery)
|
||||
return queryString ? `?${queryString}` : ''
|
||||
}
|
||||
|
||||
private contentFormatters: Record<ContentType, (input: any) => any> = {
|
||||
[ContentType.Json]: (input: any) =>
|
||||
input !== null &&
|
||||
(typeof input === 'object' || typeof input === 'string')
|
||||
? JSON.stringify(input)
|
||||
: input,
|
||||
[ContentType.JsonApi]: (input: any) =>
|
||||
input !== null &&
|
||||
(typeof input === 'object' || typeof input === 'string')
|
||||
? JSON.stringify(input)
|
||||
: input,
|
||||
[ContentType.Text]: (input: any) =>
|
||||
input !== null && typeof input !== 'string'
|
||||
? JSON.stringify(input)
|
||||
: input,
|
||||
[ContentType.FormData]: (input: any) =>
|
||||
Object.keys(input || {}).reduce((formData, key) => {
|
||||
const property = input[key]
|
||||
formData.append(
|
||||
key,
|
||||
property instanceof Blob
|
||||
? property
|
||||
: typeof property === 'object' && property !== null
|
||||
? JSON.stringify(property)
|
||||
: `${property}`
|
||||
)
|
||||
return formData
|
||||
}, new FormData()),
|
||||
[ContentType.UrlEncoded]: (input: any) => this.toQueryString(input),
|
||||
}
|
||||
|
||||
protected mergeRequestParams(
|
||||
params1: RequestParams,
|
||||
params2?: RequestParams
|
||||
): RequestParams {
|
||||
return {
|
||||
...this.baseApiParams,
|
||||
...params1,
|
||||
...(params2 || {}),
|
||||
headers: {
|
||||
...(this.baseApiParams.headers || {}),
|
||||
...(params1.headers || {}),
|
||||
...((params2 && params2.headers) || {}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
protected createAbortSignal = (
|
||||
cancelToken: CancelToken
|
||||
): AbortSignal | undefined => {
|
||||
if (this.abortControllers.has(cancelToken)) {
|
||||
const abortController = this.abortControllers.get(cancelToken)
|
||||
if (abortController) {
|
||||
return abortController.signal
|
||||
}
|
||||
return void 0
|
||||
}
|
||||
|
||||
const abortController = new AbortController()
|
||||
this.abortControllers.set(cancelToken, abortController)
|
||||
return abortController.signal
|
||||
}
|
||||
|
||||
public abortRequest = (cancelToken: CancelToken) => {
|
||||
const abortController = this.abortControllers.get(cancelToken)
|
||||
|
||||
if (abortController) {
|
||||
abortController.abort()
|
||||
this.abortControllers.delete(cancelToken)
|
||||
}
|
||||
}
|
||||
|
||||
public request = async <T = any, E = any>({
|
||||
body,
|
||||
secure,
|
||||
path,
|
||||
type,
|
||||
query,
|
||||
format,
|
||||
baseUrl,
|
||||
cancelToken,
|
||||
...params
|
||||
}: FullRequestParams): Promise<HttpResponse<T, E>> => {
|
||||
const secureParams =
|
||||
((typeof secure === 'boolean'
|
||||
? secure
|
||||
: this.baseApiParams.secure) &&
|
||||
this.securityWorker &&
|
||||
(await this.securityWorker(this.securityData))) ||
|
||||
{}
|
||||
const requestParams = this.mergeRequestParams(params, secureParams)
|
||||
const queryString = query && this.toQueryString(query)
|
||||
const payloadFormatter =
|
||||
this.contentFormatters[type || ContentType.Json]
|
||||
const responseFormat = format || requestParams.format
|
||||
|
||||
return this.customFetch(
|
||||
`${baseUrl || this.baseUrl || ''}${path}${queryString ? `?${queryString}` : ''}`,
|
||||
{
|
||||
...requestParams,
|
||||
headers: {
|
||||
...(requestParams.headers || {}),
|
||||
...(type && type !== ContentType.FormData
|
||||
? { 'Content-Type': type }
|
||||
: {}),
|
||||
},
|
||||
signal:
|
||||
(cancelToken
|
||||
? this.createAbortSignal(cancelToken)
|
||||
: requestParams.signal) || null,
|
||||
body:
|
||||
typeof body === 'undefined' || body === null
|
||||
? null
|
||||
: payloadFormatter(body),
|
||||
}
|
||||
).then(async (response) => {
|
||||
const r = response.clone() as HttpResponse<T, E>
|
||||
r.data = null as unknown as T
|
||||
r.error = null as unknown as E
|
||||
|
||||
const data = !responseFormat
|
||||
? r
|
||||
: await response[responseFormat]()
|
||||
.then((data) => {
|
||||
if (r.ok) {
|
||||
r.data = data
|
||||
} else {
|
||||
r.error = data
|
||||
}
|
||||
return r
|
||||
})
|
||||
.catch((e) => {
|
||||
r.error = e
|
||||
return r
|
||||
})
|
||||
|
||||
if (cancelToken) {
|
||||
this.abortControllers.delete(cancelToken)
|
||||
}
|
||||
|
||||
if (!response.ok) throw data
|
||||
return data
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user