import logger from './logger.js' const MAX_PAGES = 100 const PAGE_SIZE = 100 /** * Walk every page of a DRF paginated list endpoint and return a single flat * array. Falls back to a raw array response for backward compat (some * endpoints don't paginate), and stops on any other unexpected shape. * * @param {import('axios').AxiosInstance} client shared apiClient * @param {string} url fully-qualified endpoint URL * @param {Object} [params] extra query params (forwarded to every page) * @returns {Promise} */ export async function paginatedGet(client, url, params = {}) { const all = [] let page = 1 let hasNext = true logger.debug(`paginatedGet start`, { url }) while (hasNext) { if (page > MAX_PAGES) { logger.warn(`paginatedGet hit ${MAX_PAGES}-page cap, stopping`, { url }) break } const pageParams = { ...params, page, page_size: PAGE_SIZE } const response = await client.get(url, { params: pageParams }) const data = response.data if (data && Array.isArray(data.results)) { all.push(...data.results) hasNext = !!data.next logger.debug( `paginatedGet page ${page}: +${data.results.length} (total ${all.length}, hasNext=${hasNext})`, { url }, ) } else if (Array.isArray(data)) { all.push(...data) hasNext = false logger.debug(`paginatedGet got non-paginated array of ${data.length}`, { url }) } else { logger.warn(`paginatedGet unexpected response shape, stopping`, { url, page }) hasNext = false } page++ } logger.debug(`paginatedGet done`, { url, total: all.length }) return all }