/** * Pure list-query serialization, shared by local and remote adapters. * * @author Laurent Declercq l.declercq@agon-innovation.ch * @version 20260921 */ /** * Normalize untrusted query parameters into a bounded list request. * * @param {Record} query - Parsed URL query. * @returns {{search: string, status: string, page: number, pageSize: number, sort: string, direction: string}} List state. */ export function parseListQuery(query = {}) { return { search: String(query.q || '').slice(0, 200), status: String(query.status || 'all'), page: Math.max(1, Math.min(10000, Number.parseInt(query.page, 10) || 1)), pageSize: [ 5, 10, 25 ].includes(Number(query.size)) ? Number(query.size) : 10, sort: String(query.sort || 'name'), direction: query.direction === 'desc' ? 'desc' : 'asc' }; } /** * Serialize only meaningful list state, keeping default URLs short. * * @param {ReturnType} state - Current list state. * @returns {string} Search string, with a leading question mark when needed. */ export function serializeListQuery(state) { const query = new URLSearchParams(); if (state.search) { query.set('q', state.search); } if (state.status !== 'all') { query.set('status', state.status); } if (state.page > 1) { query.set('page', String(state.page)); } if (state.pageSize !== 10) { query.set('size', String(state.pageSize)); } if (state.sort !== 'name') { query.set('sort', state.sort); } if (state.direction === 'desc') { query.set('direction', state.direction); } return query.size ? `?${query}` : ''; }