Files
Outpost/OutlineKit/Sources/OutlineKit/Core/OutlineAPIClient.swift
T
Puranjay Savar Mattas 277e5fb4ae feat: add comment marker (list + resolve/unresolve)
Wraps Outline's Comments API in OutlineKit for the first time -
comments.list is documented in the vendored spec; comments.resolve/
unresolve are not, confirmed real against Outline's own server source
instead of guessed. Comment bodies are ProseMirror documents (data),
not plain text - added a small recursive JSONValue tree plus a
best-effort plainText() walk for display, since nothing here needs to
write comment bodies back (out of scope for this pass, see
DocumentCommentsSheet's doc comment).

Reader toolbar gets a marker (bubble icon + count badge) only when
the document actually has comments, per explicit instruction that
this should be a simple symbol rather than a true in-document gutter
marker at each comment's anchor position - anchoring is plain-text-
substring-based server-side and doesn't map cleanly onto this app's
own Markdown rendering. Opens a read-only comment list with a
Resolve/Unresolve toggle per the confirmed scope for this pass; no
creating or replying yet.
2026-08-20 20:52:44 +01:00

123 lines
8.4 KiB
Swift

import Foundation
/// REST-layer boundary. The CRDT/sync layer and editor UI layer depend only on this
/// protocol, never on `LiveOutlineAPIClient`, so the transport can be swapped or mocked
/// without touching callers.
public protocol OutlineAPIClient: Sendable {
/// Validates the current token and identifies the signed-in user/workspace. Backed by `auth.info`.
func authInfo() async throws -> OutlineAuthInfo
func documentInfo(id: String) async throws -> OutlineDocument
func listDocuments(collectionId: String?, parentDocumentId: String?, offset: Int, limit: Int) async throws -> [OutlineDocument]
/// Richer filtering (sort/direction/userId) for the Home page's tabs. See `DocumentsListRequest`.
func documentsList(_ request: DocumentsListRequest) async throws -> [OutlineDocument]
/// Documents the current user has recently viewed. Backed by `documents.viewed`.
func listViewedDocuments(offset: Int, limit: Int) async throws -> [OutlineDocument]
/// Full-text search with snippets/ranking. Backed by `documents.search`.
func searchDocuments(_ request: DocumentSearchRequest) async throws -> [OutlineDocumentSearchResult]
/// Title-only search — faster, no snippets. Backed by `documents.search_titles`.
func searchDocumentTitles(_ request: DocumentSearchTitlesRequest) async throws -> [OutlineDocument]
func createDocument(_ request: CreateDocumentRequest) async throws -> OutlineDocument
func updateDocument(_ request: UpdateDocumentRequest) async throws -> OutlineDocument
func starDocument(_ request: StarDocumentRequest) async throws -> OutlineStar
func templatizeDocument(_ request: TemplatizeDocumentRequest) async throws -> OutlineTemplate
func duplicateDocument(_ request: DuplicateDocumentRequest) async throws -> [OutlineDocument]
func unpublishDocument(_ request: UnpublishDocumentRequest) async throws -> OutlineDocument
func archiveDocument(id: String) async throws -> OutlineDocument
func moveDocument(_ request: MoveDocumentRequest) async throws
func deleteDocument(_ request: DeleteDocumentRequest) async throws
/// Requires insights to be enabled on the document server-side. Backed by `documents.insights`.
func documentInsights(_ request: DocumentInsightsRequest) async throws -> [OutlineDocumentInsight]
/// Backed by `revisions.list` — omits full body content for performance.
func listRevisions(_ request: ListRevisionsRequest) async throws -> [OutlineRevision]
/// Returns the document's markdown source directly (not a file operation job). Backed by `documents.export`.
func exportDocument(id: String) async throws -> String
func createShare(_ request: CreateShareRequest) async throws -> OutlineShare
func shareInfo(documentId: String) async throws -> OutlineShare?
func updateShare(_ request: UpdateShareRequest) async throws -> OutlineShare
func listShares(_ request: ListSharesRequest) async throws -> [OutlineShare]
func revokeShare(id: String) async throws
/// See `OutlinePin` — best-effort, not in the vendored spec.
func createPin(_ request: CreatePinRequest) async throws -> OutlinePin
func listPins(_ request: ListPinsRequest) async throws -> [OutlinePin]
func deletePin(id: String) async throws
/// See `OutlineSubscription` — best-effort, not in the vendored spec.
func createSubscription(_ request: CreateSubscriptionRequest) async throws -> OutlineSubscription
func listSubscriptions(_ request: ListSubscriptionsRequest) async throws -> [OutlineSubscription]
func deleteSubscription(id: String) async throws
/// Historical view records, not live presence. Backed by `views.list`.
func listViews(_ request: ListViewsRequest) async throws -> [OutlineView]
/// See `OutlineComment`. `resolve`/`unresolve` are confirmed real
/// against Outline's own server source but aren't in the vendored spec.
func listComments(_ request: ListCommentsRequest) async throws -> [OutlineComment]
func resolveComment(id: String) async throws -> OutlineComment
func unresolveComment(id: String) async throws -> OutlineComment
/// See `OutlineMembership`/`OutlineDocumentMember` — `add` is confirmed
/// from Outline's official docs, the rest are best-effort.
func addDocumentUser(_ request: AddDocumentUserRequest) async throws -> OutlineMembership
func removeDocumentUser(_ request: RemoveDocumentUserRequest) async throws
func documentUsers(_ request: ListDocumentUsersRequest) async throws -> [OutlineDocumentMember]
/// For searching workspace members to invite. Backed by `users.list`.
func listUsers(_ request: ListUsersRequest) async throws -> [OutlineUser]
func listCollections(offset: Int, limit: Int) async throws -> [OutlineCollection]
func collectionInfo(id: String) async throws -> OutlineCollection
func updateCollection(_ request: UpdateCollectionRequest) async throws -> OutlineCollection
func deleteCollection(id: String) async throws
/// Kicks off an async export job — this only wraps the trigger, not polling
/// for completion or downloading the resulting file.
func exportCollection(_ request: ExportCollectionRequest) async throws -> OutlineFileOperation
func starCollection(_ request: StarCollectionRequest) async throws -> OutlineStar
/// Every star across both documents and collections for the current user. Backed by `stars.list`.
func listStars(_ request: ListStarsRequest) async throws -> [OutlineStar]
func deleteStar(id: String) async throws
func currentUser() async throws -> OutlineUser
/// Two-step presigned upload: this requests where/how to upload,
/// `uploadAttachmentFile` performs the actual multipart POST to that
/// target. See `OutlineAttachment`/`CreateAttachmentResult`.
func createAttachment(_ request: CreateAttachmentRequest) async throws -> CreateAttachmentResult
func uploadAttachmentFile(_ result: CreateAttachmentResult, fileData: Data) async throws
/// Fetches raw bytes from an authenticated, server-relative GET path —
/// e.g. `/api/attachments.redirect?id=<uuid>`, the reference Outline's
/// own editor embeds for uploaded images in document Markdown. Unlike
/// `post`'s RPC endpoints, this is a GET that 302-redirects to the
/// actual (often presigned, cross-host) storage URL; `path` is resolved
/// against the client's base URL, same as `uploadAttachmentFile`'s
/// `uploadUrl` handling.
func fetchAuthenticatedFile(path: String) async throws -> Data
/// Best-effort — matches the shape every other simple `id`-only delete
/// in this API uses (`pins.delete`, `stars.delete`, …), not confirmed
/// against a live server specifically for attachments yet.
func deleteAttachment(id: String) async throws
/// `users.update`, avatar only. See `UpdateUserAvatarRequest`.
func updateUserAvatar(_ request: UpdateUserAvatarRequest) async throws -> OutlineUser
/// `users.update`, name only. See `UpdateUserNameRequest`.
func updateUserName(_ request: UpdateUserNameRequest) async throws -> OutlineUser
/// `users.update`, language only. See `UpdateUserLanguageRequest`.
func updateUserLanguage(_ request: UpdateUserLanguageRequest) async throws -> OutlineUser
/// `users.update`, preferences only. See `UpdateUserPreferencesRequest`.
func updateUserPreferences(_ request: UpdateUserPreferencesRequest) async throws -> OutlineUser
/// Backed by `users.delete` — self-service account deletion, no
/// confirmation code param confirmed live, matches every other simple
/// no-body delete in this API.
func deleteAccount() async throws
/// `nil` targets every notification event. See `NotificationEventType`.
func subscribeToNotifications(eventType: NotificationEventType?) async throws -> OutlineUser
func unsubscribeFromNotifications(eventType: NotificationEventType?) async throws -> OutlineUser
/// Settings → API & Access.
func listApiKeys(_ request: ListApiKeysRequest) async throws -> [OutlineAPIKey]
/// The returned `OutlineAPIKey.value` is the only time the full
/// plaintext key is ever available — the caller is responsible for
/// displaying it once and then discarding it.
func createApiKey(_ request: CreateApiKeyRequest) async throws -> OutlineAPIKey
func deleteApiKey(id: String) async throws
/// Settings → Installation. Self-hosted server version info.
func installationInfo() async throws -> OutlineInstallationInfo
}