diff --git a/Package.swift b/Package.swift index c09ab920..f7eb332d 100644 --- a/Package.swift +++ b/Package.swift @@ -74,5 +74,5 @@ let package = Package( ] ), ], - swiftLanguageVersions: [.v6] + swiftLanguageModes: [.v6] ) diff --git a/README.md b/README.md index ea070f9b..178181d2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![sswg:graduated|94x20](https://img.shields.io/badge/sswg-graduated-green.svg)]([https://github.com/swift-server/sswg/blob/master/process/incubation.md#sandbox-level](https://www.swift.org/sswg/incubation-process.html#graduation-requirements)) [![Build](https://github.com/kylebrowning/APNSwift/workflows/test/badge.svg)](https://github.com/kylebrowning/APNSwift/actions) -[![Documentation](https://img.shields.io/badge/documentation-blueviolet.svg)](https://swiftpackageindex.com/swift-server-community/APNSwift/main/documentation/apnswift) +[![Documentation](https://img.shields.io/badge/documentation-blueviolet.svg)](https://swiftpackageindex.com/swift-server-community/APNSwift/documentation) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fswift-server-community%2FAPNSwift%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/swift-server-community/APNSwift) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fswift-server-community%2FAPNSwift%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/swift-server-community/APNSwift)

APNSwift

@@ -25,7 +25,7 @@ To install `APNSwift`, just add the package as a dependency in your [**Package.s ```swift dependencies: [ - .package(url: "https://github.com/swift-server-community/APNSwift.git", from: "5.0.0"), + .package(url: "https://github.com/swift-server-community/APNSwift.git", from: "6.0.0"), ] ``` @@ -44,15 +44,11 @@ let client = APNSClient( ), eventLoopGroupProvider: .createNew, responseDecoder: JSONDecoder(), - requestEncoder: JSONEncoder(), - byteBufferAllocator: .init(), - backgroundActivityLogger: logger + requestEncoder: JSONEncoder() ) -defer { - client.shutdown { _ in - logger.error("Failed to shutdown APNSClient") - } -} + +// Shutdown the client when done +try await client.shutdown() ``` ## Sending a simple notification @@ -74,44 +70,40 @@ try await client.sendAlertNotification( topic: "com.app.bundle", payload: Payload() ), - deviceToken: "device-token", - deadline: .nanoseconds(Int64.max), - logger: myLogger + deviceToken: "device-token" ) ``` ## Sending Live Activity Update / End -It requires sending `ContentState` matching with the live activity configuration to successfully update activity state. `ContentState` needs to conform to `Encodable` +It requires sending `ContentState` matching with the live activity configuration to successfully update activity state. `ContentState` needs to conform to `Encodable` and `Sendable`. ```swift - try await client.sendLiveActivityNotification( - .init( - expiration: .immediately, - priority: .immediately, - appID: "com.app.bundle", - contentState: ContentState, - event: .update, - timestamp: Int(Date().timeIntervalSince1970) - ), - activityPushToken: activityPushToken, - deadline: .distantFuture - ) +try await client.sendLiveActivityNotification( + .init( + expiration: .immediately, + priority: .immediately, + appID: "com.app.bundle", + contentState: ContentState, + event: .update, + timestamp: Int(Date().timeIntervalSince1970) + ), + deviceToken: activityPushToken +) ``` ```swift - try await client.sendLiveActivityNotification( - .init( - expiration: .immediately, - priority: .immediately, - appID: "com.app.bundle", - contentState: ContentState, - event: .end, - timestamp: Int(Date().timeIntervalSince1970), - dismissalDate: .dismissImmediately // Optional to alter default behaviour - ), - activityPushToken: activityPushToken, - deadline: .distantFuture - ) +try await client.sendLiveActivityNotification( + .init( + expiration: .immediately, + priority: .immediately, + appID: "com.app.bundle", + contentState: ContentState, + event: .end, + timestamp: Int(Date().timeIntervalSince1970), + dismissalDate: .immediately // Optional to alter default behaviour + ), + deviceToken: activityPushToken +) ``` ## Authentication `APNSwift` provides two authentication methods. `jwt`, and `TLS`. @@ -121,8 +113,8 @@ These can be configured when created your `APNSClientConfiguration` *Notes: `jwt` requires an encrypted version of your .p8 file from Apple which comes in a `pem` format. If you're having trouble with your key being invalid please confirm it is a PEM file* ``` - openssl pkcs8 -nocrypt -in /path/to/my/key.p8 -out ~/Downloads/key.pem - ``` +openssl pkcs8 -nocrypt -in /path/to/my/key.p8 -out ~/Downloads/key.pem +``` ## Logging By default APNSwift has a no-op logger which will not log anything. However if you pass a logger in, you will see logs. diff --git a/Sources/APNS/APNS.docc/APNSwift.md b/Sources/APNS/APNS.docc/APNSwift.md index 5b0c9baa..384ea897 100644 --- a/Sources/APNS/APNS.docc/APNSwift.md +++ b/Sources/APNS/APNS.docc/APNSwift.md @@ -1,5 +1,6 @@ -# ``APNSwift`` -A non-blocking Swift package for sending remote Apple Push Notification requests to Apple's APNS. +# ``APNS`` + +A non-blocking Swift module for sending remote Apple Push Notification requests to APNS built on AsyncHttpClient. ## Installation @@ -7,27 +8,12 @@ To install `APNSwift`, just add the package as a dependency in your [**Package.s ```swift dependencies: [ - .package(url: "https://github.com/swift-server-community/APNSwift.git", from: "4.0.0"), + .package(url: "https://github.com/swift-server-community/APNSwift.git", from: "6.0.0"), ] ``` -If youd like to give our bleeding edge release a try, which is what the Readme is expecting use `5.0.0-alpha.N`. If you need the old Readme, see [here](https://github.com/swift-server-community/APNSwift/tree/4.0.0) - -```swift -dependencies: [ - .package(url: "https://github.com/swift-server-community/APNSwift.git", from: "5.0.0-alpha.5"), -] -``` - -## Foundations -`APNSwift` is built with a layered approach. It exposes three tiers of API's. -1. A [raw API](https://github.com/swift-server-community/APNSwift/blob/d60241fe2b6eb193331567a871697d3f4bdf70fb/Sources/APNSwift/APNSClient.swift#L254) that takes basic types such as `String`'s -2. A slightly more [semantically safe API](https://github.com/swift-server-community/APNSwift/blob/d60241fe2b6eb193331567a871697d3f4bdf70fb/Sources/APNSwift/APNSClient.swift#L183), which takes types, like [`APNSPriority`](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNSwift/APNSPriority.swift), [`APNSPushType`](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNSwift/APNSPushType.swift), [`APNSNotificationExpiration`](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNSwift/APNSNotificationExpiration.swift), etc. -3. The [safest API](https://github.com/swift-server-community/APNSwift/blob/d60241fe2b6eb193331567a871697d3f4bdf70fb/Sources/APNSwift/Alert/APNSClient%2BAlert.swift#L32) which takes fully semantic types such as [`APNSAlertNotification`](https://github.com/swift-server-community/APNSwift/blob/d60241fe2b6eb193331567a871697d3f4bdf70fb/Sources/APNSwift/Alert/APNSAlertNotification.swift#L177) - -**We recommened using number 3, the semantically safest API to ensure your push notification is delivered correctly**. *This README assumes that you are using number 3.* However if you need more granular approach, or something doesn't exist in this library, please use 2 or 1. (Also please open an issue if we missed something so we can get a semantically correct version!) ## Getting Started -APNSwift aims to provide sementically correct structures to sending push notifications. You first need to setup a [`APNSClient`](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNSwift/APNSClient.swift). To do that youll need to know your authentication method +APNSwift aims to provide semantically correct structures to sending push notifications. You first need to setup a [`APNSClient`](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNS/APNSClient.swift). To do that youll need to know your authentication method ```swift let client = APNSClient( @@ -41,15 +27,11 @@ let client = APNSClient( ), eventLoopGroupProvider: .createNew, responseDecoder: JSONDecoder(), - requestEncoder: JSONEncoder(), - byteBufferAllocator: .init(), - backgroundActivityLogger: logger + requestEncoder: JSONEncoder() ) -defer { - client.shutdown { _ in - logger.error("Failed to shutdown APNSClient") - } -} + +// Shutdown the client when done +try await client.shutdown() ``` ## Sending a simple notification @@ -71,9 +53,7 @@ try await client.sendAlertNotification( topic: "com.app.bundle", payload: Payload() ), - deviceToken: "device-token", - deadline: .nanoseconds(Int64.max), - logger: myLogger + deviceToken: "device-token" ) ``` @@ -85,8 +65,8 @@ These can be configured when created your `APNSClientConfiguration` *Notes: `jwt` requires an encrypted version of your .p8 file from Apple which comes in a `pem` format. If you're having trouble with your key being invalid please confirm it is a PEM file* ``` - openssl pkcs8 -nocrypt -in /path/to/my/key.p8 -out ~/Downloads/key.pem - ``` +openssl pkcs8 -nocrypt -in /path/to/my/key.p8 -out ~/Downloads/key.pem +``` ## Logging By default APNSwift has a no-op logger which will not log anything. However if you pass a logger in, you will see logs. @@ -98,31 +78,6 @@ This logger can be passed into the `APNSClient` and will log background things l #### **Notification Send Logger** This logger can be passed into any of the `send:` methods and will log everything related to a single send request. -## Using the non semantic safe APIs - -APNSwift provides the ability to send raw payloads. You can use `Data`, `ByteBuffer`, `DispatchData`, `Array` -Though this is to be used with caution. APNSwift cannot gurantee delivery if you do not have the correct payload. -For more information see: [Creating APN Payload](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html) - -```swift -/// Extremely Raw, -try await client.send( - payload: payload, - deviceToken: token, - pushType: "alert", deadline: .distantFuture -) - -/// or a little safer but still raw -try await client.send( - payload: payload, - deviceToken: token, - pushType: .alert, - expiration: .immediatly, - priority: .immediatly, - deadline: .distantFuture -) -``` - ## Server Example Take a look at [Program.swift](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNSwiftExample/Program.swift) @@ -136,3 +91,4 @@ Once inside configure your App Bundle ID and assign your development team. Build * Pitch discussion: [Swift Server Forums](https://forums.swift.org/t/apple-push-notification-service-implementation-pitch/20193) * Proposal: [SSWG-0006](https://forums.swift.org/t/feedback-nioapns-nio-based-apple-push-notification-service/24393) +* 5.0 breaking changings: [Swift Server Forums]([Blog post here on breaking changing](https://forums.swift.org/t/apnswift-5-0-0-beta-release/60075/3)) diff --git a/Sources/APNS/APNSClient.swift b/Sources/APNS/APNSClient.swift index e277e334..b9a7dcc7 100644 --- a/Sources/APNS/APNSClient.swift +++ b/Sources/APNS/APNSClient.swift @@ -57,8 +57,8 @@ public final class APNSClient(_ type: T.Type, from buffer: ByteBuffer) throws -> T diff --git a/Sources/APNS/Coding/APNSJSONEncoder.swift b/Sources/APNS/Coding/APNSJSONEncoder.swift index e195bfea..1f04a333 100644 --- a/Sources/APNS/Coding/APNSJSONEncoder.swift +++ b/Sources/APNS/Coding/APNSJSONEncoder.swift @@ -16,7 +16,7 @@ import Foundation import NIOCore import NIOFoundationCompat -/// A protocol that is similar to the ``JSONEncoder``. This allows users of APNSwift to customize the encoder used +/// A protocol that is similar to the `JSONEncoder`. This allows users of APNSwift to customize the encoder used /// for encoding the notification JSON payloads. public protocol APNSJSONEncoder { func encode(_ value: T, into buffer: inout ByteBuffer) throws