Skip to content

Commit 2180617

Browse files
authored
Convert to Async Await, Add configurable environments, remove deprecated 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.
1 parent fc7a2f5 commit 2180617

33 files changed

+1104
-1552
lines changed

.github/FUNDING.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
github: [kylebrowning, tanner0101]
1+
github: [kylebrowning]

.github/workflows/swift.yml

+4-11
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,23 @@ name: test
22
on:
33
- pull_request
44
jobs:
5-
xenial-5-2:
5+
xenial-5-6:
66
container:
7-
image: vapor/swift:5.2-xenial
8-
runs-on: ubuntu-latest
9-
steps:
10-
- uses: actions/checkout@v1
11-
- run: swift test --enable-test-discovery
12-
bionic-5-2:
13-
container:
14-
image: vapor/swift:5.2-bionic
7+
image: swift:5.6-focal
158
runs-on: ubuntu-latest
169
steps:
1710
- uses: actions/checkout@v1
1811
- run: swift test --enable-test-discovery
1912
thread:
2013
container:
21-
image: vapor/swift:5.2-bionic
14+
image: swift:5.6-focal
2215
runs-on: ubuntu-latest
2316
steps:
2417
- uses: actions/checkout@v1
2518
- run: swift test --enable-test-discovery --sanitize=thread
2619
address:
2720
container:
28-
image: vapor/swift:5.2-bionic
21+
image: swift:5.6-focal
2922
runs-on: ubuntu-latest
3023
steps:
3124
- uses: actions/checkout@v1

.spi.yml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
version: 1
2+
builder:
3+
configs:
4+
- documentation_targets: [APNSwift]

.swift-format

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"fileScopedDeclarationPrivacy" : {
3+
"accessLevel" : "private"
4+
},
5+
"indentation" : {
6+
"spaces" : 4
7+
},
8+
"indentConditionalCompilationBlocks" : true,
9+
"indentSwitchCaseLabels" : false,
10+
"lineBreakAroundMultilineExpressionChainComponents" : false,
11+
"lineBreakBeforeControlFlowKeywords" : false,
12+
"lineBreakBeforeEachArgument" : false,
13+
"lineBreakBeforeEachGenericRequirement" : false,
14+
"lineLength" : 100,
15+
"maximumBlankLines" : 1,
16+
"prioritizeKeepingFunctionOutputTogether" : false,
17+
"respectsExistingLineBreaks" : true,
18+
"rules" : {
19+
"AllPublicDeclarationsHaveDocumentation" : false,
20+
"AlwaysUseLowerCamelCase" : true,
21+
"AmbiguousTrailingClosureOverload" : true,
22+
"BeginDocumentationCommentWithOneLineSummary" : false,
23+
"DoNotUseSemicolons" : true,
24+
"DontRepeatTypeInStaticProperties" : true,
25+
"FileScopedDeclarationPrivacy" : true,
26+
"FullyIndirectEnum" : true,
27+
"GroupNumericLiterals" : true,
28+
"IdentifiersMustBeASCII" : true,
29+
"NeverForceUnwrap" : false,
30+
"NeverUseForceTry" : false,
31+
"NeverUseImplicitlyUnwrappedOptionals" : false,
32+
"NoAccessLevelOnExtensionDeclaration" : true,
33+
"NoBlockComments" : true,
34+
"NoCasesWithOnlyFallthrough" : true,
35+
"NoEmptyTrailingClosureParentheses" : true,
36+
"NoLabelsInCasePatterns" : true,
37+
"NoLeadingUnderscores" : false,
38+
"NoParensAroundConditions" : true,
39+
"NoVoidReturnOnFunctionSignature" : true,
40+
"OneCasePerLine" : true,
41+
"OneVariableDeclarationPerLine" : true,
42+
"OnlyOneTrailingClosureArgument" : true,
43+
"OrderedImports" : true,
44+
"ReturnVoidInsteadOfEmptyTuple" : true,
45+
"UseEarlyExits" : false,
46+
"UseLetInEveryBoundCaseVariable" : true,
47+
"UseShorthandTypeNames" : true,
48+
"UseSingleLinePropertyGetter" : true,
49+
"UseSynthesizedInitializer" : true,
50+
"UseTripleSlashForDocumentationComments" : true,
51+
"UseWhereClausesInForLoops" : false,
52+
"ValidateDocumentationComments" : false
53+
},
54+
"tabWidth" : 4,
55+
"version" : 1
56+
}

.swiftlint.yml

-54
This file was deleted.

