diff --git a/CHANGELOG.md b/CHANGELOG.md index 176efe4a..4fcd2778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 20.2.0 + +* Add transaction support for Databases and TablesDB + ## 20.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/README.md b/README.md index e24685c6..7c7ff16c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Add this to your package's `pubspec.yaml` file: ```yml dependencies: - appwrite: ^20.1.0 + appwrite: ^20.2.0 ``` You can install packages from the command line: diff --git a/docs/examples/databases/create-document.md b/docs/examples/databases/create-document.md index 3becbcf1..0acbe689 100644 --- a/docs/examples/databases/create-document.md +++ b/docs/examples/databases/create-document.md @@ -18,4 +18,5 @@ Document result = await databases.createDocument( "isAdmin": false }, permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/databases/create-operations.md b/docs/examples/databases/create-operations.md new file mode 100644 index 00000000..2dec7ff7 --- /dev/null +++ b/docs/examples/databases/create-operations.md @@ -0,0 +1,22 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ], // optional +); diff --git a/docs/examples/databases/create-transaction.md b/docs/examples/databases/create-transaction.md new file mode 100644 index 00000000..3d7ddc3e --- /dev/null +++ b/docs/examples/databases/create-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.createTransaction( + ttl: 60, // optional +); diff --git a/docs/examples/databases/decrement-document-attribute.md b/docs/examples/databases/decrement-document-attribute.md index ec0d9ee3..dad45bc8 100644 --- a/docs/examples/databases/decrement-document-attribute.md +++ b/docs/examples/databases/decrement-document-attribute.md @@ -13,4 +13,5 @@ Document result = await databases.decrementDocumentAttribute( attribute: '', value: 0, // optional min: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/databases/delete-document.md b/docs/examples/databases/delete-document.md index 3354917c..bd101370 100644 --- a/docs/examples/databases/delete-document.md +++ b/docs/examples/databases/delete-document.md @@ -10,4 +10,5 @@ await databases.deleteDocument( databaseId: '', collectionId: '', documentId: '', + transactionId: '', // optional ); diff --git a/docs/examples/databases/delete-transaction.md b/docs/examples/databases/delete-transaction.md new file mode 100644 index 00000000..333dd1d3 --- /dev/null +++ b/docs/examples/databases/delete-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +await databases.deleteTransaction( + transactionId: '', +); diff --git a/docs/examples/databases/get-document.md b/docs/examples/databases/get-document.md index f85c1f9b..9dcf2cf1 100644 --- a/docs/examples/databases/get-document.md +++ b/docs/examples/databases/get-document.md @@ -11,4 +11,5 @@ Document result = await databases.getDocument( collectionId: '', documentId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/databases/get-transaction.md b/docs/examples/databases/get-transaction.md new file mode 100644 index 00000000..153b0f38 --- /dev/null +++ b/docs/examples/databases/get-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.getTransaction( + transactionId: '', +); diff --git a/docs/examples/databases/increment-document-attribute.md b/docs/examples/databases/increment-document-attribute.md index 78f5b0cb..855fd8f5 100644 --- a/docs/examples/databases/increment-document-attribute.md +++ b/docs/examples/databases/increment-document-attribute.md @@ -13,4 +13,5 @@ Document result = await databases.incrementDocumentAttribute( attribute: '', value: 0, // optional max: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/databases/list-documents.md b/docs/examples/databases/list-documents.md index 31fec1f5..b53120cb 100644 --- a/docs/examples/databases/list-documents.md +++ b/docs/examples/databases/list-documents.md @@ -10,4 +10,5 @@ DocumentList result = await databases.listDocuments( databaseId: '', collectionId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/databases/list-transactions.md b/docs/examples/databases/list-transactions.md new file mode 100644 index 00000000..467a1ced --- /dev/null +++ b/docs/examples/databases/list-transactions.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +TransactionList result = await databases.listTransactions( + queries: [], // optional +); diff --git a/docs/examples/databases/update-document.md b/docs/examples/databases/update-document.md index 1f444d87..44ade30c 100644 --- a/docs/examples/databases/update-document.md +++ b/docs/examples/databases/update-document.md @@ -12,4 +12,5 @@ Document result = await databases.updateDocument( documentId: '', data: {}, // optional permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/databases/update-transaction.md b/docs/examples/databases/update-transaction.md new file mode 100644 index 00000000..a51f9d05 --- /dev/null +++ b/docs/examples/databases/update-transaction.md @@ -0,0 +1,13 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.updateTransaction( + transactionId: '', + commit: false, // optional + rollback: false, // optional +); diff --git a/docs/examples/databases/upsert-document.md b/docs/examples/databases/upsert-document.md index 398a99cb..10117ac7 100644 --- a/docs/examples/databases/upsert-document.md +++ b/docs/examples/databases/upsert-document.md @@ -12,4 +12,5 @@ Document result = await databases.upsertDocument( documentId: '', data: {}, permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/create-operations.md b/docs/examples/tablesdb/create-operations.md new file mode 100644 index 00000000..631aefe6 --- /dev/null +++ b/docs/examples/tablesdb/create-operations.md @@ -0,0 +1,22 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ], // optional +); diff --git a/docs/examples/tablesdb/create-row.md b/docs/examples/tablesdb/create-row.md index 038bb2ba..345f0c23 100644 --- a/docs/examples/tablesdb/create-row.md +++ b/docs/examples/tablesdb/create-row.md @@ -18,4 +18,5 @@ Row result = await tablesDB.createRow( "isAdmin": false }, permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/create-transaction.md b/docs/examples/tablesdb/create-transaction.md new file mode 100644 index 00000000..0ad0eb52 --- /dev/null +++ b/docs/examples/tablesdb/create-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.createTransaction( + ttl: 60, // optional +); diff --git a/docs/examples/tablesdb/decrement-row-column.md b/docs/examples/tablesdb/decrement-row-column.md index 4f3b4bdb..65f67513 100644 --- a/docs/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/tablesdb/decrement-row-column.md @@ -13,4 +13,5 @@ Row result = await tablesDB.decrementRowColumn( column: '', value: 0, // optional min: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/delete-row.md b/docs/examples/tablesdb/delete-row.md index cc902fa1..b8ea1d26 100644 --- a/docs/examples/tablesdb/delete-row.md +++ b/docs/examples/tablesdb/delete-row.md @@ -10,4 +10,5 @@ await tablesDB.deleteRow( databaseId: '', tableId: '', rowId: '', + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/delete-transaction.md b/docs/examples/tablesdb/delete-transaction.md new file mode 100644 index 00000000..2d27c6af --- /dev/null +++ b/docs/examples/tablesdb/delete-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +await tablesDB.deleteTransaction( + transactionId: '', +); diff --git a/docs/examples/tablesdb/get-row.md b/docs/examples/tablesdb/get-row.md index 29e6eaab..eb75da50 100644 --- a/docs/examples/tablesdb/get-row.md +++ b/docs/examples/tablesdb/get-row.md @@ -11,4 +11,5 @@ Row result = await tablesDB.getRow( tableId: '', rowId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/get-transaction.md b/docs/examples/tablesdb/get-transaction.md new file mode 100644 index 00000000..000e2302 --- /dev/null +++ b/docs/examples/tablesdb/get-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.getTransaction( + transactionId: '', +); diff --git a/docs/examples/tablesdb/increment-row-column.md b/docs/examples/tablesdb/increment-row-column.md index e05dc767..91cd0ce3 100644 --- a/docs/examples/tablesdb/increment-row-column.md +++ b/docs/examples/tablesdb/increment-row-column.md @@ -13,4 +13,5 @@ Row result = await tablesDB.incrementRowColumn( column: '', value: 0, // optional max: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/list-rows.md b/docs/examples/tablesdb/list-rows.md index 7763e2ae..01d70665 100644 --- a/docs/examples/tablesdb/list-rows.md +++ b/docs/examples/tablesdb/list-rows.md @@ -10,4 +10,5 @@ RowList result = await tablesDB.listRows( databaseId: '', tableId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/list-transactions.md b/docs/examples/tablesdb/list-transactions.md new file mode 100644 index 00000000..5e088ced --- /dev/null +++ b/docs/examples/tablesdb/list-transactions.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +TransactionList result = await tablesDB.listTransactions( + queries: [], // optional +); diff --git a/docs/examples/tablesdb/update-row.md b/docs/examples/tablesdb/update-row.md index c2cc84d7..08ab3093 100644 --- a/docs/examples/tablesdb/update-row.md +++ b/docs/examples/tablesdb/update-row.md @@ -12,4 +12,5 @@ Row result = await tablesDB.updateRow( rowId: '', data: {}, // optional permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/tablesdb/update-transaction.md b/docs/examples/tablesdb/update-transaction.md new file mode 100644 index 00000000..ef56443e --- /dev/null +++ b/docs/examples/tablesdb/update-transaction.md @@ -0,0 +1,13 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.updateTransaction( + transactionId: '', + commit: false, // optional + rollback: false, // optional +); diff --git a/docs/examples/tablesdb/upsert-row.md b/docs/examples/tablesdb/upsert-row.md index 6a958a18..061bb0b8 100644 --- a/docs/examples/tablesdb/upsert-row.md +++ b/docs/examples/tablesdb/upsert-row.md @@ -12,4 +12,5 @@ Row result = await tablesDB.upsertRow( rowId: '', data: {}, // optional permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/lib/models.dart b/lib/models.dart index b5aad7f7..ca9bccc6 100644 --- a/lib/models.dart +++ b/lib/models.dart @@ -19,6 +19,7 @@ part 'src/models/language_list.dart'; part 'src/models/currency_list.dart'; part 'src/models/phone_list.dart'; part 'src/models/locale_code_list.dart'; +part 'src/models/transaction_list.dart'; part 'src/models/row.dart'; part 'src/models/document.dart'; part 'src/models/log.dart'; @@ -51,5 +52,6 @@ part 'src/models/mfa_challenge.dart'; part 'src/models/mfa_recovery_codes.dart'; part 'src/models/mfa_type.dart'; part 'src/models/mfa_factors.dart'; +part 'src/models/transaction.dart'; part 'src/models/subscriber.dart'; part 'src/models/target.dart'; diff --git a/lib/services/databases.dart b/lib/services/databases.dart index 8e165559..4c76d231 100644 --- a/lib/services/databases.dart +++ b/lib/services/databases.dart @@ -6,6 +6,138 @@ class Databases extends Service { /// Initializes a [Databases] service Databases(super.client); + /// List transactions across all databases. + Future listTransactions({ + List? queries, + }) async { + const String apiPath = '/databases/transactions'; + + final Map apiParams = {'queries': queries}; + + final Map apiHeaders = {}; + + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.TransactionList.fromMap(res.data); + } + + /// Create a new transaction. + Future createTransaction({int? ttl}) async { + const String apiPath = '/databases/transactions'; + + final Map apiParams = {'ttl': ttl}; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + + /// Get a transaction by its unique ID. + Future getTransaction({ + required String transactionId, + }) async { + final String apiPath = '/databases/transactions/{transactionId}'.replaceAll( + '{transactionId}', + transactionId, + ); + + final Map apiParams = {}; + + final Map apiHeaders = {}; + + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + + /// Update a transaction, to either commit or roll back its operations. + Future updateTransaction({ + required String transactionId, + bool? commit, + bool? rollback, + }) async { + final String apiPath = '/databases/transactions/{transactionId}'.replaceAll( + '{transactionId}', + transactionId, + ); + + final Map apiParams = { + 'commit': commit, + 'rollback': rollback, + }; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + + /// Delete a transaction by its unique ID. + Future deleteTransaction({required String transactionId}) async { + final String apiPath = '/databases/transactions/{transactionId}'.replaceAll( + '{transactionId}', + transactionId, + ); + + final Map apiParams = {}; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return res.data; + } + + /// Create multiple operations in a single transaction. + Future createOperations({ + required String transactionId, + List? operations, + }) async { + final String apiPath = '/databases/transactions/{transactionId}/operations' + .replaceAll('{transactionId}', transactionId); + + final Map apiParams = {'operations': operations}; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + /// Get a list of all the user's documents in a given collection. You can use /// the query params to filter your results. @Deprecated( @@ -15,13 +147,17 @@ class Databases extends Service { required String databaseId, required String collectionId, List? queries, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents' .replaceAll('{databaseId}', databaseId) .replaceAll('{collectionId}', collectionId); - final Map apiParams = {'queries': queries}; + final Map apiParams = { + 'queries': queries, + 'transactionId': transactionId, + }; final Map apiHeaders = {}; @@ -48,6 +184,7 @@ class Databases extends Service { required String documentId, required Map data, List? permissions, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents' @@ -58,6 +195,7 @@ class Databases extends Service { 'documentId': documentId, 'data': data, 'permissions': permissions, + 'transactionId': transactionId, }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -82,6 +220,7 @@ class Databases extends Service { required String collectionId, required String documentId, List? queries, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' @@ -89,7 +228,10 @@ class Databases extends Service { .replaceAll('{collectionId}', collectionId) .replaceAll('{documentId}', documentId); - final Map apiParams = {'queries': queries}; + final Map apiParams = { + 'queries': queries, + 'transactionId': transactionId, + }; final Map apiHeaders = {}; @@ -116,6 +258,7 @@ class Databases extends Service { required String documentId, required Map data, List? permissions, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' @@ -126,6 +269,7 @@ class Databases extends Service { final Map apiParams = { 'data': data, 'permissions': permissions, + 'transactionId': transactionId, }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -151,6 +295,7 @@ class Databases extends Service { required String documentId, Map? data, List? permissions, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' @@ -161,6 +306,7 @@ class Databases extends Service { final Map apiParams = { 'data': data, 'permissions': permissions, + 'transactionId': transactionId, }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -183,6 +329,7 @@ class Databases extends Service { required String databaseId, required String collectionId, required String documentId, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' @@ -190,7 +337,7 @@ class Databases extends Service { .replaceAll('{collectionId}', collectionId) .replaceAll('{documentId}', documentId); - final Map apiParams = {}; + final Map apiParams = {'transactionId': transactionId}; final Map apiHeaders = {'content-type': 'application/json'}; @@ -215,6 +362,7 @@ class Databases extends Service { required String attribute, double? value, double? min, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/decrement' @@ -223,7 +371,11 @@ class Databases extends Service { .replaceAll('{documentId}', documentId) .replaceAll('{attribute}', attribute); - final Map apiParams = {'value': value, 'min': min}; + final Map apiParams = { + 'value': value, + 'min': min, + 'transactionId': transactionId, + }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -248,6 +400,7 @@ class Databases extends Service { required String attribute, double? value, double? max, + String? transactionId, }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/increment' @@ -256,7 +409,11 @@ class Databases extends Service { .replaceAll('{documentId}', documentId) .replaceAll('{attribute}', attribute); - final Map apiParams = {'value': value, 'max': max}; + final Map apiParams = { + 'value': value, + 'max': max, + 'transactionId': transactionId, + }; final Map apiHeaders = {'content-type': 'application/json'}; diff --git a/lib/services/tables_db.dart b/lib/services/tables_db.dart index 2ed5b29f..ad65808e 100644 --- a/lib/services/tables_db.dart +++ b/lib/services/tables_db.dart @@ -4,18 +4,154 @@ class TablesDB extends Service { /// Initializes a [TablesDB] service TablesDB(super.client); + /// List transactions across all databases. + Future listTransactions({ + List? queries, + }) async { + const String apiPath = '/tablesdb/transactions'; + + final Map apiParams = {'queries': queries}; + + final Map apiHeaders = {}; + + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.TransactionList.fromMap(res.data); + } + + /// Create a new transaction. + Future createTransaction({int? ttl}) async { + const String apiPath = '/tablesdb/transactions'; + + final Map apiParams = {'ttl': ttl}; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + + /// Get a transaction by its unique ID. + Future getTransaction({ + required String transactionId, + }) async { + final String apiPath = '/tablesdb/transactions/{transactionId}'.replaceAll( + '{transactionId}', + transactionId, + ); + + final Map apiParams = {}; + + final Map apiHeaders = {}; + + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + + /// Update a transaction, to either commit or roll back its operations. + Future updateTransaction({ + required String transactionId, + bool? commit, + bool? rollback, + }) async { + final String apiPath = '/tablesdb/transactions/{transactionId}'.replaceAll( + '{transactionId}', + transactionId, + ); + + final Map apiParams = { + 'commit': commit, + 'rollback': rollback, + }; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + + /// Delete a transaction by its unique ID. + Future deleteTransaction({required String transactionId}) async { + final String apiPath = '/tablesdb/transactions/{transactionId}'.replaceAll( + '{transactionId}', + transactionId, + ); + + final Map apiParams = {}; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return res.data; + } + + /// Create multiple operations in a single transaction. + Future createOperations({ + required String transactionId, + List? operations, + }) async { + final String apiPath = '/tablesdb/transactions/{transactionId}/operations' + .replaceAll('{transactionId}', transactionId); + + final Map apiParams = {'operations': operations}; + + final Map apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); + + return models.Transaction.fromMap(res.data); + } + /// Get a list of all the user's rows in a given table. You can use the query /// params to filter your results. Future listRows({ required String databaseId, required String tableId, List? queries, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows' .replaceAll('{databaseId}', databaseId) .replaceAll('{tableId}', tableId); - final Map apiParams = {'queries': queries}; + final Map apiParams = { + 'queries': queries, + 'transactionId': transactionId, + }; final Map apiHeaders = {}; @@ -39,6 +175,7 @@ class TablesDB extends Service { required String rowId, required Map data, List? permissions, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows' .replaceAll('{databaseId}', databaseId) @@ -48,6 +185,7 @@ class TablesDB extends Service { 'rowId': rowId, 'data': data, 'permissions': permissions, + 'transactionId': transactionId, }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -69,6 +207,7 @@ class TablesDB extends Service { required String tableId, required String rowId, List? queries, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' @@ -76,7 +215,10 @@ class TablesDB extends Service { .replaceAll('{tableId}', tableId) .replaceAll('{rowId}', rowId); - final Map apiParams = {'queries': queries}; + final Map apiParams = { + 'queries': queries, + 'transactionId': transactionId, + }; final Map apiHeaders = {}; @@ -100,6 +242,7 @@ class TablesDB extends Service { required String rowId, Map? data, List? permissions, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' @@ -110,6 +253,7 @@ class TablesDB extends Service { final Map apiParams = { 'data': data, 'permissions': permissions, + 'transactionId': transactionId, }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -132,6 +276,7 @@ class TablesDB extends Service { required String rowId, Map? data, List? permissions, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' @@ -142,6 +287,7 @@ class TablesDB extends Service { final Map apiParams = { 'data': data, 'permissions': permissions, + 'transactionId': transactionId, }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -161,6 +307,7 @@ class TablesDB extends Service { required String databaseId, required String tableId, required String rowId, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' @@ -168,7 +315,7 @@ class TablesDB extends Service { .replaceAll('{tableId}', tableId) .replaceAll('{rowId}', rowId); - final Map apiParams = {}; + final Map apiParams = {'transactionId': transactionId}; final Map apiHeaders = {'content-type': 'application/json'}; @@ -190,6 +337,7 @@ class TablesDB extends Service { required String column, double? value, double? min, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/decrement' @@ -198,7 +346,11 @@ class TablesDB extends Service { .replaceAll('{rowId}', rowId) .replaceAll('{column}', column); - final Map apiParams = {'value': value, 'min': min}; + final Map apiParams = { + 'value': value, + 'min': min, + 'transactionId': transactionId, + }; final Map apiHeaders = {'content-type': 'application/json'}; @@ -220,6 +372,7 @@ class TablesDB extends Service { required String column, double? value, double? max, + String? transactionId, }) async { final String apiPath = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/increment' @@ -228,7 +381,11 @@ class TablesDB extends Service { .replaceAll('{rowId}', rowId) .replaceAll('{column}', column); - final Map apiParams = {'value': value, 'max': max}; + final Map apiParams = { + 'value': value, + 'max': max, + 'transactionId': transactionId, + }; final Map apiHeaders = {'content-type': 'application/json'}; diff --git a/lib/src/client_browser.dart b/lib/src/client_browser.dart index ec2126e3..cad02495 100644 --- a/lib/src/client_browser.dart +++ b/lib/src/client_browser.dart @@ -40,7 +40,7 @@ class ClientBrowser extends ClientBase with ClientMixin { 'x-sdk-name': 'Flutter', 'x-sdk-platform': 'client', 'x-sdk-language': 'flutter', - 'x-sdk-version': '20.1.0', + 'x-sdk-version': '20.2.0', 'X-Appwrite-Response-Format': '1.8.0', }; diff --git a/lib/src/client_io.dart b/lib/src/client_io.dart index a811ce67..73c12233 100644 --- a/lib/src/client_io.dart +++ b/lib/src/client_io.dart @@ -58,7 +58,7 @@ class ClientIO extends ClientBase with ClientMixin { 'x-sdk-name': 'Flutter', 'x-sdk-platform': 'client', 'x-sdk-language': 'flutter', - 'x-sdk-version': '20.1.0', + 'x-sdk-version': '20.2.0', 'X-Appwrite-Response-Format': '1.8.0', }; diff --git a/lib/src/models/transaction.dart b/lib/src/models/transaction.dart new file mode 100644 index 00000000..fd71d50d --- /dev/null +++ b/lib/src/models/transaction.dart @@ -0,0 +1,53 @@ +part of '../../models.dart'; + +/// Transaction +class Transaction implements Model { + /// Transaction ID. + final String $id; + + /// Transaction creation time in ISO 8601 format. + final String $createdAt; + + /// Transaction update date in ISO 8601 format. + final String $updatedAt; + + /// Current status of the transaction. One of: pending, committing, committed, rolled_back, failed. + final String status; + + /// Number of operations in the transaction. + final int operations; + + /// Expiration time in ISO 8601 format. + final String expiresAt; + + Transaction({ + required this.$id, + required this.$createdAt, + required this.$updatedAt, + required this.status, + required this.operations, + required this.expiresAt, + }); + + factory Transaction.fromMap(Map map) { + return Transaction( + $id: map['\$id'].toString(), + $createdAt: map['\$createdAt'].toString(), + $updatedAt: map['\$updatedAt'].toString(), + status: map['status'].toString(), + operations: map['operations'], + expiresAt: map['expiresAt'].toString(), + ); + } + + Map toMap() { + return { + "\$id": $id, + "\$createdAt": $createdAt, + "\$updatedAt": $updatedAt, + "status": status, + "operations": operations, + "expiresAt": expiresAt, + }; + } +} diff --git a/lib/src/models/transaction_list.dart b/lib/src/models/transaction_list.dart new file mode 100644 index 00000000..146e836e --- /dev/null +++ b/lib/src/models/transaction_list.dart @@ -0,0 +1,28 @@ +part of '../../models.dart'; + +/// Transaction List +class TransactionList implements Model { + /// Total number of transactions that matched your query. + final int total; + + /// List of transactions. + final List transactions; + + TransactionList({required this.total, required this.transactions}); + + factory TransactionList.fromMap(Map map) { + return TransactionList( + total: map['total'], + transactions: List.from( + map['transactions'].map((p) => Transaction.fromMap(p)), + ), + ); + } + + Map toMap() { + return { + "total": total, + "transactions": transactions.map((p) => p.toMap()).toList(), + }; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index fbb10dba..7b5d3ce9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: appwrite -version: 20.1.0 +version: 20.2.0 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 homepage: https://appwrite.io repository: https://github.com/appwrite/sdk-for-flutter diff --git a/test/services/databases_test.dart b/test/services/databases_test.dart index aeceecf2..c05a994f 100644 --- a/test/services/databases_test.dart +++ b/test/services/databases_test.dart @@ -55,6 +55,123 @@ void main() { databases = Databases(client); }); + test('test method listTransactions()', () async { + final Map data = { + 'total': 5, + 'transactions': [],}; + + + when(client.call( + HttpMethod.get, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await databases.listTransactions( + ); + expect(response, isA()); + + }); + + test('test method createTransaction()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.post, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await databases.createTransaction( + ); + expect(response, isA()); + + }); + + test('test method getTransaction()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.get, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await databases.getTransaction( + transactionId: '', + ); + expect(response, isA()); + + }); + + test('test method updateTransaction()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.patch, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await databases.updateTransaction( + transactionId: '', + ); + expect(response, isA()); + + }); + + test('test method deleteTransaction()', () async { + final data = ''; + + when(client.call( + HttpMethod.delete, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await databases.deleteTransaction( + transactionId: '', + ); + }); + + test('test method createOperations()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.post, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await databases.createOperations( + transactionId: '', + ); + expect(response, isA()); + + }); + test('test method listDocuments()', () async { final Map data = { 'total': 5, diff --git a/test/services/tables_db_test.dart b/test/services/tables_db_test.dart index 9b11eb45..61964d4c 100644 --- a/test/services/tables_db_test.dart +++ b/test/services/tables_db_test.dart @@ -55,6 +55,123 @@ void main() { tablesDB = TablesDB(client); }); + test('test method listTransactions()', () async { + final Map data = { + 'total': 5, + 'transactions': [],}; + + + when(client.call( + HttpMethod.get, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await tablesDB.listTransactions( + ); + expect(response, isA()); + + }); + + test('test method createTransaction()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.post, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await tablesDB.createTransaction( + ); + expect(response, isA()); + + }); + + test('test method getTransaction()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.get, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await tablesDB.getTransaction( + transactionId: '', + ); + expect(response, isA()); + + }); + + test('test method updateTransaction()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.patch, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await tablesDB.updateTransaction( + transactionId: '', + ); + expect(response, isA()); + + }); + + test('test method deleteTransaction()', () async { + final data = ''; + + when(client.call( + HttpMethod.delete, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await tablesDB.deleteTransaction( + transactionId: '', + ); + }); + + test('test method createOperations()', () async { + final Map data = { + '\$id': '259125845563242502', + '\$createdAt': '2020-10-15T06:38:00.000+00:00', + '\$updatedAt': '2020-10-15T06:38:00.000+00:00', + 'status': 'pending', + 'operations': 5, + 'expiresAt': '2020-10-15T06:38:00.000+00:00',}; + + + when(client.call( + HttpMethod.post, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await tablesDB.createOperations( + transactionId: '', + ); + expect(response, isA()); + + }); + test('test method listRows()', () async { final Map data = { 'total': 5, diff --git a/test/src/models/transaction_list_test.dart b/test/src/models/transaction_list_test.dart new file mode 100644 index 00000000..68023e18 --- /dev/null +++ b/test/src/models/transaction_list_test.dart @@ -0,0 +1,19 @@ +import 'package:appwrite/models.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('TransactionList', () { + test('model', () { + final model = TransactionList( + total: 5, + transactions: [], + ); + + final map = model.toMap(); + final result = TransactionList.fromMap(map); + + expect(result.total, 5); + expect(result.transactions, []); + }); + }); +} diff --git a/test/src/models/transaction_test.dart b/test/src/models/transaction_test.dart new file mode 100644 index 00000000..723ebac2 --- /dev/null +++ b/test/src/models/transaction_test.dart @@ -0,0 +1,27 @@ +import 'package:appwrite/models.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('Transaction', () { + test('model', () { + final model = Transaction( + $id: '259125845563242502', + $createdAt: '2020-10-15T06:38:00.000+00:00', + $updatedAt: '2020-10-15T06:38:00.000+00:00', + status: 'pending', + operations: 5, + expiresAt: '2020-10-15T06:38:00.000+00:00', + ); + + final map = model.toMap(); + final result = Transaction.fromMap(map); + + expect(result.$id, '259125845563242502'); + expect(result.$createdAt, '2020-10-15T06:38:00.000+00:00'); + expect(result.$updatedAt, '2020-10-15T06:38:00.000+00:00'); + expect(result.status, 'pending'); + expect(result.operations, 5); + expect(result.expiresAt, '2020-10-15T06:38:00.000+00:00'); + }); + }); +}