• Gets the current authenticated user's manga list from AniList. Fetches the complete collection in chunks if needed. Detects and propagates rate limit errors to the caller.

    Parameters

    • token: string

      The user's access token.

    • OptionalabortSignal: AbortSignal

      Optional AbortSignal to cancel the request.

    • OptionalnoRetry: boolean

      Disable automatic retry logic (default: false).

    Returns Promise<UserMediaList>

    Promise resolving to user's manga list keyed by media ID.

    On network failure, auth failure, or rate limiting.

    export async function getUserMangaList(
    token: string,
    abortSignal?: AbortSignal,
    noRetry?: boolean,
    ): Promise<UserMediaList> {
    return withGroupAsync(`[AniListClient] Get User Manga List`, async () => {
    if (!token) {
    const error = createError(
    ErrorType.AUTH,
    "Access token required to fetch user manga list",
    new Error("Missing access token"),
    );
    captureError(
    ErrorType.AUTH,
    "Access token required to fetch user manga list",
    new Error("Missing access token"),
    );
    throw error;
    }

    try {
    // Get the user's ID first
    const viewerId = await getAuthenticatedUserId(token, abortSignal);
    console.debug(
    "[AniListClient] ✅ Successfully retrieved user ID:",
    viewerId,
    );

    if (!viewerId) {
    const error = createError(
    ErrorType.VALIDATION,
    "Failed to get your AniList user ID",
    new Error("User ID resolution failed"),
    );
    captureError(
    ErrorType.VALIDATION,
    "Failed to get AniList user ID",
    new Error("User ID resolution failed"),
    );
    throw error;
    }

    // Fetch all manga lists using multiple chunks if needed
    return await fetchCompleteUserMediaList(
    viewerId,
    token,
    abortSignal,
    noRetry,
    );
    } catch (error: unknown) {
    // Early return if error is not an object
    if (!error || typeof error !== "object") {
    captureError(
    ErrorType.UNKNOWN,
    "Unknown error fetching user manga list",
    error instanceof Error ? error : new Error(String(error)),
    );
    throw error;
    }

    const errorObj = error as {
    status?: number;
    isRateLimited?: boolean;
    retryAfter?: number;
    message?: string;
    };

    // Check for direct rate limit errors
    const directRateLimitError = checkDirectRateLimitError(errorObj);
    if (directRateLimitError) {
    throw directRateLimitError;
    }

    // Check for rate limit mentions in error messages
    const messageBasisRateLimitError = checkRateLimitInMessage(errorObj);
    if (messageBasisRateLimitError) {
    throw messageBasisRateLimitError;
    }

    throw error;
    }
    });
    }