mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-08 19:19:42 +00:00
Machine cli mtimes and file/directory modified are Double on the wire (fs.stat mtimeMs carries sub-ms precision); integer decode threw on real hub data. Mirrors the Android LenientEpochMs fix; 461 package tests green in the Linux harness.
117 lines
3.6 KiB
Swift
117 lines
3.6 KiB
Swift
import Foundation
|
|
|
|
// Wire types of the git & files surface (A-M4a):
|
|
// `docs/api/client-contract/rest.md` "Git & files"; shapes from
|
|
// `shared/src/apiTypes.ts` (`CommandResponse`, `FileReadResponse`,
|
|
// `FileSearchResponse`, `ListDirectoryResponse`), field-for-field in lockstep
|
|
// with the Android port (`app.hapi.protocol.wire.FilesApi`). All are
|
|
// RPC-wrapped — HTTP 200 with `success: false` is a normal failure, callers
|
|
// must check. The session `DirectoryEntry` row already lives in
|
|
// `ApiResponses.swift` (shared with the machine list-directory RPC family).
|
|
|
|
/// `GET /api/sessions/:id/git-status|git-diff-numstat|git-diff-file` —
|
|
/// `CommandResponse`: the hub relays raw git stdout verbatim; clients parse
|
|
/// it themselves (`HapiProtocol/Git/` twins `web/src/lib/gitParsers.ts`).
|
|
public struct GitCommandResponse: Codable, Equatable, Sendable {
|
|
public var success: Bool
|
|
public var stdout: String?
|
|
public var stderr: String?
|
|
public var exitCode: Int?
|
|
public var error: String?
|
|
|
|
public init(
|
|
success: Bool,
|
|
stdout: String? = nil,
|
|
stderr: String? = nil,
|
|
exitCode: Int? = nil,
|
|
error: String? = nil
|
|
) {
|
|
self.success = success
|
|
self.stdout = stdout
|
|
self.stderr = stderr
|
|
self.exitCode = exitCode
|
|
self.error = error
|
|
}
|
|
}
|
|
|
|
/// `GET /api/sessions/:id/file?path=` — `content` is **base64** (decode
|
|
/// before display).
|
|
public struct FileReadResponse: Codable, Equatable, Sendable {
|
|
public var success: Bool
|
|
public var content: String?
|
|
/// Bytes on disk.
|
|
public var size: Int?
|
|
/// Epoch ms.
|
|
public var modified: Double?
|
|
public var error: String?
|
|
|
|
public init(
|
|
success: Bool,
|
|
content: String? = nil,
|
|
size: Int? = nil,
|
|
modified: Double? = nil,
|
|
error: String? = nil
|
|
) {
|
|
self.success = success
|
|
self.content = content
|
|
self.size = size
|
|
self.modified = modified
|
|
self.error = error
|
|
}
|
|
}
|
|
|
|
/// `GET /api/sessions/:id/files?query=&limit=` (ripgrep-backed search).
|
|
public struct FileSearchResponse: Codable, Equatable, Sendable {
|
|
public var success: Bool
|
|
public var files: [FileSearchItem]?
|
|
public var error: String?
|
|
|
|
public init(success: Bool, files: [FileSearchItem]? = nil, error: String? = nil) {
|
|
self.success = success
|
|
self.files = files
|
|
self.error = error
|
|
}
|
|
}
|
|
|
|
public struct FileSearchItem: Codable, Equatable, Sendable {
|
|
public var fileName: String
|
|
/// Directory part; empty at the session root.
|
|
public var filePath: String
|
|
public var fullPath: String
|
|
/// `'file' | 'folder'` (search results are files in practice).
|
|
public var fileType: String
|
|
public var size: Int?
|
|
/// Epoch ms.
|
|
public var modified: Double?
|
|
|
|
public init(
|
|
fileName: String,
|
|
filePath: String,
|
|
fullPath: String,
|
|
fileType: String,
|
|
size: Int? = nil,
|
|
modified: Double? = nil
|
|
) {
|
|
self.fileName = fileName
|
|
self.filePath = filePath
|
|
self.fullPath = fullPath
|
|
self.fileType = fileType
|
|
self.size = size
|
|
self.modified = modified
|
|
}
|
|
}
|
|
|
|
/// `GET /api/sessions/:id/directory?path=` — empty path = session root.
|
|
/// Entries are the shared session `DirectoryEntry` rows (`ApiResponses.swift`).
|
|
public struct ListDirectoryResponse: Codable, Equatable, Sendable {
|
|
public var success: Bool
|
|
public var entries: [DirectoryEntry]?
|
|
public var error: String?
|
|
|
|
public init(success: Bool, entries: [DirectoryEntry]? = nil, error: String? = nil) {
|
|
self.success = success
|
|
self.entries = entries
|
|
self.error = error
|
|
}
|
|
}
|