Skip to content

Commit a049430

Browse files
authored
Merge pull request #47 from appwrite/dev
feat: Swift SDK update for version 13.3.0
2 parents 4903240 + 5d4e9af commit a049430

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+765
-155
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## 13.3.0
4+
5+
* Add `total` parameter to list queries allowing skipping counting rows in a table for improved performance
6+
* Add `Operator` class for atomic modification of rows via update, bulk update, upsert, and bulk upsert operations
7+
* Add `createResendProvider` and `updateResendProvider` methods to `Messaging` service
8+
39
## 13.2.2
410

511
* Fix issue: Missing AppwriteEnums dependency causing build failure

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Add the package to your `Package.swift` dependencies:
3333

3434
```swift
3535
dependencies: [
36-
.package(url: "git@github.com:appwrite/sdk-for-swift.git", from: "13.2.2"),
36+
.package(url: "git@github.com:appwrite/sdk-for-swift.git", from: "13.3.0"),
3737
],
3838
```
3939

Sources/Appwrite/Client.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ open class Client {
2121
"x-sdk-name": "Swift",
2222
"x-sdk-platform": "server",
2323
"x-sdk-language": "swift",
24-
"x-sdk-version": "13.2.2",
24+
"x-sdk-version": "13.3.0",
2525
"x-appwrite-response-format": "1.8.0"
2626
]
2727

