diff --git a/apps/desktop/src/main/ipc/generated-ipc-invoke-map.ts b/apps/desktop/src/main/ipc/generated-ipc-invoke-map.ts index 0742fc6bb..8d7a51d6b 100644 --- a/apps/desktop/src/main/ipc/generated-ipc-invoke-map.ts +++ b/apps/desktop/src/main/ipc/generated-ipc-invoke-map.ts @@ -2,328 +2,2519 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ export interface MainIpcInvokeHandlers { - "account:getInfo": (...args: []) => Awaited - "account:getRecoveryKey": (...args: []) => Awaited> - "account:signOut": (...args: []) => Awaited> - "ai-inline:get-server-port": (...args: []) => Awaited - "ai-inline:get-settings": (...args: []) => Awaited - "ai-inline:set-settings": (...args: [Partial]) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; }> - "ai-inline:start-server": (...args: []) => Awaited> - "ai-inline:stop-server": (...args: []) => Awaited> - "auth:init-oauth": (...args: [{ provider: "google"; }]) => Awaited | { success: false; error: string }> - "auth:refresh-token": (...args: []) => Awaited> - "auth:request-otp": (...args: [{ email: string; }]) => Awaited | { success: false; error: string }> - "auth:resend-otp": (...args: [{ email: string; }]) => Awaited | { success: false; error: string }> - "auth:verify-otp": (...args: [{ email: string; code: string; }]) => Awaited | { success: false; error: string }> - "bookmarks:bulk-create": (...args: [{ items: { itemType: string; itemId: string; }[]; }]) => Awaited> - "bookmarks:bulk-delete": (...args: [{ bookmarkIds: string[]; }]) => Awaited> - "bookmarks:create": (...args: [{ itemType: string; itemId: string; }]) => Awaited> - "bookmarks:delete": (...args: [string]) => Awaited> - "bookmarks:get": (...args: [string]) => Awaited> - "bookmarks:get-by-item": (...args: [{ itemType: string; itemId: string; }]) => Awaited> - "bookmarks:is-bookmarked": (...args: [{ itemType: string; itemId: string; }]) => Awaited> - "bookmarks:list": (...args: [{ itemType?: string | undefined; sortBy?: "createdAt" | "position" | undefined; sortOrder?: "asc" | "desc" | undefined; limit?: number | undefined; offset?: number | undefined; }]) => Awaited> - "bookmarks:list-by-type": (...args: [string]) => Awaited> - "bookmarks:reorder": (...args: [{ bookmarkIds: string[]; }]) => Awaited> - "bookmarks:toggle": (...args: [{ itemType: string; itemId: string; }]) => Awaited> - "calendar:connect-provider": (...args: [{ provider: string; }]) => Awaited> - "calendar:create-event": (...args: [{ title: string; startAt: string; description?: string | null | undefined; location?: string | null | undefined; endAt?: string | null | undefined; timezone?: string | undefined; isAllDay?: boolean | undefined; recurrenceRule?: Record | null | undefined; recurrenceExceptions?: Record[] | null | undefined; }]) => Awaited> - "calendar:delete-event": (...args: [string]) => Awaited> - "calendar:disconnect-provider": (...args: [{ provider: string; }]) => Awaited> - "calendar:get-event": (...args: [string]) => Awaited> - "calendar:get-provider-status": (...args: [{ provider: string; }]) => Awaited> - "calendar:get-range": (...args: [{ startAt: string; endAt: string; includeUnselectedSources?: boolean | undefined; }]) => Awaited> - "calendar:list-events": (...args: [{ includeArchived?: boolean | undefined; }]) => Awaited> - "calendar:list-sources": (...args: [{ provider?: string | undefined; kind?: "account" | "calendar" | undefined; selectedOnly?: boolean | undefined; }]) => Awaited> - "calendar:refresh-provider": (...args: [{ provider: string; }]) => Awaited> - "calendar:update-event": (...args: [{ id: string; title?: string | undefined; description?: string | null | undefined; location?: string | null | undefined; startAt?: string | undefined; endAt?: string | null | undefined; timezone?: string | undefined; isAllDay?: boolean | undefined; recurrenceRule?: Record | null | undefined; recurrenceExceptions?: Record[] | null | undefined; }]) => Awaited> - "calendar:update-source-selection": (...args: [{ id: string; isSelected: boolean; }]) => Awaited> - "context-menu:show": (...args: [{ id: string; label: string; accelerator?: string | undefined; disabled?: boolean | undefined; type?: "normal" | "separator" | undefined; }[]]) => Awaited> - "crdt:apply-update": (...args: [unknown]) => Awaited> - "crdt:close-doc": (...args: [unknown]) => Awaited> - "crdt:open-doc": (...args: [unknown]) => Awaited> - "crdt:sync-step-1": (...args: [{ noteId: string; stateVector: number[]; }]) => Awaited> - "crdt:sync-step-2": (...args: [{ noteId: string; diff: number[]; }]) => Awaited> - "crypto:decrypt-item": (...args: [{ itemId: string; type: "note" | "filter" | "project" | "journal" | "task" | "settings" | "inbox" | "tag_definition" | "folder_config" | "calendar_event" | "calendar_source" | "calendar_binding" | "calendar_external_event"; encryptedKey: string; keyNonce: string; encryptedData: string; dataNonce: string; signature: string; operation?: "create" | "update" | "delete" | undefined; deletedAt?: number | undefined; metadata?: Record | undefined; }]) => Awaited> - "crypto:encrypt-item": (...args: [{ itemId: string; type: "note" | "filter" | "project" | "journal" | "task" | "settings" | "inbox" | "tag_definition" | "folder_config" | "calendar_event" | "calendar_source" | "calendar_binding" | "calendar_external_event"; content: Record; operation?: "create" | "update" | "delete" | undefined; deletedAt?: number | undefined; metadata?: Record | undefined; }]) => Awaited> - "crypto:get-rotation-progress": (...args: []) => Awaited - "crypto:rotate-keys": (...args: [{ confirm: boolean; }]) => Awaited> - "crypto:verify-signature": (...args: [{ itemId: string; type: "note" | "filter" | "project" | "journal" | "task" | "settings" | "inbox" | "tag_definition" | "folder_config" | "calendar_event" | "calendar_source" | "calendar_binding" | "calendar_external_event"; encryptedKey: string; keyNonce: string; encryptedData: string; dataNonce: string; signature: string; operation?: "create" | "update" | "delete" | undefined; deletedAt?: number | undefined; metadata?: Record | undefined; }]) => Awaited> - "folder-view:delete-view": (...args: [{ folderPath: string; viewName: string; }]) => Awaited> - "folder-view:folder-exists": (...args: [string]) => Awaited - "folder-view:get-available-properties": (...args: [{ folderPath: string; }]) => Awaited> - "folder-view:get-config": (...args: [{ folderPath: string; }]) => Awaited> - "folder-view:get-folder-suggestions": (...args: [{ noteId: string; }]) => Awaited> - "folder-view:get-views": (...args: [{ folderPath: string; }]) => Awaited> - "folder-view:list-with-properties": (...args: [{ folderPath: string; properties?: string[] | undefined; limit?: number | undefined; offset?: number | undefined; }]) => Awaited> - "folder-view:set-config": (...args: [{ folderPath: string; config: { path?: string | undefined; template?: string | undefined; inherit?: boolean | undefined; formulas?: Record | undefined; properties?: Record | undefined; summaries?: Record | undefined; views?: { name: string; type?: "table" | "grid" | "list" | "kanban" | undefined; default?: boolean | undefined; columns?: { id: string; width?: number | undefined; displayName?: string | undefined; showSummary?: boolean | undefined; }[] | undefined; filters?: unknown; order?: { property: string; direction: "asc" | "desc"; }[] | undefined; groupBy?: { property: string; direction?: "asc" | "desc" | undefined; collapsed?: boolean | undefined; showSummary?: boolean | undefined; } | undefined; limit?: number | undefined; showSummaries?: boolean | undefined; }[] | undefined; }; }]) => Awaited> - "folder-view:set-view": (...args: [{ folderPath: string; view: { name: string; type?: "table" | "grid" | "list" | "kanban" | undefined; default?: boolean | undefined; columns?: { id: string; width?: number | undefined; displayName?: string | undefined; showSummary?: boolean | undefined; }[] | undefined; filters?: unknown; order?: { property: string; direction: "asc" | "desc"; }[] | undefined; groupBy?: { property: string; direction?: "asc" | "desc" | undefined; collapsed?: boolean | undefined; showSummary?: boolean | undefined; } | undefined; limit?: number | undefined; showSummaries?: boolean | undefined; }; }]) => Awaited> - "graph:get-graph-data": (...args: []) => Awaited<{ nodes: { id: string; type: "note" | "project" | "journal" | "task"; label: string; tags: string[]; wordCount: number; connectionCount: number; emoji: string | null; color: string; isOrphan: boolean; isUnresolved: boolean; }[]; edges: { id: string; source: string; target: string; type: "wikilink" | "task-note" | "project-task" | "tag-cooccurrence"; weight: number; }[]; }> - "graph:get-local-graph": (...args: [{ noteId: string; depth?: number | undefined; }]) => Awaited<{ nodes: { id: string; type: "note" | "project" | "journal" | "task"; label: string; tags: string[]; wordCount: number; connectionCount: number; emoji: string | null; color: string; isOrphan: boolean; isUnresolved: boolean; }[]; edges: { id: string; source: string; target: string; type: "wikilink" | "task-note" | "project-task" | "tag-cooccurrence"; weight: number; }[]; }> - "inbox:add-tag": (...args: [any, any]) => Awaited> - "inbox:archive": (...args: [any]) => Awaited> - "inbox:bulk-archive": (...args: [any]) => Awaited> - "inbox:bulk-file": (...args: [any]) => Awaited> - "inbox:bulk-snooze": (...args: [any]) => Awaited> - "inbox:bulk-tag": (...args: [any]) => Awaited> - "inbox:capture-clip": (...args: [unknown]) => Awaited> - "inbox:capture-image": (...args: [any]) => Awaited> - "inbox:capture-link": (...args: [any]) => Awaited> - "inbox:capture-pdf": (...args: [unknown]) => Awaited> - "inbox:capture-text": (...args: [any]) => Awaited> - "inbox:capture-voice": (...args: [any]) => Awaited> - "inbox:convert-to-note": (...args: [any]) => Awaited> - "inbox:convert-to-task": (...args: [any]) => Awaited> - "inbox:delete-permanent": (...args: [any]) => Awaited> - "inbox:file": (...args: [any]) => Awaited> - "inbox:file-all-stale": (...args: []) => Awaited> - "inbox:get": (...args: [any]) => Awaited> - "inbox:get-filing-history": (...args: [any]) => Awaited> - "inbox:get-jobs": (...args: [any]) => Awaited> - "inbox:get-patterns": (...args: []) => Awaited> - "inbox:get-snoozed": (...args: []) => Awaited> - "inbox:get-stale-threshold": (...args: []) => Awaited> - "inbox:get-stats": (...args: []) => Awaited> - "inbox:get-suggestions": (...args: [any]) => Awaited> - "inbox:get-tags": (...args: []) => Awaited> - "inbox:link-to-note": (...args: [any, any, any]) => Awaited> - "inbox:list": (...args: [any]) => Awaited> - "inbox:list-archived": (...args: [any]) => Awaited> - "inbox:mark-viewed": (...args: [any]) => Awaited> - "inbox:preview-link": (...args: [string]) => Awaited> - "inbox:remove-tag": (...args: [any, any]) => Awaited> - "inbox:retry-metadata": (...args: [any]) => Awaited> - "inbox:retry-transcription": (...args: [any]) => Awaited> - "inbox:set-stale-threshold": (...args: [any]) => Awaited> - "inbox:snooze": (...args: [any]) => Awaited> - "inbox:track-suggestion": (...args: [string, string, string, string, number, string[], string[]]) => Awaited> - "inbox:unarchive": (...args: [any]) => Awaited> - "inbox:undo-archive": (...args: [any]) => Awaited> - "inbox:undo-file": (...args: [any]) => Awaited> - "inbox:unsnooze": (...args: [any]) => Awaited> - "inbox:update": (...args: [any]) => Awaited> - "journal:createEntry": (...args: [{ date: string; content?: string | undefined; tags?: string[] | undefined; properties?: Record | undefined; }]) => Awaited | undefined; }>> - "journal:deleteEntry": (...args: [{ date: string; }]) => Awaited> - "journal:getAllTags": (...args: []) => Awaited> - "journal:getDayContext": (...args: [{ date: string; }]) => Awaited> - "journal:getEntry": (...args: [{ date: string; }]) => Awaited | undefined; } | null>> - "journal:getHeatmap": (...args: [{ year: number; }]) => Awaited> - "journal:getMonthEntries": (...args: [{ year: number; month: number; }]) => Awaited> - "journal:getStreak": (...args: []) => Awaited> - "journal:getYearStats": (...args: [{ year: number; }]) => Awaited> - "journal:updateEntry": (...args: [{ date: string; content?: string | undefined; tags?: string[] | undefined; properties?: Record | undefined; }]) => Awaited | undefined; }>> - "notes:add-property-option": (...args: [{ propertyName: string; option: { value: string; color: string; }; }]) => Awaited> - "notes:add-status-option": (...args: [{ propertyName: string; categoryKey: "todo" | "in_progress" | "done"; option: { value: string; color: string; }; }]) => Awaited> - "notes:create": (...args: [{ title: string; content?: string | undefined; folder?: string | undefined; tags?: string[] | undefined; template?: string | undefined; }]) => Awaited | { success: false; error: string }> - "notes:create-folder": (...args: [string]) => Awaited> - "notes:create-property-definition": (...args: [{ name: string; type: "number" | "date" | "text" | "select" | "checkbox" | "url" | "status" | "multiselect"; options?: { value: string; color: string; default?: boolean | undefined; }[] | undefined; defaultValue?: unknown; color?: string | undefined; }]) => Awaited | { success: false; error: string }> - "notes:delete": (...args: [string]) => Awaited> - "notes:delete-attachment": (...args: [{ noteId: string; filename: string; }]) => Awaited | { success: false; error: string }> - "notes:delete-folder": (...args: [string]) => Awaited> - "notes:delete-property-definition": (...args: [{ name: string; }]) => Awaited> - "notes:delete-version": (...args: [string]) => Awaited> - "notes:ensure-property-definition": (...args: [{ name: string; type: "select" | "status" | "multiselect"; }]) => Awaited> - "notes:exists": (...args: [string]) => Awaited> - "notes:export-html": (...args: [{ noteId: string; includeMetadata?: boolean | undefined; pageSize?: "A4" | "Letter" | "Legal" | undefined; }]) => Awaited | { success: false; error: string }> - "notes:export-pdf": (...args: [{ noteId: string; includeMetadata?: boolean | undefined; pageSize?: "A4" | "Letter" | "Legal" | undefined; }]) => Awaited | { success: false; error: string }> - "notes:get": (...args: [string]) => Awaited> - "notes:get-all-positions": (...args: []) => Awaited; }>> - "notes:get-by-path": (...args: [string]) => Awaited> - "notes:get-file": (...args: [string]) => Awaited> - "notes:get-folder-config": (...args: [string]) => Awaited> - "notes:get-folder-template": (...args: [string]) => Awaited> - "notes:get-folders": (...args: []) => Awaited> - "notes:get-links": (...args: [string]) => Awaited> - "notes:get-local-only-count": (...args: []) => Awaited> - "notes:get-positions": (...args: [{ folderPath: string; }]) => Awaited<{ success: true; positions: { path: string; position: number; folderPath: string; }[]; } | { success: false; error: string }> - "notes:get-property-definitions": (...args: []) => Awaited> - "notes:get-tags": (...args: []) => Awaited> - "notes:get-version": (...args: [string]) => Awaited> - "notes:get-versions": (...args: [string]) => Awaited> - "notes:import-files": (...args: [{ sourcePaths: string[]; targetFolder?: string | undefined; }]) => Awaited | { success: false; error: string }> - "notes:list": (...args: [{ folder?: string | undefined; tags?: string[] | undefined; sortBy?: "title" | "modified" | "created" | "position" | undefined; sortOrder?: "asc" | "desc" | undefined; limit?: number | undefined; offset?: number | undefined; }]) => Awaited> - "notes:list-attachments": (...args: [string]) => Awaited> - "notes:move": (...args: [{ id: string; newFolder: string; }]) => Awaited | { success: false; error: string }> - "notes:open-external": (...args: [string]) => Awaited> - "notes:preview-by-title": (...args: [string]) => Awaited> - "notes:remove-property-option": (...args: [{ propertyName: string; optionValue: string; }]) => Awaited> - "notes:rename": (...args: [{ id: string; newTitle: string; }]) => Awaited | { success: false; error: string }> - "notes:rename-folder": (...args: [{ oldPath: string; newPath: string; }]) => Awaited | { success: false; error: string }> - "notes:rename-property-option": (...args: [{ propertyName: string; oldValue: string; newValue: string; }]) => Awaited> - "notes:reorder": (...args: [{ folderPath: string; notePaths: string[]; }]) => Awaited<{ success: true; } | { success: false; error: string }> - "notes:resolve-by-title": (...args: [string]) => Awaited> - "notes:restore-version": (...args: [string]) => Awaited> - "notes:reveal-in-finder": (...args: [string]) => Awaited> - "notes:set-folder-config": (...args: [{ folderPath: string; config: { icon?: string | null | undefined; template?: string | undefined; inherit?: boolean | undefined; }; }]) => Awaited | { success: false; error: string }> - "notes:set-local-only": (...args: [{ id: string; localOnly: boolean; }]) => Awaited | { success: false; error: string }> - "notes:show-import-dialog": (...args: []) => Awaited> - "notes:update": (...args: [{ id: string; title?: string | undefined; content?: string | undefined; tags?: string[] | undefined; frontmatter?: Record | undefined; emoji?: string | null | undefined; }]) => Awaited | { success: false; error: string }> - "notes:update-option-color": (...args: [{ propertyName: string; optionValue: string; newColor: string; }]) => Awaited> - "notes:update-property-definition": (...args: [{ name: string; type?: "number" | "date" | "text" | "select" | "checkbox" | "url" | "status" | "multiselect" | undefined; options?: { value: string; color: string; default?: boolean | undefined; }[] | undefined; defaultValue?: unknown; color?: string | undefined; }]) => Awaited | { success: false; error: string }> - "notes:upload-attachment": (...args: [{ noteId: string; filename: string; data: number[] | ArrayBuffer; }]) => Awaited> - "properties:get": (...args: [{ entityId: string; }]) => Awaited> - "properties:rename": (...args: [{ entityId: string; oldName: string; newName: string; }]) => Awaited> - "properties:set": (...args: [{ entityId: string; properties: Record; }]) => Awaited> - "quick-capture:get-clipboard": (...args: []) => Awaited - "reminder:bulk-dismiss": (...args: [{ reminderIds: string[]; }]) => Awaited> - "reminder:count-pending": (...args: []) => Awaited> - "reminder:create": (...args: [{ targetType: "note"; targetId: string; remindAt: string; title?: string | undefined; note?: string | undefined; } | { targetType: "journal"; targetId: string; remindAt: string; title?: string | undefined; note?: string | undefined; } | { targetType: "highlight"; targetId: string; highlightText: string; highlightStart: number; highlightEnd: number; remindAt: string; title?: string | undefined; note?: string | undefined; }]) => Awaited> - "reminder:delete": (...args: [string]) => Awaited> - "reminder:dismiss": (...args: [string]) => Awaited> - "reminder:get": (...args: [string]) => Awaited> - "reminder:get-due": (...args: []) => Awaited> - "reminder:get-for-target": (...args: [{ targetType: "note" | "journal" | "highlight"; targetId: string; }]) => Awaited> - "reminder:get-upcoming": (...args: [number | undefined]) => Awaited> - "reminder:list": (...args: [{ targetType?: "note" | "journal" | "highlight" | undefined; targetId?: string | undefined; status?: "pending" | "triggered" | "dismissed" | "snoozed" | ("pending" | "triggered" | "dismissed" | "snoozed")[] | undefined; fromDate?: string | undefined; toDate?: string | undefined; limit?: number | undefined; offset?: number | undefined; }]) => Awaited> - "reminder:snooze": (...args: [{ id: string; snoozeUntil: string; }]) => Awaited> - "reminder:update": (...args: [{ id: string; remindAt?: string | undefined; title?: string | null | undefined; note?: string | null | undefined; }]) => Awaited> - "saved-filters:create": (...args: [{ name: string; config: { filters: { search?: string | undefined; projectIds?: string[] | undefined; priorities?: ("urgent" | "high" | "medium" | "low" | "none")[] | undefined; dueDate?: { type: "custom" | "any" | "none" | "overdue" | "today" | "tomorrow" | "this-week" | "next-week" | "this-month"; customStart?: string | null | undefined; customEnd?: string | null | undefined; } | undefined; statusIds?: string[] | undefined; completion?: "active" | "completed" | "all" | undefined; repeatType?: "all" | "repeating" | "one-time" | undefined; hasTime?: "all" | "with-time" | "without-time" | undefined; }; sort?: { field: "title" | "createdAt" | "priority" | "dueDate" | "completedAt" | "project"; direction: "asc" | "desc"; } | undefined; starred?: boolean | undefined; }; }]) => Awaited> - "saved-filters:delete": (...args: [{ id: string; }]) => Awaited> - "saved-filters:list": (...args: []) => Awaited> - "saved-filters:reorder": (...args: [{ ids: string[]; positions: number[]; }]) => Awaited> - "saved-filters:update": (...args: [{ id: string; name?: string | undefined; config?: { filters: { search?: string | undefined; projectIds?: string[] | undefined; priorities?: ("urgent" | "high" | "medium" | "low" | "none")[] | undefined; dueDate?: { type: "custom" | "any" | "none" | "overdue" | "today" | "tomorrow" | "this-week" | "next-week" | "this-month"; customStart?: string | null | undefined; customEnd?: string | null | undefined; } | undefined; statusIds?: string[] | undefined; completion?: "active" | "completed" | "all" | undefined; repeatType?: "all" | "repeating" | "one-time" | undefined; hasTime?: "all" | "with-time" | "without-time" | undefined; }; sort?: { field: "title" | "createdAt" | "priority" | "dueDate" | "completedAt" | "project"; direction: "asc" | "desc"; } | undefined; starred?: boolean | undefined; } | undefined; position?: number | undefined; }]) => Awaited> - "search:add-reason": (...args: [{ itemId: string; itemType: "note" | "journal" | "task" | "inbox"; itemTitle: string; searchQuery: string; itemIcon?: string | null | undefined; }]) => Awaited> - "search:clear-reasons": (...args: []) => Awaited> - "search:get-all-tags": (...args: []) => Awaited> - "search:get-reasons": (...args: []) => Awaited> - "search:get-stats": (...args: []) => Awaited> - "search:query": (...args: [{ text: string; types?: ("note" | "journal" | "task" | "inbox")[] | undefined; tags?: string[] | undefined; dateRange?: { from: string; to: string; } | null | undefined; projectId?: string | null | undefined; folderPath?: string | null | undefined; limit?: number | undefined; offset?: number | undefined; }]) => Awaited> - "search:quick": (...args: [string]) => Awaited> - "search:rebuild-index": (...args: []) => Awaited> - "settings:downloadVoiceModel": (...args: []) => Awaited> - "settings:get": (...args: [string]) => Awaited - "settings:getAIModelStatus": (...args: []) => Awaited> - "settings:getAISettings": (...args: []) => Awaited - "settings:getBackupSettings": (...args: []) => Awaited<{ autoBackup: boolean; frequencyHours: 1 | 6 | 12 | 24; maxBackups: number; lastBackupAt: string | null; }> - "settings:getEditorSettings": (...args: []) => Awaited<{ width: "medium" | "narrow" | "wide"; spellCheck: boolean; autoSaveDelay: number; showWordCount: boolean; toolbarMode: "floating" | "sticky"; }> - "settings:getGeneralSettings": (...args: []) => Awaited<{ theme: "light" | "dark" | "white" | "system"; fontSize: "small" | "medium" | "large"; fontFamily: "system" | "serif" | "sans-serif" | "monospace" | "gelasio" | "geist" | "inter"; accentColor: string; startOnBoot: boolean; language: string; onboardingCompleted: boolean; createInSelectedFolder: boolean; clockFormat: "12h" | "24h"; }> - "settings:getGraphSettings": (...args: []) => Awaited<{ layout: "forceatlas2" | "circular" | "random"; showLabels: boolean; showEdgeLabels: boolean; animateLayout: boolean; showTagEdges: boolean; }> - "settings:getJournalSettings": (...args: []) => Awaited<{ defaultTemplate: string | null; showSchedule: boolean; showTasks: boolean; showAIConnections: boolean; showStatsFooter: boolean; }> - "settings:getKeyboardSettings": (...args: []) => Awaited<{ overrides: Record; globalCapture: { key: string; modifiers: { meta?: boolean | undefined; ctrl?: boolean | undefined; shift?: boolean | undefined; alt?: boolean | undefined; }; } | null; }> - "settings:getNoteEditorSettings": (...args: []) => Awaited - "settings:getSyncSettings": (...args: []) => Awaited<{ enabled: boolean; autoSync: boolean; }> - "settings:getTabSettings": (...args: []) => Awaited - "settings:getTaskSettings": (...args: []) => Awaited<{ defaultProjectId: string | null; defaultSortOrder: "createdAt" | "priority" | "dueDate" | "manual"; weekStartDay: "sunday" | "monday"; staleInboxDays: number; }> - "settings:getVoiceModelStatus": (...args: []) => Awaited - "settings:getVoiceRecordingReadiness": (...args: []) => Awaited> - "settings:getVoiceTranscriptionOpenAIKeyStatus": (...args: []) => Awaited> - "settings:getVoiceTranscriptionSettings": (...args: []) => Awaited<{ provider: "local" | "openai"; }> - "settings:loadAIModel": (...args: []) => Awaited> - "settings:registerGlobalCapture": (...args: []) => Awaited> - "settings:reindexEmbeddings": (...args: []) => Awaited> - "settings:resetKeyboardSettings": (...args: []) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; }> - "settings:set": (...args: [{ key: string; value: string; }]) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; }> - "settings:setAISettings": (...args: [Partial]) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; }> - "settings:setBackupSettings": (...args: [Partial<{ autoBackup: boolean; frequencyHours: 1 | 6 | 12 | 24; maxBackups: number; lastBackupAt: string | null; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "settings:setEditorSettings": (...args: [Partial<{ width: "medium" | "narrow" | "wide"; spellCheck: boolean; autoSaveDelay: number; showWordCount: boolean; toolbarMode: "floating" | "sticky"; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "settings:setGeneralSettings": (...args: [Partial<{ theme: "light" | "dark" | "white" | "system"; fontSize: "small" | "medium" | "large"; fontFamily: "system" | "serif" | "sans-serif" | "monospace" | "gelasio" | "geist" | "inter"; accentColor: string; startOnBoot: boolean; language: string; onboardingCompleted: boolean; createInSelectedFolder: boolean; clockFormat: "12h" | "24h"; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "settings:setGraphSettings": (...args: [Partial<{ layout: "forceatlas2" | "circular" | "random"; showLabels: boolean; showEdgeLabels: boolean; animateLayout: boolean; showTagEdges: boolean; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "settings:setJournalSettings": (...args: [Partial]) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; }> - "settings:setKeyboardSettings": (...args: [Partial<{ overrides: Record; globalCapture: { key: string; modifiers: { meta?: boolean | undefined; ctrl?: boolean | undefined; shift?: boolean | undefined; alt?: boolean | undefined; }; } | null; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "settings:setNoteEditorSettings": (...args: [Partial]) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; }> - "settings:setSyncSettings": (...args: [Partial<{ enabled: boolean; autoSync: boolean; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "settings:setTabSettings": (...args: [Partial]) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; }> - "settings:setTaskSettings": (...args: [Partial<{ defaultProjectId: string | null; defaultSortOrder: "createdAt" | "priority" | "dueDate" | "manual"; weekStartDay: "sunday" | "monday"; staleInboxDays: number; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "settings:setVoiceTranscriptionOpenAIKey": (...args: [{ apiKey: string; }]) => Awaited> - "settings:setVoiceTranscriptionSettings": (...args: [Partial<{ provider: "local" | "openai"; }>]) => Awaited<{ success: boolean; error?: string | undefined; }> - "sync:approve-linking": (...args: [{ sessionId: string; }]) => Awaited | { success: false; error: string }> - "sync:check-device-status": (...args: []) => Awaited> - "sync:complete-linking-qr": (...args: [{ sessionId: string; }]) => Awaited | { success: false; error: string }> - "sync:confirm-recovery-phrase": (...args: [{ confirmed: boolean; }]) => Awaited | { success: false; error: string }> - "sync:download-attachment": (...args: [{ attachmentId: string; targetPath?: string | undefined; }]) => Awaited | { success: false; error: string }> - "sync:emergency-wipe": (...args: []) => Awaited> - "sync:generate-linking-qr": (...args: []) => Awaited> - "sync:get-devices": (...args: []) => Awaited> - "sync:get-download-progress": (...args: [{ attachmentId: string; }]) => Awaited<{ progress: number; downloadedChunks: number; totalChunks: number; status: "downloading"; } | null | { success: false; error: string }> - "sync:get-history": (...args: [{ limit?: number | undefined; offset?: number | undefined; }]) => Awaited<{ entries: { id: string; type: "error" | "push" | "pull"; itemCount: number; direction: string | undefined; details: unknown; durationMs: number | undefined; createdAt: number; }[]; total: number; } | { success: false; error: string }> - "sync:get-linking-sas": (...args: [{ sessionId: string; }]) => Awaited | { success: false; error: string }> - "sync:get-quarantined-items": (...args: []) => Awaited - "sync:get-queue-size": (...args: []) => Awaited<{ pending: number; failed: number; }> - "sync:get-recovery-phrase": (...args: []) => Awaited - "sync:get-status": (...args: []) => Awaited - "sync:get-storage-breakdown": (...args: []) => Awaited> - "sync:get-synced-settings": (...args: []) => Awaited<{ general?: { theme?: "light" | "dark" | "white" | "system" | undefined; fontSize?: "small" | "medium" | "large" | undefined; fontFamily?: "system" | "serif" | "sans-serif" | "monospace" | "gelasio" | "geist" | "inter" | undefined; accentColor?: string | undefined; startOnBoot?: boolean | undefined; language?: string | undefined; createInSelectedFolder?: boolean | undefined; } | undefined; editor?: { width?: "medium" | "narrow" | "wide" | undefined; spellCheck?: boolean | undefined; autoSaveDelay?: number | undefined; showWordCount?: boolean | undefined; toolbarMode?: "floating" | "sticky" | undefined; } | undefined; tasks?: { defaultProjectId?: string | null | undefined; defaultSortOrder?: "createdAt" | "priority" | "dueDate" | "manual" | undefined; weekStartDay?: "sunday" | "monday" | undefined; staleInboxDays?: number | undefined; showCompleted?: boolean | undefined; sortBy?: string | undefined; } | undefined; keyboard?: { overrides?: Record | undefined; } | undefined; notes?: { defaultFolder?: string | undefined; editorFontSize?: number | undefined; spellCheck?: boolean | undefined; } | undefined; sync?: { autoSync?: boolean | undefined; syncIntervalMinutes?: number | undefined; } | undefined; } | null> - "sync:get-upload-progress": (...args: [{ sessionId: string; }]) => Awaited<{ progress: number; uploadedChunks: number; totalChunks: number; status: "uploading"; } | null | { success: false; error: string }> - "sync:link-via-qr": (...args: [{ qrData: string; oauthToken?: string | undefined; provider?: string | undefined; }]) => Awaited | { success: false; error: string }> - "sync:link-via-recovery": (...args: [{ recoveryPhrase: string; }]) => Awaited | { success: false; error: string }> - "sync:logout": (...args: []) => Awaited> - "sync:pause": (...args: []) => Awaited<{ success: boolean; wasPaused: boolean; }> - "sync:remove-device": (...args: [{ deviceId: string; }]) => Awaited | { success: false; error: string }> - "sync:rename-device": (...args: [{ deviceId: string; newName: string; }]) => Awaited | { success: false; error: string }> - "sync:resume": (...args: []) => Awaited<{ success: boolean; pendingCount: number; }> - "sync:setup-first-device": (...args: [{ oauthToken: string; provider: "google"; state: string; }]) => Awaited | { success: false; error: string }> - "sync:setup-new-account": (...args: []) => Awaited> - "sync:trigger-sync": (...args: []) => Awaited> - "sync:update-synced-setting": (...args: [{ fieldPath: string; value: unknown; }]) => Awaited<{ success: boolean; error: string; } | { success: boolean; error?: undefined; } | { success: false; error: string }> - "sync:upload-attachment": (...args: [{ noteId: string; filePath: string; }]) => Awaited | { success: false; error: string }> - "tags:delete": (...args: [string]) => Awaited> - "tags:get-all-with-counts": (...args: []) => Awaited> - "tags:get-notes-by-tag": (...args: [{ tag: string; sortBy?: "title" | "modified" | "created" | undefined; sortOrder?: "asc" | "desc" | undefined; includeDescendants?: boolean | undefined; }]) => Awaited> - "tags:merge": (...args: [{ source: string; target: string; }]) => Awaited> - "tags:pin-note-to-tag": (...args: [{ noteId: string; tag: string; }]) => Awaited> - "tags:remove-from-note": (...args: [{ noteId: string; tag: string; }]) => Awaited> - "tags:rename": (...args: [{ oldName: string; newName: string; }]) => Awaited> - "tags:unpin-note-from-tag": (...args: [{ noteId: string; tag: string; }]) => Awaited> - "tags:update-color": (...args: [{ tag: string; color: string; }]) => Awaited> - "tasks:archive": (...args: [string]) => Awaited> - "tasks:bulk-archive": (...args: [{ ids: string[]; }]) => Awaited> - "tasks:bulk-complete": (...args: [{ ids: string[]; }]) => Awaited> - "tasks:bulk-delete": (...args: [{ ids: string[]; }]) => Awaited> - "tasks:bulk-move": (...args: [{ ids: string[]; projectId: string; }]) => Awaited> - "tasks:complete": (...args: [{ id: string; completedAt?: string | undefined; }]) => Awaited> - "tasks:convert-to-subtask": (...args: [{ taskId: string; parentId: string; }]) => Awaited> - "tasks:convert-to-task": (...args: [string]) => Awaited> - "tasks:create": (...args: [{ projectId: string; title: string; description?: string | null | undefined; priority?: number | undefined; statusId?: string | null | undefined; parentId?: string | null | undefined; dueDate?: string | null | undefined; dueTime?: string | null | undefined; startDate?: string | null | undefined; isRepeating?: boolean | undefined; repeatConfig?: { frequency: "daily" | "weekly" | "monthly" | "yearly"; endType: "date" | "never" | "count"; createdAt: string; interval?: number | undefined; daysOfWeek?: number[] | undefined; monthlyType?: "dayOfMonth" | "weekPattern" | undefined; dayOfMonth?: number | undefined; weekOfMonth?: number | undefined; dayOfWeekForMonth?: number | undefined; endDate?: string | null | undefined; endCount?: number | undefined; completedCount?: number | undefined; } | null | undefined; repeatFrom?: "due" | "completion" | null | undefined; tags?: string[] | undefined; linkedNoteIds?: string[] | undefined; sourceNoteId?: string | null | undefined; position?: number | undefined; }]) => Awaited> - "tasks:delete": (...args: [string]) => Awaited> - "tasks:duplicate": (...args: [string]) => Awaited> - "tasks:get": (...args: [string]) => Awaited> - "tasks:get-linked-tasks": (...args: [string]) => Awaited> - "tasks:get-overdue": (...args: []) => Awaited> - "tasks:get-stats": (...args: []) => Awaited> - "tasks:get-subtasks": (...args: [string]) => Awaited> - "tasks:get-tags": (...args: []) => Awaited> - "tasks:get-today": (...args: []) => Awaited> - "tasks:get-upcoming": (...args: [{ days?: number | undefined; }]) => Awaited> - "tasks:list": (...args: [{ projectId?: string | undefined; statusId?: string | null | undefined; parentId?: string | null | undefined; includeCompleted?: boolean | undefined; includeArchived?: boolean | undefined; dueBefore?: string | undefined; dueAfter?: string | undefined; tags?: string[] | undefined; search?: string | undefined; sortBy?: "modified" | "created" | "position" | "priority" | "dueDate" | undefined; sortOrder?: "asc" | "desc" | undefined; limit?: number | undefined; offset?: number | undefined; }]) => Awaited> - "tasks:move": (...args: [{ taskId: string; position: number; targetProjectId?: string | undefined; targetStatusId?: string | null | undefined; targetParentId?: string | null | undefined; }]) => Awaited> - "tasks:project-archive": (...args: [string]) => Awaited> - "tasks:project-create": (...args: [{ name: string; description?: string | null | undefined; color?: string | undefined; icon?: string | null | undefined; statuses?: { name: string; type: "todo" | "in_progress" | "done"; order: number; color?: string | undefined; }[] | undefined; }]) => Awaited> - "tasks:project-delete": (...args: [string]) => Awaited> - "tasks:project-get": (...args: [string]) => Awaited> - "tasks:project-list": (...args: []) => Awaited> - "tasks:project-reorder": (...args: [{ projectIds: string[]; positions: number[]; }]) => Awaited> - "tasks:project-update": (...args: [{ id: string; name?: string | undefined; description?: string | null | undefined; color?: string | undefined; icon?: string | null | undefined; statuses?: { name: string; type: "todo" | "in_progress" | "done"; order: number; id?: string | undefined; color?: string | undefined; }[] | undefined; }]) => Awaited> - "tasks:reorder": (...args: [{ taskIds: string[]; positions: number[]; }]) => Awaited> - "tasks:seed-demo": (...args: []) => Awaited> - "tasks:seed-performance-test": (...args: []) => Awaited> - "tasks:status-create": (...args: [{ projectId: string; name: string; color?: string | undefined; isDone?: boolean | undefined; }]) => Awaited> - "tasks:status-delete": (...args: [string]) => Awaited> - "tasks:status-list": (...args: [string]) => Awaited> - "tasks:status-reorder": (...args: [{ statusIds: string[]; positions: number[]; }]) => Awaited> - "tasks:status-update": (...args: [{ id: string; name?: string | undefined; color?: string | undefined; position?: number | undefined; isDefault?: boolean | undefined; isDone?: boolean | undefined; }]) => Awaited> - "tasks:unarchive": (...args: [string]) => Awaited> - "tasks:uncomplete": (...args: [string]) => Awaited> - "tasks:update": (...args: [{ id: string; title?: string | undefined; description?: string | null | undefined; priority?: number | undefined; projectId?: string | undefined; statusId?: string | null | undefined; parentId?: string | null | undefined; dueDate?: string | null | undefined; dueTime?: string | null | undefined; startDate?: string | null | undefined; isRepeating?: boolean | undefined; repeatConfig?: { frequency: "daily" | "weekly" | "monthly" | "yearly"; endType: "date" | "never" | "count"; createdAt: string; interval?: number | undefined; daysOfWeek?: number[] | undefined; monthlyType?: "dayOfMonth" | "weekPattern" | undefined; dayOfMonth?: number | undefined; weekOfMonth?: number | undefined; dayOfWeekForMonth?: number | undefined; endDate?: string | null | undefined; endCount?: number | undefined; completedCount?: number | undefined; } | null | undefined; repeatFrom?: "due" | "completion" | null | undefined; tags?: string[] | undefined; linkedNoteIds?: string[] | undefined; }]) => Awaited> - "templates:create": (...args: [{ name: string; description?: string | undefined; icon?: string | null | undefined; tags?: string[] | undefined; properties?: { name: string; type: "number" | "date" | "text" | "select" | "checkbox" | "url" | "multiselect" | "rating"; value: unknown; options?: string[] | undefined; }[] | undefined; content?: string | undefined; }]) => Awaited> - "templates:delete": (...args: [string]) => Awaited> - "templates:duplicate": (...args: [{ id: string; newName: string; }]) => Awaited> - "templates:get": (...args: [string]) => Awaited> - "templates:list": (...args: []) => Awaited> - "templates:update": (...args: [{ id: string; name?: string | undefined; description?: string | undefined; icon?: string | null | undefined; tags?: string[] | undefined; properties?: { name: string; type: "number" | "date" | "text" | "select" | "checkbox" | "url" | "multiselect" | "rating"; value: unknown; options?: string[] | undefined; }[] | undefined; content?: string | undefined; }]) => Awaited> - "vault:close": (...args: []) => Awaited> - "vault:get-all": (...args: []) => Awaited> - "vault:get-config": (...args: []) => Awaited> - "vault:get-status": (...args: []) => Awaited> - "vault:reindex": (...args: []) => Awaited> - "vault:remove": (...args: [string]) => Awaited> - "vault:reveal": (...args: []) => Awaited> - "vault:select": (...args: [{ path?: string | undefined; }]) => Awaited> - "vault:switch": (...args: [string]) => Awaited> - "vault:update-config": (...args: [{ excludePatterns?: string[] | undefined; defaultNoteFolder?: string | undefined; journalFolder?: string | undefined; attachmentsFolder?: string | undefined; }]) => Awaited> + 'account:getInfo': (...args: []) => Awaited + 'account:getRecoveryKey': ( + ...args: [] + ) => Awaited< + Promise< + | { success: boolean; error: string; key?: undefined } + | { success: boolean; key: string; error?: undefined } + > + > + 'account:signOut': ( + ...args: [] + ) => Awaited> + 'ai-inline:get-server-port': (...args: []) => Awaited + 'ai-inline:get-settings': ( + ...args: [] + ) => Awaited + 'ai-inline:set-settings': ( + ...args: [ + Partial + ] + ) => Awaited<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + 'ai-inline:start-server': ( + ...args: [] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; error: string; port?: undefined } + | { success: boolean; port: number; error?: undefined } + > + > + 'ai-inline:stop-server': (...args: []) => Awaited> + 'auth:init-oauth': ( + ...args: [{ provider: 'google' }] + ) => Awaited | { success: false; error: string }> + 'auth:refresh-token': ( + ...args: [] + ) => Awaited> + 'auth:request-otp': ( + ...args: [{ email: string }] + ) => Awaited | { success: false; error: string }> + 'auth:resend-otp': ( + ...args: [{ email: string }] + ) => Awaited | { success: false; error: string }> + 'auth:verify-otp': (...args: [{ email: string; code: string }]) => Awaited< + | Promise<{ + success: boolean + isNewUser: boolean + needsSetup: boolean + needsRecoveryInput: boolean + }> + | { success: false; error: string } + > + 'bookmarks:bulk-create': ( + ...args: [{ items: { itemType: string; itemId: string }[] }] + ) => Awaited> + 'bookmarks:bulk-delete': ( + ...args: [{ bookmarkIds: string[] }] + ) => Awaited> + 'bookmarks:create': (...args: [{ itemType: string; itemId: string }]) => Awaited< + Promise< + | { success: boolean; bookmark: null; error: string } + | { + success: boolean + bookmark: { + id: string + createdAt: string + position: number + itemType: string + itemId: string + } + error?: undefined + } + > + > + 'bookmarks:delete': ( + ...args: [string] + ) => Awaited< + Promise<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + > + 'bookmarks:get': (...args: [string]) => Awaited< + Promise<{ + id: string + createdAt: string + position: number + itemType: string + itemId: string + } | null> + > + 'bookmarks:get-by-item': (...args: [{ itemType: string; itemId: string }]) => Awaited< + Promise<{ + id: string + createdAt: string + position: number + itemType: string + itemId: string + } | null> + > + 'bookmarks:is-bookmarked': ( + ...args: [{ itemType: string; itemId: string }] + ) => Awaited> + 'bookmarks:list': ( + ...args: [ + { + itemType?: string | undefined + sortBy?: 'createdAt' | 'position' | undefined + sortOrder?: 'asc' | 'desc' | undefined + limit?: number | undefined + offset?: number | undefined + } + ] + ) => Awaited< + Promise + > + 'bookmarks:list-by-type': ( + ...args: [string] + ) => Awaited< + Promise + > + 'bookmarks:reorder': ( + ...args: [{ bookmarkIds: string[] }] + ) => Awaited> + 'bookmarks:toggle': (...args: [{ itemType: string; itemId: string }]) => Awaited< + Promise<{ + success: boolean + isBookmarked: boolean + bookmark: { + id: string + createdAt: string + position: number + itemType: string + itemId: string + } | null + }> + > + 'calendar:connect-provider': ( + ...args: [{ provider: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/calendar-api').CalendarProviderMutationResponse + > + > + 'calendar:create-event': ( + ...args: [ + { + title: string + startAt: string + description?: string | null | undefined + location?: string | null | undefined + endAt?: string | null | undefined + timezone?: string | undefined + isAllDay?: boolean | undefined + recurrenceRule?: Record | null | undefined + recurrenceExceptions?: Record[] | null | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/calendar-api').CalendarEventMutationResponse + > + > + 'calendar:delete-event': ( + ...args: [string] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/calendar-api').CalendarDeleteResponse + > + > + 'calendar:disconnect-provider': ( + ...args: [{ provider: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/calendar-api').CalendarProviderMutationResponse + > + > + 'calendar:get-event': ( + ...args: [string] + ) => Awaited< + Promise + > + 'calendar:get-provider-status': ( + ...args: [{ provider: string }] + ) => Awaited< + Promise + > + 'calendar:get-range': ( + ...args: [{ startAt: string; endAt: string; includeUnselectedSources?: boolean | undefined }] + ) => Awaited< + Promise + > + 'calendar:list-events': ( + ...args: [{ includeArchived?: boolean | undefined }] + ) => Awaited< + Promise + > + 'calendar:list-sources': ( + ...args: [ + { + provider?: string | undefined + kind?: 'account' | 'calendar' | undefined + selectedOnly?: boolean | undefined + } + ] + ) => Awaited< + Promise + > + 'calendar:refresh-provider': ( + ...args: [{ provider: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/calendar-api').CalendarProviderMutationResponse + > + > + 'calendar:update-event': ( + ...args: [ + { + id: string + title?: string | undefined + description?: string | null | undefined + location?: string | null | undefined + startAt?: string | undefined + endAt?: string | null | undefined + timezone?: string | undefined + isAllDay?: boolean | undefined + recurrenceRule?: Record | null | undefined + recurrenceExceptions?: Record[] | null | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/calendar-api').CalendarEventMutationResponse + > + > + 'calendar:update-source-selection': ( + ...args: [{ id: string; isSelected: boolean }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/calendar-api').CalendarSourceMutationResponse + > + > + 'context-menu:show': ( + ...args: [ + { + id: string + label: string + accelerator?: string | undefined + disabled?: boolean | undefined + type?: 'normal' | 'separator' | undefined + }[] + ] + ) => Awaited> + 'crdt:apply-update': (...args: [unknown]) => Awaited> + 'crdt:close-doc': (...args: [unknown]) => Awaited> + 'crdt:open-doc': ( + ...args: [unknown] + ) => Awaited< + Promise<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + > + 'crdt:sync-step-1': ( + ...args: [{ noteId: string; stateVector: number[] }] + ) => Awaited< + Promise + > + 'crdt:sync-step-2': (...args: [{ noteId: string; diff: number[] }]) => Awaited> + 'crypto:decrypt-item': ( + ...args: [ + { + itemId: string + type: + | 'note' + | 'filter' + | 'project' + | 'journal' + | 'task' + | 'settings' + | 'inbox' + | 'tag_definition' + | 'folder_config' + | 'calendar_event' + | 'calendar_source' + | 'calendar_binding' + | 'calendar_external_event' + encryptedKey: string + keyNonce: string + encryptedData: string + dataNonce: string + signature: string + operation?: 'create' | 'update' | 'delete' | undefined + deletedAt?: number | undefined + metadata?: Record | undefined + } + ] + ) => Awaited< + Promise + > + 'crypto:encrypt-item': ( + ...args: [ + { + itemId: string + type: + | 'note' + | 'filter' + | 'project' + | 'journal' + | 'task' + | 'settings' + | 'inbox' + | 'tag_definition' + | 'folder_config' + | 'calendar_event' + | 'calendar_source' + | 'calendar_binding' + | 'calendar_external_event' + content: Record + operation?: 'create' | 'update' | 'delete' | undefined + deletedAt?: number | undefined + metadata?: Record | undefined + } + ] + ) => Awaited< + Promise + > + 'crypto:get-rotation-progress': ( + ...args: [] + ) => Awaited + 'crypto:rotate-keys': ( + ...args: [{ confirm: boolean }] + ) => Awaited> + 'crypto:verify-signature': ( + ...args: [ + { + itemId: string + type: + | 'note' + | 'filter' + | 'project' + | 'journal' + | 'task' + | 'settings' + | 'inbox' + | 'tag_definition' + | 'folder_config' + | 'calendar_event' + | 'calendar_source' + | 'calendar_binding' + | 'calendar_external_event' + encryptedKey: string + keyNonce: string + encryptedData: string + dataNonce: string + signature: string + operation?: 'create' | 'update' | 'delete' | undefined + deletedAt?: number | undefined + metadata?: Record | undefined + } + ] + ) => Awaited< + Promise + > + 'folder-view:delete-view': ( + ...args: [{ folderPath: string; viewName: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/folder-view-api').DeleteViewResponse + > + > + 'folder-view:folder-exists': (...args: [string]) => Awaited + 'folder-view:get-available-properties': ( + ...args: [{ folderPath: string }] + ) => Awaited< + Promise< + import('../../../../../packages/contracts/src/folder-view-api').GetAvailablePropertiesResponse + > + > + 'folder-view:get-config': ( + ...args: [{ folderPath: string }] + ) => Awaited< + Promise + > + 'folder-view:get-folder-suggestions': ( + ...args: [{ noteId: string }] + ) => Awaited< + Promise< + import('../../../../../packages/contracts/src/folder-view-api').GetFolderSuggestionsResponse + > + > + 'folder-view:get-views': ( + ...args: [{ folderPath: string }] + ) => Awaited< + Promise + > + 'folder-view:list-with-properties': ( + ...args: [ + { + folderPath: string + properties?: string[] | undefined + limit?: number | undefined + offset?: number | undefined + } + ] + ) => Awaited< + Promise< + import('../../../../../packages/contracts/src/folder-view-api').ListWithPropertiesResponse + > + > + 'folder-view:set-config': ( + ...args: [ + { + folderPath: string + config: { + path?: string | undefined + template?: string | undefined + inherit?: boolean | undefined + formulas?: Record | undefined + properties?: + | Record< + string, + { + displayName?: string | undefined + color?: boolean | undefined + dateFormat?: string | undefined + numberFormat?: string | undefined + hidden?: boolean | undefined + } + > + | undefined + summaries?: + | Record< + string, + { + type: + | 'custom' + | 'count' + | 'sum' + | 'average' + | 'min' + | 'max' + | 'countBy' + | 'countUnique' + label?: string | undefined + expression?: string | undefined + } + > + | undefined + views?: + | { + name: string + type?: 'table' | 'grid' | 'list' | 'kanban' | undefined + default?: boolean | undefined + columns?: + | { + id: string + width?: number | undefined + displayName?: string | undefined + showSummary?: boolean | undefined + }[] + | undefined + filters?: unknown + order?: { property: string; direction: 'asc' | 'desc' }[] | undefined + groupBy?: + | { + property: string + direction?: 'asc' | 'desc' | undefined + collapsed?: boolean | undefined + showSummary?: boolean | undefined + } + | undefined + limit?: number | undefined + showSummaries?: boolean | undefined + }[] + | undefined + } + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/folder-view-api').SetConfigResponse + > + > + 'folder-view:set-view': ( + ...args: [ + { + folderPath: string + view: { + name: string + type?: 'table' | 'grid' | 'list' | 'kanban' | undefined + default?: boolean | undefined + columns?: + | { + id: string + width?: number | undefined + displayName?: string | undefined + showSummary?: boolean | undefined + }[] + | undefined + filters?: unknown + order?: { property: string; direction: 'asc' | 'desc' }[] | undefined + groupBy?: + | { + property: string + direction?: 'asc' | 'desc' | undefined + collapsed?: boolean | undefined + showSummary?: boolean | undefined + } + | undefined + limit?: number | undefined + showSummaries?: boolean | undefined + } + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/folder-view-api').SetViewResponse + > + > + 'graph:get-graph-data': (...args: []) => Awaited<{ + nodes: { + id: string + type: 'note' | 'project' | 'journal' | 'task' + label: string + tags: string[] + wordCount: number + connectionCount: number + emoji: string | null + color: string + isOrphan: boolean + isUnresolved: boolean + }[] + edges: { + id: string + source: string + target: string + type: 'wikilink' | 'task-note' | 'project-task' | 'tag-cooccurrence' + weight: number + }[] + }> + 'graph:get-local-graph': (...args: [{ noteId: string; depth?: number | undefined }]) => Awaited<{ + nodes: { + id: string + type: 'note' | 'project' | 'journal' | 'task' + label: string + tags: string[] + wordCount: number + connectionCount: number + emoji: string | null + color: string + isOrphan: boolean + isUnresolved: boolean + }[] + edges: { + id: string + source: string + target: string + type: 'wikilink' | 'task-note' | 'project-task' | 'tag-cooccurrence' + weight: number + }[] + }> + 'inbox:add-tag': ( + ...args: [any, any] + ) => Awaited> + 'inbox:archive': ( + ...args: [any] + ) => Awaited> + 'inbox:bulk-archive': ( + ...args: [any] + ) => Awaited> + 'inbox:bulk-file': ( + ...args: [any] + ) => Awaited> + 'inbox:bulk-snooze': (...args: [any]) => Awaited< + Promise<{ + success: boolean + processedCount: number + errors: { itemId: string; error: string }[] + }> + > + 'inbox:bulk-tag': ( + ...args: [any] + ) => Awaited> + 'inbox:capture-clip': ( + ...args: [unknown] + ) => Awaited> + 'inbox:capture-image': ( + ...args: [any] + ) => Awaited< + Promise + > + 'inbox:capture-link': ( + ...args: [any] + ) => Awaited< + Promise + > + 'inbox:capture-pdf': ( + ...args: [unknown] + ) => Awaited> + 'inbox:capture-text': ( + ...args: [any] + ) => Awaited< + Promise + > + 'inbox:capture-voice': ( + ...args: [any] + ) => Awaited< + Promise + > + 'inbox:convert-to-note': ( + ...args: [any] + ) => Awaited> + 'inbox:convert-to-task': ( + ...args: [any] + ) => Awaited> + 'inbox:delete-permanent': ( + ...args: [any] + ) => Awaited> + 'inbox:file': ( + ...args: [any] + ) => Awaited> + 'inbox:file-all-stale': ( + ...args: [] + ) => Awaited> + 'inbox:get': ( + ...args: [any] + ) => Awaited> + 'inbox:get-filing-history': ( + ...args: [any] + ) => Awaited< + Promise + > + 'inbox:get-jobs': ( + ...args: [any] + ) => Awaited> + 'inbox:get-patterns': ( + ...args: [] + ) => Awaited> + 'inbox:get-snoozed': ( + ...args: [] + ) => Awaited> + 'inbox:get-stale-threshold': (...args: []) => Awaited> + 'inbox:get-stats': ( + ...args: [] + ) => Awaited> + 'inbox:get-suggestions': (...args: [any]) => Awaited< + Promise<{ + suggestions: import('../../../../../packages/domain-inbox/src/types').InboxFilingSuggestion[] + }> + > + 'inbox:get-tags': (...args: []) => Awaited> + 'inbox:link-to-note': ( + ...args: [any, any, any] + ) => Awaited> + 'inbox:list': ( + ...args: [any] + ) => Awaited> + 'inbox:list-archived': ( + ...args: [any] + ) => Awaited< + Promise + > + 'inbox:mark-viewed': ( + ...args: [any] + ) => Awaited> + 'inbox:preview-link': (...args: [string]) => Awaited< + Promise< + | { + title: string + domain: string + favicon: string | undefined + image: string | undefined + description: string | undefined + } + | { + title: string + domain: string + favicon?: undefined + image?: undefined + description?: undefined + } + > + > + 'inbox:remove-tag': ( + ...args: [any, any] + ) => Awaited> + 'inbox:retry-metadata': ( + ...args: [any] + ) => Awaited> + 'inbox:retry-transcription': ( + ...args: [any] + ) => Awaited> + 'inbox:set-stale-threshold': (...args: [any]) => Awaited> + 'inbox:snooze': ( + ...args: [any] + ) => Awaited> + 'inbox:track-suggestion': ( + ...args: [string, string, string, string, number, string[], string[]] + ) => Awaited< + Promise<{ success: false; error: string } | { success: boolean; error?: string | undefined }> + > + 'inbox:unarchive': ( + ...args: [any] + ) => Awaited> + 'inbox:undo-archive': ( + ...args: [any] + ) => Awaited> + 'inbox:undo-file': ( + ...args: [any] + ) => Awaited> + 'inbox:unsnooze': ( + ...args: [any] + ) => Awaited> + 'inbox:update': ( + ...args: [any] + ) => Awaited> + 'journal:createEntry': ( + ...args: [ + { + date: string + content?: string | undefined + tags?: string[] | undefined + properties?: Record | undefined + } + ] + ) => Awaited< + Promise<{ + id: string + date: string + content: string + wordCount: number + characterCount: number + tags: string[] + createdAt: string + modifiedAt: string + properties?: Record | undefined + }> + > + 'journal:deleteEntry': (...args: [{ date: string }]) => Awaited> + 'journal:getAllTags': (...args: []) => Awaited> + 'journal:getDayContext': (...args: [{ date: string }]) => Awaited< + Promise<{ + date: string + tasks: { + id: string + title: string + completed: boolean + priority?: 'urgent' | 'high' | 'medium' | 'low' | undefined + isOverdue?: boolean | undefined + }[] + events: { + id: string + time: string + title: string + type: 'meeting' | 'focus' | 'event' + attendeeCount?: number | undefined + }[] + overdueCount: number + }> + > + 'journal:getEntry': (...args: [{ date: string }]) => Awaited< + Promise<{ + id: string + date: string + content: string + wordCount: number + characterCount: number + tags: string[] + createdAt: string + modifiedAt: string + properties?: Record | undefined + } | null> + > + 'journal:getHeatmap': ( + ...args: [{ year: number }] + ) => Awaited> + 'journal:getMonthEntries': (...args: [{ year: number; month: number }]) => Awaited< + Promise< + { + date: string + preview: string + wordCount: number + characterCount: number + activityLevel: 0 | 1 | 2 | 4 | 3 + tags: string[] + }[] + > + > + 'journal:getStreak': ( + ...args: [] + ) => Awaited< + Promise<{ currentStreak: number; longestStreak: number; lastEntryDate: string | null }> + > + 'journal:getYearStats': (...args: [{ year: number }]) => Awaited< + Promise< + { + year: number + month: number + entryCount: number + totalWordCount: number + totalCharacterCount: number + averageLevel: number + }[] + > + > + 'journal:updateEntry': ( + ...args: [ + { + date: string + content?: string | undefined + tags?: string[] | undefined + properties?: Record | undefined + } + ] + ) => Awaited< + Promise<{ + id: string + date: string + content: string + wordCount: number + characterCount: number + tags: string[] + createdAt: string + modifiedAt: string + properties?: Record | undefined + }> + > + 'notes:add-property-option': ( + ...args: [{ propertyName: string; option: { value: string; color: string } }] + ) => Awaited> + 'notes:add-status-option': ( + ...args: [ + { + propertyName: string + categoryKey: 'todo' | 'in_progress' | 'done' + option: { value: string; color: string } + } + ] + ) => Awaited> + 'notes:create': ( + ...args: [ + { + title: string + content?: string | undefined + folder?: string | undefined + tags?: string[] | undefined + template?: string | undefined + } + ] + ) => Awaited< + | Promise<{ success: true; note: import('../vault/notes-crud').Note }> + | { success: false; error: string } + > + 'notes:create-folder': ( + ...args: [string] + ) => Awaited> + 'notes:create-property-definition': ( + ...args: [ + { + name: string + type: 'number' | 'date' | 'text' | 'select' | 'checkbox' | 'url' | 'status' | 'multiselect' + options?: { value: string; color: string; default?: boolean | undefined }[] | undefined + defaultValue?: unknown + color?: string | undefined + } + ] + ) => Awaited< + | Promise< + | { + success: true + definition: + | import('../../../../../packages/contracts/src/property-types').PropertyDefinition + | undefined + } + | { + success: true + definition: { + type: string + name: string + createdAt: string + options: string | null + defaultValue: string | null + color: string | null + } + } + > + | { success: false; error: string } + > + 'notes:delete': ( + ...args: [string] + ) => Awaited> + 'notes:delete-attachment': ( + ...args: [{ noteId: string; filename: string }] + ) => Awaited | { success: false; error: string }> + 'notes:delete-folder': ( + ...args: [string] + ) => Awaited> + 'notes:delete-property-definition': ( + ...args: [{ name: string }] + ) => Awaited> + 'notes:delete-version': ( + ...args: [string] + ) => Awaited> + 'notes:ensure-property-definition': ( + ...args: [{ name: string; type: 'select' | 'status' | 'multiselect' }] + ) => Awaited> + 'notes:exists': (...args: [string]) => Awaited> + 'notes:export-html': ( + ...args: [ + { + noteId: string + includeMetadata?: boolean | undefined + pageSize?: 'A4' | 'Letter' | 'Legal' | undefined + } + ] + ) => Awaited< + | Promise< + | { success: false; error: string; path?: undefined } + | { success: true; path: string; error?: undefined } + > + | { success: false; error: string } + > + 'notes:export-pdf': ( + ...args: [ + { + noteId: string + includeMetadata?: boolean | undefined + pageSize?: 'A4' | 'Letter' | 'Legal' | undefined + } + ] + ) => Awaited< + | Promise< + | { success: false; error: string; path?: undefined } + | { success: true; path: string; error?: undefined } + > + | { success: false; error: string } + > + 'notes:get': (...args: [string]) => Awaited> + 'notes:get-all-positions': ( + ...args: [] + ) => Awaited< + Promise< + { success: false; error: string } | { success: boolean; positions: Record } + > + > + 'notes:get-by-path': ( + ...args: [string] + ) => Awaited> + 'notes:get-file': ( + ...args: [string] + ) => Awaited> + 'notes:get-folder-config': ( + ...args: [string] + ) => Awaited< + Promise + > + 'notes:get-folder-template': (...args: [string]) => Awaited> + 'notes:get-folders': ( + ...args: [] + ) => Awaited> + 'notes:get-links': ( + ...args: [string] + ) => Awaited> + 'notes:get-local-only-count': (...args: []) => Awaited> + 'notes:get-positions': ( + ...args: [{ folderPath: string }] + ) => Awaited< + | { success: true; positions: { path: string; position: number; folderPath: string }[] } + | { success: false; error: string } + > + 'notes:get-property-definitions': (...args: []) => Awaited< + Promise< + { + type: string + name: string + createdAt: string + options: string | null + defaultValue: string | null + color: string | null + }[] + > + > + 'notes:get-tags': ( + ...args: [] + ) => Awaited> + 'notes:get-version': ( + ...args: [string] + ) => Awaited> + 'notes:get-versions': ( + ...args: [string] + ) => Awaited> + 'notes:import-files': ( + ...args: [{ sourcePaths: string[]; targetFolder?: string | undefined }] + ) => Awaited< + Promise | { success: false; error: string } + > + 'notes:list': ( + ...args: [ + { + folder?: string | undefined + tags?: string[] | undefined + sortBy?: 'title' | 'modified' | 'created' | 'position' | undefined + sortOrder?: 'asc' | 'desc' | undefined + limit?: number | undefined + offset?: number | undefined + } + ] + ) => Awaited> + 'notes:list-attachments': ( + ...args: [string] + ) => Awaited> + 'notes:move': ( + ...args: [{ id: string; newFolder: string }] + ) => Awaited< + | Promise<{ success: true; note: import('../vault/notes-crud').Note }> + | { success: false; error: string } + > + 'notes:open-external': (...args: [string]) => Awaited> + 'notes:preview-by-title': (...args: [string]) => Awaited< + Promise<{ + id: string + title: string + emoji: string | null + snippet: string | null + tags: { name: string; color: string }[] + createdAt: string + } | null> + > + 'notes:remove-property-option': ( + ...args: [{ propertyName: string; optionValue: string }] + ) => Awaited> + 'notes:rename': ( + ...args: [{ id: string; newTitle: string }] + ) => Awaited< + | Promise<{ success: true; note: import('../vault/notes-crud').Note }> + | { success: false; error: string } + > + 'notes:rename-folder': ( + ...args: [{ oldPath: string; newPath: string }] + ) => Awaited | { success: false; error: string }> + 'notes:rename-property-option': ( + ...args: [{ propertyName: string; oldValue: string; newValue: string }] + ) => Awaited> + 'notes:reorder': ( + ...args: [{ folderPath: string; notePaths: string[] }] + ) => Awaited<{ success: true } | { success: false; error: string }> + 'notes:resolve-by-title': (...args: [string]) => Awaited< + Promise<{ + id: string + path: string + title: string + fileType: import('../../../../../packages/shared/src/file-types').FileType + } | null> + > + 'notes:restore-version': ( + ...args: [string] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; note: import('../vault/notes-crud').Note } + > + > + 'notes:reveal-in-finder': (...args: [string]) => Awaited> + 'notes:set-folder-config': ( + ...args: [ + { + folderPath: string + config: { + icon?: string | null | undefined + template?: string | undefined + inherit?: boolean | undefined + } + } + ] + ) => Awaited | { success: false; error: string }> + 'notes:set-local-only': ( + ...args: [{ id: string; localOnly: boolean }] + ) => Awaited< + | Promise<{ success: true; note: import('../vault/notes-crud').Note }> + | { success: false; error: string } + > + 'notes:show-import-dialog': ( + ...args: [] + ) => Awaited> + 'notes:update': ( + ...args: [ + { + id: string + title?: string | undefined + content?: string | undefined + tags?: string[] | undefined + frontmatter?: Record | undefined + emoji?: string | null | undefined + } + ] + ) => Awaited< + | Promise<{ success: true; note: import('../vault/notes-crud').Note }> + | { success: false; error: string } + > + 'notes:update-option-color': ( + ...args: [{ propertyName: string; optionValue: string; newColor: string }] + ) => Awaited> + 'notes:update-property-definition': ( + ...args: [ + { + name: string + type?: + | 'number' + | 'date' + | 'text' + | 'select' + | 'checkbox' + | 'url' + | 'status' + | 'multiselect' + | undefined + options?: { value: string; color: string; default?: boolean | undefined }[] | undefined + defaultValue?: unknown + color?: string | undefined + } + ] + ) => Awaited< + | Promise< + | { success: false; definition: null; error: string } + | { + success: true + definition: + | import('../../../../../packages/contracts/src/property-types').PropertyDefinition + | undefined + error?: undefined + } + | { + success: true + definition: + | { + type: string + name: string + createdAt: string + options: string | null + defaultValue: string | null + color: string | null + } + | undefined + error?: undefined + } + > + | { success: false; error: string } + > + 'notes:upload-attachment': ( + ...args: [{ noteId: string; filename: string; data: number[] | ArrayBuffer }] + ) => Awaited> + 'properties:get': ( + ...args: [{ entityId: string }] + ) => Awaited> + 'properties:rename': ( + ...args: [{ entityId: string; oldName: string; newName: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/properties-api').RenamePropertyResponse + > + > + 'properties:set': ( + ...args: [{ entityId: string; properties: Record }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/properties-api').SetPropertiesResponse + > + > + 'quick-capture:get-clipboard': (...args: []) => Awaited + 'reminder:bulk-dismiss': ( + ...args: [{ reminderIds: string[] }] + ) => Awaited< + Promise<{ success: false; error: string } | { success: boolean; dismissedCount: number }> + > + 'reminder:count-pending': (...args: []) => Awaited> + 'reminder:create': ( + ...args: [ + | { + targetType: 'note' + targetId: string + remindAt: string + title?: string | undefined + note?: string | undefined + } + | { + targetType: 'journal' + targetId: string + remindAt: string + title?: string | undefined + note?: string | undefined + } + | { + targetType: 'highlight' + targetId: string + highlightText: string + highlightStart: number + highlightEnd: number + remindAt: string + title?: string | undefined + note?: string | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { + success: boolean + reminder: import('../../../../../packages/contracts/src/reminders-api').Reminder + } + > + > + 'reminder:delete': ( + ...args: [string] + ) => Awaited< + Promise<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + > + 'reminder:dismiss': (...args: [string]) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; reminder: null; error: string } + | { + success: boolean + reminder: import('../../../../../packages/contracts/src/reminders-api').Reminder + error?: undefined + } + > + > + 'reminder:get': ( + ...args: [string] + ) => Awaited< + Promise + > + 'reminder:get-due': ( + ...args: [] + ) => Awaited< + Promise + > + 'reminder:get-for-target': ( + ...args: [{ targetType: 'note' | 'journal' | 'highlight'; targetId: string }] + ) => Awaited> + 'reminder:get-upcoming': (...args: [number | undefined]) => Awaited< + Promise<{ + reminders: import('../../../../../packages/contracts/src/reminders-api').ReminderWithTarget[] + total: number + hasMore: boolean + }> + > + 'reminder:list': ( + ...args: [ + { + targetType?: 'note' | 'journal' | 'highlight' | undefined + targetId?: string | undefined + status?: + | 'pending' + | 'triggered' + | 'dismissed' + | 'snoozed' + | ('pending' | 'triggered' | 'dismissed' | 'snoozed')[] + | undefined + fromDate?: string | undefined + toDate?: string | undefined + limit?: number | undefined + offset?: number | undefined + } + ] + ) => Awaited< + Promise<{ + reminders: import('../../../../../packages/contracts/src/reminders-api').ReminderWithTarget[] + total: number + hasMore: boolean + }> + > + 'reminder:snooze': (...args: [{ id: string; snoozeUntil: string }]) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; reminder: null; error: string } + | { + success: boolean + reminder: import('../../../../../packages/contracts/src/reminders-api').Reminder + error?: undefined + } + > + > + 'reminder:update': ( + ...args: [ + { + id: string + remindAt?: string | undefined + title?: string | null | undefined + note?: string | null | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; reminder: null; error: string } + | { + success: boolean + reminder: import('../../../../../packages/contracts/src/reminders-api').Reminder + error?: undefined + } + > + > + 'saved-filters:create': ( + ...args: [ + { + name: string + config: { + filters: { + search?: string | undefined + projectIds?: string[] | undefined + priorities?: ('urgent' | 'high' | 'medium' | 'low' | 'none')[] | undefined + dueDate?: + | { + type: + | 'custom' + | 'any' + | 'none' + | 'overdue' + | 'today' + | 'tomorrow' + | 'this-week' + | 'next-week' + | 'this-month' + customStart?: string | null | undefined + customEnd?: string | null | undefined + } + | undefined + statusIds?: string[] | undefined + completion?: 'active' | 'completed' | 'all' | undefined + repeatType?: 'all' | 'repeating' | 'one-time' | undefined + hasTime?: 'all' | 'with-time' | 'without-time' | undefined + } + sort?: + | { + field: 'title' | 'createdAt' | 'priority' | 'dueDate' | 'completedAt' | 'project' + direction: 'asc' | 'desc' + } + | undefined + starred?: boolean | undefined + } + } + ] + ) => Awaited< + Promise<{ + success: boolean + savedFilter: import('../../../../../packages/contracts/src/saved-filters-api').SavedFilter + }> + > + 'saved-filters:delete': ( + ...args: [{ id: string }] + ) => Awaited< + Promise<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + > + 'saved-filters:list': (...args: []) => Awaited< + Promise<{ + savedFilters: import('../../../../../packages/contracts/src/saved-filters-api').SavedFilter[] + }> + > + 'saved-filters:reorder': ( + ...args: [{ ids: string[]; positions: number[] }] + ) => Awaited> + 'saved-filters:update': ( + ...args: [ + { + id: string + name?: string | undefined + config?: + | { + filters: { + search?: string | undefined + projectIds?: string[] | undefined + priorities?: ('urgent' | 'high' | 'medium' | 'low' | 'none')[] | undefined + dueDate?: + | { + type: + | 'custom' + | 'any' + | 'none' + | 'overdue' + | 'today' + | 'tomorrow' + | 'this-week' + | 'next-week' + | 'this-month' + customStart?: string | null | undefined + customEnd?: string | null | undefined + } + | undefined + statusIds?: string[] | undefined + completion?: 'active' | 'completed' | 'all' | undefined + repeatType?: 'all' | 'repeating' | 'one-time' | undefined + hasTime?: 'all' | 'with-time' | 'without-time' | undefined + } + sort?: + | { + field: + | 'title' + | 'createdAt' + | 'priority' + | 'dueDate' + | 'completedAt' + | 'project' + direction: 'asc' | 'desc' + } + | undefined + starred?: boolean | undefined + } + | undefined + position?: number | undefined + } + ] + ) => Awaited< + Promise< + | { success: boolean; savedFilter: null; error: string } + | { + success: boolean + savedFilter: + | import('../../../../../packages/contracts/src/saved-filters-api').SavedFilter + | null + error?: undefined + } + > + > + 'search:add-reason': ( + ...args: [ + { + itemId: string + itemType: 'note' | 'journal' | 'task' | 'inbox' + itemTitle: string + searchQuery: string + itemIcon?: string | null | undefined + } + ] + ) => Awaited> + 'search:clear-reasons': (...args: []) => Awaited> + 'search:get-all-tags': (...args: []) => Awaited> + 'search:get-reasons': ( + ...args: [] + ) => Awaited> + 'search:get-stats': ( + ...args: [] + ) => Awaited> + 'search:query': ( + ...args: [ + { + text: string + types?: ('note' | 'journal' | 'task' | 'inbox')[] | undefined + tags?: string[] | undefined + dateRange?: { from: string; to: string } | null | undefined + projectId?: string | null | undefined + folderPath?: string | null | undefined + limit?: number | undefined + offset?: number | undefined + } + ] + ) => Awaited> + 'search:quick': ( + ...args: [string] + ) => Awaited< + Promise + > + 'search:rebuild-index': (...args: []) => Awaited< + Promise< + | { + notes: number + tasks: number + inbox: number + durationMs: number + started: true + error?: undefined + } + | { started: false; error: string } + > + > + 'settings:downloadVoiceModel': ( + ...args: [] + ) => Awaited< + Promise<{ success: boolean; error?: undefined } | { success: boolean; error: string }> + > + 'settings:get': (...args: [string]) => Awaited + 'settings:getAIModelStatus': ( + ...args: [] + ) => Awaited> + 'settings:getAISettings': (...args: []) => Awaited + 'settings:getBackupSettings': (...args: []) => Awaited<{ + autoBackup: boolean + frequencyHours: 1 | 6 | 12 | 24 + maxBackups: number + lastBackupAt: string | null + }> + 'settings:getEditorSettings': (...args: []) => Awaited<{ + width: 'medium' | 'narrow' | 'wide' + spellCheck: boolean + autoSaveDelay: number + showWordCount: boolean + toolbarMode: 'floating' | 'sticky' + }> + 'settings:getGeneralSettings': (...args: []) => Awaited<{ + theme: 'light' | 'dark' | 'white' | 'system' + fontSize: 'small' | 'medium' | 'large' + fontFamily: 'system' | 'serif' | 'sans-serif' | 'monospace' | 'gelasio' | 'geist' | 'inter' + accentColor: string + startOnBoot: boolean + language: string + onboardingCompleted: boolean + createInSelectedFolder: boolean + clockFormat: '12h' | '24h' + }> + 'settings:getGraphSettings': (...args: []) => Awaited<{ + layout: 'forceatlas2' | 'circular' | 'random' + showLabels: boolean + showEdgeLabels: boolean + animateLayout: boolean + showTagEdges: boolean + }> + 'settings:getJournalSettings': (...args: []) => Awaited<{ + defaultTemplate: string | null + showSchedule: boolean + showTasks: boolean + showAIConnections: boolean + showStatsFooter: boolean + }> + 'settings:getKeyboardSettings': (...args: []) => Awaited<{ + overrides: Record< + string, + { + key: string + modifiers: { + meta?: boolean | undefined + ctrl?: boolean | undefined + shift?: boolean | undefined + alt?: boolean | undefined + } + } + > + globalCapture: { + key: string + modifiers: { + meta?: boolean | undefined + ctrl?: boolean | undefined + shift?: boolean | undefined + alt?: boolean | undefined + } + } | null + }> + 'settings:getNoteEditorSettings': ( + ...args: [] + ) => Awaited + 'settings:getSyncSettings': (...args: []) => Awaited<{ enabled: boolean; autoSync: boolean }> + 'settings:getTabSettings': (...args: []) => Awaited + 'settings:getTaskSettings': (...args: []) => Awaited<{ + defaultProjectId: string | null + defaultSortOrder: 'createdAt' | 'priority' | 'dueDate' | 'manual' + weekStartDay: 'sunday' | 'monday' + staleInboxDays: number + }> + 'settings:getVoiceModelStatus': ( + ...args: [] + ) => Awaited + 'settings:getVoiceRecordingReadiness': ( + ...args: [] + ) => Awaited> + 'settings:getVoiceTranscriptionOpenAIKeyStatus': ( + ...args: [] + ) => Awaited> + 'settings:getVoiceTranscriptionSettings': ( + ...args: [] + ) => Awaited<{ provider: 'local' | 'openai' }> + 'settings:loadAIModel': ( + ...args: [] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; message: string; error?: undefined } + | { success: boolean; error: string; message?: undefined } + | { success: boolean; message?: undefined; error?: undefined } + > + > + 'settings:registerGlobalCapture': ( + ...args: [] + ) => Awaited> + 'settings:reindexEmbeddings': ( + ...args: [] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; computed: number; skipped: number; error?: string | undefined } + > + > + 'settings:resetKeyboardSettings': ( + ...args: [] + ) => Awaited<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + 'settings:set': ( + ...args: [{ key: string; value: string }] + ) => Awaited<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + 'settings:setAISettings': ( + ...args: [Partial] + ) => Awaited<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + 'settings:setBackupSettings': ( + ...args: [ + Partial<{ + autoBackup: boolean + frequencyHours: 1 | 6 | 12 | 24 + maxBackups: number + lastBackupAt: string | null + }> + ] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'settings:setEditorSettings': ( + ...args: [ + Partial<{ + width: 'medium' | 'narrow' | 'wide' + spellCheck: boolean + autoSaveDelay: number + showWordCount: boolean + toolbarMode: 'floating' | 'sticky' + }> + ] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'settings:setGeneralSettings': ( + ...args: [ + Partial<{ + theme: 'light' | 'dark' | 'white' | 'system' + fontSize: 'small' | 'medium' | 'large' + fontFamily: 'system' | 'serif' | 'sans-serif' | 'monospace' | 'gelasio' | 'geist' | 'inter' + accentColor: string + startOnBoot: boolean + language: string + onboardingCompleted: boolean + createInSelectedFolder: boolean + clockFormat: '12h' | '24h' + }> + ] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'settings:setGraphSettings': ( + ...args: [ + Partial<{ + layout: 'forceatlas2' | 'circular' | 'random' + showLabels: boolean + showEdgeLabels: boolean + animateLayout: boolean + showTagEdges: boolean + }> + ] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'settings:setJournalSettings': ( + ...args: [Partial] + ) => Awaited<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + 'settings:setKeyboardSettings': ( + ...args: [ + Partial<{ + overrides: Record< + string, + { + key: string + modifiers: { + meta?: boolean | undefined + ctrl?: boolean | undefined + shift?: boolean | undefined + alt?: boolean | undefined + } + } + > + globalCapture: { + key: string + modifiers: { + meta?: boolean | undefined + ctrl?: boolean | undefined + shift?: boolean | undefined + alt?: boolean | undefined + } + } | null + }> + ] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'settings:setNoteEditorSettings': ( + ...args: [Partial] + ) => Awaited<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + 'settings:setSyncSettings': ( + ...args: [Partial<{ enabled: boolean; autoSync: boolean }>] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'settings:setTabSettings': ( + ...args: [Partial] + ) => Awaited<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + 'settings:setTaskSettings': ( + ...args: [ + Partial<{ + defaultProjectId: string | null + defaultSortOrder: 'createdAt' | 'priority' | 'dueDate' | 'manual' + weekStartDay: 'sunday' | 'monday' + staleInboxDays: number + }> + ] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'settings:setVoiceTranscriptionOpenAIKey': ( + ...args: [{ apiKey: string }] + ) => Awaited< + Promise<{ success: boolean; error?: undefined } | { success: boolean; error: string }> + > + 'settings:setVoiceTranscriptionSettings': ( + ...args: [Partial<{ provider: 'local' | 'openai' }>] + ) => Awaited<{ success: boolean; error?: string | undefined }> + 'sync:approve-linking': ( + ...args: [{ sessionId: string }] + ) => Awaited< + | Promise + | { success: false; error: string } + > + 'sync:check-device-status': (...args: []) => Awaited> + 'sync:complete-linking-qr': ( + ...args: [{ sessionId: string }] + ) => Awaited< + | Promise + | { success: false; error: string } + > + 'sync:confirm-recovery-phrase': ( + ...args: [{ confirmed: boolean }] + ) => Awaited | { success: false; error: string }> + 'sync:download-attachment': ( + ...args: [{ attachmentId: string; targetPath?: string | undefined }] + ) => Awaited< + | Promise< + | { success: boolean; error: string; filePath?: undefined } + | { success: boolean; filePath: string; error?: undefined } + > + | { success: false; error: string } + > + 'sync:emergency-wipe': (...args: []) => Awaited> + 'sync:generate-linking-qr': ( + ...args: [] + ) => Awaited< + Promise + > + 'sync:get-devices': (...args: []) => Awaited< + Promise<{ + devices: { + id: string + name: string + platform: 'macos' | 'windows' | 'linux' | 'ios' | 'android' + linkedAt: number + lastSyncAt: number | undefined + isCurrentDevice: boolean + }[] + email: string | undefined + }> + > + 'sync:get-download-progress': ( + ...args: [{ attachmentId: string }] + ) => Awaited< + | { progress: number; downloadedChunks: number; totalChunks: number; status: 'downloading' } + | null + | { success: false; error: string } + > + 'sync:get-history': ( + ...args: [{ limit?: number | undefined; offset?: number | undefined }] + ) => Awaited< + | { + entries: { + id: string + type: 'error' | 'push' | 'pull' + itemCount: number + direction: string | undefined + details: unknown + durationMs: number | undefined + createdAt: number + }[] + total: number + } + | { success: false; error: string } + > + 'sync:get-linking-sas': ( + ...args: [{ sessionId: string }] + ) => Awaited< + | Promise<{ verificationCode?: string | undefined; error?: string | undefined }> + | { success: false; error: string } + > + 'sync:get-quarantined-items': ( + ...args: [] + ) => Awaited + 'sync:get-queue-size': (...args: []) => Awaited<{ pending: number; failed: number }> + 'sync:get-recovery-phrase': (...args: []) => Awaited + 'sync:get-status': ( + ...args: [] + ) => Awaited< + | import('../../../../../packages/contracts/src/ipc-sync-ops').GetSyncStatusResult + | { status: string; pendingCount: number } + > + 'sync:get-storage-breakdown': ( + ...args: [] + ) => Awaited< + Promise< + import('../../../../../packages/contracts/src/ipc-sync-ops').StorageBreakdownResult | null + > + > + 'sync:get-synced-settings': (...args: []) => Awaited<{ + general?: + | { + theme?: 'light' | 'dark' | 'white' | 'system' | undefined + fontSize?: 'small' | 'medium' | 'large' | undefined + fontFamily?: + | 'system' + | 'serif' + | 'sans-serif' + | 'monospace' + | 'gelasio' + | 'geist' + | 'inter' + | undefined + accentColor?: string | undefined + startOnBoot?: boolean | undefined + language?: string | undefined + createInSelectedFolder?: boolean | undefined + } + | undefined + editor?: + | { + width?: 'medium' | 'narrow' | 'wide' | undefined + spellCheck?: boolean | undefined + autoSaveDelay?: number | undefined + showWordCount?: boolean | undefined + toolbarMode?: 'floating' | 'sticky' | undefined + } + | undefined + tasks?: + | { + defaultProjectId?: string | null | undefined + defaultSortOrder?: 'createdAt' | 'priority' | 'dueDate' | 'manual' | undefined + weekStartDay?: 'sunday' | 'monday' | undefined + staleInboxDays?: number | undefined + showCompleted?: boolean | undefined + sortBy?: string | undefined + } + | undefined + keyboard?: { overrides?: Record | undefined } | undefined + notes?: + | { + defaultFolder?: string | undefined + editorFontSize?: number | undefined + spellCheck?: boolean | undefined + } + | undefined + sync?: { autoSync?: boolean | undefined; syncIntervalMinutes?: number | undefined } | undefined + } | null> + 'sync:get-upload-progress': ( + ...args: [{ sessionId: string }] + ) => Awaited< + | { progress: number; uploadedChunks: number; totalChunks: number; status: 'uploading' } + | null + | { success: false; error: string } + > + 'sync:link-via-qr': ( + ...args: [{ qrData: string; oauthToken?: string | undefined; provider?: string | undefined }] + ) => Awaited< + | Promise + | { success: false; error: string } + > + 'sync:link-via-recovery': ( + ...args: [{ recoveryPhrase: string }] + ) => Awaited< + | Promise< + | { success: boolean; error: string; deviceId?: undefined } + | { success: boolean; deviceId: string; error?: undefined } + > + | { success: false; error: string } + > + 'sync:logout': ( + ...args: [] + ) => Awaited> + 'sync:pause': (...args: []) => Awaited<{ success: boolean; wasPaused: boolean }> + 'sync:remove-device': ( + ...args: [{ deviceId: string }] + ) => Awaited< + | Promise<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + | { success: false; error: string } + > + 'sync:rename-device': ( + ...args: [{ deviceId: string; newName: string }] + ) => Awaited< + | Promise<{ success: boolean; error: string } | { success: boolean; error?: undefined }> + | { success: false; error: string } + > + 'sync:resume': (...args: []) => Awaited<{ success: boolean; pendingCount: number }> + 'sync:setup-first-device': ( + ...args: [{ oauthToken: string; provider: 'google'; state: string }] + ) => Awaited< + | Promise< + | { + success: boolean + needsRecoverySetup: boolean + deviceId: string + needsRecoveryInput?: undefined + } + | { + success: boolean + needsRecoverySetup: boolean + needsRecoveryInput: boolean + deviceId?: undefined + } + > + | { success: false; error: string } + > + 'sync:setup-new-account': ( + ...args: [] + ) => Awaited< + Promise< + | { success: boolean; error: string; deviceId?: undefined } + | { success: boolean; deviceId: string; error?: undefined } + > + > + 'sync:trigger-sync': ( + ...args: [] + ) => Awaited> + 'sync:update-synced-setting': ( + ...args: [{ fieldPath: string; value: unknown }] + ) => Awaited< + | { success: boolean; error: string } + | { success: boolean; error?: undefined } + | { success: false; error: string } + > + 'sync:upload-attachment': ( + ...args: [{ noteId: string; filePath: string }] + ) => Awaited< + | Promise< + | { success: boolean; error: string; attachmentId?: undefined; sessionId?: undefined } + | { success: boolean; attachmentId: string; sessionId: string; error?: undefined } + > + | { success: false; error: string } + > + 'tags:delete': ( + ...args: [string] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/tags-api').DeleteTagResponse + > + > + 'tags:get-all-with-counts': ( + ...args: [] + ) => Awaited< + Promise + > + 'tags:get-notes-by-tag': ( + ...args: [ + { + tag: string + sortBy?: 'title' | 'modified' | 'created' | undefined + sortOrder?: 'asc' | 'desc' | undefined + includeDescendants?: boolean | undefined + } + ] + ) => Awaited< + Promise + > + 'tags:merge': ( + ...args: [{ source: string; target: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/tags-api').MergeTagResponse + > + > + 'tags:pin-note-to-tag': ( + ...args: [{ noteId: string; tag: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/tags-api').TagOperationResponse + > + > + 'tags:remove-from-note': ( + ...args: [{ noteId: string; tag: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/tags-api').TagOperationResponse + > + > + 'tags:rename': ( + ...args: [{ oldName: string; newName: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/tags-api').RenameTagResponse + > + > + 'tags:unpin-note-from-tag': ( + ...args: [{ noteId: string; tag: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/tags-api').TagOperationResponse + > + > + 'tags:update-color': ( + ...args: [{ tag: string; color: string }] + ) => Awaited< + Promise< + | { success: false; error: string } + | import('../../../../../packages/contracts/src/tags-api').TagOperationResponse + > + > + 'tasks:archive': ( + ...args: [string] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; error: string } + | { success: boolean; error?: undefined } + > + > + 'tasks:bulk-archive': ( + ...args: [{ ids: string[] }] + ) => Awaited> + 'tasks:bulk-complete': ( + ...args: [{ ids: string[] }] + ) => Awaited> + 'tasks:bulk-delete': ( + ...args: [{ ids: string[] }] + ) => Awaited> + 'tasks:bulk-move': ( + ...args: [{ ids: string[]; projectId: string }] + ) => Awaited> + 'tasks:complete': (...args: [{ id: string; completedAt?: string | undefined }]) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: null; error: string } + | { + success: boolean + task: import('../../../../../packages/domain-tasks/src/types').Task + error?: undefined + } + > + > + 'tasks:convert-to-subtask': (...args: [{ taskId: string; parentId: string }]) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: null; error: string } + | { + success: boolean + task: import('../../../../../packages/domain-tasks/src/types').Task + error?: undefined + } + > + > + 'tasks:convert-to-task': (...args: [string]) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: null; error: string } + | { + success: boolean + task: import('../../../../../packages/domain-tasks/src/types').Task + error?: undefined + } + > + > + 'tasks:create': ( + ...args: [ + { + projectId: string + title: string + description?: string | null | undefined + priority?: number | undefined + statusId?: string | null | undefined + parentId?: string | null | undefined + dueDate?: string | null | undefined + dueTime?: string | null | undefined + startDate?: string | null | undefined + isRepeating?: boolean | undefined + repeatConfig?: + | { + frequency: 'daily' | 'weekly' | 'monthly' | 'yearly' + endType: 'date' | 'never' | 'count' + createdAt: string + interval?: number | undefined + daysOfWeek?: number[] | undefined + monthlyType?: 'dayOfMonth' | 'weekPattern' | undefined + dayOfMonth?: number | undefined + weekOfMonth?: number | undefined + dayOfWeekForMonth?: number | undefined + endDate?: string | null | undefined + endCount?: number | undefined + completedCount?: number | undefined + } + | null + | undefined + repeatFrom?: 'due' | 'completion' | null | undefined + tags?: string[] | undefined + linkedNoteIds?: string[] | undefined + sourceNoteId?: string | null | undefined + position?: number | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: import('../../../../../packages/domain-tasks/src/types').Task } + > + > + 'tasks:delete': ( + ...args: [string] + ) => Awaited> + 'tasks:duplicate': (...args: [string]) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: null; error: string } + | { + success: boolean + task: import('../../../../../packages/domain-tasks/src/types').Task + error?: undefined + } + > + > + 'tasks:get': ( + ...args: [string] + ) => Awaited> + 'tasks:get-linked-tasks': ( + ...args: [string] + ) => Awaited> + 'tasks:get-overdue': ( + ...args: [] + ) => Awaited> + 'tasks:get-stats': ( + ...args: [] + ) => Awaited> + 'tasks:get-subtasks': ( + ...args: [string] + ) => Awaited> + 'tasks:get-tags': (...args: []) => Awaited> + 'tasks:get-today': ( + ...args: [] + ) => Awaited> + 'tasks:get-upcoming': ( + ...args: [{ days?: number | undefined }] + ) => Awaited> + 'tasks:list': ( + ...args: [ + { + projectId?: string | undefined + statusId?: string | null | undefined + parentId?: string | null | undefined + includeCompleted?: boolean | undefined + includeArchived?: boolean | undefined + dueBefore?: string | undefined + dueAfter?: string | undefined + tags?: string[] | undefined + search?: string | undefined + sortBy?: 'modified' | 'created' | 'position' | 'priority' | 'dueDate' | undefined + sortOrder?: 'asc' | 'desc' | undefined + limit?: number | undefined + offset?: number | undefined + } + ] + ) => Awaited> + 'tasks:move': ( + ...args: [ + { + taskId: string + position: number + targetProjectId?: string | undefined + targetStatusId?: string | null | undefined + targetParentId?: string | null | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: null; error: string } + | { + success: boolean + task: import('../../../../../packages/domain-tasks/src/types').Task + error?: undefined + } + > + > + 'tasks:project-archive': ( + ...args: [string] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; error: string } + | { success: boolean; error?: undefined } + > + > + 'tasks:project-create': ( + ...args: [ + { + name: string + description?: string | null | undefined + color?: string | undefined + icon?: string | null | undefined + statuses?: + | { + name: string + type: 'todo' | 'in_progress' | 'done' + order: number + color?: string | undefined + }[] + | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { + success: boolean + project: import('../../../../../packages/domain-tasks/src/types').ProjectWithStatuses + } + > + > + 'tasks:project-delete': ( + ...args: [string] + ) => Awaited> + 'tasks:project-get': ( + ...args: [string] + ) => Awaited< + Promise< + import('../../../../../packages/domain-tasks/src/types').ProjectWithStatuses | undefined + > + > + 'tasks:project-list': (...args: []) => Awaited< + Promise<{ + projects: import('../../../../../packages/domain-tasks/src/types').ProjectWithStats[] + }> + > + 'tasks:project-reorder': ( + ...args: [{ projectIds: string[]; positions: number[] }] + ) => Awaited> + 'tasks:project-update': ( + ...args: [ + { + id: string + name?: string | undefined + description?: string | null | undefined + color?: string | undefined + icon?: string | null | undefined + statuses?: + | { + name: string + type: 'todo' | 'in_progress' | 'done' + order: number + id?: string | undefined + color?: string | undefined + }[] + | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; project: null; error: string } + | { + success: boolean + project: import('../../../../../packages/domain-tasks/src/types').ProjectWithStatuses + error?: undefined + } + > + > + 'tasks:reorder': ( + ...args: [{ taskIds: string[]; positions: number[] }] + ) => Awaited> + 'tasks:seed-demo': (...args: []) => Awaited> + 'tasks:seed-performance-test': ( + ...args: [] + ) => Awaited> + 'tasks:status-create': ( + ...args: [ + { projectId: string; name: string; color?: string | undefined; isDone?: boolean | undefined } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { + success: boolean + status: import('../../../../../packages/domain-tasks/src/types').Status + } + > + > + 'tasks:status-delete': ( + ...args: [string] + ) => Awaited> + 'tasks:status-list': ( + ...args: [string] + ) => Awaited> + 'tasks:status-reorder': ( + ...args: [{ statusIds: string[]; positions: number[] }] + ) => Awaited> + 'tasks:status-update': ( + ...args: [ + { + id: string + name?: string | undefined + color?: string | undefined + position?: number | undefined + isDefault?: boolean | undefined + isDone?: boolean | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; error: string; status?: undefined } + | { + success: boolean + status: import('../../../../../packages/domain-tasks/src/types').Status + error?: undefined + } + > + > + 'tasks:unarchive': ( + ...args: [string] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; error: string } + | { success: boolean; error?: undefined } + > + > + 'tasks:uncomplete': (...args: [string]) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: null; error: string } + | { + success: boolean + task: import('../../../../../packages/domain-tasks/src/types').Task + error?: undefined + } + > + > + 'tasks:update': ( + ...args: [ + { + id: string + title?: string | undefined + description?: string | null | undefined + priority?: number | undefined + projectId?: string | undefined + statusId?: string | null | undefined + parentId?: string | null | undefined + dueDate?: string | null | undefined + dueTime?: string | null | undefined + startDate?: string | null | undefined + isRepeating?: boolean | undefined + repeatConfig?: + | { + frequency: 'daily' | 'weekly' | 'monthly' | 'yearly' + endType: 'date' | 'never' | 'count' + createdAt: string + interval?: number | undefined + daysOfWeek?: number[] | undefined + monthlyType?: 'dayOfMonth' | 'weekPattern' | undefined + dayOfMonth?: number | undefined + weekOfMonth?: number | undefined + dayOfWeekForMonth?: number | undefined + endDate?: string | null | undefined + endCount?: number | undefined + completedCount?: number | undefined + } + | null + | undefined + repeatFrom?: 'due' | 'completion' | null | undefined + tags?: string[] | undefined + linkedNoteIds?: string[] | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { success: boolean; task: null; error: string } + | { + success: boolean + task: import('../../../../../packages/domain-tasks/src/types').Task + error?: undefined + } + > + > + 'templates:create': ( + ...args: [ + { + name: string + description?: string | undefined + icon?: string | null | undefined + tags?: string[] | undefined + properties?: + | { + name: string + type: + | 'number' + | 'date' + | 'text' + | 'select' + | 'checkbox' + | 'url' + | 'multiselect' + | 'rating' + value: unknown + options?: string[] | undefined + }[] + | undefined + content?: string | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { + success: boolean + template: import('../../../../../packages/contracts/src/templates-api').Template + } + > + > + 'templates:delete': ( + ...args: [string] + ) => Awaited> + 'templates:duplicate': (...args: [{ id: string; newName: string }]) => Awaited< + Promise< + | { success: false; error: string } + | { + success: boolean + template: import('../../../../../packages/contracts/src/templates-api').Template + } + > + > + 'templates:get': ( + ...args: [string] + ) => Awaited< + Promise + > + 'templates:list': (...args: []) => Awaited< + Promise<{ + templates: import('../../../../../packages/contracts/src/templates-api').TemplateListItem[] + }> + > + 'templates:update': ( + ...args: [ + { + id: string + name?: string | undefined + description?: string | undefined + icon?: string | null | undefined + tags?: string[] | undefined + properties?: + | { + name: string + type: + | 'number' + | 'date' + | 'text' + | 'select' + | 'checkbox' + | 'url' + | 'multiselect' + | 'rating' + value: unknown + options?: string[] | undefined + }[] + | undefined + content?: string | undefined + } + ] + ) => Awaited< + Promise< + | { success: false; error: string } + | { + success: boolean + template: import('../../../../../packages/contracts/src/templates-api').Template + } + > + > + 'vault:close': (...args: []) => Awaited> + 'vault:get-all': ( + ...args: [] + ) => Awaited> + 'vault:get-config': ( + ...args: [] + ) => Awaited> + 'vault:get-status': ( + ...args: [] + ) => Awaited> + 'vault:reindex': (...args: []) => Awaited> + 'vault:remove': (...args: [string]) => Awaited> + 'vault:reveal': (...args: []) => Awaited> + 'vault:select': ( + ...args: [{ path?: string | undefined }] + ) => Awaited< + Promise + > + 'vault:switch': ( + ...args: [string] + ) => Awaited< + Promise + > + 'vault:update-config': ( + ...args: [ + { + excludePatterns?: string[] | undefined + defaultNoteFolder?: string | undefined + journalFolder?: string | undefined + attachmentsFolder?: string | undefined + } + ] + ) => Awaited> } export type MainIpcInvokeChannel = keyof MainIpcInvokeHandlers -export type MainIpcInvokeArgs = - Parameters -export type MainIpcInvokeResult = - ReturnType +export type MainIpcInvokeArgs = Parameters +export type MainIpcInvokeResult = ReturnType< + MainIpcInvokeHandlers[C] +> diff --git a/apps/desktop/src/preload/generated-rpc.ts b/apps/desktop/src/preload/generated-rpc.ts index 7cc13b580..6a192172d 100644 --- a/apps/desktop/src/preload/generated-rpc.ts +++ b/apps/desktop/src/preload/generated-rpc.ts @@ -2,7 +2,11 @@ export type { GeneratedRpcApi } from '@memry/rpc' import type { GeneratedRpcApi } from '@memry/rpc' -import type { MainIpcInvokeArgs, MainIpcInvokeChannel, MainIpcInvokeResult } from '../main/ipc/generated-ipc-invoke-map' +import type { + MainIpcInvokeArgs, + MainIpcInvokeChannel, + MainIpcInvokeResult +} from '../main/ipc/generated-ipc-invoke-map' export interface GeneratedRpcDeps { invoke( @@ -20,119 +24,257 @@ export function createGeneratedRpcApi({ }: GeneratedRpcDeps): GeneratedRpcApi { return { notes: { - create: ((input) => invoke("notes:create", input)) as GeneratedRpcApi["notes"]["create"], - get: ((id) => invoke("notes:get", id)) as GeneratedRpcApi["notes"]["get"], - getByPath: ((path) => invoke("notes:get-by-path", path)) as GeneratedRpcApi["notes"]["getByPath"], - getFile: ((id) => invoke("notes:get-file", id)) as GeneratedRpcApi["notes"]["getFile"], - resolveByTitle: ((title) => invoke("notes:resolve-by-title", title)) as GeneratedRpcApi["notes"]["resolveByTitle"], - previewByTitle: ((title) => invoke("notes:preview-by-title", title)) as GeneratedRpcApi["notes"]["previewByTitle"], - update: ((input) => invoke("notes:update", input)) as GeneratedRpcApi["notes"]["update"], - rename: ((id, newTitle) => invoke("notes:rename", { id, newTitle })) as GeneratedRpcApi["notes"]["rename"], - move: ((id, newFolder) => invoke("notes:move", { id, newFolder })) as GeneratedRpcApi["notes"]["move"], - delete: ((id) => invoke("notes:delete", id)) as GeneratedRpcApi["notes"]["delete"], - list: ((options) => invoke("notes:list", options ?? {})) as GeneratedRpcApi["notes"]["list"], - getTags: (() => invoke("notes:get-tags")) as GeneratedRpcApi["notes"]["getTags"], - getLinks: ((id) => invoke("notes:get-links", id)) as GeneratedRpcApi["notes"]["getLinks"], - getFolders: (() => invoke("notes:get-folders")) as GeneratedRpcApi["notes"]["getFolders"], - createFolder: ((path) => invoke("notes:create-folder", path)) as GeneratedRpcApi["notes"]["createFolder"], - renameFolder: ((oldPath, newPath) => invoke("notes:rename-folder", { oldPath, newPath })) as GeneratedRpcApi["notes"]["renameFolder"], - deleteFolder: ((path) => invoke("notes:delete-folder", path)) as GeneratedRpcApi["notes"]["deleteFolder"], - exists: ((titleOrPath) => invoke("notes:exists", titleOrPath)) as GeneratedRpcApi["notes"]["exists"], - openExternal: ((id) => invoke("notes:open-external", id)) as GeneratedRpcApi["notes"]["openExternal"], - revealInFinder: ((id) => invoke("notes:reveal-in-finder", id)) as GeneratedRpcApi["notes"]["revealInFinder"], - getPropertyDefinitions: (() => invoke("notes:get-property-definitions")) as GeneratedRpcApi["notes"]["getPropertyDefinitions"], - createPropertyDefinition: ((input) => invoke("notes:create-property-definition", input)) as GeneratedRpcApi["notes"]["createPropertyDefinition"], - updatePropertyDefinition: ((input) => invoke("notes:update-property-definition", input)) as GeneratedRpcApi["notes"]["updatePropertyDefinition"], - ensurePropertyDefinition: ((name, type) => invoke("notes:ensure-property-definition", { name, type })) as GeneratedRpcApi["notes"]["ensurePropertyDefinition"], - addPropertyOption: ((propertyName, option) => invoke("notes:add-property-option", { propertyName, option })) as GeneratedRpcApi["notes"]["addPropertyOption"], - addStatusOption: ((propertyName, categoryKey, option) => invoke("notes:add-status-option", { propertyName, categoryKey, option })) as GeneratedRpcApi["notes"]["addStatusOption"], - removePropertyOption: ((propertyName, optionValue) => invoke("notes:remove-property-option", { propertyName, optionValue })) as GeneratedRpcApi["notes"]["removePropertyOption"], - renamePropertyOption: ((propertyName, oldValue, newValue) => invoke("notes:rename-property-option", { propertyName, oldValue, newValue })) as GeneratedRpcApi["notes"]["renamePropertyOption"], - updateOptionColor: ((propertyName, optionValue, newColor) => invoke("notes:update-option-color", { propertyName, optionValue, newColor })) as GeneratedRpcApi["notes"]["updateOptionColor"], - deletePropertyDefinition: ((name) => invoke("notes:delete-property-definition", { name })) as GeneratedRpcApi["notes"]["deletePropertyDefinition"], + create: ((input) => invoke('notes:create', input)) as GeneratedRpcApi['notes']['create'], + get: ((id) => invoke('notes:get', id)) as GeneratedRpcApi['notes']['get'], + getByPath: ((path) => + invoke('notes:get-by-path', path)) as GeneratedRpcApi['notes']['getByPath'], + getFile: ((id) => invoke('notes:get-file', id)) as GeneratedRpcApi['notes']['getFile'], + resolveByTitle: ((title) => + invoke('notes:resolve-by-title', title)) as GeneratedRpcApi['notes']['resolveByTitle'], + previewByTitle: ((title) => + invoke('notes:preview-by-title', title)) as GeneratedRpcApi['notes']['previewByTitle'], + update: ((input) => invoke('notes:update', input)) as GeneratedRpcApi['notes']['update'], + rename: ((id, newTitle) => + invoke('notes:rename', { id, newTitle })) as GeneratedRpcApi['notes']['rename'], + move: ((id, newFolder) => + invoke('notes:move', { id, newFolder })) as GeneratedRpcApi['notes']['move'], + delete: ((id) => invoke('notes:delete', id)) as GeneratedRpcApi['notes']['delete'], + list: ((options) => invoke('notes:list', options ?? {})) as GeneratedRpcApi['notes']['list'], + getTags: (() => invoke('notes:get-tags')) as GeneratedRpcApi['notes']['getTags'], + getLinks: ((id) => invoke('notes:get-links', id)) as GeneratedRpcApi['notes']['getLinks'], + getFolders: (() => invoke('notes:get-folders')) as GeneratedRpcApi['notes']['getFolders'], + createFolder: ((path) => + invoke('notes:create-folder', path)) as GeneratedRpcApi['notes']['createFolder'], + renameFolder: ((oldPath, newPath) => + invoke('notes:rename-folder', { + oldPath, + newPath + })) as GeneratedRpcApi['notes']['renameFolder'], + deleteFolder: ((path) => + invoke('notes:delete-folder', path)) as GeneratedRpcApi['notes']['deleteFolder'], + exists: ((titleOrPath) => + invoke('notes:exists', titleOrPath)) as GeneratedRpcApi['notes']['exists'], + openExternal: ((id) => + invoke('notes:open-external', id)) as GeneratedRpcApi['notes']['openExternal'], + revealInFinder: ((id) => + invoke('notes:reveal-in-finder', id)) as GeneratedRpcApi['notes']['revealInFinder'], + getPropertyDefinitions: (() => + invoke( + 'notes:get-property-definitions' + )) as GeneratedRpcApi['notes']['getPropertyDefinitions'], + createPropertyDefinition: ((input) => + invoke( + 'notes:create-property-definition', + input + )) as GeneratedRpcApi['notes']['createPropertyDefinition'], + updatePropertyDefinition: ((input) => + invoke( + 'notes:update-property-definition', + input + )) as GeneratedRpcApi['notes']['updatePropertyDefinition'], + ensurePropertyDefinition: ((name, type) => + invoke('notes:ensure-property-definition', { + name, + type + })) as GeneratedRpcApi['notes']['ensurePropertyDefinition'], + addPropertyOption: ((propertyName, option) => + invoke('notes:add-property-option', { + propertyName, + option + })) as GeneratedRpcApi['notes']['addPropertyOption'], + addStatusOption: ((propertyName, categoryKey, option) => + invoke('notes:add-status-option', { + propertyName, + categoryKey, + option + })) as GeneratedRpcApi['notes']['addStatusOption'], + removePropertyOption: ((propertyName, optionValue) => + invoke('notes:remove-property-option', { + propertyName, + optionValue + })) as GeneratedRpcApi['notes']['removePropertyOption'], + renamePropertyOption: ((propertyName, oldValue, newValue) => + invoke('notes:rename-property-option', { + propertyName, + oldValue, + newValue + })) as GeneratedRpcApi['notes']['renamePropertyOption'], + updateOptionColor: ((propertyName, optionValue, newColor) => + invoke('notes:update-option-color', { + propertyName, + optionValue, + newColor + })) as GeneratedRpcApi['notes']['updateOptionColor'], + deletePropertyDefinition: ((name) => + invoke('notes:delete-property-definition', { + name + })) as GeneratedRpcApi['notes']['deletePropertyDefinition'], uploadAttachment: (async (noteId, file) => - invoke("notes:upload-attachment", { + invoke('notes:upload-attachment', { noteId, filename: file.name, data: Array.from(new Uint8Array(await file.arrayBuffer())) - })) as GeneratedRpcApi["notes"]["uploadAttachment"], - listAttachments: ((noteId) => invoke("notes:list-attachments", noteId)) as GeneratedRpcApi["notes"]["listAttachments"], - deleteAttachment: ((noteId, filename) => invoke("notes:delete-attachment", { noteId, filename })) as GeneratedRpcApi["notes"]["deleteAttachment"], - getFolderConfig: ((folderPath) => invoke("notes:get-folder-config", folderPath)) as GeneratedRpcApi["notes"]["getFolderConfig"], - setFolderConfig: ((folderPath, config) => invoke("notes:set-folder-config", { folderPath, config })) as GeneratedRpcApi["notes"]["setFolderConfig"], - getFolderTemplate: ((folderPath) => invoke("notes:get-folder-template", folderPath)) as GeneratedRpcApi["notes"]["getFolderTemplate"], - exportPdf: ((input) => invoke("notes:export-pdf", input)) as GeneratedRpcApi["notes"]["exportPdf"], - exportHtml: ((input) => invoke("notes:export-html", input)) as GeneratedRpcApi["notes"]["exportHtml"], - getVersions: ((noteId) => invoke("notes:get-versions", noteId)) as GeneratedRpcApi["notes"]["getVersions"], - getVersion: ((snapshotId) => invoke("notes:get-version", snapshotId)) as GeneratedRpcApi["notes"]["getVersion"], - restoreVersion: ((snapshotId) => invoke("notes:restore-version", snapshotId)) as GeneratedRpcApi["notes"]["restoreVersion"], - deleteVersion: ((snapshotId) => invoke("notes:delete-version", snapshotId)) as GeneratedRpcApi["notes"]["deleteVersion"], - getPositions: ((folderPath) => invoke("notes:get-positions", { folderPath })) as GeneratedRpcApi["notes"]["getPositions"], - getAllPositions: (() => invoke("notes:get-all-positions")) as GeneratedRpcApi["notes"]["getAllPositions"], - reorder: ((folderPath, notePaths) => invoke("notes:reorder", { folderPath, notePaths })) as GeneratedRpcApi["notes"]["reorder"], - importFiles: ((sourcePaths, targetFolder) => invoke("notes:import-files", { sourcePaths, targetFolder })) as GeneratedRpcApi["notes"]["importFiles"], - showImportDialog: (() => invoke("notes:show-import-dialog")) as GeneratedRpcApi["notes"]["showImportDialog"], - setLocalOnly: ((id, localOnly) => invoke("notes:set-local-only", { id, localOnly })) as GeneratedRpcApi["notes"]["setLocalOnly"], - getLocalOnlyCount: (() => invoke("notes:get-local-only-count")) as GeneratedRpcApi["notes"]["getLocalOnlyCount"], + })) as GeneratedRpcApi['notes']['uploadAttachment'], + listAttachments: ((noteId) => + invoke('notes:list-attachments', noteId)) as GeneratedRpcApi['notes']['listAttachments'], + deleteAttachment: ((noteId, filename) => + invoke('notes:delete-attachment', { + noteId, + filename + })) as GeneratedRpcApi['notes']['deleteAttachment'], + getFolderConfig: ((folderPath) => + invoke( + 'notes:get-folder-config', + folderPath + )) as GeneratedRpcApi['notes']['getFolderConfig'], + setFolderConfig: ((folderPath, config) => + invoke('notes:set-folder-config', { + folderPath, + config + })) as GeneratedRpcApi['notes']['setFolderConfig'], + getFolderTemplate: ((folderPath) => + invoke( + 'notes:get-folder-template', + folderPath + )) as GeneratedRpcApi['notes']['getFolderTemplate'], + exportPdf: ((input) => + invoke('notes:export-pdf', input)) as GeneratedRpcApi['notes']['exportPdf'], + exportHtml: ((input) => + invoke('notes:export-html', input)) as GeneratedRpcApi['notes']['exportHtml'], + getVersions: ((noteId) => + invoke('notes:get-versions', noteId)) as GeneratedRpcApi['notes']['getVersions'], + getVersion: ((snapshotId) => + invoke('notes:get-version', snapshotId)) as GeneratedRpcApi['notes']['getVersion'], + restoreVersion: ((snapshotId) => + invoke('notes:restore-version', snapshotId)) as GeneratedRpcApi['notes']['restoreVersion'], + deleteVersion: ((snapshotId) => + invoke('notes:delete-version', snapshotId)) as GeneratedRpcApi['notes']['deleteVersion'], + getPositions: ((folderPath) => + invoke('notes:get-positions', { folderPath })) as GeneratedRpcApi['notes']['getPositions'], + getAllPositions: (() => + invoke('notes:get-all-positions')) as GeneratedRpcApi['notes']['getAllPositions'], + reorder: ((folderPath, notePaths) => + invoke('notes:reorder', { folderPath, notePaths })) as GeneratedRpcApi['notes']['reorder'], + importFiles: ((sourcePaths, targetFolder) => + invoke('notes:import-files', { + sourcePaths, + targetFolder + })) as GeneratedRpcApi['notes']['importFiles'], + showImportDialog: (() => + invoke('notes:show-import-dialog')) as GeneratedRpcApi['notes']['showImportDialog'], + setLocalOnly: ((id, localOnly) => + invoke('notes:set-local-only', { + id, + localOnly + })) as GeneratedRpcApi['notes']['setLocalOnly'], + getLocalOnlyCount: (() => + invoke('notes:get-local-only-count')) as GeneratedRpcApi['notes']['getLocalOnlyCount'] }, tasks: { - create: ((input) => invoke("tasks:create", input)) as GeneratedRpcApi["tasks"]["create"], - get: ((id) => invoke("tasks:get", id)) as GeneratedRpcApi["tasks"]["get"], - update: ((input) => invoke("tasks:update", input)) as GeneratedRpcApi["tasks"]["update"], - delete: ((id) => invoke("tasks:delete", id)) as GeneratedRpcApi["tasks"]["delete"], - list: ((options) => invoke("tasks:list", options ?? {})) as GeneratedRpcApi["tasks"]["list"], - complete: ((input) => invoke("tasks:complete", input)) as GeneratedRpcApi["tasks"]["complete"], - uncomplete: ((id) => invoke("tasks:uncomplete", id)) as GeneratedRpcApi["tasks"]["uncomplete"], - archive: ((id) => invoke("tasks:archive", id)) as GeneratedRpcApi["tasks"]["archive"], - unarchive: ((id) => invoke("tasks:unarchive", id)) as GeneratedRpcApi["tasks"]["unarchive"], - move: ((input) => invoke("tasks:move", input)) as GeneratedRpcApi["tasks"]["move"], - reorder: ((taskIds, positions) => invoke("tasks:reorder", { taskIds, positions })) as GeneratedRpcApi["tasks"]["reorder"], - duplicate: ((id) => invoke("tasks:duplicate", id)) as GeneratedRpcApi["tasks"]["duplicate"], - getSubtasks: ((parentId) => invoke("tasks:get-subtasks", parentId)) as GeneratedRpcApi["tasks"]["getSubtasks"], - convertToSubtask: ((taskId, parentId) => invoke("tasks:convert-to-subtask", { taskId, parentId })) as GeneratedRpcApi["tasks"]["convertToSubtask"], - convertToTask: ((taskId) => invoke("tasks:convert-to-task", taskId)) as GeneratedRpcApi["tasks"]["convertToTask"], - createProject: ((input) => invoke("tasks:project-create", input)) as GeneratedRpcApi["tasks"]["createProject"], - getProject: ((id) => invoke("tasks:project-get", id)) as GeneratedRpcApi["tasks"]["getProject"], - updateProject: ((input) => invoke("tasks:project-update", input)) as GeneratedRpcApi["tasks"]["updateProject"], - deleteProject: ((id) => invoke("tasks:project-delete", id)) as GeneratedRpcApi["tasks"]["deleteProject"], - listProjects: (() => invoke("tasks:project-list")) as GeneratedRpcApi["tasks"]["listProjects"], - archiveProject: ((id) => invoke("tasks:project-archive", id)) as GeneratedRpcApi["tasks"]["archiveProject"], - reorderProjects: ((projectIds, positions) => invoke("tasks:project-reorder", { projectIds, positions })) as GeneratedRpcApi["tasks"]["reorderProjects"], - createStatus: ((input) => invoke("tasks:status-create", input)) as GeneratedRpcApi["tasks"]["createStatus"], - updateStatus: ((id, updates) => invoke("tasks:status-update", { id, ...updates })) as GeneratedRpcApi["tasks"]["updateStatus"], - deleteStatus: ((id) => invoke("tasks:status-delete", id)) as GeneratedRpcApi["tasks"]["deleteStatus"], - reorderStatuses: ((statusIds, positions) => invoke("tasks:status-reorder", { statusIds, positions })) as GeneratedRpcApi["tasks"]["reorderStatuses"], - listStatuses: ((projectId) => invoke("tasks:status-list", projectId)) as GeneratedRpcApi["tasks"]["listStatuses"], - getTags: (() => invoke("tasks:get-tags")) as GeneratedRpcApi["tasks"]["getTags"], - bulkComplete: ((ids) => invoke("tasks:bulk-complete", { ids })) as GeneratedRpcApi["tasks"]["bulkComplete"], - bulkDelete: ((ids) => invoke("tasks:bulk-delete", { ids })) as GeneratedRpcApi["tasks"]["bulkDelete"], - bulkMove: ((ids, projectId) => invoke("tasks:bulk-move", { ids, projectId })) as GeneratedRpcApi["tasks"]["bulkMove"], - bulkArchive: ((ids) => invoke("tasks:bulk-archive", { ids })) as GeneratedRpcApi["tasks"]["bulkArchive"], - getStats: (() => invoke("tasks:get-stats")) as GeneratedRpcApi["tasks"]["getStats"], - getToday: (() => invoke("tasks:get-today")) as GeneratedRpcApi["tasks"]["getToday"], - getUpcoming: ((days) => invoke("tasks:get-upcoming", { days: days ?? 7 })) as GeneratedRpcApi["tasks"]["getUpcoming"], - getOverdue: (() => invoke("tasks:get-overdue")) as GeneratedRpcApi["tasks"]["getOverdue"], - getLinkedTasks: ((noteId) => invoke("tasks:get-linked-tasks", noteId)) as GeneratedRpcApi["tasks"]["getLinkedTasks"], - seedPerformanceTest: (() => invoke("tasks:seed-performance-test")) as GeneratedRpcApi["tasks"]["seedPerformanceTest"], - seedDemo: (() => invoke("tasks:seed-demo")) as GeneratedRpcApi["tasks"]["seedDemo"], + create: ((input) => invoke('tasks:create', input)) as GeneratedRpcApi['tasks']['create'], + get: ((id) => invoke('tasks:get', id)) as GeneratedRpcApi['tasks']['get'], + update: ((input) => invoke('tasks:update', input)) as GeneratedRpcApi['tasks']['update'], + delete: ((id) => invoke('tasks:delete', id)) as GeneratedRpcApi['tasks']['delete'], + list: ((options) => invoke('tasks:list', options ?? {})) as GeneratedRpcApi['tasks']['list'], + complete: ((input) => + invoke('tasks:complete', input)) as GeneratedRpcApi['tasks']['complete'], + uncomplete: ((id) => + invoke('tasks:uncomplete', id)) as GeneratedRpcApi['tasks']['uncomplete'], + archive: ((id) => invoke('tasks:archive', id)) as GeneratedRpcApi['tasks']['archive'], + unarchive: ((id) => invoke('tasks:unarchive', id)) as GeneratedRpcApi['tasks']['unarchive'], + move: ((input) => invoke('tasks:move', input)) as GeneratedRpcApi['tasks']['move'], + reorder: ((taskIds, positions) => + invoke('tasks:reorder', { taskIds, positions })) as GeneratedRpcApi['tasks']['reorder'], + duplicate: ((id) => invoke('tasks:duplicate', id)) as GeneratedRpcApi['tasks']['duplicate'], + getSubtasks: ((parentId) => + invoke('tasks:get-subtasks', parentId)) as GeneratedRpcApi['tasks']['getSubtasks'], + convertToSubtask: ((taskId, parentId) => + invoke('tasks:convert-to-subtask', { + taskId, + parentId + })) as GeneratedRpcApi['tasks']['convertToSubtask'], + convertToTask: ((taskId) => + invoke('tasks:convert-to-task', taskId)) as GeneratedRpcApi['tasks']['convertToTask'], + createProject: ((input) => + invoke('tasks:project-create', input)) as GeneratedRpcApi['tasks']['createProject'], + getProject: ((id) => + invoke('tasks:project-get', id)) as GeneratedRpcApi['tasks']['getProject'], + updateProject: ((input) => + invoke('tasks:project-update', input)) as GeneratedRpcApi['tasks']['updateProject'], + deleteProject: ((id) => + invoke('tasks:project-delete', id)) as GeneratedRpcApi['tasks']['deleteProject'], + listProjects: (() => + invoke('tasks:project-list')) as GeneratedRpcApi['tasks']['listProjects'], + archiveProject: ((id) => + invoke('tasks:project-archive', id)) as GeneratedRpcApi['tasks']['archiveProject'], + reorderProjects: ((projectIds, positions) => + invoke('tasks:project-reorder', { + projectIds, + positions + })) as GeneratedRpcApi['tasks']['reorderProjects'], + createStatus: ((input) => + invoke('tasks:status-create', input)) as GeneratedRpcApi['tasks']['createStatus'], + updateStatus: ((id, updates) => + invoke('tasks:status-update', { + id, + ...updates + })) as GeneratedRpcApi['tasks']['updateStatus'], + deleteStatus: ((id) => + invoke('tasks:status-delete', id)) as GeneratedRpcApi['tasks']['deleteStatus'], + reorderStatuses: ((statusIds, positions) => + invoke('tasks:status-reorder', { + statusIds, + positions + })) as GeneratedRpcApi['tasks']['reorderStatuses'], + listStatuses: ((projectId) => + invoke('tasks:status-list', projectId)) as GeneratedRpcApi['tasks']['listStatuses'], + getTags: (() => invoke('tasks:get-tags')) as GeneratedRpcApi['tasks']['getTags'], + bulkComplete: ((ids) => + invoke('tasks:bulk-complete', { ids })) as GeneratedRpcApi['tasks']['bulkComplete'], + bulkDelete: ((ids) => + invoke('tasks:bulk-delete', { ids })) as GeneratedRpcApi['tasks']['bulkDelete'], + bulkMove: ((ids, projectId) => + invoke('tasks:bulk-move', { ids, projectId })) as GeneratedRpcApi['tasks']['bulkMove'], + bulkArchive: ((ids) => + invoke('tasks:bulk-archive', { ids })) as GeneratedRpcApi['tasks']['bulkArchive'], + getStats: (() => invoke('tasks:get-stats')) as GeneratedRpcApi['tasks']['getStats'], + getToday: (() => invoke('tasks:get-today')) as GeneratedRpcApi['tasks']['getToday'], + getUpcoming: ((days) => + invoke('tasks:get-upcoming', { + days: days ?? 7 + })) as GeneratedRpcApi['tasks']['getUpcoming'], + getOverdue: (() => invoke('tasks:get-overdue')) as GeneratedRpcApi['tasks']['getOverdue'], + getLinkedTasks: ((noteId) => + invoke('tasks:get-linked-tasks', noteId)) as GeneratedRpcApi['tasks']['getLinkedTasks'], + seedPerformanceTest: (() => + invoke('tasks:seed-performance-test')) as GeneratedRpcApi['tasks']['seedPerformanceTest'], + seedDemo: (() => invoke('tasks:seed-demo')) as GeneratedRpcApi['tasks']['seedDemo'] }, inbox: { - captureText: ((input) => invoke("inbox:capture-text", input)) as GeneratedRpcApi["inbox"]["captureText"], - captureLink: ((input) => invoke("inbox:capture-link", input)) as GeneratedRpcApi["inbox"]["captureLink"], - previewLink: ((url) => invoke("inbox:preview-link", url)) as GeneratedRpcApi["inbox"]["previewLink"], - captureImage: ((input) => invoke("inbox:capture-image", input)) as GeneratedRpcApi["inbox"]["captureImage"], - captureVoice: ((input) => invoke("inbox:capture-voice", input)) as GeneratedRpcApi["inbox"]["captureVoice"], - captureClip: ((input) => invoke("inbox:capture-clip", input)) as GeneratedRpcApi["inbox"]["captureClip"], - capturePdf: ((input) => invoke("inbox:capture-pdf", input)) as GeneratedRpcApi["inbox"]["capturePdf"], - get: ((id) => invoke("inbox:get", id)) as GeneratedRpcApi["inbox"]["get"], - list: ((options) => invoke("inbox:list", options ?? {})) as GeneratedRpcApi["inbox"]["list"], - update: ((input) => invoke("inbox:update", input)) as GeneratedRpcApi["inbox"]["update"], - archive: ((id) => invoke("inbox:archive", id)) as GeneratedRpcApi["inbox"]["archive"], - file: ((input) => invoke("inbox:file", input)) as GeneratedRpcApi["inbox"]["file"], - getSuggestions: ((itemId) => invoke("inbox:get-suggestions", itemId)) as GeneratedRpcApi["inbox"]["getSuggestions"], + captureText: ((input) => + invoke('inbox:capture-text', input)) as GeneratedRpcApi['inbox']['captureText'], + captureLink: ((input) => + invoke('inbox:capture-link', input)) as GeneratedRpcApi['inbox']['captureLink'], + previewLink: ((url) => + invoke('inbox:preview-link', url)) as GeneratedRpcApi['inbox']['previewLink'], + captureImage: ((input) => + invoke('inbox:capture-image', input)) as GeneratedRpcApi['inbox']['captureImage'], + captureVoice: ((input) => + invoke('inbox:capture-voice', input)) as GeneratedRpcApi['inbox']['captureVoice'], + captureClip: ((input) => + invoke('inbox:capture-clip', input)) as GeneratedRpcApi['inbox']['captureClip'], + capturePdf: ((input) => + invoke('inbox:capture-pdf', input)) as GeneratedRpcApi['inbox']['capturePdf'], + get: ((id) => invoke('inbox:get', id)) as GeneratedRpcApi['inbox']['get'], + list: ((options) => invoke('inbox:list', options ?? {})) as GeneratedRpcApi['inbox']['list'], + update: ((input) => invoke('inbox:update', input)) as GeneratedRpcApi['inbox']['update'], + archive: ((id) => invoke('inbox:archive', id)) as GeneratedRpcApi['inbox']['archive'], + file: ((input) => invoke('inbox:file', input)) as GeneratedRpcApi['inbox']['file'], + getSuggestions: ((itemId) => + invoke('inbox:get-suggestions', itemId)) as GeneratedRpcApi['inbox']['getSuggestions'], trackSuggestion: ((input) => invoke( - "inbox:track-suggestion", + 'inbox:track-suggestion', input.itemId, input.itemType, input.suggestedTo, @@ -140,59 +282,133 @@ export function createGeneratedRpcApi({ input.confidence, input.suggestedTags ?? [], input.actualTags ?? [] - )) as GeneratedRpcApi["inbox"]["trackSuggestion"], - convertToNote: ((itemId) => invoke("inbox:convert-to-note", itemId)) as GeneratedRpcApi["inbox"]["convertToNote"], - convertToTask: ((itemId) => invoke("inbox:convert-to-task", itemId)) as GeneratedRpcApi["inbox"]["convertToTask"], - linkToNote: ((itemId, noteId, tags) => invoke("inbox:link-to-note", itemId, noteId, tags ?? [])) as GeneratedRpcApi["inbox"]["linkToNote"], - addTag: ((itemId, tag) => invoke("inbox:add-tag", itemId, tag)) as GeneratedRpcApi["inbox"]["addTag"], - removeTag: ((itemId, tag) => invoke("inbox:remove-tag", itemId, tag)) as GeneratedRpcApi["inbox"]["removeTag"], - getTags: (() => invoke("inbox:get-tags")) as GeneratedRpcApi["inbox"]["getTags"], - snooze: ((input) => invoke("inbox:snooze", input)) as GeneratedRpcApi["inbox"]["snooze"], - unsnooze: ((itemId) => invoke("inbox:unsnooze", itemId)) as GeneratedRpcApi["inbox"]["unsnooze"], - getSnoozed: (() => invoke("inbox:get-snoozed")) as GeneratedRpcApi["inbox"]["getSnoozed"], - markViewed: ((itemId) => invoke("inbox:mark-viewed", itemId)) as GeneratedRpcApi["inbox"]["markViewed"], - bulkFile: ((input) => invoke("inbox:bulk-file", input)) as GeneratedRpcApi["inbox"]["bulkFile"], - bulkArchive: ((input) => invoke("inbox:bulk-archive", input)) as GeneratedRpcApi["inbox"]["bulkArchive"], - bulkTag: ((input) => invoke("inbox:bulk-tag", input)) as GeneratedRpcApi["inbox"]["bulkTag"], - bulkSnooze: ((input) => invoke("inbox:bulk-snooze", input)) as GeneratedRpcApi["inbox"]["bulkSnooze"], - fileAllStale: (() => invoke("inbox:file-all-stale")) as GeneratedRpcApi["inbox"]["fileAllStale"], - retryTranscription: ((itemId) => invoke("inbox:retry-transcription", itemId)) as GeneratedRpcApi["inbox"]["retryTranscription"], - retryMetadata: ((itemId) => invoke("inbox:retry-metadata", itemId)) as GeneratedRpcApi["inbox"]["retryMetadata"], - getStats: (() => invoke("inbox:get-stats")) as GeneratedRpcApi["inbox"]["getStats"], - getJobs: ((options) => invoke("inbox:get-jobs", options ?? {})) as GeneratedRpcApi["inbox"]["getJobs"], - getPatterns: (() => invoke("inbox:get-patterns")) as GeneratedRpcApi["inbox"]["getPatterns"], - getStaleThreshold: (() => invoke("inbox:get-stale-threshold")) as GeneratedRpcApi["inbox"]["getStaleThreshold"], - setStaleThreshold: ((days) => invoke("inbox:set-stale-threshold", days)) as GeneratedRpcApi["inbox"]["setStaleThreshold"], - listArchived: ((options) => invoke("inbox:list-archived", options ?? {})) as GeneratedRpcApi["inbox"]["listArchived"], - unarchive: ((id) => invoke("inbox:unarchive", id)) as GeneratedRpcApi["inbox"]["unarchive"], - deletePermanent: ((id) => invoke("inbox:delete-permanent", id)) as GeneratedRpcApi["inbox"]["deletePermanent"], - getFilingHistory: ((options) => invoke("inbox:get-filing-history", options ?? {})) as GeneratedRpcApi["inbox"]["getFilingHistory"], - undoFile: ((id) => invoke("inbox:undo-file", id)) as GeneratedRpcApi["inbox"]["undoFile"], - undoArchive: ((id) => invoke("inbox:undo-archive", id)) as GeneratedRpcApi["inbox"]["undoArchive"], + )) as GeneratedRpcApi['inbox']['trackSuggestion'], + convertToNote: ((itemId) => + invoke('inbox:convert-to-note', itemId)) as GeneratedRpcApi['inbox']['convertToNote'], + convertToTask: ((itemId) => + invoke('inbox:convert-to-task', itemId)) as GeneratedRpcApi['inbox']['convertToTask'], + linkToNote: ((itemId, noteId, tags) => + invoke( + 'inbox:link-to-note', + itemId, + noteId, + tags ?? [] + )) as GeneratedRpcApi['inbox']['linkToNote'], + addTag: ((itemId, tag) => + invoke('inbox:add-tag', itemId, tag)) as GeneratedRpcApi['inbox']['addTag'], + removeTag: ((itemId, tag) => + invoke('inbox:remove-tag', itemId, tag)) as GeneratedRpcApi['inbox']['removeTag'], + getTags: (() => invoke('inbox:get-tags')) as GeneratedRpcApi['inbox']['getTags'], + snooze: ((input) => invoke('inbox:snooze', input)) as GeneratedRpcApi['inbox']['snooze'], + unsnooze: ((itemId) => + invoke('inbox:unsnooze', itemId)) as GeneratedRpcApi['inbox']['unsnooze'], + getSnoozed: (() => invoke('inbox:get-snoozed')) as GeneratedRpcApi['inbox']['getSnoozed'], + markViewed: ((itemId) => + invoke('inbox:mark-viewed', itemId)) as GeneratedRpcApi['inbox']['markViewed'], + bulkFile: ((input) => + invoke('inbox:bulk-file', input)) as GeneratedRpcApi['inbox']['bulkFile'], + bulkArchive: ((input) => + invoke('inbox:bulk-archive', input)) as GeneratedRpcApi['inbox']['bulkArchive'], + bulkTag: ((input) => invoke('inbox:bulk-tag', input)) as GeneratedRpcApi['inbox']['bulkTag'], + bulkSnooze: ((input) => + invoke('inbox:bulk-snooze', input)) as GeneratedRpcApi['inbox']['bulkSnooze'], + fileAllStale: (() => + invoke('inbox:file-all-stale')) as GeneratedRpcApi['inbox']['fileAllStale'], + retryTranscription: ((itemId) => + invoke( + 'inbox:retry-transcription', + itemId + )) as GeneratedRpcApi['inbox']['retryTranscription'], + retryMetadata: ((itemId) => + invoke('inbox:retry-metadata', itemId)) as GeneratedRpcApi['inbox']['retryMetadata'], + getStats: (() => invoke('inbox:get-stats')) as GeneratedRpcApi['inbox']['getStats'], + getJobs: ((options) => + invoke('inbox:get-jobs', options ?? {})) as GeneratedRpcApi['inbox']['getJobs'], + getPatterns: (() => invoke('inbox:get-patterns')) as GeneratedRpcApi['inbox']['getPatterns'], + getStaleThreshold: (() => + invoke('inbox:get-stale-threshold')) as GeneratedRpcApi['inbox']['getStaleThreshold'], + setStaleThreshold: ((days) => + invoke('inbox:set-stale-threshold', days)) as GeneratedRpcApi['inbox']['setStaleThreshold'], + listArchived: ((options) => + invoke('inbox:list-archived', options ?? {})) as GeneratedRpcApi['inbox']['listArchived'], + unarchive: ((id) => invoke('inbox:unarchive', id)) as GeneratedRpcApi['inbox']['unarchive'], + deletePermanent: ((id) => + invoke('inbox:delete-permanent', id)) as GeneratedRpcApi['inbox']['deletePermanent'], + getFilingHistory: ((options) => + invoke( + 'inbox:get-filing-history', + options ?? {} + )) as GeneratedRpcApi['inbox']['getFilingHistory'], + undoFile: ((id) => invoke('inbox:undo-file', id)) as GeneratedRpcApi['inbox']['undoFile'], + undoArchive: ((id) => + invoke('inbox:undo-archive', id)) as GeneratedRpcApi['inbox']['undoArchive'] }, settings: { - get: ((key) => invoke("settings:get", key)) as GeneratedRpcApi["settings"]["get"], - set: ((key, value) => invoke("settings:set", { key, value })) as GeneratedRpcApi["settings"]["set"], - getJournalSettings: (() => invoke("settings:getJournalSettings")) as GeneratedRpcApi["settings"]["getJournalSettings"], - setJournalSettings: ((settings) => invoke("settings:setJournalSettings", settings)) as GeneratedRpcApi["settings"]["setJournalSettings"], - getAISettings: (() => invoke("settings:getAISettings")) as GeneratedRpcApi["settings"]["getAISettings"], - setAISettings: ((settings) => invoke("settings:setAISettings", settings)) as GeneratedRpcApi["settings"]["setAISettings"], - getVoiceTranscriptionSettings: (() => invoke("settings:getVoiceTranscriptionSettings")) as GeneratedRpcApi["settings"]["getVoiceTranscriptionSettings"], - setVoiceTranscriptionSettings: ((settings) => invoke("settings:setVoiceTranscriptionSettings", settings)) as GeneratedRpcApi["settings"]["setVoiceTranscriptionSettings"], - getVoiceModelStatus: (() => invoke("settings:getVoiceModelStatus")) as GeneratedRpcApi["settings"]["getVoiceModelStatus"], - downloadVoiceModel: (() => invoke("settings:downloadVoiceModel")) as GeneratedRpcApi["settings"]["downloadVoiceModel"], - getVoiceRecordingReadiness: (() => invoke("settings:getVoiceRecordingReadiness")) as GeneratedRpcApi["settings"]["getVoiceRecordingReadiness"], - getVoiceTranscriptionOpenAIKeyStatus: (() => invoke("settings:getVoiceTranscriptionOpenAIKeyStatus")) as GeneratedRpcApi["settings"]["getVoiceTranscriptionOpenAIKeyStatus"], - setVoiceTranscriptionOpenAIKey: ((apiKey) => invoke("settings:setVoiceTranscriptionOpenAIKey", { apiKey })) as GeneratedRpcApi["settings"]["setVoiceTranscriptionOpenAIKey"], - getAIModelStatus: (() => invoke("settings:getAIModelStatus")) as GeneratedRpcApi["settings"]["getAIModelStatus"], - loadAIModel: (() => invoke("settings:loadAIModel")) as GeneratedRpcApi["settings"]["loadAIModel"], - reindexEmbeddings: (() => invoke("settings:reindexEmbeddings")) as GeneratedRpcApi["settings"]["reindexEmbeddings"], - getTabSettings: (() => invoke("settings:getTabSettings")) as GeneratedRpcApi["settings"]["getTabSettings"], - setTabSettings: ((settings) => invoke("settings:setTabSettings", settings)) as GeneratedRpcApi["settings"]["setTabSettings"], - getNoteEditorSettings: (() => invoke("settings:getNoteEditorSettings")) as GeneratedRpcApi["settings"]["getNoteEditorSettings"], - setNoteEditorSettings: ((settings) => invoke("settings:setNoteEditorSettings", settings)) as GeneratedRpcApi["settings"]["setNoteEditorSettings"], + get: ((key) => invoke('settings:get', key)) as GeneratedRpcApi['settings']['get'], + set: ((key, value) => + invoke('settings:set', { key, value })) as GeneratedRpcApi['settings']['set'], + getJournalSettings: (() => + invoke('settings:getJournalSettings')) as GeneratedRpcApi['settings']['getJournalSettings'], + setJournalSettings: ((settings) => + invoke( + 'settings:setJournalSettings', + settings + )) as GeneratedRpcApi['settings']['setJournalSettings'], + getAISettings: (() => + invoke('settings:getAISettings')) as GeneratedRpcApi['settings']['getAISettings'], + setAISettings: ((settings) => + invoke('settings:setAISettings', settings)) as GeneratedRpcApi['settings']['setAISettings'], + getVoiceTranscriptionSettings: (() => + invoke( + 'settings:getVoiceTranscriptionSettings' + )) as GeneratedRpcApi['settings']['getVoiceTranscriptionSettings'], + setVoiceTranscriptionSettings: ((settings) => + invoke( + 'settings:setVoiceTranscriptionSettings', + settings + )) as GeneratedRpcApi['settings']['setVoiceTranscriptionSettings'], + getVoiceModelStatus: (() => + invoke( + 'settings:getVoiceModelStatus' + )) as GeneratedRpcApi['settings']['getVoiceModelStatus'], + downloadVoiceModel: (() => + invoke('settings:downloadVoiceModel')) as GeneratedRpcApi['settings']['downloadVoiceModel'], + getVoiceRecordingReadiness: (() => + invoke( + 'settings:getVoiceRecordingReadiness' + )) as GeneratedRpcApi['settings']['getVoiceRecordingReadiness'], + getVoiceTranscriptionOpenAIKeyStatus: (() => + invoke( + 'settings:getVoiceTranscriptionOpenAIKeyStatus' + )) as GeneratedRpcApi['settings']['getVoiceTranscriptionOpenAIKeyStatus'], + setVoiceTranscriptionOpenAIKey: ((apiKey) => + invoke('settings:setVoiceTranscriptionOpenAIKey', { + apiKey + })) as GeneratedRpcApi['settings']['setVoiceTranscriptionOpenAIKey'], + getAIModelStatus: (() => + invoke('settings:getAIModelStatus')) as GeneratedRpcApi['settings']['getAIModelStatus'], + loadAIModel: (() => + invoke('settings:loadAIModel')) as GeneratedRpcApi['settings']['loadAIModel'], + reindexEmbeddings: (() => + invoke('settings:reindexEmbeddings')) as GeneratedRpcApi['settings']['reindexEmbeddings'], + getTabSettings: (() => + invoke('settings:getTabSettings')) as GeneratedRpcApi['settings']['getTabSettings'], + setTabSettings: ((settings) => + invoke( + 'settings:setTabSettings', + settings + )) as GeneratedRpcApi['settings']['setTabSettings'], + getNoteEditorSettings: (() => + invoke( + 'settings:getNoteEditorSettings' + )) as GeneratedRpcApi['settings']['getNoteEditorSettings'], + setNoteEditorSettings: ((settings) => + invoke( + 'settings:setNoteEditorSettings', + settings + )) as GeneratedRpcApi['settings']['setNoteEditorSettings'], getStartupThemeSync: (() => { - const raw = invokeSync("settings:getStartupThemeSync") as + const raw = invokeSync('settings:getStartupThemeSync') as | 'light' | 'dark' | 'white' @@ -200,68 +416,180 @@ export function createGeneratedRpcApi({ | { theme?: 'light' | 'dark' | 'white' | 'system' } | null | undefined - return typeof raw === 'string' ? raw : raw?.theme ?? 'system' - }) as GeneratedRpcApi["settings"]["getStartupThemeSync"], - getGeneralSettings: (() => invoke("settings:getGeneralSettings")) as GeneratedRpcApi["settings"]["getGeneralSettings"], - setGeneralSettings: ((settings) => invoke("settings:setGeneralSettings", settings)) as GeneratedRpcApi["settings"]["setGeneralSettings"], - getEditorSettings: (() => invoke("settings:getEditorSettings")) as GeneratedRpcApi["settings"]["getEditorSettings"], - setEditorSettings: ((settings) => invoke("settings:setEditorSettings", settings)) as GeneratedRpcApi["settings"]["setEditorSettings"], - getTaskSettings: (() => invoke("settings:getTaskSettings")) as GeneratedRpcApi["settings"]["getTaskSettings"], - setTaskSettings: ((settings) => invoke("settings:setTaskSettings", settings)) as GeneratedRpcApi["settings"]["setTaskSettings"], - getKeyboardSettings: (() => invoke("settings:getKeyboardSettings")) as GeneratedRpcApi["settings"]["getKeyboardSettings"], - setKeyboardSettings: ((settings) => invoke("settings:setKeyboardSettings", settings)) as GeneratedRpcApi["settings"]["setKeyboardSettings"], - resetKeyboardSettings: (() => invoke("settings:resetKeyboardSettings")) as GeneratedRpcApi["settings"]["resetKeyboardSettings"], - getSyncSettings: (() => invoke("settings:getSyncSettings")) as GeneratedRpcApi["settings"]["getSyncSettings"], - setSyncSettings: ((settings) => invoke("settings:setSyncSettings", settings)) as GeneratedRpcApi["settings"]["setSyncSettings"], - getBackupSettings: (() => invoke("settings:getBackupSettings")) as GeneratedRpcApi["settings"]["getBackupSettings"], - setBackupSettings: ((settings) => invoke("settings:setBackupSettings", settings)) as GeneratedRpcApi["settings"]["setBackupSettings"], - getGraphSettings: (() => invoke("settings:getGraphSettings")) as GeneratedRpcApi["settings"]["getGraphSettings"], - setGraphSettings: ((settings) => invoke("settings:setGraphSettings", settings)) as GeneratedRpcApi["settings"]["setGraphSettings"], - registerGlobalCapture: (() => invoke("settings:registerGlobalCapture")) as GeneratedRpcApi["settings"]["registerGlobalCapture"], + return typeof raw === 'string' ? raw : (raw?.theme ?? 'system') + }) as GeneratedRpcApi['settings']['getStartupThemeSync'], + getGeneralSettings: (() => + invoke('settings:getGeneralSettings')) as GeneratedRpcApi['settings']['getGeneralSettings'], + setGeneralSettings: ((settings) => + invoke( + 'settings:setGeneralSettings', + settings + )) as GeneratedRpcApi['settings']['setGeneralSettings'], + getEditorSettings: (() => + invoke('settings:getEditorSettings')) as GeneratedRpcApi['settings']['getEditorSettings'], + setEditorSettings: ((settings) => + invoke( + 'settings:setEditorSettings', + settings + )) as GeneratedRpcApi['settings']['setEditorSettings'], + getTaskSettings: (() => + invoke('settings:getTaskSettings')) as GeneratedRpcApi['settings']['getTaskSettings'], + setTaskSettings: ((settings) => + invoke( + 'settings:setTaskSettings', + settings + )) as GeneratedRpcApi['settings']['setTaskSettings'], + getKeyboardSettings: (() => + invoke( + 'settings:getKeyboardSettings' + )) as GeneratedRpcApi['settings']['getKeyboardSettings'], + setKeyboardSettings: ((settings) => + invoke( + 'settings:setKeyboardSettings', + settings + )) as GeneratedRpcApi['settings']['setKeyboardSettings'], + resetKeyboardSettings: (() => + invoke( + 'settings:resetKeyboardSettings' + )) as GeneratedRpcApi['settings']['resetKeyboardSettings'], + getSyncSettings: (() => + invoke('settings:getSyncSettings')) as GeneratedRpcApi['settings']['getSyncSettings'], + setSyncSettings: ((settings) => + invoke( + 'settings:setSyncSettings', + settings + )) as GeneratedRpcApi['settings']['setSyncSettings'], + getBackupSettings: (() => + invoke('settings:getBackupSettings')) as GeneratedRpcApi['settings']['getBackupSettings'], + setBackupSettings: ((settings) => + invoke( + 'settings:setBackupSettings', + settings + )) as GeneratedRpcApi['settings']['setBackupSettings'], + getGraphSettings: (() => + invoke('settings:getGraphSettings')) as GeneratedRpcApi['settings']['getGraphSettings'], + setGraphSettings: ((settings) => + invoke( + 'settings:setGraphSettings', + settings + )) as GeneratedRpcApi['settings']['setGraphSettings'], + registerGlobalCapture: (() => + invoke( + 'settings:registerGlobalCapture' + )) as GeneratedRpcApi['settings']['registerGlobalCapture'] }, calendar: { - createEvent: ((input) => invoke("calendar:create-event", input)) as GeneratedRpcApi["calendar"]["createEvent"], - getEvent: ((id) => invoke("calendar:get-event", id)) as GeneratedRpcApi["calendar"]["getEvent"], - updateEvent: ((input) => invoke("calendar:update-event", input)) as GeneratedRpcApi["calendar"]["updateEvent"], - deleteEvent: ((id) => invoke("calendar:delete-event", id)) as GeneratedRpcApi["calendar"]["deleteEvent"], - listEvents: ((options) => invoke("calendar:list-events", options ?? {})) as GeneratedRpcApi["calendar"]["listEvents"], - getRange: ((input) => invoke("calendar:get-range", input)) as GeneratedRpcApi["calendar"]["getRange"], - listSources: ((options) => invoke("calendar:list-sources", options ?? {})) as GeneratedRpcApi["calendar"]["listSources"], - updateSourceSelection: ((input) => invoke("calendar:update-source-selection", input)) as GeneratedRpcApi["calendar"]["updateSourceSelection"], - getProviderStatus: ((input) => invoke("calendar:get-provider-status", input)) as GeneratedRpcApi["calendar"]["getProviderStatus"], - connectProvider: ((input) => invoke("calendar:connect-provider", input)) as GeneratedRpcApi["calendar"]["connectProvider"], - disconnectProvider: ((input) => invoke("calendar:disconnect-provider", input)) as GeneratedRpcApi["calendar"]["disconnectProvider"], - refreshProvider: ((input) => invoke("calendar:refresh-provider", input)) as GeneratedRpcApi["calendar"]["refreshProvider"], + createEvent: ((input) => + invoke('calendar:create-event', input)) as GeneratedRpcApi['calendar']['createEvent'], + getEvent: ((id) => + invoke('calendar:get-event', id)) as GeneratedRpcApi['calendar']['getEvent'], + updateEvent: ((input) => + invoke('calendar:update-event', input)) as GeneratedRpcApi['calendar']['updateEvent'], + deleteEvent: ((id) => + invoke('calendar:delete-event', id)) as GeneratedRpcApi['calendar']['deleteEvent'], + listEvents: ((options) => + invoke('calendar:list-events', options ?? {})) as GeneratedRpcApi['calendar']['listEvents'], + getRange: ((input) => + invoke('calendar:get-range', input)) as GeneratedRpcApi['calendar']['getRange'], + listSources: ((options) => + invoke( + 'calendar:list-sources', + options ?? {} + )) as GeneratedRpcApi['calendar']['listSources'], + updateSourceSelection: ((input) => + invoke( + 'calendar:update-source-selection', + input + )) as GeneratedRpcApi['calendar']['updateSourceSelection'], + getProviderStatus: ((input) => + invoke( + 'calendar:get-provider-status', + input + )) as GeneratedRpcApi['calendar']['getProviderStatus'], + connectProvider: ((input) => + invoke( + 'calendar:connect-provider', + input + )) as GeneratedRpcApi['calendar']['connectProvider'], + disconnectProvider: ((input) => + invoke( + 'calendar:disconnect-provider', + input + )) as GeneratedRpcApi['calendar']['disconnectProvider'], + refreshProvider: ((input) => + invoke( + 'calendar:refresh-provider', + input + )) as GeneratedRpcApi['calendar']['refreshProvider'] }, - onNoteCreated: ((callback) => subscribe("notes:created", callback)) as GeneratedRpcApi["onNoteCreated"], - onNoteUpdated: ((callback) => subscribe("notes:updated", callback)) as GeneratedRpcApi["onNoteUpdated"], - onNoteDeleted: ((callback) => subscribe("notes:deleted", callback)) as GeneratedRpcApi["onNoteDeleted"], - onNoteRenamed: ((callback) => subscribe("notes:renamed", callback)) as GeneratedRpcApi["onNoteRenamed"], - onNoteMoved: ((callback) => subscribe("notes:moved", callback)) as GeneratedRpcApi["onNoteMoved"], - onNoteExternalChange: ((callback) => subscribe("notes:external-change", callback)) as GeneratedRpcApi["onNoteExternalChange"], - onTagsChanged: ((callback) => subscribe("notes:tags-changed", callback)) as GeneratedRpcApi["onTagsChanged"], - onFolderConfigUpdated: ((callback) => subscribe("notes:folder-config-updated", callback)) as GeneratedRpcApi["onFolderConfigUpdated"], - onTaskCreated: ((callback) => subscribe("tasks:created", callback)) as GeneratedRpcApi["onTaskCreated"], - onTaskUpdated: ((callback) => subscribe("tasks:updated", callback)) as GeneratedRpcApi["onTaskUpdated"], - onTaskDeleted: ((callback) => subscribe("tasks:deleted", callback)) as GeneratedRpcApi["onTaskDeleted"], - onTaskCompleted: ((callback) => subscribe("tasks:completed", callback)) as GeneratedRpcApi["onTaskCompleted"], - onTaskMoved: ((callback) => subscribe("tasks:moved", callback)) as GeneratedRpcApi["onTaskMoved"], - onProjectCreated: ((callback) => subscribe("tasks:project-created", callback)) as GeneratedRpcApi["onProjectCreated"], - onProjectUpdated: ((callback) => subscribe("tasks:project-updated", callback)) as GeneratedRpcApi["onProjectUpdated"], - onProjectDeleted: ((callback) => subscribe("tasks:project-deleted", callback)) as GeneratedRpcApi["onProjectDeleted"], - onInboxCaptured: ((callback) => subscribe("inbox:captured", callback)) as GeneratedRpcApi["onInboxCaptured"], - onInboxUpdated: ((callback) => subscribe("inbox:updated", callback)) as GeneratedRpcApi["onInboxUpdated"], - onInboxArchived: ((callback) => subscribe("inbox:archived", callback)) as GeneratedRpcApi["onInboxArchived"], - onInboxFiled: ((callback) => subscribe("inbox:filed", callback)) as GeneratedRpcApi["onInboxFiled"], - onInboxSnoozed: ((callback) => subscribe("inbox:snoozed", callback)) as GeneratedRpcApi["onInboxSnoozed"], - onInboxSnoozeDue: ((callback) => subscribe("inbox:snooze-due", callback)) as GeneratedRpcApi["onInboxSnoozeDue"], - onInboxTranscriptionComplete: ((callback) => subscribe("inbox:transcription-complete", callback)) as GeneratedRpcApi["onInboxTranscriptionComplete"], - onInboxMetadataComplete: ((callback) => subscribe("inbox:metadata-complete", callback)) as GeneratedRpcApi["onInboxMetadataComplete"], - onInboxProcessingError: ((callback) => subscribe("inbox:processing-error", callback)) as GeneratedRpcApi["onInboxProcessingError"], - onSettingsChanged: ((callback) => subscribe("settings:changed", callback)) as GeneratedRpcApi["onSettingsChanged"], - onEmbeddingProgress: ((callback) => subscribe("settings:embeddingProgress", callback)) as GeneratedRpcApi["onEmbeddingProgress"], - onVoiceModelProgress: ((callback) => subscribe("settings:voiceModelProgress", callback)) as GeneratedRpcApi["onVoiceModelProgress"], - onSettingsOpenRequested: ((callback) => subscribe("settings:openSection", callback)) as GeneratedRpcApi["onSettingsOpenRequested"], - onCalendarChanged: ((callback) => subscribe("calendar:changed", callback)) as GeneratedRpcApi["onCalendarChanged"], + onNoteCreated: ((callback) => + subscribe('notes:created', callback)) as GeneratedRpcApi['onNoteCreated'], + onNoteUpdated: ((callback) => + subscribe('notes:updated', callback)) as GeneratedRpcApi['onNoteUpdated'], + onNoteDeleted: ((callback) => + subscribe('notes:deleted', callback)) as GeneratedRpcApi['onNoteDeleted'], + onNoteRenamed: ((callback) => + subscribe('notes:renamed', callback)) as GeneratedRpcApi['onNoteRenamed'], + onNoteMoved: ((callback) => + subscribe('notes:moved', callback)) as GeneratedRpcApi['onNoteMoved'], + onNoteExternalChange: ((callback) => + subscribe('notes:external-change', callback)) as GeneratedRpcApi['onNoteExternalChange'], + onTagsChanged: ((callback) => + subscribe('notes:tags-changed', callback)) as GeneratedRpcApi['onTagsChanged'], + onFolderConfigUpdated: ((callback) => + subscribe( + 'notes:folder-config-updated', + callback + )) as GeneratedRpcApi['onFolderConfigUpdated'], + onTaskCreated: ((callback) => + subscribe('tasks:created', callback)) as GeneratedRpcApi['onTaskCreated'], + onTaskUpdated: ((callback) => + subscribe('tasks:updated', callback)) as GeneratedRpcApi['onTaskUpdated'], + onTaskDeleted: ((callback) => + subscribe('tasks:deleted', callback)) as GeneratedRpcApi['onTaskDeleted'], + onTaskCompleted: ((callback) => + subscribe('tasks:completed', callback)) as GeneratedRpcApi['onTaskCompleted'], + onTaskMoved: ((callback) => + subscribe('tasks:moved', callback)) as GeneratedRpcApi['onTaskMoved'], + onProjectCreated: ((callback) => + subscribe('tasks:project-created', callback)) as GeneratedRpcApi['onProjectCreated'], + onProjectUpdated: ((callback) => + subscribe('tasks:project-updated', callback)) as GeneratedRpcApi['onProjectUpdated'], + onProjectDeleted: ((callback) => + subscribe('tasks:project-deleted', callback)) as GeneratedRpcApi['onProjectDeleted'], + onInboxCaptured: ((callback) => + subscribe('inbox:captured', callback)) as GeneratedRpcApi['onInboxCaptured'], + onInboxUpdated: ((callback) => + subscribe('inbox:updated', callback)) as GeneratedRpcApi['onInboxUpdated'], + onInboxArchived: ((callback) => + subscribe('inbox:archived', callback)) as GeneratedRpcApi['onInboxArchived'], + onInboxFiled: ((callback) => + subscribe('inbox:filed', callback)) as GeneratedRpcApi['onInboxFiled'], + onInboxSnoozed: ((callback) => + subscribe('inbox:snoozed', callback)) as GeneratedRpcApi['onInboxSnoozed'], + onInboxSnoozeDue: ((callback) => + subscribe('inbox:snooze-due', callback)) as GeneratedRpcApi['onInboxSnoozeDue'], + onInboxTranscriptionComplete: ((callback) => + subscribe( + 'inbox:transcription-complete', + callback + )) as GeneratedRpcApi['onInboxTranscriptionComplete'], + onInboxMetadataComplete: ((callback) => + subscribe('inbox:metadata-complete', callback)) as GeneratedRpcApi['onInboxMetadataComplete'], + onInboxProcessingError: ((callback) => + subscribe('inbox:processing-error', callback)) as GeneratedRpcApi['onInboxProcessingError'], + onSettingsChanged: ((callback) => + subscribe('settings:changed', callback)) as GeneratedRpcApi['onSettingsChanged'], + onEmbeddingProgress: ((callback) => + subscribe('settings:embeddingProgress', callback)) as GeneratedRpcApi['onEmbeddingProgress'], + onVoiceModelProgress: ((callback) => + subscribe( + 'settings:voiceModelProgress', + callback + )) as GeneratedRpcApi['onVoiceModelProgress'], + onSettingsOpenRequested: ((callback) => + subscribe('settings:openSection', callback)) as GeneratedRpcApi['onSettingsOpenRequested'], + onCalendarChanged: ((callback) => + subscribe('calendar:changed', callback)) as GeneratedRpcApi['onCalendarChanged'] } } diff --git a/apps/desktop/tests/e2e/fixtures.ts b/apps/desktop/tests/e2e/fixtures.ts index c1ec60a91..cf9150fc5 100644 --- a/apps/desktop/tests/e2e/fixtures.ts +++ b/apps/desktop/tests/e2e/fixtures.ts @@ -1,70 +1,55 @@ /** - * Playwright fixtures for Electron testing. + * Playwright fixtures for single-device Electron E2E tests. + * + * Delegates launch + teardown to utils/electron-lifecycle.ts, which provides + * bounded shutdown, SIGKILL fallback, and first-window retry. */ -import { test as base, _electron as electron, ElectronApplication, Page } from '@playwright/test' -import * as path from 'path' +import { test as base, ElectronApplication, Page } from '@playwright/test' import * as fs from 'fs' import * as os from 'os' +import * as path from 'path' + +import { + destroyElectronApp, + launchElectronWithWindow, + LaunchedElectron +} from './utils/electron-lifecycle' -// Extend base test with Electron fixtures export const test = base.extend<{ electronApp: ElectronApplication page: Page testVaultPath: string }>({ - // Create a test vault for each test testVaultPath: async ({}, use) => { const vaultPath = fs.mkdtempSync(path.join(os.tmpdir(), 'memry-e2e-')) - // Initialize vault structure fs.mkdirSync(path.join(vaultPath, '.memry'), { recursive: true }) fs.mkdirSync(path.join(vaultPath, 'notes'), { recursive: true }) fs.mkdirSync(path.join(vaultPath, 'journal'), { recursive: true }) await use(vaultPath) - // Cleanup fs.rmSync(vaultPath, { recursive: true, force: true }) }, - // Launch Electron application electronApp: async ({ testVaultPath }, use) => { - const isCI = !!process.env.CI - // Per-test user-data-dir keeps Chromium state (cookies, localStorage, - // GPU caches) isolated. Without this, Electron's shared - // `Application Support/Electron` dir can hold corrupted state from - // previous runs (e.g. an `[object Object]` theme value that crashes - // next-themes during renderer init), causing every test to fail. - const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'memry-userdata-')) - const app = await electron.launch({ - args: [ - ...(isCI ? ['--no-sandbox', '--disable-gpu'] : []), - `--user-data-dir=${userDataDir}`, - path.join(__dirname, '../../out/main/index.js') - ], - env: { - ...process.env, - NODE_ENV: 'test', - TEST_VAULT_PATH: testVaultPath, - ...(isCI && { ELECTRON_DISABLE_SANDBOX: '1' }) - } - }) + const launched = await launchElectronWithWindow({ testVaultPath }) - await use(app) + ;(launched.app as unknown as { __launched?: LaunchedElectron }).__launched = launched - await app.close() - fs.rmSync(userDataDir, { recursive: true, force: true }) + await use(launched.app) + + const dirs = [launched.userDataDir] + if (launched.resolvedUserDataDir !== launched.userDataDir) { + dirs.push(launched.resolvedUserDataDir) + } + await destroyElectronApp(launched.app, dirs) }, - // Get the main window page page: async ({ electronApp }, use) => { - // Wait for the first window - const page = await electronApp.firstWindow() - - // Wait for the app to be ready - await page.waitForLoadState('domcontentloaded') - + const launched = (electronApp as unknown as { __launched?: LaunchedElectron }).__launched + const page = launched?.page ?? (await electronApp.firstWindow({ timeout: 45_000 })) await use(page) } }) diff --git a/apps/desktop/tests/e2e/fixtures/sync-fixtures.ts b/apps/desktop/tests/e2e/fixtures/sync-fixtures.ts index 57225c669..3e041c395 100644 --- a/apps/desktop/tests/e2e/fixtures/sync-fixtures.ts +++ b/apps/desktop/tests/e2e/fixtures/sync-fixtures.ts @@ -1,7 +1,6 @@ import { test as base, expect as playwrightExpect, - _electron as electron, ElectronApplication, Page } from '@playwright/test' @@ -10,12 +9,11 @@ import * as fs from 'fs' import * as os from 'os' import * as path from 'path' import { waitForAppReady } from '../utils/electron-helpers' - -interface LaunchResult { - app: ElectronApplication - userDataDir: string - resolvedUserDataDir: string -} +import { + destroyElectronApp, + launchElectronWithWindow, + LaunchedElectron +} from '../utils/electron-lifecycle' function createTestVault(prefix: string): string { const vaultPath = fs.mkdtempSync(path.join(os.tmpdir(), prefix)) @@ -25,41 +23,6 @@ function createTestVault(prefix: string): string { return vaultPath } -async function launchElectronApp( - deviceId: string, - vaultPath: string, - syncServerUrl: string | null -): Promise { - const isCI = !!process.env.CI - const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), `memry-userdata-${deviceId}-`)) - const app = await electron.launch({ - args: [ - ...(isCI ? ['--no-sandbox', '--disable-gpu'] : []), - `--user-data-dir=${userDataDir}`, - path.join(__dirname, '../../../out/main/index.js') - ], - env: { - ...process.env, - NODE_ENV: 'test', - MEMRY_DEVICE: deviceId, - TEST_VAULT_PATH: vaultPath, - ...(syncServerUrl && { SYNC_SERVER_URL: syncServerUrl }), - ...(isCI && { ELECTRON_DISABLE_SANDBOX: '1' }) - } - }) - - const resolvedUserDataDir = await app.evaluate(({ app }) => app.getPath('userData')) - - return { app, userDataDir, resolvedUserDataDir } -} - -async function getReadyPage(app: ElectronApplication): Promise { - const page = await app.firstWindow() - await page.waitForLoadState('domcontentloaded') - await waitForAppReady(page) - return page -} - async function waitForVaultPath( page: Page, expectedVaultPath: string, @@ -113,37 +76,47 @@ export const test = base.extend<{ }, electronAppA: async ({ deviceIdA, vaultPathA, syncServerUrl }, use) => { - const { app, userDataDir, resolvedUserDataDir } = await launchElectronApp( - deviceIdA, - vaultPathA, + const launched = await launchElectronWithWindow({ + testVaultPath: vaultPathA, + deviceId: deviceIdA, syncServerUrl - ) - await use(app) - await app.close() - cleanupDir(userDataDir) - cleanupDir(resolvedUserDataDir) + }) + ;(launched.app as unknown as { __launched?: LaunchedElectron }).__launched = launched + await use(launched.app) + const dirs = [launched.userDataDir] + if (launched.resolvedUserDataDir !== launched.userDataDir) { + dirs.push(launched.resolvedUserDataDir) + } + await destroyElectronApp(launched.app, dirs) }, electronAppB: async ({ deviceIdB, vaultPathB, syncServerUrl }, use) => { - const { app, userDataDir, resolvedUserDataDir } = await launchElectronApp( - deviceIdB, - vaultPathB, + const launched = await launchElectronWithWindow({ + testVaultPath: vaultPathB, + deviceId: deviceIdB, syncServerUrl - ) - await use(app) - await app.close() - cleanupDir(userDataDir) - cleanupDir(resolvedUserDataDir) + }) + ;(launched.app as unknown as { __launched?: LaunchedElectron }).__launched = launched + await use(launched.app) + const dirs = [launched.userDataDir] + if (launched.resolvedUserDataDir !== launched.userDataDir) { + dirs.push(launched.resolvedUserDataDir) + } + await destroyElectronApp(launched.app, dirs) }, pageA: async ({ electronAppA, vaultPathA }, use) => { - const page = await getReadyPage(electronAppA) + const launched = (electronAppA as unknown as { __launched?: LaunchedElectron }).__launched + const page = launched?.page ?? (await electronAppA.firstWindow({ timeout: 45_000 })) + await waitForAppReady(page) await waitForVaultPath(page, vaultPathA) await use(page) }, pageB: async ({ electronAppB, vaultPathB }, use) => { - const page = await getReadyPage(electronAppB) + const launched = (electronAppB as unknown as { __launched?: LaunchedElectron }).__launched + const page = launched?.page ?? (await electronAppB.firstWindow({ timeout: 45_000 })) + await waitForAppReady(page) await waitForVaultPath(page, vaultPathB) await use(page) } diff --git a/apps/desktop/tests/e2e/utils/electron-lifecycle.ts b/apps/desktop/tests/e2e/utils/electron-lifecycle.ts new file mode 100644 index 000000000..a25529c60 --- /dev/null +++ b/apps/desktop/tests/e2e/utils/electron-lifecycle.ts @@ -0,0 +1,130 @@ +/** + * Shared Electron launch + teardown helpers for E2E fixtures. + * + * All helpers enforce: + * - a bounded graceful shutdown (SIGKILL fallback) so a hung main-process + * shutdown can never blow past Playwright's 60s teardown limit + * - a single retry on first-window timeout — an occasional stall on macOS + * leaves the main process alive but no window event fires; a clean relaunch + * always unblocks it + * - best-effort cleanup of both the requested user-data-dir and the + * Electron-resolved one (they can differ on macOS) + */ + +import { _electron as electron, ElectronApplication, Page } from '@playwright/test' +import * as fs from 'fs' +import * as os from 'os' +import * as path from 'path' + +const MAIN_ENTRY = path.join(__dirname, '../../../out/main/index.js') +const isCI = !!process.env.CI + +const FIRST_WINDOW_MS = 30_000 +const GRACEFUL_CLOSE_MS = 8_000 + +export interface LaunchOptions { + testVaultPath: string + deviceId?: string + syncServerUrl?: string | null + extraEnv?: Record +} + +export interface LaunchedElectron { + app: ElectronApplication + page: Page + userDataDir: string + resolvedUserDataDir: string + mainLogs: string[] +} + +export async function destroyElectronApp(app: ElectronApplication, dirs: string[]): Promise { + const child = app.process() + const graceful = app.close().catch(() => {}) + const timedOut = await Promise.race([ + graceful.then(() => false), + new Promise((resolve) => setTimeout(() => resolve(true), GRACEFUL_CLOSE_MS)) + ]) + if (timedOut && child && !child.killed) { + try { + child.kill('SIGKILL') + } catch { + // already exited + } + await new Promise((resolve) => setTimeout(resolve, 500)) + } + for (const dir of dirs) { + if (!dir) continue + try { + fs.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }) + } catch { + // best-effort cleanup + } + } +} + +async function launchOnce(opts: LaunchOptions): Promise { + const prefix = opts.deviceId ? `memry-userdata-${opts.deviceId}-` : 'memry-userdata-' + const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), prefix)) + const mainLogs: string[] = [] + + const env: Record = { + ...process.env, + NODE_ENV: 'test', + TEST_VAULT_PATH: opts.testVaultPath, + ...(opts.deviceId ? { MEMRY_DEVICE: opts.deviceId } : {}), + ...(opts.syncServerUrl ? { SYNC_SERVER_URL: opts.syncServerUrl } : {}), + ...(isCI && { ELECTRON_DISABLE_SANDBOX: '1' }), + ...(opts.extraEnv ?? {}) + } + + const app = await electron.launch({ + args: [ + ...(isCI ? ['--no-sandbox', '--disable-gpu'] : []), + `--user-data-dir=${userDataDir}`, + MAIN_ENTRY + ], + env + }) + + app.on('console', (msg) => { + try { + mainLogs.push(`[${msg.type()}] ${msg.text()}`) + } catch { + // ignore + } + }) + const child = app.process() + if (child?.stdout) { + child.stdout.on('data', (buf: Buffer) => mainLogs.push(`[stdout] ${buf.toString()}`)) + } + if (child?.stderr) { + child.stderr.on('data', (buf: Buffer) => mainLogs.push(`[stderr] ${buf.toString()}`)) + } + + try { + const page = await app.firstWindow({ timeout: FIRST_WINDOW_MS }) + await page.waitForLoadState('domcontentloaded') + let resolvedUserDataDir = userDataDir + try { + resolvedUserDataDir = await app.evaluate(({ app }) => app.getPath('userData')) + } catch { + // fall back to requested dir + } + return { app, page, userDataDir, resolvedUserDataDir, mainLogs } + } catch (err) { + await destroyElectronApp(app, [userDataDir]) + const tail = mainLogs.slice(-40).join('').slice(-4000) + const baseMsg = err instanceof Error ? err.message : String(err) + throw new Error(`${baseMsg}\n--- main process output ---\n${tail}\n--- end ---`) + } +} + +export async function launchElectronWithWindow(opts: LaunchOptions): Promise { + // Single attempt. Experimentally a retry loop here made the full suite + // dramatically slower (each failed test burned 2x the timeout) without + // increasing the pass rate — the underlying flakiness appears to be + // systemic (macOS resource pressure mid-run) rather than transient, so a + // local retry doesn't help. We rely on Playwright-level retries (configured + // via the `retries` option in playwright.config.ts) if we need them. + return launchOnce(opts) +}