Skip to content

Commit 02e2f94

Browse files
committed
wire up the telescope implementation to the admin control panel
1 parent 57dd38d commit 02e2f94

File tree

9 files changed

+81
-15
lines changed

9 files changed

+81
-15
lines changed

Sources/GitHubAPI/GraphQL.Response.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,10 @@ extension GraphQL
44
{
55
/// A GraphQL response wrapper, which contains a single field named ``data``.
66
@frozen public
7-
struct Response<Data> where Data:JSONDecodable
7+
enum Response<Data> where Data:JSONDecodable
88
{
9-
public
10-
var data:Data
11-
12-
@inlinable internal
13-
init(data:Data)
14-
{
15-
self.data = data
16-
}
9+
case success(Data)
10+
case failure(ServerError)
1711
}
1812
}
1913
extension GraphQL.Response:JSONObjectDecodable
@@ -22,11 +16,19 @@ extension GraphQL.Response:JSONObjectDecodable
2216
enum CodingKey:String, Sendable
2317
{
2418
case data
19+
case errors
2520
}
2621

2722
@inlinable public
2823
init(json:JSON.ObjectDecoder<CodingKey>) throws
2924
{
30-
self.init(data: try json[.data].decode())
25+
if let data:Data = try json[.data]?.decode()
26+
{
27+
self = .success(data)
28+
}
29+
else
30+
{
31+
self = .failure(.init(json: try json[.errors].decode()))
32+
}
3133
}
3234
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import JSON
2+
3+
extension GraphQL
4+
{
5+
@frozen public
6+
struct ServerError:Error
7+
{
8+
@usableFromInline
9+
let json:JSON.Array
10+
11+
@inlinable internal
12+
init(json:JSON.Array)
13+
{
14+
self.json = json
15+
}
16+
}
17+
}

Sources/GitHubClient/GitHubClient.Connection.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ extension GitHubClient<GitHub.API>.Connection
6262
json.utf8 += buffer.readableBytesView
6363
}
6464

65-
let wrapper:GraphQL.Response<Response> = try json.decode()
66-
return wrapper.data
65+
switch try json.decode(GraphQL.Response<Response>.self)
66+
{
67+
case .success(let data): return data
68+
case .failure(let error): throw error
69+
}
6770

6871
case 403?:
6972
if let second:String = response.headers?["x-ratelimit-reset"].first,

Sources/Swiftinit/Tree/Swiftinit.API.Post.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ extension Swiftinit.API
88
case packageIndex = "package-index"
99
case packageIndexTag = "package-index-tag"
1010

11+
case telescope = "telescope"
12+
1113
case uplinkAll = "uplink-all"
1214
case uplink
1315
case unlink

Sources/SwiftinitPages/Surfaces/Administration/Swiftinit.AdminPage.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,30 @@ extension Swiftinit.AdminPage:Swiftinit.AdministrativePage
196196
}
197197
}
198198

199+
main[.form]
200+
{
201+
$0.enctype = "\(MediaType.application(.x_www_form_urlencoded))"
202+
$0.action = "\(Swiftinit.API[.telescope])"
203+
$0.method = "post"
204+
}
205+
content:
206+
{
207+
$0[.p]
208+
{
209+
$0[.input]
210+
{
211+
$0.type = "number"
212+
$0.name = "days"
213+
$0.placeholder = "days"
214+
}
215+
}
216+
217+
$0[.p]
218+
{
219+
$0[.button] { $0.type = "submit" } = "Activate Package Telescope"
220+
}
221+
}
222+
199223
// Destructive actions.
200224
for action:Action in
201225
[

Sources/SwiftinitServer/Endpoints/Interactive/Swiftinit.AdminEndpoint.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extension Swiftinit
1313
{
1414
case perform(Swiftinit.AdminPage.Action, MultipartForm?)
1515
case recode(Swiftinit.AdminPage.Recode.Target)
16+
case telescope(days:Int)
1617
}
1718
}
1819
extension Swiftinit.AdminEndpoint:RestrictedEndpoint
@@ -69,6 +70,12 @@ extension Swiftinit.AdminEndpoint:RestrictedEndpoint
6970

7071
case .perform(.upload, nil):
7172
return nil
73+
74+
case .telescope(days: let days):
75+
let updates:Mongo.Updates = try await server.db.crawlingWindows.create(days: days,
76+
with: session)
77+
78+
return .ok("Updated \(updates.modified) of \(updates.selected) crawling windows.")
7279
}
7380

7481
return .ok(page.resource(format: server.format))

Sources/SwiftinitServer/Plugins/GitHub.RepoNode.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ extension GitHub.RepoNode:JSONObjectDecodable
135135
archived: try json[.archived].decode(),
136136
disabled: try json[.disabled].decode(),
137137
fork: try json[.fork].decode(),
138-
homepage: try json[.homepage]?.decode(as: String.self) { $0.isEmpty ? nil : $0 },
138+
// Yes, `String?`, the GitHub API does occasionally return explicit null.
139+
homepage: try json[.homepage]?.decode(as: String?.self)
140+
{
141+
$0.map { $0.isEmpty ? nil : $0 } ?? nil
142+
},
139143
about: try json[.about]?.decode(to: String?.self),
140144
created: try json[.created].decode(),
141145
updated: try json[.updated].decode(),

Sources/SwiftinitServer/Plugins/GitHubClient.Connection (ext).swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ extension GitHubClient<GitHub.API>.Connection
8080
}
8181

8282
func search(repos search:String,
83-
limit:Int = 1000,
83+
limit:Int = 100,
8484
pat:String) async throws -> GitHubPlugin.RepoTelescopeResponse
8585
{
8686
let query:JSON = .object
8787
{
8888
$0["query"] = """
8989
query
9090
{
91-
search(query: \(search), type: REPOSITORY, first: \(limit))
91+
search(query: "\(search)", type: REPOSITORY, first: \(limit))
9292
{
9393
nodes
9494
{

Sources/SwiftinitServer/Swiftinit.AnyEndpoint.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,13 @@ extension Swiftinit.AnyEndpoint
348348
tag: tag))
349349
}
350350

351+
case .telescope:
352+
if let days:String = form["days"],
353+
let days:Int = .init(days)
354+
{
355+
return .interactive(Swiftinit.AdminEndpoint.telescope(days: days))
356+
}
357+
351358
case .uplinkAll:
352359
return .procedural(Swiftinit.GlobalUplinkEndpoint.init(
353360
queue: form["queue"] == "true"))

0 commit comments

Comments
 (0)