Sources/Appwrite/Operator.swift

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
import Foundation
2+
3+
public enum Condition: String, Codable {
4+
case equal = "equal"
5+
case notEqual = "notEqual"
6+
case greaterThan = "greaterThan"
7+
case greaterThanEqual = "greaterThanEqual"
8+
case lessThan = "lessThan"
9+
case lessThanEqual = "lessThanEqual"
10+
case contains = "contains"
11+
case isNull = "isNull"
12+
case isNotNull = "isNotNull"
13+
}
14+
15+
enum OperatorValue: Codable {
16+
case string(String)
17+
case int(Int)
18+
case double(Double)
19+
case bool(Bool)
20+
case array([OperatorValue])
21+
case null
22+
23+
init(from decoder: Decoder) throws {
24+
let container = try decoder.singleValueContainer()
25+
26+
if container.decodeNil() {
27+
self = .null
28+
} else if let stringValue = try? container.decode(String.self) {
29+
self = .string(stringValue)
30+
} else if let intValue = try? container.decode(Int.self) {
31+
self = .int(intValue)
32+
} else if let doubleValue = try? container.decode(Double.self) {
33+
self = .double(doubleValue)
34+
} else if let boolValue = try? container.decode(Bool.self) {
35+
self = .bool(boolValue)
36+
} else if let arrayValue = try? container.decode([OperatorValue].self) {
37+
self = .array(arrayValue)
38+
} else {
39+
throw DecodingError.dataCorruptedError(
40+
in: container,
41+
debugDescription: "OperatorValue cannot be decoded"
42+
)
43+
}
44+
}
45+
46+
func encode(to encoder: Encoder) throws {
47+
var container = encoder.singleValueContainer()
48+
switch self {
49+
case .string(let value):
50+
try container.encode(value)
51+
case .int(let value):
52+
try container.encode(value)
53+
case .double(let value):
54+
try container.encode(value)
55+
case .bool(let value):
56+
try container.encode(value)
57+
case .array(let value):
58+
try container.encode(value)
59+
case .null:
60+
try container.encodeNil()
61+
}
62+
}
63+
}
64+
65+
public struct Operator : Codable, CustomStringConvertible {
66+
var method: String
67+
var values: [OperatorValue]?
68+
69+
init(method: String, values: Any? = nil) {
70+
self.method = method
71+
self.values = Operator.convertToOperatorValueArray(values)
72+
}
73+
74+
public init(from decoder: Decoder) throws {
75+
let container = try decoder.container(keyedBy: CodingKeys.self)
76+
77+
self.method = try container.decode(String.self, forKey: .method)
78+
self.values = try container.decodeIfPresent([OperatorValue].self, forKey: .values)
79+
}
80+
81+
private static func convertToOperatorValueArray(_ values: Any?) -> [OperatorValue]? {
82+
// Handle nil
83+
if values == nil {
84+
return nil
85+
}
86+
87+
// Handle NSNull as [.null]
88+
if values is NSNull {
89+
return [.null]
90+
}
91+
92+
switch values {
93+
case let valueArray as [OperatorValue]:
94+
return valueArray
95+
case let stringArray as [String]:
96+
return stringArray.map { .string($0) }
97+
case let intArray as [Int]:
98+
return intArray.map { .int($0) }
99+
case let doubleArray as [Double]:
100+
return doubleArray.map { .double($0) }
101+
case let boolArray as [Bool]:
102+
return boolArray.map { .bool($0) }
103+
case let stringValue as String:
104+
return [.string(stringValue)]
105+
case let intValue as Int:
106+
return [.int(intValue)]
107+
case let doubleValue as Double:
108+
return [.double(doubleValue)]
109+
case let boolValue as Bool:
110+
return [.bool(boolValue)]
111+
case let anyArray as [Any]:
112+
// Preserve empty arrays as empty OperatorValue arrays
113+
if anyArray.isEmpty {
114+
return []
115+
}
116+
117+
// Map all items, converting nil/unknown to .null
118+
let nestedValues = anyArray.map { item -> OperatorValue in
119+
if item is NSNull {
120+
return .null
121+
} else if let stringValue = item as? String {
122+
return .string(stringValue)
123+
} else if let intValue = item as? Int {
124+
return .int(intValue)
125+
} else if let doubleValue = item as? Double {
126+
return .double(doubleValue)
127+
} else if let boolValue = item as? Bool {
128+
return .bool(boolValue)
129+
} else if let nestedArray = item as? [Any] {
130+
let converted = convertToOperatorValueArray(nestedArray) ?? []
131+
return .array(converted)
132+
} else {
133+
// Unknown/unsupported types become .null
134+
return .null
135+
}
136+
}
137+
return nestedValues
138+
default:
139+
// Unknown types become [.null]
140+
return [.null]
141+
}
142+
}
143+
144+
enum CodingKeys: String, CodingKey {
145+
case method
146+
case values
147+
}
148+
149+
public func encode(to encoder: Encoder) throws {
150+
var container = encoder.container(keyedBy: CodingKeys.self)
151+
try container.encode(method, forKey: .method)
152+
153+
if (values != nil) {
154+
try container.encode(values, forKey: .values)
155+
}
156+
}
157+
158+
public var description: String {
159+
guard let data = try? JSONEncoder().encode(self) else {
160+
return ""
161+
}
162+
163+
return String(data: data, encoding: .utf8) ?? ""
164+
}
165+
166+
public static func increment(_ value: Double = 1, max: Double? = nil) -> String {
167+
if value.isNaN || value.isInfinite {
168+
fatalError("Value cannot be NaN or Infinity")
169+
}
170+
if let max = max, max.isNaN || max.isInfinite {
171+
fatalError("Max cannot be NaN or Infinity")
172+
}
173+
var values: [Any] = [value]
174+
if let max = max {
175+
values.append(max)
176+
}
177+
return Operator(method: "increment", values: values).description
178+
}
179+
180+
public static func decrement(_ value: Double = 1, min: Double? = nil) -> String {
181+
if value.isNaN || value.isInfinite {
182+
fatalError("Value cannot be NaN or Infinity")
183+
}
184+
if let min = min, min.isNaN || min.isInfinite {
185+
fatalError("Min cannot be NaN or Infinity")
186+
}
187+
var values: [Any] = [value]
188+
if let min = min {
189+
values.append(min)
190+
}
191+
return Operator(method: "decrement", values: values).description
192+
}
193+
194+
public static func multiply(_ factor: Double, max: Double? = nil) -> String {
195+
if factor.isNaN || factor.isInfinite {
196+
fatalError("Factor cannot be NaN or Infinity")
197+
}
198+
if let max = max, max.isNaN || max.isInfinite {
199+
fatalError("Max cannot be NaN or Infinity")
200+
}
201+
var values: [Any] = [factor]
202+
if let max = max {
203+
values.append(max)
204+
}
205+
return Operator(method: "multiply", values: values).description
206+
}
207+
208+
public static func divide(_ divisor: Double, min: Double? = nil) -> String {
209+
if divisor.isNaN || divisor.isInfinite {
210+
fatalError("Divisor cannot be NaN or Infinity")
211+
}
212+
if let min = min, min.isNaN || min.isInfinite {
213+
fatalError("Min cannot be NaN or Infinity")
214+
}
215+
if divisor == 0 {
216+
fatalError("Divisor cannot be zero")
217+
}
218+
var values: [Any] = [divisor]
219+
if let min = min {
220+
values.append(min)
221+
}
222+
return Operator(method: "divide", values: values).description
223+
}
224+
225+
public static func modulo(_ divisor: Double) -> String {
226+
if divisor.isNaN || divisor.isInfinite {
227+
fatalError("Divisor cannot be NaN or Infinity")
228+
}
229+
if divisor == 0 {
230+
fatalError("Divisor cannot be zero")
231+
}
232+
return Operator(method: "modulo", values: [divisor]).description
233+
}
234+
235+
public static func power(_ exponent: Double, max: Double? = nil) -> String {
236+
if exponent.isNaN || exponent.isInfinite {
237+
fatalError("Exponent cannot be NaN or Infinity")
238+
}
239+
if let max = max, max.isNaN || max.isInfinite {
240+
fatalError("Max cannot be NaN or Infinity")
241+
}
242+
var values: [Any] = [exponent]
243+
if let max = max {
244+
values.append(max)
245+
}
246+
return Operator(method: "power", values: values).description
247+
}
248+
249+
public static func arrayAppend(_ values: [Any]) -> String {
250+
return Operator(method: "arrayAppend", values: values).description
251+
}
252+
253+
public static func arrayPrepend(_ values: [Any]) -> String {
254+
return Operator(method: "arrayPrepend", values: values).description
255+
}
256+
257+
public static func arrayInsert(_ index: Int, value: Any) -> String {
258+
return Operator(method: "arrayInsert", values: [index, value]).description
259+
}
260+
261+
public static func arrayRemove(_ value: Any) -> String {
262+
return Operator(method: "arrayRemove", values: [value]).description
263+
}
264+
265+
public static func arrayUnique() -> String {
266+
return Operator(method: "arrayUnique", values: []).description
267+
}
268+
269+
public static func arrayIntersect(_ values: [Any]) -> String {
270+
return Operator(method: "arrayIntersect", values: values).description
271+
}
272+
273+
public static func arrayDiff(_ values: [Any]) -> String {
274+
return Operator(method: "arrayDiff", values: values).description
275+
}
276+
277+
public static func arrayFilter(_ condition: Condition, value: Any? = nil) -> String {
278+
let values: [Any] = [condition.rawValue, value ?? NSNull()]
279+
return Operator(method: "arrayFilter", values: values).description
280+
}
281+
282+
public static func stringConcat(_ value: Any) -> String {
283+
return Operator(method: "stringConcat", values: [value]).description
284+
}
285+
286+
public static func stringReplace(_ search: String, _ replace: String) -> String {
287+
return Operator(method: "stringReplace", values: [search, replace]).description
288+
}
289+
290+
public static func toggle() -> String {
291+
return Operator(method: "toggle", values: []).description
292+
}
293+
294+
public static func dateAddDays(_ days: Int) -> String {
295+
return Operator(method: "dateAddDays", values: [days]).description
296+
}
297+
298+
public static func dateSubDays(_ days: Int) -> String {
299+
return Operator(method: "dateSubDays", values: [days]).description
300+
}
301+
302+
public static func dateSetNow() -> String {
303+
return Operator(method: "dateSetNow", values: []).description
304+
}
305+
}

