Skip to content

Commit f4af591

Browse files
authored
Add StructuredQueriesTagged package trait (#13)
* Add swift-tagged trait * Add TaggedStructuredQueries trait * Use same convention as Subprocess * wip * wip * wip
1 parent cfff2de commit f4af591

File tree

6 files changed

+260
-6
lines changed

6 files changed

+260
-6
lines changed

Package.resolved

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"originHash" : "587a4f16d6abcf8ce2a9823d3a1470bab537338281a888ef1c84c91c18be68a5",
2+
"originHash" : "a9cc8edf77ac5412b54a8aed27b41c2fc10588741da62b1886a48257aa83a50f",
33
"pins" : [
44
{
55
"identity" : "combine-schedulers",
@@ -69,8 +69,8 @@
6969
"kind" : "remoteSourceControl",
7070
"location" : "https://github.com/pointfreeco/swift-macro-testing",
7171
"state" : {
72-
"revision" : "cfe474c7e97d429ea31eefed2e9ab8c7c74260f9",
73-
"version" : "0.6.2"
72+
"revision" : "2de00af725ff4c43c9a90d7893835de312653169",
73+
"version" : "0.6.3"
7474
}
7575
},
7676
{
@@ -91,6 +91,15 @@
9191
"version" : "601.0.1"
9292
}
9393
},
94+
{
95+
"identity" : "swift-tagged",
96+
"kind" : "remoteSourceControl",
97+
"location" : "https://github.com/pointfreeco/swift-tagged",
98+
"state" : {
99+
"revision" : "3907a9438f5b57d317001dc99f3f11b46882272b",
100+
"version" : "0.10.0"
101+
}
102+
},
94103
{
95104
"identity" : "xctest-dynamic-overlay",
96105
"kind" : "remoteSourceControl",

Package.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 6.0
1+
// swift-tools-version: 6.1
22

33
import CompilerPluginSupport
44
import PackageDescription
@@ -29,11 +29,19 @@ let package = Package(
2929
targets: ["StructuredQueriesSQLite"]
3030
),
3131
],
32+
traits: [
33+
.trait(
34+
name: "StructuredQueriesTagged",
35+
description: "Introduce StructuredQueries conformances to the swift-tagged package.",
36+
enabledTraits: []
37+
)
38+
],
3239
dependencies: [
3340
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"),
3441
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.8.1"),
35-
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.0"),
36-
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.1"),
42+
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.3"),
43+
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"),
44+
.package(url: "https://github.com/pointfreeco/swift-tagged", from: "0.10.0"),
3745
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.2"),
3846
.package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"602.0.0"),
3947
],
@@ -43,6 +51,11 @@ let package = Package(
4351
dependencies: [
4452
"StructuredQueriesSupport",
4553
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
54+
.product(
55+
name: "Tagged",
56+
package: "swift-tagged",
57+
condition: .when(traits: ["StructuredQueriesTagged"])
58+
),
4659
]
4760
),
4861
.target(

[email protected]

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// swift-tools-version: 6.0
2+
3+
import CompilerPluginSupport
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "swift-structured-queries",
8+
platforms: [
9+
.iOS(.v13),
10+
.macOS(.v10_15),
11+
.tvOS(.v13),
12+
.watchOS(.v6),
13+
],
14+
products: [
15+
.library(
16+
name: "StructuredQueries",
17+
targets: ["StructuredQueries"]
18+
),
19+
.library(
20+
name: "StructuredQueriesCore",
21+
targets: ["StructuredQueriesCore"]
22+
),
23+
.library(
24+
name: "StructuredQueriesTestSupport",
25+
targets: ["StructuredQueriesTestSupport"]
26+
),
27+
.library(
28+
name: "_StructuredQueriesSQLite",
29+
targets: ["StructuredQueriesSQLite"]
30+
),
31+
],
32+
dependencies: [
33+
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"),
34+
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.8.1"),
35+
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.3"),
36+
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"),
37+
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.2"),
38+
.package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"602.0.0"),
39+
],
40+
targets: [
41+
.target(
42+
name: "StructuredQueriesCore",
43+
dependencies: [
44+
"StructuredQueriesSupport",
45+
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
46+
]
47+
),
48+
.target(
49+
name: "StructuredQueries",
50+
dependencies: [
51+
"StructuredQueriesCore",
52+
"StructuredQueriesMacros",
53+
]
54+
),
55+
.macro(
56+
name: "StructuredQueriesMacros",
57+
dependencies: [
58+
"StructuredQueriesSupport",
59+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
60+
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
61+
]
62+
),
63+
.target(
64+
name: "StructuredQueriesSQLite",
65+
dependencies: [
66+
"StructuredQueries"
67+
]
68+
),
69+
.target(
70+
name: "StructuredQueriesTestSupport",
71+
dependencies: [
72+
"StructuredQueriesCore",
73+
.product(name: "CustomDump", package: "swift-custom-dump"),
74+
.product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"),
75+
]
76+
),
77+
.testTarget(
78+
name: "StructuredQueriesMacrosTests",
79+
dependencies: [
80+
"StructuredQueries",
81+
"StructuredQueriesMacros",
82+
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
83+
.product(name: "MacroTesting", package: "swift-macro-testing"),
84+
]
85+
),
86+
.testTarget(
87+
name: "StructuredQueriesTests",
88+
dependencies: [
89+
"StructuredQueries",
90+
"StructuredQueriesSQLite",
91+
"StructuredQueriesTestSupport",
92+
.product(name: "CustomDump", package: "swift-custom-dump"),
93+
.product(name: "Dependencies", package: "swift-dependencies"),
94+
.product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"),
95+
]
96+
),
97+
98+
.target(name: "StructuredQueriesSupport"),
99+
],
100+
swiftLanguageModes: [.v6]
101+
)
102+
103+
let swiftSettings: [SwiftSetting] = [
104+
.enableUpcomingFeature("MemberImportVisibility")
105+
// .unsafeFlags([
106+
// "-Xfrontend",
107+
// "-warn-long-function-bodies=50",
108+
// "-Xfrontend",
109+
// "-warn-long-expression-type-checking=50",
110+
// ])
111+
]
112+
113+
for index in package.targets.indices {
114+
package.targets[index].swiftSettings = swiftSettings
115+
}
116+
117+
#if !os(Darwin)
118+
package.targets.append(
119+
.systemLibrary(
120+
name: "StructuredQueriesSQLite3",
121+
providers: [.apt(["libsqlite3-dev"])]
122+
)
123+
)
124+
125+
for index in package.targets.indices {
126+
if package.targets[index].name == "StructuredQueriesSQLite" {
127+
package.targets[index].dependencies.append("StructuredQueriesSQLite3")
128+
}
129+
}
130+
#endif
131+
132+
#if !os(Windows)
133+
// Add the documentation compiler plugin if possible
134+
package.dependencies.append(
135+
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0")
136+
)
137+
#endif

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,23 @@ And then adding the product to any target that needs access to the library:
230230
.product(name: "StructuredQueries", package: "swift-structured-queries"),
231231
```
232232

233+
If you are on Swift 6.1 or greater, you can enable package traits that extend the library with
234+
support for other libraries. For example, you can introduce type-safe identifiers to your tables
235+
_via_ [Tagged](https://github.com/pointfreeco/swift-tagged) by enabling the
236+
`StructuredQueriesTagged` trait:
237+
238+
```diff
239+
dependencies: [
240+
.package(
241+
url: "https://github.com/pointfreeco/swift-structured-queries",
242+
from: "0.1.0",
243+
+ traits: [
244+
+ "StructuredQueriesTagged",
245+
+ ]
246+
),
247+
]
248+
```
249+
233250
## Community
234251

235252
If you want to discuss this library or have a question about how to use it to solve a particular

Sources/StructuredQueriesCore/Documentation.docc/Articles/DefiningYourSchema.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,51 @@ With that you can insert reminders with notes like so:
258258
}
259259
}
260260
261+
#### Tagged identifiers
262+
263+
The [Tagged](https://github.com/pointfreeco/swift-tagged) library provides lightweight syntax for
264+
introducing type-safe identifiers (and more) to your models. StructuredQueries ships support for
265+
Tagged with a `StructuredQueriesTagged` package trait, which is available starting from Swift 6.1.
266+
267+
To enable the trait, specify it in the Package.swift file that depends on StructuredQueries:
268+
269+
```diff
270+
.package(
271+
url: "https://github.com/pointfreeco/swift-structured-queries",
272+
from: "0.2.0",
273+
+ traits: ["StructuredQueriesTagged"]
274+
),
275+
```
276+
277+
This will allow you to introduce distinct `Tagged` identifiers throughout your schema:
278+
279+
```diff
280+
@Table
281+
struct RemindersList: Identifiable {
282+
- let id: Int
283+
+ typealias ID = Tagged<Self, Int>
284+
+ let id: ID
285+
// ...
286+
}
287+
@Table
288+
struct Reminder: Identifiable {
289+
- let id: Int
290+
+ typealias ID = Tagged<Self, Int>
291+
+ let id: ID
292+
// ...
293+
var remindersList: Reminder.ID
294+
}
295+
```
296+
297+
This adds a new layer of type-safety when constructing queries. Previously comparing a
298+
`RemindersList.ID` to a `Reminder.ID` would compile just fine, even though it is a nonsensical thing
299+
to do. But now, such a comparison is a compile time error:
300+
301+
```
302+
RemindersList.leftJoin(Reminder.all) {
303+
$0.id == $1.id // 🛑 Requires the types 'Reminder.ID' and 'RemindersList.ID' be equivalent
304+
}
305+
261306
#### Default representations for dates and UUIDs
262307
263308
While some relational databases, like MySQL and Postgres, have native types for dates and UUIDs,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#if StructuredQueriesTagged
2+
import Tagged
3+
4+
extension Tagged: _OptionalPromotable where RawValue: _OptionalPromotable {}
5+
6+
extension Tagged: QueryBindable where RawValue: QueryBindable {}
7+
8+
extension Tagged: QueryDecodable where RawValue: QueryDecodable {}
9+
10+
extension Tagged: QueryExpression where RawValue: QueryExpression {
11+
public var queryFragment: QueryFragment {
12+
rawValue.queryFragment
13+
}
14+
}
15+
16+
extension Tagged: QueryRepresentable where RawValue: QueryRepresentable {
17+
public typealias QueryOutput = Tagged<Tag, RawValue.QueryOutput>
18+
19+
public var queryOutput: QueryOutput {
20+
QueryOutput(rawValue: self.rawValue.queryOutput)
21+
}
22+
23+
public init(queryOutput: QueryOutput) {
24+
self.init(rawValue: RawValue(queryOutput: queryOutput.rawValue))
25+
}
26+
}
27+
28+
extension Tagged: SQLiteType where RawValue: SQLiteType {
29+
public static var typeAffinity: SQLiteTypeAffinity {
30+
RawValue.typeAffinity
31+
}
32+
}
33+
#endif

0 commit comments

Comments
 (0)