Skip to content

Commit 2a36e75

Browse files
committed
Add package traits example
1 parent 44929c9 commit 2a36e75

File tree

13 files changed

+267
-0
lines changed

13 files changed

+267
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// swift-tools-version: 6.1
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "MiddlewareClientWithSQLCipher",
6+
products: [
7+
.library(name: "MiddlewareClientWithSQLCipher",
8+
targets: ["MiddlewareClientWithSQLCipher"])
9+
],
10+
dependencies: [
11+
.package(path: "../SQLMiddleware", traits: ["SQLCipher"])
12+
],
13+
targets: [
14+
.target(name: "MiddlewareClientWithSQLCipher", dependencies: [
15+
.product(name: "SQLMiddleware", package: "SQLMiddleware")
16+
]),
17+
.testTarget(name: "MiddlewareClientWithSQLCipherTests",
18+
dependencies: ["MiddlewareClientWithSQLCipher"])
19+
]
20+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import SQLMiddleware
2+
3+
func databaseVerison() -> String? {
4+
middlewareDatabaseType()
5+
}
6+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Testing
2+
@testable import MiddlewareClientWithSQLCipher
3+
4+
@Test func example() async throws {
5+
#expect(databaseVerison() == "SQLCipher 4.8.0 community")
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// swift-tools-version: 6.1
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "MiddlewareClientWithoutSQLCipher",
6+
products: [
7+
.library(name: "MiddlewareClientWithoutSQLCipher",
8+
targets: ["MiddlewareClientWithoutSQLCipher"])
9+
],
10+
dependencies: [
11+
.package(path: "../SQLMiddleware")
12+
],
13+
targets: [
14+
.target(name: "MiddlewareClientWithoutSQLCipher", dependencies: [
15+
.product(name: "SQLMiddleware", package: "SQLMiddleware")
16+
]),
17+
.testTarget(name: "MiddlewareClientWithoutSQLCipherTests",
18+
dependencies: ["MiddlewareClientWithoutSQLCipher"])
19+
]
20+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import SQLMiddleware
2+
3+
func databaseVerison() -> String? {
4+
middlewareDatabaseType()
5+
}
6+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Testing
2+
@testable import MiddlewareClientWithoutSQLCipher
3+
4+
@Test func example() async throws {
5+
#expect(databaseVerison() == "SQLite3 3.43.2")
6+
}

Examples/PackageTraits/README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
2+
## Package Trait Example
3+
4+
This example demonstrates conditionally including `swift-sqlcipher` based on a [package trait](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0450-swiftpm-package-traits.md) in order to support both plain `SQLite3` as well as `SQLCipher` from the same package.
5+
6+
There are three separate packages in this example:
7+
8+
```
9+
SQLMiddleware
10+
├── Package.swift
11+
└── Sources
12+
└── SQLMiddleware
13+
└── SQLMiddleware.swift
14+
15+
MiddlewareClientWithSQLCipher
16+
├── Package.swift
17+
├── Sources
18+
│   └── MiddlewareClientWithSQLCipher
19+
│   └── MiddlewareClientWithSQLCipher.swift
20+
└── Tests
21+
└── MiddlewareClientWithSQLCipherTests
22+
└── MiddlewareClientWithSQLCipherTests.swift
23+
24+
MiddlewareClientWithoutSQLCipher
25+
├── Package.swift
26+
├── Sources
27+
│   └── MiddlewareClientWithoutSQLCipher
28+
│   └── MiddlewareClientWithoutSQLCipher.swift
29+
└── Tests
30+
└── MiddlewareClientWithoutSQLCipherTests
31+
└── MiddlewareClientWithoutSQLCipherTests.swift
32+
```
33+
34+
### SQLMiddleware
35+
36+
The package with the dependency on `swift-sqlcipher` that publishes a "SQLCipher" trait enabling client packages to enable the `SQLCipher` import based on the dependency declaration in their `Package.swift`.
37+
38+
```swift
39+
// swift-tools-version: 6.1
40+
import PackageDescription
41+
42+
let package = Package(
43+
name: "SQLMiddleware",
44+
products: [
45+
.library(name: "SQLMiddleware", targets: ["SQLMiddleware"]),
46+
],
47+
traits: [
48+
.trait(name: "SQLCipher", description: "Use the SQLCipher library rather than the vendored SQLite")
49+
],
50+
dependencies: [
51+
.package(url: "https://github.com/skiptools/swift-sqlcipher.git", from: "1.4.0")
52+
],
53+
targets: [
54+
.target(name: "SQLMiddleware", dependencies: [
55+
// target only depends on SQLCipher when the "SQLCipher" trait is activated by a dependent package
56+
// otherwise it will default to using the system "SQLite3" framework
57+
.product(name: "SQLCipher", package: "swift-sqlcipher", condition: .when(traits: ["SQLCipher"]))
58+
])
59+
]
60+
)
61+
```
62+
63+
64+
The `SQLMiddleware` module has just a single top-level function `middlewareDatabaseType()` that will return either "SQLCipher <version>" or "SQLite3 <version>" depending on whether it was included with the "SQLCipher" trait.
65+
66+
```swift
67+
#if canImport(SQLCipher)
68+
import SQLCipher
69+
#else
70+
import SQLite3
71+
#endif
72+
73+
public func databaseVerison() -> String? {
74+
#if canImport(SQLCipher)
75+
let dbtype = "SQLCipher"
76+
let sql = "PRAGMA cipher_version;"
77+
#else
78+
let dbtype = "SQLite3"
79+
let sql = "SELECT sqlite_version();"
80+
#endif
81+
let version = queryString(sql: sql)
82+
return "\(dbtype) \(version ?? "unknown")"
83+
}
84+
85+
public func queryString(sql: String, databasePath: String = ":memory:") -> String? {
86+
if sqlite3_open(databasePath, &db) == SQLITE_OK {
87+
etc
88+
}
89+
}
90+
```
91+
92+
93+
### MiddlewareClientWithSQLCipher
94+
95+
A dependent of `SQLMiddleware` that enables the `SQLCipher` trait.
96+
97+
It contains a test case:
98+
99+
```swift
100+
@Test func example() async throws {
101+
#expect(databaseVerison() == "SQLCipher 4.8.0 community")
102+
}
103+
```
104+
105+
### MiddlewareClientWithoutSQLCipher
106+
107+
A dependent of `SQLMiddleware` that does not enable the `SQLCipher` trait. It is otherwise identical to `MiddlewareClientWithSQLCipher` in every way.
108+
109+
It contains a test case:
110+
111+
```swift
112+
@Test func example() async throws {
113+
#expect(databaseVerison() == "SQLite3 3.43.2")
114+
}
115+
```
116+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc

0 commit comments

Comments
 (0)