Fix query and API bugs: 403 for non-owners, page bounds, lifecycle filters, cover fallback, race-safe inserts, async album delete

This commit is contained in:
2026-09-24 05:14:05 +02:00
parent ab388e6ad6
commit 0e3576922f
90 changed files with 2083 additions and 322 deletions
+65 -2
View File
@@ -1396,6 +1396,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -1430,6 +1437,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -1465,6 +1479,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -1507,6 +1528,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -1825,6 +1853,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -1957,6 +1992,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -1991,6 +2033,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -2073,6 +2122,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -2353,6 +2409,13 @@ export interface operations {
};
content?: never;
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Not Found */
404: {
headers: {
@@ -2561,8 +2624,8 @@ export interface operations {
"application/json": components["schemas"]["TrackApplicationResponse"];
};
};
/** @description Not Found */
404: {
/** @description No Content */
204: {
headers: {
[name: string]: unknown;
};
+3 -2
View File
@@ -3,7 +3,7 @@ export const SEARCH_DEBOUNCE_MS = 450;
export const SEARCH_MIN_LENGTH = 2;
export const INFINITE_SCROLL_ROOT_MARGIN = '300px';
export const ALBUMS_PAGE_SIZE = 50;
export const ALBUM_TRACKS_PAGE_SIZE = 200;
export const ALBUM_TRACKS_PAGE_SIZE = 100;
export const ALBUM_EARLIEST_YEAR = 1877;
export const LIBRARY_PICKER_PAGE_SIZE = 50;
export const EXPLORE_ALBUMS_PAGE_SIZE = 10;
@@ -15,7 +15,8 @@ export const HOME_CONTINUE_LIMIT = 10;
export const HOME_SPOTLIGHT_TRACKS_LIMIT = 5;
export const HOME_POPULAR_MAX = 8;
export const PLAYLIST_PICKER_PAGE_SIZE = 50;
export const LIKED_TRACKS_PAGE_SIZE = 500;
export const LIKED_TRACKS_LIMIT = 500;
export const PLAYLIST_TRACKS_LIMIT = 500;
export const EXPLORE_USERS_LIMIT = 12;
export const FOLLOW_LIST_PAGE_SIZE = 30;
export const MENU_WIDTH = 240;
+22
View File
@@ -0,0 +1,22 @@
/** Largest page size the API accepts (`PageRequest.MaxPageSize` in the backend). */
export const API_MAX_PAGE_SIZE = 100;
type Page<T> = { items: T[]; hasNextPage: boolean };
/** Loads consecutive pages until the list ends or `maxItems` items were collected. */
export async function fetchAllPages<T>(
loadPage: (pageNumber: number, pageSize: number) => Promise<Page<T> | undefined>,
maxItems: number
): Promise<T[]> {
const items: T[] = [];
for (let pageNumber = 1; items.length < maxItems; pageNumber++) {
const page = await loadPage(pageNumber, API_MAX_PAGE_SIZE);
if (!page) break;
items.push(...page.items);
if (!page.hasNextPage) break;
}
return items.slice(0, maxItems);
}