Skip to content

Commit

Permalink
Update to Swift 5.10 (#18)
Browse files Browse the repository at this point in the history
* Improve DocC

* Make everything `Sendable` 

* Add DocC catalog

* Improve test coverage
  • Loading branch information
fpseverino authored Sep 7, 2024
1 parent 9619411 commit 5804515
Show file tree
Hide file tree
Showing 18 changed files with 260 additions and 131 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: test
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
pull_request: { types: [opened, reopened, synchronize, ready_for_review] }
push: { branches: [ main ] }

jobs:
unit-tests:
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
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: [SendGridKit]
Empty file removed CHANGELOG.md
Empty file.
35 changes: 26 additions & 9 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
// swift-tools-version:5.6
// swift-tools-version:5.10
import PackageDescription

let package = Package(
name: "sendgrid-kit",
platforms: [
.macOS(.v10_15),
.macOS(.v13),
],
products: [
.library(name: "SendGridKit", targets: ["SendGridKit"]),
],
dependencies: [
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.9.0"),
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.22.0"),
],
targets: [
.target(name: "SendGridKit", dependencies: [
.product(name: "AsyncHTTPClient", package: "async-http-client"),
]),
.testTarget(name: "SendGridKitTests", dependencies: [
.target(name: "SendGridKit"),
])
.target(
name: "SendGridKit",
dependencies: [
.product(name: "AsyncHTTPClient", package: "async-http-client"),
],
swiftSettings: swiftSettings
),
.testTarget(
name: "SendGridKitTests",
dependencies: [
.target(name: "SendGridKit"),
],
swiftSettings: swiftSettings
),
]
)

var swiftSettings: [SwiftSetting] { [
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("ConciseMagicFile"),
.enableUpcomingFeature("ForwardTrailingClosures"),
.enableUpcomingFeature("DisableOutwardActorInference"),
.enableUpcomingFeature("StrictConcurrency"),
.enableExperimentalFeature("StrictConcurrency=complete"),
] }
66 changes: 44 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
# SendGridKit
<div align="center">
<img src="https://avatars.githubusercontent.com/u/26165732?s=200&v=4" width="100" height="100" alt="avatar" />
<h1>SendGridKit</h1>
<a href="https://swiftpackageindex.com/vapor-community/sendgrid-kit/documentation">
<img src="https://design.vapor.codes/images/readthedocs.svg" alt="Documentation">
</a>
<a href="https://discord.gg/vapor"><img src="https://design.vapor.codes/images/discordchat.svg" alt="Team Chat"></a>
<a href="LICENSE"><img src="https://design.vapor.codes/images/mitlicense.svg" alt="MIT License"></a>
<a href="https://github.com/vapor-community/sendgrid-kit/actions/workflows/test.yml">
<img src="https://img.shields.io/github/actions/workflow/status/vapor-community/sendgrid-kit/test.yml?event=push&style=plastic&logo=github&label=tests&logoColor=%23ccc" alt="Continuous Integration">
</a>
<a href="https://codecov.io/github/vapor-community/sendgrid-kit">
<img src="https://img.shields.io/codecov/c/github/vapor-community/sendgrid-kit?style=plastic&logo=codecov&label=codecov">
</a>
<a href="https://swift.org">
<img src="https://design.vapor.codes/images/swift510up.svg" alt="Swift 5.10+">
</a>
</div>
<br>

![Swift](http://img.shields.io/badge/swift-5.6-brightgreen.svg)
📧 SendGridKit is a Swift package used to communicate with the SendGrid API for Server Side Swift Apps.

SendGridKit is a Swift package used to communicate with the SendGrid API for Server Side Swift Apps.
Send simple emails, or leverage the full capabilities of [SendGrid's V3 API](https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send).

## Setup
Add the dependency to Package.swift:
### Getting Started

~~~~swift
dependencies: [
...
.package(url: "https://github.com/vapor-community/sendgrid-kit.git", from: "2.0.0")
],
targets: [
.target(name: "App", dependencies: [
.product(name: "SendGridKit", package: "sendgrid-kit"),
]),
~~~~
Use the SPM string to easily include the dependendency in your `Package.swift` file

```swift
.package(url: "https://github.com/vapor-community/sendgrid-kit.git", from: "2.0.0")
```

and add it to your target's dependencies:

```swift
.product(name: "SendGridKit", package: "sendgrid-kit")
```

## Overview

Register the config and the provider.

Expand All @@ -25,9 +45,10 @@ let httpClient = HTTPClient(...)
let sendGridClient = SendGridClient(httpClient: httpClient, apiKey: "YOUR_API_KEY")
~~~~

## Using the API
### Using the API

You can use all of the available parameters here to build your `SendGridEmail`.

You can use all of the available parameters here to build your `SendGridEmail`
Usage in a route closure would be as followed:

~~~~swift
Expand All @@ -37,15 +58,16 @@ let email = SendGridEmail(...)
try await sendGridClient.send(email)
~~~~

## Error handling
If the request to the API failed for any reason a `SendGridError` is `thrown` and has an `errors` property that contains an array of errors returned by the API.
Simply ensure you catch errors thrown like any other throwing function
### Error handling

If the request to the API failed for any reason a `SendGridError` is thrown, which has an `errors` property that contains an array of errors returned by the API.

Simply ensure you catch errors thrown like any other throwing function.

~~~~swift
do {
try await sendGridClient.send(...)
}
catch let error as SendGridError {
} catch let error as SendGridError {
print(error)
}
~~~~
3 changes: 1 addition & 2 deletions Sources/SendGridKit/Models/AdvancedSuppressionManager.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

public struct AdvancedSuppressionManager: Codable {
public struct AdvancedSuppressionManager: Codable, Sendable {
/// The unsubscribe group to associate with this email.
public var groupId: Int

Expand All @@ -19,5 +19,4 @@ public struct AdvancedSuppressionManager: Codable {
case groupId = "group_id"
case groupsToDisplay = "groups_to_display"
}

}
4 changes: 2 additions & 2 deletions Sources/SendGridKit/Models/EmailAddress.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

public struct EmailAddress: Codable {
/// format: email
public struct EmailAddress: Codable, Sendable {
/// The email address of the person to whom you are sending an email.
public var email: String

/// The name of the person to whom you are sending an email.
Expand Down
13 changes: 8 additions & 5 deletions Sources/SendGridKit/Models/EmailAttachment.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Foundation

public struct EmailAttachment: Codable {

public struct EmailAttachment: Codable, Sendable {
/// The Base64 encoded content of the attachment.
public var content: String

/// The mime type of the content you are attaching. For example, “text/plain” or “text/html”.
/// The MIME type of the content you are attaching.
///
/// For example, `“text/plain”` or `“text/html”`.
public var type: String?

/// The filename of the attachment.
Expand All @@ -14,7 +15,10 @@ public struct EmailAttachment: Codable {
/// The content-disposition of the attachment specifying how you would like the attachment to be displayed.
public var disposition: String?

/// The content id for the attachment. This is used when the disposition is set to “inline” and the attachment is an image, allowing the file to be displayed within the body of your email.
/// The content ID for the attachment.
///
/// This is used when the disposition is set to “inline” and the attachment is an image,
/// allowing the file to be displayed within the body of your email.
public var contentId: String?

public init(
Expand All @@ -38,5 +42,4 @@ public struct EmailAttachment: Codable {
case disposition
case contentId = "content_id"
}

}
11 changes: 7 additions & 4 deletions Sources/SendGridKit/Models/EmailContent.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import Foundation

public struct EmailContent: Codable {

/// The mime type of the content you are including in your email. For example, “text/plain” or “text/html”.
public struct EmailContent: Codable, Sendable {
/// The MIME type of the content you are including in your email.
///
/// For example, `“text/plain”` or `“text/html”`.
public var type: String

/// The actual content of the specified mime type that you are including in your email. minLength 1
/// The actual content of the specified MIME type that you are including in your email.
///
/// > Important: The minimum length is 1.
public var value: String

public init(
Expand Down
23 changes: 14 additions & 9 deletions Sources/SendGridKit/Models/MailSettings.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import Foundation

public struct MailSettings: Codable {

/// Allows you to bypass all unsubscribe groups and suppressions to ensure that the email is delivered to every single recipient. This should only be used in emergencies when it is absolutely necessary that every recipient receives your email.
public struct MailSettings: Codable, Sendable {
/// Allows you to bypass all unsubscribe groups and suppressions to ensure that the email is delivered to every single recipient.
///
/// > Important: This should only be used in emergencies when it is absolutely necessary that every recipient receives your email.
public var bypassListManagement: Setting?


/// Allows you to bypass the spam report list to ensure that the email is delivered to recipients. Bounce and unsubscribe lists will still be checked; addresses on these other lists will not receive the message.
/// Allows you to bypass the spam report list to ensure that the email is delivered to recipients.
///
/// > Note: Bounce and unsubscribe lists will still be checked;
/// addresses on these other lists will not receive the message.
public var bypassSpamManagement: Setting?

/// Allows you to bypass the bounce list to ensure that the email is delivered to recipients. Spam report and unsubscribe lists will still be checked; addresses on these other lists will not receive the message.
/// Allows you to bypass the bounce list to ensure that the email is delivered to recipients.
///
/// > Note: Spam report and unsubscribe lists will still be checked;
/// addresses on these other lists will not receive the message.
public var bypassBounceManagement: Setting?

/// The default footer that you would like included on every email.
Expand Down Expand Up @@ -41,13 +47,12 @@ public struct MailSettings: Codable {
}
}

public struct Setting: Codable {
public struct Setting: Codable, Sendable {
/// Indicates if this setting is enabled.
public var enable: Bool

}

public struct Footer: Codable {
public struct Footer: Codable, Sendable {
/// Indicates if this setting is enabled.
public var enable: Bool

Expand Down
24 changes: 15 additions & 9 deletions Sources/SendGridKit/Models/Personalization.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import Foundation

public struct Personalization: Codable {

/// An array of recipients. Each object within this array may contain the name, but must always contain the email, of a recipient.
public struct Personalization: Codable, Sendable {
/// An array of recipients.
///
/// > Important: Each object within this array may contain the name, but must always contain the email, of a recipient.
public var to: [EmailAddress]?

/// An array of recipients who will receive a copy of your email. Each object within this array may contain the name, but must always contain the email, of a recipient.
/// An array of recipients who will receive a copy of your email.
///
/// > Important: Each object within this array may contain the name, but must always contain the email, of a recipient.
public var cc: [EmailAddress]?

/// An array of recipients who will receive a blind carbon copy of your email. Each object within this array may contain the name, but must always contain the email, of a recipient.
/// An array of recipients who will receive a blind carbon copy of your email.
///
/// > Important: Each object within this array may contain the name, but must always contain the email, of a recipient.
public var bcc: [EmailAddress]?

/// The subject of your email.
Expand All @@ -17,16 +22,18 @@ public struct Personalization: Codable {
/// A collection of JSON key/value pairs allowing you to specify specific handling instructions for your email.
public var headers: [String: String]?

/// A collection of key/value pairs following the pattern "substitution_tag":"value to substitute".
/// A collection of key/value pairs following the pattern `"substitution_tag":"value to substitute"`.
public var substitutions: [String: String]?

/// A collection of key/value pairs following the pattern "key":"value" to substitute handlebar template data
/// A collection of key/value pairs following the pattern `"key":"value"` to substitute handlebar template data.
public var dynamicTemplateData: [String: String]?

/// Values that are specific to this personalization that will be carried along with the email and its activity data.
public var customArgs: [String: String]?

/// A unix timestamp allowing you to specify when you want your email to be delivered. Scheduling more than 72 hours in advance is forbidden.
/// A UNIX timestamp allowing you to specify when you want your email to be delivered.
///
/// > Important: Scheduling more than 72 hours in advance is forbidden.
public var sendAt: Date?

public init(
Expand Down Expand Up @@ -62,5 +69,4 @@ public struct Personalization: Codable {
case dynamicTemplateData = "dynamic_template_data"
case sendAt = "send_at"
}

}
Loading

0 comments on commit 5804515

Please sign in to comment.