From a3e183d63c09a8e8286a3851ab66dafbce1d96c4 Mon Sep 17 00:00:00 2001 From: Kevin De Porre Date: Mon, 9 Mar 2026 16:18:13 +0100 Subject: [PATCH 1/6] feat(examples): add Electron offline-first todo app with SQLite persistence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a complete Electron example demonstrating offline-first architecture with TanStack DB, combining SQLite persistence for collection data with a SQLite-backed offline transaction outbox. Key features: - SQLite persistence via IPC bridge (main process ↔ renderer) - Custom ElectronSQLiteStorageAdapter for the offline transactions outbox, ensuring pending mutations survive app restarts - Server state persisted to JSON file so data survives dev server restarts - fetchWithRetry for resilient network calls with exponential backoff - Reset button to clear all state (server, SQLite, outbox) - DevTools menu (Cmd+Shift+I) for testing offline mode - StrictMode-safe initialization (ref guard prevents ghost Web Lock from double-mount blocking leader election) Co-Authored-By: Claude Opus 4.6 --- examples/electron/offline-first/.gitignore | 1 + .../electron/offline-first/electron/main.ts | 161 +++++++++ .../offline-first/electron/preload.cjs | 13 + examples/electron/offline-first/index.html | 12 + examples/electron/offline-first/package.json | 44 +++ .../electron/offline-first/server/index.ts | 129 +++++++ examples/electron/offline-first/src/App.css | 236 +++++++++++++ examples/electron/offline-first/src/App.tsx | 53 +++ .../offline-first/src/components/TodoList.tsx | 168 +++++++++ .../electron/offline-first/src/db/todos.ts | 321 ++++++++++++++++++ examples/electron/offline-first/src/main.tsx | 13 + .../electron/offline-first/src/utils/api.ts | 71 ++++ .../offline-first/src/utils/queryClient.ts | 10 + examples/electron/offline-first/tsconfig.json | 19 ++ .../electron/offline-first/tsconfig.node.json | 11 + .../electron/offline-first/vite.config.ts | 7 + 16 files changed, 1269 insertions(+) create mode 100644 examples/electron/offline-first/.gitignore create mode 100644 examples/electron/offline-first/electron/main.ts create mode 100644 examples/electron/offline-first/electron/preload.cjs create mode 100644 examples/electron/offline-first/index.html create mode 100644 examples/electron/offline-first/package.json create mode 100644 examples/electron/offline-first/server/index.ts create mode 100644 examples/electron/offline-first/src/App.css create mode 100644 examples/electron/offline-first/src/App.tsx create mode 100644 examples/electron/offline-first/src/components/TodoList.tsx create mode 100644 examples/electron/offline-first/src/db/todos.ts create mode 100644 examples/electron/offline-first/src/main.tsx create mode 100644 examples/electron/offline-first/src/utils/api.ts create mode 100644 examples/electron/offline-first/src/utils/queryClient.ts create mode 100644 examples/electron/offline-first/tsconfig.json create mode 100644 examples/electron/offline-first/tsconfig.node.json create mode 100644 examples/electron/offline-first/vite.config.ts diff --git a/examples/electron/offline-first/.gitignore b/examples/electron/offline-first/.gitignore new file mode 100644 index 000000000..3d6335244 --- /dev/null +++ b/examples/electron/offline-first/.gitignore @@ -0,0 +1 @@ +server/todos.json diff --git a/examples/electron/offline-first/electron/main.ts b/examples/electron/offline-first/electron/main.ts new file mode 100644 index 000000000..9894c4039 --- /dev/null +++ b/examples/electron/offline-first/electron/main.ts @@ -0,0 +1,161 @@ +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { BrowserWindow, Menu, app, ipcMain } from 'electron' +import Database from 'better-sqlite3' +import { createNodeSQLitePersistence } from '@tanstack/db-node-sqlite-persisted-collection' +import { exposeElectronSQLitePersistence } from '@tanstack/db-electron-sqlite-persisted-collection' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +// Open SQLite database in Electron's user data directory +const dbPath = path.join(app.getPath('userData'), 'todos.sqlite') +console.log(`[Main] SQLite database path: ${dbPath}`) + +const database = new Database(dbPath) + +// Create persistence adapter from better-sqlite3 database +const persistence = createNodeSQLitePersistence({ database }) + +// Expose persistence over IPC so the renderer can use it +exposeElectronSQLitePersistence({ ipcMain, persistence }) + +// ── Key-value store for offline transaction outbox ── +// Uses a simple SQLite table so pending mutations survive app restarts. +database.exec(` + CREATE TABLE IF NOT EXISTS kv_store ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL + ) +`) + +ipcMain.handle('kv:get', (_e, key: string) => { + const row = database + .prepare('SELECT value FROM kv_store WHERE key = ?') + .get(key) as { value: string } | undefined + console.log(`[KV] get "${key}" → ${row ? `found (${row.value.length} chars)` : 'null'}`) + return row?.value ?? null +}) + +ipcMain.handle('kv:set', (_e, key: string, value: string) => { + console.log(`[KV] set "${key}" (${value.length} chars)`) + database + .prepare( + 'INSERT INTO kv_store (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value', + ) + .run(key, value) +}) + +ipcMain.handle('kv:delete', (_e, key: string) => { + console.log(`[KV] delete "${key}"`) + database.prepare('DELETE FROM kv_store WHERE key = ?').run(key) +}) + +ipcMain.handle('kv:keys', () => { + const rows = database + .prepare('SELECT key FROM kv_store') + .all() as Array<{ key: string }> + console.log(`[KV] keys → [${rows.map((r) => `"${r.key}"`).join(', ')}]`) + return rows.map((r) => r.key) +}) + +ipcMain.handle('kv:clear', () => { + database.exec('DELETE FROM kv_store') +}) + +// Reset: drop all tables from the SQLite database +ipcMain.handle('tanstack-db:reset-database', () => { + const tables = database + .prepare("SELECT name FROM sqlite_master WHERE type='table'") + .all() as Array<{ name: string }> + for (const { name } of tables) { + database.prepare(`DROP TABLE IF EXISTS "${name}"`).run() + } + console.log('[Main] Database reset — all tables dropped') +}) + +function createWindow() { + const preloadPath = path.join(__dirname, 'preload.cjs') + + const win = new BrowserWindow({ + width: 800, + height: 600, + webPreferences: { + contextIsolation: true, + nodeIntegration: false, + preload: preloadPath, + }, + }) + + // Dev: load Vite dev server. Prod: load built files. + if (process.env.NODE_ENV !== 'production') { + win.loadURL('http://localhost:5173') + } else { + win.loadFile(path.join(__dirname, '..', 'dist', 'index.html')) + } +} + +app.whenReady().then(() => { + // Add a menu with "New Window" so cross-window sync can be tested. + // BroadcastChannel only works between windows in the same Electron process, + // so opening a second `electron .` process won't sync — use this menu instead. + const menu = Menu.buildFromTemplate([ + { + label: app.name, + submenu: [{ role: 'quit' }], + }, + { + label: 'File', + submenu: [ + { + label: 'New Window', + accelerator: 'CmdOrCtrl+N', + click: () => createWindow(), + }, + { role: 'close' }, + ], + }, + { + label: 'View', + submenu: [ + { + label: 'Toggle DevTools', + accelerator: 'CmdOrCtrl+Shift+I', + click: (_item, win) => win?.webContents.toggleDevTools(), + }, + { role: 'reload' }, + { role: 'forceReload' }, + ], + }, + { + label: 'Edit', + submenu: [ + { role: 'undo' }, + { role: 'redo' }, + { type: 'separator' }, + { role: 'cut' }, + { role: 'copy' }, + { role: 'paste' }, + { role: 'selectAll' }, + ], + }, + ]) + Menu.setApplicationMenu(menu) + + createWindow() +}) + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit() + } +}) + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow() + } +}) + +app.on('before-quit', () => { + database.close() +}) diff --git a/examples/electron/offline-first/electron/preload.cjs b/examples/electron/offline-first/electron/preload.cjs new file mode 100644 index 000000000..466dceead --- /dev/null +++ b/examples/electron/offline-first/electron/preload.cjs @@ -0,0 +1,13 @@ +const { contextBridge, ipcRenderer } = require('electron') + +contextBridge.exposeInMainWorld('electronAPI', { + invoke: (channel, ...args) => ipcRenderer.invoke(channel, ...args), + resetDatabase: () => ipcRenderer.invoke('tanstack-db:reset-database'), + kv: { + get: (key) => ipcRenderer.invoke('kv:get', key), + set: (key, value) => ipcRenderer.invoke('kv:set', key, value), + delete: (key) => ipcRenderer.invoke('kv:delete', key), + keys: () => ipcRenderer.invoke('kv:keys'), + clear: () => ipcRenderer.invoke('kv:clear'), + }, +}) diff --git a/examples/electron/offline-first/index.html b/examples/electron/offline-first/index.html new file mode 100644 index 000000000..26f6b0626 --- /dev/null +++ b/examples/electron/offline-first/index.html @@ -0,0 +1,12 @@ + + + + + + TanStack DB – Electron Offline-First + + +
+ + + diff --git a/examples/electron/offline-first/package.json b/examples/electron/offline-first/package.json new file mode 100644 index 000000000..11ebc1b91 --- /dev/null +++ b/examples/electron/offline-first/package.json @@ -0,0 +1,44 @@ +{ + "name": "offline-first-electron", + "version": "1.0.0", + "private": true, + "type": "module", + "main": "electron/main.ts", + "scripts": { + "dev": "concurrently \"pnpm dev:renderer\" \"pnpm dev:server\" \"pnpm dev:electron\"", + "dev:renderer": "vite", + "dev:server": "tsx server/index.ts", + "dev:electron": "wait-on http://localhost:5173 && electron .", + "server": "tsx server/index.ts", + "postinstall": "prebuild-install --runtime electron --target 40.2.1 --arch arm64 || echo 'prebuild-install failed, try: npx @electron/rebuild'" + }, + "dependencies": { + "@tanstack/db-electron-sqlite-persisted-collection": "workspace:*", + "@tanstack/db-node-sqlite-persisted-collection": "workspace:*", + "@tanstack/offline-transactions": "workspace:*", + "@tanstack/query-db-collection": "workspace:*", + "@tanstack/react-db": "workspace:*", + "@tanstack/react-query": "^5.90.20", + "better-sqlite3": "^12.6.2", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "zod": "^3.25.76" + }, + "devDependencies": { + "@types/better-sqlite3": "^7.6.13", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.6", + "@types/react": "^19.2.13", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.3", + "@electron/rebuild": "^3.7.1", + "concurrently": "^9.1.2", + "cors": "^2.8.6", + "electron": "^40.2.1", + "express": "^5.2.1", + "tsx": "^4.21.0", + "typescript": "^5.9.2", + "vite": "^7.3.0", + "wait-on": "^8.0.3" + } +} diff --git a/examples/electron/offline-first/server/index.ts b/examples/electron/offline-first/server/index.ts new file mode 100644 index 000000000..001f59bcb --- /dev/null +++ b/examples/electron/offline-first/server/index.ts @@ -0,0 +1,129 @@ +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import cors from 'cors' +import express from 'express' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +const app = express() +const PORT = 3001 + +app.use(cors()) +app.use(express.json()) + +// Types +interface Todo { + id: string + text: string + completed: boolean + createdAt: string + updatedAt: string +} + +// Persist server state to a JSON file so data survives restarts +const TODOS_FILE = path.join(__dirname, 'todos.json') + +function loadTodos(): Map { + try { + const data = JSON.parse(fs.readFileSync(TODOS_FILE, 'utf-8')) as Array + return new Map(data.map((t) => [t.id, t])) + } catch { + return new Map() + } +} + +function saveTodos() { + fs.writeFileSync( + TODOS_FILE, + JSON.stringify(Array.from(todosStore.values()), null, 2), + ) +} + +const todosStore = loadTodos() + +// Helper function to generate IDs +function generateId(): string { + return Math.random().toString(36).substring(2) + Date.now().toString(36) +} + +// Simulate network delay +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) + +// GET all todos +app.get('/api/todos', async (_req, res) => { + console.log('GET /api/todos') + await delay(200) + const todos = Array.from(todosStore.values()).sort( + (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), + ) + res.json(todos) +}) + +// POST create todo — accepts client-generated ID +app.post('/api/todos', async (req, res) => { + console.log('POST /api/todos', req.body) + await delay(200) + + const { id, text, completed } = req.body + if (!text || text.trim() === '') { + return res.status(400).json({ error: 'Todo text is required' }) + } + + const now = new Date().toISOString() + const todo: Todo = { + id: id || generateId(), + text, + completed: completed ?? false, + createdAt: now, + updatedAt: now, + } + todosStore.set(todo.id, todo) + saveTodos() + res.status(201).json(todo) +}) + +// PUT update todo +app.put('/api/todos/:id', async (req, res) => { + console.log('PUT /api/todos/' + req.params.id, req.body) + await delay(200) + + const existing = todosStore.get(req.params.id) + if (!existing) { + return res.status(404).json({ error: 'Todo not found' }) + } + + const updated: Todo = { + ...existing, + ...req.body, + updatedAt: new Date().toISOString(), + } + todosStore.set(req.params.id, updated) + saveTodos() + res.json(updated) +}) + +// DELETE todo +app.delete('/api/todos/:id', async (req, res) => { + console.log('DELETE /api/todos/' + req.params.id) + await delay(200) + + if (!todosStore.delete(req.params.id)) { + return res.status(404).json({ error: 'Todo not found' }) + } + saveTodos() + res.json({ success: true }) +}) + +// DELETE all todos +app.delete('/api/todos', async (_req, res) => { + console.log('DELETE /api/todos (clear all)') + await delay(200) + todosStore.clear() + saveTodos() + res.json({ success: true }) +}) + +app.listen(PORT, '0.0.0.0', () => { + console.log(`Server running at http://0.0.0.0:${PORT}`) +}) diff --git a/examples/electron/offline-first/src/App.css b/examples/electron/offline-first/src/App.css new file mode 100644 index 000000000..5cec65194 --- /dev/null +++ b/examples/electron/offline-first/src/App.css @@ -0,0 +1,236 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + background: #f5f5f5; + color: #1a1a1a; +} + +.container { + max-width: 600px; + margin: 0 auto; + padding: 2rem 1rem; +} + +h1 { + font-size: 1.5rem; + margin-bottom: 1rem; + color: #111; +} + +.status-bar { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; + flex-wrap: wrap; +} + +.badge { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.625rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; +} + +.badge-online { + background: #dcfce7; + color: #166534; +} + +.badge-offline { + background: #fee2e2; + color: #991b1b; +} + +.badge-pending { + background: #fef3c7; + color: #92400e; +} + +.badge-count { + background: #e0e7ff; + color: #3730a3; +} + +.badge-offline-enabled { + background: #dbeafe; + color: #1e40af; +} + +.badge-offline-disabled { + background: #f3f4f6; + color: #6b7280; +} + +.error-bar { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.5rem 0.75rem; + margin-bottom: 1rem; + background: #fee2e2; + border: 1px solid #fecaca; + border-radius: 0.375rem; + font-size: 0.8rem; + color: #991b1b; +} + +.error-bar button { + background: none; + border: none; + color: #991b1b; + font-size: 1rem; + cursor: pointer; + padding: 0 0.25rem; +} + +.reset-btn { + margin-left: auto; + padding: 0.25rem 0.75rem; + background: white; + color: #dc2626; + border: 1px solid #dc2626; + border-radius: 0.375rem; + font-size: 0.75rem; + font-weight: 600; + cursor: pointer; +} + +.reset-btn:hover { + background: #dc2626; + color: white; +} + +.input-row { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; +} + +.todo-input { + flex: 1; + padding: 0.625rem 0.75rem; + border: 1px solid #d1d5db; + border-radius: 0.375rem; + font-size: 0.875rem; + outline: none; +} + +.todo-input:focus { + border-color: #6366f1; + box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2); +} + +.add-btn { + padding: 0.625rem 1rem; + background: #6366f1; + color: white; + border: none; + border-radius: 0.375rem; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; +} + +.add-btn:hover:not(:disabled) { + background: #4f46e5; +} + +.add-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.todo-list { + list-style: none; +} + +.todo-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + background: white; + border: 1px solid #e5e7eb; + border-radius: 0.375rem; + margin-bottom: 0.5rem; +} + +.todo-item.completed .todo-text { + text-decoration: line-through; + color: #9ca3af; +} + +.toggle-btn { + width: 1.5rem; + height: 1.5rem; + border: 2px solid #d1d5db; + border-radius: 50%; + background: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + color: #6366f1; + flex-shrink: 0; +} + +.completed .toggle-btn { + background: #6366f1; + border-color: #6366f1; + color: white; +} + +.todo-text { + flex: 1; + font-size: 0.875rem; +} + +.delete-btn { + background: none; + border: none; + color: #9ca3af; + font-size: 1.25rem; + cursor: pointer; + padding: 0 0.25rem; + line-height: 1; +} + +.delete-btn:hover { + color: #ef4444; +} + +.empty-message { + text-align: center; + color: #9ca3af; + padding: 2rem 0; +} + +.instructions { + margin-top: 2rem; + padding: 1rem; + background: #f0f0ff; + border-radius: 0.5rem; + font-size: 0.8rem; + color: #444; +} + +.instructions h3 { + margin-bottom: 0.5rem; + font-size: 0.875rem; +} + +.instructions ul { + padding-left: 1.25rem; +} + +.instructions li { + margin-bottom: 0.25rem; +} diff --git a/examples/electron/offline-first/src/App.tsx b/examples/electron/offline-first/src/App.tsx new file mode 100644 index 000000000..b41518349 --- /dev/null +++ b/examples/electron/offline-first/src/App.tsx @@ -0,0 +1,53 @@ +import { useEffect, useRef, useState } from 'react' +import { createTodos } from './db/todos' +import { TodoList } from './components/TodoList' +import './App.css' + +type TodosState = ReturnType + +export function App() { + const [todosState, setTodosState] = useState(null) + const [error, setError] = useState(null) + const initRef = useRef(false) + + useEffect(() => { + // Prevent double-initialization from React StrictMode. + // The offline executor acquires a Web Lock for leadership — disposing + // and re-creating it in the StrictMode mount→cleanup→mount cycle + // leaves a ghost lock that blocks the second executor from becoming leader. + if (initRef.current) return + initRef.current = true + + try { + const state = createTodos() + setTodosState(state) + } catch (err) { + console.error('Failed to initialize:', err) + setError(err instanceof Error ? err.message : String(err)) + } + }, []) + + if (error) { + return ( +
+