CONTRIBUTING.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
## Maintainers
22
- [@kylebrowning](https://github.com/kylebrowning)
3-
- [@tanner0101](https://github.com/tanner0101)
43

54
## Legal
65

@@ -19,11 +18,11 @@ Please ensure to specify the following:
1918
* OS version and output of `uname -a`
2019
* Swift version or output of `swift --version`
2120
* output of `pkg-config --cflags openssl`
22-
21+
2322
## Submitting a Pull Request
24-
23+
2524
A great PR that is likely to be merged quickly is:
26-
25+
2726
1. Concise, with as few changes as needed to achieve the end result.
2827
1. Tested, ensuring that regressions aren't introduced now or in the future.
2928
1. Documented, adding API documentation as needed to cover new functions and properties.

NOTICE.txt

-21
This file was deleted.

Package.swift

+8-18
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,32 @@
1-
// swift-tools-version:5.2
1+
// swift-tools-version:5.6
22
import PackageDescription
33

44
let package = Package(
55
name: "apnswift",
66
platforms: [
7-
.macOS(.v10_15),
8-
.iOS(.v13),
7+
.macOS(.v12),
8+
.iOS(.v15),
99
],
1010
products: [
1111
.executable(name: "APNSwiftExample", targets: ["APNSwiftExample"]),
1212
.library(name: "APNSwift", targets: ["APNSwift"]),
1313
],
1414
dependencies: [
15-
.package(url: "https://github.com/apple/swift-nio.git", from: "2.10.1"),
16-
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.14.0"),
17-
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.13.0"),
1815
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
19-
.package(url: "https://github.com/vapor/jwt-kit.git", from: "4.0.0"),
16+
.package(url: "https://github.com/apple/swift-crypto.git", "1.0.0" ..< "3.0.0"),
17+
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.10.0"),
2018
],
2119
targets: [
22-
.target(name: "APNSwiftExample", dependencies: [
23-
.target(name: "APNSwift"),
24-
]),
25-
.target(name: "APNSwiftPemExample", dependencies: [
20+
.executableTarget(name: "APNSwiftExample", dependencies: [
2621
.target(name: "APNSwift"),
2722
]),
2823
.testTarget(name: "APNSwiftTests", dependencies: [
2924
.target(name: "APNSwift"),
3025
]),
3126
.target(name: "APNSwift", dependencies: [
32-
.product(name: "JWTKit", package: "jwt-kit"),
3327
.product(name: "Logging", package: "swift-log"),
34-
.product(name: "NIO", package: "swift-nio"),
35-
.product(name: "NIOSSL", package: "swift-nio-ssl"),
36-
.product(name: "NIOHTTP1", package: "swift-nio"),
37-
.product(name: "NIOHTTP2", package: "swift-nio-http2"),
38-
.product(name: "NIOFoundationCompat", package: "swift-nio"),
39-
.product(name: "NIOTLS", package: "swift-nio"),
28+
.product(name: "Crypto", package: "swift-crypto"),
29+
.product(name: "AsyncHTTPClient", package: "async-http-client")
4030
]),
4131
]
4232
)

README.md

+36-41
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ To install `APNSwift`, just add the package as a dependency in your [**Package.s
1313

1414
```swift
1515
dependencies: [
16-
.package(url: "https://github.com/kylebrowning/APNSwift.git", .upToNextMinor(from: "1.3.0"))
16+
.package(url: "https://github.com/swift-server-community/APNSwift.git", from: "5.0.0"),
1717
]
1818
```
1919

@@ -23,25 +23,37 @@ dependencies: [
2323
struct BasicNotification: APNSwiftNotification {
2424
let aps: APNSwiftPayload
2525
}
26+
2627
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
2728
var logger = Logger(label: "com.apnswift")
2829
logger.logLevel = .debug
30+
31+
/// Create your HTTPClient (or pass in one you already have)
32+
let httpClient = HTTPClient(eventLoopGroupProvider: .shared(group))
33+
34+
/// Create your `AuthentictionConfig`
35+
let authenticationConfig: APNSwiftConfiguration.Authentication = .init(
36+
privateKey: try .loadFrom(filePath: "/Users/kylebrowning/Documents/AuthKey_9UC9ZLQ8YW.p8"),
37+
teamIdentifier: "ABBM6U9RM5",
38+
keyIdentifier: "9UC9ZLQ8YW"
39+
)
40+
41+
/// If you need to use an a secrets manager instead of read from disk, use
42+
/// `loadfrom(string:)`
43+
2944
let apnsConfig = try APNSwiftConfiguration(
30-
authenticationMethod: .jwt(
31-
key: .private(filePath: "/Users/kylebrowning/Desktop/AuthKey_9UC9ZLQ8YW.p8"),
32-
keyIdentifier: "9UC9ZLQ8YW",
33-
teamIdentifier: "ABBM6U9RM5"
34-
),
45+
authenticationConfig: authenticationConfig,
3546
topic: "com.grasscove.Fern",
3647
environment: .sandbox,
3748
logger: logger
3849
)
50+
let apns = APNSwiftConnection(configuration: apnsConfig, logger: logger)
3951

40-
let apns = try APNSwiftConnection.connect(configuration: apnsConfig, on: group.next()).wait()
4152
let aps = APNSwiftPayload(alert: .init(title: "Hey There", subtitle: "Subtitle", body: "Body"), hasContentAvailable: true)
42-
try apns.send(BasicNotification(aps: aps), pushType: .alert, to: "98AAD4A2398DDC58595F02FA307DF9A15C18B6111D1B806949549085A8E6A55D").wait()
43-
try apns.close().wait()
44-
try group.syncShutdownGracefully()
53+
let deviceToken = "myDeviceToken"
54+
try await apns.send(notification, pushType: .alert, to: deviceToken)
55+
try await httpClient.shutdown()
56+
try! group.syncShutdownGracefully()
4557
exit(0)
4658
```
4759

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

5264
```swift
5365
let apnsConfig = try APNSwiftConfiguration(
54-
authenticationMethod: .jwt(
55-
key: .private(filePath: "/Users/kylebrowning/Desktop/AuthKey_9UC9ZLQ8YW.p8"),
56-
keyIdentifier: "9UC9ZLQ8YW",
57-
teamIdentifier: "ABBM6U9RM5"
58-
),
66+
authenticationConfig: authenticationConfig,
5967
topic: "com.grasscove.Fern",
6068
environment: .sandbox,
6169
logger: logger
6270
)
6371
```
64-
#### Example `APNSwiftConfiguration`
72+
73+
#### APNSwiftConfiguration.Authentication
74+
[`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.
75+
76+
6577
```swift
66-
let signer = ...
67-
let apnsConfig = try APNSwiftConfiguration(keyIdentifier: "9UC9ZLQ8YW",
68-
teamIdentifier: "ABBM6U9RM5",
69-
signer: signer),
70-
topic: "com.grasscove.Fern",
71-
environment: .sandbox)
78+
let authenticationConfig: APNSwiftConfiguration.Authentication = .init(
79+
privateKey: try .loadFrom(filePath: "/Users/kylebrowning/Documents/AuthKey_9UC9ZLQ8YW.p8"),
80+
teamIdentifier: "ABBM6U9RM5",
81+
keyIdentifier: "9UC9ZLQ8YW"
82+
)
7283
```
7384

7485
### APNSwiftConnection
7586

76-
[`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.
87+
[`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.
7788

7889

7990
#### Example `APNSwiftConnection`
8091
```swift
81-
let apnsConfig = ...
82-
let apns = try APNSwiftConnection.connect(configuration: apnsConfig, on: group.next()).wait()
92+
let apns = APNSwiftConnection(configuration: apnsConfig, logger: logger)
8393
```
8494

8595
### APNSwiftAlert
@@ -122,22 +132,7 @@ struct AcmeNotification: APNSwiftNotification {
122132
let apns: APNSwiftConnection: = ...
123133
let aps: APNSwiftPayload = ...
124134
let notification = AcmeNotification(acme2: ["bang", "whiz"], aps: aps)
125-
let res = try apns.send(notification, to: "de1d666223de85db0186f654852cc960551125ee841ca044fdf5ef6a4756a77e").wait()
126-
```
127-
128-
### Using PEM instead of P8
129-
#### Note: this is blocking
130-
```swift
131-
132-
var apnsConfig = try APNSwiftConfiguration(
133-
authenticationMethod: .tls(
134-
privateKeyPath: "/Users/kylebrowning/Projects/swift/Fern/development_com.grasscove.Fern.pkey",
135-
pemPath: "/Users/kylebrowning/Projects/swift/Fern/development_com.grasscove.Fern.pem"
136-
),
137-
topic: "com.grasscove.Fern",
138-
environment: .sandbox
139-
)
140-
let apns = try APNSwiftConnection.connect(configuration: apnsConfig, on: group.next()).wait()
135+
let res = try apns.send(notification, to: "de1d666223de85db0186f654852cc960551125ee841ca044fdf5ef6a4756a77e")
141136
```
142137

143138
### Need a completely custom arbtirary payload and dont like being typecast?

0 commit comments

Comments
 (0)