Skip to content

Commit c94c500

Browse files
authored
Extract the LCP persistence layer (#442)
1 parent 587f195 commit c94c500

23 files changed

+388
-236
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ All notable changes to this project will be documented in this file. Take a look
2626

2727
* EPUB: The `scroll` preference is now forced to `true` when rendering vertical text (e.g. CJK vertical). [See this discussion for the rationale](https://github.com/readium/swift-toolkit/discussions/370).
2828

29+
#### LCP
30+
31+
* The Readium LCP persistence layer was extracted to allow applications to provide their own implementations. Take a look at [the migration guide](Documentation/Migration%20Guide.md) for guidance.
32+
2933
### Fixed
3034

3135
#### Navigator

Cartfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ github "krzyzanowskim/CryptoSwift" == 1.5.1 # From 1.6.0, the build fails in Git
44
github "ra1028/DifferenceKit" ~> 1.3.0
55
github "readium/GCDWebServer" ~> 4.0.0
66
github "scinfu/SwiftSoup" == 2.5.3 # 2.6.0 requires Xcode 14
7-
github "stephencelis/SQLite.swift" == 0.13.3 # 0.14 introduces a breaking change
7+
github "stephencelis/SQLite.swift" ~> 0.15.3
88
github "weichsel/ZIPFoundation" == 0.9.11 # 0.9.12 requires iOS 12+

Documentation/Guides/Getting Started.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The toolkit has been designed following these core tenets:
2828
### Adapters to third-party dependencies
2929

3030
* `ReadiumAdapterGCDWebServer` provides an HTTP server built with [GCDWebServer](https://github.com/swisspol/GCDWebServer).
31+
* `ReadiumAdapterLCPSQLite` provides implementations of the `ReadiumLCP` license and passphrase repositories using [SQLite.swift](https://github.com/stephencelis/SQLite.swift).
3132

3233
## Overview of the shared models (`R2Shared`)
3334

Documentation/Migration Guide.md

+30
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,36 @@ All migration steps necessary in reading apps to upgrade to major versions of th
88

99
Plenty of completion-based APIs were changed to use `async` functions instead. Follow the deprecation warnings to update your codebase.
1010

11+
### Readium LCP SQLite adapter
12+
13+
The Readium LCP persistence layer was extracted to allow applications to provide their own implementations. The previous implementation is now part of a new package, `ReadiumAdapterLCPSQLite`, which you need to use to maintain the same behavior as before.
14+
15+
To use `ReadiumAdapterLCPSQLite`, you must update your imports and the dependencies included in your project:
16+
17+
* Swift Package Manager:
18+
* Add the `ReadiumAdapterLCPSQLite` package to your project dependencies.
19+
* Carthage:
20+
* Update the Carthage dependencies and make sure the new `ReadiumAdapterLCPSQLite.xcframework` was built.
21+
* Add this new framework to your project dependencies.
22+
* CocoaPods:
23+
* Update the `pod` statements in your `Podfile` with the following, before running `pod install`:
24+
```
25+
pod 'ReadiumAdapterLCPSQLite', podspec: 'https://raw.githubusercontent.com/readium/swift-toolkit/3.0.0/Support/CocoaPods/ReadiumAdapterLCPSQLite.podspec'
26+
```
27+
Then, provide the adapters when initializing the `LCPService`.
28+
29+
```swift
30+
import ReadiumAdapterLCPSQLite
31+
import ReadiumLCP
32+
33+
let lcpService = LCPService(
34+
client: LCPClient(),
35+
licenseRepository: LCPSQLiteLicenseRepository(),
36+
passphraseRepository: LCPSQLitePassphraseRepository(),
37+
httpClient: DefaultHTTPClient()
38+
)
39+
```
40+
1141

1242
## 3.0.0-alpha.1
1343

Package.swift

+11-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ let package = Package(
2020

2121
// Adapters to third-party dependencies.
2222
.library(name: "ReadiumAdapterGCDWebServer", targets: ["ReadiumAdapterGCDWebServer"]),
23+
.library(name: "ReadiumAdapterLCPSQLite", targets: ["ReadiumAdapterLCPSQLite"]),
2324
],
2425
dependencies: [
2526
.package(url: "https://github.com/cezheng/Fuzi.git", from: "3.1.3"),
@@ -30,8 +31,7 @@ let package = Package(
3031
.package(url: "https://github.com/readium/GCDWebServer.git", from: "4.0.0"),
3132
// From 2.6.0, Xcode 14 is required
3233
.package(url: "https://github.com/scinfu/SwiftSoup.git", "2.5.3" ..< "2.6.0"),
33-
// 0.14 introduced a breaking change
34-
.package(url: "https://github.com/stephencelis/SQLite.swift.git", "0.12.0" ..< "0.13.3"),
34+
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.3"),
3535
// 0.9.12 requires iOS 12+
3636
.package(url: "https://github.com/weichsel/ZIPFoundation.git", "0.9.0" ..< "0.9.12"),
3737
],
@@ -130,7 +130,6 @@ let package = Package(
130130
"CryptoSwift",
131131
"ZIPFoundation",
132132
"ReadiumShared",
133-
.product(name: "SQLite", package: "SQLite.swift"),
134133
],
135134
path: "Sources/LCP",
136135
resources: [
@@ -157,6 +156,15 @@ let package = Package(
157156
path: "Sources/Adapters/GCDWebServer"
158157
),
159158

159+
.target(
160+
name: "ReadiumAdapterLCPSQLite",
161+
dependencies: [
162+
.product(name: "SQLite", package: "SQLite.swift"),
163+
"ReadiumLCP",
164+
],
165+
path: "Sources/Adapters/LCPSQLite"
166+
),
167+
160168
.target(
161169
name: "ReadiumInternal",
162170
path: "Sources/Internal"

README.md

+14-13
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,18 @@ Note that Carthage will build all Readium modules and their dependencies, but yo
5454

5555
Refer to the following table to know which dependencies are required for each Readium library.
5656

57-
| | `ReadiumShared` | `ReadiumStreamer` | `ReadiumNavigator` | `ReadiumOPDS` | `ReadiumLCP` |
58-
|-----------------------|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|
59-
| **`ReadiumShared`** | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
60-
| **`ReadiumInternal`** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
61-
| `CryptoSwift` | | :heavy_check_mark: | | | :heavy_check_mark: |
62-
| `DifferenceKit` | | | :heavy_check_mark: | | |
63-
| `Fuzi` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
64-
| `Minizip` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
65-
| `ReadiumGCDWebServer` | | :heavy_check_mark: | | | |
66-
| `SQLite.swift` | | | | | :heavy_check_mark: |
67-
| `SwiftSoup` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
68-
| `ZIPFoundation` | | | | | :heavy_check_mark: |
57+
| | `ReadiumShared` | `ReadiumStreamer` | `ReadiumNavigator` | `ReadiumOPDS` | `ReadiumLCP` | `ReadiumAdapterGCDWebServer` | `ReadiumAdapterLCPSQLite` |
58+
|-----------------------|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|------------------------------|---------------------------|
59+
| **`ReadiumShared`** | | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
60+
| **`ReadiumInternal`** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | |
61+
| `CryptoSwift` | | :heavy_check_mark: | | | :heavy_check_mark: | | |
62+
| `DifferenceKit` | | | :heavy_check_mark: | | | | |
63+
| `Fuzi` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | |
64+
| `Minizip` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | |
65+
| `ReadiumGCDWebServer` | | | | | | :heavy_check_mark: | |
66+
| `SQLite.swift` | | | | | | | :heavy_check_mark: |
67+
| `SwiftSoup` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | |
68+
| `ZIPFoundation` | | | | | :heavy_check_mark: | | |
6969

7070
### CocoaPods
7171

@@ -79,7 +79,7 @@ pod 'ReadiumOPDS', podspec: 'https://raw.githubusercontent.com/readium/swift-too
7979
pod 'ReadiumLCP', podspec: 'https://raw.githubusercontent.com/readium/swift-toolkit/3.0.0-alpha.1/Support/CocoaPods/ReadiumLCP.podspec'
8080
pod 'ReadiumInternal', podspec: 'https://raw.githubusercontent.com/readium/swift-toolkit/3.0.0-alpha.1/Support/CocoaPods/ReadiumInternal.podspec'
8181
82-
# Required if you use ReadiumStreamer.
82+
# Required if you use ReadiumAdapterGCDWebServer.
8383
pod 'ReadiumGCDWebServer', podspec: 'https://raw.githubusercontent.com/readium/GCDWebServer/4.0.0/GCDWebServer.podspec'
8484
```
8585

@@ -102,3 +102,4 @@ Finally, add the Readium libraries you want to use to your app target from the *
102102
### Building with Readium LCP
103103

104104
Using the toolkit with Readium LCP requires additional dependencies, including the framework `R2LCPClient.framework` provided by EDRLab. [Contact EDRLab](mailto:[email protected]) to request your private `R2LCPClient.framework` and the setup instructions.
105+

Sources/LCP/Persistence/SQLiteLCPLicenseRepository.swift renamed to Sources/Adapters/LCPSQLite/SQLiteLCPLicenseRepository.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
//
66

77
import Foundation
8+
import ReadiumLCP
89
import SQLite
910

10-
public class SQLiteLCPLicenseRepository: LCPLicenseRepository {
11+
public class LCPSQLiteLicenseRepository: LCPLicenseRepository {
1112
let licenses = Table("Licenses")
1213
let id = Expression<String>("id")
1314
let printsLeft = Expression<Int?>("printsLeft")
@@ -55,8 +56,7 @@ public class SQLiteLCPLicenseRepository: LCPLicenseRepository {
5556

5657
public func isDeviceRegistered(for id: LicenseDocument.ID) async throws -> Bool {
5758
try checkExists(id)
58-
let query = licenses.filter(self.id == id && registered == true)
59-
let count = try db.count(query)
59+
let count = try db.scalar(licenses.filter(self.id == id && registered == true).count)
6060
return count != 0
6161
}
6262

@@ -94,7 +94,7 @@ public class SQLiteLCPLicenseRepository: LCPLicenseRepository {
9494
}
9595

9696
private func exists(_ licenseID: LicenseDocument.ID) -> Bool {
97-
((try? db.count(licenses.filter(id == licenseID))) ?? 0) != 0
97+
((try? db.scalar(licenses.filter(id == licenseID).count)) ?? 0) != 0
9898
}
9999

100100
private func get(_ column: Expression<Int?>, for licenseId: String) throws -> Int? {

Sources/LCP/Persistence/SQLiteLCPPassphraseRepository.swift renamed to Sources/Adapters/LCPSQLite/SQLiteLCPPassphraseRepository.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
//
66

77
import Foundation
8+
import ReadiumLCP
89
import ReadiumShared
910
import SQLite
1011

11-
public class SQLiteLCPPassphraseRepository: LCPPassphraseRepository, Loggable {
12+
public class LCPSQLitePassphraseRepository: LCPPassphraseRepository, Loggable {
1213
let transactions = Table("Transactions")
1314
let licenseId = Expression<String>("licenseId")
1415
let provider = Expression<String>("origin")

Sources/LCP/Authentications/LCPDialogViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ final class LCPDialogViewController: UIViewController {
181181
present(browser, animated: true)
182182
}
183183

184-
/// Makes sure the form contents in scrollable when the keyboard is visible.
184+
/// Makes sure the form contents is scrollable when the keyboard is visible.
185185
@objc func keyboardWillChangeFrame(_ note: Notification) {
186186
guard let window = UIApplication.shared.keyWindow, let scrollView = scrollView, let scrollViewSuperview = scrollView.superview, let info = note.userInfo else {
187187
return

Sources/LCP/Persistence/Connection.swift

-17
This file was deleted.

Support/Carthage/.xcodegen

+36-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
}
1919
}
2020
},
21+
"ReadiumAdapterLCPSQLite" : {
22+
"build" : {
23+
"targets" : {
24+
"ReadiumAdapterLCPSQLite" : "all"
25+
}
26+
}
27+
},
2128
"ReadiumInternal" : {
2229
"build" : {
2330
"targets" : {
@@ -87,6 +94,31 @@
8794
],
8895
"type" : "framework"
8996
},
97+
"ReadiumAdapterLCPSQLite" : {
98+
"dependencies" : [
99+
{
100+
"framework" : "..\/..\/Carthage\/Build\/SQLite.xcframework"
101+
},
102+
{
103+
"target" : "ReadiumShared"
104+
},
105+
{
106+
"target" : "ReadiumLCP"
107+
}
108+
],
109+
"deploymentTarget" : "13.0",
110+
"platform" : "iOS",
111+
"settings" : {
112+
"INFOPLIST_FILE" : "Info.plist",
113+
"PRODUCT_BUNDLE_IDENTIFIER" : "org.readium.swift-toolkit.adapter.lcpsqlite"
114+
},
115+
"sources" : [
116+
{
117+
"path" : "..\/..\/Sources\/Adapters\/LCPSQLite"
118+
}
119+
],
120+
"type" : "framework"
121+
},
90122
"ReadiumInternal" : {
91123
"deploymentTarget" : "13.0",
92124
"platform" : "iOS",
@@ -112,9 +144,6 @@
112144
{
113145
"framework" : "..\/..\/Carthage\/Build\/Minizip.xcframework"
114146
},
115-
{
116-
"framework" : "..\/..\/Carthage\/Build\/SQLite.xcframework"
117-
},
118147
{
119148
"framework" : "..\/..\/Carthage\/Build\/ZIPFoundation.xcframework"
120149
},
@@ -290,6 +319,10 @@
290319
../../Sources/Adapters/GCDWebServer
291320
../../Sources/Adapters/GCDWebServer/GCDHTTPServer.swift
292321
../../Sources/Adapters/GCDWebServer/ResourceResponse.swift
322+
../../Sources/Adapters/LCPSQLite
323+
../../Sources/Adapters/LCPSQLite/Database.swift
324+
../../Sources/Adapters/LCPSQLite/SQLiteLCPLicenseRepository.swift
325+
../../Sources/Adapters/LCPSQLite/SQLiteLCPPassphraseRepository.swift
293326
../../Sources/Internal
294327
../../Sources/Internal/Extensions
295328
../../Sources/Internal/Extensions/Array.swift
@@ -349,11 +382,6 @@
349382
../../Sources/LCP/License/Model/Components/LSD/PotentialRights.swift
350383
../../Sources/LCP/License/Model/LicenseDocument.swift
351384
../../Sources/LCP/License/Model/StatusDocument.swift
352-
../../Sources/LCP/Persistence
353-
../../Sources/LCP/Persistence/Connection.swift
354-
../../Sources/LCP/Persistence/Database.swift
355-
../../Sources/LCP/Persistence/SQLiteLCPLicenseRepository.swift
356-
../../Sources/LCP/Persistence/SQLiteLCPPassphraseRepository.swift
357385
../../Sources/LCP/Resources
358386
../../Sources/LCP/Resources/en.lproj
359387
../../Sources/LCP/Resources/en.lproj/Localizable.strings

0 commit comments

Comments
 (0)