diff --git a/README.md b/README.md index c7da177..0d94889 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ ![Swift Package Manager](https://img.shields.io/github/v/release/appwrite/sdk-for-apple.svg?color=green&style=flat-square) ![License](https://img.shields.io/github/license/appwrite/sdk-for-apple.svg?style=flat-square) -![Version](https://img.shields.io/badge/api%20version-1.7.4-blue.svg?style=flat-square) +![Version](https://img.shields.io/badge/api%20version-1.8.0-blue.svg?style=flat-square) [![Build Status](https://img.shields.io/travis/com/appwrite/sdk-generator?style=flat-square)](https://travis-ci.com/appwrite/sdk-generator) [![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite) [![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord) -**This SDK is compatible with Appwrite server version 1.7.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-apple/releases).** +**This SDK is compatible with Appwrite server version 1.8.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-apple/releases).** Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Apple SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs) @@ -31,7 +31,7 @@ Add the package to your `Package.swift` dependencies: ```swift dependencies: [ - .package(url: "git@github.com:appwrite/sdk-for-apple.git", from: "10.2.0"), + .package(url: "git@github.com:appwrite/sdk-for-apple.git", from: "11.0.0"), ], ``` diff --git a/Sources/Appwrite/Client.swift b/Sources/Appwrite/Client.swift index bcd9028..910f79a 100644 --- a/Sources/Appwrite/Client.swift +++ b/Sources/Appwrite/Client.swift @@ -23,8 +23,8 @@ open class Client { "x-sdk-name": "Apple", "x-sdk-platform": "client", "x-sdk-language": "apple", - "x-sdk-version": "10.2.0", - "x-appwrite-response-format": "1.7.0" + "x-sdk-version": "11.0.0", + "x-appwrite-response-format": "1.8.0" ] internal var config: [String: String] = [:] diff --git a/Sources/Appwrite/Query.swift b/Sources/Appwrite/Query.swift index 20c499e..1956cdd 100644 --- a/Sources/Appwrite/Query.swift +++ b/Sources/Appwrite/Query.swift @@ -284,6 +284,90 @@ public struct Query : Codable, CustomStringConvertible { ).description } + public static func notContains(_ attribute: String, value: Any) -> String { + return Query( + method: "notContains", + attribute: attribute, + values: Query.parseValue(value) + ).description + } + + public static func notSearch(_ attribute: String, value: String) -> String { + return Query( + method: "notSearch", + attribute: attribute, + values: [value] + ).description + } + + public static func notBetween(_ attribute: String, start: Int, end: Int) -> String { + return Query( + method: "notBetween", + attribute: attribute, + values: [start, end] + ).description + } + + public static func notBetween(_ attribute: String, start: Double, end: Double) -> String { + return Query( + method: "notBetween", + attribute: attribute, + values: [start, end] + ).description + } + + public static func notBetween(_ attribute: String, start: String, end: String) -> String { + return Query( + method: "notBetween", + attribute: attribute, + values: [start, end] + ).description + } + + public static func notStartsWith(_ attribute: String, value: String) -> String { + return Query( + method: "notStartsWith", + attribute: attribute, + values: [value] + ).description + } + + public static func notEndsWith(_ attribute: String, value: String) -> String { + return Query( + method: "notEndsWith", + attribute: attribute, + values: [value] + ).description + } + + public static func createdBefore(_ value: String) -> String { + return Query( + method: "createdBefore", + values: [value] + ).description + } + + public static func createdAfter(_ value: String) -> String { + return Query( + method: "createdAfter", + values: [value] + ).description + } + + public static func updatedBefore(_ value: String) -> String { + return Query( + method: "updatedBefore", + values: [value] + ).description + } + + public static func updatedAfter(_ value: String) -> String { + return Query( + method: "updatedAfter", + values: [value] + ).description + } + public static func or(_ queries: [String]) -> String { let decoder = JSONDecoder() let decodedQueries = queries.compactMap { queryStr -> Query? in diff --git a/Sources/Appwrite/Services/Account.swift b/Sources/Appwrite/Services/Account.swift index 59f06a8..4234e7a 100644 --- a/Sources/Appwrite/Services/Account.swift +++ b/Sources/Appwrite/Services/Account.swift @@ -391,6 +391,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.MfaType /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.createMFAAuthenticator` instead.") open func createMfaAuthenticator( type: AppwriteEnums.AuthenticatorType ) async throws -> AppwriteModels.MfaType { @@ -416,6 +417,42 @@ open class Account: Service { ) } + /// + /// Add an authenticator app to be used as an MFA factor. Verify the + /// authenticator using the [verify + /// authenticator](/docs/references/cloud/client-web/account#updateMfaAuthenticator) + /// method. + /// + /// - Parameters: + /// - type: AppwriteEnums.AuthenticatorType + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.MfaType + /// + open func createMFAAuthenticator( + type: AppwriteEnums.AuthenticatorType + ) async throws -> AppwriteModels.MfaType { + let apiPath: String = "/account/mfa/authenticators/{type}" + .replacingOccurrences(of: "{type}", with: type.rawValue) + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.MfaType = { response in + return AppwriteModels.MfaType.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Verify an authenticator app after adding it using the [add /// authenticator](/docs/references/cloud/client-web/account#createMfaAuthenticator) @@ -427,6 +464,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.User /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.updateMFAAuthenticator` instead.") open func updateMfaAuthenticator( type: AppwriteEnums.AuthenticatorType, otp: String, @@ -467,6 +505,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.User /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.updateMFAAuthenticator` instead.") open func updateMfaAuthenticator( type: AppwriteEnums.AuthenticatorType, otp: String @@ -478,6 +517,68 @@ open class Account: Service { ) } + /// + /// Verify an authenticator app after adding it using the [add + /// authenticator](/docs/references/cloud/client-web/account#createMfaAuthenticator) + /// method. + /// + /// - Parameters: + /// - type: AppwriteEnums.AuthenticatorType + /// - otp: String + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.User + /// + open func updateMFAAuthenticator( + type: AppwriteEnums.AuthenticatorType, + otp: String, + nestedType: T.Type + ) async throws -> AppwriteModels.User { + let apiPath: String = "/account/mfa/authenticators/{type}" + .replacingOccurrences(of: "{type}", with: type.rawValue) + + let apiParams: [String: Any?] = [ + "otp": otp + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.User = { response in + return AppwriteModels.User.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PUT", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Verify an authenticator app after adding it using the [add + /// authenticator](/docs/references/cloud/client-web/account#createMfaAuthenticator) + /// method. + /// + /// - Parameters: + /// - type: AppwriteEnums.AuthenticatorType + /// - otp: String + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.User + /// + open func updateMFAAuthenticator( + type: AppwriteEnums.AuthenticatorType, + otp: String + ) async throws -> AppwriteModels.User<[String: AnyCodable]> { + return try await updateMFAAuthenticator( + type: type, + otp: otp, + nestedType: [String: AnyCodable].self + ) + } + /// /// Delete an authenticator for a user by ID. /// @@ -486,6 +587,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: Any /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.deleteMFAAuthenticator` instead.") open func deleteMfaAuthenticator( type: AppwriteEnums.AuthenticatorType ) async throws -> Any { @@ -505,6 +607,33 @@ open class Account: Service { params: apiParams ) } + /// + /// Delete an authenticator for a user by ID. + /// + /// - Parameters: + /// - type: AppwriteEnums.AuthenticatorType + /// - Throws: Exception if the request fails + /// - Returns: Any + /// + open func deleteMFAAuthenticator( + type: AppwriteEnums.AuthenticatorType + ) async throws -> Any { + let apiPath: String = "/account/mfa/authenticators/{type}" + .replacingOccurrences(of: "{type}", with: type.rawValue) + + 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 ) + } + /// /// Begin the process of MFA verification after sign-in. Finish the flow with /// [updateMfaChallenge](/docs/references/cloud/client-web/account#updateMfaChallenge) @@ -515,6 +644,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.MfaChallenge /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.createMFAChallenge` instead.") open func createMfaChallenge( factor: AppwriteEnums.AuthenticationFactor ) async throws -> AppwriteModels.MfaChallenge { @@ -541,6 +671,42 @@ open class Account: Service { ) } + /// + /// Begin the process of MFA verification after sign-in. Finish the flow with + /// [updateMfaChallenge](/docs/references/cloud/client-web/account#updateMfaChallenge) + /// method. + /// + /// - Parameters: + /// - factor: AppwriteEnums.AuthenticationFactor + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.MfaChallenge + /// + open func createMFAChallenge( + factor: AppwriteEnums.AuthenticationFactor + ) async throws -> AppwriteModels.MfaChallenge { + let apiPath: String = "/account/mfa/challenge" + + let apiParams: [String: Any?] = [ + "factor": factor + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.MfaChallenge = { response in + return AppwriteModels.MfaChallenge.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Complete the MFA challenge by providing the one-time password. Finish the /// process of MFA verification by providing the one-time password. To begin @@ -554,6 +720,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Session /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.updateMFAChallenge` instead.") open func updateMfaChallenge( challengeId: String, otp: String @@ -582,12 +749,54 @@ open class Account: Service { ) } + /// + /// Complete the MFA challenge by providing the one-time password. Finish the + /// process of MFA verification by providing the one-time password. To begin + /// the flow, use + /// [createMfaChallenge](/docs/references/cloud/client-web/account#createMfaChallenge) + /// method. + /// + /// - Parameters: + /// - challengeId: String + /// - otp: String + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Session + /// + open func updateMFAChallenge( + challengeId: String, + otp: String + ) async throws -> AppwriteModels.Session { + let apiPath: String = "/account/mfa/challenge" + + let apiParams: [String: Any?] = [ + "challengeId": challengeId, + "otp": otp + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Session = { response in + return AppwriteModels.Session.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PUT", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// List the factors available on the account to be used as a MFA challange. /// /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.MfaFactors /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.listMFAFactors` instead.") open func listMfaFactors( ) async throws -> AppwriteModels.MfaFactors { let apiPath: String = "/account/mfa/factors" @@ -609,6 +818,33 @@ open class Account: Service { ) } + /// + /// List the factors available on the account to be used as a MFA challange. + /// + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.MfaFactors + /// + open func listMFAFactors( + ) async throws -> AppwriteModels.MfaFactors { + let apiPath: String = "/account/mfa/factors" + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.MfaFactors = { response in + return AppwriteModels.MfaFactors.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Get recovery codes that can be used as backup for MFA flow. Before getting /// codes, they must be generated using @@ -618,6 +854,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.MfaRecoveryCodes /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.getMFARecoveryCodes` instead.") open func getMfaRecoveryCodes( ) async throws -> AppwriteModels.MfaRecoveryCodes { let apiPath: String = "/account/mfa/recovery-codes" @@ -639,6 +876,36 @@ open class Account: Service { ) } + /// + /// Get recovery codes that can be used as backup for MFA flow. Before getting + /// codes, they must be generated using + /// [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) + /// method. An OTP challenge is required to read recovery codes. + /// + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.MfaRecoveryCodes + /// + open func getMFARecoveryCodes( + ) async throws -> AppwriteModels.MfaRecoveryCodes { + let apiPath: String = "/account/mfa/recovery-codes" + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.MfaRecoveryCodes = { response in + return AppwriteModels.MfaRecoveryCodes.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Generate recovery codes as backup for MFA flow. It's recommended to /// generate and show then immediately after user successfully adds their @@ -649,6 +916,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.MfaRecoveryCodes /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.createMFARecoveryCodes` instead.") open func createMfaRecoveryCodes( ) async throws -> AppwriteModels.MfaRecoveryCodes { let apiPath: String = "/account/mfa/recovery-codes" @@ -672,6 +940,39 @@ open class Account: Service { ) } + /// + /// Generate recovery codes as backup for MFA flow. It's recommended to + /// generate and show then immediately after user successfully adds their + /// authehticator. Recovery codes can be used as a MFA verification type in + /// [createMfaChallenge](/docs/references/cloud/client-web/account#createMfaChallenge) + /// method. + /// + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.MfaRecoveryCodes + /// + open func createMFARecoveryCodes( + ) async throws -> AppwriteModels.MfaRecoveryCodes { + let apiPath: String = "/account/mfa/recovery-codes" + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.MfaRecoveryCodes = { response in + return AppwriteModels.MfaRecoveryCodes.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Regenerate recovery codes that can be used as backup for MFA flow. Before /// regenerating codes, they must be first generated using @@ -681,6 +982,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.MfaRecoveryCodes /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `Account.updateMFARecoveryCodes` instead.") open func updateMfaRecoveryCodes( ) async throws -> AppwriteModels.MfaRecoveryCodes { let apiPath: String = "/account/mfa/recovery-codes" @@ -704,6 +1006,38 @@ open class Account: Service { ) } + /// + /// Regenerate recovery codes that can be used as backup for MFA flow. Before + /// regenerating codes, they must be first generated using + /// [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) + /// method. An OTP challenge is required to regenreate recovery codes. + /// + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.MfaRecoveryCodes + /// + open func updateMFARecoveryCodes( + ) async throws -> AppwriteModels.MfaRecoveryCodes { + let apiPath: String = "/account/mfa/recovery-codes" + + let apiParams: [String: Any] = [:] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.MfaRecoveryCodes = { response in + return AppwriteModels.MfaRecoveryCodes.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PATCH", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + /// /// Update currently logged in user account name. /// @@ -1214,6 +1548,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Session /// + @available(*, deprecated, message: "This API has been deprecated.") open func updateMagicURLSession( userId: String, secret: String @@ -1313,6 +1648,7 @@ open class Account: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Session /// + @available(*, deprecated, message: "This API has been deprecated.") open func updatePhoneSession( userId: String, secret: String @@ -1641,8 +1977,11 @@ open class Account: Service { /// /// Sends the user an email with a secret key for creating a session. If the - /// provided user ID has not be registered, a new user will be created. Use the - /// returned user ID and secret and submit a request to the [POST + /// email address has never been used, a **new account is created** using the + /// provided `userId`. Otherwise, if the email address is already attached to + /// an account, the **user ID is ignored**. Then, the user will receive an + /// email with the one-time password. Use the returned user ID and secret and + /// submit a request to the [POST /// /v1/account/sessions/token](https://appwrite.io/docs/references/cloud/client-web/account#createSession) /// endpoint to complete the login process. The secret sent to the user's email /// is valid for 15 minutes. @@ -1650,6 +1989,7 @@ open class Account: Service { /// A user is limited to 10 active sessions at a time by default. [Learn more /// about session /// limits](https://appwrite.io/docs/authentication-security#limits). + /// /// /// - Parameters: /// - userId: String diff --git a/Sources/Appwrite/Services/Databases.swift b/Sources/Appwrite/Services/Databases.swift index 599c7b7..e8c8f1e 100644 --- a/Sources/Appwrite/Services/Databases.swift +++ b/Sources/Appwrite/Services/Databases.swift @@ -19,6 +19,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.listRows` instead.") open func listDocuments( databaseId: String, collectionId: String, @@ -59,6 +60,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.DocumentList /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.listRows` instead.") open func listDocuments( databaseId: String, collectionId: String, @@ -87,6 +89,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.createRow` instead.") open func createDocument( databaseId: String, collectionId: String, @@ -137,6 +140,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.createRow` instead.") open func createDocument( databaseId: String, collectionId: String, @@ -166,6 +170,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.getRow` instead.") open func getDocument( databaseId: String, collectionId: String, @@ -209,6 +214,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.getRow` instead.") open func getDocument( databaseId: String, collectionId: String, @@ -225,10 +231,6 @@ open class Databases: Service { } /// - /// **WARNING: Experimental Feature** - This endpoint is experimental and not - /// yet officially supported. It may be subject to breaking changes or removal - /// in future versions. - /// /// Create or update a Document. Before using this route, you should create a /// new collection resource using either a [server /// integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) @@ -243,6 +245,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.upsertRow` instead.") open func upsertDocument( databaseId: String, collectionId: String, @@ -279,10 +282,6 @@ open class Databases: Service { } /// - /// **WARNING: Experimental Feature** - This endpoint is experimental and not - /// yet officially supported. It may be subject to breaking changes or removal - /// in future versions. - /// /// Create or update a Document. Before using this route, you should create a /// new collection resource using either a [server /// integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) @@ -297,6 +296,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.upsertRow` instead.") open func upsertDocument( databaseId: String, collectionId: String, @@ -327,6 +327,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.updateRow` instead.") open func updateDocument( databaseId: String, collectionId: String, @@ -375,6 +376,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.updateRow` instead.") open func updateDocument( databaseId: String, collectionId: String, @@ -402,6 +404,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: Any /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.deleteRow` instead.") open func deleteDocument( databaseId: String, collectionId: String, @@ -438,6 +441,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.decrementRowColumn` instead.") open func decrementDocumentAttribute( databaseId: String, collectionId: String, @@ -488,6 +492,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.decrementRowColumn` instead.") open func decrementDocumentAttribute( databaseId: String, collectionId: String, @@ -520,6 +525,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.incrementRowColumn` instead.") open func incrementDocumentAttribute( databaseId: String, collectionId: String, @@ -570,6 +576,7 @@ open class Databases: Service { /// - Throws: Exception if the request fails /// - Returns: AppwriteModels.Document /// + @available(*, deprecated, message: "This API has been deprecated since 1.8.0. Please use `TablesDB.incrementRowColumn` instead.") open func incrementDocumentAttribute( databaseId: String, collectionId: String, diff --git a/Sources/Appwrite/Services/TablesDb.swift b/Sources/Appwrite/Services/TablesDb.swift new file mode 100644 index 0000000..cbc2abb --- /dev/null +++ b/Sources/Appwrite/Services/TablesDb.swift @@ -0,0 +1,585 @@ +import AsyncHTTPClient +import Foundation +import NIO +import JSONCodable +import AppwriteEnums +import AppwriteModels + +/// +open class TablesDB: Service { + + /// + /// Get a list of all the user's rows in a given table. You can use the query + /// params to filter your results. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - queries: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.RowList + /// + open func listRows( + databaseId: String, + tableId: String, + queries: [String]? = nil, + nestedType: T.Type + ) async throws -> AppwriteModels.RowList { + let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" + .replacingOccurrences(of: "{databaseId}", with: databaseId) + .replacingOccurrences(of: "{tableId}", with: tableId) + + let apiParams: [String: Any?] = [ + "queries": queries + ] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.RowList = { response in + return AppwriteModels.RowList.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Get a list of all the user's rows in a given table. You can use the query + /// params to filter your results. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - queries: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.RowList + /// + open func listRows( + databaseId: String, + tableId: String, + queries: [String]? = nil + ) async throws -> AppwriteModels.RowList<[String: AnyCodable]> { + return try await listRows( + databaseId: databaseId, + tableId: tableId, + queries: queries, + nestedType: [String: AnyCodable].self + ) + } + + /// + /// Create a new Row. Before using this route, you should create a new table + /// resource using either a [server + /// integration](https://appwrite.io/docs/server/tablesdb#tablesDBCreateTable) + /// API or directly from your database console. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - data: Any + /// - permissions: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func createRow( + databaseId: String, + tableId: String, + rowId: String, + data: Any, + permissions: [String]? = nil, + nestedType: T.Type + ) async throws -> AppwriteModels.Row { + let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows" + .replacingOccurrences(of: "{databaseId}", with: databaseId) + .replacingOccurrences(of: "{tableId}", with: tableId) + + let apiParams: [String: Any?] = [ + "rowId": rowId, + "data": data, + "permissions": permissions + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Row = { response in + return AppwriteModels.Row.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "POST", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Create a new Row. Before using this route, you should create a new table + /// resource using either a [server + /// integration](https://appwrite.io/docs/server/tablesdb#tablesDBCreateTable) + /// API or directly from your database console. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - data: Any + /// - permissions: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func createRow( + databaseId: String, + tableId: String, + rowId: String, + data: Any, + permissions: [String]? = nil + ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { + return try await createRow( + databaseId: databaseId, + tableId: tableId, + rowId: rowId, + data: data, + permissions: permissions, + nestedType: [String: AnyCodable].self + ) + } + + /// + /// Get a row by its unique ID. This endpoint response returns a JSON object + /// with the row data. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - queries: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func getRow( + databaseId: String, + tableId: String, + rowId: String, + queries: [String]? = nil, + nestedType: T.Type + ) async throws -> AppwriteModels.Row { + 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?] = [ + "queries": queries + ] + + let apiHeaders: [String: String] = [:] + + let converter: (Any) -> AppwriteModels.Row = { response in + return AppwriteModels.Row.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "GET", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Get a row by its unique ID. This endpoint response returns a JSON object + /// with the row data. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - queries: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func getRow( + databaseId: String, + tableId: String, + rowId: String, + queries: [String]? = nil + ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { + return try await getRow( + databaseId: databaseId, + tableId: tableId, + rowId: rowId, + queries: queries, + nestedType: [String: AnyCodable].self + ) + } + + /// + /// Create or update a Row. Before using this route, you should create a new + /// table resource using either a [server + /// integration](https://appwrite.io/docs/server/tablesdb#tablesDBCreateTable) + /// API or directly from your database console. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - data: Any (optional) + /// - permissions: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func upsertRow( + databaseId: String, + tableId: String, + rowId: String, + data: Any? = nil, + permissions: [String]? = nil, + nestedType: T.Type + ) async throws -> AppwriteModels.Row { + 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?] = [ + "data": data, + "permissions": permissions + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Row = { response in + return AppwriteModels.Row.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PUT", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Create or update a Row. Before using this route, you should create a new + /// table resource using either a [server + /// integration](https://appwrite.io/docs/server/tablesdb#tablesDBCreateTable) + /// API or directly from your database console. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - data: Any (optional) + /// - permissions: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func upsertRow( + databaseId: String, + tableId: String, + rowId: String, + data: Any? = nil, + permissions: [String]? = nil + ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { + return try await upsertRow( + databaseId: databaseId, + tableId: tableId, + rowId: rowId, + data: data, + permissions: permissions, + nestedType: [String: AnyCodable].self + ) + } + + /// + /// Update a row by its unique ID. Using the patch method you can pass only + /// specific fields that will get updated. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - data: Any (optional) + /// - permissions: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func updateRow( + databaseId: String, + tableId: String, + rowId: String, + data: Any? = nil, + permissions: [String]? = nil, + nestedType: T.Type + ) async throws -> AppwriteModels.Row { + 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?] = [ + "data": data, + "permissions": permissions + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Row = { response in + return AppwriteModels.Row.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PATCH", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Update a row by its unique ID. Using the patch method you can pass only + /// specific fields that will get updated. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - data: Any (optional) + /// - permissions: [String] (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func updateRow( + databaseId: String, + tableId: String, + rowId: String, + data: Any? = nil, + permissions: [String]? = nil + ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { + return try await updateRow( + databaseId: databaseId, + tableId: tableId, + rowId: rowId, + data: data, + permissions: permissions, + nestedType: [String: AnyCodable].self + ) + } + + /// + /// Delete a row by its unique ID. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - Throws: Exception if the request fails + /// - Returns: Any + /// + open func deleteRow( + databaseId: String, + tableId: String, + rowId: String + ) 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 apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + return try await client.call( + method: "DELETE", + path: apiPath, + headers: apiHeaders, + params: apiParams ) + } + + /// + /// Decrement a specific column of a row by a given value. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - column: String + /// - value: Double (optional) + /// - min: Double (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func decrementRowColumn( + databaseId: String, + tableId: String, + rowId: String, + column: String, + value: Double? = nil, + min: Double? = nil, + nestedType: T.Type + ) async throws -> AppwriteModels.Row { + let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/decrement" + .replacingOccurrences(of: "{databaseId}", with: databaseId) + .replacingOccurrences(of: "{tableId}", with: tableId) + .replacingOccurrences(of: "{rowId}", with: rowId) + .replacingOccurrences(of: "{column}", with: column) + + let apiParams: [String: Any?] = [ + "value": value, + "min": min + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Row = { response in + return AppwriteModels.Row.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PATCH", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Decrement a specific column of a row by a given value. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - column: String + /// - value: Double (optional) + /// - min: Double (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func decrementRowColumn( + databaseId: String, + tableId: String, + rowId: String, + column: String, + value: Double? = nil, + min: Double? = nil + ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { + return try await decrementRowColumn( + databaseId: databaseId, + tableId: tableId, + rowId: rowId, + column: column, + value: value, + min: min, + nestedType: [String: AnyCodable].self + ) + } + + /// + /// Increment a specific column of a row by a given value. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - column: String + /// - value: Double (optional) + /// - max: Double (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func incrementRowColumn( + databaseId: String, + tableId: String, + rowId: String, + column: String, + value: Double? = nil, + max: Double? = nil, + nestedType: T.Type + ) async throws -> AppwriteModels.Row { + let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/increment" + .replacingOccurrences(of: "{databaseId}", with: databaseId) + .replacingOccurrences(of: "{tableId}", with: tableId) + .replacingOccurrences(of: "{rowId}", with: rowId) + .replacingOccurrences(of: "{column}", with: column) + + let apiParams: [String: Any?] = [ + "value": value, + "max": max + ] + + let apiHeaders: [String: String] = [ + "content-type": "application/json" + ] + + let converter: (Any) -> AppwriteModels.Row = { response in + return AppwriteModels.Row.from(map: response as! [String: Any]) + } + + return try await client.call( + method: "PATCH", + path: apiPath, + headers: apiHeaders, + params: apiParams, + converter: converter + ) + } + + /// + /// Increment a specific column of a row by a given value. + /// + /// - Parameters: + /// - databaseId: String + /// - tableId: String + /// - rowId: String + /// - column: String + /// - value: Double (optional) + /// - max: Double (optional) + /// - Throws: Exception if the request fails + /// - Returns: AppwriteModels.Row + /// + open func incrementRowColumn( + databaseId: String, + tableId: String, + rowId: String, + column: String, + value: Double? = nil, + max: Double? = nil + ) async throws -> AppwriteModels.Row<[String: AnyCodable]> { + return try await incrementRowColumn( + databaseId: databaseId, + tableId: tableId, + rowId: rowId, + column: column, + value: value, + max: max, + nestedType: [String: AnyCodable].self + ) + } + + +} \ No newline at end of file diff --git a/Sources/AppwriteModels/ContinentList.swift b/Sources/AppwriteModels/ContinentList.swift index fa9a90f..0e697e7 100644 --- a/Sources/AppwriteModels/ContinentList.swift +++ b/Sources/AppwriteModels/ContinentList.swift @@ -9,7 +9,7 @@ open class ContinentList: Codable { case continents = "continents" } - /// Total number of continents documents that matched your query. + /// Total number of continents that matched your query. public let total: Int /// List of continents. diff --git a/Sources/AppwriteModels/CountryList.swift b/Sources/AppwriteModels/CountryList.swift index 865cc19..15a8d89 100644 --- a/Sources/AppwriteModels/CountryList.swift +++ b/Sources/AppwriteModels/CountryList.swift @@ -9,7 +9,7 @@ open class CountryList: Codable { case countries = "countries" } - /// Total number of countries documents that matched your query. + /// Total number of countries that matched your query. public let total: Int /// List of countries. diff --git a/Sources/AppwriteModels/CurrencyList.swift b/Sources/AppwriteModels/CurrencyList.swift index 1e0dff9..81d1c26 100644 --- a/Sources/AppwriteModels/CurrencyList.swift +++ b/Sources/AppwriteModels/CurrencyList.swift @@ -9,7 +9,7 @@ open class CurrencyList: Codable { case currencies = "currencies" } - /// Total number of currencies documents that matched your query. + /// Total number of currencies that matched your query. public let total: Int /// List of currencies. diff --git a/Sources/AppwriteModels/DocumentList.swift b/Sources/AppwriteModels/DocumentList.swift index a129182..77f2679 100644 --- a/Sources/AppwriteModels/DocumentList.swift +++ b/Sources/AppwriteModels/DocumentList.swift @@ -9,7 +9,7 @@ open class DocumentList: Codable { case documents = "documents" } - /// Total number of documents documents that matched your query. + /// Total number of documents that matched your query. public let total: Int /// List of documents. diff --git a/Sources/AppwriteModels/Execution.swift b/Sources/AppwriteModels/Execution.swift index 6e81532..baaf71e 100644 --- a/Sources/AppwriteModels/Execution.swift +++ b/Sources/AppwriteModels/Execution.swift @@ -10,6 +10,7 @@ open class Execution: Codable { case updatedAt = "$updatedAt" case permissions = "$permissions" case functionId = "functionId" + case deploymentId = "deploymentId" case trigger = "trigger" case status = "status" case requestMethod = "requestMethod" @@ -30,7 +31,7 @@ open class Execution: Codable { /// Execution creation date in ISO 8601 format. public let createdAt: String - /// Execution upate date in ISO 8601 format. + /// Execution update date in ISO 8601 format. public let updatedAt: String /// Execution roles. @@ -39,6 +40,9 @@ open class Execution: Codable { /// Function ID. public let functionId: String + /// Function's deployment ID used to create the execution. + public let deploymentId: String + /// The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`. public let trigger: String @@ -82,6 +86,7 @@ open class Execution: Codable { updatedAt: String, permissions: [String], functionId: String, + deploymentId: String, trigger: String, status: String, requestMethod: String, @@ -100,6 +105,7 @@ open class Execution: Codable { self.updatedAt = updatedAt self.permissions = permissions self.functionId = functionId + self.deploymentId = deploymentId self.trigger = trigger self.status = status self.requestMethod = requestMethod @@ -122,6 +128,7 @@ open class Execution: Codable { self.updatedAt = try container.decode(String.self, forKey: .updatedAt) self.permissions = try container.decode([String].self, forKey: .permissions) self.functionId = try container.decode(String.self, forKey: .functionId) + self.deploymentId = try container.decode(String.self, forKey: .deploymentId) self.trigger = try container.decode(String.self, forKey: .trigger) self.status = try container.decode(String.self, forKey: .status) self.requestMethod = try container.decode(String.self, forKey: .requestMethod) @@ -144,6 +151,7 @@ open class Execution: Codable { try container.encode(updatedAt, forKey: .updatedAt) try container.encode(permissions, forKey: .permissions) try container.encode(functionId, forKey: .functionId) + try container.encode(deploymentId, forKey: .deploymentId) try container.encode(trigger, forKey: .trigger) try container.encode(status, forKey: .status) try container.encode(requestMethod, forKey: .requestMethod) @@ -165,6 +173,7 @@ open class Execution: Codable { "$updatedAt": updatedAt as Any, "$permissions": permissions as Any, "functionId": functionId as Any, + "deploymentId": deploymentId as Any, "trigger": trigger as Any, "status": status as Any, "requestMethod": requestMethod as Any, @@ -187,6 +196,7 @@ open class Execution: Codable { updatedAt: map["$updatedAt"] as! String, permissions: map["$permissions"] as! [String], functionId: map["functionId"] as! String, + deploymentId: map["deploymentId"] as! String, trigger: map["trigger"] as! String, status: map["status"] as! String, requestMethod: map["requestMethod"] as! String, diff --git a/Sources/AppwriteModels/ExecutionList.swift b/Sources/AppwriteModels/ExecutionList.swift index 72d43a6..c903b34 100644 --- a/Sources/AppwriteModels/ExecutionList.swift +++ b/Sources/AppwriteModels/ExecutionList.swift @@ -9,7 +9,7 @@ open class ExecutionList: Codable { case executions = "executions" } - /// Total number of executions documents that matched your query. + /// Total number of executions that matched your query. public let total: Int /// List of executions. diff --git a/Sources/AppwriteModels/FileList.swift b/Sources/AppwriteModels/FileList.swift index bec7b76..19d52a0 100644 --- a/Sources/AppwriteModels/FileList.swift +++ b/Sources/AppwriteModels/FileList.swift @@ -9,7 +9,7 @@ open class FileList: Codable { case files = "files" } - /// Total number of files documents that matched your query. + /// Total number of files that matched your query. public let total: Int /// List of files. diff --git a/Sources/AppwriteModels/IdentityList.swift b/Sources/AppwriteModels/IdentityList.swift index 6065fad..abcc362 100644 --- a/Sources/AppwriteModels/IdentityList.swift +++ b/Sources/AppwriteModels/IdentityList.swift @@ -9,7 +9,7 @@ open class IdentityList: Codable { case identities = "identities" } - /// Total number of identities documents that matched your query. + /// Total number of identities that matched your query. public let total: Int /// List of identities. diff --git a/Sources/AppwriteModels/LanguageList.swift b/Sources/AppwriteModels/LanguageList.swift index 13c6e4a..2b1f03c 100644 --- a/Sources/AppwriteModels/LanguageList.swift +++ b/Sources/AppwriteModels/LanguageList.swift @@ -9,7 +9,7 @@ open class LanguageList: Codable { case languages = "languages" } - /// Total number of languages documents that matched your query. + /// Total number of languages that matched your query. public let total: Int /// List of languages. diff --git a/Sources/AppwriteModels/LocaleCodeList.swift b/Sources/AppwriteModels/LocaleCodeList.swift index 5ef0653..f1d1678 100644 --- a/Sources/AppwriteModels/LocaleCodeList.swift +++ b/Sources/AppwriteModels/LocaleCodeList.swift @@ -9,7 +9,7 @@ open class LocaleCodeList: Codable { case localeCodes = "localeCodes" } - /// Total number of localeCodes documents that matched your query. + /// Total number of localeCodes that matched your query. public let total: Int /// List of localeCodes. diff --git a/Sources/AppwriteModels/LogList.swift b/Sources/AppwriteModels/LogList.swift index 7ff2d07..ba76a8a 100644 --- a/Sources/AppwriteModels/LogList.swift +++ b/Sources/AppwriteModels/LogList.swift @@ -9,7 +9,7 @@ open class LogList: Codable { case logs = "logs" } - /// Total number of logs documents that matched your query. + /// Total number of logs that matched your query. public let total: Int /// List of logs. diff --git a/Sources/AppwriteModels/MembershipList.swift b/Sources/AppwriteModels/MembershipList.swift index a7b0cd6..7d6ffd1 100644 --- a/Sources/AppwriteModels/MembershipList.swift +++ b/Sources/AppwriteModels/MembershipList.swift @@ -9,7 +9,7 @@ open class MembershipList: Codable { case memberships = "memberships" } - /// Total number of memberships documents that matched your query. + /// Total number of memberships that matched your query. public let total: Int /// List of memberships. diff --git a/Sources/AppwriteModels/PhoneList.swift b/Sources/AppwriteModels/PhoneList.swift index 6f3bee3..f09d239 100644 --- a/Sources/AppwriteModels/PhoneList.swift +++ b/Sources/AppwriteModels/PhoneList.swift @@ -9,7 +9,7 @@ open class PhoneList: Codable { case phones = "phones" } - /// Total number of phones documents that matched your query. + /// Total number of phones that matched your query. public let total: Int /// List of phones. diff --git a/Sources/AppwriteModels/Row.swift b/Sources/AppwriteModels/Row.swift new file mode 100644 index 0000000..6e94a9e --- /dev/null +++ b/Sources/AppwriteModels/Row.swift @@ -0,0 +1,113 @@ +import Foundation +import JSONCodable + +/// Row +open class Row: Codable { + + enum CodingKeys: String, CodingKey { + case id = "$id" + case sequence = "$sequence" + case tableId = "$tableId" + case databaseId = "$databaseId" + case createdAt = "$createdAt" + case updatedAt = "$updatedAt" + case permissions = "$permissions" + case data + } + + /// Row ID. + public let id: String + + /// Row automatically incrementing ID. + public let sequence: Int + + /// Table ID. + public let tableId: String + + /// Database ID. + public let databaseId: String + + /// Row creation date in ISO 8601 format. + public let createdAt: String + + /// Row update date in ISO 8601 format. + public let updatedAt: String + + /// Row permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). + public let permissions: [String] + + /// Additional properties + public let data: T + + init( + id: String, + sequence: Int, + tableId: String, + databaseId: String, + createdAt: String, + updatedAt: String, + permissions: [String], + data: T + ) { + self.id = id + self.sequence = sequence + self.tableId = tableId + self.databaseId = databaseId + self.createdAt = createdAt + self.updatedAt = updatedAt + self.permissions = permissions + self.data = data + } + + 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.sequence = try container.decode(Int.self, forKey: .sequence) + self.tableId = try container.decode(String.self, forKey: .tableId) + self.databaseId = try container.decode(String.self, forKey: .databaseId) + self.createdAt = try container.decode(String.self, forKey: .createdAt) + self.updatedAt = try container.decode(String.self, forKey: .updatedAt) + self.permissions = try container.decode([String].self, forKey: .permissions) + self.data = try container.decode(T.self, forKey: .data) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(id, forKey: .id) + try container.encode(sequence, forKey: .sequence) + try container.encode(tableId, forKey: .tableId) + try container.encode(databaseId, forKey: .databaseId) + try container.encode(createdAt, forKey: .createdAt) + try container.encode(updatedAt, forKey: .updatedAt) + try container.encode(permissions, forKey: .permissions) + try container.encode(data, forKey: .data) + } + + public func toMap() -> [String: Any] { + return [ + "$id": id as Any, + "$sequence": sequence as Any, + "$tableId": tableId as Any, + "$databaseId": databaseId as Any, + "$createdAt": createdAt as Any, + "$updatedAt": updatedAt as Any, + "$permissions": permissions as Any, + "data": try! JSONEncoder().encode(data) + ] + } + + public static func from(map: [String: Any] ) -> Row { + return Row( + id: map["$id"] as! String, + sequence: map["$sequence"] as! Int, + tableId: map["$tableId"] as! String, + databaseId: map["$databaseId"] as! String, + createdAt: map["$createdAt"] as! String, + updatedAt: map["$updatedAt"] as! String, + permissions: map["$permissions"] as! [String], + data: try! JSONDecoder().decode(T.self, from: JSONSerialization.data(withJSONObject: map, options: [])) + ) + } +} diff --git a/Sources/AppwriteModels/RowList.swift b/Sources/AppwriteModels/RowList.swift new file mode 100644 index 0000000..c14c83b --- /dev/null +++ b/Sources/AppwriteModels/RowList.swift @@ -0,0 +1,54 @@ +import Foundation +import JSONCodable + +/// Rows List +open class RowList: Codable { + + enum CodingKeys: String, CodingKey { + case total = "total" + case rows = "rows" + } + + /// Total number of rows that matched your query. + public let total: Int + + /// List of rows. + public let rows: [Row] + + + init( + total: Int, + rows: [Row] + ) { + self.total = total + self.rows = rows + } + + 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.rows = try container.decode([Row].self, forKey: .rows) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(total, forKey: .total) + try container.encode(rows, forKey: .rows) + } + + public func toMap() -> [String: Any] { + return [ + "total": total as Any, + "rows": rows.map { $0.toMap() } as Any + ] + } + + public static func from(map: [String: Any] ) -> RowList { + return RowList( + total: map["total"] as! Int, + rows: (map["rows"] as! [[String: Any]]).map { Row.from(map: $0) } + ) + } +} diff --git a/Sources/AppwriteModels/SessionList.swift b/Sources/AppwriteModels/SessionList.swift index 13b6b3d..c9c8394 100644 --- a/Sources/AppwriteModels/SessionList.swift +++ b/Sources/AppwriteModels/SessionList.swift @@ -9,7 +9,7 @@ open class SessionList: Codable { case sessions = "sessions" } - /// Total number of sessions documents that matched your query. + /// Total number of sessions that matched your query. public let total: Int /// List of sessions. diff --git a/Sources/AppwriteModels/TeamList.swift b/Sources/AppwriteModels/TeamList.swift index 384d9f6..2b789d9 100644 --- a/Sources/AppwriteModels/TeamList.swift +++ b/Sources/AppwriteModels/TeamList.swift @@ -9,7 +9,7 @@ open class TeamList: Codable { case teams = "teams" } - /// Total number of teams documents that matched your query. + /// Total number of teams that matched your query. public let total: Int /// List of teams. diff --git a/docs/examples/account/create-j-w-t.md b/docs/examples/account/create-jwt.md similarity index 100% rename from docs/examples/account/create-j-w-t.md rename to docs/examples/account/create-jwt.md diff --git a/docs/examples/account/create-magic-u-r-l-token.md b/docs/examples/account/create-magic-url-token.md similarity index 100% rename from docs/examples/account/create-magic-u-r-l-token.md rename to docs/examples/account/create-magic-url-token.md diff --git a/docs/examples/account/create-mfa-authenticator.md b/docs/examples/account/create-mfa-authenticator.md index 56799e3..cfe0082 100644 --- a/docs/examples/account/create-mfa-authenticator.md +++ b/docs/examples/account/create-mfa-authenticator.md @@ -7,7 +7,7 @@ let client = Client() let account = Account(client) -let mfaType = try await account.createMfaAuthenticator( +let mfaType = try await account.createMFAAuthenticator( type: .totp ) diff --git a/docs/examples/account/create-mfa-challenge.md b/docs/examples/account/create-mfa-challenge.md index 0b5d385..27f1bc1 100644 --- a/docs/examples/account/create-mfa-challenge.md +++ b/docs/examples/account/create-mfa-challenge.md @@ -7,7 +7,7 @@ let client = Client() let account = Account(client) -let mfaChallenge = try await account.createMfaChallenge( +let mfaChallenge = try await account.createMFAChallenge( factor: .email ) diff --git a/docs/examples/account/create-mfa-recovery-codes.md b/docs/examples/account/create-mfa-recovery-codes.md index c0ccb39..2674a40 100644 --- a/docs/examples/account/create-mfa-recovery-codes.md +++ b/docs/examples/account/create-mfa-recovery-codes.md @@ -6,5 +6,5 @@ let client = Client() let account = Account(client) -let mfaRecoveryCodes = try await account.createMfaRecoveryCodes() +let mfaRecoveryCodes = try await account.createMFARecoveryCodes() diff --git a/docs/examples/account/create-o-auth2session.md b/docs/examples/account/create-o-auth-2-session.md similarity index 100% rename from docs/examples/account/create-o-auth2session.md rename to docs/examples/account/create-o-auth-2-session.md diff --git a/docs/examples/account/create-o-auth2token.md b/docs/examples/account/create-o-auth-2-token.md similarity index 100% rename from docs/examples/account/create-o-auth2token.md rename to docs/examples/account/create-o-auth-2-token.md diff --git a/docs/examples/account/delete-mfa-authenticator.md b/docs/examples/account/delete-mfa-authenticator.md index 16cbbe3..adfa363 100644 --- a/docs/examples/account/delete-mfa-authenticator.md +++ b/docs/examples/account/delete-mfa-authenticator.md @@ -7,7 +7,7 @@ let client = Client() let account = Account(client) -let result = try await account.deleteMfaAuthenticator( +let result = try await account.deleteMFAAuthenticator( type: .totp ) diff --git a/docs/examples/account/get-mfa-recovery-codes.md b/docs/examples/account/get-mfa-recovery-codes.md index 2f5d623..efee499 100644 --- a/docs/examples/account/get-mfa-recovery-codes.md +++ b/docs/examples/account/get-mfa-recovery-codes.md @@ -6,5 +6,5 @@ let client = Client() let account = Account(client) -let mfaRecoveryCodes = try await account.getMfaRecoveryCodes() +let mfaRecoveryCodes = try await account.getMFARecoveryCodes() diff --git a/docs/examples/account/list-mfa-factors.md b/docs/examples/account/list-mfa-factors.md index f6d7a6f..d81e77e 100644 --- a/docs/examples/account/list-mfa-factors.md +++ b/docs/examples/account/list-mfa-factors.md @@ -6,5 +6,5 @@ let client = Client() let account = Account(client) -let mfaFactors = try await account.listMfaFactors() +let mfaFactors = try await account.listMFAFactors() diff --git a/docs/examples/account/update-magic-u-r-l-session.md b/docs/examples/account/update-magic-url-session.md similarity index 100% rename from docs/examples/account/update-magic-u-r-l-session.md rename to docs/examples/account/update-magic-url-session.md diff --git a/docs/examples/account/update-mfa-authenticator.md b/docs/examples/account/update-mfa-authenticator.md index 6a42fb9..5245be2 100644 --- a/docs/examples/account/update-mfa-authenticator.md +++ b/docs/examples/account/update-mfa-authenticator.md @@ -7,7 +7,7 @@ let client = Client() let account = Account(client) -let user = try await account.updateMfaAuthenticator( +let user = try await account.updateMFAAuthenticator( type: .totp, otp: "" ) diff --git a/docs/examples/account/update-mfa-challenge.md b/docs/examples/account/update-mfa-challenge.md index db9753b..473393e 100644 --- a/docs/examples/account/update-mfa-challenge.md +++ b/docs/examples/account/update-mfa-challenge.md @@ -6,7 +6,7 @@ let client = Client() let account = Account(client) -let session = try await account.updateMfaChallenge( +let session = try await account.updateMFAChallenge( challengeId: "", otp: "" ) diff --git a/docs/examples/account/update-mfa-recovery-codes.md b/docs/examples/account/update-mfa-recovery-codes.md index c3b8d41..fbd6847 100644 --- a/docs/examples/account/update-mfa-recovery-codes.md +++ b/docs/examples/account/update-mfa-recovery-codes.md @@ -6,5 +6,5 @@ let client = Client() let account = Account(client) -let mfaRecoveryCodes = try await account.updateMfaRecoveryCodes() +let mfaRecoveryCodes = try await account.updateMFARecoveryCodes() diff --git a/docs/examples/account/update-m-f-a.md b/docs/examples/account/update-mfa.md similarity index 100% rename from docs/examples/account/update-m-f-a.md rename to docs/examples/account/update-mfa.md diff --git a/docs/examples/avatars/get-q-r.md b/docs/examples/avatars/get-qr.md similarity index 100% rename from docs/examples/avatars/get-q-r.md rename to docs/examples/avatars/get-qr.md diff --git a/docs/examples/functions/create-execution.md b/docs/examples/functions/create-execution.md index 7470e9e..b7311df 100644 --- a/docs/examples/functions/create-execution.md +++ b/docs/examples/functions/create-execution.md @@ -14,6 +14,6 @@ let execution = try await functions.createExecution( path: "", // optional method: .gET, // optional headers: [:], // optional - scheduledAt: "" // optional + scheduledAt: "" // optional ) diff --git a/docs/examples/locale/list-countries-e-u.md b/docs/examples/locale/list-countries-eu.md similarity index 100% rename from docs/examples/locale/list-countries-e-u.md rename to docs/examples/locale/list-countries-eu.md diff --git a/docs/examples/tablesdb/create-row.md b/docs/examples/tablesdb/create-row.md new file mode 100644 index 0000000..0972892 --- /dev/null +++ b/docs/examples/tablesdb/create-row.md @@ -0,0 +1,16 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let row = try await tablesDB.createRow( + databaseId: "", + tableId: "", + rowId: "", + data: [:], + permissions: ["read("any")"] // optional +) + diff --git a/docs/examples/tablesdb/decrement-row-column.md b/docs/examples/tablesdb/decrement-row-column.md new file mode 100644 index 0000000..ab8ac5b --- /dev/null +++ b/docs/examples/tablesdb/decrement-row-column.md @@ -0,0 +1,17 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let row = try await tablesDB.decrementRowColumn( + databaseId: "", + tableId: "", + rowId: "", + column: "", + value: 0, // optional + min: 0 // optional +) + diff --git a/docs/examples/tablesdb/delete-row.md b/docs/examples/tablesdb/delete-row.md new file mode 100644 index 0000000..b527aca --- /dev/null +++ b/docs/examples/tablesdb/delete-row.md @@ -0,0 +1,14 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let result = try await tablesDB.deleteRow( + databaseId: "", + tableId: "", + rowId: "" +) + diff --git a/docs/examples/tablesdb/get-row.md b/docs/examples/tablesdb/get-row.md new file mode 100644 index 0000000..bc2e2c6 --- /dev/null +++ b/docs/examples/tablesdb/get-row.md @@ -0,0 +1,15 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let row = try await tablesDB.getRow( + databaseId: "", + tableId: "", + rowId: "", + queries: [] // optional +) + diff --git a/docs/examples/tablesdb/increment-row-column.md b/docs/examples/tablesdb/increment-row-column.md new file mode 100644 index 0000000..550d668 --- /dev/null +++ b/docs/examples/tablesdb/increment-row-column.md @@ -0,0 +1,17 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let row = try await tablesDB.incrementRowColumn( + databaseId: "", + tableId: "", + rowId: "", + column: "", + value: 0, // optional + max: 0 // optional +) + diff --git a/docs/examples/tablesdb/list-rows.md b/docs/examples/tablesdb/list-rows.md new file mode 100644 index 0000000..94853c2 --- /dev/null +++ b/docs/examples/tablesdb/list-rows.md @@ -0,0 +1,14 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let rowList = try await tablesDB.listRows( + databaseId: "", + tableId: "", + queries: [] // optional +) + diff --git a/docs/examples/tablesdb/update-row.md b/docs/examples/tablesdb/update-row.md new file mode 100644 index 0000000..87a8f27 --- /dev/null +++ b/docs/examples/tablesdb/update-row.md @@ -0,0 +1,16 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let row = try await tablesDB.updateRow( + databaseId: "", + tableId: "", + rowId: "", + data: [:], // optional + permissions: ["read("any")"] // optional +) + diff --git a/docs/examples/tablesdb/upsert-row.md b/docs/examples/tablesdb/upsert-row.md new file mode 100644 index 0000000..ed95da7 --- /dev/null +++ b/docs/examples/tablesdb/upsert-row.md @@ -0,0 +1,16 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let row = try await tablesDB.upsertRow( + databaseId: "", + tableId: "", + rowId: "", + data: [:], // optional + permissions: ["read("any")"] // optional +) +