Refine provider reference
This page lists what each provider in @taruvi/refine-providers 1.3.7
supports, and the request each Refine call sends. Every provider takes the same
@taruvi/sdk Client. For setup, start with Refine integration.
| Provider | Serves |
|---|---|
dataProvider(client) | Data table records and edges |
storageDataProvider(client) | Objects in a storage bucket |
appDataProvider(client) | App roles, settings, and secrets; function and saved-query runs |
userDataProvider(client) | Users, their roles, and their apps |
authProvider(client) | Hosted sign-in, sign-out, the session, and the current user |
accessControlProvider(client, options?) | useCan, <CanAccess>, and button visibility |
functionsDataProvider and analyticsDataProvider are deprecated. Use
appDataProvider with useCustom instead.
dataProvider#
The resource name is the table name; set meta.tableName when they differ.
Request paths below are relative to /api/apps/APP_SLUG/datatables/TABLE/.
Read records#
useList<Task>({
resource: 'tasks',
filters: [{field: 'done', operator: 'eq', value: false}],
sorters: [{field: 'title', order: 'asc'}],
pagination: {currentPage: 1, pageSize: 20},
});
getList—GET …/data/with Refine's filters, sorters, and pagination.getOne—GET …/data/ID/.getMany—GET …/data/?id__in=…. Setmeta.idColumnNamewhen the primary key isn'tid.
Create records#
const {mutate: create} = useCreate<Task>();
create({resource: 'tasks', values: {title: 'Ship docs', done: false}});
create—POST …/data/, orPOST …/data/upsert/withmeta.upsert. Returns the created record.createMany— OnePOSTper record. Returns the created records.
Update records#
const {mutate: update} = useUpdate<Task>();
update({resource: 'tasks', id: 'TASK_ID', values: {done: true}});
update—PATCH …/data/ID/.updateMany—PATCH …/data/, with each ID merged into the values.
Delete records#
const {mutate: remove} = useDelete<Task>();
remove({resource: 'tasks', id: 'TASK_ID'});
deleteOne—DELETE …/data/ID/.deleteMany—DELETE …/data/?ids=, or every record that matchesmeta.filterswithmeta.deleteByFilter.
deleteMany with meta.deleteByFilter removes every record that matches
meta.filters, not only the IDs you pass. Read with the same filters first.
Custom requests#
custom sends a request to /api/apps/APP_SLUG/datatables/URL, where url is
relative to datatables/.
Meta options#
useList({
resource: 'tasks',
meta: {populate: ['assignee'], search: 'launch', allowedActions: ['update', 'delete']},
});
tableName— The table to use instead of the resource name. Applies to every method.populate— Relationships to expand, as an array, a comma-separated string, or'*'. ForgetList,getOne, andgetMany.select— The columns to return, forgetList.search— Full-text search, forgetList.aggregate,groupBy,having— Aggregates such as['count(*)'], the grouping fields, and a filter on the groups, forgetList.allowedActions—['update', 'delete'], forgetList. Each row gains_allowed_actions.idColumnName— The primary key column, forgetManyandupdateMany. Defaults toid.upsert— Inserts or updates on the primary key, forcreate.deleteByFilterwithfilters— Deletes every record that matchesmeta.filters, fordeleteMany.format,include,depth,relationship_type— Graph queries. A graphgetListignores filters, sorters, and pagination. On writes, the operation targets the edge table.
meta.headers is declared on the TaruviMeta type but not applied to
requests.
Filter operators#
Refine's operators map to TaruviBase filters:
| Refine operator | Sent as |
|---|---|
eq | field=value |
ne, lt, gt, lte, gte | field__ne, field__lt, … |
contains, ncontains, startswith, endswith, and their n… forms | Case-insensitive matches |
containss, startswiths, endswiths, and their n… forms | Case-sensitive matches |
icontains, istartswith, iendswith, and their n… forms | The same as contains, startswith, and endswith |
in, nin, ina, nina, between, nbetween | Comma-separated values |
null, nnull | Null checks |
Array and range operators, like, ilike, search | Passed through; wrap the filters in toRefineFilters() to satisfy Refine's types |
A filter whose value is undefined, or null with an operator other than
null, is skipped. An operator not in this table, such as Refine's eqs,
fails the request, at any depth of and/or groups. With
meta.deleteByFilter, a filter without a value fails the request instead of
being skipped. or and and groups are sent as a filter tree. See
Advanced filters.
storageDataProvider#
The resource name is the bucket slug; set meta.bucketName when they differ.
Operations that take an id expect the object path: file_path on a
listed object, or path on a browsed file. A listed object's own id is a
number and doesn't work here. Request paths below are relative to
/api/apps/APP_SLUG/storage/buckets/BUCKET/objects/.
List and browse objects#
useList({resource: 'documents', meta: {mode: 'browse', prefix: 'uploads/'}});
getList— Lists objects withGET …/objects/, filtered and sorted by Refine's filters and sorters. Every condition must match;orgroups fail the request.getListwithmeta: {mode: 'browse', prefix}— Lists the folders and files directly underprefixinstead.
getMany isn't supported.
Download a file or read its details#
useOne({resource: 'documents', id: 'reports/q3.pdf', meta: {metadata: true}});
getOne downloads the object as a Blob. With meta.metadata: true, it
returns the object's details instead.
Upload files#
const {mutate: upload} = useCreate<StorageObject, HttpError, StorageUploadVariables>();
upload({resource: 'documents', values: {files: [file], paths: ['uploads/q3.pdf']}});
create uploads values.files, with optional paths and metadatas matched
by index. It returns the first uploaded object.
Update metadata#
update replaces the object's metadata, with PATCH …/objects/PATH/.
Visibility follows the bucket and can't be changed per object.
Delete objects#
deleteOne and deleteMany delete objects by path, with
POST …/objects/batch-delete/. Objects TaruviBase skips, because they're
missing or a policy denies the delete, make the call fail with
NotFoundError, ForbiddenError, or TaruviError.
Get an Office link#
useCustom({
url: 'documents',
method: 'get',
dataProviderName: 'storage',
meta: {kind: 'editAccess', filePath: 'contracts/msa.docx'},
});
custom with meta.kind set to 'viewAccess' or 'editAccess' returns a
SharePoint link, {url, mode}, for an Office file. url is the bucket. Other
custom calls send a request to …/storage/buckets/URL.
appDataProvider#
Register it as the app provider, and pass dataProviderName: 'app' to its
hooks.
Read roles, settings, and secrets#
useList({
resource: 'secrets',
dataProviderName: 'app',
meta: {keys: ['app_config', 'feature_flags']},
});
useListonroles— The app's roles.useListonsecrets— The secrets named inmeta.keys.meta.appandmeta.includeMetadataare optional.useOneonsettings— The app's settings.useOneonsecrets— The secret whose key isid.meta.appandmeta.tagsare optional.
Other operations throw.
Run a function#
useCustom runs its request when the component mounts. To run a function from
a button, use useCustomMutation, whose values become the function's
params:
import {useCustomMutation} from '@refinedev/core';
export function SendReportButton() {
const {mutate, mutation} = useCustomMutation();
return (
<button
type="button"
disabled={mutation.isPending}
onClick={() =>
mutate({
url: 'send-report',
method: 'post',
values: {month: '2026-09'},
dataProviderName: 'app',
meta: {kind: 'function'},
})
}
>
Send report
</button>
);
}
url is the function's slug, and the call returns the function's result.
Without meta.async, the function's own mode applies. meta.async: true
queues the run and returns the invocation, whose celery_task_id identifies
it.
Run a saved query#
useCustom({
url: 'revenue-by-month',
method: 'post',
dataProviderName: 'app',
config: {payload: {year: 2026}},
meta: {kind: 'analytics'},
});
url is the saved query's slug, and payload holds its parameters. A run
that fails rejects with the SDK's error, with statusCode 400 and code
BAD_REQUEST.
userDataProvider#
Register it as the user provider. Any signed-in user can list and read
users. Creating, updating, and deleting them needs organization access or a
Super Admin app role in one of the site's apps; anyone else's mutation fails
with ForbiddenError.
List users#
useList({
resource: 'users',
dataProviderName: 'user',
filters: [{field: 'search', operator: 'eq', value: 'ada'}],
pagination: {currentPage: 1, pageSize: 20},
});
Refine filters on search, is_active, is_superuser, is_deleted, and
roles apply; other filter fields are ignored. Pagination and the first sorter
apply.
Read and manage a user#
useOneonusers— The user whose username isid.id: 'me'returns the signed-in user.useCreate,useUpdate,useDeleteonusers— Create, update, or soft-delete a user.idis the username, not the numericidon list rows.
A user's roles and apps#
useList on roles or apps returns the roles or apps of the user in
meta.username.
authProvider#
login({callbackUrl?})— Redirects to hosted sign-in unless a session is stored.register({callbackUrl?})— Redirects to hosted sign-up.logout({callbackUrl?})— Clears the stored session, redirects to TaruviBase sign-out, and returnsredirectTo: callbackUrlor'/login'. If TaruviBase doesn't accept the return address, the user confirms sign-out on TaruviBase's page.check()— Validates the stored session with TaruviBase. When it isn't valid, returnsredirectTo: '/login', which<Authenticated>follows when it has nofallback.onError(error)— On401, redirects to sign-in. Other errors, including403, keep the session.getIdentity()— The signed-in user, fromGET /api/users/me/.getPermissions()— The signed-in user'sroles,permissions,groups,is_staff, andis_superuser.
accessControlProvider#
accessControlProvider(client, {
entityType: (resource) => `datatable:${resource}`,
batchDelayMs: 50,
buttons: {enableAccessControl: true, hideIfUnauthorized: true},
});
Options
entityType— Maps a resource name to a policy kind, for checks that don't set one.batchDelayMs— How long to collectuseCanchecks before sending them as one request. Defaults to50.buttons.enableAccessControl— Whether Refine's action buttons check access. Defaults totrue.buttons.hideIfUnauthorized— Hide, rather than disable, buttons the user can't use. Defaults totrue.
Results are cached for 5 minutes. A check without a signed-in user returns
can: false.
How a check is sent
- Kind —
params.entityType, then the resource'smeta.entityType, then theentityTypeoption, then the resource name. Kinds look likedatatable:TABLEorstorage:BUCKET. - Action — Refine's
listandshowbecomeread,editbecomesupdate, andclonebecomescreate; others are sent unchanged. - Record ID —
params.id, or*when there is none. - Attributes —
params, without Refine'sresourceobject andentityType.
See Show only what users may do for the full kind table.
Utilities#
The package also exports the helpers the providers use, for custom providers
or useCustom calls: convertRefineFilters, convertRefineSorters,
convertRefinePagination, buildRefineQueryParams,
convertRefineFiltersToBackendTree, toRefineFilters, and the
REFINE_OPERATOR_MAP table above.