@jimjam.dev/url-state
Version:
A url state manager for nextjs
112 lines • 3.72 kB
JavaScript
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