diff --git a/Examples/LambdaFunctions/Sources/APIGateway/main.swift b/Examples/LambdaFunctions/Sources/APIGateway/main.swift index abe0f5a5..30865c10 100644 --- a/Examples/LambdaFunctions/Sources/APIGateway/main.swift +++ b/Examples/LambdaFunctions/Sources/APIGateway/main.swift @@ -24,11 +24,11 @@ Lambda.run(APIGatewayProxyLambda()) // FIXME: Use proper Event abstractions once added to AWSLambdaRuntime struct APIGatewayProxyLambda: EventLoopLambdaHandler { - public typealias In = APIGateway.V2.Request - public typealias Out = APIGateway.V2.Response + typealias In = APIGatewayV2Request + typealias Out = APIGatewayV2Response - public func handle(context: Lambda.Context, event: APIGateway.V2.Request) -> EventLoopFuture { + func handle(context: Lambda.Context, event: APIGatewayV2Request) -> EventLoopFuture { context.logger.debug("hello, api gateway!") - return context.eventLoop.makeSucceededFuture(APIGateway.V2.Response(statusCode: .ok, body: "hello, world!")) + return context.eventLoop.makeSucceededFuture(APIGatewayV2Response(statusCode: .ok, body: "hello, world!")) } } diff --git a/Sources/AWSLambdaEvents/ALB.swift b/Sources/AWSLambdaEvents/ALB.swift index a5495399..e193f5a2 100644 --- a/Sources/AWSLambdaEvents/ALB.swift +++ b/Sources/AWSLambdaEvents/ALB.swift @@ -15,63 +15,61 @@ import class Foundation.JSONEncoder // https://github.com/aws/aws-lambda-go/blob/master/events/alb.go -public enum ALB { - /// ALBTargetGroupRequest contains data originating from the ALB Lambda target group integration - public struct TargetGroupRequest: Codable { - /// ALBTargetGroupRequestContext contains the information to identify the load balancer invoking the lambda - public struct Context: Codable { - public let elb: ELBContext - } +/// ALBTargetGroupRequest contains data originating from the ALB Lambda target group integration +public struct ALBTargetGroupRequest: Codable { + /// ALBTargetGroupRequestContext contains the information to identify the load balancer invoking the lambda + public struct Context: Codable { + public let elb: ELBContext + } - public let httpMethod: HTTPMethod - public let path: String - public let queryStringParameters: [String: String] + public let httpMethod: HTTPMethod + public let path: String + public let queryStringParameters: [String: String] - /// Depending on your configuration of your target group either `headers` or `multiValueHeaders` - /// are set. - /// - /// For more information visit: - /// https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers - public let headers: HTTPHeaders? + /// Depending on your configuration of your target group either `headers` or `multiValueHeaders` + /// are set. + /// + /// For more information visit: + /// https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers + public let headers: HTTPHeaders? - /// Depending on your configuration of your target group either `headers` or `multiValueHeaders` - /// are set. - /// - /// For more information visit: - /// https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers - public let multiValueHeaders: HTTPMultiValueHeaders? - public let requestContext: Context - public let isBase64Encoded: Bool - public let body: String? - } + /// Depending on your configuration of your target group either `headers` or `multiValueHeaders` + /// are set. + /// + /// For more information visit: + /// https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers + public let multiValueHeaders: HTTPMultiValueHeaders? + public let requestContext: Context + public let isBase64Encoded: Bool + public let body: String? /// ELBContext contains the information to identify the ARN invoking the lambda public struct ELBContext: Codable { public let targetGroupArn: String } +} - public struct TargetGroupResponse: Codable { - public var statusCode: HTTPResponseStatus - public var statusDescription: String? - public var headers: HTTPHeaders? - public var multiValueHeaders: HTTPMultiValueHeaders? - public var body: String - public var isBase64Encoded: Bool +public struct ALBTargetGroupResponse: Codable { + public var statusCode: HTTPResponseStatus + public var statusDescription: String? + public var headers: HTTPHeaders? + public var multiValueHeaders: HTTPMultiValueHeaders? + public var body: String + public var isBase64Encoded: Bool - public init( - statusCode: HTTPResponseStatus, - statusDescription: String? = nil, - headers: HTTPHeaders? = nil, - multiValueHeaders: HTTPMultiValueHeaders? = nil, - body: String = "", - isBase64Encoded: Bool = false - ) { - self.statusCode = statusCode - self.statusDescription = statusDescription - self.headers = headers - self.multiValueHeaders = multiValueHeaders - self.body = body - self.isBase64Encoded = isBase64Encoded - } + public init( + statusCode: HTTPResponseStatus, + statusDescription: String? = nil, + headers: HTTPHeaders? = nil, + multiValueHeaders: HTTPMultiValueHeaders? = nil, + body: String = "", + isBase64Encoded: Bool = false + ) { + self.statusCode = statusCode + self.statusDescription = statusDescription + self.headers = headers + self.multiValueHeaders = multiValueHeaders + self.body = body + self.isBase64Encoded = isBase64Encoded } } diff --git a/Sources/AWSLambdaEvents/APIGateway+V2.swift b/Sources/AWSLambdaEvents/APIGateway+V2.swift index 1f4f0e22..3d69e1ac 100644 --- a/Sources/AWSLambdaEvents/APIGateway+V2.swift +++ b/Sources/AWSLambdaEvents/APIGateway+V2.swift @@ -12,105 +12,97 @@ // //===----------------------------------------------------------------------===// -extension APIGateway { - public struct V2 {} -} +/// APIGatewayV2Request contains data coming from the new HTTP API Gateway +public struct APIGatewayV2Request: Codable { + /// Context contains the information to identify the AWS account and resources invoking the Lambda function. + public struct Context: Codable { + public struct HTTP: Codable { + public let method: HTTPMethod + public let path: String + public let `protocol`: String + public let sourceIp: String + public let userAgent: String + } -extension APIGateway.V2 { - /// APIGateway.V2.Request contains data coming from the new HTTP API Gateway - public struct Request: Codable { - /// Context contains the information to identify the AWS account and resources invoking the Lambda function. - public struct Context: Codable { - public struct HTTP: Codable { - public let method: HTTPMethod - public let path: String - public let `protocol`: String - public let sourceIp: String - public let userAgent: String + /// Authorizer contains authorizer information for the request context. + public struct Authorizer: Codable { + /// JWT contains JWT authorizer information for the request context. + public struct JWT: Codable { + public let claims: [String: String] + public let scopes: [String]? } - /// Authorizer contains authorizer information for the request context. - public struct Authorizer: Codable { - /// JWT contains JWT authorizer information for the request context. - public struct JWT: Codable { - public let claims: [String: String] - public let scopes: [String]? - } - - public let jwt: JWT - } + public let jwt: JWT + } - public let accountId: String - public let apiId: String - public let domainName: String - public let domainPrefix: String - public let stage: String - public let requestId: String + public let accountId: String + public let apiId: String + public let domainName: String + public let domainPrefix: String + public let stage: String + public let requestId: String - public let http: HTTP - public let authorizer: Authorizer? + public let http: HTTP + public let authorizer: Authorizer? - /// The request time in format: 23/Apr/2020:11:08:18 +0000 - public let time: String - public let timeEpoch: UInt64 - } + /// The request time in format: 23/Apr/2020:11:08:18 +0000 + public let time: String + public let timeEpoch: UInt64 + } - public let version: String - public let routeKey: String - public let rawPath: String - public let rawQueryString: String + public let version: String + public let routeKey: String + public let rawPath: String + public let rawQueryString: String - public let cookies: [String]? - public let headers: HTTPHeaders - public let queryStringParameters: [String: String]? - public let pathParameters: [String: String]? + public let cookies: [String]? + public let headers: HTTPHeaders + public let queryStringParameters: [String: String]? + public let pathParameters: [String: String]? - public let context: Context - public let stageVariables: [String: String]? + public let context: Context + public let stageVariables: [String: String]? - public let body: String? - public let isBase64Encoded: Bool + public let body: String? + public let isBase64Encoded: Bool - enum CodingKeys: String, CodingKey { - case version - case routeKey - case rawPath - case rawQueryString + enum CodingKeys: String, CodingKey { + case version + case routeKey + case rawPath + case rawQueryString - case cookies - case headers - case queryStringParameters - case pathParameters + case cookies + case headers + case queryStringParameters + case pathParameters - case context = "requestContext" - case stageVariables + case context = "requestContext" + case stageVariables - case body - case isBase64Encoded - } + case body + case isBase64Encoded } } -extension APIGateway.V2 { - public struct Response: Codable { - public var statusCode: HTTPResponseStatus - public var headers: HTTPHeaders? - public var body: String? - public var isBase64Encoded: Bool? - public var cookies: [String]? - - public init( - statusCode: HTTPResponseStatus, - headers: HTTPHeaders? = nil, - body: String? = nil, - isBase64Encoded: Bool? = nil, - cookies: [String]? = nil - ) { - self.statusCode = statusCode - self.headers = headers - self.body = body - self.isBase64Encoded = isBase64Encoded - self.cookies = cookies - } +public struct APIGatewayV2Response: Codable { + public var statusCode: HTTPResponseStatus + public var headers: HTTPHeaders? + public var body: String? + public var isBase64Encoded: Bool? + public var cookies: [String]? + + public init( + statusCode: HTTPResponseStatus, + headers: HTTPHeaders? = nil, + body: String? = nil, + isBase64Encoded: Bool? = nil, + cookies: [String]? = nil + ) { + self.statusCode = statusCode + self.headers = headers + self.body = body + self.isBase64Encoded = isBase64Encoded + self.cookies = cookies } } diff --git a/Sources/AWSLambdaEvents/APIGateway.swift b/Sources/AWSLambdaEvents/APIGateway.swift index a944cef2..4116b19c 100644 --- a/Sources/AWSLambdaEvents/APIGateway.swift +++ b/Sources/AWSLambdaEvents/APIGateway.swift @@ -17,77 +17,73 @@ import class Foundation.JSONEncoder // https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html // https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html -public enum APIGateway { - /// APIGatewayRequest contains data coming from the API Gateway - public struct Request: Codable { - public struct Context: Codable { - public struct Identity: Codable { - public let cognitoIdentityPoolId: String? +/// APIGatewayRequest contains data coming from the API Gateway +public struct APIGatewayRequest: Codable { + public struct Context: Codable { + public struct Identity: Codable { + public let cognitoIdentityPoolId: String? - public let apiKey: String? - public let userArn: String? - public let cognitoAuthenticationType: String? - public let caller: String? - public let userAgent: String? - public let user: String? + public let apiKey: String? + public let userArn: String? + public let cognitoAuthenticationType: String? + public let caller: String? + public let userAgent: String? + public let user: String? - public let cognitoAuthenticationProvider: String? - public let sourceIp: String? - public let accountId: String? - } - - public let resourceId: String - public let apiId: String - public let resourcePath: String - public let httpMethod: String - public let requestId: String - public let accountId: String - public let stage: String - - public let identity: Identity - public let extendedRequestId: String? - public let path: String + public let cognitoAuthenticationProvider: String? + public let sourceIp: String? + public let accountId: String? } - public let resource: String + public let resourceId: String + public let apiId: String + public let resourcePath: String + public let httpMethod: String + public let requestId: String + public let accountId: String + public let stage: String + + public let identity: Identity + public let extendedRequestId: String? public let path: String - public let httpMethod: HTTPMethod + } - public let queryStringParameters: [String: String]? - public let multiValueQueryStringParameters: [String: [String]]? - public let headers: HTTPHeaders - public let multiValueHeaders: HTTPMultiValueHeaders - public let pathParameters: [String: String]? - public let stageVariables: [String: String]? + public let resource: String + public let path: String + public let httpMethod: HTTPMethod - public let requestContext: Context - public let body: String? - public let isBase64Encoded: Bool - } + public let queryStringParameters: [String: String]? + public let multiValueQueryStringParameters: [String: [String]]? + public let headers: HTTPHeaders + public let multiValueHeaders: HTTPMultiValueHeaders + public let pathParameters: [String: String]? + public let stageVariables: [String: String]? + + public let requestContext: Context + public let body: String? + public let isBase64Encoded: Bool } // MARK: - Response - -extension APIGateway { - public struct Response: Codable { - public var statusCode: HTTPResponseStatus - public var headers: HTTPHeaders? - public var multiValueHeaders: HTTPMultiValueHeaders? - public var body: String? - public var isBase64Encoded: Bool? +public struct APIGatewayResponse: Codable { + public var statusCode: HTTPResponseStatus + public var headers: HTTPHeaders? + public var multiValueHeaders: HTTPMultiValueHeaders? + public var body: String? + public var isBase64Encoded: Bool? - public init( - statusCode: HTTPResponseStatus, - headers: HTTPHeaders? = nil, - multiValueHeaders: HTTPMultiValueHeaders? = nil, - body: String? = nil, - isBase64Encoded: Bool? = nil - ) { - self.statusCode = statusCode - self.headers = headers - self.multiValueHeaders = multiValueHeaders - self.body = body - self.isBase64Encoded = isBase64Encoded - } + public init( + statusCode: HTTPResponseStatus, + headers: HTTPHeaders? = nil, + multiValueHeaders: HTTPMultiValueHeaders? = nil, + body: String? = nil, + isBase64Encoded: Bool? = nil + ) { + self.statusCode = statusCode + self.headers = headers + self.multiValueHeaders = multiValueHeaders + self.body = body + self.isBase64Encoded = isBase64Encoded } } diff --git a/Sources/AWSLambdaEvents/AppSync.swift b/Sources/AWSLambdaEvents/AppSync.swift index 909cb337..51f175cd 100644 --- a/Sources/AWSLambdaEvents/AppSync.swift +++ b/Sources/AWSLambdaEvents/AppSync.swift @@ -13,157 +13,153 @@ //===----------------------------------------------------------------------===// // https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html -public enum AppSync { - public struct Event: Decodable { - public let arguments: [String: ArgumentValue] - - public enum ArgumentValue: Codable { - case string(String) - case dictionary([String: String]) - - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if let strValue = try? container.decode(String.self) { - self = .string(strValue) - } else if let dictionaryValue = try? container.decode([String: String].self) { - self = .dictionary(dictionaryValue) - } else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: """ - Unexpected AppSync argument. - Expected a String or a Dictionary. - """) - } - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .dictionary(let array): - try container.encode(array) - case .string(let str): - try container.encode(str) - } +public struct AppSyncEvent: Decodable { + public let arguments: [String: ArgumentValue] + + public enum ArgumentValue: Codable { + case string(String) + case dictionary([String: String]) + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let strValue = try? container.decode(String.self) { + self = .string(strValue) + } else if let dictionaryValue = try? container.decode([String: String].self) { + self = .dictionary(dictionaryValue) + } else { + throw DecodingError.dataCorruptedError(in: container, debugDescription: """ + Unexpected AppSync argument. + Expected a String or a Dictionary. + """) } } - public let request: Request - public struct Request: Decodable { - let headers: HTTPHeaders + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .dictionary(let array): + try container.encode(array) + case .string(let str): + try container.encode(str) + } } + } - public let source: [String: String]? - public let stash: [String: String]? + public let request: Request + public struct Request: Decodable { + let headers: HTTPHeaders + } - public let info: Info - public struct Info: Codable { - public var selectionSetList: [String] - public var selectionSetGraphQL: String - public var parentTypeName: String - public var fieldName: String - public var variables: [String: String] - } + public let source: [String: String]? + public let stash: [String: String]? - public let identity: Identity? - public enum Identity: Codable { - case iam(IAMIdentity) - case cognitoUserPools(CognitoUserPoolIdentity) - - public struct IAMIdentity: Codable { - public let accountId: String - public let cognitoIdentityPoolId: String - public let cognitoIdentityId: String - public let sourceIp: [String] - public let username: String? - public let userArn: String - public let cognitoIdentityAuthType: String - public let cognitoIdentityAuthProvider: String - } + public let info: Info + public struct Info: Codable { + public var selectionSetList: [String] + public var selectionSetGraphQL: String + public var parentTypeName: String + public var fieldName: String + public var variables: [String: String] + } - public struct CognitoUserPoolIdentity: Codable { - public let defaultAuthStrategy: String - public let issuer: String - public let sourceIp: [String] - public let sub: String - public let username: String? - - public struct Claims { - let sub: String - let emailVerified: Bool - let iss: String - let phoneNumberVerified: Bool - let cognitoUsername: String - let aud: String - let eventId: String - let tokenUse: String - let authTime: Int - let phoneNumber: String? - let exp: Int - let iat: Int - let email: String? - - enum CodingKeys: String, CodingKey { - case sub - case emailVerified = "email_verified" - case iss - case phoneNumberVerified = "phone_number_verified" - case cognitoUsername = "cognito:username" - case aud - case eventId = "event_id" - case tokenUse = "token_use" - case authTime = "auth_time" - case phoneNumber = "phone_number" - case exp - case iat - case email - } - } - } + public let identity: Identity? + public enum Identity: Codable { + case iam(IAMIdentity) + case cognitoUserPools(CognitoUserPoolIdentity) + + public struct IAMIdentity: Codable { + public let accountId: String + public let cognitoIdentityPoolId: String + public let cognitoIdentityId: String + public let sourceIp: [String] + public let username: String? + public let userArn: String + public let cognitoIdentityAuthType: String + public let cognitoIdentityAuthProvider: String + } - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if let iamIdentity = try? container.decode(IAMIdentity.self) { - self = .iam(iamIdentity) - } else if let cognitoIdentity = try? container.decode(CognitoUserPoolIdentity.self) { - self = .cognitoUserPools(cognitoIdentity) - } else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: """ - Unexpected Identity argument. - Expected a IAM Identity or a Cognito User Pool Identity. - """) + public struct CognitoUserPoolIdentity: Codable { + public let defaultAuthStrategy: String + public let issuer: String + public let sourceIp: [String] + public let sub: String + public let username: String? + + public struct Claims { + let sub: String + let emailVerified: Bool + let iss: String + let phoneNumberVerified: Bool + let cognitoUsername: String + let aud: String + let eventId: String + let tokenUse: String + let authTime: Int + let phoneNumber: String? + let exp: Int + let iat: Int + let email: String? + + enum CodingKeys: String, CodingKey { + case sub + case emailVerified = "email_verified" + case iss + case phoneNumberVerified = "phone_number_verified" + case cognitoUsername = "cognito:username" + case aud + case eventId = "event_id" + case tokenUse = "token_use" + case authTime = "auth_time" + case phoneNumber = "phone_number" + case exp + case iat + case email } } + } - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .iam(let iamIdentity): - try container.encode(iamIdentity) - case .cognitoUserPools(let cognitoUserPool): - try container.encode(cognitoUserPool) - } + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let iamIdentity = try? container.decode(IAMIdentity.self) { + self = .iam(iamIdentity) + } else if let cognitoIdentity = try? container.decode(CognitoUserPoolIdentity.self) { + self = .cognitoUserPools(cognitoIdentity) + } else { + throw DecodingError.dataCorruptedError(in: container, debugDescription: """ + Unexpected Identity argument. + Expected a IAM Identity or a Cognito User Pool Identity. + """) } } - } -} -extension AppSync { - public enum Response: Encodable { public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { - case .array(let array): - try container.encode(array) - case .object(let object): - try container.encode(object) - case .dictionary(let dictionary): - try container.encode(dictionary) + case .iam(let iamIdentity): + try container.encode(iamIdentity) + case .cognitoUserPools(let cognitoUserPool): + try container.encode(cognitoUserPool) } } + } +} - case object(ResultType) - case array([ResultType]) - case dictionary([String: ResultType]) +public enum AppSyncResponse: Encodable { + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .array(let array): + try container.encode(array) + case .object(let object): + try container.encode(object) + case .dictionary(let dictionary): + try container.encode(dictionary) + } } - public typealias JSONStringResponse = Response + case object(ResultType) + case array([ResultType]) + case dictionary([String: ResultType]) } + +public typealias AppSyncJSONResponse = AppSyncResponse diff --git a/Sources/AWSLambdaEvents/Cloudwatch.swift b/Sources/AWSLambdaEvents/Cloudwatch.swift index 4a1c59f6..2700cee3 100644 --- a/Sources/AWSLambdaEvents/Cloudwatch.swift +++ b/Sources/AWSLambdaEvents/Cloudwatch.swift @@ -15,7 +15,7 @@ import struct Foundation.Date /// EventBridge has the same events/notification types as CloudWatch -typealias EventBridge = Cloudwatch +typealias EventBridgeEvent = CloudwatchEvent public protocol CloudwatchDetail: Decodable { static var name: String { get } @@ -27,61 +27,65 @@ extension CloudwatchDetail { } } -public enum Cloudwatch { - /// CloudWatch.Event is the outer structure of an event sent via CloudWatch Events. - /// - /// **NOTE**: For examples of events that come via CloudWatch Events, see - /// https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html - /// https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html - /// https://docs.aws.amazon.com/eventbridge/latest/userguide/event-types.html - public struct Event: Decodable { - public let id: String - public let source: String - public let accountId: String - public let time: Date - public let region: AWSRegion - public let resources: [String] - public let detail: Detail - - enum CodingKeys: String, CodingKey { - case id - case source - case accountId = "account" - case time - case region - case resources - case detailType = "detail-type" - case detail - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) +/// CloudWatch.Event is the outer structure of an event sent via CloudWatch Events. +/// +/// **NOTE**: For examples of events that come via CloudWatch Events, see +/// https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html +/// https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html +/// https://docs.aws.amazon.com/eventbridge/latest/userguide/event-types.html +public struct CloudwatchEvent: Decodable { + public let id: String + public let source: String + public let accountId: String + public let time: Date + public let region: AWSRegion + public let resources: [String] + public let detail: Detail + + enum CodingKeys: String, CodingKey { + case id + case source + case accountId = "account" + case time + case region + case resources + case detailType = "detail-type" + case detail + } - self.id = try container.decode(String.self, forKey: .id) - self.source = try container.decode(String.self, forKey: .source) - self.accountId = try container.decode(String.self, forKey: .accountId) - self.time = (try container.decode(ISO8601Coding.self, forKey: .time)).wrappedValue - self.region = try container.decode(AWSRegion.self, forKey: .region) - self.resources = try container.decode([String].self, forKey: .resources) + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) - let detailType = try container.decode(String.self, forKey: .detailType) - guard detailType.lowercased() == Detail.name.lowercased() else { - throw DetailTypeMismatch(name: detailType, type: Detail.self) - } + self.id = try container.decode(String.self, forKey: .id) + self.source = try container.decode(String.self, forKey: .source) + self.accountId = try container.decode(String.self, forKey: .accountId) + self.time = (try container.decode(ISO8601Coding.self, forKey: .time)).wrappedValue + self.region = try container.decode(AWSRegion.self, forKey: .region) + self.resources = try container.decode([String].self, forKey: .resources) - self.detail = try container.decode(Detail.self, forKey: .detail) + let detailType = try container.decode(String.self, forKey: .detailType) + guard detailType.lowercased() == Detail.name.lowercased() else { + throw CloudwatchDetails.TypeMismatch(name: detailType, type: Detail.self) } + + self.detail = try container.decode(Detail.self, forKey: .detail) } +} + +// MARK: - Common Event Types - // MARK: - Common Event Types +public typealias CloudwatchScheduledEvent = CloudwatchEvent +public typealias CloudwatchEC2InstanceStateChangeNotificationEvent = + CloudwatchEvent +public typealias CloudwatchEC2SpotInstanceInterruptionNoticeEvent = + CloudwatchEvent - public typealias ScheduledEvent = Event +public enum CloudwatchDetails { public struct Scheduled: CloudwatchDetail { public static let name = "Scheduled Event" } public enum EC2 { - public typealias InstanceStateChangeNotificationEvent = Event public struct InstanceStateChangeNotification: CloudwatchDetail { public static let name = "EC2 Instance State-change Notification" @@ -102,7 +106,6 @@ public enum Cloudwatch { } } - public typealias SpotInstanceInterruptionNoticeEvent = Event public struct SpotInstanceInterruptionNotice: CloudwatchDetail { public static let name = "EC2 Spot Instance Interruption Warning" @@ -122,7 +125,7 @@ public enum Cloudwatch { } } - struct DetailTypeMismatch: Error { + struct TypeMismatch: Error { let name: String let type: Any } diff --git a/Sources/AWSLambdaEvents/DynamoDB.swift b/Sources/AWSLambdaEvents/DynamoDB.swift index f75a1135..ac095160 100644 --- a/Sources/AWSLambdaEvents/DynamoDB.swift +++ b/Sources/AWSLambdaEvents/DynamoDB.swift @@ -15,13 +15,11 @@ import struct Foundation.Date // https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html -public enum DynamoDB { - public struct Event: Decodable { - public let records: [EventRecord] +public struct DynamoDBEvent: Decodable { + public let records: [EventRecord] - public enum CodingKeys: String, CodingKey { - case records = "Records" - } + public enum CodingKeys: String, CodingKey { + case records = "Records" } public enum KeyType: String, Codable { @@ -146,7 +144,7 @@ public enum DynamoDB { } } -extension DynamoDB.StreamRecord: Decodable { +extension DynamoDBEvent.StreamRecord: Decodable { enum CodingKeys: String, CodingKey { case approximateCreationDateTime = "ApproximateCreationDateTime" case keys = "Keys" @@ -161,22 +159,22 @@ extension DynamoDB.StreamRecord: Decodable { let container = try decoder.container(keyedBy: CodingKeys.self) self.keys = try container.decode( - [String: DynamoDB.AttributeValue].self, + [String: DynamoDBEvent.AttributeValue].self, forKey: .keys ) self.newImage = try container.decodeIfPresent( - [String: DynamoDB.AttributeValue].self, + [String: DynamoDBEvent.AttributeValue].self, forKey: .newImage ) self.oldImage = try container.decodeIfPresent( - [String: DynamoDB.AttributeValue].self, + [String: DynamoDBEvent.AttributeValue].self, forKey: .oldImage ) self.sequenceNumber = try container.decode(String.self, forKey: .sequenceNumber) self.sizeBytes = try container.decode(Int64.self, forKey: .sizeBytes) - self.streamViewType = try container.decode(DynamoDB.StreamViewType.self, forKey: .streamViewType) + self.streamViewType = try container.decode(DynamoDBEvent.StreamViewType.self, forKey: .streamViewType) if let timestamp = try container.decodeIfPresent(Double.self, forKey: .approximateCreationDateTime) { self.approximateCreationDateTime = Date(timeIntervalSince1970: timestamp) @@ -188,7 +186,7 @@ extension DynamoDB.StreamRecord: Decodable { // MARK: - AttributeValue - -extension DynamoDB { +extension DynamoDBEvent { public enum AttributeValue { case boolean(Bool) case binary([UInt8]) @@ -204,7 +202,7 @@ extension DynamoDB { } } -extension DynamoDB.AttributeValue: Decodable { +extension DynamoDBEvent.AttributeValue: Decodable { enum CodingKeys: String, CodingKey { case binary = "B" case bool = "BOOL" @@ -244,11 +242,11 @@ extension DynamoDB.AttributeValue: Decodable { self = .binarySet(buffers) case .list: - let values = try container.decode([DynamoDB.AttributeValue].self, forKey: .list) + let values = try container.decode([DynamoDBEvent.AttributeValue].self, forKey: .list) self = .list(values) case .map: - let value = try container.decode([String: DynamoDB.AttributeValue].self, forKey: .map) + let value = try container.decode([String: DynamoDBEvent.AttributeValue].self, forKey: .map) self = .map(value) case .number: @@ -273,7 +271,7 @@ extension DynamoDB.AttributeValue: Decodable { } } -extension DynamoDB.AttributeValue: Equatable { +extension DynamoDBEvent.AttributeValue: Equatable { public static func == (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case (.boolean(let lhs), .boolean(let rhs)): @@ -304,7 +302,7 @@ extension DynamoDB.AttributeValue: Equatable { // MARK: DynamoDB AttributeValue Decoding -extension DynamoDB { +extension DynamoDBEvent { public struct Decoder { @usableFromInline var userInfo: [CodingUserInfoKey: Any] = [:] @@ -906,7 +904,7 @@ extension DynamoDB { } } -extension DynamoDB.AttributeValue { +extension DynamoDBEvent.AttributeValue { fileprivate var debugDataTypeDescription: String { switch self { case .list: diff --git a/Sources/AWSLambdaEvents/S3.swift b/Sources/AWSLambdaEvents/S3.swift index d90de568..81247ab7 100644 --- a/Sources/AWSLambdaEvents/S3.swift +++ b/Sources/AWSLambdaEvents/S3.swift @@ -16,27 +16,25 @@ import struct Foundation.Date // https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html -public enum S3 { - public struct Event: Decodable { - public struct Record: Decodable { - public let eventVersion: String - public let eventSource: String - public let awsRegion: AWSRegion +public struct S3Event: Decodable { + public struct Record: Decodable { + public let eventVersion: String + public let eventSource: String + public let awsRegion: AWSRegion - @ISO8601WithFractionalSecondsCoding - public var eventTime: Date - public let eventName: String - public let userIdentity: UserIdentity - public let requestParameters: RequestParameters - public let responseElements: [String: String] - public let s3: Entity - } + @ISO8601WithFractionalSecondsCoding + public var eventTime: Date + public let eventName: String + public let userIdentity: UserIdentity + public let requestParameters: RequestParameters + public let responseElements: [String: String] + public let s3: Entity + } - public let records: [Record] + public let records: [Record] - public enum CodingKeys: String, CodingKey { - case records = "Records" - } + public enum CodingKeys: String, CodingKey { + case records = "Records" } public struct RequestParameters: Codable, Equatable { diff --git a/Sources/AWSLambdaEvents/SES.swift b/Sources/AWSLambdaEvents/SES.swift index 4c5b3719..c54d82af 100644 --- a/Sources/AWSLambdaEvents/SES.swift +++ b/Sources/AWSLambdaEvents/SES.swift @@ -16,19 +16,17 @@ import struct Foundation.Date // https://docs.aws.amazon.com/lambda/latest/dg/services-ses.html -public enum SES { - public struct Event: Decodable { - public struct Record: Decodable { - public let eventSource: String - public let eventVersion: String - public let ses: Message - } +public struct SESEvent: Decodable { + public struct Record: Decodable { + public let eventSource: String + public let eventVersion: String + public let ses: Message + } - public let records: [Record] + public let records: [Record] - public enum CodingKeys: String, CodingKey { - case records = "Records" - } + public enum CodingKeys: String, CodingKey { + case records = "Records" } public struct Message: Decodable { diff --git a/Sources/AWSLambdaEvents/SNS.swift b/Sources/AWSLambdaEvents/SNS.swift index a7ec21f6..9cb41007 100644 --- a/Sources/AWSLambdaEvents/SNS.swift +++ b/Sources/AWSLambdaEvents/SNS.swift @@ -16,27 +16,25 @@ import struct Foundation.Date // https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html -public enum SNS { - public struct Event: Decodable { - public struct Record: Decodable { - public let eventVersion: String - public let eventSubscriptionArn: String - public let eventSource: String - public let sns: Message +public struct SNSEvent: Decodable { + public struct Record: Decodable { + public let eventVersion: String + public let eventSubscriptionArn: String + public let eventSource: String + public let sns: Message - public enum CodingKeys: String, CodingKey { - case eventVersion = "EventVersion" - case eventSubscriptionArn = "EventSubscriptionArn" - case eventSource = "EventSource" - case sns = "Sns" - } + public enum CodingKeys: String, CodingKey { + case eventVersion = "EventVersion" + case eventSubscriptionArn = "EventSubscriptionArn" + case eventSource = "EventSource" + case sns = "Sns" } + } - public let records: [Record] + public let records: [Record] - public enum CodingKeys: String, CodingKey { - case records = "Records" - } + public enum CodingKeys: String, CodingKey { + case records = "Records" } public struct Message { @@ -61,7 +59,7 @@ public enum SNS { } } -extension SNS.Message: Decodable { +extension SNSEvent.Message: Decodable { enum CodingKeys: String, CodingKey { case signature = "Signature" case messageId = "MessageId" @@ -77,9 +75,9 @@ extension SNS.Message: Decodable { } } -extension SNS.Message.Attribute: Equatable {} +extension SNSEvent.Message.Attribute: Equatable {} -extension SNS.Message.Attribute: Decodable { +extension SNSEvent.Message.Attribute: Decodable { enum CodingKeys: String, CodingKey { case dataType = "Type" case dataValue = "Value" diff --git a/Sources/AWSLambdaEvents/SQS.swift b/Sources/AWSLambdaEvents/SQS.swift index f2aca1fd..2af8d69f 100644 --- a/Sources/AWSLambdaEvents/SQS.swift +++ b/Sources/AWSLambdaEvents/SQS.swift @@ -14,13 +14,11 @@ // https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html -public enum SQS { - public struct Event: Decodable { - public let records: [Message] +public struct SQSEvent: Decodable { + public let records: [Message] - enum CodingKeys: String, CodingKey { - case records = "Records" - } + enum CodingKeys: String, CodingKey { + case records = "Records" } public struct Message { @@ -44,7 +42,7 @@ public enum SQS { } } -extension SQS.Message: Decodable { +extension SQSEvent.Message: Decodable { enum CodingKeys: String, CodingKey { case messageId case receiptHandle @@ -59,9 +57,9 @@ extension SQS.Message: Decodable { } } -extension SQS.Message.Attribute: Equatable {} +extension SQSEvent.Message.Attribute: Equatable {} -extension SQS.Message.Attribute: Decodable { +extension SQSEvent.Message.Attribute: Decodable { enum CodingKeys: String, CodingKey { case dataType case stringValue diff --git a/Tests/AWSLambdaEventsTests/ALBTests.swift b/Tests/AWSLambdaEventsTests/ALBTests.swift index b24684c9..5667d22b 100644 --- a/Tests/AWSLambdaEventsTests/ALBTests.swift +++ b/Tests/AWSLambdaEventsTests/ALBTests.swift @@ -49,7 +49,7 @@ class ALBTests: XCTestCase { do { let decoder = JSONDecoder() - let event = try decoder.decode(ALB.TargetGroupRequest.self, from: data) + let event = try decoder.decode(ALBTargetGroupRequest.self, from: data) XCTAssertEqual(event.httpMethod, .GET) XCTAssertEqual(event.body, "") diff --git a/Tests/AWSLambdaEventsTests/APIGateway+V2Tests.swift b/Tests/AWSLambdaEventsTests/APIGateway+V2Tests.swift index 9d682c94..c32c2d82 100644 --- a/Tests/AWSLambdaEventsTests/APIGateway+V2Tests.swift +++ b/Tests/AWSLambdaEventsTests/APIGateway+V2Tests.swift @@ -78,8 +78,8 @@ class APIGatewayV2Tests: XCTestCase { func testRequestDecodingExampleGetRequest() { let data = APIGatewayV2Tests.exampleGetEventBody.data(using: .utf8)! - var req: APIGateway.V2.Request? - XCTAssertNoThrow(req = try JSONDecoder().decode(APIGateway.V2.Request.self, from: data)) + var req: APIGatewayV2Request? + XCTAssertNoThrow(req = try JSONDecoder().decode(APIGatewayV2Request.self, from: data)) XCTAssertEqual(req?.rawPath, "/hello") XCTAssertEqual(req?.context.http.method, .GET) diff --git a/Tests/AWSLambdaEventsTests/APIGatewayTests.swift b/Tests/AWSLambdaEventsTests/APIGatewayTests.swift index 37cba98a..caa2c3be 100644 --- a/Tests/AWSLambdaEventsTests/APIGatewayTests.swift +++ b/Tests/AWSLambdaEventsTests/APIGatewayTests.swift @@ -30,8 +30,8 @@ class APIGatewayTests: XCTestCase { func testRequestDecodingExampleGetRequest() { let data = APIGatewayTests.exampleGetEventBody.data(using: .utf8)! - var req: APIGateway.Request? - XCTAssertNoThrow(req = try JSONDecoder().decode(APIGateway.Request.self, from: data)) + var req: APIGatewayRequest? + XCTAssertNoThrow(req = try JSONDecoder().decode(APIGatewayRequest.self, from: data)) XCTAssertEqual(req?.path, "/test") XCTAssertEqual(req?.httpMethod, .GET) @@ -39,8 +39,8 @@ class APIGatewayTests: XCTestCase { func testRequestDecodingTodoPostRequest() { let data = APIGatewayTests.todoPostEventBody.data(using: .utf8)! - var req: APIGateway.Request? - XCTAssertNoThrow(req = try JSONDecoder().decode(APIGateway.Request.self, from: data)) + var req: APIGatewayRequest? + XCTAssertNoThrow(req = try JSONDecoder().decode(APIGatewayRequest.self, from: data)) XCTAssertEqual(req?.path, "/todos") XCTAssertEqual(req?.httpMethod, .POST) @@ -58,7 +58,7 @@ class APIGatewayTests: XCTestCase { } func testResponseEncoding() { - let resp = APIGateway.Response( + let resp = APIGatewayResponse( statusCode: .ok, headers: ["Server": "Test"], body: "abc123" diff --git a/Tests/AWSLambdaEventsTests/AppSyncTests.swift b/Tests/AWSLambdaEventsTests/AppSyncTests.swift index 5aeda17d..c21a1bcc 100644 --- a/Tests/AWSLambdaEventsTests/AppSyncTests.swift +++ b/Tests/AWSLambdaEventsTests/AppSyncTests.swift @@ -97,8 +97,8 @@ class AppSyncTests: XCTestCase { func testRequestDecodingExampleEvent() { let data = AppSyncTests.exampleEventBody.data(using: .utf8)! - var event: AppSync.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(AppSync.Event.self, from: data)) + var event: AppSyncEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(AppSyncEvent.self, from: data)) XCTAssertNotNil(event?.arguments) XCTAssertEqual(event?.arguments["id"], .string("my identifier")) @@ -171,8 +171,8 @@ class AppSyncTests: XCTestCase { """ let data = eventBody.data(using: .utf8)! - var event: AppSync.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(AppSync.Event.self, from: data)) + var event: AppSyncEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(AppSyncEvent.self, from: data)) XCTAssertEqual(event?.source?["name"], "Hello") XCTAssertTrue(event?.stash?.isEmpty ?? false, "stash dictionary must be empty") XCTAssertNil(event?.identity) @@ -239,8 +239,8 @@ class AppSyncTests: XCTestCase { """ let data = eventBody.data(using: .utf8)! - var event: AppSync.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(AppSync.Event.self, from: data)) + var event: AppSyncEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(AppSyncEvent.self, from: data)) switch event?.identity { case .iam(let iamIdentity): XCTAssertEqual(iamIdentity.accountId, "accountId1") @@ -257,7 +257,7 @@ class AppSyncTests: XCTestCase { } } -extension AppSync.Event.ArgumentValue: Equatable { +extension AppSyncEvent.ArgumentValue: Equatable { public static func == (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case (.string(let lhsString), .string(let rhsString)): diff --git a/Tests/AWSLambdaEventsTests/CloudwatchTests.swift b/Tests/AWSLambdaEventsTests/CloudwatchTests.swift index b931e020..561d170a 100644 --- a/Tests/AWSLambdaEventsTests/CloudwatchTests.swift +++ b/Tests/AWSLambdaEventsTests/CloudwatchTests.swift @@ -34,10 +34,10 @@ class CloudwatchTests: XCTestCase { } func testScheduledEventFromJSON() { - let eventBody = CloudwatchTests.eventBody(type: Cloudwatch.Scheduled.name, details: "{}") + let eventBody = CloudwatchTests.eventBody(type: CloudwatchDetails.Scheduled.name, details: "{}") let data = eventBody.data(using: .utf8)! - var maybeEvent: Cloudwatch.ScheduledEvent? - XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(Cloudwatch.ScheduledEvent.self, from: data)) + var maybeEvent: CloudwatchScheduledEvent? + XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(CloudwatchScheduledEvent.self, from: data)) guard let event = maybeEvent else { return XCTFail("Expected to have an event") @@ -52,11 +52,11 @@ class CloudwatchTests: XCTestCase { } func testEC2InstanceStateChangeNotificationEventFromJSON() { - let eventBody = CloudwatchTests.eventBody(type: Cloudwatch.EC2.InstanceStateChangeNotification.name, + let eventBody = CloudwatchTests.eventBody(type: CloudwatchDetails.EC2.InstanceStateChangeNotification.name, details: "{ \"instance-id\": \"0\", \"state\": \"stopping\" }") let data = eventBody.data(using: .utf8)! - var maybeEvent: Cloudwatch.EC2.InstanceStateChangeNotificationEvent? - XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(Cloudwatch.EC2.InstanceStateChangeNotificationEvent.self, from: data)) + var maybeEvent: CloudwatchEC2InstanceStateChangeNotificationEvent? + XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(CloudwatchEC2InstanceStateChangeNotificationEvent.self, from: data)) guard let event = maybeEvent else { return XCTFail("Expected to have an event") @@ -73,11 +73,11 @@ class CloudwatchTests: XCTestCase { } func testEC2SpotInstanceInterruptionNoticeEventFromJSON() { - let eventBody = CloudwatchTests.eventBody(type: Cloudwatch.EC2.SpotInstanceInterruptionNotice.name, + let eventBody = CloudwatchTests.eventBody(type: CloudwatchDetails.EC2.SpotInstanceInterruptionNotice.name, details: "{ \"instance-id\": \"0\", \"instance-action\": \"terminate\" }") let data = eventBody.data(using: .utf8)! - var maybeEvent: Cloudwatch.EC2.SpotInstanceInterruptionNoticeEvent? - XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(Cloudwatch.EC2.SpotInstanceInterruptionNoticeEvent.self, from: data)) + var maybeEvent: CloudwatchEC2SpotInstanceInterruptionNoticeEvent? + XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(CloudwatchEC2SpotInstanceInterruptionNoticeEvent.self, from: data)) guard let event = maybeEvent else { return XCTFail("Expected to have an event") @@ -102,8 +102,8 @@ class CloudwatchTests: XCTestCase { let eventBody = CloudwatchTests.eventBody(type: Custom.name, details: "{ \"name\": \"foo\" }") let data = eventBody.data(using: .utf8)! - var maybeEvent: Cloudwatch.Event? - XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(Cloudwatch.Event.self, from: data)) + var maybeEvent: CloudwatchEvent? + XCTAssertNoThrow(maybeEvent = try JSONDecoder().decode(CloudwatchEvent.self, from: data)) guard let event = maybeEvent else { return XCTFail("Expected to have an event") @@ -121,17 +121,17 @@ class CloudwatchTests: XCTestCase { func testUnregistredType() { let eventBody = CloudwatchTests.eventBody(type: UUID().uuidString, details: "{}") let data = eventBody.data(using: .utf8)! - XCTAssertThrowsError(try JSONDecoder().decode(Cloudwatch.ScheduledEvent.self, from: data)) { error in - XCTAssert(error is Cloudwatch.DetailTypeMismatch, "expected DetailTypeMismatch but received \(error)") + XCTAssertThrowsError(try JSONDecoder().decode(CloudwatchScheduledEvent.self, from: data)) { error in + XCTAssert(error is CloudwatchDetails.TypeMismatch, "expected DetailTypeMismatch but received \(error)") } } func testTypeMismatch() { - let eventBody = CloudwatchTests.eventBody(type: Cloudwatch.EC2.InstanceStateChangeNotification.name, + let eventBody = CloudwatchTests.eventBody(type: CloudwatchDetails.EC2.InstanceStateChangeNotification.name, details: "{ \"instance-id\": \"0\", \"state\": \"stopping\" }") let data = eventBody.data(using: .utf8)! - XCTAssertThrowsError(try JSONDecoder().decode(Cloudwatch.ScheduledEvent.self, from: data)) { error in - XCTAssert(error is Cloudwatch.DetailTypeMismatch, "expected DetailTypeMismatch but received \(error)") + XCTAssertThrowsError(try JSONDecoder().decode(CloudwatchScheduledEvent.self, from: data)) { error in + XCTAssert(error is CloudwatchDetails.TypeMismatch, "expected DetailTypeMismatch but received \(error)") } } } diff --git a/Tests/AWSLambdaEventsTests/DynamoDBTests.swift b/Tests/AWSLambdaEventsTests/DynamoDBTests.swift index 91745ff6..cd6ac50f 100644 --- a/Tests/AWSLambdaEventsTests/DynamoDBTests.swift +++ b/Tests/AWSLambdaEventsTests/DynamoDBTests.swift @@ -114,8 +114,8 @@ class DynamoDBTests: XCTestCase { func testEventFromJSON() { let data = DynamoDBTests.streamEventBody.data(using: .utf8)! - var event: DynamoDB.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(DynamoDB.Event.self, from: data)) + var event: DynamoDBEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(DynamoDBEvent.self, from: data)) XCTAssertEqual(event?.records.count, 3) } @@ -124,71 +124,71 @@ class DynamoDBTests: XCTestCase { func testAttributeValueBoolDecoding() { let json = "{\"BOOL\": true}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .boolean(true)) } func testAttributeValueBinaryDecoding() { let json = "{\"B\": \"YmFzZTY0\"}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .binary([UInt8]("base64".utf8))) } func testAttributeValueBinarySetDecoding() { let json = "{\"BS\": [\"YmFzZTY0\", \"YWJjMTIz\"]}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .binarySet([[UInt8]("base64".utf8), [UInt8]("abc123".utf8)])) } func testAttributeValueStringDecoding() { let json = "{\"S\": \"huhu\"}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .string("huhu")) } func testAttributeValueStringSetDecoding() { let json = "{\"SS\": [\"huhu\", \"haha\"]}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .stringSet(["huhu", "haha"])) } func testAttributeValueNullDecoding() { let json = "{\"NULL\": true}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .null) } func testAttributeValueNumberDecoding() { let json = "{\"N\": \"1.2345\"}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .number("1.2345")) } func testAttributeValueNumberSetDecoding() { let json = "{\"NS\": [\"1.2345\", \"-19\"]}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .numberSet(["1.2345", "-19"])) } func testAttributeValueListDecoding() { let json = "{\"L\": [{\"NS\": [\"1.2345\", \"-19\"]}, {\"S\": \"huhu\"}]}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .list([.numberSet(["1.2345", "-19"]), .string("huhu")])) } func testAttributeValueMapDecoding() { let json = "{\"M\": {\"numbers\": {\"NS\": [\"1.2345\", \"-19\"]}, \"string\": {\"S\": \"huhu\"}}}" - var value: DynamoDB.AttributeValue? - XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) + var value: DynamoDBEvent.AttributeValue? + XCTAssertNoThrow(value = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) XCTAssertEqual(value, .map([ "numbers": .numberSet(["1.2345", "-19"]), "string": .string("huhu"), @@ -197,7 +197,7 @@ class DynamoDBTests: XCTestCase { func testAttributeValueEmptyDecoding() { let json = "{\"haha\": 1}" - XCTAssertThrowsError(_ = try JSONDecoder().decode(DynamoDB.AttributeValue.self, from: json.data(using: .utf8)!)) { error in + XCTAssertThrowsError(_ = try JSONDecoder().decode(DynamoDBEvent.AttributeValue.self, from: json.data(using: .utf8)!)) { error in guard case DecodingError.dataCorrupted = error else { XCTFail("Unexpected error: \(String(describing: error))") return @@ -206,15 +206,15 @@ class DynamoDBTests: XCTestCase { } func testAttributeValueEquatable() { - XCTAssertEqual(DynamoDB.AttributeValue.boolean(true), .boolean(true)) - XCTAssertNotEqual(DynamoDB.AttributeValue.boolean(true), .boolean(false)) - XCTAssertNotEqual(DynamoDB.AttributeValue.boolean(true), .string("haha")) + XCTAssertEqual(DynamoDBEvent.AttributeValue.boolean(true), .boolean(true)) + XCTAssertNotEqual(DynamoDBEvent.AttributeValue.boolean(true), .boolean(false)) + XCTAssertNotEqual(DynamoDBEvent.AttributeValue.boolean(true), .string("haha")) } // MARK: - DynamoDB Decoder Tests - func testDecoderSimple() { - let value: [String: DynamoDB.AttributeValue] = [ + let value: [String: DynamoDBEvent.AttributeValue] = [ "foo": .string("bar"), "xyz": .number("123"), ] @@ -225,7 +225,7 @@ class DynamoDBTests: XCTestCase { } var test: Test? - XCTAssertNoThrow(test = try DynamoDB.Decoder().decode(Test.self, from: value)) + XCTAssertNoThrow(test = try DynamoDBEvent.Decoder().decode(Test.self, from: value)) XCTAssertEqual(test?.foo, "bar") XCTAssertEqual(test?.xyz, 123) } diff --git a/Tests/AWSLambdaEventsTests/S3Tests.swift b/Tests/AWSLambdaEventsTests/S3Tests.swift index 5c6d240c..217a934a 100644 --- a/Tests/AWSLambdaEventsTests/S3Tests.swift +++ b/Tests/AWSLambdaEventsTests/S3Tests.swift @@ -98,10 +98,10 @@ class S3Tests: XCTestCase { } """ - func testObjectCreatedEvent() { + func testSimpleEventFromJSON() { let data = S3Tests.eventBodyObjectCreated.data(using: .utf8)! - var event: S3.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(S3.Event.self, from: data)) + var event: S3Event? + XCTAssertNoThrow(event = try JSONDecoder().decode(S3Event.self, from: data)) guard let record = event?.records.first else { XCTFail("Expected to have one record") @@ -113,13 +113,13 @@ class S3Tests: XCTestCase { XCTAssertEqual(record.awsRegion, .eu_central_1) XCTAssertEqual(record.eventName, "ObjectCreated:Put") XCTAssertEqual(record.eventTime, Date(timeIntervalSince1970: 1_578_907_540.621)) - XCTAssertEqual(record.userIdentity, S3.UserIdentity(principalId: "AWS:AAAAAAAJ2MQ4YFQZ7AULJ")) - XCTAssertEqual(record.requestParameters, S3.RequestParameters(sourceIPAddress: "123.123.123.123")) + XCTAssertEqual(record.userIdentity, S3Event.UserIdentity(principalId: "AWS:AAAAAAAJ2MQ4YFQZ7AULJ")) + XCTAssertEqual(record.requestParameters, S3Event.RequestParameters(sourceIPAddress: "123.123.123.123")) XCTAssertEqual(record.responseElements.count, 2) XCTAssertEqual(record.s3.schemaVersion, "1.0") XCTAssertEqual(record.s3.configurationId, "98b55bc4-3c0c-4007-b727-c6b77a259dde") XCTAssertEqual(record.s3.bucket.name, "eventsources") - XCTAssertEqual(record.s3.bucket.ownerIdentity, S3.UserIdentity(principalId: "AAAAAAAAAAAAAA")) + XCTAssertEqual(record.s3.bucket.ownerIdentity, S3Event.UserIdentity(principalId: "AAAAAAAAAAAAAA")) XCTAssertEqual(record.s3.bucket.arn, "arn:aws:s3:::eventsources") XCTAssertEqual(record.s3.object.key, "Hi.md") XCTAssertEqual(record.s3.object.size, 2880) @@ -129,8 +129,8 @@ class S3Tests: XCTestCase { func testObjectRemovedEvent() { let data = S3Tests.eventBodyObjectRemoved.data(using: .utf8)! - var event: S3.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(S3.Event.self, from: data)) + var event: S3Event? + XCTAssertNoThrow(event = try JSONDecoder().decode(S3Event.self, from: data)) guard let record = event?.records.first else { XCTFail("Expected to have one record") @@ -142,13 +142,13 @@ class S3Tests: XCTestCase { XCTAssertEqual(record.awsRegion, .eu_central_1) XCTAssertEqual(record.eventName, "ObjectRemoved:DeleteMarkerCreated") XCTAssertEqual(record.eventTime, Date(timeIntervalSince1970: 1_578_907_540.621)) - XCTAssertEqual(record.userIdentity, S3.UserIdentity(principalId: "AWS:AAAAAAAJ2MQ4YFQZ7AULJ")) - XCTAssertEqual(record.requestParameters, S3.RequestParameters(sourceIPAddress: "123.123.123.123")) + XCTAssertEqual(record.userIdentity, S3Event.UserIdentity(principalId: "AWS:AAAAAAAJ2MQ4YFQZ7AULJ")) + XCTAssertEqual(record.requestParameters, S3Event.RequestParameters(sourceIPAddress: "123.123.123.123")) XCTAssertEqual(record.responseElements.count, 2) XCTAssertEqual(record.s3.schemaVersion, "1.0") XCTAssertEqual(record.s3.configurationId, "98b55bc4-3c0c-4007-b727-c6b77a259dde") XCTAssertEqual(record.s3.bucket.name, "eventsources") - XCTAssertEqual(record.s3.bucket.ownerIdentity, S3.UserIdentity(principalId: "AAAAAAAAAAAAAA")) + XCTAssertEqual(record.s3.bucket.ownerIdentity, S3Event.UserIdentity(principalId: "AAAAAAAAAAAAAA")) XCTAssertEqual(record.s3.bucket.arn, "arn:aws:s3:::eventsources") XCTAssertEqual(record.s3.object.key, "Hi.md") XCTAssertNil(record.s3.object.size) diff --git a/Tests/AWSLambdaEventsTests/SESTests.swift b/Tests/AWSLambdaEventsTests/SESTests.swift index 0f4b417d..3a838e16 100644 --- a/Tests/AWSLambdaEventsTests/SESTests.swift +++ b/Tests/AWSLambdaEventsTests/SESTests.swift @@ -87,8 +87,8 @@ class SESTests: XCTestCase { func testSimpleEventFromJSON() { let data = Data(SESTests.eventBody.utf8) - var event: SES.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(SES.Event.self, from: data)) + var event: SESEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(SESEvent.self, from: data)) guard let record = event?.records.first else { XCTFail("Expected to have one record") diff --git a/Tests/AWSLambdaEventsTests/SNSTests.swift b/Tests/AWSLambdaEventsTests/SNSTests.swift index 916a69ea..df0dd9fb 100644 --- a/Tests/AWSLambdaEventsTests/SNSTests.swift +++ b/Tests/AWSLambdaEventsTests/SNSTests.swift @@ -52,8 +52,8 @@ class SNSTests: XCTestCase { func testSimpleEventFromJSON() { let data = SNSTests.eventBody.data(using: .utf8)! - var event: SNS.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(SNS.Event.self, from: data)) + var event: SNSEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(SNSEvent.self, from: data)) guard let record = event?.records.first else { XCTFail("Expected to have one record") diff --git a/Tests/AWSLambdaEventsTests/SQSTests.swift b/Tests/AWSLambdaEventsTests/SQSTests.swift index ca8e3c70..cd28972c 100644 --- a/Tests/AWSLambdaEventsTests/SQSTests.swift +++ b/Tests/AWSLambdaEventsTests/SQSTests.swift @@ -61,8 +61,8 @@ class SQSTests: XCTestCase { func testSimpleEventFromJSON() { let data = SQSTests.eventBody.data(using: .utf8)! - var event: SQS.Event? - XCTAssertNoThrow(event = try JSONDecoder().decode(SQS.Event.self, from: data)) + var event: SQSEvent? + XCTAssertNoThrow(event = try JSONDecoder().decode(SQSEvent.self, from: data)) guard let message = event?.records.first else { XCTFail("Expected to have one message in the event")