diff --git a/Package.resolved b/Package.resolved index f41502f..2584942 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,17 +6,17 @@ "repositoryURL": "https://github.com/swift-aws/aws-sdk-swift", "state": { "branch": null, - "revision": "bc557114b6c16f63780d35ac2c5c21bf5c9b8f12", - "version": "3.0.0" + "revision": "028a16332df2212f82dc64ada4568131844a9e47", + "version": "3.3.0" } }, { "package": "AWSSDKSwiftCore", - "repositoryURL": "https://github.com/swift-aws/aws-sdk-swift-core.git", + "repositoryURL": "https://github.com/swift-aws/aws-sdk-swift-core", "state": { "branch": null, - "revision": "254c1e3f85414bf0f529f47cc081be2bd0c12c1c", - "version": "3.0.1" + "revision": "14dc7e963b9889c57395cb280f634540da189501", + "version": "3.4.0" } }, { @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/vapor/core.git", "state": { "branch": null, - "revision": "2731f8ba0cf274a61c9bd6ab43550f692ffaf879", - "version": "3.9.0" + "revision": "18f2436bf7a6bc2224372c0885db2e0159af1649", + "version": "3.9.2" } }, { @@ -51,26 +51,26 @@ "repositoryURL": "https://github.com/vapor/fluent", "state": { "branch": null, - "revision": "b915c321c6f9e83743ee5efa35a30895e1b02e51", - "version": "3.2.0" + "revision": "783819d8838d15e1a05b459aa0fd1bde1e37ac26", + "version": "3.2.1" } }, { "package": "HypertextApplicationLanguage", - "repositoryURL": "https://github.com/Yasumoto/HypertextApplicationLanguage.git", + "repositoryURL": "https://github.com/swift-aws/HypertextApplicationLanguage.git", "state": { "branch": null, - "revision": "2302002502fe573494577cc6e8df686e385519f8", - "version": "1.1.0" + "revision": "aa2c9141d491682f17b2310aed17b9adfc006256", + "version": "1.1.1" } }, { "package": "INIParser", - "repositoryURL": "https://github.com/PerfectlySoft/Perfect-INIParser.git", + "repositoryURL": "https://github.com/swift-aws/Perfect-INIParser.git", "state": { "branch": null, - "revision": "0952aac9ca54324ff25191569fd9c48eec424772", - "version": "3.0.2" + "revision": "42de0efc7a01105e19b80d533d3d282a98277f6c", + "version": "3.0.3" } }, { @@ -126,15 +126,6 @@ "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", "version": "1.0.0" } - }, - { - "package": "SwiftyJSON", - "repositoryURL": "https://github.com/IBM-Swift/SwiftyJSON.git", - "state": { - "branch": null, - "revision": "f2612ea3ac29996ae9601bdcb00cc1c29e26f104", - "version": "17.0.4" - } } ] }, diff --git a/Package.swift b/Package.swift index 8b73a16..9b45864 100644 --- a/Package.swift +++ b/Package.swift @@ -14,7 +14,7 @@ let package = Package( .package(url: "https://github.com/vapor/fluent", from: "3.1.0"), // 💫 AWS Client Library - .package(url: "https://github.com/swift-aws/aws-sdk-swift", from: "3.0.0"), + .package(url: "https://github.com/swift-aws/aws-sdk-swift", from: "3.3.0"), ], targets: [ .target( diff --git a/Sources/FluentDynamoDB/DynamoConnection.swift b/Sources/FluentDynamoDB/DynamoConnection.swift index 2e94105..0253306 100644 --- a/Sources/FluentDynamoDB/DynamoConnection.swift +++ b/Sources/FluentDynamoDB/DynamoConnection.swift @@ -77,20 +77,22 @@ extension DynamoConnection: DatabaseQueryable { case .get: let inputItem = DynamoDB.GetItemInput( key: requestedKey, tableName: query.table) - return try self.handle.getItem(inputItem).map { output in + return self.handle.getItem(inputItem).map { output in return try handler(Output(attributes: output.item)) } case .set: let inputItem = DynamoDB.PutItemInput(item: requestedKey, returnValues: .allOld, tableName: query.table) - return try self.handle.putItem(inputItem).map { output in + return self.handle.putItem(inputItem).map { output in return try handler(Output(attributes: output.attributes)) } case .delete: - let inputItem: DynamoDB.DeleteItemInput = DynamoDB.DeleteItemInput( + let inputItem = DynamoDB.DeleteItemInput( key: requestedKey, returnValues: .allOld, tableName: query.table) - return try self.handle.deleteItem(inputItem).map { output in + return self.handle.deleteItem(inputItem).map { output in return try handler(DynamoValue(attributes: output.attributes)) } + case .filter: + return self.eventLoop.newFailedFuture(error: DynamoConnectionError.notImplementedYet) } } catch { return self.eventLoop.newFailedFuture(error: error) @@ -127,7 +129,7 @@ extension DynamoConnection: DatabaseQueryable { // Note that DynamoDB allows batch operations to query multiple items. For simplicity, we're // always assuming we're querying one table at a time. We will always check the response for // the table name we've specified in the query itself. - return try self.handle.batchGetItem(batchInput).map { (output: DynamoDB.BatchGetItemOutput) -> [DynamoValue] in + return self.handle.batchGetItem(batchInput).map { (output: DynamoDB.BatchGetItemOutput) -> [DynamoValue] in guard let values: [[String : DynamoDB.AttributeValue]] = output.responses?[query.table] else { return [DynamoValue]() } return values.map { DynamoValue(attributes: $0) } } @@ -136,7 +138,20 @@ extension DynamoConnection: DatabaseQueryable { case .delete: throw DynamoConnectionError.notImplementedYet + case .filter: + let queryInput = DynamoDB.QueryInput( + expressionAttributeNames: query.expressionAttributeNames, + expressionAttributeValues: query.expressionAttributeValues, + indexName: query.index, + keyConditionExpression: query.keyConditionExpression, + tableName: query.table) + return self.handle.query(queryInput).map { (output: DynamoDB.QueryOutput) in + return output.items?.compactMap { (item: [String: DynamoDB.AttributeValue]) -> DynamoValue in + return DynamoValue(attributes: item) + } ?? [DynamoValue]() + } } + } catch { return self.eventLoop.newFailedFuture(error: error) } diff --git a/Sources/FluentDynamoDB/Query/DynamoQuery.swift b/Sources/FluentDynamoDB/Query/DynamoQuery.swift index ea21242..2a2f5e1 100644 --- a/Sources/FluentDynamoDB/Query/DynamoQuery.swift +++ b/Sources/FluentDynamoDB/Query/DynamoQuery.swift @@ -5,9 +5,12 @@ // Created by Joe Smith on 4/12/19. // +// Good sign of abstraction leakage +import DynamoDB + /// What type of request to make to DynamoDB public enum DynamoQueryAction { - case set, get, delete + case set, get, delete, filter } /// 🔎 A DynamoDB operation @@ -20,12 +23,28 @@ public struct DynamoQuery { /// 🍴 The name of the table in DynamoDB to work on public let table: String + /// ↪️ An optional (Globlal Secondary or Local) Index to query against + public let index: String? + /// 💸 Which value(s) to perform the action upon public let keys: [DynamoValue] - public init(action: DynamoQueryAction, table: String, keys: [DynamoValue]) { + public init(action: DynamoQueryAction, table: String, keys: [DynamoValue], index: String? = nil, expressionAttributeNames: [String: String]? = nil, expressionAttributeValues: [String: DynamoDB.AttributeValue]? = nil, keyConditionExpression: String? = nil) { self.action = action self.table = table self.keys = keys + self.index = index + + self.expressionAttributeNames = expressionAttributeNames + self.expressionAttributeValues = expressionAttributeValues + self.keyConditionExpression = keyConditionExpression } + +// Need to clean these up and figure out a better/simpler way to do queries. + /// `ExpressionAttributeNames` used when `filter`ing + public let expressionAttributeNames: [String: String]? + /// ExpressionAttributeValues used when `filter`ing + public let expressionAttributeValues: [String: DynamoDB.AttributeValue]? + /// 🔀 [KeyConditionExpression](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#API_Query_RequestSyntax) which tells DynamoDB which queries to filter for. Only used when performing a `filter` action. + public let keyConditionExpression: String? }