• Update a single manga entry in AniList.

    Parameters

    • mediaEntry: AniListMediaEntry

      The AniList media entry to update.

    • token: string

      The user's authentication token.

    Returns Promise<SyncResult>

    A promise resolving to a SyncResult object.

    export async function updateMangaEntry(
    mediaEntry: AniListMediaEntry,
    token: string,
    ): Promise<SyncResult> {
    // Generate an operation ID for tracking in logs early
    const operationId = `${mediaEntry.mediaId}-${Date.now().toString(36).substring(4, 10)}`;

    return withGroupAsync(
    `[AniListSync] Update Entry [${operationId}] - Media ${mediaEntry.mediaId}`,
    async () => {
    if (!token) {
    console.error(
    `[AniListSync] ❌ [${operationId}] No authentication token provided`,
    );
    return {
    success: false,
    mediaId: mediaEntry.mediaId,
    error: "No authentication token provided",
    rateLimited: false,
    retryAfter: null,
    };
    }

    try {
    // Build variables based on entry type (existing vs new)
    let variables = mediaEntry.previousValues
    ? buildVariablesForExistingEntry(mediaEntry)
    : buildVariablesForNewEntry(mediaEntry);

    // Apply incremental sync modifications if needed
    variables = applyIncrementalSyncStep(
    mediaEntry,
    variables,
    operationId,
    );

    // Generate a dynamic mutation with only the needed variables
    const mutation = generateUpdateMangaEntryMutation(variables);

    // Define the expected response structure to handle both direct and nested formats
    interface SaveMediaListEntryData {
    SaveMediaListEntry?: {
    id: number;
    status: string;
    progress: number;
    private: boolean;
    score: number;
    };
    data?: {
    SaveMediaListEntry?: {
    id: number;
    status: string;
    progress: number;
    private: boolean;
    score: number;
    };
    };
    }

    // Make the API request with optimized variables and mutation
    const response = await request<SaveMediaListEntryData>(
    mutation,
    variables,
    token,
    );

    // Check for GraphQL errors
    if (response.errors && response.errors.length > 0) {
    return handleGraphQLErrors(
    response.errors,
    mediaEntry.mediaId,
    operationId,
    );
    }

    // Handle response data
    return handleResponseData(response, mediaEntry.mediaId, operationId);
    } catch (error) {
    // Handle exception errors
    return handleUpdateError(error, mediaEntry, operationId);
    }
    },
    );
    }