Skip to content

Commit

Permalink
Convert to Async Await, Add configurable environments, remove depreca…
Browse files Browse the repository at this point in the history
…ted code (#130)

* Initial

* updates

* clean up, let overriden environment be a thing

* use nio deadline

* use configured decoder

* update workflow

* Workflow again

* again?

* re-run

* cleanup, remove PEM

* cleanup

* use dispatch group instead of sleep().

* use executable target

* update versions

* remove test code

* cleanup and remove JWTKit

* more cleanup

* udate headers

* update readme

* update readme

* Update public vendor to be `internal`

* update meta files

* linted

* more privates, more internals.
  • Loading branch information
kylebrowning authored Jun 10, 2022
1 parent fc7a2f5 commit 2180617
Show file tree
Hide file tree
Showing 33 changed files with 1,104 additions and 1,552 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
github: [kylebrowning, tanner0101]
github: [kylebrowning]
15 changes: 4 additions & 11 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,23 @@ name: test
on:
- pull_request
jobs:
xenial-5-2:
xenial-5-6:
container:
image: vapor/swift:5.2-xenial
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery
bionic-5-2:
container:
image: vapor/swift:5.2-bionic
image: swift:5.6-focal
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery
thread:
container:
image: vapor/swift:5.2-bionic
image: swift:5.6-focal
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery --sanitize=thread
address:
container:
image: vapor/swift:5.2-bionic
image: swift:5.6-focal
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
Expand Down
4 changes: 4 additions & 0 deletions .spi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: 1
builder:
configs:
- documentation_targets: [APNSwift]
56 changes: 56 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"fileScopedDeclarationPrivacy" : {
"accessLevel" : "private"
},
"indentation" : {
"spaces" : 4
},
"indentConditionalCompilationBlocks" : true,
"indentSwitchCaseLabels" : false,
"lineBreakAroundMultilineExpressionChainComponents" : false,
"lineBreakBeforeControlFlowKeywords" : false,
"lineBreakBeforeEachArgument" : false,
"lineBreakBeforeEachGenericRequirement" : false,
"lineLength" : 100,
"maximumBlankLines" : 1,
"prioritizeKeepingFunctionOutputTogether" : false,
"respectsExistingLineBreaks" : true,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLowerCamelCase" : true,
"AmbiguousTrailingClosureOverload" : true,
"BeginDocumentationCommentWithOneLineSummary" : false,
"DoNotUseSemicolons" : true,
"DontRepeatTypeInStaticProperties" : true,
"FileScopedDeclarationPrivacy" : true,
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : false,
"NeverUseImplicitlyUnwrappedOptionals" : false,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoBlockComments" : true,
"NoCasesWithOnlyFallthrough" : true,
"NoEmptyTrailingClosureParentheses" : true,
"NoLabelsInCasePatterns" : true,
"NoLeadingUnderscores" : false,
"NoParensAroundConditions" : true,
"NoVoidReturnOnFunctionSignature" : true,
"OneCasePerLine" : true,
"OneVariableDeclarationPerLine" : true,
"OnlyOneTrailingClosureArgument" : true,
"OrderedImports" : true,
"ReturnVoidInsteadOfEmptyTuple" : true,
"UseEarlyExits" : false,
"UseLetInEveryBoundCaseVariable" : true,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : true,
"UseSynthesizedInitializer" : true,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : false,
"ValidateDocumentationComments" : false
},
"tabWidth" : 4,
"version" : 1
}
54 changes: 0 additions & 54 deletions .swiftlint.yml

This file was deleted.

