Skip to content
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Add this to your package's `pubspec.yaml` file:

```yml
dependencies:
appwrite: ^18.0.0
appwrite: ^19.0.0
```

You can install packages from the command line:
Expand Down
6 changes: 5 additions & 1 deletion docs/examples/account/update-prefs.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@ Client client = Client()
Account account = Account(client);

User result = await account.updatePrefs(
prefs: {},
prefs: {
"language": "en",
"timezone": "UTC",
"darkTheme": true
},
);
8 changes: 7 additions & 1 deletion docs/examples/databases/create-document.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ Document result = await databases.createDocument(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documentId: '<DOCUMENT_ID>',
data: {},
data: {
"username": "walter.obrien",
"email": "[email protected]",
"fullName": "Walter O'Brien",
"age": 30,
"isAdmin": false
},
permissions: ["read("any")"], // optional
);
Comment on lines 20 to 21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix invalid permissions syntax in Dart snippet.

Use typed builders to avoid quoting issues.

Apply:

-    permissions: ["read("any")"], // optional
+    permissions: [Permission.read(Role.any())], // optional
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions: ["read("any")"], // optional
);
permissions: [Permission.read(Role.any())], // optional
);
🤖 Prompt for AI Agents
In docs/examples/databases/create-document.md around lines 20 to 21, the Dart
snippet uses invalid permissions syntax permissions: ["read("any")"] — replace
the quoted raw string with the Dart typed builder form (use the appropriate
Permission/read builder function or constructor with a plain 'any' argument) so
permissions are constructed as typed objects instead of strings; update the
example to call the Permission builder API consistently with the surrounding
snippet and remove the nested quotes/parentheses error.

8 changes: 7 additions & 1 deletion docs/examples/tablesdb/create-row.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ Row result = await tablesDB.createRow(
databaseId: '<DATABASE_ID>',
tableId: '<TABLE_ID>',
rowId: '<ROW_ID>',
data: {},
data: {
"username": "walter.obrien",
"email": "[email protected]",
"fullName": "Walter O'Brien",
"age": 30,
"isAdmin": false
},
permissions: ["read("any")"], // optional
);
Comment on lines 20 to 21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix invalid permissions syntax in Dart snippet.

The current string quoting will not compile. Use the SDK helpers.

Apply:

-    permissions: ["read("any")"], // optional
+    permissions: [Permission.read(Role.any())], // optional
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions: ["read("any")"], // optional
);
permissions: [Permission.read(Role.any())], // optional
);
🤖 Prompt for AI Agents
In docs/examples/tablesdb/create-row.md around lines 20-21, the Dart permissions
string uses invalid nested quotes and won't compile; replace the string with the
SDK permission helper (use the Permission.read helper and pass "any" as the
argument) instead of the literal "read("any")" string, and ensure the Dart
snippet imports and uses the SDK Permission helper correctly so the permissions
array contains the helper call rather than an invalid quoted string.

