gitbay/Issues/IssueCreateViewModel.swift
47 lines · 1412 bytes
1import Foundation
2import Observation
3
4/// `issue create <repo> --title <t> --file -`.
5@Observable
6@MainActor
7final class IssueCreateViewModel {
8
9 private(set) var working = false
10 private(set) var errorMessage: String?
11 var format: String?
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 nonisolated private struct Created: Decodable, Sendable {
22 let number: Int64
23 }
24
25 /// Returns the new issue's number, or nil with `errorMessage` set.
26 func create(title: String, body: String) async -> Int64? {
27 working = true
28 errorMessage = nil
29 defer { working = false }
30 do {
31 var argv = ["issue", "create", repoPath, "--title", title]
32 var stdin: String?
33 if !body.isEmpty {
34 argv.append(contentsOf: ["--file", "-"])
35 stdin = body
36 }
37 if let format { argv.append(contentsOf: ["--format", format]) }
38 let created = try await client.run(argv, stdin: stdin, as: Created.self)
39 return created?.number
40 } catch let error as GitbayError {
41 errorMessage = error.userFacingMessage
42 } catch {
43 errorMessage = GitbayError.transport(error).userFacingMessage
44 }
45 return nil
46 }
47}