7 changes: 3 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
## Maintainers
- [@kylebrowning](https://github.com/kylebrowning)
- [@tanner0101](https://github.com/tanner0101)

## Legal

Expand All @@ -19,11 +18,11 @@ Please ensure to specify the following:
* OS version and output of `uname -a`
* Swift version or output of `swift --version`
* output of `pkg-config --cflags openssl`

## Submitting a Pull Request

A great PR that is likely to be merged quickly is:

1. Concise, with as few changes as needed to achieve the end result.
1. Tested, ensuring that regressions aren't introduced now or in the future.
1. Documented, adding API documentation as needed to cover new functions and properties.
Expand Down
21 changes: 0 additions & 21 deletions NOTICE.txt

This file was deleted.

26 changes: 8 additions & 18 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
// swift-tools-version:5.2
// swift-tools-version:5.6
import PackageDescription

let package = Package(
name: "apnswift",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.macOS(.v12),
.iOS(.v15),
],
products: [
.executable(name: "APNSwiftExample", targets: ["APNSwiftExample"]),
.library(name: "APNSwift", targets: ["APNSwift"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.10.1"),
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.14.0"),
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.13.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
.package(url: "https://github.com/vapor/jwt-kit.git", from: "4.0.0"),
.package(url: "https://github.com/apple/swift-crypto.git", "1.0.0" ..< "3.0.0"),
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.10.0"),
],
targets: [
.target(name: "APNSwiftExample", dependencies: [
.target(name: "APNSwift"),
]),
.target(name: "APNSwiftPemExample", dependencies: [
.executableTarget(name: "APNSwiftExample", dependencies: [
.target(name: "APNSwift"),
]),
.testTarget(name: "APNSwiftTests", dependencies: [
.target(name: "APNSwift"),
]),
.target(name: "APNSwift", dependencies: [
.product(name: "JWTKit", package: "jwt-kit"),
.product(name: "Logging", package: "swift-log"),
.product(name: "NIO", package: "swift-nio"),
.product(name: "NIOSSL", package: "swift-nio-ssl"),
.product(name: "NIOHTTP1", package: "swift-nio"),
.product(name: "NIOHTTP2", package: "swift-nio-http2"),
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "NIOTLS", package: "swift-nio"),
.product(name: "Crypto", package: "swift-crypto"),
.product(name: "AsyncHTTPClient", package: "async-http-client")
]),
]
)
77 changes: 36 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ To install `APNSwift`, just add the package as a dependency in your [**Package.s

```swift
dependencies: [
.package(url: "https://github.com/kylebrowning/APNSwift.git", .upToNextMinor(from: "1.3.0"))
.package(url: "https://github.com/swift-server-community/APNSwift.git", from: "5.0.0"),
]
```

Expand All @@ -23,25 +23,37 @@ dependencies: [
struct BasicNotification: APNSwiftNotification {
let aps: APNSwiftPayload
}

let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
var logger = Logger(label: "com.apnswift")
logger.logLevel = .debug

/// Create your HTTPClient (or pass in one you already have)
let httpClient = HTTPClient(eventLoopGroupProvider: .shared(group))

/// Create your `AuthentictionConfig`
let authenticationConfig: APNSwiftConfiguration.Authentication = .init(
privateKey: try .loadFrom(filePath: "/Users/kylebrowning/Documents/AuthKey_9UC9ZLQ8YW.p8"),
teamIdentifier: "ABBM6U9RM5",
keyIdentifier: "9UC9ZLQ8YW"
)

/// If you need to use an a secrets manager instead of read from disk, use
/// `loadfrom(string:)`

let apnsConfig = try APNSwiftConfiguration(
authenticationMethod: .jwt(
key: .private(filePath: "/Users/kylebrowning/Desktop/AuthKey_9UC9ZLQ8YW.p8"),
keyIdentifier: "9UC9ZLQ8YW",
teamIdentifier: "ABBM6U9RM5"
),
authenticationConfig: authenticationConfig,
topic: "com.grasscove.Fern",
environment: .sandbox,
logger: logger
)
let apns = APNSwiftConnection(configuration: apnsConfig, logger: logger)

let apns = try APNSwiftConnection.connect(configuration: apnsConfig, on: group.next()).wait()
let aps = APNSwiftPayload(alert: .init(title: "Hey There", subtitle: "Subtitle", body: "Body"), hasContentAvailable: true)
try apns.send(BasicNotification(aps: aps), pushType: .alert, to: "98AAD4A2398DDC58595F02FA307DF9A15C18B6111D1B806949549085A8E6A55D").wait()
try apns.close().wait()
try group.syncShutdownGracefully()
let deviceToken = "myDeviceToken"
try await apns.send(notification, pushType: .alert, to: deviceToken)
try await httpClient.shutdown()
try! group.syncShutdownGracefully()
exit(0)
```

Expand All @@ -51,35 +63,33 @@ exit(0)

```swift
let apnsConfig = try APNSwiftConfiguration(
authenticationMethod: .jwt(
key: .private(filePath: "/Users/kylebrowning/Desktop/AuthKey_9UC9ZLQ8YW.p8"),
keyIdentifier: "9UC9ZLQ8YW",
teamIdentifier: "ABBM6U9RM5"
),
authenticationConfig: authenticationConfig,
topic: "com.grasscove.Fern",
environment: .sandbox,
logger: logger
)
```
#### Example `APNSwiftConfiguration`

#### APNSwiftConfiguration.Authentication
[`APNSwiftConfiguration.Authentication`](https://github.com/swift-server-community/APNSwift/blob/master/Sources/APNSwift/APNSwiftConfiguration.swift#L26) is a struct that provides authentication keys and metadata to the signer.


```swift
let signer = ...
let apnsConfig = try APNSwiftConfiguration(keyIdentifier: "9UC9ZLQ8YW",
teamIdentifier: "ABBM6U9RM5",
signer: signer),
topic: "com.grasscove.Fern",
environment: .sandbox)
let authenticationConfig: APNSwiftConfiguration.Authentication = .init(
privateKey: try .loadFrom(filePath: "/Users/kylebrowning/Documents/AuthKey_9UC9ZLQ8YW.p8"),
teamIdentifier: "ABBM6U9RM5",
keyIdentifier: "9UC9ZLQ8YW"
)
```

### APNSwiftConnection

[`APNSwiftConnection`](https://github.com/kylebrowning/swift-nio-http2-apns/blob/master/Sources/APNSwift/APNSwiftConnection.swift) is a class with methods thats provides a wrapper to NIO's ClientBootstrap. The `swift-nio-http2` dependency is utilized here. It also provides a function to send a notification to a specific device token string.
[`APNSwiftConnection`](https://github.com/kylebrowning/swift-nio-http2-apns/blob/master/Sources/APNSwift/APNSwiftConnection.swift) provides functions to send a notification to a specific device token string.


#### Example `APNSwiftConnection`
```swift
let apnsConfig = ...
let apns = try APNSwiftConnection.connect(configuration: apnsConfig, on: group.next()).wait()
let apns = APNSwiftConnection(configuration: apnsConfig, logger: logger)
```

### APNSwiftAlert
Expand Down Expand Up @@ -122,22 +132,7 @@ struct AcmeNotification: APNSwiftNotification {
let apns: APNSwiftConnection: = ...
let aps: APNSwiftPayload = ...
let notification = AcmeNotification(acme2: ["bang", "whiz"], aps: aps)
let res = try apns.send(notification, to: "de1d666223de85db0186f654852cc960551125ee841ca044fdf5ef6a4756a77e").wait()
```

### Using PEM instead of P8
#### Note: this is blocking
```swift

var apnsConfig = try APNSwiftConfiguration(
authenticationMethod: .tls(
privateKeyPath: "/Users/kylebrowning/Projects/swift/Fern/development_com.grasscove.Fern.pkey",
pemPath: "/Users/kylebrowning/Projects/swift/Fern/development_com.grasscove.Fern.pem"
),
topic: "com.grasscove.Fern",
environment: .sandbox
)
let apns = try APNSwiftConnection.connect(configuration: apnsConfig, on: group.next()).wait()
let res = try apns.send(notification, to: "de1d666223de85db0186f654852cc960551125ee841ca044fdf5ef6a4756a77e")
```

### Need a completely custom arbtirary payload and dont like being typecast?
Expand Down
Loading

0 comments on commit 2180617

Please sign in to comment.