The AniList media entry to update.
The user's authentication token.
A promise resolving to a SyncResult object.
export async function updateMangaEntry(
entry: AniListMediaEntry,
token: string,
): Promise<SyncResult> {
// Generate an operation ID for tracking in logs early
const operationId = `${entry.mediaId}-${Date.now().toString(36).substring(4, 10)}`;
if (!token) {
console.error(`❌ [${operationId}] No authentication token provided`);
return {
success: false,
mediaId: entry.mediaId,
error: "No authentication token provided",
rateLimited: false,
retryAfter: null,
};
}
try {
// Build variables based on entry type (existing vs new)
let variables = entry.previousValues
? buildVariablesForExistingEntry(entry)
: buildVariablesForNewEntry(entry);
// Apply incremental sync modifications if needed
variables = applyIncrementalSyncStep(entry, 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, entry.mediaId, operationId);
}
// Handle response data
return handleResponseData(response, entry.mediaId, operationId);
} catch (error) {
// Handle exception errors
return handleUpdateError(error, entry, operationId);
}
}
Update a single manga entry in AniList.