@taruvi/refine-providers 1.3.4-beta.0 → 1.3.4-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -108,7 +108,12 @@ mutate({ resource: "posts", id: 1 });
108
108
 
109
109
  ### Filtering
110
110
 
111
- List requests send **JSON `filters`** (`Database.filters(tree)` in the SDK): `convertRefineFiltersToBackendTree` maps Refine `CrudFilter[]` to the platform tree (nested `and` / `or` preserved). Bracket query keys from `convertRefineFilters` remain for helpers / Storage flatten mode.
111
+ List `getList` filters use an explicit **`TaruviListFilters`** shape:
112
+
113
+ - **`FlatFilterLeaf[]`** (array of `{ field, operator, value }`) → top-level **`field__op`** query params via `Database.filters(field, op, value)` (including FK traversal like `department_id.name`).
114
+ - **`LogicalCrudFilter`** (object `{ operator: "and" | "or", value: [...] }`) → JSON **`filters`** tree via `Database.filters(tree)`.
115
+
116
+ Legacy Refine **`CrudFilter[]`** is still accepted: all field leaves → flat array; a single root `and`/`or` object → logical object; mixed lists fall back to the JSON tree. Bracket keys from `convertRefineFilters` remain for helpers / Storage flatten mode.
112
117
 
113
118
  Full support for Refine filter operators:
114
119
 