Initialization Error

+

{error}

+
+ ) + } + + if (!todosState) { + return ( +
+

Loading...

+
+ ) + } + + return ( + + ) +} diff --git a/examples/electron/offline-first/src/components/TodoList.tsx b/examples/electron/offline-first/src/components/TodoList.tsx new file mode 100644 index 000000000..436c50773 --- /dev/null +++ b/examples/electron/offline-first/src/components/TodoList.tsx @@ -0,0 +1,168 @@ +import { useCallback, useEffect, useState } from 'react' +import { useLiveQuery } from '@tanstack/react-db' +import { createTodoActions } from '../db/todos' +import { todoApi } from '../utils/api' +import type { createTodos } from '../db/todos' + +interface TodoListProps { + collection: ReturnType['collection'] + executor: ReturnType['executor'] +} + +export function TodoList({ collection, executor }: TodoListProps) { + const [inputText, setInputText] = useState('') + const [isOnline, setIsOnline] = useState(navigator.onLine) + const [pendingCount, setPendingCount] = useState(0) + const [error, setError] = useState(null) + const [actions] = useState(() => createTodoActions(executor)) + + // Monitor network status + useEffect(() => { + const handleOnline = () => { + setIsOnline(true) + executor.notifyOnline() + } + const handleOffline = () => setIsOnline(false) + + window.addEventListener('online', handleOnline) + window.addEventListener('offline', handleOffline) + return () => { + window.removeEventListener('online', handleOnline) + window.removeEventListener('offline', handleOffline) + } + }, [executor]) + + // Poll pending mutation count + useEffect(() => { + const interval = setInterval(() => { + setPendingCount(executor.getPendingCount()) + }, 100) + return () => clearInterval(interval) + }, [executor]) + + // Query all todos sorted by creation date + const { data: todos = [], isLoading } = useLiveQuery((query) => + query + .from({ todo: collection }) + .orderBy(({ todo }) => todo.createdAt, 'desc'), + ) + + const handleAddTodo = useCallback(() => { + const text = inputText.trim() + if (!text) return + try { + setError(null) + actions.addTodo(text) + setInputText('') + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to add todo') + } + }, [inputText, actions]) + + const handleKeyDown = useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter') handleAddTodo() + }, + [handleAddTodo], + ) + + if (isLoading) { + return ( +
+

Loading...

+
+ ) + } + + return ( +
+

TanStack DB – Electron Offline-First

+ +
+ + {isOnline ? 'Online' : 'Offline'} + + + {executor.isOfflineEnabled ? 'Offline Mode' : 'Online Only'} + + {pendingCount > 0 && ( + + {pendingCount} pending + + )} + + {todos.length} todo{todos.length !== 1 ? 's' : ''} + + +
+ + {error && ( +
+ {error} + +
+ )} + +
+ setInputText(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="What needs to be done?" + /> + +
+ +
    + {todos.map((todo) => ( +
  • + + {todo.text} + +
  • + ))} +
+ + {todos.length === 0 && ( +

No todos yet. Add one above!

+ )} + +
+

Try it out

+
    +
  • Persistence: Add todos, quit the app, reopen — data is still there
  • +
  • Multiple windows: Press Cmd+N (or File → New Window) to open a second window — each window syncs independently with the server
  • +
  • Offline mode: Stop the server (pnpm dev:server), add todos, restart — they sync automatically
  • +
+
+
+ ) +} diff --git a/examples/electron/offline-first/src/db/todos.ts b/examples/electron/offline-first/src/db/todos.ts new file mode 100644 index 000000000..b9e9d5012 --- /dev/null +++ b/examples/electron/offline-first/src/db/todos.ts @@ -0,0 +1,321 @@ +import { createCollection } from '@tanstack/react-db' +import { queryCollectionOptions } from '@tanstack/query-db-collection' +import { startOfflineExecutor } from '@tanstack/offline-transactions' +import { + createElectronSQLitePersistence, + persistedCollectionOptions, +} from '@tanstack/db-electron-sqlite-persisted-collection' +import { z } from 'zod' +import { queryClient } from '../utils/queryClient' +import type { StorageAdapter } from '@tanstack/offline-transactions' +import type { Todo } from '../utils/api' +import type { PendingMutation } from '@tanstack/db' + +// Declare the electronAPI exposed via preload +declare global { + interface Window { + electronAPI: { + invoke: (channel: string, ...args: Array) => Promise + resetDatabase: () => Promise + kv: { + get: (key: string) => Promise + set: (key: string, value: string) => Promise + delete: (key: string) => Promise + keys: () => Promise> + clear: () => Promise + } + } + } +} + +/** + * SQLite-backed storage adapter for the offline transactions outbox. + * Stores pending mutations in the main process SQLite database via IPC, + * so they survive app restarts (unlike IndexedDB in Electron). + */ +class ElectronSQLiteStorageAdapter implements StorageAdapter { + private prefix: string + + constructor(prefix = 'offline-tx:') { + this.prefix = prefix + } + + private prefixedKey(key: string): string { + return `${this.prefix}${key}` + } + + async get(key: string): Promise { + return window.electronAPI.kv.get(this.prefixedKey(key)) + } + + async set(key: string, value: string): Promise { + await window.electronAPI.kv.set(this.prefixedKey(key), value) + } + + async delete(key: string): Promise { + await window.electronAPI.kv.delete(this.prefixedKey(key)) + } + + async keys(): Promise> { + const allKeys = await window.electronAPI.kv.keys() + return allKeys + .filter((k) => k.startsWith(this.prefix)) + .map((k) => k.slice(this.prefix.length)) + } + + async clear(): Promise { + const keys = await this.keys() + for (const key of keys) { + await window.electronAPI.kv.delete(this.prefixedKey(key)) + } + } +} + +/** + * Fetch with retry and exponential backoff. + * Keeps retrying on network errors and non-OK responses so the app + * degrades gracefully when the server is temporarily unreachable. + */ +async function fetchWithRetry( + url: string, + options: RequestInit = {}, + retryConfig: { retries?: number; delay?: number; backoff?: number } = {}, +): Promise { + const { retries = 6, delay = 1000, backoff = 2 } = retryConfig + + for (let i = 0; i <= retries; i++) { + try { + const response = await fetch(url, options) + if (response.ok) return response + + console.warn( + `Fetch attempt ${i + 1} failed with status: ${response.status}. Retrying...`, + ) + } catch (error) { + console.error( + `Fetch attempt ${i + 1} failed due to a network error:`, + error, + ) + if (i >= retries) throw error + } + + if (i < retries) { + const currentDelay = delay * Math.pow(backoff, i) + await new Promise((resolve) => setTimeout(resolve, currentDelay)) + } + } + + throw new Error(`Failed to fetch ${url} after ${retries} retries.`) +} + +// Schema — use ISO strings for dates (SQLite-friendly) +const todoSchema = z.object({ + id: z.string(), + text: z.string(), + completed: z.boolean(), + createdAt: z.string(), + updatedAt: z.string(), +}) + +// Create persistence via IPC bridge to the main process SQLite database +const persistence = createElectronSQLitePersistence({ + invoke: window.electronAPI.invoke, +}) + +const BASE_URL = 'http://localhost:3001' + +// Compose: query sync wrapped in persisted collection +const queryOpts = queryCollectionOptions({ + id: 'todos-collection', + queryClient, + queryKey: ['todos'], + queryFn: async (): Promise> => { + const response = await fetchWithRetry(`${BASE_URL}/api/todos`) + if (!response.ok) { + throw new Error(`Failed to fetch todos: ${response.status}`) + } + return response.json() + }, + getKey: (item) => item.id, + schema: todoSchema, + refetchInterval: 3000, +}) + +// Sync function to push mutations to the backend +async function syncTodos({ + transaction, + idempotencyKey, +}: { + transaction: { mutations: Array } + idempotencyKey: string +}) { + const mutations = transaction.mutations + + console.log( + `[Sync] Processing ${mutations.length} mutations`, + idempotencyKey, + ) + + for (const mutation of mutations) { + try { + switch (mutation.type) { + case 'insert': { + const todoData = mutation.modified as Todo + const response = await fetchWithRetry(`${BASE_URL}/api/todos`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Idempotency-Key': idempotencyKey, + }, + body: JSON.stringify({ + id: todoData.id, + text: todoData.text, + completed: todoData.completed, + }), + }) + if (!response.ok) { + throw new Error(`Failed to sync insert: ${response.statusText}`) + } + break + } + + case 'update': { + const todoData = mutation.modified as Partial + const id = (mutation.modified as Todo).id + const response = await fetchWithRetry( + `${BASE_URL}/api/todos/${id}`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Idempotency-Key': idempotencyKey, + }, + body: JSON.stringify({ + text: todoData.text, + completed: todoData.completed, + }), + }, + ) + if (!response.ok) { + throw new Error(`Failed to sync update: ${response.statusText}`) + } + break + } + + case 'delete': { + const id = (mutation.original as Todo).id + const response = await fetchWithRetry( + `${BASE_URL}/api/todos/${id}`, + { + method: 'DELETE', + headers: { + 'Idempotency-Key': idempotencyKey, + }, + }, + ) + if (!response.ok) { + throw new Error(`Failed to sync delete: ${response.statusText}`) + } + break + } + } + } catch (error) { + console.error('[Sync] Error syncing mutation:', mutation, error) + throw error + } + } + + // Refresh the collection after sync + await collection.utils.refetch() +} + +// Create the persisted collection +const collection = createCollection( + persistedCollectionOptions({ + ...queryOpts, + persistence, + schemaVersion: 1, + }), +) + +// Create todos setup: collection + offline executor +export function createTodos() { + const executor = startOfflineExecutor({ + collections: { todos: collection }, + storage: new ElectronSQLiteStorageAdapter('offline-tx:'), + mutationFns: { + syncTodos, + }, + onLeadershipChange: (isLeader) => { + console.log('[Offline] Leadership changed:', isLeader) + }, + onStorageFailure: (diagnostic) => { + console.warn('[Offline] Storage failure:', diagnostic) + }, + }) + + console.log('[Offline] Executor mode:', executor.mode) + + // Log when initialization completes and pending transactions are loaded + executor.waitForInit().then(() => { + console.log('[Offline] Init complete. isOfflineEnabled:', executor.isOfflineEnabled) + console.log('[Offline] Pending count:', executor.getPendingCount()) + }).catch((err) => { + console.error('[Offline] Init failed:', err) + }) + + return { + collection, + executor, + close: () => { + executor.dispose() + }, + } +} + +// Helper to create offline actions +export function createTodoActions( + offline: ReturnType['executor'], +) { + const addTodo = offline.createOfflineAction({ + mutationFnName: 'syncTodos', + onMutate: (text: string) => { + const now = new Date().toISOString() + const newTodo: Todo = { + id: crypto.randomUUID(), + text: text.trim(), + completed: false, + createdAt: now, + updatedAt: now, + } + collection.insert(newTodo) + return newTodo + }, + }) + + const toggleTodo = offline.createOfflineAction({ + mutationFnName: 'syncTodos', + onMutate: (id: string) => { + const todo = collection.get(id) + if (!todo) return + collection.update(id, (draft) => { + draft.completed = !draft.completed + draft.updatedAt = new Date().toISOString() + }) + return todo + }, + }) + + const deleteTodo = offline.createOfflineAction({ + mutationFnName: 'syncTodos', + onMutate: (id: string) => { + const todo = collection.get(id) + if (todo) { + collection.delete(id) + } + return todo + }, + }) + + return { addTodo, toggleTodo, deleteTodo } +} diff --git a/examples/electron/offline-first/src/main.tsx b/examples/electron/offline-first/src/main.tsx new file mode 100644 index 000000000..dd8a06b61 --- /dev/null +++ b/examples/electron/offline-first/src/main.tsx @@ -0,0 +1,13 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import { QueryClientProvider } from '@tanstack/react-query' +import { queryClient } from './utils/queryClient' +import { App } from './App' + +createRoot(document.getElementById('root')!).render( + + + + + , +) diff --git a/examples/electron/offline-first/src/utils/api.ts b/examples/electron/offline-first/src/utils/api.ts new file mode 100644 index 000000000..732bb5dac --- /dev/null +++ b/examples/electron/offline-first/src/utils/api.ts @@ -0,0 +1,71 @@ +const BASE_URL = 'http://localhost:3001' + +export interface Todo { + id: string + text: string + completed: boolean + createdAt: string + updatedAt: string +} + +export const todoApi = { + async getAll(): Promise> { + const response = await fetch(`${BASE_URL}/api/todos`) + if (!response.ok) { + throw new Error(`Failed to fetch todos: ${response.status}`) + } + return response.json() + }, + + async create(data: { + id: string + text: string + completed?: boolean + }): Promise { + const response = await fetch(`${BASE_URL}/api/todos`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }) + if (!response.ok) { + throw new Error(`Failed to create todo: ${response.status}`) + } + return response.json() + }, + + async update( + id: string, + data: { text?: string; completed?: boolean }, + ): Promise { + const response = await fetch(`${BASE_URL}/api/todos/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }) + if (response.status === 404) return null + if (!response.ok) { + throw new Error(`Failed to update todo: ${response.status}`) + } + return response.json() + }, + + async delete(id: string): Promise { + const response = await fetch(`${BASE_URL}/api/todos/${id}`, { + method: 'DELETE', + }) + if (response.status === 404) return false + if (!response.ok) { + throw new Error(`Failed to delete todo: ${response.status}`) + } + return true + }, + + async deleteAll(): Promise { + const response = await fetch(`${BASE_URL}/api/todos`, { + method: 'DELETE', + }) + if (!response.ok) { + throw new Error(`Failed to delete all todos: ${response.status}`) + } + }, +} diff --git a/examples/electron/offline-first/src/utils/queryClient.ts b/examples/electron/offline-first/src/utils/queryClient.ts new file mode 100644 index 000000000..55c589ceb --- /dev/null +++ b/examples/electron/offline-first/src/utils/queryClient.ts @@ -0,0 +1,10 @@ +import { QueryClient } from '@tanstack/react-query' + +export const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60, // 1 minute + retry: 3, + }, + }, +}) diff --git a/examples/electron/offline-first/tsconfig.json b/examples/electron/offline-first/tsconfig.json new file mode 100644 index 000000000..26e53f511 --- /dev/null +++ b/examples/electron/offline-first/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": false, + "noUnusedParameters": false + }, + "include": ["src", "electron", "server", "vite.config.ts"] +} diff --git a/examples/electron/offline-first/tsconfig.node.json b/examples/electron/offline-first/tsconfig.node.json new file mode 100644 index 000000000..0c6b507fd --- /dev/null +++ b/examples/electron/offline-first/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "skipLibCheck": true, + "strict": true, + "noEmit": true + }, + "include": ["electron", "server", "vite.config.ts"] +} diff --git a/examples/electron/offline-first/vite.config.ts b/examples/electron/offline-first/vite.config.ts new file mode 100644 index 000000000..cecf58e7d --- /dev/null +++ b/examples/electron/offline-first/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + base: './', +}) From a248301e13d13b02083d94b49c91692510783df0 Mon Sep 17 00:00:00 2001 From: Kevin De Porre Date: Mon, 9 Mar 2026 16:20:37 +0100 Subject: [PATCH 2/6] chore: update pnpm-lock.yaml for Electron example Co-Authored-By: Claude Opus 4.6 --- pnpm-lock.yaml | 1008 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 721 insertions(+), 287 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 666bb0866..f7bb5ac74 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -193,6 +193,85 @@ importers: specifier: ^5.9.2 version: 5.9.3 + examples/electron/offline-first: + dependencies: + '@tanstack/db-electron-sqlite-persisted-collection': + specifier: workspace:* + version: link:../../../packages/db-electron-sqlite-persisted-collection + '@tanstack/db-node-sqlite-persisted-collection': + specifier: workspace:* + version: link:../../../packages/db-node-sqlite-persisted-collection + '@tanstack/offline-transactions': + specifier: workspace:* + version: link:../../../packages/offline-transactions + '@tanstack/query-db-collection': + specifier: workspace:* + version: link:../../../packages/query-db-collection + '@tanstack/react-db': + specifier: workspace:* + version: link:../../../packages/react-db + '@tanstack/react-query': + specifier: ^5.90.20 + version: 5.90.21(react@19.2.4) + better-sqlite3: + specifier: ^12.6.2 + version: 12.6.2 + react: + specifier: ^19.2.4 + version: 19.2.4 + react-dom: + specifier: ^19.2.4 + version: 19.2.4(react@19.2.4) + zod: + specifier: ^3.25.76 + version: 3.25.76 + devDependencies: + '@electron/rebuild': + specifier: ^3.7.1 + version: 3.7.2 + '@types/better-sqlite3': + specifier: ^7.6.13 + version: 7.6.13 + '@types/cors': + specifier: ^2.8.19 + version: 2.8.19 + '@types/express': + specifier: ^5.0.6 + version: 5.0.6 + '@types/react': + specifier: ^19.2.13 + version: 19.2.14 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react': + specifier: ^5.1.3 + version: 5.1.4(vite@7.3.1(@types/node@25.2.2)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.90.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)) + concurrently: + specifier: ^9.1.2 + version: 9.2.1 + cors: + specifier: ^2.8.6 + version: 2.8.6 + electron: + specifier: ^40.2.1 + version: 40.7.0 + express: + specifier: ^5.2.1 + version: 5.2.1 + tsx: + specifier: ^4.21.0 + version: 4.21.0 + typescript: + specifier: ^5.9.2 + version: 5.9.3 + vite: + specifier: ^7.3.0 + version: 7.3.1(@types/node@25.2.2)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.90.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1) + wait-on: + specifier: ^8.0.3 + version: 8.0.5 + examples/react-native/offline-transactions: dependencies: '@expo/metro-runtime': @@ -667,7 +746,7 @@ importers: version: 0.45.1(@op-engineering/op-sqlite@15.2.5(react-native@0.79.6(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.18.0)(better-sqlite3@12.6.2)(gel@2.1.1)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8) drizzle-zod: specifier: ^0.8.3 - version: 0.8.3(drizzle-orm@0.45.1(@op-engineering/op-sqlite@15.2.5(react-native@0.79.6(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.18.0)(better-sqlite3@12.6.2)(gel@2.1.1)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8))(zod@4.3.6) + version: 0.8.3(drizzle-orm@0.45.1(@op-engineering/op-sqlite@15.2.5(react-native@0.79.6(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.18.0)(better-sqlite3@12.6.2)(gel@2.1.1)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8))(zod@3.25.76) express: specifier: ^5.2.1 version: 5.2.1 @@ -976,6 +1055,28 @@ importers: specifier: ^3.2.4 version: 3.2.4(vitest@3.2.4) + packages/db-tauri-sqlite-persisted-collection: + dependencies: + '@tanstack/db-sqlite-persisted-collection-core': + specifier: workspace:* + version: link:../db-sqlite-persisted-collection-core + typescript: + specifier: '>=4.7' + version: 5.9.3 + devDependencies: + '@tauri-apps/plugin-sql': + specifier: ^2.2.0 + version: 2.3.2 + '@types/better-sqlite3': + specifier: ^7.6.13 + version: 7.6.13 + '@vitest/coverage-istanbul': + specifier: ^3.2.4 + version: 3.2.4(vitest@3.2.4) + better-sqlite3: + specifier: ^12.6.2 + version: 12.6.2 + packages/electric-db-collection: dependencies: '@electric-sql/client': @@ -2173,6 +2274,17 @@ packages: resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} engines: {node: '>=12'} + '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + resolution: {tarball: https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2} + version: 10.2.0-electron.1 + engines: {node: '>=12.13.0'} + hasBin: true + + '@electron/rebuild@3.7.2': + resolution: {integrity: sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==} + engines: {node: '>=12.13.0'} + hasBin: true + '@emnapi/core@1.7.1': resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} @@ -2202,12 +2314,6 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.27.3': resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} engines: {node: '>=18'} @@ -2232,12 +2338,6 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.27.3': resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} @@ -2262,12 +2362,6 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.27.3': resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} @@ -2292,12 +2386,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.27.3': resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} @@ -2322,12 +2410,6 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.27.3': resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} @@ -2352,12 +2434,6 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.27.3': resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} @@ -2382,12 +2458,6 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.27.3': resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} @@ -2412,12 +2482,6 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.27.3': resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} @@ -2442,12 +2506,6 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.27.3': resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} @@ -2472,12 +2530,6 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.27.3': resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} @@ -2502,12 +2554,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.27.3': resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} @@ -2532,12 +2578,6 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.27.3': resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} @@ -2562,12 +2602,6 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.27.3': resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} @@ -2592,12 +2626,6 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.27.3': resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} @@ -2622,12 +2650,6 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.27.3': resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} @@ -2652,12 +2674,6 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.27.3': resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} @@ -2682,12 +2698,6 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} @@ -2706,12 +2716,6 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.27.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} @@ -2736,12 +2740,6 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.27.3': resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} @@ -2760,12 +2758,6 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.27.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} @@ -2790,12 +2782,6 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.27.3': resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} @@ -2814,12 +2800,6 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/openharmony-arm64@0.27.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} @@ -2844,12 +2824,6 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.27.3': resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} @@ -2874,12 +2848,6 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.27.3': resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} @@ -2904,12 +2872,6 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.27.3': resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} @@ -2934,12 +2896,6 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.27.3': resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} @@ -3303,6 +3259,9 @@ packages: '@firebase/webchannel-wrapper@1.0.3': resolution: {integrity: sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==} + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + '@gerrit0/mini-shiki@3.13.1': resolution: {integrity: sha512-fDWM5QQc70jwBIt/WYMybdyXdyBmoJe7r1hpM+V/bHnyla79sygVDK2/LlVxIPc4n5FA3B5Wzt7AQH2+psNphg==} @@ -3315,6 +3274,26 @@ packages: engines: {node: '>=6'} hasBin: true + '@hapi/address@5.1.1': + resolution: {integrity: sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==} + engines: {node: '>=14.0.0'} + + '@hapi/formula@3.0.2': + resolution: {integrity: sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==} + + '@hapi/hoek@11.0.7': + resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==} + + '@hapi/pinpoint@2.0.1': + resolution: {integrity: sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==} + + '@hapi/tlds@1.1.6': + resolution: {integrity: sha512-xdi7A/4NZokvV0ewovme3aUO5kQhW9pQ2YD1hRqZGhhSi5rBv4usHYidVocXSi9eihYsznZxLtAiEYYUL6VBGw==} + engines: {node: '>=14.0.0'} + + '@hapi/topo@6.0.2': + resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} + '@hono/node-server@1.19.9': resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} engines: {node: '>=18.14.1'} @@ -3730,6 +3709,10 @@ packages: cpu: [x64] os: [win32] + '@malept/cross-spawn-promise@2.0.0': + resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==} + engines: {node: '>= 12.13.0'} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -3934,6 +3917,10 @@ packages: resolution: {integrity: sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==} engines: {node: ^20.17.0 || >=22.9.0} + '@npmcli/fs@2.1.2': + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + '@npmcli/fs@5.0.0': resolution: {integrity: sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==} engines: {node: ^20.17.0 || >=22.9.0} @@ -3947,6 +3934,11 @@ packages: engines: {node: ^20.17.0 || >=22.9.0} hasBin: true + '@npmcli/move-file@2.0.1': + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + '@npmcli/node-gyp@5.0.0': resolution: {integrity: sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==} engines: {node: ^20.17.0 || >=22.9.0} @@ -5053,6 +5045,12 @@ packages: peerDependencies: vite: ^6.0.0 || ^7.0.0 + '@tauri-apps/api@2.10.1': + resolution: {integrity: sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==} + + '@tauri-apps/plugin-sql@2.3.2': + resolution: {integrity: sha512-4VDXhcKXVpyh5KKpnTGAn6q2DikPHH+TXGh9ZDQzULmG/JEz1RDvzQStgBJKddiukRbYEZ8CGIA2kskx+T+PpA==} + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -5076,6 +5074,10 @@ packages: '@types/react-dom': optional: true + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + '@trpc/client@11.10.0': resolution: {integrity: sha512-h0s2AwDtuhS8INRb4hlo4z3RKCkarWqlOy+3ffJgrlDxzzW6aLUN+9nDrcN4huPje1Em15tbCOqhIc6oaKYTRw==} peerDependencies: @@ -5554,6 +5556,9 @@ packages: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + abbrev@4.0.0: resolution: {integrity: sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==} engines: {node: ^20.17.0 || >=22.9.0} @@ -5580,10 +5585,22 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + ajv-draft-04@1.0.0: resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} peerDependencies: @@ -5761,10 +5778,16 @@ packages: async-mutex@0.5.0: resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axios@1.13.6: + resolution: {integrity: sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -6046,6 +6069,10 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + cacache@20.0.3: resolution: {integrity: sha512-3pUp4e8hv07k1QlijZu6Kn7c9+ZpWWk4j3F8N3xPuCExULobqJydKYOTj1FTq58srkJsXvO7LbGAH4C0ZU3WGw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -6142,6 +6169,10 @@ packages: chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} @@ -6161,10 +6192,18 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + cli-cursor@2.1.0: resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} engines: {node: '>=4'} + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -6229,6 +6268,10 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + comlink@4.4.2: resolution: {integrity: sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==} @@ -6512,6 +6555,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -6533,10 +6580,6 @@ packages: engines: {node: '>=0.10'} hasBin: true - detect-libc@2.0.4: - resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} - engines: {node: '>=8'} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -6874,11 +6917,6 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} - engines: {node: '>=18'} - hasBin: true - esbuild@0.27.3: resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} engines: {node: '>=18'} @@ -7342,6 +7380,10 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + formatly@0.3.0: resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} engines: {node: '>=18.3.0'} @@ -7370,6 +7412,10 @@ packages: fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -7378,6 +7424,10 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + fs-minipass@3.0.3: resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -7492,6 +7542,11 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + global-agent@3.0.0: resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} engines: {node: '>=10.0'} @@ -7648,6 +7703,10 @@ packages: http-parser-js@0.5.10: resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -7660,6 +7719,10 @@ packages: resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} engines: {node: '>=10.19.0'} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -7672,6 +7735,9 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + husky@9.1.7: resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} @@ -7735,6 +7801,9 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -7869,10 +7938,17 @@ packages: resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==} engines: {node: '>=8'} + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + is-interactive@2.0.0: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -7955,6 +8031,10 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} @@ -8101,6 +8181,10 @@ packages: jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + joi@18.0.2: + resolution: {integrity: sha512-RuCOQMIt78LWnktPoeBL0GErkNaJPTBGcYuyaBvUOQSpcpcLfWrHPPihYdOGbV5pam9VTWbeoF7TsGiHugcjGA==} + engines: {node: '>= 20'} + jose@6.1.3: resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} @@ -8474,6 +8558,10 @@ packages: resolution: {integrity: sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==} engines: {node: '>=4'} + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + log-symbols@6.0.0: resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} engines: {node: '>=18'} @@ -8517,6 +8605,10 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} @@ -8537,6 +8629,10 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} + make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + make-fetch-happen@15.0.3: resolution: {integrity: sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -8702,6 +8798,10 @@ packages: resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} engines: {node: '>=4'} + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} @@ -8740,6 +8840,10 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -8747,10 +8851,18 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + minipass-collect@2.0.1: resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} engines: {node: '>=16 || 14 >=14.17'} + minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + minipass-fetch@5.0.1: resolution: {integrity: sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -8763,6 +8875,10 @@ packages: resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} engines: {node: '>=8'} + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + minipass-sized@2.0.0: resolution: {integrity: sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==} engines: {node: '>=8'} @@ -8771,10 +8887,18 @@ packages: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + minizlib@3.1.0: resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} engines: {node: '>= 18'} @@ -8917,6 +9041,9 @@ packages: node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + node-api-version@0.2.1: + resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -8945,6 +9072,11 @@ packages: node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + nopt@9.0.0: resolution: {integrity: sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -9066,6 +9198,10 @@ packages: resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} engines: {node: '>=4'} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} @@ -9090,6 +9226,10 @@ packages: resolution: {integrity: sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==} engines: {node: '>=6'} + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + ora@8.2.0: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} @@ -9143,6 +9283,10 @@ packages: resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} engines: {node: '>=6'} + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + p-map@7.0.4: resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} engines: {node: '>=18'} @@ -9416,6 +9560,10 @@ packages: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + proc-log@2.0.1: + resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + proc-log@4.2.0: resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -9432,6 +9580,14 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + promise-retry@2.0.1: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} @@ -9454,6 +9610,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + publint@0.3.17: resolution: {integrity: sha512-Q3NLegA9XM6usW+dYQRG1g9uEHiYUzcCVBJDJ7yMcWRqVU9LYZUWdqbwMZfmTCFC5PZLQpLAmhvRcQRl3exqkw==} engines: {node: '>=18'} @@ -9604,6 +9763,10 @@ packages: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} + read-binary-file-arch@1.0.6: + resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==} + hasBin: true + read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -9735,6 +9898,10 @@ packages: resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} engines: {node: '>=4'} + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + restore-cursor@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -10094,6 +10261,10 @@ packages: resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} engines: {node: '>=10.2.0'} + socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + socks-proxy-agent@8.0.5: resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} engines: {node: '>= 14'} @@ -10173,6 +10344,10 @@ packages: resolution: {integrity: sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==} engines: {node: ^20.17.0 || >=22.9.0} + ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + stable-hash-x@0.2.0: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} @@ -10392,6 +10567,11 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + tar@7.5.7: resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==} engines: {node: '>=18'} @@ -10694,10 +10874,18 @@ packages: resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} + unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + unique-filename@5.0.0: resolution: {integrity: sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg==} engines: {node: ^20.17.0 || >=22.9.0} + unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + unique-slug@6.0.0: resolution: {integrity: sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -10969,6 +11157,11 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + wait-on@8.0.5: + resolution: {integrity: sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag==} + engines: {node: '>=12.0.0'} + hasBin: true + walk-up-path@4.0.0: resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} engines: {node: 20 || >=22} @@ -12501,15 +12694,51 @@ snapshots: '@electron/get@2.0.3': dependencies: debug: 4.4.3 - env-paths: 2.2.1 - fs-extra: 8.1.0 + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 6.3.1 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.3 + glob: 8.1.0 + graceful-fs: 4.2.11 + make-fetch-happen: 10.2.1 + nopt: 6.0.0 + proc-log: 2.0.1 + semver: 7.7.4 + tar: 6.2.1 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + + '@electron/rebuild@3.7.2': + dependencies: + '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2 + '@malept/cross-spawn-promise': 2.0.0 + chalk: 4.1.2 + debug: 4.4.3 + detect-libc: 2.1.2 + fs-extra: 10.1.0 got: 11.8.6 - progress: 2.0.3 - semver: 6.3.1 - sumchecker: 3.0.1 - optionalDependencies: - global-agent: 3.0.0 + node-abi: 3.87.0 + node-api-version: 0.2.1 + ora: 5.4.1 + read-binary-file-arch: 1.0.6 + semver: 7.7.4 + tar: 6.2.1 + yargs: 17.7.2 transitivePeerDependencies: + - bluebird - supports-color '@emnapi/core@1.7.1': @@ -12544,9 +12773,6 @@ snapshots: '@esbuild/aix-ppc64@0.25.9': optional: true - '@esbuild/aix-ppc64@0.27.2': - optional: true - '@esbuild/aix-ppc64@0.27.3': optional: true @@ -12559,9 +12785,6 @@ snapshots: '@esbuild/android-arm64@0.25.9': optional: true - '@esbuild/android-arm64@0.27.2': - optional: true - '@esbuild/android-arm64@0.27.3': optional: true @@ -12574,9 +12797,6 @@ snapshots: '@esbuild/android-arm@0.25.9': optional: true - '@esbuild/android-arm@0.27.2': - optional: true - '@esbuild/android-arm@0.27.3': optional: true @@ -12589,9 +12809,6 @@ snapshots: '@esbuild/android-x64@0.25.9': optional: true - '@esbuild/android-x64@0.27.2': - optional: true - '@esbuild/android-x64@0.27.3': optional: true @@ -12604,9 +12821,6 @@ snapshots: '@esbuild/darwin-arm64@0.25.9': optional: true - '@esbuild/darwin-arm64@0.27.2': - optional: true - '@esbuild/darwin-arm64@0.27.3': optional: true @@ -12619,9 +12833,6 @@ snapshots: '@esbuild/darwin-x64@0.25.9': optional: true - '@esbuild/darwin-x64@0.27.2': - optional: true - '@esbuild/darwin-x64@0.27.3': optional: true @@ -12634,9 +12845,6 @@ snapshots: '@esbuild/freebsd-arm64@0.25.9': optional: true - '@esbuild/freebsd-arm64@0.27.2': - optional: true - '@esbuild/freebsd-arm64@0.27.3': optional: true @@ -12649,9 +12857,6 @@ snapshots: '@esbuild/freebsd-x64@0.25.9': optional: true - '@esbuild/freebsd-x64@0.27.2': - optional: true - '@esbuild/freebsd-x64@0.27.3': optional: true @@ -12664,9 +12869,6 @@ snapshots: '@esbuild/linux-arm64@0.25.9': optional: true - '@esbuild/linux-arm64@0.27.2': - optional: true - '@esbuild/linux-arm64@0.27.3': optional: true @@ -12679,9 +12881,6 @@ snapshots: '@esbuild/linux-arm@0.25.9': optional: true - '@esbuild/linux-arm@0.27.2': - optional: true - '@esbuild/linux-arm@0.27.3': optional: true @@ -12694,9 +12893,6 @@ snapshots: '@esbuild/linux-ia32@0.25.9': optional: true - '@esbuild/linux-ia32@0.27.2': - optional: true - '@esbuild/linux-ia32@0.27.3': optional: true @@ -12709,9 +12905,6 @@ snapshots: '@esbuild/linux-loong64@0.25.9': optional: true - '@esbuild/linux-loong64@0.27.2': - optional: true - '@esbuild/linux-loong64@0.27.3': optional: true @@ -12724,9 +12917,6 @@ snapshots: '@esbuild/linux-mips64el@0.25.9': optional: true - '@esbuild/linux-mips64el@0.27.2': - optional: true - '@esbuild/linux-mips64el@0.27.3': optional: true @@ -12739,9 +12929,6 @@ snapshots: '@esbuild/linux-ppc64@0.25.9': optional: true - '@esbuild/linux-ppc64@0.27.2': - optional: true - '@esbuild/linux-ppc64@0.27.3': optional: true @@ -12754,9 +12941,6 @@ snapshots: '@esbuild/linux-riscv64@0.25.9': optional: true - '@esbuild/linux-riscv64@0.27.2': - optional: true - '@esbuild/linux-riscv64@0.27.3': optional: true @@ -12769,9 +12953,6 @@ snapshots: '@esbuild/linux-s390x@0.25.9': optional: true - '@esbuild/linux-s390x@0.27.2': - optional: true - '@esbuild/linux-s390x@0.27.3': optional: true @@ -12784,9 +12965,6 @@ snapshots: '@esbuild/linux-x64@0.25.9': optional: true - '@esbuild/linux-x64@0.27.2': - optional: true - '@esbuild/linux-x64@0.27.3': optional: true @@ -12796,9 +12974,6 @@ snapshots: '@esbuild/netbsd-arm64@0.25.9': optional: true - '@esbuild/netbsd-arm64@0.27.2': - optional: true - '@esbuild/netbsd-arm64@0.27.3': optional: true @@ -12811,9 +12986,6 @@ snapshots: '@esbuild/netbsd-x64@0.25.9': optional: true - '@esbuild/netbsd-x64@0.27.2': - optional: true - '@esbuild/netbsd-x64@0.27.3': optional: true @@ -12823,9 +12995,6 @@ snapshots: '@esbuild/openbsd-arm64@0.25.9': optional: true - '@esbuild/openbsd-arm64@0.27.2': - optional: true - '@esbuild/openbsd-arm64@0.27.3': optional: true @@ -12838,9 +13007,6 @@ snapshots: '@esbuild/openbsd-x64@0.25.9': optional: true - '@esbuild/openbsd-x64@0.27.2': - optional: true - '@esbuild/openbsd-x64@0.27.3': optional: true @@ -12850,9 +13016,6 @@ snapshots: '@esbuild/openharmony-arm64@0.25.9': optional: true - '@esbuild/openharmony-arm64@0.27.2': - optional: true - '@esbuild/openharmony-arm64@0.27.3': optional: true @@ -12865,9 +13028,6 @@ snapshots: '@esbuild/sunos-x64@0.25.9': optional: true - '@esbuild/sunos-x64@0.27.2': - optional: true - '@esbuild/sunos-x64@0.27.3': optional: true @@ -12880,9 +13040,6 @@ snapshots: '@esbuild/win32-arm64@0.25.9': optional: true - '@esbuild/win32-arm64@0.27.2': - optional: true - '@esbuild/win32-arm64@0.27.3': optional: true @@ -12895,9 +13052,6 @@ snapshots: '@esbuild/win32-ia32@0.25.9': optional: true - '@esbuild/win32-ia32@0.27.2': - optional: true - '@esbuild/win32-ia32@0.27.3': optional: true @@ -12910,9 +13064,6 @@ snapshots: '@esbuild/win32-x64@0.25.9': optional: true - '@esbuild/win32-x64@0.27.2': - optional: true - '@esbuild/win32-x64@0.27.3': optional: true @@ -13558,6 +13709,8 @@ snapshots: '@firebase/webchannel-wrapper@1.0.3': {} + '@gar/promisify@1.1.3': {} + '@gerrit0/mini-shiki@3.13.1': dependencies: '@shikijs/engine-oniguruma': 3.13.0 @@ -13578,6 +13731,22 @@ snapshots: protobufjs: 7.5.4 yargs: 17.7.2 + '@hapi/address@5.1.1': + dependencies: + '@hapi/hoek': 11.0.7 + + '@hapi/formula@3.0.2': {} + + '@hapi/hoek@11.0.7': {} + + '@hapi/pinpoint@2.0.1': {} + + '@hapi/tlds@1.1.6': {} + + '@hapi/topo@6.0.2': + dependencies: + '@hapi/hoek': 11.0.7 + '@hono/node-server@1.19.9(hono@4.11.9)': dependencies: hono: 4.11.9 @@ -13965,6 +14134,10 @@ snapshots: '@lmdb/lmdb-win32-x64@3.4.2': optional: true + '@malept/cross-spawn-promise@2.0.0': + dependencies: + cross-spawn: 7.0.6 + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.28.4 @@ -14176,6 +14349,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@npmcli/fs@2.1.2': + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.7.4 + '@npmcli/fs@5.0.0': dependencies: semver: 7.7.4 @@ -14196,6 +14374,11 @@ snapshots: npm-bundled: 5.0.0 npm-normalize-package-bin: 5.0.0 + '@npmcli/move-file@2.0.1': + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + '@npmcli/node-gyp@5.0.0': {} '@npmcli/package-json@7.0.4': @@ -15474,6 +15657,12 @@ snapshots: - supports-color - typescript + '@tauri-apps/api@2.10.1': {} + + '@tauri-apps/plugin-sql@2.3.2': + dependencies: + '@tauri-apps/api': 2.10.1 + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.0 @@ -15504,6 +15693,8 @@ snapshots: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) + '@tootallnate/once@2.0.0': {} + '@trpc/client@11.10.0(@trpc/server@11.10.0(typescript@5.9.3))(typescript@5.9.3)': dependencies: '@trpc/server': 11.10.0(typescript@5.9.3) @@ -16078,6 +16269,8 @@ snapshots: jsonparse: 1.3.1 through: 2.3.8 + abbrev@1.1.1: {} + abbrev@4.0.0: {} abort-controller@3.0.0: @@ -16100,8 +16293,23 @@ snapshots: acorn@8.16.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + agent-base@7.1.4: {} + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + ajv-draft-04@1.0.0(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 @@ -16316,10 +16524,20 @@ snapshots: dependencies: tslib: 2.8.1 + asynckit@0.4.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 + axios@1.13.6: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axobject-query@4.1.0: {} babel-dead-code-elimination@1.0.12: @@ -16664,6 +16882,29 @@ snapshots: cac@6.7.14: {} + cacache@16.1.3: + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 9.0.1 + tar: 6.2.1 + unique-filename: 2.0.1 + transitivePeerDependencies: + - bluebird + cacache@20.0.3: dependencies: '@npmcli/fs': 5.0.0 @@ -16795,6 +17036,8 @@ snapshots: chownr@1.1.4: {} + chownr@2.0.0: {} + chownr@3.0.0: {} chrome-launcher@0.15.2: @@ -16821,10 +17064,16 @@ snapshots: ci-info@3.9.0: {} + clean-stack@2.2.0: {} + cli-cursor@2.1.0: dependencies: restore-cursor: 2.0.0 + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -16890,6 +17139,10 @@ snapshots: colorette@2.0.20: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + comlink@4.4.2: {} commander@11.1.0: @@ -17149,6 +17402,8 @@ snapshots: defu@6.1.4: {} + delayed-stream@1.0.0: {} + depd@2.0.0: {} dequal@2.0.3: {} @@ -17159,8 +17414,6 @@ snapshots: detect-libc@1.0.3: {} - detect-libc@2.0.4: {} - detect-libc@2.1.2: {} detect-node@2.1.0: @@ -17246,6 +17499,11 @@ snapshots: pg: 8.19.0 postgres: 3.4.8 + drizzle-zod@0.8.3(drizzle-orm@0.45.1(@op-engineering/op-sqlite@15.2.5(react-native@0.79.6(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.18.0)(better-sqlite3@12.6.2)(gel@2.1.1)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8))(zod@3.25.76): + dependencies: + drizzle-orm: 0.45.1(@op-engineering/op-sqlite@15.2.5(react-native@0.79.6(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.18.0)(better-sqlite3@12.6.2)(gel@2.1.1)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8) + zod: 3.25.76 + drizzle-zod@0.8.3(drizzle-orm@0.45.1(@op-engineering/op-sqlite@15.2.5(react-native@0.79.6(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.18.0)(better-sqlite3@12.6.2)(gel@2.1.1)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8))(zod@4.3.6): dependencies: drizzle-orm: 0.45.1(@op-engineering/op-sqlite@15.2.5(react-native@0.79.6(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.18.0)(better-sqlite3@12.6.2)(gel@2.1.1)(kysely@0.28.11)(pg@8.19.0)(postgres@3.4.8) @@ -17555,35 +17813,6 @@ snapshots: '@esbuild/win32-ia32': 0.25.9 '@esbuild/win32-x64': 0.25.9 - esbuild@0.27.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 - esbuild@0.27.3: optionalDependencies: '@esbuild/aix-ppc64': 0.27.3 @@ -18207,6 +18436,14 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + formatly@0.3.0: dependencies: fd-package-json: 2.0.0 @@ -18223,6 +18460,12 @@ snapshots: fs-constants@1.0.0: {} + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 @@ -18235,6 +18478,10 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + fs-minipass@3.0.3: dependencies: minipass: 7.1.2 @@ -18370,6 +18617,14 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.9 + once: 1.4.0 + global-agent@3.0.0: dependencies: boolean: 3.2.0 @@ -18526,6 +18781,14 @@ snapshots: http-parser-js@0.5.10: {} + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 @@ -18546,6 +18809,13 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 @@ -18557,6 +18827,10 @@ snapshots: human-signals@5.0.0: {} + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + husky@9.1.7: {} iconv-lite@0.4.24: @@ -18605,6 +18879,8 @@ snapshots: indent-string@4.0.0: {} + infer-owner@1.0.4: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -18728,8 +19004,12 @@ snapshots: dependencies: html-tags: 3.3.1 + is-interactive@1.0.0: {} + is-interactive@2.0.0: {} + is-lambda@1.0.1: {} + is-map@2.0.3: {} is-my-ip-valid@1.0.1: {} @@ -18805,6 +19085,8 @@ snapshots: dependencies: which-typed-array: 1.1.19 + is-unicode-supported@0.1.0: {} + is-unicode-supported@1.3.0: {} is-unicode-supported@2.1.0: {} @@ -18990,6 +19272,16 @@ snapshots: jju@1.4.0: {} + joi@18.0.2: + dependencies: + '@hapi/address': 5.1.1 + '@hapi/formula': 3.0.2 + '@hapi/hoek': 11.0.7 + '@hapi/pinpoint': 2.0.1 + '@hapi/tlds': 1.1.6 + '@hapi/topo': 6.0.2 + '@standard-schema/spec': 1.1.0 + jose@6.1.3: {} js-base64@3.7.8: {} @@ -19272,7 +19564,7 @@ snapshots: lightningcss@1.31.1: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 optionalDependencies: lightningcss-android-arm64: 1.31.1 lightningcss-darwin-arm64: 1.31.1 @@ -19379,6 +19671,11 @@ snapshots: dependencies: chalk: 2.4.2 + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + log-symbols@6.0.0: dependencies: chalk: 5.6.2 @@ -19428,6 +19725,8 @@ snapshots: dependencies: yallist: 4.0.0 + lru-cache@7.18.3: {} + lunr@2.3.9: {} lz-string@1.5.0: {} @@ -19450,6 +19749,28 @@ snapshots: dependencies: semver: 7.7.4 + make-fetch-happen@10.2.1: + dependencies: + agentkeepalive: 4.6.0 + cacache: 16.1.3 + http-cache-semantics: 4.2.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.4 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 9.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + make-fetch-happen@15.0.3: dependencies: '@npmcli/agent': 4.0.0 @@ -19721,6 +20042,8 @@ snapshots: mimic-fn@1.2.0: {} + mimic-fn@2.1.0: {} + mimic-fn@4.0.0: {} mimic-function@5.0.1: {} @@ -19757,16 +20080,32 @@ snapshots: dependencies: brace-expansion: 1.1.12 + minimatch@5.1.9: + dependencies: + brace-expansion: 2.0.2 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 minimist@1.2.8: {} + minipass-collect@1.0.2: + dependencies: + minipass: 3.3.6 + minipass-collect@2.0.1: dependencies: minipass: 7.1.2 + minipass-fetch@2.1.2: + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + minipass-fetch@5.0.1: dependencies: minipass: 7.1.2 @@ -19783,6 +20122,10 @@ snapshots: dependencies: minipass: 3.3.6 + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + minipass-sized@2.0.0: dependencies: minipass: 7.1.2 @@ -19791,8 +20134,15 @@ snapshots: dependencies: yallist: 4.0.0 + minipass@5.0.0: {} + minipass@7.1.2: {} + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + minizlib@3.1.0: dependencies: minipass: 7.1.2 @@ -19905,6 +20255,10 @@ snapshots: node-addon-api@7.1.1: optional: true + node-api-version@0.2.1: + dependencies: + semver: 7.7.4 + node-fetch@2.7.0(encoding@0.1.13): dependencies: whatwg-url: 5.0.0 @@ -19915,7 +20269,7 @@ snapshots: node-gyp-build-optional-packages@5.2.2: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 optional: true node-gyp@12.2.0: @@ -19937,6 +20291,10 @@ snapshots: node-releases@2.0.27: {} + nopt@6.0.0: + dependencies: + abbrev: 1.1.1 + nopt@9.0.0: dependencies: abbrev: 4.0.0 @@ -20072,6 +20430,10 @@ snapshots: dependencies: mimic-fn: 1.2.0 + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + onetime@6.0.0: dependencies: mimic-fn: 4.0.0 @@ -20109,6 +20471,18 @@ snapshots: strip-ansi: 5.2.0 wcwidth: 1.0.1 + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + ora@8.2.0: dependencies: chalk: 5.6.2 @@ -20183,6 +20557,10 @@ snapshots: p-map@2.1.0: {} + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + p-map@7.0.4: {} p-queue@6.6.2: @@ -20408,7 +20786,7 @@ snapshots: prebuild-install@7.1.3: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 expand-template: 2.0.3 github-from-package: 0.0.0 minimist: 1.2.8 @@ -20445,6 +20823,8 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + proc-log@2.0.1: {} + proc-log@4.2.0: {} proc-log@5.0.0: {} @@ -20453,6 +20833,8 @@ snapshots: progress@2.0.3: {} + promise-inflight@1.0.1: {} + promise-retry@2.0.1: dependencies: err-code: 2.0.3 @@ -20493,6 +20875,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} + publint@0.3.17: dependencies: '@publint/pack': 0.1.4 @@ -20673,6 +21057,12 @@ snapshots: react@19.2.4: {} + read-binary-file-arch@1.0.6: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 @@ -20815,6 +21205,11 @@ snapshots: onetime: 2.0.1 signal-exit: 3.0.7 + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -21353,6 +21748,14 @@ snapshots: - supports-color - utf-8-validate + socks-proxy-agent@7.0.0: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 @@ -21434,6 +21837,10 @@ snapshots: dependencies: minipass: 7.1.2 + ssri@9.0.1: + dependencies: + minipass: 3.3.6 + stable-hash-x@0.2.0: {} stack-utils@2.0.6: @@ -21687,6 +22094,15 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + tar@7.5.7: dependencies: '@isaacs/fs-minipass': 4.0.1 @@ -21826,7 +22242,7 @@ snapshots: tsx@4.21.0: dependencies: - esbuild: 0.27.2 + esbuild: 0.27.3 get-tsconfig: 4.10.1 optionalDependencies: fsevents: 2.3.3 @@ -21971,10 +22387,18 @@ snapshots: unicode-property-aliases-ecmascript@2.2.0: {} + unique-filename@2.0.1: + dependencies: + unique-slug: 3.0.0 + unique-filename@5.0.0: dependencies: unique-slug: 6.0.0 + unique-slug@3.0.0: + dependencies: + imurmurhash: 0.1.4 + unique-slug@6.0.0: dependencies: imurmurhash: 0.1.4 @@ -22161,7 +22585,7 @@ snapshots: vite@7.3.1(@types/node@25.2.2)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.90.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1): dependencies: - esbuild: 0.27.2 + esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 @@ -22257,6 +22681,16 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + wait-on@8.0.5: + dependencies: + axios: 1.13.6 + joi: 18.0.2 + lodash: 4.17.21 + minimist: 1.2.8 + rxjs: 7.8.2 + transitivePeerDependencies: + - debug + walk-up-path@4.0.0: {} walker@1.0.8: From 24c0a95b9b4fb6760bbab7b378aa67154fd0820a Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 15:21:53 +0000 Subject: [PATCH 3/6] ci: apply automated fixes --- .../electron/offline-first/electron/main.ts | 10 ++-- examples/electron/offline-first/src/App.css | 3 +- .../offline-first/src/components/TodoList.tsx | 47 +++++++++++---- .../electron/offline-first/src/db/todos.ts | 59 +++++++++---------- 4 files changed, 72 insertions(+), 47 deletions(-) diff --git a/examples/electron/offline-first/electron/main.ts b/examples/electron/offline-first/electron/main.ts index 9894c4039..b4cc574ca 100644 --- a/examples/electron/offline-first/electron/main.ts +++ b/examples/electron/offline-first/electron/main.ts @@ -32,7 +32,9 @@ ipcMain.handle('kv:get', (_e, key: string) => { const row = database .prepare('SELECT value FROM kv_store WHERE key = ?') .get(key) as { value: string } | undefined - console.log(`[KV] get "${key}" → ${row ? `found (${row.value.length} chars)` : 'null'}`) + console.log( + `[KV] get "${key}" → ${row ? `found (${row.value.length} chars)` : 'null'}`, + ) return row?.value ?? null }) @@ -51,9 +53,9 @@ ipcMain.handle('kv:delete', (_e, key: string) => { }) ipcMain.handle('kv:keys', () => { - const rows = database - .prepare('SELECT key FROM kv_store') - .all() as Array<{ key: string }> + const rows = database.prepare('SELECT key FROM kv_store').all() as Array<{ + key: string + }> console.log(`[KV] keys → [${rows.map((r) => `"${r.key}"`).join(', ')}]`) return rows.map((r) => r.key) }) diff --git a/examples/electron/offline-first/src/App.css b/examples/electron/offline-first/src/App.css index 5cec65194..cec1c9e62 100644 --- a/examples/electron/offline-first/src/App.css +++ b/examples/electron/offline-first/src/App.css @@ -5,7 +5,8 @@ } body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; color: #1a1a1a; } diff --git a/examples/electron/offline-first/src/components/TodoList.tsx b/examples/electron/offline-first/src/components/TodoList.tsx index 436c50773..20f60ab98 100644 --- a/examples/electron/offline-first/src/components/TodoList.tsx +++ b/examples/electron/offline-first/src/components/TodoList.tsx @@ -79,16 +79,18 @@ export function TodoList({ collection, executor }: TodoListProps) {

TanStack DB – Electron Offline-First

- + {isOnline ? 'Online' : 'Offline'} - + {executor.isOfflineEnabled ? 'Offline Mode' : 'Online Only'} {pendingCount > 0 && ( - - {pendingCount} pending - + {pendingCount} pending )} {todos.length} todo{todos.length !== 1 ? 's' : ''} @@ -96,7 +98,12 @@ export function TodoList({ collection, executor }: TodoListProps) {
    {todos.map((todo) => ( -
  • +