Skip to content

Commit 503c0f0

Browse files
committed
Added package collections to the keyword result pages
1 parent 17184b7 commit 503c0f0

File tree

8 files changed

+59
-7
lines changed

8 files changed

+59
-7
lines changed

Sources/App/Controllers/PackageCollectionController.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ enum PackageCollectionController {
3232
filterBy: .author(owner),
3333
authorName: "\(owner) via the Swift Package Index"
3434
)
35+
case let .keyword(keyword):
36+
return try await SignedCollection.generate(
37+
db: req.db,
38+
filterBy: .keyword(keyword),
39+
authorName: "Swift Package Index",
40+
collectionName: keyword,
41+
keywords: [keyword],
42+
overview: "A custom package collection generated by the Swift Package Index"
43+
)
3544
case let .custom(key):
3645
let collection = try await CustomCollection.find(on: req.db, key: key)
3746
.unwrap(or: Abort(.notFound))
@@ -50,11 +59,13 @@ enum PackageCollectionController {
5059

5160
enum CollectionType {
5261
case author(String)
62+
case keyword(String)
5363
case custom(String)
5464
}
5565

5666
static func getCollectionType(req: Request) -> CollectionType? {
5767
if let owner = req.parameters.get("owner") { return .author(owner) }
68+
if let keyword = req.parameters.get("keyword") { return .keyword(keyword) }
5869
if let key = req.parameters.get("key") { return .custom(key) }
5970
return nil
6071
}

Sources/App/Core/PackageCollection+VersionResult.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ extension PackageCollection.VersionResult {
5555
switch filter {
5656
case let .author(owner):
5757
query.filter(Repository.self, \Repository.$owner, .custom("ilike"), owner)
58+
case let .keyword(keyword):
59+
query.filter(Repository.self, \Repository.$keywords, .custom("@>"), [keyword])
5860
case let .customCollection(key):
5961
query
6062
.join(CustomCollectionPackage.self, on: \Package.$id == \CustomCollectionPackage.$package.$id)

Sources/App/Core/PackageCollection+generate.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extension PackageCollection {
3434
enum Filter {
3535
case urls([String])
3636
case author(String)
37+
case keyword(String)
3738
case customCollection(String)
3839
}
3940

@@ -98,6 +99,10 @@ extension PackageCollection {
9899
return owner
99100
case (.author, .some(let label)):
100101
return label
102+
case (.keyword(let keyword), .none):
103+
return keyword
104+
case (.keyword, .some(let label)):
105+
return label
101106
case (.customCollection(let name), .none):
102107
return name
103108
case (.customCollection, .some(let label)):

Sources/App/Core/PackageCollection+signing.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ extension SignedCollection {
3232
keywords: [String]? = nil,
3333
overview: String? = nil,
3434
revision: Int? = nil) async throws -> SignedCollection {
35-
let collection = try await PackageCollection.generate(db: db,
36-
filterBy: filter,
37-
authorName: authorName,
38-
collectionName: collectionName,
39-
keywords: keywords,
40-
overview: overview,
41-
revision: revision)
35+
let collection = try await PackageCollection.generate(db: db,
36+
filterBy: filter,
37+
authorName: authorName,
38+
collectionName: collectionName,
39+
keywords: keywords,
40+
overview: overview,
41+
revision: revision)
4242
return try await sign(collection: collection)
4343
}
4444

Sources/App/Core/SiteURL.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ enum SiteURL: Resourceable, Sendable {
122122
case javascripts(String)
123123
case keywords(_ keyword: Parameter<String>)
124124
case package(_ owner: Parameter<String>, _ repository: Parameter<String>, PackagePathComponents?)
125+
case packageCollectionKeyword(_ keyword: Parameter<String>)
125126
case packageCollectionAuthor(_ owner: Parameter<String>)
126127
case packageCollectionCustom(_ key: Parameter<String>)
127128
case packageCollections
@@ -211,6 +212,12 @@ enum SiteURL: Resourceable, Sendable {
211212
case .package:
212213
fatalError("invalid path: \(self)")
213214

215+
case let .packageCollectionKeyword(.value(keyword)):
216+
return "keywords/\(keyword)/collection.json"
217+
218+
case .packageCollectionKeyword(.key):
219+
fatalError("invalid path: \(self)")
220+
214221
case let .packageCollectionAuthor(.value(owner)):
215222
return "\(owner)/collection.json"
216223

@@ -324,6 +331,12 @@ enum SiteURL: Resourceable, Sendable {
324331
case .package:
325332
fatalError("pathComponents must not be called with a value parameter")
326333

334+
case .packageCollectionKeyword(.key):
335+
return ["keywords", ":keyword", "collection.json"]
336+
337+
case .packageCollectionKeyword(.value):
338+
fatalError("pathComponents must not be called with a value parameter")
339+
327340
case .packageCollectionAuthor(.key):
328341
return [":owner", "collection.json"]
329342

Sources/App/Views/Keyword/KeywordShow+View.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@ enum KeywordShow {
4848
.class("trimmed"),
4949
.text("Packages for keyword “\(model.keyword)")
5050
),
51+
.p(
52+
.text("These packages are available as a package collection, "),
53+
.a(
54+
.href(SiteURL.packageCollections.relativeURL()),
55+
"usable in Xcode or SwiftPM"
56+
),
57+
.text(".")
58+
),
59+
.copyableInputForm(buttonName: "Copy Package Collection URL",
60+
eventName: "Copy Package Collection URL Button",
61+
valueToCopy: SiteURL.packageCollectionKeyword(.value(model.keyword)).absoluteURL()),
62+
.hr(.class("minor")),
5163
.ul(
5264
.id("package-list"),
5365
.group(

Sources/App/routes.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ func routes(_ app: Application) throws {
9292
use: PackageCollectionController.generate).excludeFromOpenAPI()
9393
app.get(SiteURL.packageCollectionCustom(.key).pathComponents,
9494
use: PackageCollectionController.generate).excludeFromOpenAPI()
95+
app.get(SiteURL.packageCollectionKeyword(.key).pathComponents,
96+
use: PackageCollectionController.generate).excludeFromOpenAPI()
9597
}
9698

9799
do { // author page

Tests/AppTests/__Snapshots__/WebpageSnapshotTests/test_KeywordShow.1.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ <h1>
8383
<main>
8484
<div class="inner">
8585
<h2 class="trimmed">Packages for keyword “networking”</h2>
86+
<p>These packages are available as a package collection,
87+
<a href="/package-collections">usable in Xcode or SwiftPM</a>.
88+
</p>
89+
<form class="copyable-input">
90+
<input type="text" data-button-name="Copy Package Collection URL" data-event-name="Copy Package Collection URL Button" value="http://localhost:8080/keywords/networking/collection.json" readonly/>
91+
</form>
92+
<hr class="minor"/>
8693
<ul id="package-list">
8794
<li>
8895
<a href="https://example.com/owner/name.git">

0 commit comments

Comments
 (0)