diff --git a/Examples/Simple/Sources/APIGateway/APIGatewayProxyLambda.swift b/Examples/Simple/Sources/APIGateway/APIGatewayProxyLambda.swift index cd9bd6b..ab5a476 100644 --- a/Examples/Simple/Sources/APIGateway/APIGatewayProxyLambda.swift +++ b/Examples/Simple/Sources/APIGateway/APIGatewayProxyLambda.swift @@ -24,7 +24,7 @@ struct APIGatewayProxyLambda: LambdaHandler { typealias Event = APIGatewayV2Request typealias Output = APIGatewayV2Response - init(context: Lambda.InitializationContext) async throws {} + init(context: LambdaInitializationContext) async throws {} func handle(_ request: APIGatewayV2Request, context: LambdaContext) async throws -> APIGatewayV2Response { context.logger.debug("hello, api gateway!") diff --git a/Sources/AWSLambdaEvents/ALB.swift b/Sources/AWSLambdaEvents/ALB.swift index e193f5a..ce0c6a9 100644 --- a/Sources/AWSLambdaEvents/ALB.swift +++ b/Sources/AWSLambdaEvents/ALB.swift @@ -16,9 +16,9 @@ import class Foundation.JSONEncoder // https://github.com/aws/aws-lambda-go/blob/master/events/alb.go /// ALBTargetGroupRequest contains data originating from the ALB Lambda target group integration -public struct ALBTargetGroupRequest: Codable { +public struct ALBTargetGroupRequest: AWSLambdaEvent { /// ALBTargetGroupRequestContext contains the information to identify the load balancer invoking the lambda - public struct Context: Codable { + public struct Context: AWSLambdaEvent { public let elb: ELBContext } @@ -44,12 +44,12 @@ public struct ALBTargetGroupRequest: Codable { public let body: String? /// ELBContext contains the information to identify the ARN invoking the lambda - public struct ELBContext: Codable { + public struct ELBContext: AWSLambdaEvent { public let targetGroupArn: String } } -public struct ALBTargetGroupResponse: Codable { +public struct ALBTargetGroupResponse: AWSLambdaEvent { public var statusCode: HTTPResponseStatus public var statusDescription: String? public var headers: HTTPHeaders? diff --git a/Sources/AWSLambdaEvents/APIGateway+V2.swift b/Sources/AWSLambdaEvents/APIGateway+V2.swift index 4579db2..d640a2e 100644 --- a/Sources/AWSLambdaEvents/APIGateway+V2.swift +++ b/Sources/AWSLambdaEvents/APIGateway+V2.swift @@ -13,10 +13,10 @@ //===----------------------------------------------------------------------===// /// APIGatewayV2Request contains data coming from the new HTTP API Gateway -public struct APIGatewayV2Request: Codable { +public struct APIGatewayV2Request: AWSLambdaEvent { /// Context contains the information to identify the AWS account and resources invoking the Lambda function. - public struct Context: Codable { - public struct HTTP: Codable { + public struct Context: AWSLambdaEvent { + public struct HTTP: AWSLambdaEvent { public let method: HTTPMethod public let path: String public let `protocol`: String @@ -25,9 +25,9 @@ public struct APIGatewayV2Request: Codable { } /// Authorizer contains authorizer information for the request context. - public struct Authorizer: Codable { + public struct Authorizer: AWSLambdaEvent { /// JWT contains JWT authorizer information for the request context. - public struct JWT: Codable { + public struct JWT: AWSLambdaEvent { public let claims: [String: String]? public let scopes: [String]? } diff --git a/Sources/AWSLambdaEvents/APIGateway.swift b/Sources/AWSLambdaEvents/APIGateway.swift index 4116b19..858126c 100644 --- a/Sources/AWSLambdaEvents/APIGateway.swift +++ b/Sources/AWSLambdaEvents/APIGateway.swift @@ -18,9 +18,9 @@ import class Foundation.JSONEncoder // https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html /// APIGatewayRequest contains data coming from the API Gateway -public struct APIGatewayRequest: Codable { - public struct Context: Codable { - public struct Identity: Codable { +public struct APIGatewayRequest: AWSLambdaEvent { + public struct Context: AWSLambdaEvent { + public struct Identity: AWSLambdaEvent { public let cognitoIdentityPoolId: String? public let apiKey: String? diff --git a/Sources/AWSLambdaEvents/AWSLambdaEvent.swift b/Sources/AWSLambdaEvents/AWSLambdaEvent.swift new file mode 100644 index 0000000..99616bc --- /dev/null +++ b/Sources/AWSLambdaEvents/AWSLambdaEvent.swift @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftAWSLambdaRuntime open source project +// +// Copyright (c) 2022 Apple Inc. and the SwiftAWSLambdaRuntime project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public protocol AWSLambdaEvent: Decodable, _AWSLambdaEventsSendable {} diff --git a/Sources/AWSLambdaEvents/AWSRegion.swift b/Sources/AWSLambdaEvents/AWSRegion.swift index e884d3a..3e16be9 100644 --- a/Sources/AWSLambdaEvents/AWSRegion.swift +++ b/Sources/AWSLambdaEvents/AWSRegion.swift @@ -16,7 +16,7 @@ // $ aws ssm get-parameters-by-path --path /aws/service/global-infrastructure/services/lambda/regions --output json /// Enumeration of the AWS Regions. -public struct AWSRegion: RawRepresentable, Equatable { +public struct AWSRegion: RawRepresentable, Equatable, _AWSLambdaEventsSendable { public typealias RawValue = String public let rawValue: String diff --git a/Sources/AWSLambdaEvents/AppSync.swift b/Sources/AWSLambdaEvents/AppSync.swift index 51f175c..9248e88 100644 --- a/Sources/AWSLambdaEvents/AppSync.swift +++ b/Sources/AWSLambdaEvents/AppSync.swift @@ -13,10 +13,10 @@ //===----------------------------------------------------------------------===// // https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html -public struct AppSyncEvent: Decodable { +public struct AppSyncEvent: AWSLambdaEvent { public let arguments: [String: ArgumentValue] - public enum ArgumentValue: Codable { + public enum ArgumentValue: AWSLambdaEvent { case string(String) case dictionary([String: String]) @@ -46,7 +46,7 @@ public struct AppSyncEvent: Decodable { } public let request: Request - public struct Request: Decodable { + public struct Request: AWSLambdaEvent { let headers: HTTPHeaders } @@ -54,7 +54,7 @@ public struct AppSyncEvent: Decodable { public let stash: [String: String]? public let info: Info - public struct Info: Codable { + public struct Info: AWSLambdaEvent { public var selectionSetList: [String] public var selectionSetGraphQL: String public var parentTypeName: String @@ -63,11 +63,11 @@ public struct AppSyncEvent: Decodable { } public let identity: Identity? - public enum Identity: Codable { + public enum Identity: AWSLambdaEvent { case iam(IAMIdentity) case cognitoUserPools(CognitoUserPoolIdentity) - public struct IAMIdentity: Codable { + public struct IAMIdentity: AWSLambdaEvent { public let accountId: String public let cognitoIdentityPoolId: String public let cognitoIdentityId: String @@ -78,7 +78,7 @@ public struct AppSyncEvent: Decodable { public let cognitoIdentityAuthProvider: String } - public struct CognitoUserPoolIdentity: Codable { + public struct CognitoUserPoolIdentity: AWSLambdaEvent { public let defaultAuthStrategy: String public let issuer: String public let sourceIp: [String] @@ -131,16 +131,6 @@ public struct AppSyncEvent: Decodable { """) } } - - 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) - } - } } } diff --git a/Sources/AWSLambdaEvents/Cloudwatch.swift b/Sources/AWSLambdaEvents/Cloudwatch.swift index 2700cee..6a641f2 100644 --- a/Sources/AWSLambdaEvents/Cloudwatch.swift +++ b/Sources/AWSLambdaEvents/Cloudwatch.swift @@ -12,12 +12,16 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=5.6) +@preconcurrency import struct Foundation.Date +#else import struct Foundation.Date +#endif /// EventBridge has the same events/notification types as CloudWatch typealias EventBridgeEvent = CloudwatchEvent -public protocol CloudwatchDetail: Decodable { +public protocol CloudwatchDetail: AWSLambdaEvent { static var name: String { get } } @@ -33,7 +37,7 @@ extension CloudwatchDetail { /// 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 struct CloudwatchEvent: AWSLambdaEvent { public let id: String public let source: String public let accountId: String @@ -89,7 +93,7 @@ public enum CloudwatchDetails { public struct InstanceStateChangeNotification: CloudwatchDetail { public static let name = "EC2 Instance State-change Notification" - public enum State: String, Codable { + public enum State: String, AWSLambdaEvent { case running case shuttingDown = "shutting-down" case stopped @@ -109,7 +113,7 @@ public enum CloudwatchDetails { public struct SpotInstanceInterruptionNotice: CloudwatchDetail { public static let name = "EC2 Spot Instance Interruption Warning" - public enum Action: String, Codable { + public enum Action: String, AWSLambdaEvent { case hibernate case stop case terminate diff --git a/Sources/AWSLambdaEvents/DynamoDB.swift b/Sources/AWSLambdaEvents/DynamoDB.swift index ac09516..3c9c54f 100644 --- a/Sources/AWSLambdaEvents/DynamoDB.swift +++ b/Sources/AWSLambdaEvents/DynamoDB.swift @@ -12,28 +12,32 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=5.6) +@preconcurrency import struct Foundation.Date +#else import struct Foundation.Date +#endif // https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html -public struct DynamoDBEvent: Decodable { +public struct DynamoDBEvent: AWSLambdaEvent { public let records: [EventRecord] public enum CodingKeys: String, CodingKey { case records = "Records" } - public enum KeyType: String, Codable { + public enum KeyType: String, AWSLambdaEvent { case hash = "HASH" case range = "RANGE" } - public enum OperationType: String, Codable { + public enum OperationType: String, AWSLambdaEvent { case insert = "INSERT" case modify = "MODIFY" case remove = "REMOVE" } - public enum SharedIteratorType: String, Codable { + public enum SharedIteratorType: String, AWSLambdaEvent { case trimHorizon = "TRIM_HORIZON" case latest = "LATEST" case atSequenceNumber = "AT_SEQUENCE_NUMBER" @@ -47,7 +51,7 @@ public struct DynamoDBEvent: Decodable { case disabled = "DISABLED" } - public enum StreamViewType: String, Codable { + public enum StreamViewType: String, AWSLambdaEvent { /// the entire item, as it appeared after it was modified. case newImage = "NEW_IMAGE" /// the entire item, as it appeared before it was modified. @@ -58,7 +62,7 @@ public struct DynamoDBEvent: Decodable { case keysOnly = "KEYS_ONLY" } - public struct EventRecord: Decodable { + public struct EventRecord: AWSLambdaEvent { /// The region in which the GetRecords request was received. public let awsRegion: AWSRegion @@ -113,7 +117,7 @@ public struct DynamoDBEvent: Decodable { } } - public struct StreamRecord { + public struct StreamRecord: AWSLambdaEvent { /// The approximate date and time when the stream record was created, in UNIX /// epoch time (http://www.epochconverter.com/) format. public let approximateCreationDateTime: Date? @@ -138,7 +142,7 @@ public struct DynamoDBEvent: Decodable { public let streamViewType: StreamViewType } - public struct UserIdentity: Codable { + public struct UserIdentity: AWSLambdaEvent { public let type: String public let principalId: String } @@ -187,7 +191,7 @@ extension DynamoDBEvent.StreamRecord: Decodable { // MARK: - AttributeValue - extension DynamoDBEvent { - public enum AttributeValue { + public enum AttributeValue: AWSLambdaEvent { case boolean(Bool) case binary([UInt8]) case binarySet([[UInt8]]) diff --git a/Sources/AWSLambdaEvents/S3.swift b/Sources/AWSLambdaEvents/S3.swift index 81247ab..f30bd02 100644 --- a/Sources/AWSLambdaEvents/S3.swift +++ b/Sources/AWSLambdaEvents/S3.swift @@ -16,8 +16,8 @@ import struct Foundation.Date // https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html -public struct S3Event: Decodable { - public struct Record: Decodable { +public struct S3Event: AWSLambdaEvent { + public struct Record: AWSLambdaEvent { public let eventVersion: String public let eventSource: String public let awsRegion: AWSRegion @@ -37,15 +37,15 @@ public struct S3Event: Decodable { case records = "Records" } - public struct RequestParameters: Codable, Equatable { + public struct RequestParameters: AWSLambdaEvent, Equatable { public let sourceIPAddress: String } - public struct UserIdentity: Codable, Equatable { + public struct UserIdentity: AWSLambdaEvent, Equatable { public let principalId: String } - public struct Entity: Codable { + public struct Entity: AWSLambdaEvent { public let configurationId: String public let schemaVersion: String public let bucket: Bucket @@ -59,13 +59,13 @@ public struct S3Event: Decodable { } } - public struct Bucket: Codable { + public struct Bucket: AWSLambdaEvent { public let name: String public let ownerIdentity: UserIdentity public let arn: String } - public struct Object: Codable { + public struct Object: AWSLambdaEvent { public let key: String /// The object's size in bytes. /// diff --git a/Sources/AWSLambdaEvents/SES.swift b/Sources/AWSLambdaEvents/SES.swift index 6e5a0e7..509835d 100644 --- a/Sources/AWSLambdaEvents/SES.swift +++ b/Sources/AWSLambdaEvents/SES.swift @@ -16,8 +16,8 @@ import struct Foundation.Date // https://docs.aws.amazon.com/lambda/latest/dg/services-ses.html -public struct SESEvent: Decodable { - public struct Record: Decodable { +public struct SESEvent: AWSLambdaEvent { + public struct Record: AWSLambdaEvent { public let eventSource: String public let eventVersion: String public let ses: Message @@ -29,12 +29,12 @@ public struct SESEvent: Decodable { case records = "Records" } - public struct Message: Decodable { + public struct Message: AWSLambdaEvent { public let mail: Mail public let receipt: Receipt } - public struct Mail: Decodable { + public struct Mail: AWSLambdaEvent { public let commonHeaders: CommonHeaders public let destination: [String] public let headers: [Header] @@ -44,7 +44,7 @@ public struct SESEvent: Decodable { @ISO8601WithFractionalSecondsCoding public var timestamp: Date } - public struct CommonHeaders: Decodable { + public struct CommonHeaders: AWSLambdaEvent { public let bcc: [String]? public let cc: [String]? @RFC5322DateTimeCoding public var date: Date @@ -55,12 +55,12 @@ public struct SESEvent: Decodable { public let to: [String]? } - public struct Header: Decodable { + public struct Header: AWSLambdaEvent { public let name: String public let value: String } - public struct Receipt: Decodable { + public struct Receipt: AWSLambdaEvent { public let action: Action public let dmarcPolicy: DMARCPolicy? public let dmarcVerdict: Verdict? @@ -73,23 +73,23 @@ public struct SESEvent: Decodable { public let virusVerdict: Verdict } - public struct Action: Decodable { + public struct Action: AWSLambdaEvent { public let functionArn: String public let invocationType: String public let type: String } - public struct Verdict: Decodable { + public struct Verdict: AWSLambdaEvent { public let status: Status } - public enum DMARCPolicy: String, Decodable { + public enum DMARCPolicy: String, AWSLambdaEvent { case none case quarantine case reject } - public enum Status: String, Decodable { + public enum Status: String, AWSLambdaEvent { case pass = "PASS" case fail = "FAIL" case gray = "GRAY" diff --git a/Sources/AWSLambdaEvents/SNS.swift b/Sources/AWSLambdaEvents/SNS.swift index 9cb4100..dd0ba0f 100644 --- a/Sources/AWSLambdaEvents/SNS.swift +++ b/Sources/AWSLambdaEvents/SNS.swift @@ -16,8 +16,8 @@ import struct Foundation.Date // https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html -public struct SNSEvent: Decodable { - public struct Record: Decodable { +public struct SNSEvent: AWSLambdaEvent { + public struct Record: AWSLambdaEvent { public let eventVersion: String public let eventSubscriptionArn: String public let eventSource: String @@ -37,8 +37,8 @@ public struct SNSEvent: Decodable { case records = "Records" } - public struct Message { - public enum Attribute { + public struct Message: AWSLambdaEvent { + public enum Attribute: AWSLambdaEvent { case string(String) case binary([UInt8]) } diff --git a/Sources/AWSLambdaEvents/SQS.swift b/Sources/AWSLambdaEvents/SQS.swift index 2af8d69..8d70e70 100644 --- a/Sources/AWSLambdaEvents/SQS.swift +++ b/Sources/AWSLambdaEvents/SQS.swift @@ -14,16 +14,16 @@ // https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html -public struct SQSEvent: Decodable { +public struct SQSEvent: AWSLambdaEvent { public let records: [Message] enum CodingKeys: String, CodingKey { case records = "Records" } - public struct Message { + public struct Message: AWSLambdaEvent { /// https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_MessageAttributeValue.html - public enum Attribute { + public enum Attribute: AWSLambdaEvent { case string(String) case binary([UInt8]) case number(String) diff --git a/Sources/AWSLambdaEvents/Utils/DateWrappers.swift b/Sources/AWSLambdaEvents/Utils/DateWrappers.swift index 6e87c93..83db178 100644 --- a/Sources/AWSLambdaEvents/Utils/DateWrappers.swift +++ b/Sources/AWSLambdaEvents/Utils/DateWrappers.swift @@ -12,13 +12,17 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=5.6) +@preconcurrency import struct Foundation.Date +#else import struct Foundation.Date +#endif import class Foundation.DateFormatter import struct Foundation.Locale import struct Foundation.TimeZone @propertyWrapper -public struct ISO8601Coding: Decodable { +public struct ISO8601Coding: AWSLambdaEvent { public let wrappedValue: Date public init(wrappedValue: Date) { @@ -47,7 +51,7 @@ public struct ISO8601Coding: Decodable { } @propertyWrapper -public struct ISO8601WithFractionalSecondsCoding: Decodable { +public struct ISO8601WithFractionalSecondsCoding: AWSLambdaEvent { public let wrappedValue: Date public init(wrappedValue: Date) { @@ -76,7 +80,7 @@ public struct ISO8601WithFractionalSecondsCoding: Decodable { } @propertyWrapper -public struct RFC5322DateTimeCoding: Decodable { +public struct RFC5322DateTimeCoding: AWSLambdaEvent { public let wrappedValue: Date public init(wrappedValue: Date) { diff --git a/Sources/AWSLambdaEvents/Utils/HTTP.swift b/Sources/AWSLambdaEvents/Utils/HTTP.swift index 9e0d8f2..b69b14f 100644 --- a/Sources/AWSLambdaEvents/Utils/HTTP.swift +++ b/Sources/AWSLambdaEvents/Utils/HTTP.swift @@ -17,7 +17,7 @@ public typealias HTTPHeaders = [String: String] public typealias HTTPMultiValueHeaders = [String: [String]] -public struct HTTPMethod: RawRepresentable, Equatable { +public struct HTTPMethod: RawRepresentable, Equatable, _AWSLambdaEventsSendable { public var rawValue: String public init?(rawValue: String) { @@ -61,7 +61,7 @@ extension HTTPMethod: Codable { // MARK: HTTPResponseStatus -public struct HTTPResponseStatus { +public struct HTTPResponseStatus: _AWSLambdaEventsSendable { public let code: UInt public let reasonPhrase: String? @@ -158,7 +158,7 @@ extension HTTPResponseStatus: Codable { extension String { internal var isValidHTTPToken: Bool { - self.utf8.allSatisfy { (char) -> Bool in + self.utf8.allSatisfy { char -> Bool in switch char { case UInt8(ascii: "a") ... UInt8(ascii: "z"), UInt8(ascii: "A") ... UInt8(ascii: "Z"), diff --git a/Sources/AWSLambdaEvents/Utils/Sendable.swift b/Sources/AWSLambdaEvents/Utils/Sendable.swift new file mode 100644 index 0000000..f8d0cb1 --- /dev/null +++ b/Sources/AWSLambdaEvents/Utils/Sendable.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftAWSLambdaRuntime open source project +// +// Copyright (c) 2022 Apple Inc. and the SwiftAWSLambdaRuntime project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// Sendable bridging types + +#if compiler(>=5.6) +public typealias _AWSLambdaEventsSendable = Sendable +#else +public typealias _AWSLambdaEventsSendable = Any +#endif diff --git a/scripts/soundness.sh b/scripts/soundness.sh index 71d43e4..ed2fc02 100755 --- a/scripts/soundness.sh +++ b/scripts/soundness.sh @@ -19,7 +19,7 @@ here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" function replace_acceptable_years() { # this needs to replace all acceptable forms with 'YEARS' - sed -e 's/2017-2018/YEARS/' -e 's/2017-2020/YEARS/' -e 's/2017-2021/YEARS/' -e 's/2019/YEARS/' -e 's/2020/YEARS/' + sed -e 's/2017-2018/YEARS/' -e 's/2017-2020/YEARS/' -e 's/2017-2021/YEARS/' -e 's/2019/YEARS/' -e 's/2020/YEARS/' -e 's/2022/YEARS/' } printf "=> Checking for unacceptable language... "