From 7fc802d60ea9ae2a526b43bbd6822c995cac01bb Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 9 Oct 2025 20:25:09 +1300 Subject: [PATCH] Add transactions --- CHANGELOG.md | 4 + README.md | 2 +- Sources/Appwrite/Client.swift | 2 +- Sources/Appwrite/Services/Databases.swift | 321 ++++++++++++++++-- Sources/Appwrite/Services/TablesDb.swift | 319 +++++++++++++++-- Sources/AppwriteModels/Transaction.swift | 94 +++++ Sources/AppwriteModels/TransactionList.swift | 54 +++ docs/examples/databases/create-document.md | 3 +- docs/examples/databases/create-documents.md | 3 +- docs/examples/databases/create-operations.md | 24 ++ docs/examples/databases/create-transaction.md | 13 + .../databases/decrement-document-attribute.md | 3 +- docs/examples/databases/delete-document.md | 3 +- docs/examples/databases/delete-documents.md | 3 +- docs/examples/databases/delete-transaction.md | 13 + docs/examples/databases/get-document.md | 3 +- docs/examples/databases/get-transaction.md | 13 + .../databases/increment-document-attribute.md | 3 +- docs/examples/databases/list-documents.md | 3 +- docs/examples/databases/list-transactions.md | 13 + docs/examples/databases/update-document.md | 3 +- docs/examples/databases/update-documents.md | 3 +- docs/examples/databases/update-transaction.md | 15 + docs/examples/databases/upsert-document.md | 3 +- docs/examples/databases/upsert-documents.md | 3 +- docs/examples/messaging/create-push.md | 2 +- docs/examples/messaging/update-push.md | 2 +- docs/examples/tablesdb/create-operations.md | 24 ++ docs/examples/tablesdb/create-row.md | 3 +- docs/examples/tablesdb/create-rows.md | 3 +- docs/examples/tablesdb/create-transaction.md | 13 + .../examples/tablesdb/decrement-row-column.md | 3 +- docs/examples/tablesdb/delete-row.md | 3 +- docs/examples/tablesdb/delete-rows.md | 3 +- docs/examples/tablesdb/delete-transaction.md | 13 + docs/examples/tablesdb/get-row.md | 3 +- docs/examples/tablesdb/get-transaction.md | 13 + .../examples/tablesdb/increment-row-column.md | 3 +- docs/examples/tablesdb/list-rows.md | 3 +- docs/examples/tablesdb/list-transactions.md | 13 + docs/examples/tablesdb/update-row.md | 3 +- docs/examples/tablesdb/update-rows.md | 3 +- docs/examples/tablesdb/update-transaction.md | 15 + docs/examples/tablesdb/upsert-row.md | 3 +- docs/examples/tablesdb/upsert-rows.md | 3 +- 45 files changed, 977 insertions(+), 77 deletions(-) create mode 100644 Sources/AppwriteModels/Transaction.swift create mode 100644 Sources/AppwriteModels/TransactionList.swift create mode 100644 docs/examples/databases/create-operations.md create mode 100644 docs/examples/databases/create-transaction.md create mode 100644 docs/examples/databases/delete-transaction.md create mode 100644 docs/examples/databases/get-transaction.md create mode 100644 docs/examples/databases/list-transactions.md create mode 100644 docs/examples/databases/update-transaction.md create mode 100644 docs/examples/tablesdb/create-operations.md create mode 100644 docs/examples/tablesdb/create-transaction.md create mode 100644 docs/examples/tablesdb/delete-transaction.md create mode 100644 docs/examples/tablesdb/get-transaction.md create mode 100644 docs/examples/tablesdb/list-transactions.md create mode 100644 docs/examples/tablesdb/update-transaction.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d73a86..0d384b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 13.2.0 + +* Add transaction support for Databases and TablesDB + ## 13.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/README.md b/README.md index c3f4c35..2f4030d 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Add the package to your `Package.swift` dependencies: ```swift dependencies: [ - .package(url: "git@github.com:appwrite/sdk-for-swift.git", from: "13.1.0"), + .package(url: "git@github.com:appwrite/sdk-for-swift.git", from: "13.2.0"), ], ``` diff --git a/Sources/Appwrite/Client.swift b/Sources/Appwrite/Client.swift index 39905ff..570386f 100644 --- a/Sources/Appwrite/Client.swift +++ b/Sources/Appwrite/Client.swift @@ -21,7 +21,7 @@ open class Client { "x-sdk-name": "Swift", "x-sdk-platform": "server", "x-sdk-language": "swift", - "x-sdk-version": "13.1.0", + "x-sdk-version": "13.2.0", "x-appwrite-response-format": "1.8.0" ] diff --git a/Sources/Appwrite/Services/Databases.swift b/Sources/Appwrite/Services/Databases.swift index 03c7f4a..4a450f8 100644 --- a/Sources/Appwrite/Services/Databases.swift +++ b/Sources/Appwrite/Services/Databases.swift @@ -87,6 +87,207 @@ open class Databases: Service { ) } + /// + /// List transactions across all databases. + /// + /// - Parameters: + /// - queries: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.TransactionList + /// + open func listTransactions( + queries: [String]? = nil + ) async throws -> AppwriteModels.TransactionList { + let apiPath: String = "/databases/transactions" + + let apiParams: [String: Any?] = [ + "queries": queries + ] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.TransactionList = { response in + return AppwriteModels.TransactionList.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Create a new transaction. + /// + /// - Parameters: + /// - ttl: Int (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func createTransaction( + ttl: Int? = nil + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/databases/transactions" + + let apiParams: [String: Any?] = [ + "ttl": ttl + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Get a transaction by its unique ID. + /// + /// - Parameters: + /// - transactionId: String + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func getTransaction( + transactionId: String + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/databases/transactions/{transactionId}" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Update a transaction, to either commit or roll back its operations. + /// + /// - Parameters: + /// - transactionId: String + /// - commit: Bool (optional) + /// - rollback: Bool (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func updateTransaction( + transactionId: String, + commit: Bool? = nil, + rollback: Bool? = nil + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/databases/transactions/{transactionId}" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any?] = [ + "commit": commit, + "rollback": rollback + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PATCH", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Delete a transaction by its unique ID. + /// + /// - Parameters: + /// - transactionId: String + /// - Throws: Exception if the request fails + /// - Returns: Any + /// + open func deleteTransaction( + transactionId: String + ) async throws -> Any { + let apiPath: String = "/databases/transactions/{transactionId}" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + return try await client.call( + method: "DELETE", + path: apiPath, + headers: apiHeaders, + params: apiParams ) + } + + /// + /// Create multiple operations in a single transaction. + /// + /// - Parameters: + /// - transactionId: String + /// - operations: [Any] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func createOperations( + transactionId: String, + operations: [Any]? = nil + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/databases/transactions/{transactionId}/operations" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any?] = [ + "operations": operations + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Get a database by its unique ID. This endpoint response returns a JSON /// object with the database metadata. @@ -1881,6 +2082,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -1889,6 +2091,7 @@ open class Databases: Service { databaseId: String, collectionId: String, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.DocumentList { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents" @@ -1896,7 +2099,8 @@ open class Databases: Service { .replacingOccurrences(of: "{collectionId}", with: collectionId) let apiParams: [String: Any?] = [ - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [:] @@ -1922,6 +2126,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -1929,12 +2134,14 @@ open class Databases: Service { open func listDocuments( databaseId: String, collectionId: String, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.DocumentList<[String: AnyCodable]> { return try await listDocuments( databaseId: databaseId, collectionId: collectionId, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -1951,6 +2158,7 @@ open class Databases: Service { /// - documentId: String /// - data: Any /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -1961,6 +2169,7 @@ open class Databases: Service { documentId: String, data: Any, permissions: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Document { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents" @@ -1970,7 +2179,8 @@ open class Databases: Service { let apiParams: [String: Any?] = [ "documentId": documentId, "data": data, - "permissions": permissions + "permissions": permissions, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2002,6 +2212,7 @@ open class Databases: Service { /// - documentId: String /// - data: Any /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2011,7 +2222,8 @@ open class Databases: Service { collectionId: String, documentId: String, data: Any, - permissions: [String]? = nil + permissions: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Document<[String: AnyCodable]> { return try await createDocument( databaseId: databaseId, @@ -2019,6 +2231,7 @@ open class Databases: Service { documentId: documentId, data: data, permissions: permissions, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2033,6 +2246,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - documents: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2041,6 +2255,7 @@ open class Databases: Service { databaseId: String, collectionId: String, documents: [Any], + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.DocumentList { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents" @@ -2048,7 +2263,8 @@ open class Databases: Service { .replacingOccurrences(of: "{collectionId}", with: collectionId) let apiParams: [String: Any?] = [ - "documents": documents + "documents": documents, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2078,6 +2294,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - documents: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2085,12 +2302,14 @@ open class Databases: Service { open func createDocuments( databaseId: String, collectionId: String, - documents: [Any] + documents: [Any], + transactionId: String? = nil ) async throws -> AppwriteModels.DocumentList<[String: AnyCodable]> { return try await createDocuments( databaseId: databaseId, collectionId: collectionId, documents: documents, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2106,6 +2325,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - documents: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2114,6 +2334,7 @@ open class Databases: Service { databaseId: String, collectionId: String, documents: [Any], + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.DocumentList { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents" @@ -2121,7 +2342,8 @@ open class Databases: Service { .replacingOccurrences(of: "{collectionId}", with: collectionId) let apiParams: [String: Any?] = [ - "documents": documents + "documents": documents, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2152,6 +2374,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - documents: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2159,12 +2382,14 @@ open class Databases: Service { open func upsertDocuments( databaseId: String, collectionId: String, - documents: [Any] + documents: [Any], + transactionId: String? = nil ) async throws -> AppwriteModels.DocumentList<[String: AnyCodable]> { return try await upsertDocuments( databaseId: databaseId, collectionId: collectionId, documents: documents, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2179,6 +2404,7 @@ open class Databases: Service { /// - collectionId: String /// - data: Any (optional) /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2188,6 +2414,7 @@ open class Databases: Service { collectionId: String, data: Any? = nil, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.DocumentList { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents" @@ -2196,7 +2423,8 @@ open class Databases: Service { let apiParams: [String: Any?] = [ "data": data, - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2226,6 +2454,7 @@ open class Databases: Service { /// - collectionId: String /// - data: Any (optional) /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2234,13 +2463,15 @@ open class Databases: Service { databaseId: String, collectionId: String, data: Any? = nil, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.DocumentList<[String: AnyCodable]> { return try await updateDocuments( databaseId: databaseId, collectionId: collectionId, data: data, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2253,6 +2484,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2261,6 +2493,7 @@ open class Databases: Service { databaseId: String, collectionId: String, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.DocumentList { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents" @@ -2268,7 +2501,8 @@ open class Databases: Service { .replacingOccurrences(of: "{collectionId}", with: collectionId) let apiParams: [String: Any?] = [ - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2296,6 +2530,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// @@ -2303,12 +2538,14 @@ open class Databases: Service { open func deleteDocuments( databaseId: String, collectionId: String, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.DocumentList<[String: AnyCodable]> { return try await deleteDocuments( databaseId: databaseId, collectionId: collectionId, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2322,6 +2559,7 @@ open class Databases: Service { /// - collectionId: String /// - documentId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2331,6 +2569,7 @@ open class Databases: Service { collectionId: String, documentId: String, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Document { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents/{documentId}" @@ -2339,7 +2578,8 @@ open class Databases: Service { .replacingOccurrences(of: "{documentId}", with: documentId) let apiParams: [String: Any?] = [ - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [:] @@ -2366,6 +2606,7 @@ open class Databases: Service { /// - collectionId: String /// - documentId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2374,13 +2615,15 @@ open class Databases: Service { databaseId: String, collectionId: String, documentId: String, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Document<[String: AnyCodable]> { return try await getDocument( databaseId: databaseId, collectionId: collectionId, documentId: documentId, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2397,6 +2640,7 @@ open class Databases: Service { /// - documentId: String /// - data: Any /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2407,6 +2651,7 @@ open class Databases: Service { documentId: String, data: Any, permissions: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Document { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents/{documentId}" @@ -2416,7 +2661,8 @@ open class Databases: Service { let apiParams: [String: Any?] = [ "data": data, - "permissions": permissions + "permissions": permissions, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2448,6 +2694,7 @@ open class Databases: Service { /// - documentId: String /// - data: Any /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2457,7 +2704,8 @@ open class Databases: Service { collectionId: String, documentId: String, data: Any, - permissions: [String]? = nil + permissions: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Document<[String: AnyCodable]> { return try await upsertDocument( databaseId: databaseId, @@ -2465,6 +2713,7 @@ open class Databases: Service { documentId: documentId, data: data, permissions: permissions, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2479,6 +2728,7 @@ open class Databases: Service { /// - documentId: String /// - data: Any (optional) /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2489,6 +2739,7 @@ open class Databases: Service { documentId: String, data: Any? = nil, permissions: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Document { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents/{documentId}" @@ -2498,7 +2749,8 @@ open class Databases: Service { let apiParams: [String: Any?] = [ "data": data, - "permissions": permissions + "permissions": permissions, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2528,6 +2780,7 @@ open class Databases: Service { /// - documentId: String /// - data: Any (optional) /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2537,7 +2790,8 @@ open class Databases: Service { collectionId: String, documentId: String, data: Any? = nil, - permissions: [String]? = nil + permissions: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Document<[String: AnyCodable]> { return try await updateDocument( databaseId: databaseId, @@ -2545,6 +2799,7 @@ open class Databases: Service { documentId: documentId, data: data, permissions: permissions, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2556,6 +2811,7 @@ open class Databases: Service { /// - databaseId: String /// - collectionId: String /// - documentId: String + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: Any /// @@ -2563,14 +2819,17 @@ open class Databases: Service { open func deleteDocument( databaseId: String, collectionId: String, - documentId: String + documentId: String, + transactionId: String? = nil ) async throws -> Any { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents/{documentId}" .replacingOccurrences(of: "{databaseId}", with: databaseId) .replacingOccurrences(of: "{collectionId}", with: collectionId) .replacingOccurrences(of: "{documentId}", with: documentId) - let apiParams: [String: Any] = [:] + let apiParams: [String: Any?] = [ + "transactionId": transactionId + ] let apiHeaders: [String: String] = [ "content-type": "application/json" @@ -2593,6 +2852,7 @@ open class Databases: Service { /// - attribute: String /// - value: Double (optional) /// - min: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2604,6 +2864,7 @@ open class Databases: Service { attribute: String, value: Double? = nil, min: Double? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Document { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/decrement" @@ -2614,7 +2875,8 @@ open class Databases: Service { let apiParams: [String: Any?] = [ "value": value, - "min": min + "min": min, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2644,6 +2906,7 @@ open class Databases: Service { /// - attribute: String /// - value: Double (optional) /// - min: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2654,7 +2917,8 @@ open class Databases: Service { documentId: String, attribute: String, value: Double? = nil, - min: Double? = nil + min: Double? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Document<[String: AnyCodable]> { return try await decrementDocumentAttribute( databaseId: databaseId, @@ -2663,6 +2927,7 @@ open class Databases: Service { attribute: attribute, value: value, min: min, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2677,6 +2942,7 @@ open class Databases: Service { /// - attribute: String /// - value: Double (optional) /// - max: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2688,6 +2954,7 @@ open class Databases: Service { attribute: String, value: Double? = nil, max: Double? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Document { let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/increment" @@ -2698,7 +2965,8 @@ open class Databases: Service { let apiParams: [String: Any?] = [ "value": value, - "max": max + "max": max, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2728,6 +2996,7 @@ open class Databases: Service { /// - attribute: String /// - value: Double (optional) /// - max: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// @@ -2738,7 +3007,8 @@ open class Databases: Service { documentId: String, attribute: String, value: Double? = nil, - max: Double? = nil + max: Double? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Document<[String: AnyCodable]> { return try await incrementDocumentAttribute( databaseId: databaseId, @@ -2747,6 +3017,7 @@ open class Databases: Service { attribute: attribute, value: value, max: max, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2846,7 +3117,7 @@ open class Databases: Service { } /// - /// Get index by ID. + /// Get an index by its unique ID. /// /// - Parameters: /// - databaseId: String diff --git a/Sources/Appwrite/Services/TablesDb.swift b/Sources/Appwrite/Services/TablesDb.swift index 56cdf05..fcc344d 100644 --- a/Sources/Appwrite/Services/TablesDb.swift +++ b/Sources/Appwrite/Services/TablesDb.swift @@ -85,6 +85,207 @@ open class TablesDB: Service { ) } + /// + /// List transactions across all databases. + /// + /// - Parameters: + /// - queries: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.TransactionList + /// + open func listTransactions( + queries: [String]? = nil + ) async throws -> AppwriteModels.TransactionList { + let apiPath: String = "/tablesdb/transactions" + + let apiParams: [String: Any?] = [ + "queries": queries + ] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.TransactionList = { response in + return AppwriteModels.TransactionList.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Create a new transaction. + /// + /// - Parameters: + /// - ttl: Int (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func createTransaction( + ttl: Int? = nil + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/tablesdb/transactions" + + let apiParams: [String: Any?] = [ + "ttl": ttl + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Get a transaction by its unique ID. + /// + /// - Parameters: + /// - transactionId: String + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func getTransaction( + transactionId: String + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/tablesdb/transactions/{transactionId}" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Update a transaction, to either commit or roll back its operations. + /// + /// - Parameters: + /// - transactionId: String + /// - commit: Bool (optional) + /// - rollback: Bool (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func updateTransaction( + transactionId: String, + commit: Bool? = nil, + rollback: Bool? = nil + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/tablesdb/transactions/{transactionId}" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any?] = [ + "commit": commit, + "rollback": rollback + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PATCH", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Delete a transaction by its unique ID. + /// + /// - Parameters: + /// - transactionId: String + /// - Throws: Exception if the request fails + /// - Returns: Any + /// + open func deleteTransaction( + transactionId: String + ) async throws -> Any { + let apiPath: String = "/tablesdb/transactions/{transactionId}" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + return try await client.call( + method: "DELETE", + path: apiPath, + headers: apiHeaders, + params: apiParams ) + } + + /// + /// Create multiple operations in a single transaction. + /// + /// - Parameters: + /// - transactionId: String + /// - operations: [Any] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Transaction + /// + open func createOperations( + transactionId: String, + operations: [Any]? = nil + ) async throws -> AppwriteModels.Transaction { + let apiPath: String = "/tablesdb/transactions/{transactionId}/operations" + .replacingOccurrences(of: "{transactionId}", with: transactionId) + + let apiParams: [String: Any?] = [ + "operations": operations + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Transaction = { response in + return AppwriteModels.Transaction.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Get a database by its unique ID. This endpoint response returns a JSON /// object with the database metadata. @@ -2003,6 +2204,7 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// @@ -2010,6 +2212,7 @@ open class TablesDB: Service { databaseId: String, tableId: String, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.RowList { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" @@ -2017,7 +2220,8 @@ open class TablesDB: Service { .replacingOccurrences(of: "{tableId}", with: tableId) let apiParams: [String: Any?] = [ - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [:] @@ -2043,18 +2247,21 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// open func listRows( databaseId: String, tableId: String, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.RowList<[String: AnyCodable]> { return try await listRows( databaseId: databaseId, tableId: tableId, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2071,6 +2278,7 @@ open class TablesDB: Service { /// - rowId: String /// - data: Any /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2080,6 +2288,7 @@ open class TablesDB: Service { rowId: String, data: Any, permissions: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Row { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" @@ -2089,7 +2298,8 @@ open class TablesDB: Service { let apiParams: [String: Any?] = [ "rowId": rowId, "data": data, - "permissions": permissions + "permissions": permissions, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2121,6 +2331,7 @@ open class TablesDB: Service { /// - rowId: String /// - data: Any /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2129,7 +2340,8 @@ open class TablesDB: Service { tableId: String, rowId: String, data: Any, - permissions: [String]? = nil + permissions: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { return try await createRow( databaseId: databaseId, @@ -2137,6 +2349,7 @@ open class TablesDB: Service { rowId: rowId, data: data, permissions: permissions, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2151,6 +2364,7 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - rows: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// @@ -2158,6 +2372,7 @@ open class TablesDB: Service { databaseId: String, tableId: String, rows: [Any], + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.RowList { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" @@ -2165,7 +2380,8 @@ open class TablesDB: Service { .replacingOccurrences(of: "{tableId}", with: tableId) let apiParams: [String: Any?] = [ - "rows": rows + "rows": rows, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2195,18 +2411,21 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - rows: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// open func createRows( databaseId: String, tableId: String, - rows: [Any] + rows: [Any], + transactionId: String? = nil ) async throws -> AppwriteModels.RowList<[String: AnyCodable]> { return try await createRows( databaseId: databaseId, tableId: tableId, rows: rows, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2222,6 +2441,7 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - rows: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// @@ -2229,6 +2449,7 @@ open class TablesDB: Service { databaseId: String, tableId: String, rows: [Any], + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.RowList { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" @@ -2236,7 +2457,8 @@ open class TablesDB: Service { .replacingOccurrences(of: "{tableId}", with: tableId) let apiParams: [String: Any?] = [ - "rows": rows + "rows": rows, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2267,18 +2489,21 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - rows: [Any] + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// open func upsertRows( databaseId: String, tableId: String, - rows: [Any] + rows: [Any], + transactionId: String? = nil ) async throws -> AppwriteModels.RowList<[String: AnyCodable]> { return try await upsertRows( databaseId: databaseId, tableId: tableId, rows: rows, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2292,6 +2517,7 @@ open class TablesDB: Service { /// - tableId: String /// - data: Any (optional) /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// @@ -2300,6 +2526,7 @@ open class TablesDB: Service { tableId: String, data: Any? = nil, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.RowList { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" @@ -2308,7 +2535,8 @@ open class TablesDB: Service { let apiParams: [String: Any?] = [ "data": data, - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2337,6 +2565,7 @@ open class TablesDB: Service { /// - tableId: String /// - data: Any (optional) /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// @@ -2344,13 +2573,15 @@ open class TablesDB: Service { databaseId: String, tableId: String, data: Any? = nil, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.RowList<[String: AnyCodable]> { return try await updateRows( databaseId: databaseId, tableId: tableId, data: data, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2363,6 +2594,7 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// @@ -2370,6 +2602,7 @@ open class TablesDB: Service { databaseId: String, tableId: String, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.RowList { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" @@ -2377,7 +2610,8 @@ open class TablesDB: Service { .replacingOccurrences(of: "{tableId}", with: tableId) let apiParams: [String: Any?] = [ - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2405,18 +2639,21 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.RowList /// open func deleteRows( databaseId: String, tableId: String, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.RowList<[String: AnyCodable]> { return try await deleteRows( databaseId: databaseId, tableId: tableId, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2430,6 +2667,7 @@ open class TablesDB: Service { /// - tableId: String /// - rowId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2438,6 +2676,7 @@ open class TablesDB: Service { tableId: String, rowId: String, queries: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Row { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}" @@ -2446,7 +2685,8 @@ open class TablesDB: Service { .replacingOccurrences(of: "{rowId}", with: rowId) let apiParams: [String: Any?] = [ - "queries": queries + "queries": queries, + "transactionId": transactionId ] let apiHeaders: [String: String] = [:] @@ -2473,6 +2713,7 @@ open class TablesDB: Service { /// - tableId: String /// - rowId: String /// - queries: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2480,13 +2721,15 @@ open class TablesDB: Service { databaseId: String, tableId: String, rowId: String, - queries: [String]? = nil + queries: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { return try await getRow( databaseId: databaseId, tableId: tableId, rowId: rowId, queries: queries, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2503,6 +2746,7 @@ open class TablesDB: Service { /// - rowId: String /// - data: Any (optional) /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2512,6 +2756,7 @@ open class TablesDB: Service { rowId: String, data: Any? = nil, permissions: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Row { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}" @@ -2521,7 +2766,8 @@ open class TablesDB: Service { let apiParams: [String: Any?] = [ "data": data, - "permissions": permissions + "permissions": permissions, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2553,6 +2799,7 @@ open class TablesDB: Service { /// - rowId: String /// - data: Any (optional) /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2561,7 +2808,8 @@ open class TablesDB: Service { tableId: String, rowId: String, data: Any? = nil, - permissions: [String]? = nil + permissions: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { return try await upsertRow( databaseId: databaseId, @@ -2569,6 +2817,7 @@ open class TablesDB: Service { rowId: rowId, data: data, permissions: permissions, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2583,6 +2832,7 @@ open class TablesDB: Service { /// - rowId: String /// - data: Any (optional) /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2592,6 +2842,7 @@ open class TablesDB: Service { rowId: String, data: Any? = nil, permissions: [String]? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Row { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}" @@ -2601,7 +2852,8 @@ open class TablesDB: Service { let apiParams: [String: Any?] = [ "data": data, - "permissions": permissions + "permissions": permissions, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2631,6 +2883,7 @@ open class TablesDB: Service { /// - rowId: String /// - data: Any (optional) /// - permissions: [String] (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2639,7 +2892,8 @@ open class TablesDB: Service { tableId: String, rowId: String, data: Any? = nil, - permissions: [String]? = nil + permissions: [String]? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { return try await updateRow( databaseId: databaseId, @@ -2647,6 +2901,7 @@ open class TablesDB: Service { rowId: rowId, data: data, permissions: permissions, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2658,20 +2913,24 @@ open class TablesDB: Service { /// - databaseId: String /// - tableId: String /// - rowId: String + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: Any /// open func deleteRow( databaseId: String, tableId: String, - rowId: String + rowId: String, + transactionId: String? = nil ) async throws -> Any { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}" .replacingOccurrences(of: "{databaseId}", with: databaseId) .replacingOccurrences(of: "{tableId}", with: tableId) .replacingOccurrences(of: "{rowId}", with: rowId) - let apiParams: [String: Any] = [:] + let apiParams: [String: Any?] = [ + "transactionId": transactionId + ] let apiHeaders: [String: String] = [ "content-type": "application/json" @@ -2694,6 +2953,7 @@ open class TablesDB: Service { /// - column: String /// - value: Double (optional) /// - min: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2704,6 +2964,7 @@ open class TablesDB: Service { column: String, value: Double? = nil, min: Double? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Row { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/decrement" @@ -2714,7 +2975,8 @@ open class TablesDB: Service { let apiParams: [String: Any?] = [ "value": value, - "min": min + "min": min, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2744,6 +3006,7 @@ open class TablesDB: Service { /// - column: String /// - value: Double (optional) /// - min: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2753,7 +3016,8 @@ open class TablesDB: Service { rowId: String, column: String, value: Double? = nil, - min: Double? = nil + min: Double? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { return try await decrementRowColumn( databaseId: databaseId, @@ -2762,6 +3026,7 @@ open class TablesDB: Service { column: column, value: value, min: min, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } @@ -2776,6 +3041,7 @@ open class TablesDB: Service { /// - column: String /// - value: Double (optional) /// - max: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2786,6 +3052,7 @@ open class TablesDB: Service { column: String, value: Double? = nil, max: Double? = nil, + transactionId: String? = nil, nestedType: T.Type ) async throws -> AppwriteModels.Row { let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/increment" @@ -2796,7 +3063,8 @@ open class TablesDB: Service { let apiParams: [String: Any?] = [ "value": value, - "max": max + "max": max, + "transactionId": transactionId ] let apiHeaders: [String: String] = [ @@ -2826,6 +3094,7 @@ open class TablesDB: Service { /// - column: String /// - value: Double (optional) /// - max: Double (optional) + /// - transactionId: String (optional) /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Row /// @@ -2835,7 +3104,8 @@ open class TablesDB: Service { rowId: String, column: String, value: Double? = nil, - max: Double? = nil + max: Double? = nil, + transactionId: String? = nil ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { return try await incrementRowColumn( databaseId: databaseId, @@ -2844,6 +3114,7 @@ open class TablesDB: Service { column: column, value: value, max: max, + transactionId: transactionId, nestedType: [String: AnyCodable].self ) } diff --git a/Sources/AppwriteModels/Transaction.swift b/Sources/AppwriteModels/Transaction.swift new file mode 100644 index 0000000..584c4c3 --- /dev/null +++ b/Sources/AppwriteModels/Transaction.swift @@ -0,0 +1,94 @@ +import Foundation +import JSONCodable + +/// Transaction +open class Transaction: Codable { + + enum CodingKeys: String, CodingKey { + case id = "$id" + case createdAt = "$createdAt" + case updatedAt = "$updatedAt" + case status = "status" + case operations = "operations" + case expiresAt = "expiresAt" + } + + /// Transaction ID. + public let id: String + + /// Transaction creation time in ISO 8601 format. + public let createdAt: String + + /// Transaction update date in ISO 8601 format. + public let updatedAt: String + + /// Current status of the transaction. One of: pending, committing, committed, rolled_back, failed. + public let status: String + + /// Number of operations in the transaction. + public let operations: Int + + /// Expiration time in ISO 8601 format. + public let expiresAt: String + + + init( + id: String, + createdAt: String, + updatedAt: String, + status: String, + operations: Int, + expiresAt: String + ) { + self.id = id + self.createdAt = createdAt + self.updatedAt = updatedAt + self.status = status + self.operations = operations + self.expiresAt = expiresAt + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.id = try container.decode(String.self, forKey: .id) + self.createdAt = try container.decode(String.self, forKey: .createdAt) + self.updatedAt = try container.decode(String.self, forKey: .updatedAt) + self.status = try container.decode(String.self, forKey: .status) + self.operations = try container.decode(Int.self, forKey: .operations) + self.expiresAt = try container.decode(String.self, forKey: .expiresAt) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(id, forKey: .id) + try container.encode(createdAt, forKey: .createdAt) + try container.encode(updatedAt, forKey: .updatedAt) + try container.encode(status, forKey: .status) + try container.encode(operations, forKey: .operations) + try container.encode(expiresAt, forKey: .expiresAt) + } + + public func toMap() -> [String: Any] { + return [ + "$id": id as Any, + "$createdAt": createdAt as Any, + "$updatedAt": updatedAt as Any, + "status": status as Any, + "operations": operations as Any, + "expiresAt": expiresAt as Any + ] + } + + public static func from(map: [String: Any] ) -> Transaction { + return Transaction( + id: map["$id"] as! String, + createdAt: map["$createdAt"] as! String, + updatedAt: map["$updatedAt"] as! String, + status: map["status"] as! String, + operations: map["operations"] as! Int, + expiresAt: map["expiresAt"] as! String + ) + } +} diff --git a/Sources/AppwriteModels/TransactionList.swift b/Sources/AppwriteModels/TransactionList.swift new file mode 100644 index 0000000..49a976a --- /dev/null +++ b/Sources/AppwriteModels/TransactionList.swift @@ -0,0 +1,54 @@ +import Foundation +import JSONCodable + +/// Transaction List +open class TransactionList: Codable { + + enum CodingKeys: String, CodingKey { + case total = "total" + case transactions = "transactions" + } + + /// Total number of transactions that matched your query. + public let total: Int + + /// List of transactions. + public let transactions: [Transaction] + + + init( + total: Int, + transactions: [Transaction] + ) { + self.total = total + self.transactions = transactions + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.total = try container.decode(Int.self, forKey: .total) + self.transactions = try container.decode([Transaction].self, forKey: .transactions) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(total, forKey: .total) + try container.encode(transactions, forKey: .transactions) + } + + public func toMap() -> [String: Any] { + return [ + "total": total as Any, + "transactions": transactions.map { $0.toMap() } as Any + ] + } + + public static func from(map: [String: Any] ) -> TransactionList { + return TransactionList( + total: map["total"] as! Int, + transactions: (map["transactions"] as! [[String: Any]]).map { Transaction.from(map: $0) } + ) + } +} diff --git a/docs/examples/databases/create-document.md b/docs/examples/databases/create-document.md index cc25fd8..604bacd 100644 --- a/docs/examples/databases/create-document.md +++ b/docs/examples/databases/create-document.md @@ -18,6 +18,7 @@ let document = try await databases.createDocument( "age": 30, "isAdmin": false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/databases/create-documents.md b/docs/examples/databases/create-documents.md index 2e992d9..82a7512 100644 --- a/docs/examples/databases/create-documents.md +++ b/docs/examples/databases/create-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.createDocuments( databaseId: "", collectionId: "", - documents: [] + documents: [], + transactionId: "" // optional ) diff --git a/docs/examples/databases/create-operations.md b/docs/examples/databases/create-operations.md new file mode 100644 index 0000000..7cab190 --- /dev/null +++ b/docs/examples/databases/create-operations.md @@ -0,0 +1,24 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try 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 0000000..333632c --- /dev/null +++ b/docs/examples/databases/create-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try 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 81516fa..8c256ad 100644 --- a/docs/examples/databases/decrement-document-attribute.md +++ b/docs/examples/databases/decrement-document-attribute.md @@ -13,6 +13,7 @@ let document = try await databases.decrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/databases/delete-document.md b/docs/examples/databases/delete-document.md index 1db5970..9120c3d 100644 --- a/docs/examples/databases/delete-document.md +++ b/docs/examples/databases/delete-document.md @@ -10,6 +10,7 @@ let databases = Databases(client) let result = try await databases.deleteDocument( databaseId: "", collectionId: "", - documentId: "" + documentId: "", + transactionId: "" // optional ) diff --git a/docs/examples/databases/delete-documents.md b/docs/examples/databases/delete-documents.md index d5321f2..79ec772 100644 --- a/docs/examples/databases/delete-documents.md +++ b/docs/examples/databases/delete-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.deleteDocuments( databaseId: "", collectionId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/databases/delete-transaction.md b/docs/examples/databases/delete-transaction.md new file mode 100644 index 0000000..8ac62ef --- /dev/null +++ b/docs/examples/databases/delete-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let result = try await databases.deleteTransaction( + transactionId: "" +) + diff --git a/docs/examples/databases/get-document.md b/docs/examples/databases/get-document.md index c92856a..319a7ec 100644 --- a/docs/examples/databases/get-document.md +++ b/docs/examples/databases/get-document.md @@ -11,6 +11,7 @@ let document = try await databases.getDocument( databaseId: "", collectionId: "", documentId: "", - queries: [] // optional + 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 0000000..bfabd08 --- /dev/null +++ b/docs/examples/databases/get-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try await databases.getTransaction( + transactionId: "" +) + diff --git a/docs/examples/databases/increment-document-attribute.md b/docs/examples/databases/increment-document-attribute.md index 64ba46b..7dd8805 100644 --- a/docs/examples/databases/increment-document-attribute.md +++ b/docs/examples/databases/increment-document-attribute.md @@ -13,6 +13,7 @@ let document = try await databases.incrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/databases/list-documents.md b/docs/examples/databases/list-documents.md index 2cac933..1147530 100644 --- a/docs/examples/databases/list-documents.md +++ b/docs/examples/databases/list-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.listDocuments( databaseId: "", collectionId: "", - queries: [] // optional + 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 0000000..bb0d852 --- /dev/null +++ b/docs/examples/databases/list-transactions.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transactionList = try await databases.listTransactions( + queries: [] // optional +) + diff --git a/docs/examples/databases/update-document.md b/docs/examples/databases/update-document.md index 7d452db..b6260d7 100644 --- a/docs/examples/databases/update-document.md +++ b/docs/examples/databases/update-document.md @@ -12,6 +12,7 @@ let document = try await databases.updateDocument( collectionId: "", documentId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/databases/update-documents.md b/docs/examples/databases/update-documents.md index 0e934b1..f1fb34a 100644 --- a/docs/examples/databases/update-documents.md +++ b/docs/examples/databases/update-documents.md @@ -11,6 +11,7 @@ let documentList = try await databases.updateDocuments( databaseId: "", collectionId: "", data: [:], // optional - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/databases/update-transaction.md b/docs/examples/databases/update-transaction.md new file mode 100644 index 0000000..79f4939 --- /dev/null +++ b/docs/examples/databases/update-transaction.md @@ -0,0 +1,15 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try 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 e78bd45..26897f4 100644 --- a/docs/examples/databases/upsert-document.md +++ b/docs/examples/databases/upsert-document.md @@ -12,6 +12,7 @@ let document = try await databases.upsertDocument( collectionId: "", documentId: "", data: [:], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/databases/upsert-documents.md b/docs/examples/databases/upsert-documents.md index 544f02f..92c5fd9 100644 --- a/docs/examples/databases/upsert-documents.md +++ b/docs/examples/databases/upsert-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.upsertDocuments( databaseId: "", collectionId: "", - documents: [] + documents: [], + transactionId: "" // optional ) diff --git a/docs/examples/messaging/create-push.md b/docs/examples/messaging/create-push.md index 498eccb..ba03b33 100644 --- a/docs/examples/messaging/create-push.md +++ b/docs/examples/messaging/create-push.md @@ -17,7 +17,7 @@ let message = try await messaging.createPush( targets: [], // optional data: [:], // optional action: "", // optional - image: "[ID1:ID2]", // optional + image: "", // optional icon: "", // optional sound: "", // optional color: "", // optional diff --git a/docs/examples/messaging/update-push.md b/docs/examples/messaging/update-push.md index e443161..b7b5bb0 100644 --- a/docs/examples/messaging/update-push.md +++ b/docs/examples/messaging/update-push.md @@ -17,7 +17,7 @@ let message = try await messaging.updatePush( body: "", // optional data: [:], // optional action: "", // optional - image: "[ID1:ID2]", // optional + image: "", // optional icon: "", // optional sound: "", // optional color: "", // optional diff --git a/docs/examples/tablesdb/create-operations.md b/docs/examples/tablesdb/create-operations.md new file mode 100644 index 0000000..5ee356e --- /dev/null +++ b/docs/examples/tablesdb/create-operations.md @@ -0,0 +1,24 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try 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 0c59a65..049ef2d 100644 --- a/docs/examples/tablesdb/create-row.md +++ b/docs/examples/tablesdb/create-row.md @@ -18,6 +18,7 @@ let row = try await tablesDB.createRow( "age": 30, "isAdmin": false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/create-rows.md b/docs/examples/tablesdb/create-rows.md index 25ea512..63fafbd 100644 --- a/docs/examples/tablesdb/create-rows.md +++ b/docs/examples/tablesdb/create-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.createRows( databaseId: "", tableId: "", - rows: [] + rows: [], + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/create-transaction.md b/docs/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000..d826446 --- /dev/null +++ b/docs/examples/tablesdb/create-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try 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 196289e..9c33055 100644 --- a/docs/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/tablesdb/decrement-row-column.md @@ -13,6 +13,7 @@ let row = try await tablesDB.decrementRowColumn( rowId: "", column: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/delete-row.md b/docs/examples/tablesdb/delete-row.md index 5449c74..a0a96ee 100644 --- a/docs/examples/tablesdb/delete-row.md +++ b/docs/examples/tablesdb/delete-row.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let result = try await tablesDB.deleteRow( databaseId: "", tableId: "", - rowId: "" + rowId: "", + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/delete-rows.md b/docs/examples/tablesdb/delete-rows.md index 85d8957..7235112 100644 --- a/docs/examples/tablesdb/delete-rows.md +++ b/docs/examples/tablesdb/delete-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.deleteRows( databaseId: "", tableId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/delete-transaction.md b/docs/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000..9a5d58b --- /dev/null +++ b/docs/examples/tablesdb/delete-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let result = try await tablesDB.deleteTransaction( + transactionId: "" +) + diff --git a/docs/examples/tablesdb/get-row.md b/docs/examples/tablesdb/get-row.md index 17e6ccb..ecadab1 100644 --- a/docs/examples/tablesdb/get-row.md +++ b/docs/examples/tablesdb/get-row.md @@ -11,6 +11,7 @@ let row = try await tablesDB.getRow( databaseId: "", tableId: "", rowId: "", - queries: [] // optional + 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 0000000..af0bd03 --- /dev/null +++ b/docs/examples/tablesdb/get-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.getTransaction( + transactionId: "" +) + diff --git a/docs/examples/tablesdb/increment-row-column.md b/docs/examples/tablesdb/increment-row-column.md index 38aa758..6c35ba8 100644 --- a/docs/examples/tablesdb/increment-row-column.md +++ b/docs/examples/tablesdb/increment-row-column.md @@ -13,6 +13,7 @@ let row = try await tablesDB.incrementRowColumn( rowId: "", column: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/list-rows.md b/docs/examples/tablesdb/list-rows.md index 7320147..92a2813 100644 --- a/docs/examples/tablesdb/list-rows.md +++ b/docs/examples/tablesdb/list-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.listRows( databaseId: "", tableId: "", - queries: [] // optional + 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 0000000..c6acb29 --- /dev/null +++ b/docs/examples/tablesdb/list-transactions.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transactionList = try await tablesDB.listTransactions( + queries: [] // optional +) + diff --git a/docs/examples/tablesdb/update-row.md b/docs/examples/tablesdb/update-row.md index e06338b..3ebd9e0 100644 --- a/docs/examples/tablesdb/update-row.md +++ b/docs/examples/tablesdb/update-row.md @@ -12,6 +12,7 @@ let row = try await tablesDB.updateRow( tableId: "", rowId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/update-rows.md b/docs/examples/tablesdb/update-rows.md index 58894f5..f18a2a3 100644 --- a/docs/examples/tablesdb/update-rows.md +++ b/docs/examples/tablesdb/update-rows.md @@ -11,6 +11,7 @@ let rowList = try await tablesDB.updateRows( databaseId: "", tableId: "", data: [:], // optional - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/update-transaction.md b/docs/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000..faa7d07 --- /dev/null +++ b/docs/examples/tablesdb/update-transaction.md @@ -0,0 +1,15 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try 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 dc133f6..1b07626 100644 --- a/docs/examples/tablesdb/upsert-row.md +++ b/docs/examples/tablesdb/upsert-row.md @@ -12,6 +12,7 @@ let row = try await tablesDB.upsertRow( tableId: "", rowId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/tablesdb/upsert-rows.md b/docs/examples/tablesdb/upsert-rows.md index fe35f0d..027087b 100644 --- a/docs/examples/tablesdb/upsert-rows.md +++ b/docs/examples/tablesdb/upsert-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.upsertRows( databaseId: "", tableId: "", - rows: [] + rows: [], + transactionId: "" // optional )