Skip to content

Commit c1cbb36

Browse files
authored
Merge pull request #251 from appwrite/dev
chore: add setDevKey and upsertDocument methods
2 parents 5ee6bfb + 6e2e60f commit c1cbb36

14 files changed

+136
-41
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change Log
22

3+
## 16.0.1
4+
5+
* Add `setDevKey` method to Client service
6+
* Add `upsertDocument` method to Databases service
7+
38
## 16.0.0
49

510
* Remove `Gif` from ImageFormat enum

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Add this to your package's `pubspec.yaml` file:
2121

2222
```yml
2323
dependencies:
24-
appwrite: ^16.0.0
24+
appwrite: ^16.1.0
2525
```
2626
2727
You can install packages from the command line:
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import 'package:appwrite/appwrite.dart';
2+
3+
Client client = Client()
4+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
5+
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
6+
7+
Databases databases = Databases(client);
8+
9+
Document result = await databases.upsertDocument(
10+
databaseId: '<DATABASE_ID>',
11+
collectionId: '<COLLECTION_ID>',
12+
documentId: '<DOCUMENT_ID>',
13+
data: {},
14+
permissions: ["read("any")"], // optional
15+
);

lib/query.dart

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,17 @@ class Query {
8282
static String contains(String attribute, dynamic value) =>
8383
Query._('contains', attribute, value).toString();
8484

85-
static String or(List<String> queries) =>
86-
Query._(
87-
'or',
88-
null,
89-
queries.map((query) => jsonDecode(query)).toList(),
90-
).toString();
91-
92-
static String and(List<String> queries) =>
93-
Query._(
94-
'and',
95-
null,
96-
queries.map((query) => jsonDecode(query)).toList(),
97-
).toString();
85+
static String or(List<String> queries) => Query._(
86+
'or',
87+
null,
88+
queries.map((query) => jsonDecode(query)).toList(),
89+
).toString();
90+
91+
static String and(List<String> queries) => Query._(
92+
'and',
93+
null,
94+
queries.map((query) => jsonDecode(query)).toList(),
95+
).toString();
9896

9997
/// Specify which attributes should be returned by the API call.
10098
static String select(List<String> attributes) =>

lib/services/databases.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,40 @@ class Databases extends Service {
9494
return models.Document.fromMap(res.data);
9595
}
9696

97+
/// Create or update a Document. Before using this route, you should create a
98+
/// new collection resource using either a [server
99+
/// integration](https://appwrite.io/docs/server/databases#databasesCreateCollection)
100+
/// API or directly from your database console.
101+
Future<models.Document> upsertDocument({
102+
required String databaseId,
103+
required String collectionId,
104+
required String documentId,
105+
required Map data,
106+
List<String>? permissions,
107+
}) async {
108+
final String apiPath =
109+
'/databases/{databaseId}/collections/{collectionId}/documents/{documentId}'
110+
.replaceAll('{databaseId}', databaseId)
111+
.replaceAll('{collectionId}', collectionId)
112+
.replaceAll('{documentId}', documentId);
113+
114+
final Map<String, dynamic> apiParams = {
115+
'data': data,
116+
'permissions': permissions,
117+
};
118+
119+
final Map<String, String> apiHeaders = {'content-type': 'application/json'};
120+
121+
final res = await client.call(
122+
HttpMethod.put,
123+
path: apiPath,
124+
params: apiParams,
125+
headers: apiHeaders,
126+
);
127+
128+
return models.Document.fromMap(res.data);
129+
}
130+
97131
/// Update a document by its unique ID. Using the patch method you can pass
98132
/// only specific fields that will get updated.
99133
Future<models.Document> updateDocument({

lib/src/client.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ abstract class Client {
7373
/// The user session to authenticate with.
7474
Client setSession(value);
7575

76+
/// Set DevKey.
77+
///
78+
/// Your secret dev API key.
79+
Client setDevKey(value);
80+
7681
/// Add headers that should be sent with all API calls.
7782
Client addHeader(String key, String value);
7883

lib/src/client_base.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ abstract class ClientBase implements Client {
1717
@override
1818
ClientBase setSession(value);
1919

20+
/// Your secret dev API key
21+
@override
22+
ClientBase setDevKey(value);
23+
2024
@override
2125
ClientBase setSelfSigned({bool status = true});
2226

lib/src/client_browser.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ClientBrowser extends ClientBase with ClientMixin {
4040
'x-sdk-name': 'Flutter',
4141
'x-sdk-platform': 'client',
4242
'x-sdk-language': 'flutter',
43-
'x-sdk-version': '16.0.0',
43+
'x-sdk-version': '16.1.0',
4444
'X-Appwrite-Response-Format': '1.7.0',
4545
};
4646

@@ -87,6 +87,14 @@ class ClientBrowser extends ClientBase with ClientMixin {
8787
return this;
8888
}
8989

90+
/// Your secret dev API key
91+
@override
92+
ClientBrowser setDevKey(value) {
93+
config['devKey'] = value;
94+
addHeader('X-Appwrite-Dev-Key', value);
95+
return this;
96+
}
97+
9098
@override
9199
ClientBrowser setSelfSigned({bool status = true}) {
92100
return this;

lib/src/client_io.dart

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,9 @@ class ClientIO extends ClientBase with ClientMixin {
4646
String endPoint = 'https://cloud.appwrite.io/v1',
4747
this.selfSigned = false,
4848
}) : _endPoint = endPoint {
49-
_nativeClient =
50-
HttpClient()
51-
..badCertificateCallback =
52-
((X509Certificate cert, String host, int port) => selfSigned);
49+
_nativeClient = HttpClient()
50+
..badCertificateCallback =
51+
((X509Certificate cert, String host, int port) => selfSigned);
5352
_httpClient = IOClient(_nativeClient);
5453
_endPointRealtime = endPoint
5554
.replaceFirst('https://', 'wss://')
@@ -59,7 +58,7 @@ class ClientIO extends ClientBase with ClientMixin {
5958
'x-sdk-name': 'Flutter',
6059
'x-sdk-platform': 'client',
6160
'x-sdk-language': 'flutter',
62-
'x-sdk-version': '16.0.0',
61+
'x-sdk-version': '16.1.0',
6362
'X-Appwrite-Response-Format': '1.7.0',
6463
};
6564

@@ -114,6 +113,14 @@ class ClientIO extends ClientBase with ClientMixin {
114113
return this;
115114
}
116115

116+
/// Your secret dev API key
117+
@override
118+
ClientIO setDevKey(value) {
119+
config['devKey'] = value;
120+
addHeader('X-Appwrite-Dev-Key', value);
121+
return this;
122+
}
123+
117124
@override
118125
ClientIO setSelfSigned({bool status = true}) {
119126
selfSigned = status;
@@ -349,10 +356,9 @@ class ClientIO extends ClientBase with ClientMixin {
349356
Future webAuth(Uri url, {String? callbackUrlScheme}) {
350357
return FlutterWebAuth2.authenticate(
351358
url: url.toString(),
352-
callbackUrlScheme:
353-
callbackUrlScheme != null && _customSchemeAllowed
354-
? callbackUrlScheme
355-
: "appwrite-callback-" + config['project']!,
359+
callbackUrlScheme: callbackUrlScheme != null && _customSchemeAllowed
360+
? callbackUrlScheme
361+
: "appwrite-callback-" + config['project']!,
356362
options: const FlutterWebAuth2Options(intentFlags: ephemeralIntentFlags),
357363
).then((value) async {
358364
Uri url = Uri.parse(value);

lib/src/client_mixin.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,9 @@ mixin ClientMixin {
124124
'',
125125
streamedResponse.statusCode,
126126
headers: streamedResponse.headers.map(
127-
(k, v) =>
128-
k.toLowerCase() == 'content-type'
129-
? MapEntry(k, 'text/plain')
130-
: MapEntry(k, v),
127+
(k, v) => k.toLowerCase() == 'content-type'
128+
? MapEntry(k, 'text/plain')
129+
: MapEntry(k, v),
131130
),
132131
request: streamedResponse.request,
133132
isRedirect: streamedResponse.isRedirect,

lib/src/realtime_io.dart

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,11 @@ class RealtimeIO extends RealtimeBase with RealtimeMixin {
5959
var r = Random();
6060
var key = base64.encode(List<int>.generate(16, (_) => r.nextInt(255)));
6161
var client = HttpClient(context: SecurityContext());
62-
client.badCertificateCallback = (
63-
X509Certificate cert,
64-
String host,
65-
int port,
66-
) {
67-
debugPrint('AppwriteRealtime: Allow self-signed certificate');
68-
return true;
69-
};
62+
client.badCertificateCallback =
63+
(X509Certificate cert, String host, int port) {
64+
debugPrint('AppwriteRealtime: Allow self-signed certificate');
65+
return true;
66+
};
7067

7168
uri = Uri(
7269
scheme: uri.scheme == 'wss' ? 'https' : 'http',

lib/src/realtime_stub.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'realtime_base.dart';
22
import 'client.dart';
33

44
/// Implemented in `realtime_browser.dart` and `realtime_io.dart`.
5-
RealtimeBase createRealtime(Client client) =>
6-
throw UnsupportedError(
7-
'Cannot create a client without dart:html or dart:io.',
8-
);
5+
RealtimeBase createRealtime(Client client) => throw UnsupportedError(
6+
'Cannot create a client without dart:html or dart:io.',
7+
);

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: appwrite
2-
version: 16.0.0
2+
version: 16.1.0
33
description: Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API
44
homepage: https://appwrite.io
55
repository: https://github.com/appwrite/sdk-for-flutter

test/services/databases_test.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,31 @@ void main() {
122122

123123
});
124124

125+
test('test method upsertDocument()', () async {
126+
final Map<String, dynamic> data = {
127+
'\$id': '5e5ea5c16897e',
128+
'\$collectionId': '5e5ea5c15117e',
129+
'\$databaseId': '5e5ea5c15117e',
130+
'\$createdAt': '2020-10-15T06:38:00.000+00:00',
131+
'\$updatedAt': '2020-10-15T06:38:00.000+00:00',
132+
'\$permissions': [],};
133+
134+
135+
when(client.call(
136+
HttpMethod.put,
137+
)).thenAnswer((_) async => Response(data: data));
138+
139+
140+
final response = await databases.upsertDocument(
141+
databaseId: '<DATABASE_ID>',
142+
collectionId: '<COLLECTION_ID>',
143+
documentId: '<DOCUMENT_ID>',
144+
data: {},
145+
);
146+
expect(response, isA<models.Document>());
147+
148+
});
149+
125150
test('test method updateDocument()', () async {
126151
final Map<String, dynamic> data = {
127152
'\$id': '5e5ea5c16897e',

0 commit comments

Comments
 (0)