Skip to main content

max / balanced_breakfast

11.8 KB · 289 lines History Blame Raw
1 /**
2 * @fileoverview Tauri IPC bridge.
3 *
4 * Thin wrappers around `window.__TAURI__.core.invoke()` that map each Tauri
5 * command to a named JS function. Organized by domain: sources, items, plugins,
6 * feeds, and OPML import/export.
7 */
8 (function() {
9 'use strict';
10
11 const invoke = window.__TAURI__.core.invoke;
12
13 BB.api = {
14 // --- Sources: feed sources aggregated by busser_id ---
15 sources: {
16 /**
17 * List all sources with item/unread counts.
18 * @returns {Promise<Array<Object>>} Source objects with id, name, totalCount, unreadCount, health, tags.
19 */
20 list: () => invoke('list_sources'),
21 },
22
23 // --- Items: individual feed entries ---
24 items: {
25 /**
26 * Fetch a paginated, filtered list of items.
27 * @param {Object} [filter] - Filter criteria (source, unread, starred, search, order, page, tag).
28 * @returns {Promise<{items: Array<Object>, hasMore: boolean}>}
29 */
30 list: (filter) => invoke('list_items', { filter: filter || {} }),
31 /**
32 * Get a single item by external_id.
33 * @param {string} id - Item external_id.
34 * @returns {Promise<Object>}
35 */
36 get: (id) => invoke('get_item', { id }),
37 /**
38 * Mark an item as read.
39 * @param {string} id - Item external_id.
40 * @returns {Promise<void>}
41 */
42 markRead: (id) => invoke('mark_item_read', { id }),
43 /**
44 * Mark an item as unread.
45 * @param {string} id - Item external_id.
46 * @returns {Promise<void>}
47 */
48 markUnread: (id) => invoke('mark_item_unread', { id }),
49 /**
50 * Star an item.
51 * @param {string} id - Item external_id.
52 * @returns {Promise<void>}
53 */
54 star: (id) => invoke('star_item', { id }),
55 /**
56 * Unstar an item.
57 * @param {string} id - Item external_id.
58 * @returns {Promise<void>}
59 */
60 unstar: (id) => invoke('unstar_item', { id }),
61 /**
62 * Get the global unread count.
63 * @returns {Promise<number>}
64 */
65 unreadCount: () => invoke('get_unread_count'),
66 /**
67 * Mark all unread items as read, optionally for a specific source.
68 * @param {string|null} [sourceId] - Source busser_id, or null for all.
69 * @returns {Promise<number>} Count of items marked read.
70 */
71 markAllRead: (sourceId) => invoke('mark_all_read', { sourceId: sourceId || null }),
72 },
73
74 // --- Plugins: Rhai busser plugins ---
75 plugins: {
76 /**
77 * List all loaded plugins (id, name).
78 * @returns {Promise<Array<{id: string, name: string, description?: string}>>}
79 */
80 list: () => invoke('list_plugins'),
81 /**
82 * Get a plugin's configuration schema (fields for the add-feed form).
83 * @param {string} id - Plugin identifier.
84 * @returns {Promise<{name: string, fields: Array<Object>}>}
85 */
86 schema: (id) => invoke('get_plugin_schema', { id }),
87 },
88
89 // --- Feeds: CRUD for subscribed feeds ---
90 feeds: {
91 /**
92 * Get all feeds for a busser (includes config for undo snapshots).
93 * @param {string} busserId - Busser/plugin identifier.
94 * @returns {Promise<Array<Object>>}
95 */
96 getByBusser: (busserId) => invoke('get_feeds_by_busser', { busserId }),
97 /**
98 * Get the first feed for a busser (with decrypted config for editing).
99 * @param {string} busserId - Busser/plugin identifier.
100 * @returns {Promise<Object>}
101 */
102 get: (busserId) => invoke('get_feed', { busserId }),
103 /**
104 * Create a new feed subscription.
105 * @param {Object} input - Feed creation input with busserId, name, config.
106 * @returns {Promise<Object>}
107 */
108 create: (input) => invoke('create_feed', { input }),
109 /**
110 * Update an existing feed's name and config.
111 * @param {string} id - Busser ID.
112 * @param {string} name - New feed name.
113 * @param {Object} config - Updated plugin config values.
114 * @returns {Promise<void>}
115 */
116 update: (id, name, config) => invoke('update_feed', { id, name, config }),
117 /**
118 * Delete a single feed by UUID.
119 * @param {string} id - Feed UUID.
120 * @returns {Promise<void>}
121 */
122 delete: (id) => invoke('delete_feed', { id }),
123 /**
124 * Delete all feeds for a busser (source deletion).
125 * @param {string} busserId - Busser/plugin identifier.
126 * @returns {Promise<void>}
127 */
128 deleteByBusser: (busserId) => invoke('delete_feeds_by_busser', { busserId }),
129 /**
130 * Trigger a fetch across all enabled feeds.
131 * @returns {Promise<{itemsFetched: number, errors: Array<Object>}>}
132 */
133 fetchAll: () => invoke('fetch_all'),
134 /**
135 * Set tags on all feeds for a busser.
136 * @param {string} busserId - Busser/plugin identifier.
137 * @param {Array<string>} tags - Tag names.
138 * @returns {Promise<void>}
139 */
140 setTags: (busserId, tags) => invoke('set_feed_tags', { busserId, tags }),
141 /**
142 * List all distinct tags across all feeds.
143 * @returns {Promise<Array<string>>}
144 */
145 listAllTags: () => invoke('list_all_tags'),
146 /**
147 * Reset circuit breaker and retry fetch.
148 * @param {string} busserId - Busser/plugin identifier.
149 * @returns {Promise<void>}
150 */
151 resetCircuitBreaker: (busserId) => invoke('reset_circuit_breaker', { busserId }),
152 },
153
154 // --- OPML: import/export feed subscriptions ---
155 opml: {
156 /**
157 * Export all feeds as OPML XML.
158 * @returns {Promise<string>} OPML XML string.
159 */
160 export: () => invoke('export_opml'),
161 /**
162 * Import feeds from OPML XML string.
163 * @param {string} content - OPML XML content.
164 * @returns {Promise<{imported: number, skipped: number, errors: Array<Object>}>}
165 */
166 import: (content) => invoke('import_opml', { content }),
167 },
168
169 // --- Query Feeds: saved filter rules ---
170 queryFeeds: {
171 /**
172 * List all query feeds with match counts.
173 * @returns {Promise<Array<{id: string, name: string, rules: Array<Object>, matchCount: number}>>}
174 */
175 list: () => invoke('list_query_feeds'),
176 /**
177 * Create a new query feed.
178 * @param {Object} input - Query feed input with name and rules.
179 * @returns {Promise<Object>}
180 */
181 create: (input) => invoke('create_query_feed', { input }),
182 /**
183 * Update a query feed.
184 * @param {string} id - Query feed ID.
185 * @param {string} name - New name.
186 * @param {Array<Object>} rules - Updated condition rules.
187 * @returns {Promise<void>}
188 */
189 update: (id, name, rules) => invoke('update_query_feed', { id, name, rules }),
190 /**
191 * Delete a query feed.
192 * @param {string} id - Query feed ID.
193 * @returns {Promise<void>}
194 */
195 delete: (id) => invoke('delete_query_feed', { id }),
196 },
197
198 // --- Bookmarks: reading list ---
199 bookmarks: {
200 list: (tag) => invoke('list_bookmarks', { tag: tag || null }),
201 create: (input) => invoke('create_bookmark', { input }),
202 createFromItem: (itemId, tags) => invoke('create_bookmark_from_item', { itemId, tags: tags || null }),
203 update: (id, input) => invoke('update_bookmark', { id, input }),
204 delete: (id) => invoke('delete_bookmark', { id }),
205 setTags: (id, tags) => invoke('set_bookmark_tags', { id, tags }),
206 listTags: () => invoke('list_bookmark_tags'),
207 isBookmarked: (url) => invoke('is_bookmarked', { url }),
208 count: () => invoke('get_bookmark_count'),
209 exportHtml: (id) => invoke('export_bookmark_html', { id }),
210 },
211
212 // --- Reader: extract article content ---
213 reader: {
214 /**
215 * Extract readable article content from a URL.
216 * @param {string} url - Article URL.
217 * @returns {Promise<{content: string, title?: string}>}
218 */
219 extract: (url) => invoke('extract_reader_view', { url }),
220 },
221
222 // --- Actions: plugin-declared custom actions ---
223 actions: {
224 /**
225 * Download a file to temp dir and open with system default app.
226 * @param {string} url - File URL to download.
227 * @returns {Promise<void>}
228 */
229 downloadAndOpen: (url) => invoke('download_and_open', { url }),
230 },
231
232 // --- Sync: cloud sync via MNW SyncKit ---
233 sync: {
234 /**
235 * Validate an API key against the server.
236 * @param {string} apiKey - API key to validate.
237 * @returns {Promise<string>} App name on success.
238 */
239 /**
240 * Get current sync status.
241 * @returns {Promise<Object>} Status with configured, authenticated, encryptionReady, etc.
242 */
243 getTiers: () => invoke('sync_get_tiers'),
244 status: () => invoke('sync_status'),
245 /**
246 * Start OAuth2 PKCE auth flow.
247 * @returns {Promise<{authUrl: string, state: string, codeVerifier: string, port: number}>}
248 */
249 startAuth: () => invoke('sync_start_auth'),
250 /**
251 * Complete auth with authorization code.
252 * @param {Object} input - Auth completion input with code, state, expectedState, codeVerifier, port.
253 * @returns {Promise<void>}
254 */
255 completeAuth: (input) => invoke('sync_complete_auth', { input }),
256 /**
257 * Disconnect from sync service.
258 * @returns {Promise<void>}
259 */
260 disconnect: () => invoke('sync_disconnect'),
261 /**
262 * Trigger manual sync.
263 * @returns {Promise<{pushed: number, pulled: number}>}
264 */
265 now: () => invoke('sync_now'),
266 /**
267 * Set up encryption (first device).
268 * @param {string} password - Encryption password.
269 * @returns {Promise<void>}
270 */
271 setupEncryptionNew: (password) => invoke('sync_setup_encryption_new', { password }),
272 /**
273 * Set up encryption (joining existing device).
274 * @param {string} password - Encryption password.
275 * @returns {Promise<void>}
276 */
277 setupEncryptionExisting: (password) => invoke('sync_setup_encryption_existing', { password }),
278 /**
279 * Update auto-sync settings.
280 * @param {Object} input - Settings with autoSyncEnabled, syncIntervalMinutes.
281 * @returns {Promise<void>}
282 */
283 updateSettings: (input) => invoke('sync_update_settings', { input }),
284 subscriptionStatus: () => invoke('sync_subscription_status'),
285 subscribe: (interval) => invoke('sync_subscribe', { interval }),
286 },
287 };
288 })();
289