import type { LocationQuery } from 'vue-router'; const DEFAULT_PLUGIN_PAGE_NUMBER = 1; const DEFAULT_PLUGIN_PAGE_SIZE = 12; const DEFAULT_PLUGIN_CATEGORY_ID = '0'; const PLUGIN_PAGE_SIZES = new Set([12, 24, 36, 48]); const DEFAULT_TOOL_PAGE_NUMBER = 1; const DEFAULT_TOOL_PAGE_SIZE = 10; const TOOL_PAGE_SIZES = new Set([10, 20, 50, 100]); const PLUGIN_LIST_QUERY_KEYS = { categoryId: 'categoryId', keyword: 'keyword', pageNumber: 'pageNumber', pageSize: 'pageSize', } as const; const PLUGIN_RETURN_QUERY_KEYS = { categoryId: 'returnCategoryId', keyword: 'returnKeyword', pageNumber: 'returnPageNumber', pageSize: 'returnPageSize', } as const; const TOOL_LIST_QUERY_KEYS = { keyword: 'toolKeyword', pageNumber: 'toolPageNumber', pageSize: 'toolPageSize', } as const; interface PluginListRouteState { categoryId: string; keyword: string; pageNumber: number; pageSize: number; } interface PluginToolListRouteState { keyword: string; pageNumber: number; pageSize: number; } function readQueryValue(query: LocationQuery, key: string): string { const value = query[key]; const normalized = Array.isArray(value) ? value[0] : value; return normalized === null || normalized === undefined ? '' : String(normalized); } function parsePositiveInteger(value: string, fallback: number): number { if (!/^\d+$/.test(value)) { return fallback; } const parsed = Number(value); return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : fallback; } function parsePluginState( query: LocationQuery, keys: typeof PLUGIN_LIST_QUERY_KEYS | typeof PLUGIN_RETURN_QUERY_KEYS, ): PluginListRouteState { const pageSize = parsePositiveInteger( readQueryValue(query, keys.pageSize), DEFAULT_PLUGIN_PAGE_SIZE, ); return { categoryId: readQueryValue(query, keys.categoryId) || DEFAULT_PLUGIN_CATEGORY_ID, keyword: readQueryValue(query, keys.keyword), pageNumber: parsePositiveInteger( readQueryValue(query, keys.pageNumber), DEFAULT_PLUGIN_PAGE_NUMBER, ), pageSize: PLUGIN_PAGE_SIZES.has(pageSize) ? pageSize : DEFAULT_PLUGIN_PAGE_SIZE, }; } function buildPluginStateQuery( state: PluginListRouteState, keys: typeof PLUGIN_LIST_QUERY_KEYS | typeof PLUGIN_RETURN_QUERY_KEYS, ): LocationQuery { return { ...(state.pageNumber === DEFAULT_PLUGIN_PAGE_NUMBER ? {} : { [keys.pageNumber]: String(state.pageNumber) }), ...(state.pageSize === DEFAULT_PLUGIN_PAGE_SIZE ? {} : { [keys.pageSize]: String(state.pageSize) }), ...(state.categoryId === DEFAULT_PLUGIN_CATEGORY_ID ? {} : { [keys.categoryId]: state.categoryId }), ...(state.keyword ? { [keys.keyword]: state.keyword } : {}), }; } function parsePluginListRouteState(query: LocationQuery): PluginListRouteState { return parsePluginState(query, PLUGIN_LIST_QUERY_KEYS); } function parsePluginToolsReturnState( query: LocationQuery, ): PluginListRouteState { return parsePluginState(query, PLUGIN_RETURN_QUERY_KEYS); } function buildPluginListRouteQuery(state: PluginListRouteState): LocationQuery { return buildPluginStateQuery(state, PLUGIN_LIST_QUERY_KEYS); } function buildPluginToolsReturnQuery( state: PluginListRouteState, ): LocationQuery { return buildPluginStateQuery(state, PLUGIN_RETURN_QUERY_KEYS); } function mergePluginListRouteQuery( query: LocationQuery, state: PluginListRouteState, ): LocationQuery { const listKeys = new Set(Object.values(PLUGIN_LIST_QUERY_KEYS)); return { ...Object.fromEntries( Object.entries(query).filter(([key]) => !listKeys.has(key)), ), ...buildPluginListRouteQuery(state), }; } function parsePluginToolListRouteState( query: LocationQuery, ): PluginToolListRouteState { const pageSize = parsePositiveInteger( readQueryValue(query, TOOL_LIST_QUERY_KEYS.pageSize), DEFAULT_TOOL_PAGE_SIZE, ); return { keyword: readQueryValue(query, TOOL_LIST_QUERY_KEYS.keyword), pageNumber: parsePositiveInteger( readQueryValue(query, TOOL_LIST_QUERY_KEYS.pageNumber), DEFAULT_TOOL_PAGE_NUMBER, ), pageSize: TOOL_PAGE_SIZES.has(pageSize) ? pageSize : DEFAULT_TOOL_PAGE_SIZE, }; } function buildPluginToolListRouteQuery( state: PluginToolListRouteState, ): LocationQuery { return { ...(state.pageNumber === DEFAULT_TOOL_PAGE_NUMBER ? {} : { [TOOL_LIST_QUERY_KEYS.pageNumber]: String(state.pageNumber) }), ...(state.pageSize === DEFAULT_TOOL_PAGE_SIZE ? {} : { [TOOL_LIST_QUERY_KEYS.pageSize]: String(state.pageSize) }), ...(state.keyword ? { [TOOL_LIST_QUERY_KEYS.keyword]: state.keyword } : {}), }; } function mergePluginToolListRouteQuery( query: LocationQuery, state: PluginToolListRouteState, ): LocationQuery { const listKeys = new Set(Object.values(TOOL_LIST_QUERY_KEYS)); return { ...Object.fromEntries( Object.entries(query).filter(([key]) => !listKeys.has(key)), ), ...buildPluginToolListRouteQuery(state), }; } function buildPluginToolsRouteQueryFromEdit( query: LocationQuery, pluginId: string, ): LocationQuery { const nextQuery: LocationQuery = { ...query, id: pluginId }; delete nextQuery.pluginId; return nextQuery; } export { buildPluginListRouteQuery, buildPluginToolsReturnQuery, buildPluginToolsRouteQueryFromEdit, mergePluginListRouteQuery, mergePluginToolListRouteQuery, parsePluginListRouteState, parsePluginToolListRouteState, parsePluginToolsReturnState, }; export type { PluginListRouteState, PluginToolListRouteState };