# Peek Core API Reference The `window.app` API is automatically injected into all `peek://` pages. This API provides access to window management, data storage, messaging, and shortcuts. ## Context Detection ```javascript // Check if running in peek:// context if (window.app) { // API available } // Source address of current page const source = window.location.toString(); // Context types: // - peek://app/... Core application pages // - peek://ext/{id}/... Extension pages ``` ## Window Management ### `window.app.window.open(url, options)` Open a new window. ```javascript const result = await window.app.window.open('peek://app/settings/settings.html', { key: 'settings', // Reuse window with same key width: 900, // Window width height: 650, // Window height x: 100, // X position y: 100, // Y position title: 'Settings', // Window title modal: true, // Modal behavior transparent: false, // Transparent background decorations: true, // Window decorations alwaysOnTop: false, // Stay on top visible: true, // Initially visible resizable: true, // Allow resize keepLive: false // Keep window alive when closed }); // Returns: { success: true, id: 'window_label' } ``` ### `window.app.window.close(id?)` Close a window. If no id, closes current window. ```javascript await window.app.window.close(); // Close current await window.app.window.close('settings'); // Close by id await window.app.window.close({ id: 'settings' }); // Object form ``` ### `window.app.window.hide(id?)` / `window.app.window.show(id?)` Toggle window visibility. ```javascript await window.app.window.hide('main'); await window.app.window.show('main'); ``` ### `window.app.window.focus(id?)` Bring window to front and focus it. ```javascript await window.app.window.focus('settings'); ``` ### `window.app.window.list()` List all open windows. ```javascript const result = await window.app.window.list(); // Returns: { // success: true, // data: [{ // id: 'main', // label: 'main', // url: 'peek://app/background.html', // source: 'peek://app/background.html', // visible: false, // focused: false // }, ...] // } ``` ### `window.app.window.exists(id)` Check if a window exists. ```javascript const result = await window.app.window.exists('settings'); // Returns: { success: true, data: true } ``` ## Datastore All datastore methods return `{ success: boolean, data?: any, error?: string }`. ### Addresses ```javascript // Add a new address const result = await window.app.datastore.addAddress('https://example.com', { title: 'Example', favicon: 'https://example.com/favicon.ico' }); // Returns: { success: true, data: { id: 'addr_123', ... } } // Get address by ID const addr = await window.app.datastore.getAddress('addr_123'); // Update address await window.app.datastore.updateAddress('addr_123', { title: 'New Title' }); // Query addresses const results = await window.app.datastore.queryAddresses({ uri: 'example.com', // Partial match limit: 10, offset: 0 }); ``` ### Visits ```javascript // Add a visit await window.app.datastore.addVisit('addr_123', { referrer: 'addr_456' }); // Query visits const visits = await window.app.datastore.queryVisits({ addressId: 'addr_123', limit: 50 }); ``` ### Tags ```javascript // Get or create a tag const tag = await window.app.datastore.getOrCreateTag('important'); // Returns: { success: true, data: { id: 'tag_123', name: 'important' } } // Tag an address await window.app.datastore.tagAddress('addr_123', 'tag_123'); // Untag an address await window.app.datastore.untagAddress('addr_123', 'tag_123'); // Get tags for an address const tags = await window.app.datastore.getAddressTags('addr_123'); ``` ### Generic Table Access ```javascript // Get all rows from a table const table = await window.app.datastore.getTable('extensions'); // Returns: { success: true, data: { row_id: { ... }, ... } } // Set a row await window.app.datastore.setRow('extensions', 'my-ext', { name: 'My Extension', enabled: true }); ``` ### Statistics ```javascript const stats = await window.app.datastore.getStats(); // Returns: { success: true, data: { // addresses: 150, // visits: 1200, // tags: 25 // }} ``` ## PubSub Messaging Cross-window communication via publish/subscribe. ### Scopes ```javascript window.app.scopes = { SYSTEM: 1, // System messages SELF: 2, // Same source only GLOBAL: 3 // All windows }; ``` ### `window.app.publish(topic, message, scope)` Publish a message. ```javascript window.app.publish('settings:changed', { theme: 'dark' }, window.app.scopes.GLOBAL); ``` ### `window.app.subscribe(topic, callback, scope)` Subscribe to messages. ```javascript window.app.subscribe('settings:changed', (msg) => { console.log('Settings changed:', msg.data); }, window.app.scopes.GLOBAL); ``` ## Keyboard Shortcuts ### `window.app.shortcuts.register(shortcut, callback, options)` Register a keyboard shortcut. ```javascript // Local shortcut (only when app focused) window.app.shortcuts.register('Command+K', () => { console.log('Command+K pressed'); }); // Global shortcut (works even when app not focused) window.app.shortcuts.register('Option+Space', () => { console.log('Global shortcut triggered'); }, { global: true }); ``` **Shortcut format:** - Modifiers: `Command`, `Control`, `Alt`, `Option`, `Shift`, `CommandOrControl` - Keys: `A-Z`, `0-9`, `F1-F12`, `Space`, `Enter`, `Escape`, `ArrowUp`, etc. - Examples: `Command+Shift+P`, `Alt+1`, `Option+ArrowDown` ### `window.app.shortcuts.unregister(shortcut, options)` Unregister a shortcut. ```javascript window.app.shortcuts.unregister('Command+K'); window.app.shortcuts.unregister('Option+Space', { global: true }); ``` ## Commands (Command Palette) Register commands that appear in the command palette. ### `window.app.commands.register(command)` ```javascript window.app.commands.register({ name: 'my-extension:do-thing', description: 'Do the thing', execute: () => { console.log('Doing the thing'); } }); ``` ### `window.app.commands.unregister(name)` ```javascript window.app.commands.unregister('my-extension:do-thing'); ``` ### `window.app.commands.getAll()` ```javascript const commands = await window.app.commands.getAll(); ``` ## Escape Handling Handle the ESC key to prevent window from closing. ```javascript window.app.escape.onEscape(() => { if (hasUnsavedChanges) { showConfirmDialog(); return { handled: true }; // Prevent close } return { handled: false }; // Allow close }); ``` ## Logging Log messages to the backend console. ```javascript window.app.log('Something happened', { detail: 'value' }); // Output in terminal: [peek://app/mypage.html] Something happened { detail: 'value' } ``` ## Debug Mode ```javascript if (window.app.debug) { console.log('Debug mode enabled'); } // Debug levels window.app.debugLevels = { BASIC: 1, FIRST_RUN: 2 }; window.app.debugLevel; // Current level ``` ## Extensions API Only available in core app pages (`peek://app/...`). ```javascript // Check permission if (window.app.extensions._hasPermission()) { const exts = await window.app.extensions.list(); } ``` ## Settings API Only available in extension pages (`peek://ext/{id}/...`). ```javascript // Get all settings const settings = await window.app.settings.get(); // Set all settings await window.app.settings.set({ theme: 'dark' }); // Get/set individual keys const theme = await window.app.settings.getKey('theme'); await window.app.settings.setKey('theme', 'light'); ``` ## Response Format All async API methods return a consistent response format: ```javascript { success: true, // Operation succeeded data: any, // Result data (if applicable) error: string // Error message (if success: false) } ``` Always check `success` before using `data`: ```javascript const result = await window.app.datastore.getAddress(id); if (result.success) { console.log(result.data); } else { console.error(result.error); } ```