2 changes: 1 addition & 1 deletion lib/appwrite.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Appwrite Flutter SDK
///
/// This SDK is compatible with Appwrite server version 1.8.x.
/// This SDK is compatible with Appwrite server version 1.8.x.
/// For older versions, please check
/// [previous releases](https://github.com/appwrite/sdk-for-flutter/releases).
library appwrite;
Expand Down
2 changes: 1 addition & 1 deletion lib/client_browser.dart
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export 'src/client_browser.dart';
export 'src/client_browser.dart';
2 changes: 1 addition & 1 deletion lib/client_io.dart
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export 'src/client_io.dart';
export 'src/client_io.dart';
86 changes: 72 additions & 14 deletions lib/query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ class Query {
Query._(this.method, [this.attribute = null, this.values = null]);

Map<String, dynamic> toJson() {
final map = <String, dynamic>{'method': method};

if (attribute != null) {
map['attribute'] = attribute;
final result = <String, dynamic>{};

result['method'] = method;

if(attribute != null) {
result['attribute'] = attribute;
}

if (values != null) {
map['values'] = values is List ? values : [values];
if(values != null) {
result['values'] = values is List ? values : [values];
}

return map;
return result;
}

@override
String toString() => jsonEncode(toJson());

/// Filter resources where [attribute] is equal to [value].
///
///
/// [value] can be a single value or a list. If a list is used
/// the query will return resources where [attribute] is equal
/// to any of the values in the list.
Expand All @@ -35,7 +37,7 @@ class Query {

/// Filter resources where [attribute] is not equal to [value].
static String notEqual(String attribute, dynamic value) =>
Query._('notEqual', attribute, [value]).toString();
Query._('notEqual', attribute, value).toString();

/// Filter resources where [attribute] is less than [value].
static String lessThan(String attribute, dynamic value) =>
Expand Down Expand Up @@ -111,6 +113,10 @@ class Query {
static String createdAfter(String value) =>
Query._('createdAfter', null, value).toString();

/// Filter resources where document was created between [start] and [end] (inclusive).
static String createdBetween(String start, String end) =>
Query._('createdBetween', null, [start, end]).toString();

Comment on lines +116 to +119
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Fix createdBetween/updatedBetween to use supported operators.

The server doesn’t expose “createdBetween”/“updatedBetween” operators. Use between() on $createdAt/$updatedAt instead to keep inclusive semantics documented in Queries. (appwrite.io)

Apply:

-  /// Filter resources where document was created between [start] and [end] (inclusive).
-  static String createdBetween(String start, String end) =>
-      Query._('createdBetween', null, [start, end]).toString();
+  /// Filter resources where document was created between [start] and [end] (inclusive).
+  static String createdBetween(String start, String end) =>
+      between(r'$createdAt', start, end);
@@
-  /// Filter resources where document was updated between [start] and [end] (inclusive).
-  static String updatedBetween(String start, String end) =>
-      Query._('updatedBetween', null, [start, end]).toString();
+  /// Filter resources where document was updated between [start] and [end] (inclusive).
+  static String updatedBetween(String start, String end) =>
+      between(r'$updatedAt', start, end);

If tests assert the JSON method name equals "createdBetween"/"updatedBetween", update them to expect method "between" and attribute "$createdAt"/"$updatedAt", respectively.

Also applies to: 126-129


🏁 Script executed:

#!/bin/bash
# Search for existing between() method and createdBetween/updatedBetween in lib/query.dart
rg -nP --type=dart 'static String between' -n lib/query.dart || true
rg -nP --type=dart 'between\(' -n lib/query.dart || true

# Locate createdBetween and updatedBetween definitions
rg -nP --type=dart 'createdBetween' -n lib/query.dart || true
rg -nP --type=dart 'updatedBetween' -n lib/query.dart || true

# Inspect Query._ constructor to see supported operators
rg -nP --type=dart 'class Query\s*{' -n lib/query.dart -A5 -B0 || true
rg -nP --type=dart 'factory Query\._' -n lib/query.dart -A3 -B3 || true

Length of output: 945


Use between operator for createdBetween/updatedBetween filters

  • lib/query.dart@115–117: replace
    Query._('createdBetween', null, [start, end]).toString();
    with
    between(r'$createdAt', start, end);
  • lib/query.dart@127–129: replace
    Query._('updatedBetween', null, [start, end]).toString();
    with
    between(r'$updatedAt', start, end);
  • Update any tests that assert method names "createdBetween"/"updatedBetween" to expect "between" with attributes "$createdAt"/"$updatedAt".
🤖 Prompt for AI Agents
In lib/query.dart around lines 114–117 and 127–129, the createdBetween and
updatedBetween helpers currently construct Query._ with operator names
"createdBetween"/"updatedBetween"; change them to call between(r'$createdAt',
start, end) and between(r'$updatedAt', start, end) respectively so the operator
used is "between" with the correct attribute; also update any tests that assert
the operator name "createdBetween"/"updatedBetween" to expect "between" and that
the attribute is "$createdAt"/"$updatedAt".

💡 Verification agent

🧩 Analysis chain

Repo-wide verification for API compatibility.

Update tests/usage to match the supported shape; remove any geometry/distance usages.

Also applies to: 126-129, 178-224


🏁 Script executed:

#!/bin/bash
# 1) Find usages of newly added helpers
rg -nP --type=dart -C2 '\b(createdBetween|updatedBetween|distance(Equal|NotEqual|GreaterThan|LessThan)|intersects|notIntersects|crosses|notCrosses|overlaps|notOverlaps|touches|notTouches)\s*\('

# 2) Show current JSON emitted by Query.createdBetween/updatedBetween
rg -nP -C3 'static\s+String\s+createdBetween|static\s+String\s+updatedBetween' lib/query.dart

# 3) Grep tests that assert method name/attribute for created/updated helpers
rg -nP -C2 'createdBetween|updatedBetween' test

Length of output: 7187


Remove unsupported geometry/distance filter methods
Delete the distance* and geometry filter helpers (distanceEqual/NotEqual/GreaterThan/LessThan and intersects/notIntersects/crosses/notCrosses/overlaps/notOverlaps/touches/notTouches) from lib/query.dart (lines 178–224).

🤖 Prompt for AI Agents
In lib/query.dart around lines 178 to 224, remove the unsupported
geometry/distance filter helper methods: all distance* methods (distanceEqual,
distanceNotEqual, distanceGreaterThan, distanceLessThan) and all geometry
intersection/relationship helpers (intersects, notIntersects, crosses,
notCrosses, overlaps, notOverlaps, touches, notTouches). Delete their method
definitions and any associated imports or references that become unused as a
result, and run a quick project build/test to ensure there are no remaining
references to these methods.

/// Filter resources where document was updated before [value].
static String updatedBefore(String value) =>
Query._('updatedBefore', null, value).toString();
Expand All @@ -119,6 +125,10 @@ class Query {
static String updatedAfter(String value) =>
Query._('updatedAfter', null, value).toString();

/// Filter resources where document was updated between [start] and [end] (inclusive).
static String updatedBetween(String start, String end) =>
Query._('updatedBetween', null, [start, end]).toString();

static String or(List<String> queries) => Query._(
'or',
null,
Expand All @@ -144,14 +154,14 @@ class Query {
Query._('orderDesc', attribute).toString();

/// Return results before [id].
///
///
/// Refer to the [Cursor Based Pagination](https://appwrite.io/docs/pagination#cursor-pagination)
/// docs for more information.
static String cursorBefore(String id) =>
Query._('cursorBefore', null, id).toString();

/// Return results after [id].
///
///
/// Refer to the [Cursor Based Pagination](https://appwrite.io/docs/pagination#cursor-pagination)
/// docs for more information.
static String cursorAfter(String id) =>
Expand All @@ -161,9 +171,57 @@ class Query {
static String limit(int limit) => Query._('limit', null, limit).toString();

/// Return results from [offset].
///
///
/// Refer to the [Offset Pagination](https://appwrite.io/docs/pagination#offset-pagination)
/// docs for more information.
static String offset(int offset) =>
Query._('offset', null, offset).toString();
}

/// Filter resources where [attribute] is at a specific distance from the given coordinates.
static String distanceEqual(String attribute, List<dynamic> values, num distance, [bool meters = true]) =>
Query._('distanceEqual', attribute, [[values, distance, meters]]).toString();

/// Filter resources where [attribute] is not at a specific distance from the given coordinates.
static String distanceNotEqual(String attribute, List<dynamic> values, num distance, [bool meters = true]) =>
Query._('distanceNotEqual', attribute, [[values, distance, meters]]).toString();

/// Filter resources where [attribute] is at a distance greater than the specified value from the given coordinates.
static String distanceGreaterThan(String attribute, List<dynamic> values, num distance, [bool meters = true]) =>
Query._('distanceGreaterThan', attribute, [[values, distance, meters]]).toString();

/// Filter resources where [attribute] is at a distance less than the specified value from the given coordinates.
static String distanceLessThan(String attribute, List<dynamic> values, num distance, [bool meters = true]) =>
Query._('distanceLessThan', attribute, [[values, distance, meters]]).toString();

/// Filter resources where [attribute] intersects with the given geometry.
static String intersects(String attribute, List<dynamic> values) =>
Query._('intersects', attribute, [values]).toString();

/// Filter resources where [attribute] does not intersect with the given geometry.
static String notIntersects(String attribute, List<dynamic> values) =>
Query._('notIntersects', attribute, [values]).toString();

/// Filter resources where [attribute] crosses the given geometry.
static String crosses(String attribute, List<dynamic> values) =>
Query._('crosses', attribute, [values]).toString();

/// Filter resources where [attribute] does not cross the given geometry.
static String notCrosses(String attribute, List<dynamic> values) =>
Query._('notCrosses', attribute, [values]).toString();

/// Filter resources where [attribute] overlaps with the given geometry.
static String overlaps(String attribute, List<dynamic> values) =>
Query._('overlaps', attribute, [values]).toString();

/// Filter resources where [attribute] does not overlap with the given geometry.
static String notOverlaps(String attribute, List<dynamic> values) =>
Query._('notOverlaps', attribute, [values]).toString();

/// Filter resources where [attribute] touches the given geometry.
static String touches(String attribute, List<dynamic> values) =>
Query._('touches', attribute, [values]).toString();

/// Filter resources where [attribute] does not touch the given geometry.
static String notTouches(String attribute, List<dynamic> values) =>
Query._('notTouches', attribute, [values]).toString();
}
2 changes: 1 addition & 1 deletion lib/realtime_browser.dart
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export 'src/realtime_browser.dart';
export 'src/realtime_browser.dart';
2 changes: 1 addition & 1 deletion lib/realtime_io.dart
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export 'src/realtime_io.dart';
export 'src/realtime_io.dart';
2 changes: 1 addition & 1 deletion lib/role.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ class Role {
static String label(String name) {
return 'label:$name';
}
}
}
Loading