Query Parser
Parse a query string into a nested object, including repeated keys and bracket notation.
ctx.query inside a route handler is a plain URLSearchParams, which has no concept of nesting or repeated-key arrays. parseQueryParams fills that gap for a query string with real structure.
import { parseQueryParams } from '@codexa/core/query';
parseQueryParams('page=1&limit=20&sort[field]=name');
// { page: '1', limit: '20', sort: { field: 'name' } }
parseQueryParams('tags[]=a&tags[]=b');
// { tags: ['a', 'b'] }
parseQueryParams('?page=1'); // leading "?" is stripped automatically
// { page: '1' }Every value comes back as a string, or nested strings, parseQueryParams does no type coercion. Convert page to a number yourself, or validate the whole result with a Zod schema, the same schema you would also use for OpenAPI query documentation.
In a route handler
scope.route({
method: 'GET',
path: '/products',
handler: (ctx) => {
const query = parseQueryParams(ctx.url.search);
// query.filters?.status, query.sort, etc.
return ctx.json({ query });
},
});Passing options through
parseQueryParams accepts the same options qs itself does, as a second argument, for cases the defaults do not cover.
parseQueryParams(search, { depth: 3, parameterLimit: 50 });