DevelopmentResource Framework
Filter Registry
Filter registry
Filters standardize how list/search UIs express conditions across resources. This module defines the canonical set of operators, which operators are valid per datatype, and a helper to provide select/enum options for filter UIs.
What it provides
filterRegistry: maps datatypes to supported operators- Types:
FilterOperator,FilterDefinition,FilterRegistry getFilterOptions(resourceName, columnName): returns{label, value}[]for select/enum-style filters
Import:
import {
filterRegistry,
type FilterOperator,
type FilterDefinition,
type FilterRegistry,
getFilterOptions,
} from "@/packages/resource-framework/registries/filter-registry";
```typescript
### Filter operators
Common operators supported by the framework:
| Operator | Meaning | Example value |
| ------------- | ---------------------------- | ------------------------------- |
| `eq` | equals | `"paid"`, `42`, `true` |
| `neq` | not equals | `"draft"` |
| `gt` | greater than | `100`, `"2024-01-01"` |
| `gte` | greater than or equal | `0` |
| `lt` | less than | `10` |
| `lte` | less than or equal | `5` |
| `contains` | substring contains (strings) | `"inv-"` |
| `starts_with` | prefix match (strings) | `"INV"` |
| `ends_with` | suffix match (strings) | `".pdf"` |
| `in` | value in list | `["paid","pending"]`, `[1,2,3]` |
| `not_in` | value not in list | `["draft"]` |
| `is_null` | value is null | — |
| `is_not_null` | value is not null | — |
> Backends should translate these into the appropriate SQL/DSL. UIs should constrain operator choices to those allowed by the column datatype via `filterRegistry`.
### Supported datatypes → allowed operators
| Datatype | Allowed operators |
| --------- | --------------------------------------------------------------------------------------------- |
| `string` | `eq`, `neq`, `contains`, `starts_with`, `ends_with`, `in`, `not_in`, `is_null`, `is_not_null` |
| `number` | `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `not_in`, `is_null`, `is_not_null` |
| `boolean` | `eq`, `neq`, `is_null`, `is_not_null` |
| `date` | `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `is_null`, `is_not_null` |
| `json` | `is_null`, `is_not_null` |
| `other` | `eq`, `neq`, `is_null`, `is_not_null` |
Use this mapping to drive operator pickers in filter UIs and to validate payloads before sending to the server.
### Types
```typescript
export type FilterOperator =
| "eq"
| "neq"
| "gt"
| "gte"
| "lt"
| "lte"
| "contains"
| "starts_with"
| "ends_with"
| "in"
| "not_in"
| "is_null"
| "is_not_null";
export type FilterDefinition = {
operators: FilterOperator[];
};
export type FilterRegistry = Record<
"string" | "number" | "boolean" | "date" | "json" | "other",
FilterDefinition
>;
```typescript
### Getting select/enum options for filters
For select-like filters (e.g., status), use `getFilterOptions(resourceName, columnName)`:
```typescript
const options = getFilterOptions("invoices", "status");
// -> [
// { label: "Draft", value: "draft" },
// { label: "Pending", value: "pending" },
// { label: "Paid", value: "paid" },
// { label: "Overdue", value: "overdue" },
// { label: "Cancelled", value: "cancelled" },
// ]
```typescript
Extend options by adding entries in the internal `FILTER_OPTIONS` map inside `filter-registry.tsx`:
```typescript
// Inside packages/resource-framework/registries/filter-registry.tsx
const FILTER_OPTIONS = {
invoices: {
status: [
{ label: "Draft", value: "draft" },
// ...
],
},
orders: {
status: [
{ label: "Open", value: "open" },
{ label: "Closed", value: "closed" },
],
},
} as const;
```typescript
### Using the registry to constrain UI
```typescript
function getAllowedOperatorsForDatatype(datatype: keyof typeof filterRegistry) {
return filterRegistry[datatype].operators;
}
// Example: for a string column
const allowed = getAllowedOperatorsForDatatype("string");
// -> ["eq","neq","contains","starts_with","ends_with","in","not_in","is_null","is_not_null"]
```typescript
Use `allowed` to populate operator dropdowns. For multi-value operators (`in`, `not_in`), render an input that accepts an array of values. For `is_null`/`is_not_null`, render without a value input.
### Notes
- Keep operators backend-agnostic; translate at the API layer.
- Add new datatypes by extending `FilterRegistry` and `filterRegistry` with a clear minimal operator set.
- For enums, prefer `getFilterOptions` to keep UI options consistent across the app.