@adonis-agora/filter
Version:
Server-side query filtering/sorting/pagination for AdonisJS — Spatie-style input, a Lucid adapter, and field allow-listing. Part of the Agora ecosystem.
46 lines • 2.67 kB
JavaScript
import { HttpContext } from '@adonisjs/core/http';
import { applyFilterFromRequest, } from './apply_from_request.js';
import { stashPagination } from './pagination_stash.js';
export function Filterable(superclass) {
class FilterableModel extends superclass {
/** The filter this model is read through. A thunk, so the filter may import the model back. */
static $filter;
/**
* Apply the model's filter to a fresh query and hand back the **query builder** plus the
* pagination the request resolved to — filters, search and sort applied, nothing executed.
* Compose whatever else the endpoint needs on the builder, then page it with
* `filterPaginate()` (no arguments) or `paginate(page, size)`.
*/
static async filter(ctx, filter, options) {
// `this` is the model the static was called on (a subclass of the mixin), which is exactly
// what these helpers need — the rule's suggestion (name the class) would pin every model to
// the anonymous mixin class instead.
// biome-ignore lint/complexity/noThisInStatic: `this` is the calling model, by design.
const model = this;
const target = filter ?? model.$filter?.();
if (!target) {
throw new Error(
// biome-ignore lint/complexity/noThisInStatic: names the model the call was made on.
`${this.name} has no filter — declare \`static $filter = () => YourFilter\` on the model, or pass one to filter().`);
}
// biome-ignore lint/complexity/noThisInStatic: the calling model builds its own query.
const query = this.query();
const pagination = await applyFilterFromRequest(query, target, ctx ?? HttpContext.getOrFail(), options);
stashPagination(query, pagination);
return { query, page: pagination.page, size: pagination.size };
}
/**
* The same, then `paginate(page, size)` with the pagination the request resolved to — the
* whole list endpoint in one call.
*/
static async filterPaginate(ctx, filter, options) {
// biome-ignore lint/complexity/noThisInStatic: `this` is the calling model, by design.
const model = this;
// biome-ignore lint/complexity/noThisInStatic: forwards the call to the same model.
const { query, page, size } = await model.filter.call(this, ctx, filter, options);
return query.paginate(page, size);
}
}
return FilterableModel;
}
//# sourceMappingURL=filterable_mixin.js.map