The Appview for the kipclip.com atproto bookmarking service
at main 263 lines 6.1 kB view raw
1// Shared TypeScript types for kipclip 2 3// AT Protocol bookmark record type 4export interface BookmarkRecord { 5 subject: string; // URI of the bookmarked content 6 createdAt: string; // ISO 8601 datetime 7 tags?: string[]; // Optional tags 8} 9 10// Enriched bookmark with metadata 11export interface EnrichedBookmark extends BookmarkRecord { 12 uri: string; // AT Protocol URI for this record 13 cid: string; // Content ID 14 title?: string; // Extracted page title 15 description?: string; // Extracted meta description 16 favicon?: string; // Extracted favicon URL 17 image?: string; // Preview image (og:image) 18 note?: string; // User note from annotation sidecar 19} 20 21// Kipclip annotation sidecar record (com.kipclip.annotation) 22export interface AnnotationRecord { 23 subject: string; // AT URI of the bookmark this annotates 24 note?: string; // User note 25 title?: string; 26 description?: string; 27 favicon?: string; 28 image?: string; 29 createdAt: string; 30} 31 32// API request/response types 33export interface AddBookmarkRequest { 34 url: string; 35 tags?: string[]; 36} 37 38export interface AddBookmarkResponse { 39 success: boolean; 40 bookmark?: EnrichedBookmark; 41 error?: string; 42} 43 44export interface ListBookmarksResponse { 45 bookmarks: EnrichedBookmark[]; 46} 47 48// URL metadata extraction result 49export interface UrlMetadata { 50 title?: string; 51 description?: string; 52 favicon?: string; 53 image?: string; // Preview image (og:image) 54} 55 56// Session info 57export interface SessionInfo { 58 did: string; 59 handle: string; 60} 61 62// AT Protocol tag record type 63export interface TagRecord { 64 value: string; // Tag text (max 64 chars) 65 createdAt: string; // ISO 8601 datetime 66} 67 68// Enriched tag with metadata 69export interface EnrichedTag extends TagRecord { 70 uri: string; // AT Protocol URI for this record 71 cid: string; // Content ID 72} 73 74// Tag API request/response types 75export interface AddTagRequest { 76 value: string; 77} 78 79export interface AddTagResponse { 80 success: boolean; 81 tag?: EnrichedTag; 82 error?: string; 83} 84 85export interface ListTagsResponse { 86 tags: EnrichedTag[]; 87} 88 89export interface UpdateTagRequest { 90 value: string; 91} 92 93export interface UpdateTagResponse { 94 success: boolean; 95 tag?: EnrichedTag; 96 error?: string; 97} 98 99export interface DeleteTagResponse { 100 success: boolean; 101 error?: string; 102} 103 104// Bookmark tag update request/response types 105export interface UpdateBookmarkTagsRequest { 106 tags: string[]; 107 title?: string; 108 url?: string; 109 description?: string; 110 note?: string; 111} 112 113export interface UpdateBookmarkTagsResponse { 114 success: boolean; 115 bookmark?: EnrichedBookmark; 116 error?: string; 117} 118 119// Shared bookmarks API types (public, no auth) 120export interface SharedBookmarksResponse { 121 bookmarks: EnrichedBookmark[]; 122 handle: string; 123 tags: string[]; 124 error?: string; 125} 126 127// User settings (stored in database) 128export interface UserSettings { 129 instapaperEnabled: boolean; 130 instapaperUsername?: string; // Decrypted, only in memory (never includes password) 131} 132 133// Settings API response 134export interface GetSettingsResponse { 135 settings: UserSettings; 136} 137 138// Settings API update request 139export interface UpdateSettingsRequest { 140 instapaperEnabled?: boolean; 141 instapaperUsername?: string; 142 instapaperPassword?: string; // Only when updating credentials 143} 144 145// Settings API update response 146export interface UpdateSettingsResponse { 147 success: boolean; 148 settings?: UserSettings; 149 error?: string; 150} 151 152// Duplicate check API types 153export interface CheckDuplicatesRequest { 154 url: string; 155} 156 157export interface CheckDuplicatesResponse { 158 duplicates: EnrichedBookmark[]; 159} 160 161// User preferences (stored on PDS as com.kipclip.preferences) 162export interface PreferencesRecord { 163 dateFormat: string; 164 readingListTag?: string; 165 createdAt: string; 166} 167 168export interface UserPreferences { 169 dateFormat: string; 170 readingListTag: string; 171} 172 173export interface UpdatePreferencesRequest { 174 dateFormat?: string; 175 readingListTag?: string; 176} 177 178export interface UpdatePreferencesResponse { 179 success: boolean; 180 preferences?: UserPreferences; 181 error?: string; 182} 183 184// Combined initial data response (for optimized page load) 185export interface InitialDataResponse { 186 bookmarks: EnrichedBookmark[]; 187 tags: EnrichedTag[]; 188 settings: UserSettings; 189 preferences: UserPreferences; 190 /** Cursor for next page of bookmarks (absent when all loaded) */ 191 bookmarkCursor?: string; 192 /** Cursor for next page of annotations (absent when all loaded) */ 193 annotationCursor?: string; 194} 195 196// Import types 197export interface ImportedBookmark { 198 url: string; 199 title?: string; 200 description?: string; 201 tags: string[]; 202 createdAt?: string; // ISO 8601, falls back to now 203} 204 205export interface ImportResult { 206 imported: number; 207 skipped: number; 208 failed: number; 209 total: number; 210 format: string; 211} 212 213// Bulk operations API types 214export interface BulkOperationRequest { 215 action: "delete" | "add-tags" | "remove-tags"; 216 uris: string[]; // bookmark URIs to operate on 217 tags?: string[]; // tags to add/remove (required for tag actions) 218} 219 220export interface BulkOperationResponse { 221 success: boolean; 222 succeeded: number; 223 failed: number; 224 errors?: string[]; 225 deletedUris?: string[]; // URIs that were actually deleted (for delete action) 226 bookmarks?: EnrichedBookmark[]; // updated bookmarks (for tag operations) 227} 228 229// Tag merge/deduplication response 230export interface MergeTagDuplicatesResponse { 231 merged: number; 232 tagsDeleted: number; 233 bookmarksUpdated: number; 234 details: { 235 canonical: string; 236 merged: string[]; 237 bookmarksUpdated: number; 238 }[]; 239} 240 241export interface ImportPrepareResponse { 242 success: boolean; 243 jobId?: string; 244 total?: number; 245 skipped?: number; 246 toImport?: number; 247 totalChunks?: number; 248 format?: string; 249 result?: ImportResult; // only when toImport === 0 250 error?: string; 251} 252 253export interface ImportProcessResponse { 254 success: boolean; 255 imported?: number; // this chunk 256 failed?: number; // this chunk 257 totalImported?: number; // cumulative 258 totalFailed?: number; // cumulative 259 remaining?: number; // chunks left 260 done?: boolean; 261 result?: ImportResult; // only when done 262 error?: string; 263}