Skip to content

Commit 8752829

Browse files
committed
Provide default model middleware
1 parent ce8ada5 commit 8752829

File tree

12 files changed

+107
-137
lines changed

12 files changed

+107
-137
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ let package = Package(
1111
.library(name: "Orders", targets: ["Orders"]),
1212
],
1313
dependencies: [
14-
.package(url: "https://github.com/vapor/vapor.git", from: "4.107.0"),
14+
.package(url: "https://github.com/vapor/vapor.git", from: "4.108.0"),
1515
.package(url: "https://github.com/vapor/fluent.git", from: "4.12.0"),
1616
.package(url: "https://github.com/vapor/apns.git", from: "4.2.0"),
1717
.package(url: "https://github.com/vapor-community/Zip.git", from: "2.2.4"),
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import FluentKit
2+
import Foundation
3+
4+
extension OrdersService: AsyncModelMiddleware {
5+
public func create(model: OD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
6+
let order = Order(
7+
typeIdentifier: OD.typeIdentifier,
8+
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString()
9+
)
10+
try await order.save(on: db)
11+
model._$order.id = try order.requireID()
12+
try await next.create(model, on: db)
13+
}
14+
15+
public func update(model: OD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
16+
let order = try await model._$order.get(on: db)
17+
order.updatedAt = Date.now
18+
try await order.save(on: db)
19+
try await next.update(model, on: db)
20+
try await self.sendPushNotifications(for: model, on: db)
21+
}
22+
}
23+
24+
extension OrdersServiceCustom: AsyncModelMiddleware {
25+
public func create(model: OD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
26+
let order = O(
27+
typeIdentifier: OD.typeIdentifier,
28+
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString()
29+
)
30+
try await order.save(on: db)
31+
model._$order.id = try order.requireID()
32+
try await next.create(model, on: db)
33+
}
34+
35+
public func update(model: OD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
36+
let order = try await model._$order.get(on: db)
37+
order.updatedAt = Date.now
38+
try await order.save(on: db)
39+
try await next.update(model, on: db)
40+
try await self.sendPushNotifications(for: model, on: db)
41+
}
42+
}

Sources/Orders/Models/OrderModel.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ public protocol OrderModel: Model where IDValue == UUID {
1616

1717
/// The authentication token supplied to your web service.
1818
var authenticationToken: String { get set }
19+
20+
/// The designated initializer.
21+
/// - Parameters:
22+
/// - typeIdentifier: The order type identifier that’s registered with Apple.
23+
/// - authenticationToken: The authentication token to use with the web service in the `webServiceURL` key.
24+
init(typeIdentifier: String, authenticationToken: String)
1925
}
2026

2127
extension OrderModel {

Sources/Orders/Orders.docc/GettingStarted.md

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -199,49 +199,18 @@ OrdersService<OrderData>.register(migrations: app.migrations)
199199
200200
### Order Data Model Middleware
201201

202-
You'll want to create a model middleware to handle the creation and update of the order data model.
203-
This middleware could be responsible for creating and linking an ``Order`` to the order data model, depending on your requirements.
204-
When your order data changes, it should also update the ``Order/updatedAt`` field of the ``Order`` and send a push notification to all devices registered to that order.
202+
This framework provides a model middleware to handle the creation and update of the order data model.
205203

206-
```swift
207-
import Vapor
208-
import Fluent
209-
import Orders
210-
211-
struct OrderDataMiddleware: AsyncModelMiddleware {
212-
private unowned let service: OrdersService<OrderData>
213-
214-
init(service: OrdersService<OrderData>) {
215-
self.service = service
216-
}
217-
218-
// Create the `Order` and add it to the `OrderData` automatically at creation
219-
func create(model: OrderData, on db: Database, next: AnyAsyncModelResponder) async throws {
220-
let order = Order(
221-
typeIdentifier: Environment.get("ORDER_TYPE_IDENTIFIER")!,
222-
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString())
223-
try await order.save(on: db)
224-
model.$order.id = try order.requireID()
225-
try await next.create(model, on: db)
226-
}
227-
228-
func update(model: OrderData, on db: Database, next: AnyAsyncModelResponder) async throws {
229-
let order = try await model.$order.get(on: db)
230-
order.updatedAt = Date()
231-
try await order.save(on: db)
232-
try await next.update(model, on: db)
233-
try await service.sendPushNotifications(for: model, on: db)
234-
}
235-
}
236-
```
204+
When you create an ``OrderDataModel`` object, it will automatically create an ``OrderModel`` object with a random auth token and the correct type identifier and link it to the order data model.
205+
When you update an order data model, it will update the ``OrderModel`` object and send a push notification to all devices registered to that order.
237206

238-
You could register it in the `configure.swift` file.
207+
You can register it like so (either with an ``OrdersService`` or an ``OrdersServiceCustom``):
239208

240209
```swift
241-
app.databases.middleware.use(OrderDataMiddleware(service: ordersService), on: .psql)
210+
app.databases.middleware.use(ordersService, on: .psql)
242211
```
243212

244-
> Important: Whenever your order data changes, you must update the ``Order/updatedAt`` time of the linked ``Order`` so that Wallet knows to retrieve a new order.
213+
> Note: If you don't like the default implementation of the model middleware, it is highly recommended that you create your own. But remember: whenever your order data changes, you must update the ``Order/updatedAt`` time of the linked ``Order`` so that Wallet knows to retrieve a new order.
245214
246215
### Generate the Order Content
247216

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import FluentKit
2+
import Foundation
3+
4+
extension PassesService: AsyncModelMiddleware {
5+
public func create(model: PD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
6+
let pass = Pass(
7+
typeIdentifier: PD.typeIdentifier,
8+
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString()
9+
)
10+
try await pass.save(on: db)
11+
model._$pass.id = try pass.requireID()
12+
try await next.create(model, on: db)
13+
}
14+
15+
public func update(model: PD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
16+
let pass = try await model._$pass.get(on: db)
17+
pass.updatedAt = Date.now
18+
try await pass.save(on: db)
19+
try await next.update(model, on: db)
20+
try await self.sendPushNotifications(for: model, on: db)
21+
}
22+
}
23+
24+
extension PassesServiceCustom: AsyncModelMiddleware {
25+
public func create(model: PD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
26+
let pass = P(
27+
typeIdentifier: PD.typeIdentifier,
28+
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString()
29+
)
30+
try await pass.save(on: db)
31+
model._$pass.id = try pass.requireID()
32+
try await next.create(model, on: db)
33+
}
34+
35+
public func update(model: PD, on db: any Database, next: any AnyAsyncModelResponder) async throws {
36+
let pass = try await model._$pass.get(on: db)
37+
pass.updatedAt = Date.now
38+
try await pass.save(on: db)
39+
try await next.update(model, on: db)
40+
try await self.sendPushNotifications(for: model, on: db)
41+
}
42+
}

Sources/Passes/Passes.docc/GettingStarted.md

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -224,49 +224,18 @@ PassesService<PassData>.register(migrations: app.migrations)
224224
225225
### Pass Data Model Middleware
226226

227-
You'll want to create a model middleware to handle the creation and update of the pass data model.
228-
This middleware could be responsible for creating and linking a ``Pass`` to the pass data model, depending on your requirements.
229-
When your pass data changes, it should also update the ``Pass/updatedAt`` field of the ``Pass`` and send a push notification to all devices registered to that pass.
227+
This framework provides a model middleware to handle the creation and update of the pass data model.
230228

231-
```swift
232-
import Vapor
233-
import Fluent
234-
import Passes
235-
236-
struct PassDataMiddleware: AsyncModelMiddleware {
237-
private unowned let service: PassesService<PassData>
238-
239-
init(service: PassesService<PassData>) {
240-
self.service = service
241-
}
242-
243-
// Create the `Pass` and add it to the `PassData` automatically at creation
244-
func create(model: PassData, on db: Database, next: AnyAsyncModelResponder) async throws {
245-
let pass = Pass(
246-
typeIdentifier: Environment.get("PASS_TYPE_IDENTIFIER")!,
247-
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString())
248-
try await pass.save(on: db)
249-
model.$pass.id = try pass.requireID()
250-
try await next.create(model, on: db)
251-
}
252-
253-
func update(model: PassData, on db: Database, next: AnyAsyncModelResponder) async throws {
254-
let pass = try await model.$pass.get(on: db)
255-
pass.updatedAt = Date()
256-
try await pass.save(on: db)
257-
try await next.update(model, on: db)
258-
try await service.sendPushNotifications(for: model, on: db)
259-
}
260-
}
261-
```
229+
When you create a ``PassDataModel`` object, it will automatically create a ``PassModel`` object with a random auth token and the correct type identifier and link it to the pass data model.
230+
When you update a pass data model, it will update the ``PassModel`` object and send a push notification to all devices registered to that pass.
262231

263-
You could register it in the `configure.swift` file.
232+
You can register it like so (either with a ``PassesService`` or a ``PassesServiceCustom``):
264233

265234
```swift
266-
app.databases.middleware.use(PassDataMiddleware(service: passesService), on: .psql)
235+
app.databases.middleware.use(passesService, on: .psql)
267236
```
268237

269-
> Important: Whenever your pass data changes, you must update the ``Pass/updatedAt`` time of the linked ``Pass`` so that Wallet knows to retrieve a new pass.
238+
> Note: If you don't like the default implementation of the model middleware, it is highly recommended that you create your own. But remember: whenever your pass data changes, you must update the ``Pass/updatedAt`` time of the linked ``Pass`` so that Wallet knows to retrieve a new pass.
270239
271240
### Generate the Pass Content
272241

Tests/OrdersTests/OrdersTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ struct OrdersTests {
384384
)
385385

386386
if !useEncryptedKey {
387-
// Test `OrderDataMiddleware` update method
387+
// Test `AsyncModelMiddleware` update method
388388
orderData.title = "Test Order 2"
389389
do {
390390
try await orderData.update(on: app.db)

Tests/OrdersTests/Utils/OrderDataMiddleware.swift

Lines changed: 0 additions & 29 deletions
This file was deleted.

Tests/OrdersTests/Utils/withApp.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func withApp(
2828
pemPrivateKey: useEncryptedKey ? TestCertificate.encryptedPemPrivateKey : TestCertificate.pemPrivateKey,
2929
pemPrivateKeyPassword: useEncryptedKey ? "password" : nil
3030
)
31-
app.databases.middleware.use(OrderDataMiddleware(service: ordersService), on: .sqlite)
31+
app.databases.middleware.use(ordersService, on: .sqlite)
3232

3333
Zip.addCustomFileExtension("order")
3434

Tests/PassesTests/PassesTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ struct PassesTests {
522522
)
523523

524524
if !useEncryptedKey {
525-
// Test `PassDataMiddleware` update method
525+
// Test `AsyncModelMiddleware` update method
526526
passData.title = "Test Pass 2"
527527
do {
528528
try await passData.update(on: app.db)

0 commit comments

Comments
 (0)