gitbay/Repos/WebhookViewModels.swift
105 lines · 3263 bytes
1import Foundation
2import Observation
3
4/// `webhook list`, `webhook add` and `webhook remove` for one repository.
5@Observable
6@MainActor
7final class WebhookListViewModel {
8
9 private(set) var state: LoadState<[Webhook]> = .loading
10 private(set) var actionError: String?
11 private(set) var working = false
12
13 private let client: GitbayClient
14 let repoPath: String
15
16 init(client: GitbayClient, repoPath: String) {
17 self.client = client
18 self.repoPath = repoPath
19 }
20
21 func load() async {
22 state = .loading
23 do {
24 let hooks = try await client.readList(["webhook", "list", repoPath], of: Webhook.self)
25 state = hooks.isEmpty ? .empty("No webhooks yet.") : .loaded(hooks)
26 } catch {
27 state = .from(error)
28 }
29 }
30
31 /// `webhook add <repo> <url> [--secret <s>] [--events <e>]` — an empty
32 /// secret or event list is left out, so the server applies its default.
33 func add(url: String, secret: String, events: String) async -> Bool {
34 let url = url.trimmingCharacters(in: .whitespaces)
35 guard !url.isEmpty else { return false }
36 var argv = ["webhook", "add", repoPath, url]
37 let secret = secret.trimmingCharacters(in: .whitespaces)
38 if !secret.isEmpty { argv += ["--secret", secret] }
39 let events = events.trimmingCharacters(in: .whitespaces)
40 if !events.isEmpty { argv += ["--events", events] }
41 await perform(argv)
42 return actionError == nil
43 }
44
45 func remove(id: Int64) async {
46 await perform(["webhook", "remove", repoPath, String(id)])
47 }
48
49 private func perform(_ argv: [String]) async {
50 working = true
51 actionError = nil
52 defer { working = false }
53 do {
54 try await client.run(argv)
55 await load()
56 } catch let error as GitbayError {
57 actionError = error.userFacingMessage
58 } catch {
59 actionError = GitbayError.transport(error).userFacingMessage
60 }
61 }
62}
63
64/// `webhook deliveries` and `webhook redeliver`.
65@Observable
66@MainActor
67final class WebhookDeliveriesViewModel {
68
69 private(set) var state: LoadState<[WebhookDelivery]> = .loading
70 private(set) var actionError: String?
71 private(set) var working = false
72
73 private let client: GitbayClient
74 let repoPath: String
75
76 init(client: GitbayClient, repoPath: String) {
77 self.client = client
78 self.repoPath = repoPath
79 }
80
81 func load() async {
82 state = .loading
83 do {
84 let rows = try await client.readList(
85 ["webhook", "deliveries", repoPath], of: WebhookDelivery.self)
86 state = rows.isEmpty ? .empty("No deliveries yet.") : .loaded(rows)
87 } catch {
88 state = .from(error)
89 }
90 }
91
92 func redeliver(id: Int64) async {
93 working = true
94 actionError = nil
95 defer { working = false }
96 do {
97 try await client.run(["webhook", "redeliver", repoPath, String(id)])
98 await load()
99 } catch let error as GitbayError {
100 actionError = error.userFacingMessage
101 } catch {
102 actionError = GitbayError.transport(error).userFacingMessage
103 }
104 }
105}