@@ -126,15 +131,7 @@ const { data } = useList({
126
131
 
127
132
  **Refine → backend operator mapping (important):**
128
133
 
129
- | Refine operator | Backend / JSON leaf operator | Meaning on platform |
130
- |-----------------|------------------------------|------------------------|
131
- | `containss` | `contains` | Case-insensitive substring (ILIKE-style) |
132
- | `contains` | `containss` | Case-sensitive substring |
133
- | `startswith`, `endswith` | same name | Case-insensitive |
134
- | `startswiths`, `endswiths` | same name | Case-sensitive |
135
- | `icontains` / `nicontains` | pass-through | Aliases; platform normalizes `icontains` → `contains` |
136
-
137
- Other operators (`eq`, `in`, `between`, array/range ops, etc.) follow `REFINE_OPERATOR_MAP` in [`src/utils.ts`](src/utils.ts).
134
+ Wire suffixes match the platform (`contains` = case-insensitive, `containss` = case-sensitive). Refine aliases map to the same tokens, e.g. `icontains` `contains`. See `REFINE_OPERATOR_MAP` in [`src/utils.ts`](src/utils.ts).
138
135
 
139
136
  **More operators:**
140
137
 
@@ -143,8 +140,8 @@ Other operators (`eq`, `in`, `between`, array/range ops, etc.) follow `REFINE_OP
143
140
  | `eq` | Equal | `status = "active"` |
144
141
  | `ne` | Not equal | `status != "deleted"` |
145
142
  | `lt`, `gt`, `lte`, `gte` | Comparison | `age >= 18` |
146
- | `containss`, `ncontainss` | Case-insensitive contains / not | Prefer for search UX |
147
- | `contains`, `ncontains` | Case-sensitive contains / not | |
143
+ | `contains`, `ncontains` | Case-insensitive contains / not | FK traversal, search UX |
144
+ | `containss`, `ncontainss` | Case-sensitive contains / not | |
148
145
  | `startswith`, `endswith` | Case-insensitive prefix/suffix | |
149
146
  | `startswiths`, `endswiths` | Case-sensitive prefix/suffix | |
150
147
  | `in`, `nin`, `ina`, `nina` | Array membership | |
package/dist/index.cjs CHANGED
@@ -11,7 +11,7 @@ var DataLoader__default = /*#__PURE__*/_interopDefault(DataLoader);
11
11
 
12
12
  // package.json
13
13
  var package_default = {
14
- version: "1.3.4-beta.0"};
14
+ version: "1.3.4-beta.2"};
15
15
 
16
16
  // src/utils.ts
17
17
  var REFINE_OPERATOR_MAP = {
@@ -24,23 +24,26 @@ var REFINE_OPERATOR_MAP = {
24
24
  gt: "gt",
25
25
  lte: "lte",
26
26
  gte: "gte",
27
- // String operators mapped to backend-safe case-sensitive LIKE variants.
28
- contains: "containss",
29
- ncontains: "ncontainss",
27
+ // String matching Taruvi wire suffix matches platform filter_translator.
28
+ contains: "contains",
29
+ ncontains: "ncontains",
30
30
  containss: "containss",
31
31
  ncontainss: "ncontainss",
32
- // String operators mapped to backend-safe case-sensitive prefix/suffix LIKE.
33
- startswith: "startswiths",
34
- nstartswith: "nstartswiths",
35
- endswith: "endswiths",
36
- nendswith: "nendswiths",
32
+ startswith: "startswith",
33
+ nstartswith: "nstartswith",
34
+ endswith: "endswith",
35
+ nendswith: "nendswith",
37
36
  startswiths: "startswiths",
38
37
  nstartswiths: "nstartswiths",
39
38
  endswiths: "endswiths",
40
39
  nendswiths: "nendswiths",
41
- // Aliases mapped to backend-safe case-sensitive LIKE variants.
42
- icontains: "containss",
43
- nicontains: "ncontainss",
40
+ // Refine aliases platform insensitive tokens
41
+ icontains: "contains",
42
+ nicontains: "ncontains",
43
+ istartswith: "startswith",
44
+ nistartswith: "nstartswith",
45
+ iendswith: "endswith",
46
+ niendswith: "nendswith",
44
47
  // Array / membership
45
48
  in: "in",
46
49
  nin: "nin",
@@ -101,6 +104,66 @@ function isLogicalFilter(filter) {
101
104
  function isFieldFilter(filter) {
102
105
  return typeof filter === "object" && filter !== null && "field" in filter && "operator" in filter && typeof filter.field === "string" && typeof filter.operator === "string";
103
106
  }
107
+ function isFlatFilterList(filters) {
108
+ if (!Array.isArray(filters)) return false;
109
+ return filters.every((f) => {
110
+ if (!isFieldFilter(f)) return false;
111
+ const leaf = f;
112
+ if (leaf.value === void 0 || leaf.value === null && leaf.operator !== "null") {
113
+ return false;
114
+ }
115
+ if (REFINE_OPERATOR_MAP[leaf.operator] === void 0) {
116
+ return false;
117
+ }
118
+ return true;
119
+ });
120
+ }
121
+ function isLogicalCrudFilter(filters) {
122
+ return typeof filters === "object" && filters !== null && !Array.isArray(filters) && isLogicalFilter(filters);
123
+ }
124
+ function normalizeTaruviListFilters(filters) {
125
+ if (filters === void 0 || filters === null) return void 0;
126
+ if (isLogicalCrudFilter(filters)) return filters;
127
+ if (isFlatFilterList(filters)) return filters;
128
+ if (!Array.isArray(filters) || filters.length === 0) return void 0;
129
+ if (filters.length === 1 && isLogicalFilter(filters[0])) {
130
+ return filters[0];
131
+ }
132
+ if (filters.every(isFieldFilter)) {
133
+ return filters;
134
+ }
135
+ return void 0;
136
+ }
137
+ function collectFlatLeaves(filters) {
138
+ if (!filters?.length) return [];
139
+ const leaves = [];
140
+ const walk = (group) => {
141
+ for (const filter of group) {
142
+ if (isLogicalFilter(filter)) {
143
+ if (filter.operator === "or") return false;
144
+ if (!walk(filter.value)) return false;
145
+ continue;
146
+ }
147
+ if (!isFieldFilter(filter)) return false;
148
+ const leaf = filter;
149
+ if (leaf.value === void 0 || leaf.value === null && leaf.operator !== "null") {
150
+ continue;
151
+ }
152
+ if (REFINE_OPERATOR_MAP[leaf.operator] === void 0) {
153
+ console.warn(`Unknown Refine operator: ${leaf.operator}`);
154
+ return false;
155
+ }
156
+ leaves.push({
157
+ field: leaf.field,
158
+ operator: leaf.operator,
159
+ value: leaf.value
160
+ });
161
+ }
162
+ return true;
163
+ };
164
+ if (!walk(filters)) return null;
165
+ return leaves;
166
+ }
104
167
  function refineOperatorToBackendKey(operator) {
105
168
  const suffix = REFINE_OPERATOR_MAP[operator];
106
169
  if (suffix === void 0) return operator;
@@ -194,6 +257,18 @@ function convertRefineFiltersToBackendTree(filters) {
194
257
  }
195
258
  return [{ operator: "and", value: nodes }];
196
259
  }
260
+ function convertLogicalFilterToBackendTree(filter) {
261
+ const node = crudFilterToBackendNodeOrNull(filter);
262
+ if (!node || !isLogicalBackendNode(node)) return null;
263
+ return [node];
264
+ }
265
+ function encodeFlatFilterListToParams(leaves) {
266
+ const params = {};
267
+ for (const leaf of leaves) {
268
+ encodeLeafFlat(leaf.field, leaf.operator, leaf.value, params);
269
+ }
270
+ return params;
271
+ }
197
272
  function convertRefineFiltersFlattened(filters) {
198
273
  if (!filters || filters.length === 0) return {};
199
274
  const params = {};
@@ -336,11 +411,38 @@ function applyAggregations(query, meta) {
336
411
  }
337
412
  return result;
338
413
  }
414
+ function applyFlatFilterList(query, leaves) {
415
+ let result = query;
416
+ for (const { field, operator, value } of leaves) {
417
+ const backendOp = refineOperatorToBackendKey(operator);
418
+ const formatted = formatRefineLeafValue(operator, value);
419
+ result = result.filters(
420
+ field,
421
+ backendOp,
422
+ formatted
423
+ );
424
+ }
425
+ return result;
426
+ }
339
427
  function applyFilters(query, filters) {
340
- if (!filters || filters.length === 0) return query;
341
- const tree = convertRefineFiltersToBackendTree(filters);
342
- if (!tree) return query;
343
- return query.filters(tree);
428
+ const normalized = normalizeTaruviListFilters(filters);
429
+ if (normalized === void 0) {
430
+ if (Array.isArray(filters) && filters.length > 0) {
431
+ const tree = convertRefineFiltersToBackendTree(filters);
432
+ if (tree) return query.filters(tree);
433
+ }
434
+ return query;
435
+ }
436
+ if (isFlatFilterList(normalized)) {
437
+ if (normalized.length === 0) return query;
438
+ return applyFlatFilterList(query, normalized);
439
+ }
440
+ if (isLogicalCrudFilter(normalized)) {
441
+ const tree = convertLogicalFilterToBackendTree(normalized);
442
+ if (!tree) return query;
443
+ return query.filters(tree);
444
+ }
445
+ return query;
344
446
  }
345
447
  function applySorters(query, sorters) {
346
448
  const ordering = convertRefineSorters(sorters);
@@ -362,6 +464,16 @@ function applyAllowedActions(query, meta) {
362
464
  if (!meta?.allowedActions?.length) return query;
363
465
  return query.allowedActions(meta.allowedActions);
364
466
  }
467
+ function applySearchAndFields(query, meta) {
468
+ if (!meta) return query;
469
+ let result = query;
470
+ const search = meta.search?.trim();
471
+ if (search) result = result.search(search);
472
+ const select = meta.select;
473
+ const fields = typeof select === "string" ? select.trim() : Array.isArray(select) ? select.map(String).join(",") : "";
474
+ if (fields) result = result.fields(fields);
475
+ return result;
476
+ }
365
477
  function isGraphQuery(meta) {
366
478
  return !!(meta?.format || meta?.graph_types || meta?.include || meta?.depth);
367
479
  }
@@ -399,6 +511,7 @@ function dataProvider(client) {
399
511
  query = applyPagination(query, pagination);
400
512
  query = applyPopulate(query, taruviMeta);
401
513
  query = applyAggregations(query, taruviMeta);
514
+ query = applySearchAndFields(query, taruviMeta);
402
515
  query = applyAllowedActions(query, taruviMeta);
403
516
  const response = await query.execute();
404
517
  return { data: response.data, total: response.total };
@@ -1249,15 +1362,21 @@ exports.applyRefineQueryParamsToDatabase = applyRefineQueryParamsToDatabase;
1249
1362
  exports.authProvider = authProvider;
1250
1363
  exports.buildQueryString = buildQueryString;
1251
1364
  exports.buildRefineQueryParams = buildRefineQueryParams;
1365
+ exports.collectFlatLeaves = collectFlatLeaves;
1366
+ exports.convertLogicalFilterToBackendTree = convertLogicalFilterToBackendTree;
1252
1367
  exports.convertRefineFilters = convertRefineFilters;
1253
1368
  exports.convertRefineFiltersToBackendTree = convertRefineFiltersToBackendTree;
1254
1369
  exports.convertRefinePagination = convertRefinePagination;
1255
1370
  exports.convertRefineSorters = convertRefineSorters;
1256
1371
  exports.dataProvider = dataProvider;
1257
1372
  exports.encodeCrudFilterBracket = encodeCrudFilterBracket;
1373
+ exports.encodeFlatFilterListToParams = encodeFlatFilterListToParams;
1258
1374
  exports.formatRefineLeafValue = formatRefineLeafValue;
1259
1375
  exports.functionsDataProvider = functionsDataProvider;
1260
1376
  exports.handleError = handleError;
1377
+ exports.isFlatFilterList = isFlatFilterList;
1378
+ exports.isLogicalCrudFilter = isLogicalCrudFilter;
1379
+ exports.normalizeTaruviListFilters = normalizeTaruviListFilters;
1261
1380
  exports.refineOperatorToBackendKey = refineOperatorToBackendKey;
1262
1381
  exports.storageDataProvider = storageDataProvider;
1263
1382
  exports.userDataProvider = userDataProvider;