UNPKG

@jimjam.dev/url-state

Version:
112 lines 3.72 kB
import { deserializeUrl } from './serializer'; /** * Configurable QueryBuilder class for processing URL state */ export class QueryBuilder { constructor(config = {}) { const ignored = config.ignored || []; this.config = { defaults: { page: 1, pageSize: 10, ...config.defaults }, ignored, ignoredSet: ignored.length > 0 ? new Set(ignored) : null, mappings: config.mappings || {}, postProcess: config.postProcess }; } /** * Add default values (rebuilds ignoredSet for consistency) */ setDefaults(defaults) { this.config.defaults = { ...this.config.defaults, ...defaults }; return this; } /** * Add properties to ignore (rebuilds ignoredSet) */ ignore(...properties) { this.config.ignored.push(...properties); this.config.ignoredSet = this.config.ignored.length > 0 ? new Set(this.config.ignored) : null; return this; } /** * Add custom property mappings */ addMapping(property, mapper) { this.config.mappings[property] = mapper; return this; } /** * Build query from searchParams with optional unique key filtering */ fromUrl(searchParams, uniqueKey = '') { const filteredParams = deserializeUrl(searchParams, uniqueKey); return this.build(filteredParams); } /** * Build query from already-filtered parameters */ build(params) { // Pre-create result with defaults (already combined in constructor) const result = Object.assign({}, this.config.defaults); // Early return if no params to process if (!params || Object.keys(params).length === 0) { return (this.config.postProcess ? this.config.postProcess(result) : result); } // Process parameters with optimized loops using pre-computed Set for (const [key, value] of Object.entries(params)) { if (value === undefined) continue; // Fast ignored check using pre-computed Set if (this.config.ignoredSet?.has(key)) continue; // Apply mapping or direct assignment const mapper = this.config.mappings[key]; result[key] = mapper ? mapper(value) : value; } // Apply post-processing if configured return (this.config.postProcess ? this.config.postProcess(result) : result); } } /** * Create a configured query builder function * * @example * ```ts * // In your lib/utils/qb.ts file: * import { createQueryBuilder } from '@jimjam.dev/url-state'; * * export const qb = createQueryBuilder({ * defaults: { page: 1, pageSize: 10 }, * ignored: ['debug'], * mappings: { * orderBy: (value) => value, * orderDir: (value) => value || '+' * }, * postProcess: (result) => { * if (result.orderBy) { * result.sort = `${result.orderDir}${result.orderBy}`; * } * return result; * } * }); * * // Use it: * const query = qb(searchParams, 'users_'); * ``` */ export function createQueryBuilder(config) { const builder = new QueryBuilder(config); // Return optimized function that reuses the same builder instance return (searchParams, uniqueKey = '') => { return builder.fromUrl(searchParams, uniqueKey); }; } /** * Direct queryBuilder function (unconfigured) * Takes searchParams and uniqueKey, returns filtered and processed query */ export function queryBuilder(searchParams, uniqueKey = '') { const builder = new QueryBuilder(); return builder.fromUrl(searchParams, uniqueKey); } //# sourceMappingURL=query-builder.js.map