{"version":3,"sources":["../src/internal/IDObject.ts","../src/internal/Relationship.ts","../src/internal/LocalizedString.ts","../src/util/APIResponseError.ts","../src/util/AuthError.ts","../src/util/Network.ts","../src/shared/Author.ts","../src/shared/Cover.ts","../src/shared/Tag.ts","../src/internal/Links.ts","../src/shared/Chapter.ts","../src/shared/Manga.ts","../src/shared/User.ts","../src/shared/Group.ts","../src/shared/UploadSession.ts","../src/shared/PersonalAuthClient.ts","../src/shared/LegacyAuthClient.ts","../src/shared/List.ts","../src/index.ts"],"sourcesContent":["/**\n * This class represents the most abstract version of a MangaDex object, containing\n * only the ID of the object. This is mostly used for instanceOf checks.\n * @internal\n */\nabstract class IDObject {\n    abstract id: string;\n}\n\nexport default IDObject;\n","import { RelationshipSchema } from '../types/schema';\nimport IDObject from '../internal/IDObject';\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\ntype GettableClass<T> = Function & { get: (id: string) => Promise<T>; getMultiple?: (ids: string[]) => Promise<T[]> };\n\ntype MFARelationshipSchema = Pick<RelationshipSchema, 'id' | 'type'> &\n    Partial<Pick<RelationshipSchema, 'related' | 'attributes'>> & { relationships?: Relationship[] };\n\n/**\n * Represents a relationship from one MangaDex object to another such as a manga, author, etc via its id.\n */\nclass Relationship<T extends IDObject = IDObject> extends IDObject {\n    /**\n     * The MangaDex UUID of the object this relationship refers to\n     */\n    id: string;\n    /**\n     * What type of object is this a relationship to\n     */\n    type: string;\n    /**\n     * If the relationship is between two manga, how are they related?\n     */\n    related?: RelationshipSchema['related'];\n    /**\n     * Cached relationships are created by using the 'includes' parameter on search requests or\n     * other functions that support it. For every type included in the parameter, relationships of\n     * that type will be replaced by the actual object. The object will still be represented\n     * by a Relationship object, but the {@link resolve} method will return instantly with the cached data.\n     * Each resulting object will have no further relationships of its own.\n     */\n    cached = false;\n\n    private cachedData?: object;\n\n    private static typeMap: Record<string, GettableClass<unknown>> = {};\n    private static typeMapLocked = false;\n\n    constructor(data: MFARelationshipSchema) {\n        super();\n        this.id = data.id;\n        if (!(data.type in Relationship.typeMap)) throw `Unregistered relationship type: ${data.type}`;\n        this.type = data.type;\n        this.related = data.related;\n\n        // Attempt to create cached object for reference expanded relationships\n        if (data.attributes) {\n            try {\n                const classObj = Relationship.typeMap[this.type];\n                // Attempt to simulate a common schema object:\n                const schemaObj = {\n                    attributes: data.attributes,\n                    id: this.id,\n                    type: this.type,\n                    relationships: data.relationships ?? [],\n                };\n                this.cachedData = Reflect.construct(classObj, [schemaObj]);\n                this.cached = true;\n            } catch (err) {\n                // console.log('Failed to create cache object');\n                // console.error(err);\n            }\n        }\n    }\n\n    /**\n     * Returns the cached related object, or undefined if nothing is cached.\n     * Unlike resolve(), this does not fetch data or perform any I/O.\n     */\n    peek() {\n        return this.cachedData as T | undefined;\n    }\n\n    /**\n     * This will automatically fetch the associated object that this relationship refers to.\n     * In other words, it wil call Manga.get(id), Chapter.get(id), etc with the information\n     * stored in this relationship instance. If this relationship is cached, then the resulting\n     * object will be missing relationships.\n     */\n    async resolve(): Promise<T> {\n        if (this.cached) return this.cachedData as T;\n        return Relationship.typeMap[this.type].get(this.id) as Promise<T>;\n    }\n\n    /**\n     * This will {@link Relationship.resolve} an array of relationships, returning another array\n     * in the same order.\n     * @param relationshipArray - An array of relationships of the same type\n     */\n    static async resolveAll<T extends IDObject>(relationshipArray: Relationship<T>[]): Promise<T[]> {\n        if (relationshipArray.length === 0) return [];\n        const classObj = Relationship.typeMap[relationshipArray[0].type] as GettableClass<T>;\n        if (classObj !== undefined && classObj.getMultiple !== undefined) {\n            return classObj.getMultiple(relationshipArray.map((i) => i.id));\n        } else {\n            return await Promise.all(relationshipArray.map((elem) => elem.resolve()));\n        }\n    }\n\n    /**\n     * This will search through a relationship response from MangaDex and convert any\n     * relationships of a specific type into relationship objects.\n     * @internal\n     */\n    static convertType<T2 extends IDObject>(\n        type: string,\n        arr: RelationshipSchema[],\n        parent?: Relationship<IDObject>,\n    ): Relationship<T2>[] {\n        return arr\n            .filter((elem) => elem.type === type)\n            .map((elem) => {\n                if (parent) return new Relationship<T2>({ ...elem, relationships: [parent] });\n                return new Relationship<T2>(elem);\n            });\n    }\n\n    /**\n     * Create a reference to an object's self\n     * @internal\n     */\n    static createSelfRelationship<T extends IDObject>(type: string, self: T) {\n        if (!self.id) throw new Error('ID is missing. Did you call this too early in the constructor?');\n        return new Relationship<T>({\n            id: self.id,\n            type,\n        });\n    }\n\n    /**\n     * This function is used to resolved circular references, and should only be used in base.ts.\n     * Specifically, it pairs a relationship type to its associated class.\n     * @internal\n     */\n    static registerTypes(types: string[], classObj: GettableClass<unknown>) {\n        if (Relationship.typeMapLocked) {\n            throw Error(`Cannot add types ${types} because the Relationship type map has been locked.`);\n        }\n        types.forEach((type) => (Relationship.typeMap[type] = classObj));\n    }\n\n    /**\n     * Lock the type map so that no more types can be registered.\n     * @internal\n     */\n    static lockTypeMap() {\n        Relationship.typeMapLocked = true;\n    }\n\n    /**\n     * Returns an array of all registered Relationship types\n     * @internal\n     */\n    static getRegisteredTypes() {\n        return Object.keys(Relationship.typeMap);\n    }\n}\n\nexport default Relationship;\n","import type { LocalizedStringSchema } from '../types/schema';\n\n/**\n * This class represents a map of locales and their associated strings.\n * Each string can be accessed by using the locale as the key (e.g. 'en', 'jp').\n * {@link localString} and {@link setGlobalLocale} can be used to\n * automatically access a preferred locale.\n * @example\n * var locStr;\n * locStr['en']; // English String\n * LocalizedString.setGlobalLocale('jp');\n * locStr.localString; // Japanese String\n */\nclass LocalizedString implements LocalizedStringSchema {\n    private static globalLocale = 'en';\n\n    [x: string]: string;\n\n    constructor(strings: LocalizedStringSchema) {\n        for (const locale in strings) {\n            this[locale] = strings[locale];\n        }\n    }\n\n    /**\n     * The string associated with the current global locale (set with setGlobalLocale()).\n     * If the global locale is not available for this string, the English string is returned.\n     * If that is also unavailable, the next available locale is returned. If no locales are\n     * available, an empty string is returned.\n     */\n    get localString() {\n        if (LocalizedString.globalLocale in this) return this[LocalizedString.globalLocale];\n        if ('en' in this) return this['en'];\n        // localString is not included in Object.keys(this)\n        for (const i of Object.keys(this)) if (typeof this[i] === 'string') return this[i];\n        return '';\n    }\n\n    /**\n     * This function sets the default locale used by {@link LocalizedString.localString}.\n     */\n    static setGlobalLocale(locale: string) {\n        if (locale.length < 2 || locale.length > 8) throw Error(`Locale \"${locale}\" has an invalid length`);\n        LocalizedString.globalLocale = locale;\n    }\n}\n\nexport default LocalizedString;\n","import { ErrorResponseSchema, ErrorSchema } from '../types/schema';\n\nexport default class APIResponseError extends Error {\n    constructor(info: ErrorResponseSchema | ErrorSchema[] | string) {\n        if (typeof info !== 'string') {\n            let errors: ErrorSchema[];\n            if ('result' in info) errors = info.errors;\n            else errors = info;\n\n            const parsedErrors = errors.map((err, i, arr) => {\n                let str = '';\n                if (arr.length > 1) str += `[${i} of ${arr.length}] `;\n                str += `${err.title} (${err.status}, ${err.id}): ${err.detail}. `;\n                return str;\n            });\n            info = parsedErrors.join('\\n');\n        }\n\n        if (info.includes('36 characters')) {\n            info +=\n                '\\n\\nIt looks like MangaDex expected a UUID, but you provided a non-UUID string. If you are using Tags, please use Tag.getByName() instead of the literal name.';\n        }\n\n        super(info);\n        Object.setPrototypeOf(this, APIResponseError.prototype);\n        this.name = 'APIResponseError';\n    }\n}\n","export default class AuthError extends Error {\n    constructor(info: string) {\n        super(info);\n        Object.setPrototypeOf(this, AuthError.prototype);\n        this.name = 'AuthError';\n    }\n}\n","import IDObject from '../internal/IDObject';\nimport APIResponseError from './APIResponseError';\nimport AuthError from './AuthError';\n\nimport type { CheckResponseSchema, ErrorResponseSchema } from '../types/schema';\nimport type { IAuthClient } from '../types/helpers';\n\ntype ParameterObj = {\n    [x: string]:\n        | string\n        | string[]\n        | number\n        | number[]\n        | boolean\n        | { [x: string]: string | number }\n        | IDObject\n        | IDObject[]\n        | undefined;\n};\n\ntype ListResponse = { data: { id: string }[]; limit: number; offset: number; total: number };\n\ntype CustomRequestInit = Omit<RequestInit, 'headers'> & { headers?: Record<string, string>; noAuth?: boolean };\n\nclass NetworkStateManager {\n    static apiOriginOverride: string | undefined;\n    static authOriginOverride: string | undefined;\n    static activeClient: IAuthClient | undefined;\n\n    static get apiOrigin() {\n        const rawDomain = this.apiOriginOverride ?? 'https://api.mangadex.org/';\n        return new URL(rawDomain).origin;\n    }\n\n    static get authOrigin() {\n        const rawDomain = this.authOriginOverride ?? 'https://auth.mangadex.org/';\n        return new URL(rawDomain).origin;\n    }\n}\n\n/**\n * If true the debug (sandbox) MangaDex domain will be used as the domain override.\n * {@link https://sandbox.mangadex.dev}\n */\nexport function useDebugServer(val: boolean) {\n    const devApiDomain = 'https://api.mangadex.dev';\n    const devAuthDomain = 'https://auth.mangadex.dev';\n    if (val) {\n        NetworkStateManager.apiOriginOverride = devApiDomain;\n        NetworkStateManager.authOriginOverride = devAuthDomain;\n    } else {\n        if (NetworkStateManager.apiOriginOverride === devApiDomain) {\n            NetworkStateManager.apiOriginOverride = undefined;\n        }\n        if (NetworkStateManager.authOriginOverride === devAuthDomain) {\n            NetworkStateManager.authOriginOverride = undefined;\n        }\n    }\n}\n\n/**\n * Changes the origin used by api calls to a custom one, or clears it if the passed value is undefined.\n * @param domain - The new domain (e.g. https://example.com)\n */\nexport function overrideApiOrigin(domain: string | undefined) {\n    NetworkStateManager.apiOriginOverride = domain;\n}\n\n/**\n * Changes the origin used by authentication calls to a custom one, or clears it if the passed value is undefined.\n * @param domain - The new domain (e.g. https://example.com)\n */\nexport function overrideAuthOrigin(domain: string | undefined) {\n    NetworkStateManager.authOriginOverride = domain;\n}\n\n/**\n * Sets the AuthClient to be used by API calls\n * @param client - The signed-in OAuth or legacy AuthClient\n */\nexport function setActiveAuthClient(client: IAuthClient) {\n    NetworkStateManager.activeClient = client;\n}\n\n/**\n * Removes the current active AuthClient so no further API calls are done with user authorization\n */\nexport function clearActiveAuthClient() {\n    NetworkStateManager.activeClient = undefined;\n}\n\n/**\n * Returns the current auth client or null if there is none\n */\nexport function getActiveAuthClient() {\n    return NetworkStateManager.activeClient ?? null;\n}\n\n/**\n * Performs a fetch request to MangaDex and parses the response as JSON.\n */\nexport async function fetchMD<T extends object>(\n    endpoint: string,\n    params?: ParameterObj,\n    requestInit: CustomRequestInit = {},\n): Promise<T> {\n    const domain = NetworkStateManager.apiOrigin;\n    const url = buildURL(domain, endpoint, params);\n\n    if (NetworkStateManager.activeClient && !requestInit.noAuth) {\n        const sessionToken = await NetworkStateManager.activeClient.getSessionToken();\n        if (requestInit.headers === undefined) requestInit.headers = {};\n        requestInit.headers['authorization'] = `Bearer ${sessionToken}`;\n    }\n    const res = await fetch(url, requestInit);\n\n    // Raise error if response isn't JSON\n    const contentType = res.headers.get('content-type');\n    if (!contentType?.toLowerCase().includes('json')) {\n        let errInfo = `${res.statusText} (${res.status}) Response was an unexpected content type: ${\n            contentType ?? 'Unspecified Type'\n        }.`;\n        try {\n            let text = await res.text();\n            if (text.length > 128) text = text.slice(0, 128);\n            errInfo += `\\nStart of Body: ${text}`;\n        } catch (_) {}\n        throw new APIResponseError(errInfo);\n    }\n\n    // Raise error if response is a MD error\n    const data = (await res.json()) as ErrorResponseSchema | T;\n    if ('result' in data && data.result !== 'ok') {\n        throw new APIResponseError(data);\n    }\n\n    // Raise error if error status code was given\n    if (res.status >= 400) {\n        throw new APIResponseError(`${res.statusText} (${res.status})`);\n    }\n\n    return data as T;\n}\n\n/**\n * Same as {@link fetchMD}, but returns the 'data' property of the response instead\n */\nexport async function fetchMDData<T extends { data: unknown }>(\n    endpoint: string,\n    params?: ParameterObj,\n    requestInit?: CustomRequestInit,\n): Promise<T['data']> {\n    const res = await fetchMD<T>(endpoint, params, requestInit);\n    return res.data;\n}\n\n/**\n * Same as {@link fetchMDData} but is designed specifically for search requests. This means that\n * multiple requests will be used for extreme limits.\n */\nexport async function fetchMDSearch<T extends ListResponse>(\n    endpoint: string,\n    params: ParameterObj & { limit?: number; offset?: number } = {},\n    requestInit?: CustomRequestInit,\n    maxLimit = 100,\n    defaultLimit = 10,\n): Promise<T['data']> {\n    // Setup initial limit and offset values:\n    const MAX_POSSIBLE_RESULTS = 10000; // Hard limit for any endpoint is 10000 total results\n    let targetLimit = Math.min(params.limit ?? defaultLimit, MAX_POSSIBLE_RESULTS);\n    const initialOffset = params.offset ?? 0;\n    if (initialOffset >= MAX_POSSIBLE_RESULTS || targetLimit <= 0) return [];\n    if (initialOffset > MAX_POSSIBLE_RESULTS - Math.min(maxLimit, targetLimit)) {\n        // Make limit smaller to avoid bounds error if offset is close to MAX_POSSIBLE_RESULTS\n        targetLimit = MAX_POSSIBLE_RESULTS - initialOffset;\n    }\n\n    // Get one result to find out how many total results there are\n    const firstResponse = await fetchMD<T>(\n        endpoint,\n        { ...params, limit: Math.min(targetLimit, maxLimit) },\n        requestInit,\n    );\n    // Return immediately if multiple requests aren't needed, or if the result contains all possible results\n    if (targetLimit <= maxLimit || firstResponse.total <= firstResponse.data.length + initialOffset) {\n        return firstResponse.data;\n    }\n    // Lower the limit if there aren't that many results\n    targetLimit = Math.min(targetLimit, firstResponse.total);\n\n    // Create an array of requests with each request having the maximum limit until the target limit is reached\n    const promises: Promise<T['data']>[] = [];\n    for (let offset = initialOffset + maxLimit; offset < targetLimit; offset += maxLimit) {\n        const limitForThisRequest = Math.min(targetLimit - offset, maxLimit);\n        promises.push(fetchMDData<T>(endpoint, { ...params, limit: limitForThisRequest, offset: offset }, requestInit));\n    }\n    const newResults = await Promise.all(promises);\n    return firstResponse.data.concat(...newResults);\n}\n\n/**\n * Will request a list of objects by an array of their ids (or similar) as a query parameter. This\n * function also accepts extra parameters in the same format as {@link fetchMDSearch}.\n */\nexport async function fetchMDByArrayParam<T extends ListResponse>(\n    endpoint: string,\n    arr: (string | IDObject)[],\n    extraParams: ParameterObj = {},\n    arrayParam = 'ids',\n    paramLimit = 100,\n    requestInit?: CustomRequestInit,\n): Promise<T['data']> {\n    const idArray = arr.map((elem) => (elem instanceof IDObject ? elem.id : elem));\n    const promises = [];\n    for (let i = 0; i < idArray.length; i += paramLimit) {\n        promises.push(\n            fetchMDData<T>(\n                endpoint,\n                { ...extraParams, [arrayParam]: idArray.slice(i, i + paramLimit), limit: paramLimit },\n                requestInit,\n            ),\n        );\n    }\n    const results = await Promise.all(promises);\n    // Reorder results so that they're in the same order as the id array\n    const sortedResults = results.flat();\n    sortedResults.sort((a, b) => idArray.indexOf(a.id) - idArray.indexOf(b.id));\n    return sortedResults;\n}\n\n/**\n * Same as {@link fetchMD}, but it instead performs a request with a JSON body\n */\nexport async function fetchMDWithBody<T extends object>(\n    endpoint: string,\n    body: object,\n    params?: ParameterObj,\n    method = 'POST',\n    requestInit: CustomRequestInit = {},\n): Promise<T> {\n    const headers = requestInit.headers !== undefined ? requestInit.headers : {};\n    headers['Content-Type'] = 'application/json';\n    return fetchMD<T>(endpoint, params, {\n        body: JSON.stringify(body),\n        method: method,\n        headers: headers,\n    });\n}\n\n/**\n * Same as {@link fetchMDData}, but it instead performs a request with a JSON body\n */\nexport async function fetchMDDataWithBody<T extends { data: unknown }>(\n    endpoint: string,\n    body: object,\n    params?: ParameterObj,\n    method = 'POST',\n    requestInit: CustomRequestInit = {},\n): Promise<T['data']> {\n    const res = await fetchMDWithBody<T>(endpoint, body, params, method, requestInit);\n    return res['data'];\n}\n\n/**\n * Performs a POST fetch request to api.mangadex.network with a JSON body\n */\nexport async function postToMDNetwork(endpoint: string, body: object, params?: ParameterObj): Promise<void> {\n    const url = buildURL('https://api.mangadex.network', endpoint, params);\n    const res = await fetch(url, {\n        body: JSON.stringify(body),\n        method: 'POST',\n        headers: {\n            'Content-Type': 'application/json',\n        },\n    });\n    if (!res.ok) throw new APIResponseError(`${res.status} ${res.statusText}`);\n}\n\nexport async function fetchMDWithFormData<T extends object>(\n    endpoint: string,\n    body: Record<\n        string,\n        | string\n        | string[]\n        | Blob\n        | Blob[]\n        | { data: string | Blob; name: string }\n        | { data: string | Blob; name: string }[]\n        | undefined\n        | null\n    >,\n    params?: ParameterObj,\n    method = 'POST',\n    requestInit: CustomRequestInit = {},\n): Promise<T> {\n    const formdata = new FormData();\n    const appendItem = (name: string, item: Blob | string | { data: string | Blob; name: string }) => {\n        if (typeof item !== 'string' && 'data' in item && 'name' in item) {\n            formdata.append(name, item.data as Blob, item.name);\n        } else {\n            formdata.append(name, item);\n        }\n    };\n    for (const [name, value] of Object.entries(body)) {\n        if (value) {\n            // MD accepts array values as name + index, not name[]\n            if (Array.isArray(value)) value.forEach((v, i) => appendItem(name + i, v));\n            else appendItem(name, value);\n        }\n    }\n    return await fetchMD<T>(endpoint, params, {\n        ...requestInit,\n        method: method,\n        body: formdata,\n    });\n}\n\n/**\n * Generate a url from a base domain, path, and parameter object\n */\nexport function buildURL(base: string, path?: string, params?: ParameterObj): URL {\n    const url = path ? new URL(path, base) : new URL(base);\n    if (!params) return url;\n\n    for (const [name, value] of Object.entries(params)) {\n        if (Array.isArray(value)) {\n            for (let i of value) {\n                if (i instanceof IDObject) i = i.id;\n                url.searchParams.append(`${name}[]`, i.toString());\n            }\n        } else if (typeof value === 'object') {\n            if (value instanceof IDObject) {\n                url.searchParams.append(name, value.id.toString());\n            } else {\n                const valueEntries = Object.entries(value);\n                for (const [k, v] of valueEntries) {\n                    url.searchParams.append(`${name}[${k}]`, v.toString());\n                }\n            }\n        } else if (value !== undefined) {\n            url.searchParams.append(name, value.toString());\n        }\n    }\n\n    return url;\n}\n\n/**\n * Checks if the current user is correctly authorized or if the specified session token is valid.\n */\nexport async function performAuthCheck(sessionToken?: string): Promise<boolean> {\n    try {\n        let options: CustomRequestInit | undefined = undefined;\n        if (sessionToken !== undefined) {\n            options = {\n                headers: {\n                    authorization: `Bearer ${sessionToken}`,\n                },\n                noAuth: true,\n            };\n        }\n        const res = await fetchMD<CheckResponseSchema>('/auth/check', undefined, options);\n        return res.isAuthenticated;\n    } catch (err) {\n        if (err instanceof APIResponseError) return false;\n        else throw err;\n    }\n}\n\n/**\n * Send a URL-encoded POST request to the MangaDex auth server\n */\nexport async function fetchMDAuth<T extends object>(endpoint: string, body: Record<string, string>): Promise<T> {\n    const params = new URLSearchParams();\n    for (const [name, value] of Object.entries(body)) params.append(name, value);\n    const domain = NetworkStateManager.authOrigin;\n    const url = new URL(endpoint, domain);\n    const res = await fetch(url, {\n        body: params,\n        method: 'POST',\n    });\n\n    if (res.status >= 400) {\n        throw new AuthError(`${res.statusText} (${res.status})`);\n    }\n\n    const resBody: T = await res.json();\n    return resBody;\n}\n","import IDObject from '../internal/IDObject';\nimport LocalizedString from '../internal/LocalizedString';\nimport { fetchMDData, fetchMDSearch, fetchMDByArrayParam, fetchMDDataWithBody, fetchMD } from '../util/Network';\nimport Relationship from '../internal/Relationship';\n\nimport {\n    AuthorAttributesSchema,\n    AuthorCreateSchema,\n    AuthorEditSchema,\n    AuthorListSchema,\n    AuthorResponseSchema,\n    AuthorSchema,\n    GetAuthorParamsSchema,\n    ResponseSchema,\n} from '../types/schema';\nimport type Manga from './Manga';\nimport type { Merge } from '../types/helpers';\n\ntype AuthorSearchParams = Partial<Merge<GetAuthorParamsSchema, { ids: Author[] }>>;\n\n/**\n * This represents an author or artist of a manga\n */\nexport default class Author extends IDObject implements AuthorAttributesSchema {\n    /**\n     * The MangaDex UUID for the author/artist\n     */\n    id: string;\n    /**\n     * The name of the author/artist\n     */\n    name: string;\n    /**\n     * A url to an image of the author/artist\n     */\n    imageUrl: string | null;\n    /**\n     * The biography of the author/artist\n     */\n    biography: LocalizedString;\n    /**\n     * URL to the author/artist's twitter\n     */\n    twitter: string | null;\n    /**\n     * URL to the author/artist's pixiv\n     */\n    pixiv: string | null;\n    /**\n     *  URL to the author/artist's melon book\n     */\n    melonBook: string | null;\n    /**\n     *  URL to the author/artist's fanbox\n     */\n    fanBox: string | null;\n    /**\n     *  URL to the author/artist's booth\n     */\n    booth: string | null;\n    /**\n     *  URL to the author/artist's nico video\n     */\n    nicoVideo: string | null;\n    /**\n     *  URL to the author/artist's skeb\n     */\n    skeb: string | null;\n    /**\n     *  URL to the author/artist's fantia\n     */\n    fantia: string | null;\n    /**\n     *  URL to the author/artist's tumblr\n     */\n    tumblr: string | null;\n    /**\n     *  URL to the author/artist's youtube\n     */\n    youtube: string | null;\n    /**\n     *  URL to the author/artist's weibo\n     */\n    weibo: string | null;\n    /**\n     *  URL to the author/artist's naver\n     */\n    naver: string | null;\n    /**\n     * URL to the author/artist's namicomi\n     */\n    namicomi: string | null;\n    /**\n     *  URL to the author/artist's website\n     */\n    website: string | null;\n    /**\n     *  The version of this author/artist's entry (incremented by updating author data)\n     */\n    version: number;\n    /**\n     * When the author/artist's entry was added\n     */\n    createdAt: Date;\n    /**\n     * The last time the author/artist's entry was updated\n     */\n    updatedAt: Date;\n    /**\n     * The manga the author/artist has worked on\n     */\n    manga: Relationship<Manga>[];\n\n    constructor(schem: AuthorSchema) {\n        super();\n        this.id = schem.id;\n        this.name = schem.attributes.name;\n        this.imageUrl = schem.attributes.imageUrl;\n        this.biography = new LocalizedString(schem.attributes.biography);\n        this.twitter = schem.attributes.twitter;\n        this.pixiv = schem.attributes.pixiv;\n        this.melonBook = schem.attributes.melonBook;\n        this.fanBox = schem.attributes.fanBox;\n        this.booth = schem.attributes.booth;\n        this.nicoVideo = schem.attributes.nicoVideo;\n        this.skeb = schem.attributes.skeb;\n        this.fantia = schem.attributes.fantia;\n        this.tumblr = schem.attributes.tumblr;\n        this.youtube = schem.attributes.youtube;\n        this.weibo = schem.attributes.weibo;\n        this.naver = schem.attributes.naver;\n        this.namicomi = schem.attributes.namicomi;\n        this.website = schem.attributes.website;\n        this.version = schem.attributes.version;\n        this.createdAt = new Date(schem.attributes.createdAt);\n        this.updatedAt = new Date(schem.attributes.updatedAt);\n        this.manga = Relationship.convertType('manga', schem.relationships);\n    }\n\n    /**\n     * Retrieve a chapter object by its id\n     */\n    static async get(id: string, expandedTypes?: AuthorSearchParams['includes']): Promise<Author> {\n        return new Author(await fetchMDData<AuthorResponseSchema>(`/author/${id}`, { includes: expandedTypes }));\n    }\n\n    /**\n     * Retrieves a list of authors/artists according to the specified search parameters\n     */\n    static async search(query?: AuthorSearchParams) {\n        const res = await fetchMDSearch<AuthorListSchema>(`/author`, query);\n        return res.map((m) => new Author(m));\n    }\n\n    /**\n     * Performs a search for an author/artist and returns the first one found. If no results are\n     * found, null is returned\n     */\n    static async getByQuery(query?: AuthorSearchParams): Promise<Author | null> {\n        const res = await this.search(query);\n        return res[0] ?? null;\n    }\n\n    /**\n     * Retrieves an array of authors/artists by an array of ids\n     */\n    static async getMultiple(ids: string[]): Promise<Author[]> {\n        const res = await fetchMDByArrayParam<AuthorListSchema>('/author', ids);\n        return res.map((a) => new Author(a));\n    }\n\n    /**\n     * Create a new Author\n     */\n    static async create(data: AuthorCreateSchema) {\n        return new Author(await fetchMDDataWithBody<AuthorResponseSchema>('/author', data));\n    }\n\n    /**\n     * Deletes an author by their id\n     */\n    static async delete(id: string) {\n        await fetchMD<ResponseSchema>(`/author/${id}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Deletes this author\n     */\n    async delete() {\n        await Author.delete(this.id);\n    }\n\n    /**\n     * Updates an author's information.\n     */\n    async update(data: Omit<AuthorCreateSchema, 'version'>) {\n        return new Author(\n            await fetchMDDataWithBody<AuthorResponseSchema>(\n                `/author/${this.id}`,\n                {\n                    ...data,\n                    version: this.version + 1,\n                } as AuthorEditSchema,\n                undefined,\n                'PUT',\n            ),\n        );\n    }\n}\n","import IDObject from '../internal/IDObject';\nimport {\n    fetchMD,\n    fetchMDByArrayParam,\n    fetchMDData,\n    fetchMDDataWithBody,\n    fetchMDSearch,\n    fetchMDWithFormData,\n} from '../util/Network';\nimport Relationship from '../internal/Relationship';\n\nimport type Manga from './Manga';\nimport type {\n    CoverAttributesSchema,\n    CoverEditSchema,\n    CoverListSchema,\n    CoverResponseSchema,\n    CoverSchema,\n    GetCoverParamsSchema,\n    ResponseSchema,\n    Cover as CoverNamespace,\n} from '../types/schema';\nimport type { Merge } from '../types/helpers';\nimport type User from './User';\n\ntype CoverSearchParams = Partial<Merge<GetCoverParamsSchema, { ids: Cover[]; manga: Manga[] }>>;\ntype CoverExpandedTypes = CoverSearchParams['includes'];\ntype CoverUploadBody = Omit<CoverNamespace.UploadCover.RequestBody, 'file'> & { file: Blob };\n\nexport default class Cover extends IDObject implements CoverAttributesSchema {\n    /**\n     * MangaDex UUID for this object\n     */\n    id: string;\n    /**\n     * What volume is this cover for, if any\n     */\n    volume: string | null;\n    /**\n     * The file name of this cover's image\n     */\n    fileName: string;\n    /**\n     * Description of this cover. May be an empty string\n     */\n    description: string | null;\n    /**\n     * What language is this cover in\n     */\n    locale: string | null;\n    /**\n     * The version of this cover (incremented by updating the cover)\n     */\n    version: number;\n    /**\n     * The date this cover was uploaded\n     */\n    createdAt: Date;\n    /**\n     * The date this cover was last updated\n     */\n    updatedAt: Date;\n    /**\n     * Url to this cover's image\n     */\n    url: string;\n    /**\n     * Relationship to the manga this cover belongs to\n     */\n    manga: Relationship<Manga>;\n    /**\n     * Relationship to the user who uploaded this cover\n     */\n    uploader: Relationship<User> | null;\n\n    constructor(schem: CoverSchema) {\n        super();\n        this.id = schem.id;\n        this.volume = schem.attributes.volume;\n        this.fileName = schem.attributes.fileName;\n        this.description = schem.attributes.description;\n        this.locale = schem.attributes.locale;\n        this.version = schem.attributes.version;\n        this.createdAt = new Date(schem.attributes.createdAt);\n        this.updatedAt = new Date(schem.attributes.updatedAt);\n        const parentRelationship = Relationship.createSelfRelationship('cover_art', this);\n        this.manga = Relationship.convertType<Manga>('manga', schem.relationships, parentRelationship).pop()!;\n        this.url = `https://mangadex.org/covers/${this.manga.id}/${this.fileName}`;\n        this.uploader = Relationship.convertType<User>('user', schem.relationships).pop() ?? null;\n    }\n\n    /**\n     * Retrieves a cover by its id\n     */\n    static async get(id: string | Manga, expandedTypes?: CoverExpandedTypes): Promise<Cover> {\n        if (id instanceof IDObject) id = id.id;\n        return new Cover(await fetchMDData<CoverResponseSchema>(`/cover/${id}`, { includes: expandedTypes }));\n    }\n\n    /**\n     * Retrieves a list of covers according to the specified search parameters\n     */\n    static async search(query?: CoverSearchParams) {\n        const res = await fetchMDSearch<CoverListSchema>(`/cover`, query);\n        return res.map((m) => new Cover(m));\n    }\n\n    /**\n     * Performs a search for a cover and returns the first one found. If no results are\n     * found, null is returned\n     */\n    static async getByQuery(query?: CoverSearchParams): Promise<Cover | null> {\n        const res = await this.search(query);\n        return res[0] ?? null;\n    }\n\n    /**\n     * Retrieves an array of covers by an array of ids\n     */\n    static async getMultiple(ids: string[]): Promise<Cover[]> {\n        const res = await fetchMDByArrayParam<CoverListSchema>('/cover', ids);\n        return res.map((a) => new Cover(a));\n    }\n\n    /**\n     * Returns an array of covers from an array of manga ids or a single manga\n     */\n    static async getMangaCovers(\n        manga: Manga | string | Manga[] | string[],\n        expandedTypes?: CoverExpandedTypes,\n    ): Promise<Cover[]> {\n        if (!Array.isArray(manga)) manga = [typeof manga === 'string' ? manga : manga.id];\n        if (manga.length === 0) return [];\n        const ids = manga.map((m) => (typeof m === 'string' ? m : m.id));\n        return Cover.search({ manga: ids, includes: expandedTypes });\n    }\n\n    /**\n     * Deletes a cover by their id\n     */\n    static async delete(id: string) {\n        await fetchMD<ResponseSchema>(`/cover/${id}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Deletes this cover\n     */\n    async delete() {\n        await Cover.delete(this.id);\n    }\n\n    /**\n     * Updates a cover's information.\n     */\n    async update(data: Omit<CoverEditSchema, 'version'>) {\n        return new Cover(\n            await fetchMDDataWithBody<CoverResponseSchema>(\n                `/cover/${this.id}`,\n                {\n                    ...data,\n                    version: this.version + 1,\n                },\n                undefined,\n                'PUT',\n            ),\n        );\n    }\n\n    /**\n     * Uploads a new cover\n     */\n    static async create(manga: string | Manga, data: CoverUploadBody) {\n        if (typeof manga !== 'string') manga = manga.id;\n        const res = await fetchMDWithFormData<CoverResponseSchema>(`/cover/${manga}`, data);\n        return new Cover(res.data);\n    }\n}\n","import { TagAttributesSchema, TagResponseSchema, TagSchema } from '../types/schema';\nimport { fetchMD } from '../util/Network';\nimport IDObject from '../internal/IDObject';\nimport LocalizedString from '../internal/LocalizedString';\n\n/**\n * This class represents a genre tag for a manga\n */\nexport default class Tag extends IDObject implements TagAttributesSchema {\n    private static allTagCache: Tag[];\n\n    /**\n     * MangaDex UUID of this tag\n     */\n    id: string;\n    /**\n     * Localized names for this tag\n     */\n    name: LocalizedString;\n    /**\n     * Localized descriptions for this tag\n     */\n    description: LocalizedString;\n    /**\n     * The tag group this tag belongs to\n     */\n    group: 'content' | 'format' | 'genre' | 'theme';\n    /**\n     * The version of this tag (incremented whenever the tag's data is updated)\n     */\n    version: number;\n\n    constructor(data: TagSchema) {\n        super();\n        this.id = data.id;\n        this.name = new LocalizedString(data.attributes.name);\n        this.description = new LocalizedString(data.attributes.description);\n        this.group = data.attributes.group;\n        this.version = data.attributes.version;\n    }\n\n    /**\n     * Get the localString from the name {@link LocalizedString} object\n     */\n    get localName() {\n        return this.name.localString;\n    }\n\n    /**\n     * Get the localString from the description {@link LocalizedString} object\n     */\n    get localDescription() {\n        return this.description.localString;\n    }\n\n    /**\n     * Retrieves every tag used on MangaDex. The result is cached so any promise\n     * after the first will resolve instantly.\n     */\n    static async getAllTags(): Promise<Tag[]> {\n        if (!Tag.allTagCache || Tag.allTagCache.length === 0) {\n            const res = await fetchMD<TagResponseSchema>('/manga/tag');\n            Tag.allTagCache = res.data.map((elem) => new Tag(elem));\n        }\n        return Tag.allTagCache;\n    }\n\n    /**\n     * Return the first tag that contains the specified name\n     */\n    static async getByName(name: string): Promise<Tag> {\n        const tags = await this.getAllTags();\n        const lowerName = name.toLowerCase();\n        const foundTag = tags.find((tag) => Object.values(tag.name).some((n) => n.toLowerCase() === lowerName));\n        if (!foundTag) throw new Error(`No tag found with name ${name}`);\n        return foundTag;\n    }\n\n    /**\n     * Return tags with the associated names\n     */\n    static async getByNames(names: string[]): Promise<Tag[]> {\n        const tags = await this.getAllTags();\n        const lowerNames = names.map((n) => n.toLowerCase());\n        return tags.filter((tag) => Object.values(tag.name).some((n) => lowerNames.includes(n.toLowerCase())));\n    }\n}\n","/**\n * A simple record object representing links to manga on different websites.\n * Websites are the keys, and the values are full urls (when available).\n */\nclass Links {\n    /**\n     * Anilist (https://anilist.co) link to manga\n     */\n    anilist?: string;\n    /**\n     * AnimePlanet (https://anime-planet.com) link to manga\n     */\n    animePlanet?: string;\n    /**\n     * Bookwalker (https://bookwalker.jp/) link to manga\n     */\n    bookWalker?: string;\n    /**\n     * Mangaupdates (https://mangaupdates.com) link to manga\n     */\n    mangaUpdates?: string;\n    /**\n     * Novelupdates (https://novelupdates.com) link to manga\n     */\n    novelUpdates?: string;\n    /**\n     * MyAnimeList (https://myanimelist.net) link to manga\n     */\n    myAnimeList?: string;\n    /**\n     * Kitsu (https://kitsu.io) link to manga\n     */\n    kitsu?: string;\n    /**\n     * Amazon (https://amazon.com) link to manga\n     */\n    amazon?: string;\n    /**\n     * EBookJapan (https://ebookjapan.yahoo.co.jp) link to manga\n     */\n    eBookJapan?: string;\n    /**\n     * Link to manga raws\n     */\n    raw?: string;\n    /**\n     * Link to offical english manga translation\n     */\n    officialEnglishTranslation?: string;\n    /**\n     * CDJapan (https://www.cdjapan.co.jp/) link to manga\n     */\n    cdJapan?: string;\n\n    constructor(linksObject?: Record<string, string>) {\n        this.anilist = !linksObject?.al ? undefined : `https://anilist.co/manga/${linksObject.al}`;\n\n        this.animePlanet = !linksObject?.ap ? undefined : `https://www.anime-planet.com/manga/${linksObject.ap}`;\n\n        this.bookWalker = !linksObject?.bw ? undefined : `https://bookwalker.jp/${linksObject.bw}`;\n\n        this.mangaUpdates = !linksObject?.mu\n            ? undefined\n            : `https://www.mangaupdates.com/series.html?id=${linksObject.mu}`;\n\n        this.novelUpdates = !linksObject?.nu ? undefined : `https://www.novelupdates.com/series/${linksObject.nu}`;\n\n        this.myAnimeList = !linksObject?.mal ? undefined : `https://myanimelist.net/manga/${linksObject.mal}`;\n\n        if (linksObject?.kt !== undefined) {\n            // Stored as either a number or slug. See official documentation\n            if (isNaN(parseInt(linksObject.kt))) {\n                this.kitsu = `https://kitsu.io/api/edge/manga?filter[slug]=${linksObject.kt}`;\n            } else {\n                this.kitsu = `https://kitsu.io/api/edge/manga/${linksObject.kt}`;\n            }\n        }\n\n        this.amazon = linksObject?.amz;\n\n        this.eBookJapan = linksObject?.ebj;\n\n        this.raw = linksObject?.raw;\n\n        this.officialEnglishTranslation = linksObject?.engtl;\n\n        this.cdJapan = linksObject?.cdj;\n    }\n}\n\nexport default Links;\n","import IDObject from '../internal/IDObject';\nimport {\n    fetchMD,\n    fetchMDByArrayParam,\n    fetchMDData,\n    fetchMDDataWithBody,\n    fetchMDSearch,\n    postToMDNetwork,\n} from '../util/Network';\nimport Relationship from '../internal/Relationship';\n\nimport type {\n    AtHome,\n    ChapterAttributesSchema,\n    ChapterEditSchema,\n    ChapterListSchema,\n    ChapterResponseSchema,\n    ChapterSchema,\n    GetChapterParamsSchema,\n    ResponseSchema,\n    Statistics,\n} from '../types/schema';\nimport type Manga from './Manga';\nimport type User from './User';\nimport type Group from './Group';\nimport type { DeepRequire, Merge } from '../types/helpers';\n\nexport type ChapterSearchParams = Partial<\n    Merge<GetChapterParamsSchema, { ids: Chapter[]; groups: Group[]; uploader: User | User[] }>\n>;\ntype AtHomeServerResponse = Required<AtHome.GetAtHomeServerChapterId.ResponseBody>;\ntype OtherChapterAttributes = Omit<ChapterAttributesSchema, 'uploader'>;\ntype ChapterStatsResponse = DeepRequire<Statistics.GetStatisticsChapters.ResponseBody>;\ntype ChapterStats = ChapterStatsResponse['statistics'][string];\n\nexport default class Chapter extends IDObject implements OtherChapterAttributes {\n    /**\n     * The MangaDex UUID of this chapter\n     */\n    id: string;\n    /**\n     * The title of this chapter\n     */\n    title: string | null;\n    /**\n     * The manga volume this chapter belongs to\n     */\n    volume: string | null;\n    /**\n     * The chapter number for this chapter\n     */\n    chapter: string | null;\n    /**\n     * The number of pages in this chapter\n     */\n    pages: number;\n    /**\n     * The language of this chapter\n     */\n    translatedLanguage: string;\n    /**\n     * Relationship to the user who uploaded this chapter\n     */\n    uploader: Relationship<User>;\n    /**\n     * Url to this chapter if it's an external chapter\n     */\n    externalUrl: string | null;\n    /**\n     * The version of this chapter (incremented by updating chapter data)\n     */\n    version: number;\n    /**\n     * When this chapter was created\n     */\n    createdAt: Date;\n    /**\n     * When this chapter was last updated\n     */\n    updatedAt: Date;\n    /**\n     * When this chapter was originally published\n     */\n    publishAt: Date;\n    /**\n     * When was / when will this chapter be readable?\n     */\n    readableAt: Date;\n    /**\n     * Is this chapter an external chapter? If it is, this chapter will have an externalUrl\n     */\n    isExternal: boolean;\n    /**\n     * A relationship to the manga this chapter belongs to\n     */\n    manga: Relationship<Manga>;\n    /**\n     * Array of relationships to the groups that translated this chapter\n     */\n    groups: Relationship<Group>[];\n    /**\n     * Is this chapter unavailable?\n     */\n    isUnavailable: boolean;\n\n    constructor(schem: ChapterSchema) {\n        super();\n        this.id = schem.id;\n        this.title = schem.attributes.title;\n        this.volume = schem.attributes.volume;\n        this.chapter = schem.attributes.chapter;\n        this.pages = schem.attributes.pages;\n        this.translatedLanguage = schem.attributes.translatedLanguage;\n        this.uploader = Relationship.convertType<User>('user', schem.relationships).pop()!;\n        this.externalUrl = schem.attributes.externalUrl;\n        this.version = schem.attributes.version;\n        this.createdAt = new Date(schem.attributes.createdAt);\n        this.publishAt = new Date(schem.attributes.publishAt);\n        this.updatedAt = new Date(schem.attributes.updatedAt);\n        this.readableAt = new Date(schem.attributes.readableAt);\n        this.isExternal = schem.attributes.externalUrl !== null;\n        this.manga = Relationship.convertType<Manga>('manga', schem.relationships).pop()!;\n        this.groups = Relationship.convertType<Group>('scanlation_group', schem.relationships);\n        this.isUnavailable = schem.attributes.isUnavailable;\n    }\n\n    /**\n     * Retrieves a chapter object by its UUID\n     */\n    static async get(id: string, expandedTypes?: ChapterSearchParams['includes']): Promise<Chapter> {\n        return new Chapter(await fetchMDData<ChapterResponseSchema>(`/chapter/${id}`, { includes: expandedTypes }));\n    }\n\n    /**\n     * Retrieves an array of chapters by an array of their ids\n     */\n    static async getMultiple(ids: string[]): Promise<Chapter[]> {\n        const res = await fetchMDByArrayParam<ChapterListSchema>(`/chapter`, ids);\n        return res.map((c) => new Chapter(c));\n    }\n\n    /**\n     * Retrieves a list of chapters according to the specified search parameters\n     */\n    static async search(query?: ChapterSearchParams): Promise<Chapter[]> {\n        const res = await fetchMDSearch<ChapterListSchema>('/chapter', query);\n        return res.map((c) => new Chapter(c));\n    }\n\n    /**\n     * Performs a search for a chapter and returns the first one found. If no results are\n     * found, null is returned\n     */\n    static async getByQuery(query?: ChapterSearchParams): Promise<Chapter | null> {\n        const res = await this.search(query);\n        return res[0] ?? null;\n    }\n\n    /**\n     * Update this chapter's information\n     */\n    async update(data: Omit<ChapterEditSchema, 'version'>): Promise<Chapter> {\n        return new Chapter(\n            await fetchMDDataWithBody<ChapterResponseSchema>(\n                `/chapter/${this.id}`,\n                {\n                    ...data,\n                    version: this.version + 1,\n                },\n                undefined,\n                'PUT',\n            ),\n        );\n    }\n\n    /**\n     * Delete this chapter\n     */\n    static async delete(id: string) {\n        await fetchMD<ResponseSchema>(`/chapter/${id}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Delete a chapter by its UUID\n     */\n    async delete() {\n        await Chapter.delete(this.id);\n    }\n\n    /**\n     * Returns an array of image URLs for this chapter's pages. Once an image is requested,\n     * if the host is from MangaDex(at)Home, please report if it succeeds or fails by using {@link reportPageURL}.\n     * @param saver - If true, the URLs will be for the compressed data-saver images (if available).\n     * @param forcePort - If true, the URLs will be forced to be on port 443.\n     */\n    async getReadablePages(saver = false, forcePort = false): Promise<string[]> {\n        if (this.isExternal) throw new Error('Cannot get readable pages for an external chapter.');\n        const res = await fetchMD<AtHomeServerResponse>(`/at-home/server/${this.id}`, {\n            forcePort443: forcePort,\n        });\n        // Get the list of image files depending on if data saver images are preferred\n        const files = (saver ? res.chapter.dataSaver ?? res.chapter.data : res.chapter.data) ?? [];\n        // Build image urls according to https://api.mangadex.org/docs/retrieving-chapter/\n        return files.map((file) => `${res.baseUrl}/${saver ? 'data-saver' : 'data'}/${res.chapter.hash}/${file}`);\n    }\n\n    /**\n     * Sends a report to MangaDex about the success/failure of a MangaDex(at)Home server.\n     * Read more information: {@link https://api.mangadex.org/docs/04-chapter/retrieving-chapter/#mangadexhome-load-successes-failures-and-retries}\n     */\n    static async reportPageURL(report: {\n        url: string;\n        success: boolean;\n        bytes: number;\n        duration: number;\n        cached: boolean;\n    }): Promise<void> {\n        await postToMDNetwork('/report', report);\n    }\n\n    /**\n     * Gets the statistics about a list of chapters\n     */\n    static async getStatistics(ids: string[] | Chapter[]): Promise<Record<string, ChapterStats>> {\n        const res = await fetchMD<ChapterStatsResponse>(`/statistics/chapter`, { chapter: ids });\n        return res.statistics;\n    }\n\n    /**\n     * Gets the statistics about this chapter\n     */\n    async getStatistics(): Promise<ChapterStats> {\n        const res = await Chapter.getStatistics([this.id]);\n        return res[this.id];\n    }\n}\n","import LocalizedString from '../internal/LocalizedString';\nimport Tag from './Tag';\nimport {\n    fetchMD,\n    fetchMDByArrayParam,\n    fetchMDData,\n    fetchMDDataWithBody,\n    fetchMDSearch,\n    fetchMDWithBody,\n} from '../util/Network';\nimport Relationship from '../internal/Relationship';\nimport Links from '../internal/Links';\nimport IDObject from '../internal/IDObject';\nimport Chapter, { ChapterSearchParams } from './Chapter';\nimport Cover from './Cover';\nimport APIResponseError from '../util/APIResponseError';\n\nimport type Author from './Author';\nimport {\n    ChapterListSchema,\n    ChapterReadMarkerBatchSchema,\n    GetMangaRandomParamsSchema,\n    GetSearchMangaParamsSchema,\n    MangaAttributesSchema,\n    MangaListSchema,\n    MangaResponseSchema,\n    MangaSchema,\n    RelationshipSchema,\n    Manga as MangaNamespace,\n    Rating,\n    ResponseSchema,\n    MappingIdBodySchema,\n    MappingIdResponseSchema,\n    MangaRelationAttributesSchema,\n    MangaRelationResponseSchema,\n    MangaRelationRequestSchema,\n    MangaRelationListSchema,\n    Statistics,\n    GetMangaDraftsParamsSchema,\n    MangaCreateSchema,\n    MangaEditSchema,\n    User as UserNamespace,\n} from '../types/schema';\nimport type { DeepRequire, Merge } from '../types/helpers';\nimport type Group from './Group';\nimport type User from './User';\n\n// This type supplements the schema type so that IDObjects can be used instead\ntype MangaSearchHelpers = {\n    group: Group;\n    includedTags: Tag[];\n    excludedTags: Tag[];\n    authors: Author[];\n    artists: Author[];\n    authorOrArtist: Author;\n    ids: IDObject[];\n};\ntype MangaSearchParams = Partial<Merge<GetSearchMangaParamsSchema, MangaSearchHelpers>>;\ntype OtherMangaAttributes = Omit<MangaAttributesSchema, 'tags' | 'links' | 'latestUploadedChapter'>;\ntype RelatedManga = { [x in RelationshipSchema['related']]: Relationship<Manga>[] };\ntype ReadmarkerResponse = Required<MangaNamespace.GetMangaChapterReadmarkers.ResponseBody>;\ntype ReadmarkerResponseGrouped = Required<MangaNamespace.GetMangaChapterReadmarkers2.ResponseBody>;\ntype RatingResponse = Required<Rating.GetRating.ResponseBody>;\ntype MangaReadingStatus = Required<MangaNamespace.GetMangaIdStatus.ResponseBody>['status'];\ntype MangaRelation = MangaRelationAttributesSchema['relation'];\ntype MangaStatsResponse = DeepRequire<Statistics.GetStatisticsManga.ResponseBody>;\ntype MangaStats = MangaStatsResponse['statistics'][string];\ntype MangaDraftSearchParams = Partial<GetMangaDraftsParamsSchema>;\ntype MangaAggregateResponse = DeepRequire<MangaNamespace.GetMangaAggregate.ResponseBody>;\ntype MangaAggregate = MangaAggregateResponse['volumes'];\ntype FollowedMangaParams = UserNamespace.GetUserFollowsManga.RequestQuery;\n\n/**\n * This class represents a specific manga series.\n * There are many static methods for requesting manga from MangaDex.\n */\nexport default class Manga extends IDObject implements OtherMangaAttributes {\n    /**\n     * The MangaDex UUID of this manga\n     */\n    id: string;\n    /**\n     * The manga's main title with different localization options\n     */\n    title: LocalizedString;\n    /**\n     * List of alternate titles with different localization options\n     */\n    altTitles: LocalizedString[];\n    /**\n     * Description with different localization options\n     */\n    description: LocalizedString;\n    /**\n     * Is this manga locked?\n     */\n    isLocked: boolean;\n    /**\n     * Link object representing links to other websites about this manga\n     */\n    links: Links;\n    /**\n     * 2 (or more) letter code for the original language of this manga\n     */\n    originalLanguage: string;\n    /**\n     * This manga's last volume based on the default feed order\n     */\n    lastVolume: string | null;\n    /**\n     * This manga's last chapter based on the default feed order\n     */\n    lastChapter: string | null;\n    /**\n     * Publication demographic of this manga\n     */\n    publicationDemographic: 'shounen' | 'shoujo' | 'josei' | 'seinen' | null;\n    /**\n     * Publication/Scanlation status of this manga\n     */\n    status: 'completed' | 'ongoing' | 'cancelled' | 'hiatus';\n    /**\n     * Year of this manga's publication\n     */\n    year: number | null;\n    /**\n     * The content rating of this manga\n     */\n    contentRating: 'safe' | 'suggestive' | 'erotica' | 'pornographic';\n    /**\n     * Does the chapter count reset whenever a new volume is added?\n     */\n    chapterNumbersResetOnNewVolume: boolean;\n    /**\n     * List of language codes that this manga has translated chapters for\n     */\n    availableTranslatedLanguages: string[];\n    /**\n     * Relationship to the latest chapter. Null if there is no latest chapter.\n     */\n    latestUploadedChapter: Relationship<Chapter> | null;\n    /**\n     * List of this manga's genre tags\n     */\n    tags: Tag[];\n    /**\n     * Status of this manga as a manga submission\n     */\n    state: 'draft' | 'submitted' | 'published' | 'rejected';\n    /**\n     * The version of this manga (incremented by updating manga data)\n     */\n    version: number;\n    /**\n     * Date the manga was added to the site\n     */\n    createdAt: Date;\n    /**\n     * Date the manga was last updated\n     */\n    updatedAt: Date;\n    /**\n     * An object containing all other manga entries related to this one.\n     * This includes spin-offs, colorization, etc.\n     */\n    relatedManga: RelatedManga;\n    /**\n     * List of relationships to authors attributed to this manga\n     */\n    authors: Relationship<Author>[];\n    /**\n     * List of relationships to artists attributed to this manga\n     */\n    artists: Relationship<Author>[];\n    /**\n     * A relationship to the current main cover of this series\n     */\n    mainCover: Relationship<Cover>;\n    /**\n     * The user that created this manga, if known.\n     */\n    creator: Relationship<User> | null;\n\n    constructor(schem: MangaSchema) {\n        super();\n        this.id = schem.id;\n        const parentRelationship = Relationship.createSelfRelationship('manga', this);\n\n        this.altTitles = schem.attributes.altTitles.map((elem) => new LocalizedString(elem));\n        this.artists = Relationship.convertType('artist', schem.relationships, parentRelationship);\n        this.authors = Relationship.convertType('author', schem.relationships, parentRelationship);\n        this.availableTranslatedLanguages = schem.attributes.availableTranslatedLanguages;\n        this.chapterNumbersResetOnNewVolume = schem.attributes.chapterNumbersResetOnNewVolume;\n        this.contentRating = schem.attributes.contentRating;\n        this.createdAt = new Date(schem.attributes.createdAt);\n        this.description = new LocalizedString(schem.attributes.description);\n        this.isLocked = schem.attributes.isLocked;\n        this.lastChapter = schem.attributes.lastChapter;\n        this.lastVolume = schem.attributes.lastVolume;\n\n        this.latestUploadedChapter = null;\n        if (schem.attributes.latestUploadedChapter) {\n            this.latestUploadedChapter = new Relationship({\n                id: schem.attributes.latestUploadedChapter,\n                type: 'chapter',\n                relationships: [parentRelationship],\n            });\n        }\n\n        this.links = new Links(schem.attributes.links);\n        this.mainCover = Relationship.convertType<Cover>('cover_art', schem.relationships, parentRelationship).pop()!;\n        this.publicationDemographic = schem.attributes.publicationDemographic;\n        this.relatedManga = Manga.getRelatedManga(schem.relationships);\n        this.state = schem.attributes.state;\n        this.status = schem.attributes.status;\n        this.tags = schem.attributes.tags.map((elem) => new Tag(elem));\n        this.title = new LocalizedString(schem.attributes.title);\n        this.updatedAt = new Date(schem.attributes.updatedAt);\n        this.version = schem.attributes.version;\n        this.year = schem.attributes.year;\n        this.originalLanguage = schem.attributes.originalLanguage;\n        this.creator = Relationship.convertType<User>('creator', schem.relationships).pop() ?? null;\n    }\n\n    private static getRelatedManga(relationships: RelationshipSchema[]): RelatedManga {\n        const relatedManga: RelatedManga = {\n            monochrome: [],\n            main_story: [],\n            adapted_from: [],\n            based_on: [],\n            prequel: [],\n            side_story: [],\n            doujinshi: [],\n            same_franchise: [],\n            shared_universe: [],\n            sequel: [],\n            spin_off: [],\n            alternate_story: [],\n            alternate_version: [],\n            preserialization: [],\n            colored: [],\n            serialization: [],\n        };\n        for (const rel of relationships) {\n            if (rel.type === 'manga') {\n                relatedManga[rel.related].push(new Relationship<Manga>(rel));\n            }\n        }\n        return relatedManga;\n    }\n\n    /**\n     * The title of this manga according to the global locale.\n     * @see {@link LocalizedString.localString}\n     */\n    get localTitle() {\n        return this.title.localString;\n    }\n\n    /**\n     * List of alternate titles for manga according to the global locale.\n     * @see {@link LocalizedString.localString}\n     */\n    get localAltTitles() {\n        return this.altTitles.map((title) => title.localString);\n    }\n\n    /**\n     * The description of this manga according to the global locale.\n     * @see {@link LocalizedString.localString}\n     */\n    get localDescription() {\n        return this.description.localString;\n    }\n\n    /**\n     * Retrieves a manga object by its UUID\n     */\n    static async get(id: string, expandedTypes?: MangaSearchParams['includes']): Promise<Manga> {\n        return new Manga(await fetchMDData<MangaResponseSchema>(`/manga/${id}`, { includes: expandedTypes }));\n    }\n\n    /**\n     * Retrieves a list of manga according to the specified search parameters\n     * @see {@link Relationship.cached} for information on how to automatically resolve Relationships\n     */\n    static async search(query?: MangaSearchParams): Promise<Manga[]> {\n        const res = await fetchMDSearch<MangaListSchema>(`/manga`, query);\n        return res.map((m) => new Manga(m));\n    }\n\n    /**\n     * Retrieves an array of manga by an array of their ids\n     */\n    static async getMultiple(ids: string[], extraParams?: Omit<MangaSearchParams, 'ids'>): Promise<Manga[]> {\n        const res = await fetchMDByArrayParam<MangaListSchema>('/manga', ids, extraParams);\n        return res.map((m) => new Manga(m));\n    }\n\n    /**\n     * Returns how many manga there are total for a search query\n     */\n    static async getTotalSearchResults(query?: Omit<MangaSearchParams, 'limit' | 'offset'>): Promise<number> {\n        const res = await fetchMD<MangaListSchema>('/manga', { ...query, limit: 1, offset: 0 });\n        return res.total;\n    }\n\n    /**\n     * Returns an array of a manga's chapters\n     */\n    static async getFeed(id: string, params?: ChapterSearchParams): Promise<Chapter[]> {\n        const res = await fetchMDSearch<ChapterListSchema>(`/manga/${id}/feed`, params);\n        return res.map((c) => new Chapter(c));\n    }\n\n    /**\n     * Returns an array of this manga's chapters\n     */\n    async getFeed(params?: ChapterSearchParams): Promise<Chapter[]> {\n        return Manga.getFeed(this.id, params);\n    }\n\n    /**\n     * Marks lists of chapters read or unread for a single manga\n     */\n    static async updateReadChapters(\n        manga: string,\n        chapters: { read?: (string | Chapter)[]; unread?: (string | Chapter)[] },\n        updateHistory = false,\n    ) {\n        if (!chapters.read && !chapters.unread) return [];\n        const body = {\n            chapterIdsRead: chapters.read?.map((c) => (typeof c === 'string' ? c : c.id)) ?? [],\n            chapterIdsUnread: chapters.unread?.map((c) => (typeof c === 'string' ? c : c.id)) ?? [],\n        } as ChapterReadMarkerBatchSchema;\n        await fetchMDWithBody(`/manga/${manga}/read`, body, { updateHistory: updateHistory });\n    }\n\n    /**\n     * Marks lists of chapters read or unread for this manga\n     */\n    async updateReadChapters(chapters: Parameters<typeof Manga.updateReadChapters>[1], updateHistory = false) {\n        return Manga.updateReadChapters(this.id, chapters, updateHistory);\n    }\n\n    /**\n     * Returns an array of read chapters for a list of manga. The response is a record with the manga ids\n     * as the keys and chapter arrays as the values.\n     */\n    static async getReadChapters(ids: string[] | Manga[]): Promise<Record<string, Chapter[]>> {\n        const mangaData: Record<string, string[]> = {};\n\n        // Split requests because there is a maximum URI length for each\n        for (let i = 0; i < ids.length; i += 100) {\n            let res = await fetchMDData<ReadmarkerResponseGrouped>('/manga/read', {\n                ids: ids.slice(i, i + 100),\n                grouped: true,\n            });\n            if (Array.isArray(res)) {\n                // The response won't be grouped if there is only one manga\n                if (ids.length === 1) {\n                    const id = typeof ids[0] === 'string' ? ids[0] : ids[0].id;\n                    res = { [id]: res };\n                } else {\n                    throw new APIResponseError('MangaDex did not respond with a grouped body.');\n                }\n            }\n            for (const [key, value] of Object.entries(res)) {\n                if (key in mangaData) mangaData[key].push(...value);\n                else mangaData[key] = value;\n            }\n        }\n\n        // Flatten all the chapters so only one request needs to be made\n        const allChapters = await Chapter.getMultiple(Object.values(mangaData).flat());\n        const returnObj: Record<string, Chapter[]> = {};\n        for (const key in mangaData) {\n            returnObj[key] = allChapters.filter((c) => mangaData[key].includes(c.id));\n        }\n        return returnObj;\n    }\n\n    /**\n     * Returns an array of read chapters for this manga\n     */\n    async getReadChapters() {\n        const res = await fetchMDData<ReadmarkerResponse>(`/manga/${this.id}/read`);\n        return await Chapter.getMultiple(res);\n    }\n\n    /**\n     * Retrieves a random manga\n     */\n    static async getRandom(query?: Pick<MangaSearchParams, keyof GetMangaRandomParamsSchema>) {\n        const res = await fetchMDData<MangaResponseSchema>('/manga/random', query);\n        return new Manga(res);\n    }\n\n    /**\n     * Performs a search for a manga and returns the first one found. If no results are\n     * found, null is returned\n     */\n    static async getByQuery(query?: MangaSearchParams): Promise<Manga | null> {\n        const res = await this.search(query);\n        return res[0] ?? null;\n    }\n\n    /**\n     * Gets all covers for this manga\n     */\n    async getCovers() {\n        return Cover.getMangaCovers(this.id);\n    }\n\n    /**\n     * Returns all manga followed by the currently authenticated user\n     */\n    static async getFollowedManga(query: FollowedMangaParams = { limit: Infinity, offset: 0 }): Promise<Manga[]> {\n        const res = await fetchMDSearch<MangaListSchema>('/user/follows/manga', query);\n        return res.map((u) => new Manga(u));\n    }\n\n    /**\n     * Returns a record of all ratings given by the currently authenticated user. The object is indexed by the manga\n     * ids and each value contains the numerical rating and when that rating was given. If a manga has no rating,\n     * 'null' is used as the value.\n     */\n    static async getUserRatings(\n        ids: string[] | Manga[],\n    ): Promise<Record<string, { rating: number; createdAt: Date } | null>> {\n        const res = await fetchMD<RatingResponse>('/rating', { manga: ids });\n        const parsedObj: Record<string, { rating: number; createdAt: Date } | null> = {};\n        for (let i of ids) {\n            if (typeof i !== 'string') i = i.id;\n            if (i in res.ratings) {\n                parsedObj[i] = {\n                    rating: res.ratings[i].rating!,\n                    createdAt: new Date(res.ratings[i].createdAt!),\n                };\n            } else {\n                parsedObj[i] = null;\n            }\n        }\n        return parsedObj;\n    }\n\n    /**\n     * Returns the rating that the currently authenticated user gave to this manga on a scale of 1-10,\n     * or returns null if there is no rating.\n     */\n    async getUserRating(): Promise<number | null> {\n        const res = await Manga.getUserRatings([this.id]);\n        return res[this.id]?.rating ?? null;\n    }\n\n    /**\n     * Makes the currently authenticated user give a manga a rating between 1-10 (inclusive).\n     */\n    static async giveRating(mangaId: string, rating: number) {\n        if (rating > 10 || rating < 1) throw new Error('Rating must be in the range of 1-10 (inclusive).');\n        await fetchMDWithBody<ResponseSchema>(`/rating/${mangaId}`, { rating: rating });\n    }\n\n    /**\n     * Makes the currently authenticated user give this manga a rating between 1-10 (inclusive).\n     */\n    async giveRating(rating: number) {\n        await Manga.giveRating(this.id, rating);\n    }\n\n    /**\n     * Removes the currently authenticated user's rating for a manga\n     */\n    static async removeRating(mangaId: string) {\n        await fetchMD<ResponseSchema>(`/rating/${mangaId}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Removes the currently authenticated user's rating for this manga\n     */\n    async removeRating() {\n        await Manga.removeRating(this.id);\n    }\n\n    /**\n     * Gets the combined feed of every manga followed by the logged in user\n     */\n    static async getFollowedFeed(query?: ChapterSearchParams): Promise<Chapter[]> {\n        const res = await fetchMDSearch<ChapterListSchema>('/user/follows/manga/feed', query);\n        return res.map((c) => new Chapter(c));\n    }\n\n    /**\n     * Converts legacy pre-V5 MangaDex ids to modern UUIDs. Returns a record with legacy ids as the keys\n     * and new ids as the values.\n     */\n    static async convertLegacyId(type: MappingIdBodySchema['type'], ids: number[]): Promise<Record<number, string>> {\n        const res = await fetchMDDataWithBody<MappingIdResponseSchema>('/legacy/mapping', {\n            type: type,\n            ids: ids,\n        } as MappingIdBodySchema);\n        return Object.fromEntries(res.map((i) => [i.attributes.legacyId, i.attributes.newId]));\n    }\n\n    /**\n     * Get every reading status (eg completed, reading, dropped, etc) for every manga marked by\n     * the currently authenticated user.\n     * @param filter - If specified, only manga with this status will be returned\n     */\n    static async getAllReadingStatus(filter?: MangaReadingStatus): Promise<Record<string, MangaReadingStatus>> {\n        const res = await fetchMD<Required<MangaNamespace.GetMangaStatus.ResponseBody>>('/manga/status', {\n            status: filter,\n        });\n        return res.statuses;\n    }\n\n    /**\n     * Gets the reading status (eg completed, reading, dropped, etc) for a manga for the currently\n     * authenticated user\n     */\n    static async getReadingStatus(id: string): Promise<MangaReadingStatus> {\n        const res = await fetchMD<Required<MangaNamespace.GetMangaIdStatus.ResponseBody>>(`/manga/${id}/status`);\n        return res.status;\n    }\n\n    /**\n     * Gets the reading status (eg completed, reading, dropped, etc) for this manga for the currently\n     * authenticated user\n     */\n    async getReadingStatus(): Promise<MangaReadingStatus> {\n        return await Manga.getReadingStatus(this.id);\n    }\n\n    /**\n     * Sets a manga's reading status (eg completed, reading, dropped, etc) for the currently authenticated user.\n     * If the status is null, the current reading status will be removed.\n     */\n    static async setReadingStatus(id: string, status: MangaReadingStatus | null): Promise<void> {\n        await fetchMDWithBody(`/manga/${id}/status`, { status: status });\n    }\n\n    /**\n     * Sets this manga's reading status (eg completed, reading, dropped, etc) for the currently authenticated user.\n     * If the status is null, the current reading status will be removed.\n     */\n    async setReadingStatus(status: MangaReadingStatus | null) {\n        await Manga.setReadingStatus(this.id, status);\n    }\n\n    /**\n     * Gets all of a manga's relations to other manga.\n     */\n    static async getRelations(id: string, expandTypes = false): Promise<RelatedManga> {\n        const res = await fetchMDData<MangaRelationListSchema>(`/manga/${id}/relation`, {\n            includes: expandTypes ? ['manga'] : undefined,\n        });\n        const relationships = res.flatMap((relation) =>\n            relation.relationships.map((rel) => ({ ...rel, related: relation.attributes.relation })),\n        );\n        return Manga.getRelatedManga(relationships);\n    }\n\n    /**\n     * Gets all of this manga's relations to other manga.\n     */\n    async getRelations(expandTypes = false): Promise<RelatedManga> {\n        return await Manga.getRelations(this.id, expandTypes);\n    }\n\n    /**\n     * Creates a relation between two manga (eg sequel/prequel, monochrome/colored, spin-off, etc)\n     * @param id - The origin manga\n     * @param targetId - The target manga for the relation (eg the sequel, spin-off, etc)\n     */\n    static async addRelation(id: string, targetId: string, relationType: MangaRelation): Promise<void> {\n        await fetchMDDataWithBody<MangaRelationResponseSchema>(`/manga/${id}/relation`, {\n            targetManga: targetId,\n            relation: relationType,\n        } as MangaRelationRequestSchema);\n    }\n\n    /**\n     * Creates a relation (eg sequel/prequel, monochrome/colored, spin-off, etc) between this manga and another\n     * @param id - The origin manga\n     * @param targetId - The target manga for the relation (eg the sequel, spin-off, etc)\n     */\n    async addRelation(targetId: string, relationType: MangaRelation): Promise<void> {\n        await Manga.addRelation(this.id, targetId, relationType);\n    }\n\n    /**\n     * Removes a relation from a manga by the relation's id\n     */\n    static async removeRelation(mangaId: string, relationId: string) {\n        await fetchMD(`/manga/${mangaId}/relation/${relationId}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Removes a relation from this manga by the relation's id\n     */\n    async removeRelation(relationId: string) {\n        await Manga.removeRelation(this.id, relationId);\n    }\n\n    /**\n     * Gets the statistics about manga including their rating distribution, comment count, and follow count\n     */\n    static async getStatistics(ids: string[] | Manga[]): Promise<Record<string, MangaStats>> {\n        const res = await fetchMD<MangaStatsResponse>(`/statistics/manga`, { manga: ids });\n        return res.statistics;\n    }\n\n    /**\n     * Gets the statistics about this manga including its rating distribution, comment count, and follow count\n     */\n    async getStatistics(): Promise<MangaStats> {\n        const res = await Manga.getStatistics([this.id]);\n        return res[this.id];\n    }\n\n    /**\n     * Retrieves a manga draft by its UUID\n     */\n    static async getDraft(id: string, expandedTypes?: MangaDraftSearchParams['includes']): Promise<Manga> {\n        return new Manga(await fetchMDData<MangaResponseSchema>(`/manga/draft/${id}`, { includes: expandedTypes }));\n    }\n\n    /**\n     * Retrieves a list of manga drafts according to the specified search parameters\n     * @see {@link Relationship.cached} for information on how to automatically resolve Relationships\n     */\n    static async searchDrafts(query?: MangaDraftSearchParams): Promise<Manga[]> {\n        const res = await fetchMDSearch<MangaListSchema>(`/manga/draft`, query);\n        return res.map((m) => new Manga(m));\n    }\n\n    /**\n     * Commits a manga object as a draft. A Manga draft that is to be submitted must have at least one cover in\n     * the original language, must be in the \"draft\" state, and must be passed the correct version in the request body.\n     */\n    static async commitDraft(draftId: string, manga: Partial<MangaAttributesSchema>): Promise<Manga> {\n        const res = await fetchMDDataWithBody<MangaResponseSchema>(`/manga/draft/${draftId}/commit`, manga);\n        return new Manga(res);\n    }\n\n    /**\n     * Create a new manga. MangaDex only allows admins to use this endpoint. Use the a manga draft instead\n     */\n    static async create(data: MangaCreateSchema) {\n        return new Manga(await fetchMDDataWithBody<MangaResponseSchema>('/manga', data));\n    }\n\n    /**\n     * Deletes a manga by its id\n     */\n    static async delete(id: string) {\n        await fetchMD<ResponseSchema>(`/manga/${id}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Deletes this manga\n     */\n    async delete() {\n        await Manga.delete(this.id);\n    }\n\n    /**\n     * Updates this manga's information.\n     */\n    async update(data: Omit<MangaCreateSchema, 'version'>) {\n        return new Manga(\n            await fetchMDDataWithBody<MangaResponseSchema>(\n                `/author/${this.id}`,\n                {\n                    ...data,\n                    version: this.version + 1,\n                } as MangaEditSchema,\n                undefined,\n                'PUT',\n            ),\n        );\n    }\n\n    /**\n     * Returns an abridged list of chapter ids for a manga separated by their volumes\n     */\n    static async getAggregate(id: string, groups?: string[] | Group[], languages?: string[]): Promise<MangaAggregate> {\n        const res = await fetchMD<MangaAggregateResponse>(`/manga/${id}/aggregate`, {\n            groups: groups,\n            translatedLanguage: languages,\n        });\n        return res.volumes;\n    }\n\n    /**\n     * Returns an abridged list of chapter ids for this manga separated by their volumes\n     */\n    async getAggregate(groups?: string[] | Group[], languages?: string[]): Promise<MangaAggregate> {\n        return Manga.getAggregate(this.id, groups, languages);\n    }\n\n    /**\n     * Makes the logged in user follow or unfollow a manga\n     */\n    static async changeFollowship(id: string, follow = true): Promise<void> {\n        await fetchMD(`/manga/${id}/follow`, undefined, { method: follow ? 'POST' : 'DELETE' });\n    }\n\n    /**\n     * Makes the user follow or unfollow this manga\n     */\n    async changeFollowship(follow = true): Promise<void> {\n        await Manga.changeFollowship(this.id, follow);\n    }\n}\n","import IDObject from '../internal/IDObject';\nimport { fetchMDByArrayParam, fetchMDData, fetchMDSearch } from '../util/Network';\nimport Relationship from '../internal/Relationship';\n\nimport type { Merge } from '../types/helpers';\nimport type {\n    GetUserParamsSchema,\n    UserAttributesSchema,\n    UserListSchema,\n    UserResponseSchema,\n    UserSchema,\n    User as UserNamespace,\n} from '../types/schema';\nimport type Group from './Group';\n\ntype UserSearchParams = Partial<Merge<GetUserParamsSchema, { ids: User[] }>>;\ntype FollowedUserParams = UserNamespace.GetUserFollowsUser.RequestQuery;\n\n/**\n * This class represents a MangaDex user such as a chapter uploader\n */\nexport default class User extends IDObject implements UserAttributesSchema {\n    id: string;\n    username: string;\n    roles: string[];\n    version: number;\n    groups: Relationship<Group>[];\n\n    constructor(schem: UserSchema) {\n        super();\n        this.id = schem.id;\n        this.username = schem.attributes.username;\n        this.roles = schem.attributes.roles;\n        this.version = schem.attributes.version;\n        this.groups = Relationship.convertType('scanlation_group', schem.relationships);\n    }\n\n    /**\n     * Retrieves a user by their id\n     */\n    static async get(id: string): Promise<User> {\n        return new User(await fetchMDData<UserResponseSchema>(`/user/${id}`));\n    }\n\n    /**\n     * Retrieves a list of users according to the specified search parameters\n     */\n    static async search(query?: UserSearchParams): Promise<User[]> {\n        const res = await fetchMDSearch<UserListSchema>(`/user`, query);\n        return res.map((u) => new User(u));\n    }\n\n    /**\n     * Retrieves an array of users by an array of ids\n     */\n    static async getMultiple(ids: string[]): Promise<User[]> {\n        const res = await fetchMDByArrayParam<UserListSchema>('/user', ids);\n        return res.map((u) => new User(u));\n    }\n\n    /**\n     * Performs a search for a user and returns the first one found. If no results are\n     * found, null is returned\n     */\n    static async getByQuery(query?: UserSearchParams): Promise<User | null> {\n        const res = await this.search(query);\n        return res[0] ?? null;\n    }\n\n    /**\n     * Returns a user object for the currently authenticated user.\n     */\n    static async getLoggedInUser(): Promise<User> {\n        return new User(await fetchMDData<UserResponseSchema>('/user/me'));\n    }\n\n    /**\n     * Returns all users followed by the currently authenticated user.\n     */\n    static async getFollowedUsers(query: FollowedUserParams = { limit: Infinity, offset: 0 }): Promise<User[]> {\n        const res = await fetchMDSearch<UserListSchema>('/user/follows/user', query);\n        return res.map((u) => new User(u));\n    }\n}\n","import IDObject from '../internal/IDObject';\nimport { fetchMD, fetchMDByArrayParam, fetchMDData, fetchMDDataWithBody, fetchMDSearch } from '../util/Network';\nimport Relationship from '../internal/Relationship';\nimport LocalizedString from '../internal/LocalizedString';\n\nimport type {\n    CreateScanlationGroupSchema,\n    GetSearchGroupParamsSchema,\n    ResponseSchema,\n    ScanlationGroupAttributesSchema,\n    ScanlationGroupListSchema,\n    ScanlationGroupResponseSchema,\n    ScanlationGroupSchema,\n    Statistics,\n    User as UserNamespace,\n} from '../types/schema';\nimport type { DeepRequire, Merge } from '../types/helpers';\nimport type User from './User';\n\ntype GroupSearchParams = Partial<Merge<GetSearchGroupParamsSchema, { ids: Group[] }>>;\ntype GroupStatsResponse = DeepRequire<Statistics.GetStatisticsGroups.ResponseBody>;\ntype GroupStats = GroupStatsResponse['statistics'][string];\ntype FollowedGroupsParams = UserNamespace.GetUserFollowsGroup.RequestQuery;\n\nexport default class Group extends IDObject implements ScanlationGroupAttributesSchema {\n    /**\n     * The MangaDex UUID of this group\n     */\n    id: string;\n    /**\n     * The name of this group\n     */\n    name: string;\n    /**\n     * Alternate names for this group, including localized names\n     */\n    altNames: LocalizedString[];\n    /**\n     * Url to this group's website\n     */\n    website: string | null;\n    /**\n     * IRC server of this group\n     */\n    ircServer: string | null;\n    /**\n     * IRC channel of this group\n     */\n    ircChannel: string | null;\n    /**\n     * Discord server of this group\n     */\n    discord: string | null;\n    /**\n     * Email of this group\n     */\n    contactEmail: string | null;\n    /**\n     * Description of this group (not localized)\n     */\n    description: string | null;\n    /**\n     * Twitter profile of this group\n     */\n    twitter: string | null;\n    /**\n     * MangaUpdates profile of this group\n     */\n    mangaUpdates: string | null;\n    /**\n     * Languages this group focusses on translating\n     */\n    focusedLanguage: string[] | null;\n    /**\n     * Is this group locked from uploading?\n     */\n    locked: boolean;\n    /**\n     * Is this an official scanlation group?\n     */\n    official: boolean;\n    /**\n     * Is this group inactive?\n     */\n    inactive: boolean;\n    /**\n     * The delay between when this group uploads a chapter and when that chapter becomes readable\n     */\n    publishDelay: string;\n    /**\n     * The version of this group (incremented by updating the group data)\n     */\n    version: number;\n    /**\n     * When this group was created\n     */\n    createdAt: Date;\n    /**\n     * When this group was last updated\n     */\n    updatedAt: Date;\n    /**\n     * Relationship to the user profile of the user\n     */\n    leader: Relationship<User> | null;\n    /**\n     * Array of relationships to the member users of this group\n     */\n    members: Relationship<User>[];\n    /**\n     * Is this group ex-licensed?\n     */\n    exLicensed: boolean;\n    /**\n     * Is this group verified?\n     */\n    verified: boolean;\n\n    constructor(schem: ScanlationGroupSchema) {\n        super();\n        this.id = schem.id;\n        this.name = schem.attributes.name;\n        this.altNames = schem.attributes.altNames.map((name) => new LocalizedString(name));\n        this.website = schem.attributes.website;\n        this.ircServer = schem.attributes.ircServer;\n        this.ircChannel = schem.attributes.ircChannel;\n        this.discord = schem.attributes.discord;\n        this.contactEmail = schem.attributes.contactEmail;\n        this.description = schem.attributes.description;\n        this.twitter = schem.attributes.twitter;\n        this.mangaUpdates = schem.attributes.mangaUpdates;\n        this.focusedLanguage = schem.attributes.focusedLanguage;\n        this.locked = schem.attributes.locked;\n        this.official = schem.attributes.official;\n        this.inactive = schem.attributes.inactive;\n        this.publishDelay = schem.attributes.publishDelay;\n        this.version = schem.attributes.version;\n        this.createdAt = new Date(schem.attributes.createdAt);\n        this.updatedAt = new Date(schem.attributes.updatedAt);\n        const parentRelationship = Relationship.createSelfRelationship('scanlation_group', this);\n        this.leader = Relationship.convertType<User>('leader', schem.relationships, parentRelationship).pop() ?? null;\n        this.members = Relationship.convertType<User>('member', schem.relationships, parentRelationship);\n        this.exLicensed = schem.attributes.exLicensed;\n        this.verified = schem.attributes.verified;\n    }\n\n    /**\n     * Retrieves a group by their id\n     */\n    static async get(id: string): Promise<Group> {\n        return new Group(await fetchMDData<ScanlationGroupResponseSchema>(`/group/${id}`));\n    }\n\n    /**\n     * Retrieves a list of groups according to the specified search parameters\n     */\n    static async search(query?: GroupSearchParams): Promise<Group[]> {\n        const res = await fetchMDSearch<ScanlationGroupListSchema>(`/group`, query);\n        return res.map((u) => new Group(u));\n    }\n\n    /**\n     * Retrieves an array of groups by an array of ids\n     */\n    static async getMultiple(ids: string[]): Promise<Group[]> {\n        const res = await fetchMDByArrayParam<ScanlationGroupListSchema>('/group', ids);\n        return res.map((u) => new Group(u));\n    }\n\n    /**\n     * Performs a search for a group and returns the first one found. If no results are\n     * found, null is returned\n     */\n    static async getByQuery(query?: GroupSearchParams): Promise<Group | null> {\n        const res = await this.search(query);\n        return res[0] ?? null;\n    }\n\n    /**\n     * Create a new group\n     */\n    static async create(data: CreateScanlationGroupSchema) {\n        return new Group(await fetchMDDataWithBody<ScanlationGroupResponseSchema>('/group', data));\n    }\n\n    /**\n     * Deletes a group by their id\n     */\n    static async delete(id: string) {\n        await fetchMD<ResponseSchema>(`/group/${id}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Deletes this group\n     */\n    async delete() {\n        await Group.delete(this.id);\n    }\n\n    /**\n     * Updates a group's information.\n     */\n    async update(data: Omit<CreateScanlationGroupSchema, 'version'>) {\n        return new Group(\n            await fetchMDDataWithBody<ScanlationGroupResponseSchema>(\n                `/group/${this.id}`,\n                {\n                    ...data,\n                    version: this.version + 1,\n                },\n                undefined,\n                'PUT',\n            ),\n        );\n    }\n\n    /**\n     * Makes the logged in user follow or unfollow a group\n     */\n    static async changeFollowship(id: string, follow = true): Promise<void> {\n        await fetchMD(`/group/${id}/follow`, undefined, { method: follow ? 'POST' : 'DELETE' });\n    }\n\n    /**\n     * Makes the user follow or unfollow this group\n     */\n    async changeFollowship(follow = true): Promise<void> {\n        await Group.changeFollowship(this.id, follow);\n    }\n\n    /**\n     * Gets the statistics about a list of groups\n     */\n    static async getStatistics(ids: string[] | Group[]): Promise<Record<string, GroupStats>> {\n        const res = await fetchMD<GroupStatsResponse>(`/statistics/group`, { group: ids });\n        return res.statistics;\n    }\n\n    /**\n     * Gets the statistics about this group\n     */\n    async getStatistics(): Promise<GroupStats> {\n        const res = await Group.getStatistics([this.id]);\n        return res[this.id];\n    }\n\n    /**\n     * Gets an array of groups that the current user follows\n     */\n    static async getFollowedGroups(query: FollowedGroupsParams = { limit: Infinity, offset: 0 }): Promise<Group[]> {\n        const res = await fetchMDSearch<ScanlationGroupListSchema>('/user/follows/group', query);\n        return res.map((u) => new Group(u));\n    }\n}\n","import IDObject from '../internal/IDObject';\nimport Relationship from '../internal/Relationship';\nimport APIResponseError from '../util/APIResponseError';\nimport { fetchMD, fetchMDWithBody, fetchMDWithFormData } from '../util/Network';\n\nimport type {\n    BeginUploadSessionSchema,\n    CommitUploadSessionSchema,\n    RelationshipSchema,\n    ResponseSchema,\n    UploadSessionAttributesSchema,\n    UploadSessionSchema,\n    Upload,\n    UploadSessionFileSchema,\n    ChapterDraftSchema,\n    UploadSessionFileAttributesSchema,\n} from '../types/schema';\nimport type Group from './Group';\nimport type Manga from './Manga';\nimport type User from './User';\nimport type Chapter from './Chapter';\n\ntype FullUploadSession = UploadSessionSchema & { relationships: RelationshipSchema[] };\ntype FixedFullUploadSession = FullUploadSession | { data: FullUploadSession };\ntype FullPageFileResponse = Required<Upload.PutUploadSessionFile.ResponseBody>;\n\n/**\n * This class represents an in-progress manga upload session including the uploaded pages.\n */\nexport default class UploadSession extends IDObject implements UploadSessionAttributesSchema {\n    /**\n     * The MangaDex UUID of this upload session\n     */\n    id!: string;\n    /**\n     * Has this session been committed (pages published)\n     */\n    isCommitted!: boolean;\n    /**\n     * Has this session still been processed by MangaDex?\n     */\n    isProcessed!: boolean;\n    /**\n     * Has this session been deleted/aborted?\n     */\n    isDeleted!: boolean;\n    /**\n     * The version of this session (incremented by updating data)\n     */\n    version!: number;\n    /**\n     * When this upload session was started\n     */\n    createdAt!: Date;\n    /**\n     * When this upload session was last updated\n     */\n    updatedAt!: Date;\n    /**\n     * A relationship to who started this upload session\n     */\n    uploader!: Relationship<User>;\n    /**\n     * A relationship to the manga this upload session is for\n     */\n    manga!: Relationship<Manga>;\n    /**\n     * An array of relationships to the groups involved with the chapter for this session\n     */\n    groups!: Relationship<Group>[];\n    /**\n     * An array of uploaded page image files\n     */\n    pages!: UploadSessionFile[];\n\n    constructor(schem: FixedFullUploadSession) {\n        super();\n        this.updateData(schem);\n    }\n\n    private updateData(schem: FixedFullUploadSession) {\n        if ('data' in schem) schem = schem.data;\n        this.id = schem.id;\n        this.isCommitted = schem.attributes.isCommitted;\n        this.isProcessed = schem.attributes.isProcessed;\n        this.isDeleted = schem.attributes.isDeleted;\n        this.version = schem.attributes.version;\n        this.createdAt = new Date(schem.attributes.createdAt);\n        this.updatedAt = new Date(schem.attributes.updatedAt);\n        this.uploader = Relationship.convertType<User>('user', schem.relationships).pop()!;\n        this.manga = Relationship.convertType<Manga>('manga', schem.relationships).pop()!;\n        this.groups = Relationship.convertType<Group>('scanlation_group', schem.relationships);\n\n        // Directly parse uploaded file relationships into UploadSessionFile instances\n        // We can't use a regular Relationship since uploaded session files don't have a get endpoint\n        this.pages = schem.relationships\n            .filter((rel) => rel.type === 'upload_session_file')\n            .map((rel) => {\n                if (!rel.attributes) {\n                    throw new Error(\n                        'MangaDex did not return session file attributes in a relationship. Did you forget a reference expansion (ie includes[])?',\n                    );\n                }\n                return new UploadSessionFile({\n                    id: rel.id,\n                    attributes: rel.attributes as UploadSessionFileAttributesSchema,\n                    type: 'upload_session_file',\n                });\n            });\n        this.pages.sort((a, b) => a.num - b.num);\n    }\n\n    /**\n     * Begin a new upload session for a specified manga. At least one group must be specified\n     * @param cancelCurrentSession - Stop any current upload session before creating this one\n     */\n    static async begin(\n        manga: string | Manga,\n        groups: string[] | Group[] = [],\n        cancelCurrentSession = false,\n    ): Promise<UploadSession> {\n        if (cancelCurrentSession) await UploadSession.cancelCurrentSession();\n        return new UploadSession(\n            await fetchMDWithBody<FixedFullUploadSession>(\n                '/upload/begin',\n                {\n                    manga: typeof manga === 'string' ? manga : manga.id,\n                    groups: groups.map((g) => (typeof g === 'string' ? g : g.id)),\n                } as BeginUploadSessionSchema,\n                { includes: ['upload_session_file'] },\n            ),\n        );\n    }\n\n    /**\n     * Start a new upload session for editing an existing chapter. The upload session will\n     * act the same as one for new chapter.\n     * @param cancelCurrentSession - Stop any current upload session before creating this one\n     */\n    static async beginChapterEdit(chapter: Chapter, cancelCurrentSession = false) {\n        if (cancelCurrentSession) await UploadSession.cancelCurrentSession();\n        return new UploadSession(\n            await fetchMDWithBody<FixedFullUploadSession>(\n                `/upload/begin/${chapter.id}`,\n                {\n                    version: chapter.version,\n                },\n                { includes: ['upload_session_file'] },\n            ),\n        );\n    }\n\n    /**\n     * Get the current upload session owned by the currently authenticated user\n     */\n    static async getCurrentSession(): Promise<UploadSession> {\n        return new UploadSession(\n            await fetchMD<FixedFullUploadSession>('/upload', { includes: ['upload_session_file'] }),\n        );\n    }\n\n    /**\n     * Cancel the current user's current upload session if it exists\n     */\n    static async cancelCurrentSession(): Promise<void> {\n        let current;\n        try {\n            current = await UploadSession.getCurrentSession();\n        } catch (_) {}\n        if (current) await current.close();\n    }\n\n    /**\n     * Closes this upload session and removes all associated uploaded files\n     */\n    async close(): Promise<void> {\n        await fetchMD<ResponseSchema>(`/upload/${this.id}`, undefined, { method: 'DELETE' });\n        this.isDeleted = true;\n    }\n\n    /**\n     * Commit and publish this chapter to MangaDex.\n     * @param pageOrder - By default, the page order is decided by the 'pages' array of this upload session object.\n     * If this parameter is supplied an array, the order of elements in that array is used instead.\n     */\n    async commit(chapterData: ChapterDraftSchema, pageOrder?: string[] | UploadSessionFile[]): Promise<void> {\n        if (pageOrder) pageOrder = pageOrder.map((p) => (typeof p === 'string' ? p : p.id));\n        else pageOrder = this.pages.map((p) => p.id);\n        this.updateData(\n            await fetchMDWithBody<FixedFullUploadSession>(\n                `/upload/${this.id}/commit`,\n                {\n                    chapterDraft: chapterData,\n                    pageOrder: pageOrder,\n                } as CommitUploadSessionSchema,\n                {\n                    includes: ['upload_session_file'],\n                },\n            ),\n        );\n    }\n\n    /**\n     * Upload new page image files as blobs. The blobs should contain the binary image data, and although not necessary,\n     * it is recommended that the image MIME type is included as well. The resulting uploaded file data will be appended\n     * to this object's 'pages' property.\n     */\n    async uploadPages(files: Blob[]): Promise<void> {\n        const maxExistingPage = Math.max(...this.pages.map((p) => p.num), 0);\n        const newFiles = files.map((file, i) => ({\n            data: file,\n            name: (i + maxExistingPage).toString(),\n        }));\n        const promises = [];\n        while (newFiles.length > 0) {\n            promises.push(\n                fetchMDWithFormData<FullPageFileResponse>(`/upload/${this.id}`, { files: newFiles.splice(0, 10) }),\n            );\n        }\n        const allResults = await Promise.all(promises);\n        const errors = allResults.flatMap((res) => res.errors ?? []);\n        if (errors.length > 0) throw new APIResponseError(errors);\n        const data = allResults.flatMap((res) => res.data ?? []).map((page) => new UploadSessionFile(page));\n        data.sort((a, b) => a.num - b.num);\n        this.pages.push(...data);\n    }\n\n    /**\n     * Delete previously uploaded page image files by their ids\n     */\n    async deletePages(pages: string[] | UploadSessionFileSchema[]): Promise<void> {\n        const ids = pages.map((p) => (typeof p === 'string' ? p : p.id));\n        await fetchMDWithBody<ResponseSchema>(`/upload/${this.id}/batch`, ids, undefined, 'DELETE');\n        this.pages = this.pages.filter((p) => !ids.includes(p.id));\n    }\n}\n\nclass UploadSessionFile extends IDObject implements UploadSessionFileAttributesSchema {\n    /**\n     * The MangaDex UUID of this uploaded file\n     */\n    id: string;\n    /**\n     * The original filename of the file. May be an empty string\n     */\n    originalFileName: string;\n    /**\n     * The hash of this file. May be an empty string\n     */\n    fileHash: string;\n    /**\n     * The file size in bytes of this file\n     */\n    fileSize: number;\n    /**\n     * The MIME image type of this file\n     */\n    mimeType: string;\n    /**\n     * Is this file stored on MangaDex's server or elsewhere\n     */\n    source: 'local' | 'remote';\n    /**\n     * The version number of this file (incremented by updating the file's data)\n     */\n    version: number;\n    /**\n     * A number assigned to this file. It is usually from the order it was uploaded, but it can also\n     * be the file hash or another number.\n     */\n    num: number;\n\n    constructor(schem: UploadSessionFileSchema) {\n        super();\n        this.id = schem.id;\n        this.originalFileName = schem.attributes.originalFileName;\n        this.fileHash = schem.attributes.fileHash;\n        this.fileSize = schem.attributes.fileSize;\n        this.mimeType = schem.attributes.mimeType;\n        this.source = schem.attributes.source;\n        this.version = schem.attributes.version;\n\n        this.num = parseInt(this.originalFileName);\n        // Even if the filename is an invalid number, we would still like a unique number like the hash\n        if (isNaN(this.num)) this.num = parseInt(this.fileHash, 16);\n        if (isNaN(this.num)) this.num = 1000;\n    }\n}\n","import { IAuthClient } from '../types/helpers';\nimport AuthError from '../util/AuthError';\nimport { fetchMDAuth, performAuthCheck, setActiveAuthClient } from '../util/Network';\n\ntype PersonalClientInfo = {\n    username: string;\n    password: string;\n    clientId: string;\n    clientSecret: string;\n};\n\ntype ClientData = PersonalClientInfo & {\n    accessToken: string;\n    accessExpiration: number;\n    refreshToken: string;\n    refreshExpiration: number;\n};\n\ntype TokenBody = {\n    access_token: string;\n    expires_in: number;\n    refresh_token: string;\n    refresh_expires_in: number;\n};\n\n/**\n * This class is used to authenticate with the MangaDex API using a personal client.\n * {@link https://api.mangadex.org/docs/02-authentication/personal-clients/}\n */\nexport default class PersonalAuthClient implements IAuthClient {\n    data: ClientData;\n\n    constructor(data: ClientData) {\n        this.data = data;\n    }\n\n    /**\n     * Returns the client's access token and refreshes it if necessary.\n     */\n    async getSessionToken() {\n        if (Date.now() > this.data.refreshExpiration) {\n            throw new AuthError('Refresh token has expired. Please login again.');\n        }\n        if (Date.now() > this.data.accessExpiration) {\n            await this.refreshTokens();\n            const isValid = await performAuthCheck(this.data.accessToken);\n            if (!isValid) {\n                throw new AuthError('Failed to validate auth token. Please login again.');\n            }\n        }\n        return this.data.accessToken;\n    }\n\n    /**\n     * Refreshes the client's access token and refresh token.\n     */\n    async refreshTokens() {\n        // Documentation says to use this url but it doesn't work:\n        // '/realms/mangadex/protocol/openid-connect/token/auth/refresh'\n\n        const res = await fetchMDAuth<TokenBody>('/realms/mangadex/protocol/openid-connect/token', {\n            grant_type: 'refresh_token',\n            refresh_token: this.data.refreshToken,\n            client_id: this.data.clientId,\n            client_secret: this.data.clientSecret,\n        });\n\n        this.data.accessToken = res.access_token;\n        this.data.accessExpiration = toExpiration(res.expires_in);\n        this.data.refreshToken = res.refresh_token;\n        this.data.refreshExpiration = toExpiration(res.refresh_expires_in);\n    }\n\n    /**\n     * Creates a new PersonalAuthClient and optionally sets it as the active client.\n     */\n    static async login(info: PersonalClientInfo, activate = true): Promise<PersonalAuthClient> {\n        const res = await fetchMDAuth<TokenBody>('/realms/mangadex/protocol/openid-connect/token', {\n            grant_type: 'password',\n            username: info.username,\n            password: info.password,\n            client_id: info.clientId,\n            client_secret: info.clientSecret,\n        });\n\n        const client = new PersonalAuthClient({\n            ...info,\n            accessToken: res.access_token,\n            accessExpiration: toExpiration(res.expires_in),\n            refreshToken: res.refresh_token,\n            refreshExpiration: toExpiration(res.refresh_expires_in),\n        });\n        if (activate) setActiveAuthClient(client);\n        return client;\n    }\n}\n\n/**\n * Converts the \"expires_in\" value from the token body to an expiration timestamp\n */\nfunction toExpiration(offset: number): number {\n    // Subtract 5s to account for network latency\n    return offset * 1000 + Date.now() - 5000;\n}\n","import { fetchMDWithBody, performAuthCheck, setActiveAuthClient } from '../util/Network';\nimport AuthError from '../util/AuthError';\n\nimport type { IAuthClient } from '../types/helpers';\nimport type { RefreshResponseSchema, LoginResponseSchema } from '../types/schema';\n\ntype LoginData = {\n    session: string;\n    refresh: string;\n    timestamp: number;\n};\n\n/**\n * This class represents a the legacy (username and password) auth client.\n * This login method is being deprecated in favor of OAuth which is implemented through {@link PersonalAuthClient} instead.\n *\n * @deprecated - This login method is being replaced by OAuth\n */\nexport default class LegacyAuthClient implements IAuthClient {\n    data: LoginData;\n\n    constructor(data: LoginData) {\n        this.data = data;\n    }\n\n    async getSessionToken(): Promise<string> {\n        // Don't refresh if the token was refreshed less than 14.9 minutes ago (15 is the maximum age)\n        if (Date.now() - this.data.timestamp >= 894000) {\n            await this.refreshTokens();\n            const isValid = await this.checkSessionToken();\n            if (!isValid) {\n                throw new AuthError('Failed to validate auth token. Please login again.');\n            }\n        }\n        return this.data.session;\n    }\n\n    /**\n     * Set this auth instance to be the one used by all API calls\n     */\n    setActive() {\n        setActiveAuthClient(this);\n    }\n\n    /**\n     * Login with a legacy username and password, and activate this client for all API calls\n     */\n    static async login(username: string, password: string): Promise<LegacyAuthClient> {\n        const res = await fetchMDWithBody<LoginResponseSchema>('/auth/login', { username, password });\n        const session = res.token.session;\n        const refresh = res.token.refresh;\n        if (!session || !refresh) throw new AuthError('MangaDex did not return auth tokens.');\n        const client = new LegacyAuthClient({\n            session,\n            refresh,\n            timestamp: Date.now(),\n        });\n        client.setActive();\n        return client;\n    }\n\n    /**\n     * Refresh the access token and update the token data for this client\n     */\n    async refreshTokens() {\n        const res = await fetchMDWithBody<RefreshResponseSchema>(\n            '/auth/refresh',\n            { token: this.data.refresh },\n            undefined,\n            'POST',\n            { noAuth: true },\n        );\n        if (!res.token)\n            throw new AuthError(`Failed to refresh auth tokens, MangaDex did not return any. ${res.message}`);\n        const session = res.token.session;\n        const refresh = res.token.refresh;\n        if (!session || !refresh) throw new AuthError(`MangaDex did not return auth tokens. ${res.message}`);\n        this.data = {\n            session,\n            refresh,\n            timestamp: Date.now(),\n        };\n    }\n\n    /**\n     * Check if the current session token is valid by asking MangaDex\n     */\n    checkSessionToken(): Promise<boolean> {\n        return performAuthCheck(this.data.session);\n    }\n}\n","import IDObject from '../internal/IDObject';\nimport { fetchMD, fetchMDData, fetchMDDataWithBody, fetchMDSearch } from '../util/Network';\nimport Relationship from '../internal/Relationship';\nimport Chapter from './Chapter';\n\nimport type {\n    ChapterListSchema,\n    CustomListAttributesSchema,\n    CustomListCreateSchema,\n    CustomListListSchema,\n    CustomListResponseSchema,\n    CustomListSchema,\n    GetListIdFeedParamsSchema,\n    ResponseSchema,\n} from '../types/schema';\nimport type Manga from './Manga';\nimport type User from './User';\n\nexport default class List extends IDObject implements CustomListAttributesSchema {\n    /**\n     * The MangaDex UUID of this custom list\n     */\n    id: string;\n    /**\n     * The display name of this custom list\n     */\n    name: string;\n    /**\n     * Is this list public or private?\n     */\n    visibility: 'private' | 'public';\n    /**\n     * The version of this custom list (incremented by updating data)\n     */\n    version: number;\n    /**\n     * A relationship to the user who created and owns this list\n     */\n    creator: Relationship<User>;\n    /**\n     * An array of relationships to the manga in this custom list\n     */\n    manga: Relationship<Manga>[];\n\n    constructor(schem: CustomListSchema) {\n        super();\n        this.id = schem.id;\n        this.name = schem.attributes.name;\n        this.visibility = schem.attributes.visibility;\n        this.version = schem.attributes.version;\n        this.creator = Relationship.convertType<User>('user', schem.relationships).pop()!;\n        this.manga = Relationship.convertType<Manga>('manga', schem.relationships);\n    }\n\n    /**\n     * Retrieves a list by its id\n     */\n    static async get(id: string): Promise<List> {\n        return new List(await fetchMDData<CustomListResponseSchema>(`/list/${id}`));\n    }\n\n    /**\n     * Create a new list\n     */\n    static async create(data: CustomListCreateSchema): Promise<List> {\n        return new List(await fetchMDDataWithBody<CustomListResponseSchema>('/list', data));\n    }\n\n    /**\n     * Deletes a list by its id\n     */\n    static async delete(id: string) {\n        await fetchMD<ResponseSchema>(`/list/${id}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Deletes this list\n     */\n    async delete() {\n        await List.delete(this.id);\n    }\n\n    /**\n     * Updates a list's information.\n     */\n    async update(data: Partial<Omit<CustomListCreateSchema, 'version'>>) {\n        return new List(\n            await fetchMDDataWithBody<CustomListResponseSchema>(\n                `/list/${this.id}`,\n                {\n                    ...data,\n                    name: data.name ?? this.name,\n                    version: this.version + 1,\n                } as CustomListCreateSchema,\n                undefined,\n                'PUT',\n            ),\n        );\n    }\n\n    /**\n     * Make the currently authenticated user follow a list\n     */\n    static async follow(id: string): Promise<void> {\n        await fetchMD(`/list/${id}/follow`, undefined, { method: 'POST' });\n    }\n\n    /**\n     * Make the currently authenticated user follow this list\n     */\n    async follow(): Promise<void> {\n        await List.follow(this.id);\n    }\n\n    /**\n     * Make the currently authenticated user unfollow a list\n     */\n    static async unfollow(id: string): Promise<void> {\n        await fetchMD(`/list/${id}/follow`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Make the currently authenticated user unfollow this list\n     */\n    async unfollow(): Promise<void> {\n        await List.unfollow(this.id);\n    }\n\n    /**\n     * Add a manga to a list\n     */\n    static async addManga(listId: string, manga: Manga | string): Promise<void> {\n        if (typeof manga !== 'string') manga = manga.id;\n        await fetchMD<ResponseSchema>(`/manga/${manga}/list/${listId}`, undefined, { method: 'POST' });\n    }\n\n    /**\n     * Add a manga to this list\n     */\n    async addManga(manga: Manga | string): Promise<void> {\n        await List.addManga(this.id, manga);\n    }\n\n    /**\n     * Remove a manga from a list\n     */\n    static async removeManga(listId: string, manga: Manga | string): Promise<void> {\n        if (typeof manga !== 'string') manga = manga.id;\n        await fetchMD<ResponseSchema>(`/manga/${manga}/list/${listId}`, undefined, { method: 'DELETE' });\n    }\n\n    /**\n     * Remove a manga from this list\n     */\n    async removeManga(manga: Manga | string): Promise<void> {\n        await List.removeManga(this.id, manga);\n    }\n\n    /**\n     * Returns all of the currently authenticated user's custom manga lists\n     */\n    static async getLoggedInUserLists(limit = Infinity, offset = 0): Promise<List[]> {\n        const res = await fetchMDSearch<CustomListListSchema>('/user/list', { limit: limit, offset: offset });\n        return res.map((u) => new List(u));\n    }\n\n    /**\n     * Returns all of a user's custom manga lists\n     */\n    static async getUserLists(user: string | User, limit = Infinity, offset = 0): Promise<List[]> {\n        if (typeof user !== 'string') user = user.id;\n        const res = await fetchMDSearch<CustomListListSchema>(`/user/${user}/list`, { limit: limit, offset: offset });\n        return res.map((u) => new List(u));\n    }\n\n    /**\n     * Returns an array of chapters from the manga in a list\n     */\n    static async getFeed(listId: string, query?: Partial<GetListIdFeedParamsSchema>): Promise<Chapter[]> {\n        const res = await fetchMDSearch<ChapterListSchema>(`/list/${listId}/feed`, query);\n        return res.map((c) => new Chapter(c));\n    }\n\n    /**\n     * Returns an array of chapters from the manga in this list\n     */\n    async getFeed(query?: Partial<GetListIdFeedParamsSchema>): Promise<Chapter[]> {\n        return await List.getFeed(this.id, query);\n    }\n\n    /**\n     * Returns all lists followed by the currently authenticated user\n     */\n    static async getFollowedLists(limit = Infinity, offset = 0): Promise<List[]> {\n        const res = await fetchMDSearch<CustomListListSchema>('/user/follows/list', { limit: limit, offset: offset });\n        return res.map((u) => new List(u));\n    }\n\n    /**\n     * Changes the visibility of this custom list\n     */\n    async changeVisibility(newVis: 'public' | 'private'): Promise<List> {\n        return await this.update({ visibility: newVis });\n    }\n\n    /**\n     * Renames this custom list\n     */\n    async rename(name: string): Promise<List> {\n        return await this.update({ name: name });\n    }\n\n    /**\n     *\n     */\n    async updateMangaList(newList: Manga[] | string[]): Promise<List> {\n        newList = newList.map((i) => (typeof i === 'string' ? i : i.id));\n        return await this.update({ manga: newList });\n    }\n}\n","import Relationship from './internal/Relationship';\nimport Author from './shared/Author';\nimport Cover from './shared/Cover';\nimport Manga from './shared/Manga';\nimport Chapter from './shared/Chapter';\nimport User from './shared/User';\nimport Group from './shared/Group';\n\nif (Relationship.getRegisteredTypes().length === 0) {\n    Relationship.registerTypes(['manga'], Manga);\n    Relationship.registerTypes(['author', 'artist'], Author);\n    Relationship.registerTypes(['cover_art'], Cover);\n    Relationship.registerTypes(['chapter'], Chapter);\n    Relationship.registerTypes(['user', 'member', 'leader', 'creator'], User);\n    Relationship.registerTypes(['scanlation_group'], Group);\n    Relationship.lockTypeMap();\n}\n\n// Export Classes:\n\nexport { default as Author } from './shared/Author';\nexport { default as Cover } from './shared/Cover';\nexport { default as Manga } from './shared/Manga';\nexport { default as Tag } from './shared/Tag';\nexport { default as Chapter } from './shared/Chapter';\nexport { default as User } from './shared/User';\nexport { default as Group } from './shared/Group';\nexport { default as UploadSession } from './shared/UploadSession';\nexport { default as PersonalAuthClient } from './shared/PersonalAuthClient';\nexport { default as LegacyAuthClient } from './shared/LegacyAuthClient';\nexport { default as List } from './shared/List';\n\n// Export specific functions:\n\nexport { useDebugServer, overrideApiOrigin, overrideAuthOrigin } from './util/Network';\n\nimport LocalizedString from './internal/LocalizedString';\n/**\n * Sets the global language locale to be used by LocalString objects.\n */\nexport const setGlobalLocale = LocalizedString.setGlobalLocale;\n\n/**\n * This will {@link Relationship.resolve} an array of relationships, returning another array\n * in the same order.\n * @param relationshipArray - An array of relationships of the same type\n */\nexport const resolveArray = Relationship.resolveAll;\n\n/**\n * Converts old (pre v5, numeric ids) Mangadex ids to v5 ids. Any invalid legacy ids will be\n * skipped by Mangadex when remapping, so call this function for each individual id if this is an issue.\n */\nexport const convertLegacyId = Manga.convertLegacyId;\n\nimport LegacyAuthClient from './shared/LegacyAuthClient';\n\n/**\n * Login with a legacy username and password\n *\n * @deprecated - This login method is being replaced by OAuth\n *\n * @param username - Username of the account\n * @param password - Password of the account\n */\nexport const login = LegacyAuthClient.login;\n\nimport PersonalAuthClient from './shared/PersonalAuthClient';\n\n/**\n * Login with a personal client. This method is recommended for smaller, private applications.\n * {@link https://api.mangadex.org/docs/02-authentication/personal-clients/}\n * @param clientInfo - Personal client info including client secret/id, username, and password\n * @param activate - By default, this client will be set as the active client for all API calls. Set this to false to disable this behavior.\n */\nexport const loginPersonal = PersonalAuthClient.login;\n\nimport { clearActiveAuthClient, getActiveAuthClient } from './util/Network';\n\n/**\n * This will clear the active auth client, effectively logging out.\n */\nexport const logout = clearActiveAuthClient;\n\n/**\n * This will return the current active auth client, if any.\n */\nexport const getCurrentAuthClient = getActiveAuthClient;\n"],"mappings":"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","names":["IDObject","IDObject_default","_Relationship","IDObject_default","data","_a","classObj","schemaObj","err","__async","relationshipArray","elem","type","arr","parent","__spreadProps","__spreadValues","self","types","Relationship","Relationship_default","_LocalizedString","strings","locale","i","LocalizedString","LocalizedString_default","APIResponseError","_APIResponseError","info","errors","err","i","arr","str","AuthError","_AuthError","info","NetworkStateManager","_a","rawDomain","useDebugServer","val","devApiDomain","devAuthDomain","overrideApiOrigin","domain","overrideAuthOrigin","setActiveAuthClient","client","clearActiveAuthClient","getActiveAuthClient","fetchMD","_0","_1","__async","endpoint","params","requestInit","url","buildURL","sessionToken","res","contentType","errInfo","text","_","APIResponseError","data","fetchMDData","fetchMDSearch","maxLimit","defaultLimit","_b","targetLimit","initialOffset","firstResponse","__spreadProps","__spreadValues","promises","offset","limitForThisRequest","newResults","fetchMDByArrayParam","arr","extraParams","arrayParam","paramLimit","idArray","elem","IDObject_default","i","sortedResults","a","b","fetchMDWithBody","_2","body","method","headers","fetchMDDataWithBody","postToMDNetwork","fetchMDWithFormData","formdata","appendItem","name","item","value","v","base","path","valueEntries","k","performAuthCheck","options","err","fetchMDAuth","AuthError","Author","_Author","IDObject_default","schem","LocalizedString_default","Relationship_default","id","expandedTypes","__async","fetchMDData","query","fetchMDSearch","m","_a","ids","fetchMDByArrayParam","data","fetchMDDataWithBody","fetchMD","__spreadProps","__spreadValues","Cover","_Cover","IDObject_default","schem","_a","parentRelationship","Relationship_default","id","expandedTypes","__async","fetchMDData","query","fetchMDSearch","m","ids","fetchMDByArrayParam","manga","fetchMD","data","fetchMDDataWithBody","__spreadProps","__spreadValues","res","fetchMDWithFormData","Tag","_Tag","IDObject_default","data","LocalizedString_default","__async","res","fetchMD","elem","name","tags","lowerName","foundTag","tag","n","names","lowerNames","Links","linksObject","Links_default","Chapter","_Chapter","IDObject_default","schem","Relationship_default","id","expandedTypes","__async","fetchMDData","ids","fetchMDByArrayParam","c","query","fetchMDSearch","_a","data","fetchMDDataWithBody","__spreadProps","__spreadValues","fetchMD","saver","forcePort","_b","res","file","report","postToMDNetwork","Manga","_Manga","IDObject_default","schem","_a","parentRelationship","Relationship_default","elem","LocalizedString_default","Links_default","Tag","relationships","relatedManga","rel","title","id","expandedTypes","__async","fetchMDData","query","fetchMDSearch","m","ids","extraParams","fetchMDByArrayParam","fetchMD","__spreadProps","__spreadValues","params","c","Chapter","manga","chapters","updateHistory","_b","_c","_d","body","fetchMDWithBody","mangaData","i","res","APIResponseError","key","value","allChapters","returnObj","Cover","u","parsedObj","mangaId","rating","type","fetchMDDataWithBody","filter","status","expandTypes","relation","targetId","relationType","relationId","draftId","data","groups","languages","follow","User","_User","IDObject_default","schem","Relationship_default","id","__async","fetchMDData","query","fetchMDSearch","u","ids","fetchMDByArrayParam","_a","Group","_Group","IDObject_default","schem","_a","name","LocalizedString_default","parentRelationship","Relationship_default","id","__async","fetchMDData","query","fetchMDSearch","u","ids","fetchMDByArrayParam","data","fetchMDDataWithBody","fetchMD","__spreadProps","__spreadValues","follow","UploadSession","_UploadSession","IDObject_default","schem","Relationship_default","rel","UploadSessionFile","a","b","_0","__async","manga","groups","cancelCurrentSession","fetchMDWithBody","g","chapter","fetchMD","current","_","chapterData","pageOrder","p","files","maxExistingPage","newFiles","file","i","promises","fetchMDWithFormData","allResults","errors","res","_a","APIResponseError","data","page","pages","ids","PersonalAuthClient","_PersonalAuthClient","data","__async","AuthError","performAuthCheck","res","fetchMDAuth","toExpiration","info","activate","client","__spreadProps","__spreadValues","setActiveAuthClient","offset","LegacyAuthClient","_LegacyAuthClient","data","__async","AuthError","setActiveAuthClient","username","password","res","fetchMDWithBody","session","refresh","client","performAuthCheck","List","_List","IDObject_default","schem","Relationship_default","id","__async","fetchMDData","data","fetchMDDataWithBody","fetchMD","_a","__spreadProps","__spreadValues","listId","manga","limit","offset","fetchMDSearch","u","user","query","c","Chapter","newVis","name","newList","i","Relationship_default","Manga","Author","Cover","Chapter","User","Group","setGlobalLocale","LocalizedString_default","resolveArray","convertLegacyId","login","LegacyAuthClient","loginPersonal","PersonalAuthClient","logout","clearActiveAuthClient","getCurrentAuthClient","getActiveAuthClient"]}