Sources/Appwrite/Query.swift

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -379,45 +379,27 @@ public struct Query : Codable, CustomStringConvertible {
379379
}
380380

381381
public static func createdBefore(_ value: String) -> String {
382-
return Query(
383-
method: "createdBefore",
384-
values: [value]
385-
).description
382+
return lessThan("$createdAt", value: value)
386383
}
387384

388385
public static func createdAfter(_ value: String) -> String {
389-
return Query(
390-
method: "createdAfter",
391-
values: [value]
392-
).description
386+
return greaterThan("$createdAt", value: value)
393387
}
394388

395389
public static func createdBetween(_ start: String, _ end: String) -> String {
396-
return Query(
397-
method: "createdBetween",
398-
values: [start, end]
399-
).description
390+
return between("$createdAt", start: start, end: end)
400391
}
401392

402393
public static func updatedBefore(_ value: String) -> String {
403-
return Query(
404-
method: "updatedBefore",
405-
values: [value]
406-
).description
394+
return lessThan("$updatedAt", value: value)
407395
}
408396

409397
public static func updatedAfter(_ value: String) -> String {
410-
return Query(
411-
method: "updatedAfter",
412-
values: [value]
413-
).description
398+
return greaterThan("$updatedAt", value: value)
414399
}
415400

416401
public static func updatedBetween(_ start: String, _ end: String) -> String {
417-
return Query(
418-
method: "updatedBetween",
419-
values: [start, end]
420-
).description
402+
return between("$updatedAt", start: start, end: end)
421403
}
422404

423405
public static func or(_ queries: [String]) -> String {

0 commit comments

Comments
 (0)