mirror of
https://github.com/appwrite/sdk-for-apple.git
synced 2026-04-07 19:17:50 +00:00
Merge pull request #107 from appwrite/dev
feat: Apple SDK update for version 15.0.0
This commit is contained in:
+5
-4
@@ -1,10 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 14.3.0
|
||||
## 15.0.0
|
||||
|
||||
* Added upsert() support for RealtimeChannel on both Document and Row variants to perform upsert operations over real-time channels.
|
||||
* Introduced new Query filter methods: contains(_:, value:), containsAny(_:, value: [Any]), containsAll(_:, value: [Any]) for enhanced querying capabilities (substring and multi-value containment).
|
||||
* Documentation and packaging updates to align with the new release: README dependency example updated from 14.2.0 to 14.1.0, and server compatibility note updated to indicate Appwrite server version 1.8.x compatibility.
|
||||
* Breaking: RealtimeChannel API required explicit IDs and threw errors.
|
||||
* Added ttl parameter to listDocuments and listRows.
|
||||
* Updated compatibility notes to latest server and SDK version.
|
||||
* Updated Document and Row comments for clarity.
|
||||
|
||||
## 14.1.0
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[](https://twitter.com/appwrite)
|
||||
[](https://appwrite.io/discord)
|
||||
|
||||
**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).**
|
||||
**This SDK is compatible with Appwrite server version latest. 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 abstracts and simplifies 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: "14.3.0"),
|
||||
.package(url: "git@github.com:appwrite/sdk-for-apple.git", from: "15.0.0"),
|
||||
],
|
||||
```
|
||||
|
||||
|
||||
@@ -16,10 +16,17 @@ public struct _Team {}
|
||||
public struct _Membership {}
|
||||
public struct _Resolved {}
|
||||
|
||||
public enum ChannelValidationError: Swift.Error {
|
||||
case invalidID
|
||||
}
|
||||
|
||||
// Helper for normalizing IDs
|
||||
private func normalize(_ id: String) -> String {
|
||||
private func normalize(_ id: String) throws -> String {
|
||||
let trimmed = id.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return trimmed.isEmpty ? "*" : trimmed
|
||||
guard !trimmed.isEmpty else {
|
||||
throw ChannelValidationError.invalidID
|
||||
}
|
||||
return trimmed
|
||||
}
|
||||
|
||||
/// Channel class with generic type parameter for type-safe method chaining
|
||||
@@ -31,9 +38,9 @@ public class RealtimeChannel<T> {
|
||||
}
|
||||
|
||||
/// Internal helper to transition to next state with segment and optional ID
|
||||
internal func next<N>(_ segment: String, _ id: String? = nil) -> RealtimeChannel<N> {
|
||||
internal func next<N>(_ segment: String, _ id: String? = nil) throws -> RealtimeChannel<N> {
|
||||
if let id = id {
|
||||
return RealtimeChannel<N>(segments + [segment, normalize(id)])
|
||||
return RealtimeChannel<N>(segments + [segment, try normalize(id)])
|
||||
}
|
||||
|
||||
return RealtimeChannel<N>(segments + [segment])
|
||||
@@ -55,32 +62,32 @@ public enum Channel {
|
||||
|
||||
// MARK: - Root Factories
|
||||
|
||||
public static func database(_ id: String = "*") -> RealtimeChannel<_Database> {
|
||||
return RealtimeChannel<_Database>(["databases", normalize(id)])
|
||||
public static func database(_ id: String) throws -> RealtimeChannel<_Database> {
|
||||
return RealtimeChannel<_Database>(["databases", try normalize(id)])
|
||||
}
|
||||
|
||||
public static func tablesdb(_ id: String = "*") -> RealtimeChannel<_TablesDB> {
|
||||
return RealtimeChannel<_TablesDB>(["tablesdb", normalize(id)])
|
||||
public static func tablesdb(_ id: String) throws -> RealtimeChannel<_TablesDB> {
|
||||
return RealtimeChannel<_TablesDB>(["tablesdb", try normalize(id)])
|
||||
}
|
||||
|
||||
public static func bucket(_ id: String = "*") -> RealtimeChannel<_Bucket> {
|
||||
return RealtimeChannel<_Bucket>(["buckets", normalize(id)])
|
||||
public static func bucket(_ id: String) throws -> RealtimeChannel<_Bucket> {
|
||||
return RealtimeChannel<_Bucket>(["buckets", try normalize(id)])
|
||||
}
|
||||
|
||||
public static func function(_ id: String = "*") -> RealtimeChannel<_Func> {
|
||||
return RealtimeChannel<_Func>(["functions", normalize(id)])
|
||||
public static func function(_ id: String) throws -> RealtimeChannel<_Func> {
|
||||
return RealtimeChannel<_Func>(["functions", try normalize(id)])
|
||||
}
|
||||
|
||||
public static func execution(_ id: String = "*") -> RealtimeChannel<_Execution> {
|
||||
return RealtimeChannel<_Execution>(["executions", normalize(id)])
|
||||
public static func execution(_ id: String) throws -> RealtimeChannel<_Execution> {
|
||||
return RealtimeChannel<_Execution>(["executions", try normalize(id)])
|
||||
}
|
||||
|
||||
public static func team(_ id: String = "*") -> RealtimeChannel<_Team> {
|
||||
return RealtimeChannel<_Team>(["teams", normalize(id)])
|
||||
public static func team(_ id: String) throws -> RealtimeChannel<_Team> {
|
||||
return RealtimeChannel<_Team>(["teams", try normalize(id)])
|
||||
}
|
||||
|
||||
public static func membership(_ id: String = "*") -> RealtimeChannel<_Membership> {
|
||||
return RealtimeChannel<_Membership>(["memberships", normalize(id)])
|
||||
public static func membership(_ id: String) throws -> RealtimeChannel<_Membership> {
|
||||
return RealtimeChannel<_Membership>(["memberships", try normalize(id)])
|
||||
}
|
||||
|
||||
public static func account() -> String {
|
||||
@@ -101,15 +108,15 @@ public enum Channel {
|
||||
|
||||
/// Only available on RealtimeChannel<_Database>
|
||||
extension RealtimeChannel where T == _Database {
|
||||
public func collection(_ id: String? = nil) -> RealtimeChannel<_Collection> {
|
||||
return self.next("collections", id ?? "*")
|
||||
public func collection(_ id: String) throws -> RealtimeChannel<_Collection> {
|
||||
return try self.next("collections", id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on RealtimeChannel<_Collection>
|
||||
extension RealtimeChannel where T == _Collection {
|
||||
public func document(_ id: String? = nil) -> RealtimeChannel<_Document> {
|
||||
return self.next("documents", id)
|
||||
public func document(_ id: String? = nil) throws -> RealtimeChannel<_Document> {
|
||||
return try self.next("documents", id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,15 +124,15 @@ extension RealtimeChannel where T == _Collection {
|
||||
|
||||
/// Only available on RealtimeChannel<_TablesDB>
|
||||
extension RealtimeChannel where T == _TablesDB {
|
||||
public func table(_ id: String? = nil) -> RealtimeChannel<_Table> {
|
||||
return self.next("tables", id ?? "*")
|
||||
public func table(_ id: String) throws -> RealtimeChannel<_Table> {
|
||||
return try self.next("tables", id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on RealtimeChannel<_Table>
|
||||
extension RealtimeChannel where T == _Table {
|
||||
public func row(_ id: String? = nil) -> RealtimeChannel<_Row> {
|
||||
return self.next("rows", id)
|
||||
public func row(_ id: String? = nil) throws -> RealtimeChannel<_Row> {
|
||||
return try self.next("rows", id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +140,8 @@ extension RealtimeChannel where T == _Table {
|
||||
|
||||
/// Only available on RealtimeChannel<_Bucket>
|
||||
extension RealtimeChannel where T == _Bucket {
|
||||
public func file(_ id: String? = nil) -> RealtimeChannel<_File> {
|
||||
return self.next("files", id)
|
||||
public func file(_ id: String? = nil) throws -> RealtimeChannel<_File> {
|
||||
return try self.next("files", id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ open class Client {
|
||||
"x-sdk-name": "Apple",
|
||||
"x-sdk-platform": "client",
|
||||
"x-sdk-language": "apple",
|
||||
"x-sdk-version": "14.3.0",
|
||||
"x-sdk-version": "15.0.0",
|
||||
"x-appwrite-response-format": "1.8.0"
|
||||
]
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ open class Databases: Service {
|
||||
/// - queries: [String] (optional)
|
||||
/// - transactionId: String (optional)
|
||||
/// - total: Bool (optional)
|
||||
/// - ttl: Int (optional)
|
||||
/// - Throws: Exception if the request fails
|
||||
/// - Returns: AppwriteModels.DocumentList<T>
|
||||
///
|
||||
@@ -229,6 +230,7 @@ open class Databases: Service {
|
||||
queries: [String]? = nil,
|
||||
transactionId: String? = nil,
|
||||
total: Bool? = nil,
|
||||
ttl: Int? = nil,
|
||||
nestedType: T.Type
|
||||
) async throws -> AppwriteModels.DocumentList<T> {
|
||||
let apiPath: String = "/databases/{databaseId}/collections/{collectionId}/documents"
|
||||
@@ -238,7 +240,8 @@ open class Databases: Service {
|
||||
let apiParams: [String: Any?] = [
|
||||
"queries": queries,
|
||||
"transactionId": transactionId,
|
||||
"total": total
|
||||
"total": total,
|
||||
"ttl": ttl
|
||||
]
|
||||
|
||||
let apiHeaders: [String: String] = [:]
|
||||
@@ -266,6 +269,7 @@ open class Databases: Service {
|
||||
/// - queries: [String] (optional)
|
||||
/// - transactionId: String (optional)
|
||||
/// - total: Bool (optional)
|
||||
/// - ttl: Int (optional)
|
||||
/// - Throws: Exception if the request fails
|
||||
/// - Returns: AppwriteModels.DocumentList<T>
|
||||
///
|
||||
@@ -275,7 +279,8 @@ open class Databases: Service {
|
||||
collectionId: String,
|
||||
queries: [String]? = nil,
|
||||
transactionId: String? = nil,
|
||||
total: Bool? = nil
|
||||
total: Bool? = nil,
|
||||
ttl: Int? = nil
|
||||
) async throws -> AppwriteModels.DocumentList<[String: AnyCodable]> {
|
||||
return try await listDocuments(
|
||||
databaseId: databaseId,
|
||||
@@ -283,6 +288,7 @@ open class Databases: Service {
|
||||
queries: queries,
|
||||
transactionId: transactionId,
|
||||
total: total,
|
||||
ttl: ttl,
|
||||
nestedType: [String: AnyCodable].self
|
||||
)
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@ open class TablesDB: Service {
|
||||
/// - queries: [String] (optional)
|
||||
/// - transactionId: String (optional)
|
||||
/// - total: Bool (optional)
|
||||
/// - ttl: Int (optional)
|
||||
/// - Throws: Exception if the request fails
|
||||
/// - Returns: AppwriteModels.RowList<T>
|
||||
///
|
||||
@@ -228,6 +229,7 @@ open class TablesDB: Service {
|
||||
queries: [String]? = nil,
|
||||
transactionId: String? = nil,
|
||||
total: Bool? = nil,
|
||||
ttl: Int? = nil,
|
||||
nestedType: T.Type
|
||||
) async throws -> AppwriteModels.RowList<T> {
|
||||
let apiPath: String = "/tablesdb/{databaseId}/tables/{tableId}/rows"
|
||||
@@ -237,7 +239,8 @@ open class TablesDB: Service {
|
||||
let apiParams: [String: Any?] = [
|
||||
"queries": queries,
|
||||
"transactionId": transactionId,
|
||||
"total": total
|
||||
"total": total,
|
||||
"ttl": ttl
|
||||
]
|
||||
|
||||
let apiHeaders: [String: String] = [:]
|
||||
@@ -265,6 +268,7 @@ open class TablesDB: Service {
|
||||
/// - queries: [String] (optional)
|
||||
/// - transactionId: String (optional)
|
||||
/// - total: Bool (optional)
|
||||
/// - ttl: Int (optional)
|
||||
/// - Throws: Exception if the request fails
|
||||
/// - Returns: AppwriteModels.RowList<T>
|
||||
///
|
||||
@@ -273,7 +277,8 @@ open class TablesDB: Service {
|
||||
tableId: String,
|
||||
queries: [String]? = nil,
|
||||
transactionId: String? = nil,
|
||||
total: Bool? = nil
|
||||
total: Bool? = nil,
|
||||
ttl: Int? = nil
|
||||
) async throws -> AppwriteModels.RowList<[String: AnyCodable]> {
|
||||
return try await listRows(
|
||||
databaseId: databaseId,
|
||||
@@ -281,6 +286,7 @@ open class TablesDB: Service {
|
||||
queries: queries,
|
||||
transactionId: transactionId,
|
||||
total: total,
|
||||
ttl: ttl,
|
||||
nestedType: [String: AnyCodable].self
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ open class Document<T : Codable>: Codable {
|
||||
|
||||
/// Document ID.
|
||||
public let id: String
|
||||
/// Document automatically incrementing ID.
|
||||
/// Document sequence ID.
|
||||
public let sequence: Int
|
||||
/// Collection ID.
|
||||
public let collectionId: String
|
||||
|
||||
@@ -17,7 +17,7 @@ open class Row<T : Codable>: Codable {
|
||||
|
||||
/// Row ID.
|
||||
public let id: String
|
||||
/// Row automatically incrementing ID.
|
||||
/// Row sequence ID.
|
||||
public let sequence: Int
|
||||
/// Table ID.
|
||||
public let tableId: String
|
||||
|
||||
@@ -12,7 +12,8 @@ let documentList = try await databases.listDocuments(
|
||||
collectionId: "<COLLECTION_ID>",
|
||||
queries: [], // optional
|
||||
transactionId: "<TRANSACTION_ID>", // optional
|
||||
total: false // optional
|
||||
total: false, // optional
|
||||
ttl: 0 // optional
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
@@ -12,7 +12,8 @@ let rowList = try await tablesDB.listRows(
|
||||
tableId: "<TABLE_ID>",
|
||||
queries: [], // optional
|
||||
transactionId: "<TRANSACTION_ID>", // optional
|
||||
total: false // optional
|
||||
total: false, // optional
|
||||
ttl: 0 // optional
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user