Update dart client to new filter syntax.

This commit is contained in:
Sebastian Jeltsch
2025-05-17 16:49:54 +02:00
parent 932abd720e
commit aa700c0ba6
2 changed files with 92 additions and 14 deletions

View File

@@ -282,6 +282,58 @@ class ErrorEvent extends Event {
String toString() => 'ErrorEvent(${_error})';
}
enum CompareOp {
equal,
notEqual,
lessThan,
lessThanEqual,
greaterThan,
greaterThanEqual,
like,
regexp,
}
String _opToSring(CompareOp op) {
return switch (op) {
CompareOp.equal => '\$eq',
CompareOp.notEqual => '\$ne',
CompareOp.lessThan => '\$lt',
CompareOp.lessThanEqual => '\$lte',
CompareOp.greaterThan => '\$gt',
CompareOp.greaterThanEqual => '\$gte',
CompareOp.like => '\$like',
CompareOp.regexp => '\$re',
};
}
sealed class FilterBase {
const FilterBase();
}
class Filter extends FilterBase {
final String column;
final CompareOp? op;
final String value;
const Filter({
required this.column,
required this.value,
this.op,
});
}
class And extends FilterBase {
final List<FilterBase> filters;
const And(this.filters);
}
class Or extends FilterBase {
final List<FilterBase> filters;
const Or(this.filters);
}
class RecordApi {
static const String _recordApi = 'api/records/v1';
@@ -293,7 +345,7 @@ class RecordApi {
Future<ListResponse> list({
Pagination? pagination,
List<String>? order,
List<String>? filters,
List<FilterBase>? filters,
bool? count,
List<String>? expand,
}) async {
@@ -313,15 +365,30 @@ class RecordApi {
if (count ?? false) params['count'] = 'true';
if (expand != null) params['expand'] = expand.join(',');
if (filters != null) {
for (final filter in filters) {
final (nameOp, value) = splitOnce(filter, '=');
if (value == null) {
throw Exception(
'Filter "${filter}" does not match: "name[op]=value"');
}
params[nameOp] = value;
}
void traverseFilters(String path, FilterBase filter) {
final _ = switch (filter) {
Filter(column: final c, op: final op, value: final v) => () {
if (op != null) {
params['${path}[${c}][${_opToSring(op)}]'] = v;
} else {
params['${path}[${c}]'] = v;
}
}(),
And(filters: final filters) => () {
filters.asMap().forEach((index, filter) {
traverseFilters('${path}[\$and][${index}]', filter);
});
}(),
Or(filters: final filters) => () {
filters.asMap().forEach((index, filter) {
traverseFilters('${path}[\$or][${index}]', filter);
});
}(),
};
}
for (final filter in filters ?? []) {
traverseFilters('filter', filter);
}
final response = await _client.fetch(

View File

@@ -272,7 +272,7 @@ Future<void> main() async {
{
final response = await api.list(
filters: ['text_not_null=${messages[0]}'],
filters: [Filter(column: 'text_not_null', value: messages[0])],
);
expect(response.records.length, 1);
expect(response.records[0]['text_not_null'], messages[0]);
@@ -281,7 +281,12 @@ Future<void> main() async {
{
final recordsAsc = (await api.list(
order: ['+text_not_null'],
filters: ['text_not_null[like]=% =?&${now}'],
filters: [
Filter(
column: 'text_not_null',
op: CompareOp.like,
value: '% =?&${now}')
],
))
.records;
expect(recordsAsc.map((el) => el['text_not_null']),
@@ -289,7 +294,10 @@ Future<void> main() async {
final recordsDesc = (await api.list(
order: ['-text_not_null'],
filters: ['text_not_null[like]=%${now}'],
filters: [
Filter(
column: 'text_not_null', op: CompareOp.like, value: '%${now}')
],
))
.records;
expect(recordsDesc.map((el) => el['text_not_null']).toList().reversed,
@@ -300,7 +308,10 @@ Future<void> main() async {
final response = (await api.list(
pagination: Pagination(limit: 1),
order: ['-text_not_null'],
filters: ['text_not_null[like]=%${now}'],
filters: [
Filter(
column: 'text_not_null', op: CompareOp.like, value: '%${now}')
],
count: true,
));