-
Notifications
You must be signed in to change notification settings - Fork 140
Dart Functions upgrade for Appwrite Functions v2 #313
base: master
Are you sure you want to change the base?
Changes from all commits
c445d79
fbea716
791ab24
30e9548
c3936df
f839eb9
22fa72e
c361b58
26473bc
ecbbf1a
f661b5a
137409c
66fe8d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# 🗂 File Backup using the Dropbox API | ||
A sample Dart Cloud Function that leverages Dropbox to create backups of important files uploaded to Appwrite. | ||
|
||
## 📝 Environment Variables | ||
Add the following environment variables in your Cloud Function settings. | ||
|
||
* **APPWRITE_API_KEY** - Create a key from the Appwrite console with the following scope (`files.read`) | ||
* **APPWRITE_ENDPOINT** - Your Appwrite Endpoint | ||
* **DROPBOX_KEY** - OAuth token from [Dropbox](https://blogs.dropbox.com/developers/2014/05/generate-an-access-token-for-your-own-account) | ||
|
||
## 🚀 Building and Packaging | ||
|
||
To package this example as a cloud function, follow these steps. | ||
|
||
```bash | ||
$ cd demos-for-functions/dart/file_backup | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's check with Eldad. Do we call it V2? I think we use naming convention |
||
|
||
$ PUB_CACHE=.appwrite/ dart pub get | ||
``` | ||
|
||
* Ensure that your folder structure looks like this | ||
``` | ||
. | ||
├── .appwrite/ | ||
├── main.dart | ||
├── pubspec.lock | ||
└── pubspec.yaml | ||
``` | ||
|
||
* Create a tarfile | ||
|
||
```bash | ||
$ cd .. | ||
$ tar -zcvf code.tar.gz file_backup | ||
Comment on lines
+33
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we please test this once? I remember reports from Discord that people didn't get function working when tarring from outside of the folder. They had to tar it from inside and use |
||
``` | ||
|
||
* Upload the tarfile to your Appwrite Console and use the following entrypoint command | ||
|
||
```bash | ||
dart main.dart | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In opr-examples we always put code in a source folder. Do we want to do it here for consistency? So the file would be |
||
``` | ||
Comment on lines
+37
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Same goes for all readmes. |
||
|
||
## 🎯 Trigger | ||
|
||
Head over to your function in the Appwrite console and under the Settings Tab, enable the `storage.files.create` event. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Event were refactored. Can we update these notes? |
||
|
||
If your function errors out with code 124, increase the timeout under the Settings Tab. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import 'dart:convert'; | ||
import 'dart:typed_data'; | ||
import 'package:dart_appwrite/dart_appwrite.dart'; | ||
import 'package:http/http.dart' as http; | ||
|
||
Future<void> backup( | ||
Uint8List buffer, | ||
String originalFileName, | ||
String dropboxAuthToken, | ||
) async { | ||
final dropboxEndpoint = | ||
Uri.parse('https://content.dropboxapi.com/2/files/upload'); | ||
|
||
final headers = { | ||
'Authorization': 'Bearer $dropboxAuthToken', | ||
'Content-Type': 'application/octet-stream', | ||
'Dropbox-API-Arg': '{"path": "/$originalFileName", "mode": "add" }' | ||
}; | ||
|
||
final dropboxResponse = | ||
await http.post(dropboxEndpoint, body: buffer, headers: headers); | ||
|
||
if (dropboxResponse.statusCode != 200) { | ||
throw Exception( | ||
'Could not backup file $originalFileName! Dropbox response was: ${dropboxResponse.body}'); | ||
} | ||
} | ||
|
||
Future<void> start(final request, final response) async { | ||
final env = request.env; | ||
final endpoint = env['APPWRITE_ENDPOINT']; | ||
if (endpoint == null) { | ||
throw ('Appwrite endpoint not specified. Please set an environment variable "APPWRITE_ENDPOINT" with your endpoint to the function'); | ||
} | ||
|
||
final client = Client() | ||
..setEndpoint(endpoint) | ||
..setProject(env['APPWRITE_FUNCTION_PROJECT_ID']) | ||
..setKey(env['APPWRITE_API_KEY']); | ||
|
||
Comment on lines
+37
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not experienced with flutter, but are there supposed to be 2 dots? |
||
final payload = jsonDecode(env['APPWRITE_FUNCTION_EVENT_DATA']!); | ||
final bucketId = payload['bucketId']; | ||
final fileId = payload['\$id']!; | ||
final originalName = payload[r'name']!; | ||
|
||
final storage = Storage(client); | ||
|
||
final dropboxKey = env['DROPBOX_KEY']; | ||
if (dropboxKey == null) { | ||
throw( | ||
'Dropbox key not specified. Please set an environment variable "DROPBOX_KEY" containing your dropbox key'); | ||
} | ||
|
||
final response = await storage.getFileDownload(bucketId: bucketId, fileId: fileId); | ||
|
||
try { | ||
await backup(response.data!, originalName, dropboxKey!); | ||
response.send('Successfully backed up $originalName'); | ||
} catch (e) { | ||
response.send('Failed backing up the file: $e'); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
name: file_backup | ||
description: Demo for backing up files to Dropbox in an Appwrite function. | ||
|
||
environment: | ||
sdk: '>=2.12.0 <3.0.0' | ||
|
||
dependencies: | ||
dart_appwrite: ^4.0.1 | ||
http: ^0.13.4 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Files and directories created by pub. | ||
.dart_tool/ | ||
.packages | ||
|
||
# Conventional directory for build output. | ||
build/ | ||
|
||
# Some Constants. | ||
constants.dart |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# GIPHYGif Generator | ||
|
||
A sample Dart Cloud Function which takes a keyword and returns the first result with giphy gif url | ||
|
||
## Getting Started | ||
|
||
Head over to the [Giphy Developers](https://developers.giphy.com/docs/api) to read their quick start guide and get your API key. Make sure to use the **GIPHY API** and not the **GIPHY SDK**. | ||
<img src = 'https://github.com/2002Bishwajeet/demos-for-functions/blob/feat-implement-generate-giphy-gif-dart/dart/generate-giphy-gif/screenshots/SDKvsAPI.png' width = '100%' height = '50%' /> | ||
|
||
Since we are retrieving an url from the API, the GIPHY API is more than enough for our needs. | ||
|
||
## ☁️ Create a new Function | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets add this title to all readmes, or remove it from here |
||
|
||
**NOTE:** If your project is not created yet, you will be prompted to create a new project. | ||
|
||
1. Go to your `appwrite console` | ||
2. Select your project and go to `Functions` | ||
<img src = 'https://github.com/2002Bishwajeet/demos-for-functions/blob/feat-implement-generate-giphy-gif-dart/dart/generate-giphy-gif/screenshots/functions.png' width = '100%' /> | ||
3. Under `Functions` click on `Add Function` | ||
<img src ='https://github.com/2002Bishwajeet/demos-for-functions/blob/feat-implement-generate-giphy-gif-dart/dart/generate-giphy-gif/screenshots/function2.png' width = '100%' /> | ||
|
||
**NOTE:** If you don't see the Dart option in the runtimes. Follow [`troubleshooting.md`](troubleshoot.md) guide to learn how to add the Dart runtime. | ||
|
||
## 📝 Environment Variables | ||
|
||
Go to Settings tab of your Cloud Function. Add the following environment variable. | ||
|
||
* **GIPHY_API_KEY** - API Key of your GIPHY account | ||
|
||
## 🚀 Building and Packaging | ||
|
||
To package this example as a cloud function, follow these steps. | ||
|
||
* Ensure that your folder structure looks like this | ||
|
||
``` | ||
. | ||
├── main.dart | ||
└── pubspec.yaml | ||
``` | ||
|
||
* Create a tarfile | ||
|
||
```bash | ||
cd .. | ||
tar -zcvf code.tar.gz generate-giphy-gif | ||
``` | ||
|
||
* Navigate to the Overview Tab of your Cloud Function > Deploy Tag | ||
* Input the command that will run your function (in this case "main.dart") as your entrypoint | ||
* Upload your tarfile | ||
* Click 'Activate' | ||
|
||
## 🎯 Trigger | ||
|
||
Head over to your function in the Appwrite console and just press **Execute**. You will notice the output in your logs | ||
|
||
|
||
## 👨💻 Live Working | ||
|
||
<img src = "screenshots\ans.gif"/> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import 'dart:convert'; | ||
import 'package:http/http.dart' as http; | ||
|
||
Future<void> start(final request, final response) async { | ||
Uri url = Uri(); | ||
if(request.env['GIPHY_API_KEY'] == null) { | ||
throw Exception("GIPHY_API_KEY is required"); | ||
} | ||
|
||
url = url.replace( | ||
scheme: 'https', | ||
host: 'api.giphy.com', | ||
path: 'v1/gifs/search', | ||
queryParameters: { | ||
'api_key': request.env['GIPHY_API_KEY'], // The Api key which we will store in Appwrite Console. | ||
// Note you can change the var name to something else too. | ||
|
||
'q': env['APPWRITE_FUNCTION_DATA'], // The search query which we will pass during execution | ||
'limit': '1', // Since we want the first top result we set the limit to 1. | ||
// This parameter is optional. To read about what parameters you can pass . | ||
// https://developers.giphy.com/docs/api/endpoint#search -> Refer to this | ||
}, | ||
); | ||
|
||
http.Response response = await http.get(url); | ||
|
||
var data = json.decode(response.body); | ||
response.send(data['data'][0]['url']); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
name: giphy | ||
description: A simple command-line application. | ||
version: 1.0.0 | ||
|
||
environment: | ||
sdk: ">=2.12.0 <3.0.0" | ||
|
||
|
||
dependencies: | ||
http: ^0.13.4 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<center> | ||
|
||
# TroubleShoot Guide ⚒️ | ||
|
||
</center> | ||
|
||
## Add Dart Runtime to your Appwrite Console | ||
|
||
* Go to your appwrite directory | ||
|
||
If you are using WSL it should be located in `\home\username\appwrite\` | ||
|
||
* Open up the `.env` file | ||
|
||
* Keep the `_APP_FUNCTIONS_ENVS` empty and add the `dart-2.17` alongside the existing ones in the `_APP_FUNCTIONS_RUNTIMES` | ||
|
||
<img src = "screenshots/ss4.png" width = "100%"> | ||
|
||
* Save the file | ||
|
||
* Then run the following command in the WSL terminal | ||
|
||
```bash | ||
docker compose up -d | ||
``` | ||
|
||
This command will restart all the existing appwrite containers along with the latest changes. Now hopover to appwrite console and you can see the `Dart` Runtime option in the functions. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# 🗂 Generate Open Street Maps | ||
A sample Dart Cloud Function that saves an open street maps tile for given latitude and longitude to Appwrite storage. | ||
|
||
## 📝 Environment Variables | ||
Add the following environment variables in your Cloud Function settings. | ||
|
||
* **APPWRITE_API_KEY** - Create a key from the Appwrite console with the following scope (`files.write`) | ||
* **APPWRITE_ENDPOINT** - Your Appwrite Endpoint | ||
* **APPWRITE_BUCKET_ID** - ID of the bucket that you want to upload the map image to | ||
|
||
## 🚀 Building and Packaging | ||
|
||
To package this example as a cloud function, follow these steps. | ||
|
||
* Ensure that your folder structure looks like this | ||
``` | ||
. | ||
├── main.dart | ||
├── pubspec.lock | ||
└── pubspec.yaml | ||
``` | ||
|
||
* Create a tarfile | ||
|
||
```bash | ||
$ cd .. | ||
$ tar -zcvf code.tar.gz generate_open_street_map | ||
``` | ||
|
||
* Upload the tarfile to your Appwrite Console and use the following entrypoint | ||
|
||
```bash | ||
main.dart | ||
``` | ||
|
||
## 🎯 Trigger | ||
|
||
Head over to your function in the Appwrite console and after clicking the `Execute Now` button, enter a JSON object in the form of | ||
```json | ||
{ | ||
"latitude": 37.7822403, | ||
"longitude": -122.3910414 | ||
} | ||
``` | ||
with your respective coordinates. | ||
|
||
If your function errors out with code 124, increase the timeout under the Settings Tab. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import 'dart:convert'; | ||
import 'dart:math'; | ||
import 'dart:io'; | ||
|
||
import 'package:http/http.dart' as http; | ||
import 'package:dart_appwrite/dart_appwrite.dart'; | ||
import 'package:vector_math/vector_math.dart'; | ||
|
||
const zoomLevel = 15; | ||
|
||
String ensureEnvVariable(String key, final request) { | ||
final value = request.env[key]; | ||
if (value == null) { | ||
print( | ||
'Could not find environment variable $key. Please set it following the instructions in the readme file.'); | ||
exit(1); | ||
} | ||
|
||
return value; | ||
} | ||
|
||
// Adapted from https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Mathematics | ||
Point<int> coordinatesToTilePoint(double latitude, double longitude) { | ||
final x = (pow(2, zoomLevel) * ((longitude + 180) / 360)).floor(); | ||
|
||
final radLat = radians(latitude); | ||
final y = (pow(2, zoomLevel - 1) * | ||
(1 - (log(tan(radLat) + (1 / cos(radLat))) / pi))) | ||
.floor(); | ||
|
||
return Point(x, y); | ||
} | ||
|
||
Future<List<int>> fetchTile(double latitude, double longitude) async { | ||
final point = coordinatesToTilePoint(latitude, longitude); | ||
final tileUrl = | ||
'https://tile.openstreetmap.org/${zoomLevel}/${point.x}/${point.y}.png'; | ||
|
||
print(tileUrl); | ||
|
||
final response = await http.get(Uri.parse(tileUrl)); | ||
if (response.statusCode != 200) { | ||
print('There was an error loading the tile for $point: ${response.body}'); | ||
exit(1); | ||
} | ||
|
||
return response.bodyBytes; | ||
} | ||
|
||
Future<void> start(final request, final response) async { | ||
final client = Client(); | ||
client | ||
.setKey(ensureEnvVariable('APPWRITE_API_KEY', request)) | ||
.setProject(ensureEnvVariable('APPWRITE_FUNCTION_PROJECT_ID', request)) | ||
.setEndpoint(ensureEnvVariable('APPWRITE_ENDPOINT', request)); | ||
|
||
final data = jsonDecode(ensureEnvVariable('APPWRITE_FUNCTION_DATA', request)); | ||
final bucketId = ensureEnvVariable('APPWRITE_BUCKET_ID'); | ||
|
||
final storage = Storage(client); | ||
final latitude = data['latitude']; | ||
final longitude = data['longitude']; | ||
|
||
final imageBytes = await fetchTile(latitude, longitude); | ||
final filename = 'osm_tile_${latitude}_${longitude}_z$zoomLevel.png'; | ||
|
||
final file = await storage.createFile( | ||
bucketId: bucketId, | ||
file: InputFile.fromBytes('file', imageBytes, filename: filename, contentType: 'image/png'), | ||
); | ||
response.json({"message": "Map created", "fileId": file.$id, "bucketId": bucketId }); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's check this command in all readmes, should be V2