diff --git a/apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts b/apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts index 110fa26c..2e22537e 100644 --- a/apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts +++ b/apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts @@ -11,6 +11,7 @@ import { Lightbulb, Brain, Network, + Settings, } from 'lucide-react'; import type { NavSection, NavItem } from '../types'; import type { KeyboardShortcut } from '@/hooks/use-keyboard-shortcuts'; @@ -32,6 +33,7 @@ interface UseNavigationProps { agent: string; terminal: string; settings: string; + projectSettings: string; ideation: string; githubIssues: string; githubPrs: string; @@ -121,6 +123,12 @@ export function useNavigation({ icon: Brain, shortcut: shortcuts.memory, }, + { + id: 'project-settings', + label: 'Settings', + icon: Settings, + shortcut: shortcuts.projectSettings, + }, ]; // Filter out hidden items diff --git a/apps/ui/src/components/ui/shell-syntax-editor.tsx b/apps/ui/src/components/ui/shell-syntax-editor.tsx index 159123c4..c405309a 100644 --- a/apps/ui/src/components/ui/shell-syntax-editor.tsx +++ b/apps/ui/src/components/ui/shell-syntax-editor.tsx @@ -70,8 +70,7 @@ const editorTheme = EditorView.theme({ backgroundColor: 'oklch(0.55 0.25 265 / 0.3)', }, '.cm-activeLine': { - backgroundColor: 'var(--accent)', - opacity: '0.3', + backgroundColor: 'transparent', }, '.cm-line': { padding: '0 0.25rem', @@ -114,7 +113,7 @@ export function ShellSyntaxEditor({ }: ShellSyntaxEditorProps) { return (
diff --git a/apps/ui/src/components/views/project-settings-view/components/project-settings-navigation.tsx b/apps/ui/src/components/views/project-settings-view/components/project-settings-navigation.tsx new file mode 100644 index 00000000..1c06dad3 --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/components/project-settings-navigation.tsx @@ -0,0 +1,122 @@ +import { X } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { Button } from '@/components/ui/button'; +import { PROJECT_SETTINGS_NAV_ITEMS } from '../config/navigation'; +import type { ProjectSettingsViewId } from '../hooks/use-project-settings-view'; + +interface ProjectSettingsNavigationProps { + activeSection: ProjectSettingsViewId; + onNavigate: (sectionId: ProjectSettingsViewId) => void; + isOpen?: boolean; + onClose?: () => void; +} + +export function ProjectSettingsNavigation({ + activeSection, + onNavigate, + isOpen = true, + onClose, +}: ProjectSettingsNavigationProps) { + return ( + <> + {/* Mobile backdrop overlay - only shown when isOpen is true on mobile */} + {isOpen && ( +
+ )} + + {/* Navigation sidebar */} + + + ); +} diff --git a/apps/ui/src/components/views/project-settings-view/config/navigation.ts b/apps/ui/src/components/views/project-settings-view/config/navigation.ts new file mode 100644 index 00000000..7f052ef5 --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/config/navigation.ts @@ -0,0 +1,16 @@ +import type { LucideIcon } from 'lucide-react'; +import { User, GitBranch, Palette, AlertTriangle } from 'lucide-react'; +import type { ProjectSettingsViewId } from '../hooks/use-project-settings-view'; + +export interface ProjectNavigationItem { + id: ProjectSettingsViewId; + label: string; + icon: LucideIcon; +} + +export const PROJECT_SETTINGS_NAV_ITEMS: ProjectNavigationItem[] = [ + { id: 'identity', label: 'Identity', icon: User }, + { id: 'worktrees', label: 'Worktrees', icon: GitBranch }, + { id: 'theme', label: 'Theme', icon: Palette }, + { id: 'danger', label: 'Danger Zone', icon: AlertTriangle }, +]; diff --git a/apps/ui/src/components/views/project-settings-view/hooks/index.ts b/apps/ui/src/components/views/project-settings-view/hooks/index.ts new file mode 100644 index 00000000..023eca9e --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/hooks/index.ts @@ -0,0 +1 @@ +export { useProjectSettingsView, type ProjectSettingsViewId } from './use-project-settings-view'; diff --git a/apps/ui/src/components/views/project-settings-view/hooks/use-project-settings-view.ts b/apps/ui/src/components/views/project-settings-view/hooks/use-project-settings-view.ts new file mode 100644 index 00000000..19faf5e3 --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/hooks/use-project-settings-view.ts @@ -0,0 +1,22 @@ +import { useState, useCallback } from 'react'; + +export type ProjectSettingsViewId = 'identity' | 'theme' | 'worktrees' | 'danger'; + +interface UseProjectSettingsViewOptions { + initialView?: ProjectSettingsViewId; +} + +export function useProjectSettingsView({ + initialView = 'identity', +}: UseProjectSettingsViewOptions = {}) { + const [activeView, setActiveView] = useState(initialView); + + const navigateTo = useCallback((viewId: ProjectSettingsViewId) => { + setActiveView(viewId); + }, []); + + return { + activeView, + navigateTo, + }; +} diff --git a/apps/ui/src/components/views/project-settings-view/index.ts b/apps/ui/src/components/views/project-settings-view/index.ts new file mode 100644 index 00000000..bc16ffaf --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/index.ts @@ -0,0 +1,6 @@ +export { ProjectSettingsView } from './project-settings-view'; +export { ProjectIdentitySection } from './project-identity-section'; +export { ProjectThemeSection } from './project-theme-section'; +export { WorktreePreferencesSection } from './worktree-preferences-section'; +export { useProjectSettingsView, type ProjectSettingsViewId } from './hooks'; +export { ProjectSettingsNavigation } from './components/project-settings-navigation'; diff --git a/apps/ui/src/components/views/project-settings-view/project-identity-section.tsx b/apps/ui/src/components/views/project-settings-view/project-identity-section.tsx new file mode 100644 index 00000000..d938ee73 --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/project-identity-section.tsx @@ -0,0 +1,199 @@ +import { useState, useRef, useEffect } from 'react'; +import { Label } from '@/components/ui/label'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { Palette, Upload, X, ImageIcon } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { useAppStore } from '@/store/app-store'; +import { IconPicker } from '@/components/layout/project-switcher/components/icon-picker'; +import { getAuthenticatedImageUrl } from '@/lib/api-fetch'; +import { getHttpApiClient } from '@/lib/http-api-client'; +import type { Project } from '@/lib/electron'; + +interface ProjectIdentitySectionProps { + project: Project; +} + +export function ProjectIdentitySection({ project }: ProjectIdentitySectionProps) { + const { setProjectIcon, setProjectName, setProjectCustomIcon } = useAppStore(); + const [projectName, setProjectNameLocal] = useState(project.name || ''); + const [projectIcon, setProjectIconLocal] = useState(project.icon || null); + const [customIconPath, setCustomIconPathLocal] = useState( + project.customIconPath || null + ); + const [isUploadingIcon, setIsUploadingIcon] = useState(false); + const fileInputRef = useRef(null); + + // Sync local state when project changes + useEffect(() => { + setProjectNameLocal(project.name || ''); + setProjectIconLocal(project.icon || null); + setCustomIconPathLocal(project.customIconPath || null); + }, [project]); + + // Auto-save when values change + const handleNameChange = (name: string) => { + setProjectNameLocal(name); + if (name.trim() && name.trim() !== project.name) { + setProjectName(project.id, name.trim()); + } + }; + + const handleIconChange = (icon: string | null) => { + setProjectIconLocal(icon); + setProjectIcon(project.id, icon); + }; + + const handleCustomIconChange = (path: string | null) => { + setCustomIconPathLocal(path); + setProjectCustomIcon(project.id, path); + // Clear Lucide icon when custom icon is set + if (path) { + setProjectIconLocal(null); + setProjectIcon(project.id, null); + } + }; + + const handleCustomIconUpload = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + // Validate file type + const validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; + if (!validTypes.includes(file.type)) { + return; + } + + // Validate file size (max 2MB for icons) + if (file.size > 2 * 1024 * 1024) { + return; + } + + setIsUploadingIcon(true); + try { + // Convert to base64 + const reader = new FileReader(); + reader.onload = async () => { + const base64Data = reader.result as string; + const result = await getHttpApiClient().saveImageToTemp( + base64Data, + `project-icon-${file.name}`, + file.type, + project.path + ); + if (result.success && result.path) { + handleCustomIconChange(result.path); + } + setIsUploadingIcon(false); + }; + reader.readAsDataURL(file); + } catch { + setIsUploadingIcon(false); + } + }; + + const handleRemoveCustomIcon = () => { + handleCustomIconChange(null); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + }; + + return ( +
+
+
+
+ +
+

Project Identity

+
+

+ Customize how your project appears in the sidebar and project switcher. +

+
+
+ {/* Project Name */} +
+ + handleNameChange(e.target.value)} + placeholder="Enter project name" + /> +
+ + {/* Project Icon */} +
+ +

+ Choose a preset icon or upload a custom image +

+ + {/* Custom Icon Upload */} +
+
+ {customIconPath ? ( +
+ Custom project icon + +
+ ) : ( +
+ +
+ )} +
+ + +

+ PNG, JPG, GIF or WebP. Max 2MB. +

+
+
+
+ + {/* Preset Icon Picker - only show if no custom icon */} + {!customIconPath && ( + + )} +
+
+
+ ); +} diff --git a/apps/ui/src/components/views/project-settings-view/project-settings-view.tsx b/apps/ui/src/components/views/project-settings-view/project-settings-view.tsx new file mode 100644 index 00000000..f441cc72 --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/project-settings-view.tsx @@ -0,0 +1,174 @@ +import { useState, useEffect } from 'react'; +import { useAppStore } from '@/store/app-store'; +import { Settings, FolderOpen, Menu } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { ProjectIdentitySection } from './project-identity-section'; +import { ProjectThemeSection } from './project-theme-section'; +import { WorktreePreferencesSection } from './worktree-preferences-section'; +import { DangerZoneSection } from '../settings-view/danger-zone/danger-zone-section'; +import { DeleteProjectDialog } from '../settings-view/components/delete-project-dialog'; +import { ProjectSettingsNavigation } from './components/project-settings-navigation'; +import { useProjectSettingsView } from './hooks/use-project-settings-view'; +import type { Project as ElectronProject } from '@/lib/electron'; + +// Breakpoint constant for mobile (matches Tailwind lg breakpoint) +const LG_BREAKPOINT = 1024; + +// Convert to the shared types used by components +interface SettingsProject { + id: string; + name: string; + path: string; + theme?: string; + icon?: string | null; + customIconPath?: string | null; +} + +export function ProjectSettingsView() { + const { currentProject, moveProjectToTrash } = useAppStore(); + const [showDeleteDialog, setShowDeleteDialog] = useState(false); + + // Use project settings view navigation hook + const { activeView, navigateTo } = useProjectSettingsView(); + + // Mobile navigation state - default to showing on desktop, hidden on mobile + const [showNavigation, setShowNavigation] = useState(() => { + if (typeof window !== 'undefined') { + return window.innerWidth >= LG_BREAKPOINT; + } + return true; + }); + + // Auto-close navigation on mobile when a section is selected + useEffect(() => { + if (typeof window !== 'undefined' && window.innerWidth < LG_BREAKPOINT) { + setShowNavigation(false); + } + }, [activeView]); + + // Handle window resize to show/hide navigation appropriately + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= LG_BREAKPOINT) { + setShowNavigation(true); + } + }; + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + // Convert electron Project to settings-view Project type + const convertProject = (project: ElectronProject | null): SettingsProject | null => { + if (!project) return null; + return { + id: project.id, + name: project.name, + path: project.path, + theme: project.theme, + icon: project.icon, + customIconPath: project.customIconPath, + }; + }; + + const settingsProject = convertProject(currentProject); + + // Render the active section based on current view + const renderActiveSection = () => { + if (!currentProject) return null; + + switch (activeView) { + case 'identity': + return ; + case 'theme': + return ; + case 'worktrees': + return ; + case 'danger': + return ( + setShowDeleteDialog(true)} + /> + ); + default: + return ; + } + }; + + // Show message if no project is selected + if (!currentProject) { + return ( +
+
+
+
+ +
+

No Project Selected

+

+ Select a project from the sidebar to configure project-specific settings. +

+
+
+
+ ); + } + + return ( +
+ {/* Header */} +
+
+ {/* Mobile menu button */} + + +
+

Project Settings

+

+ Configure settings for {currentProject.name} +

+
+
+
+ + {/* Content Area with Sidebar */} +
+ {/* Side Navigation */} + setShowNavigation(false)} + /> + + {/* Content Panel - Shows only the active section */} +
+
{renderActiveSection()}
+
+
+ + {/* Delete Project Confirmation Dialog */} + +
+ ); +} diff --git a/apps/ui/src/components/views/project-settings-view/project-theme-section.tsx b/apps/ui/src/components/views/project-settings-view/project-theme-section.tsx new file mode 100644 index 00000000..d9293df2 --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/project-theme-section.tsx @@ -0,0 +1,164 @@ +import { useState } from 'react'; +import { Label } from '@/components/ui/label'; +import { Checkbox } from '@/components/ui/checkbox'; +import { Palette, Moon, Sun } from 'lucide-react'; +import { darkThemes, lightThemes, type Theme } from '@/config/theme-options'; +import { cn } from '@/lib/utils'; +import { useAppStore } from '@/store/app-store'; +import type { Project } from '@/lib/electron'; + +interface ProjectThemeSectionProps { + project: Project; +} + +export function ProjectThemeSection({ project }: ProjectThemeSectionProps) { + const { theme: globalTheme, setProjectTheme } = useAppStore(); + const [activeTab, setActiveTab] = useState<'dark' | 'light'>('dark'); + + const projectTheme = project.theme as Theme | undefined; + const hasCustomTheme = projectTheme !== undefined; + const effectiveTheme = projectTheme || globalTheme; + + const themesToShow = activeTab === 'dark' ? darkThemes : lightThemes; + + const handleThemeChange = (theme: Theme) => { + setProjectTheme(project.id, theme); + }; + + const handleUseGlobalTheme = (checked: boolean) => { + if (checked) { + // Clear project theme to use global + setProjectTheme(project.id, null); + } else { + // Set project theme to current global theme + setProjectTheme(project.id, globalTheme); + } + }; + + return ( +
+
+
+
+ +
+

Theme

+
+

+ Customize the theme for this project. +

+
+
+ {/* Use Global Theme Toggle */} +
+ +
+ +

+ When enabled, this project will use the global theme setting. Disable to set a + project-specific theme. +

+
+
+ + {/* Theme Selection - only show if not using global theme */} + {hasCustomTheme && ( +
+
+ + {/* Dark/Light Tabs */} +
+ + +
+
+
+ {themesToShow.map(({ value, label, Icon, testId, color }) => { + const isActive = effectiveTheme === value; + return ( + + ); + })} +
+
+ )} + + {/* Info when using global theme */} + {!hasCustomTheme && ( +
+

+ This project is using the global theme:{' '} + {globalTheme} +

+
+ )} +
+
+ ); +} diff --git a/apps/ui/src/components/views/project-settings-view/worktree-preferences-section.tsx b/apps/ui/src/components/views/project-settings-view/worktree-preferences-section.tsx new file mode 100644 index 00000000..af85eb03 --- /dev/null +++ b/apps/ui/src/components/views/project-settings-view/worktree-preferences-section.tsx @@ -0,0 +1,450 @@ +import { useState, useEffect, useCallback } from 'react'; +import { Label } from '@/components/ui/label'; +import { Checkbox } from '@/components/ui/checkbox'; +import { Button } from '@/components/ui/button'; +import { ShellSyntaxEditor } from '@/components/ui/shell-syntax-editor'; +import { + GitBranch, + Terminal, + FileCode, + Save, + RotateCcw, + Trash2, + Loader2, + PanelBottomClose, +} from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { apiGet, apiPut, apiDelete } from '@/lib/api-fetch'; +import { toast } from 'sonner'; +import { useAppStore } from '@/store/app-store'; +import { getHttpApiClient } from '@/lib/http-api-client'; +import type { Project } from '@/lib/electron'; + +interface WorktreePreferencesSectionProps { + project: Project; +} + +interface InitScriptResponse { + success: boolean; + exists: boolean; + content: string; + path: string; + error?: string; +} + +export function WorktreePreferencesSection({ project }: WorktreePreferencesSectionProps) { + const globalUseWorktrees = useAppStore((s) => s.useWorktrees); + const getProjectUseWorktrees = useAppStore((s) => s.getProjectUseWorktrees); + const setProjectUseWorktrees = useAppStore((s) => s.setProjectUseWorktrees); + const getShowInitScriptIndicator = useAppStore((s) => s.getShowInitScriptIndicator); + const setShowInitScriptIndicator = useAppStore((s) => s.setShowInitScriptIndicator); + const getDefaultDeleteBranch = useAppStore((s) => s.getDefaultDeleteBranch); + const setDefaultDeleteBranch = useAppStore((s) => s.setDefaultDeleteBranch); + const getAutoDismissInitScriptIndicator = useAppStore((s) => s.getAutoDismissInitScriptIndicator); + const setAutoDismissInitScriptIndicator = useAppStore((s) => s.setAutoDismissInitScriptIndicator); + + // Get effective worktrees setting (project override or global fallback) + const projectUseWorktrees = getProjectUseWorktrees(project.path); + const effectiveUseWorktrees = projectUseWorktrees ?? globalUseWorktrees; + + const [scriptContent, setScriptContent] = useState(''); + const [originalContent, setOriginalContent] = useState(''); + const [scriptExists, setScriptExists] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [isSaving, setIsSaving] = useState(false); + const [isDeleting, setIsDeleting] = useState(false); + + // Get the current settings for this project + const showIndicator = getShowInitScriptIndicator(project.path); + const defaultDeleteBranch = getDefaultDeleteBranch(project.path); + const autoDismiss = getAutoDismissInitScriptIndicator(project.path); + + // Check if there are unsaved changes + const hasChanges = scriptContent !== originalContent; + + // Load project settings (including useWorktrees) when project changes + useEffect(() => { + const loadProjectSettings = async () => { + try { + const httpClient = getHttpApiClient(); + const response = await httpClient.settings.getProject(project.path); + if (response.success && response.settings) { + // Sync useWorktrees to store if it has a value + if (response.settings.useWorktrees !== undefined) { + setProjectUseWorktrees(project.path, response.settings.useWorktrees); + } + // Also sync other settings to store + if (response.settings.showInitScriptIndicator !== undefined) { + setShowInitScriptIndicator(project.path, response.settings.showInitScriptIndicator); + } + if (response.settings.defaultDeleteBranchWithWorktree !== undefined) { + setDefaultDeleteBranch(project.path, response.settings.defaultDeleteBranchWithWorktree); + } + if (response.settings.autoDismissInitScriptIndicator !== undefined) { + setAutoDismissInitScriptIndicator( + project.path, + response.settings.autoDismissInitScriptIndicator + ); + } + } + } catch (error) { + console.error('Failed to load project settings:', error); + } + }; + + loadProjectSettings(); + }, [ + project.path, + setProjectUseWorktrees, + setShowInitScriptIndicator, + setDefaultDeleteBranch, + setAutoDismissInitScriptIndicator, + ]); + + // Load init script content when project changes + useEffect(() => { + const loadInitScript = async () => { + setIsLoading(true); + try { + const response = await apiGet( + `/api/worktree/init-script?projectPath=${encodeURIComponent(project.path)}` + ); + if (response.success) { + const content = response.content || ''; + setScriptContent(content); + setOriginalContent(content); + setScriptExists(response.exists); + } + } catch (error) { + console.error('Failed to load init script:', error); + } finally { + setIsLoading(false); + } + }; + + loadInitScript(); + }, [project.path]); + + // Save script + const handleSave = useCallback(async () => { + setIsSaving(true); + try { + const response = await apiPut<{ success: boolean; error?: string }>( + '/api/worktree/init-script', + { + projectPath: project.path, + content: scriptContent, + } + ); + if (response.success) { + setOriginalContent(scriptContent); + setScriptExists(true); + toast.success('Init script saved'); + } else { + toast.error('Failed to save init script', { + description: response.error, + }); + } + } catch (error) { + console.error('Failed to save init script:', error); + toast.error('Failed to save init script'); + } finally { + setIsSaving(false); + } + }, [project.path, scriptContent]); + + // Reset to original content + const handleReset = useCallback(() => { + setScriptContent(originalContent); + }, [originalContent]); + + // Delete script + const handleDelete = useCallback(async () => { + setIsDeleting(true); + try { + const response = await apiDelete<{ success: boolean; error?: string }>( + '/api/worktree/init-script', + { + body: { projectPath: project.path }, + } + ); + if (response.success) { + setScriptContent(''); + setOriginalContent(''); + setScriptExists(false); + toast.success('Init script deleted'); + } else { + toast.error('Failed to delete init script', { + description: response.error, + }); + } + } catch (error) { + console.error('Failed to delete init script:', error); + toast.error('Failed to delete init script'); + } finally { + setIsDeleting(false); + } + }, [project.path]); + + // Handle content change (no auto-save) + const handleContentChange = useCallback((value: string) => { + setScriptContent(value); + }, []); + + return ( +
+
+
+
+ +
+

+ Worktree Preferences +

+
+

+ Configure worktree behavior for this project. +

+
+
+ {/* Enable Git Worktree Isolation Toggle */} +
+ { + const value = checked === true; + setProjectUseWorktrees(project.path, value); + try { + const httpClient = getHttpApiClient(); + await httpClient.settings.updateProject(project.path, { + useWorktrees: value, + }); + } catch (error) { + console.error('Failed to persist useWorktrees:', error); + } + }} + className="mt-1" + data-testid="project-use-worktrees-checkbox" + /> +
+ +

+ Creates isolated git branches for each feature in this project. When disabled, agents + work directly in the main project directory. +

+
+
+ + {/* Separator */} +
+ + {/* Show Init Script Indicator Toggle */} +
+ { + const value = checked === true; + setShowInitScriptIndicator(project.path, value); + // Persist to server + try { + const httpClient = getHttpApiClient(); + await httpClient.settings.updateProject(project.path, { + showInitScriptIndicator: value, + }); + } catch (error) { + console.error('Failed to persist showInitScriptIndicator:', error); + } + }} + className="mt-1" + /> +
+ +

+ Display a floating panel in the bottom-right corner showing init script execution + status and output when a worktree is created. +

+
+
+ + {/* Auto-dismiss Init Script Indicator Toggle */} + {showIndicator && ( +
+ { + const value = checked === true; + setAutoDismissInitScriptIndicator(project.path, value); + // Persist to server + try { + const httpClient = getHttpApiClient(); + await httpClient.settings.updateProject(project.path, { + autoDismissInitScriptIndicator: value, + }); + } catch (error) { + console.error('Failed to persist autoDismissInitScriptIndicator:', error); + } + }} + className="mt-1" + /> +
+ +

+ Automatically hide the indicator 5 seconds after the script completes. +

+
+
+ )} + + {/* Default Delete Branch Toggle */} +
+ { + const value = checked === true; + setDefaultDeleteBranch(project.path, value); + // Persist to server + try { + const httpClient = getHttpApiClient(); + await httpClient.settings.updateProject(project.path, { + defaultDeleteBranch: value, + }); + } catch (error) { + console.error('Failed to persist defaultDeleteBranch:', error); + } + }} + className="mt-1" + /> +
+ +

+ When deleting a worktree, automatically check the "Also delete the branch" option. +

+
+
+ + {/* Separator */} +
+ + {/* Init Script Section */} +
+
+
+ + +
+
+

+ Shell commands to run after a worktree is created. Runs once per worktree. Uses Git Bash + on Windows for cross-platform compatibility. +

+ + {/* File path indicator */} +
+ + .automaker/worktree-init.sh + {hasChanges && (unsaved changes)} +
+ + {isLoading ? ( +
+ +
+ ) : ( + <> + + + {/* Action buttons */} +
+ + + +
+ + )} +
+
+
+ ); +} diff --git a/apps/ui/src/components/views/settings-view.tsx b/apps/ui/src/components/views/settings-view.tsx index 1ddf0a39..3bcec3bb 100644 --- a/apps/ui/src/components/views/settings-view.tsx +++ b/apps/ui/src/components/views/settings-view.tsx @@ -6,7 +6,6 @@ import { useSettingsView, type SettingsViewId } from './settings-view/hooks'; import { NAV_ITEMS } from './settings-view/config/navigation'; import { SettingsHeader } from './settings-view/components/settings-header'; import { KeyboardMapDialog } from './settings-view/components/keyboard-map-dialog'; -import { DeleteProjectDialog } from './settings-view/components/delete-project-dialog'; import { SettingsNavigation } from './settings-view/components/settings-navigation'; import { ApiKeysSection } from './settings-view/api-keys/api-keys-section'; import { ModelDefaultsSection } from './settings-view/model-defaults'; @@ -16,7 +15,6 @@ import { AudioSection } from './settings-view/audio/audio-section'; import { KeyboardShortcutsSection } from './settings-view/keyboard-shortcuts/keyboard-shortcuts-section'; import { FeatureDefaultsSection } from './settings-view/feature-defaults/feature-defaults-section'; import { WorktreesSection } from './settings-view/worktrees'; -import { DangerZoneSection } from './settings-view/danger-zone/danger-zone-section'; import { AccountSection } from './settings-view/account'; import { SecuritySection } from './settings-view/security'; import { DeveloperSection } from './settings-view/developer/developer-section'; @@ -30,8 +28,7 @@ import { MCPServersSection } from './settings-view/mcp-servers'; import { PromptCustomizationSection } from './settings-view/prompts'; import { EventHooksSection } from './settings-view/event-hooks'; import { ImportExportDialog } from './settings-view/components/import-export-dialog'; -import type { Project as SettingsProject, Theme } from './settings-view/shared/types'; -import type { Project as ElectronProject } from '@/lib/electron'; +import type { Theme } from './settings-view/shared/types'; // Breakpoint constant for mobile (matches Tailwind lg breakpoint) const LG_BREAKPOINT = 1024; @@ -40,7 +37,6 @@ export function SettingsView() { const { theme, setTheme, - setProjectTheme, defaultSkipTests, setDefaultSkipTests, enableDependencyBlocking, @@ -54,7 +50,6 @@ export function SettingsView() { muteDoneSound, setMuteDoneSound, currentProject, - moveProjectToTrash, defaultPlanningMode, setDefaultPlanningMode, defaultRequirePlanApproval, @@ -69,34 +64,8 @@ export function SettingsView() { setSkipSandboxWarning, } = useAppStore(); - // Convert electron Project to settings-view Project type - const convertProject = (project: ElectronProject | null): SettingsProject | null => { - if (!project) return null; - return { - id: project.id, - name: project.name, - path: project.path, - theme: project.theme as Theme | undefined, - icon: project.icon, - customIconPath: project.customIconPath, - }; - }; - - const settingsProject = convertProject(currentProject); - - // Compute the effective theme for the current project - const effectiveTheme = (settingsProject?.theme || theme) as Theme; - - // Handler to set theme - always updates global theme (user's preference), - // and also sets per-project theme if a project is selected - const handleSetTheme = (newTheme: typeof theme) => { - // Always update global theme so user's preference persists across all projects - setTheme(newTheme); - // Also set per-project theme if a project is selected - if (currentProject) { - setProjectTheme(currentProject.id, newTheme); - } - }; + // Global theme (project-specific themes are managed in Project Settings) + const globalTheme = theme as Theme; // Get initial view from URL search params const { view: initialView } = useSearch({ from: '/settings' }); @@ -113,7 +82,6 @@ export function SettingsView() { } }; - const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [showKeyboardMapDialog, setShowKeyboardMapDialog] = useState(false); const [showImportExportDialog, setShowImportExportDialog] = useState(false); @@ -172,9 +140,8 @@ export function SettingsView() { case 'appearance': return ( handleSetTheme(theme as any)} + effectiveTheme={globalTheme} + onThemeChange={(newTheme) => setTheme(newTheme as typeof theme)} /> ); case 'terminal': @@ -223,13 +190,6 @@ export function SettingsView() { ); case 'developer': return ; - case 'danger': - return ( - setShowDeleteDialog(true)} - /> - ); default: return ; } @@ -265,14 +225,6 @@ export function SettingsView() { {/* Keyboard Map Dialog */} - {/* Delete Project Confirmation Dialog */} - - {/* Import/Export Settings Dialog */}
diff --git a/apps/ui/src/components/views/settings-view/appearance/appearance-section.tsx b/apps/ui/src/components/views/settings-view/appearance/appearance-section.tsx index 003501f9..47646287 100644 --- a/apps/ui/src/components/views/settings-view/appearance/appearance-section.tsx +++ b/apps/ui/src/components/views/settings-view/appearance/appearance-section.tsx @@ -1,118 +1,20 @@ -import { useState, useRef, useEffect } from 'react'; +import { useState } from 'react'; import { Label } from '@/components/ui/label'; -import { Input } from '@/components/ui/input'; -import { Button } from '@/components/ui/button'; -import { Palette, Moon, Sun, Upload, X, ImageIcon } from 'lucide-react'; +import { Palette, Moon, Sun } from 'lucide-react'; import { darkThemes, lightThemes } from '@/config/theme-options'; import { cn } from '@/lib/utils'; -import { useAppStore } from '@/store/app-store'; -import { IconPicker } from '@/components/layout/project-switcher/components/icon-picker'; -import { getAuthenticatedImageUrl } from '@/lib/api-fetch'; -import { getHttpApiClient } from '@/lib/http-api-client'; -import type { Theme, Project } from '../shared/types'; +import type { Theme } from '../shared/types'; interface AppearanceSectionProps { effectiveTheme: Theme; - currentProject: Project | null; onThemeChange: (theme: Theme) => void; } -export function AppearanceSection({ - effectiveTheme, - currentProject, - onThemeChange, -}: AppearanceSectionProps) { - const { setProjectIcon, setProjectName, setProjectCustomIcon } = useAppStore(); +export function AppearanceSection({ effectiveTheme, onThemeChange }: AppearanceSectionProps) { const [activeTab, setActiveTab] = useState<'dark' | 'light'>('dark'); - const [projectName, setProjectNameLocal] = useState(currentProject?.name || ''); - const [projectIcon, setProjectIconLocal] = useState(currentProject?.icon || null); - const [customIconPath, setCustomIconPathLocal] = useState( - currentProject?.customIconPath || null - ); - const [isUploadingIcon, setIsUploadingIcon] = useState(false); - const fileInputRef = useRef(null); - - // Sync local state when currentProject changes - useEffect(() => { - setProjectNameLocal(currentProject?.name || ''); - setProjectIconLocal(currentProject?.icon || null); - setCustomIconPathLocal(currentProject?.customIconPath || null); - }, [currentProject]); const themesToShow = activeTab === 'dark' ? darkThemes : lightThemes; - // Auto-save when values change - const handleNameChange = (name: string) => { - setProjectNameLocal(name); - if (currentProject && name.trim() && name.trim() !== currentProject.name) { - setProjectName(currentProject.id, name.trim()); - } - }; - - const handleIconChange = (icon: string | null) => { - setProjectIconLocal(icon); - if (currentProject) { - setProjectIcon(currentProject.id, icon); - } - }; - - const handleCustomIconChange = (path: string | null) => { - setCustomIconPathLocal(path); - if (currentProject) { - setProjectCustomIcon(currentProject.id, path); - // Clear Lucide icon when custom icon is set - if (path) { - setProjectIconLocal(null); - setProjectIcon(currentProject.id, null); - } - } - }; - - const handleCustomIconUpload = async (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file || !currentProject) return; - - // Validate file type - const validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; - if (!validTypes.includes(file.type)) { - return; - } - - // Validate file size (max 2MB for icons) - if (file.size > 2 * 1024 * 1024) { - return; - } - - setIsUploadingIcon(true); - try { - // Convert to base64 - const reader = new FileReader(); - reader.onload = async () => { - const base64Data = reader.result as string; - const result = await getHttpApiClient().saveImageToTemp( - base64Data, - `project-icon-${file.name}`, - file.type, - currentProject.path - ); - if (result.success && result.path) { - handleCustomIconChange(result.path); - } - setIsUploadingIcon(false); - }; - reader.readAsDataURL(file); - } catch { - setIsUploadingIcon(false); - } - }; - - const handleRemoveCustomIcon = () => { - handleCustomIconChange(null); - if (fileInputRef.current) { - fileInputRef.current.value = ''; - } - }; - return (
- {/* Project Details Section */} - {currentProject && ( -
-
-
- - handleNameChange(e.target.value)} - placeholder="Enter project name" - /> -
- -
- -

- Choose a preset icon or upload a custom image -

- - {/* Custom Icon Upload */} -
-
- {customIconPath ? ( -
- Custom project icon - -
- ) : ( -
- -
- )} -
- - -

- PNG, JPG, GIF or WebP. Max 2MB. -

-
-
-
- - {/* Preset Icon Picker - only show if no custom icon */} - {!customIconPath && ( - - )} -
-
-
- )} - {/* Theme Section */}
- + {/* Dark/Light Tabs */}
))} - - {/* Project Settings - only show when a project is selected */} - {currentProject && ( - <> - {/* Divider */} -
- - {/* Project Settings Label */} -
- Project Settings -
- - {/* Project Settings Items */} -
- {PROJECT_NAV_ITEMS.map((item) => ( - - ))} -
- - )}
diff --git a/apps/ui/src/components/views/settings-view/config/navigation.ts b/apps/ui/src/components/views/settings-view/config/navigation.ts index c5d5d362..107d8678 100644 --- a/apps/ui/src/components/views/settings-view/config/navigation.ts +++ b/apps/ui/src/components/views/settings-view/config/navigation.ts @@ -8,13 +8,11 @@ import { Settings2, Volume2, FlaskConical, - Trash2, Workflow, Plug, MessageSquareText, User, Shield, - Cpu, GitBranch, Code2, Webhook, @@ -84,10 +82,5 @@ export const GLOBAL_NAV_GROUPS: NavigationGroup[] = [ // Flat list of all global nav items for backwards compatibility export const GLOBAL_NAV_ITEMS: NavigationItem[] = GLOBAL_NAV_GROUPS.flatMap((group) => group.items); -// Project-specific settings - only visible when a project is selected -export const PROJECT_NAV_ITEMS: NavigationItem[] = [ - { id: 'danger', label: 'Danger Zone', icon: Trash2 }, -]; - // Legacy export for backwards compatibility -export const NAV_ITEMS: NavigationItem[] = [...GLOBAL_NAV_ITEMS, ...PROJECT_NAV_ITEMS]; +export const NAV_ITEMS: NavigationItem[] = GLOBAL_NAV_ITEMS; diff --git a/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx b/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx index 2d232a65..062d2d0d 100644 --- a/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx +++ b/apps/ui/src/components/views/settings-view/worktrees/worktrees-section.tsx @@ -1,172 +1,14 @@ -import { useState, useEffect, useCallback } from 'react'; import { Label } from '@/components/ui/label'; import { Checkbox } from '@/components/ui/checkbox'; -import { Button } from '@/components/ui/button'; -import { ShellSyntaxEditor } from '@/components/ui/shell-syntax-editor'; -import { - GitBranch, - Terminal, - FileCode, - Save, - RotateCcw, - Trash2, - Loader2, - PanelBottomClose, -} from 'lucide-react'; +import { GitBranch } from 'lucide-react'; import { cn } from '@/lib/utils'; -import { apiGet, apiPut, apiDelete } from '@/lib/api-fetch'; -import { toast } from 'sonner'; -import { useAppStore } from '@/store/app-store'; -import { getHttpApiClient } from '@/lib/http-api-client'; interface WorktreesSectionProps { useWorktrees: boolean; onUseWorktreesChange: (value: boolean) => void; } -interface InitScriptResponse { - success: boolean; - exists: boolean; - content: string; - path: string; - error?: string; -} - export function WorktreesSection({ useWorktrees, onUseWorktreesChange }: WorktreesSectionProps) { - const currentProject = useAppStore((s) => s.currentProject); - const getShowInitScriptIndicator = useAppStore((s) => s.getShowInitScriptIndicator); - const setShowInitScriptIndicator = useAppStore((s) => s.setShowInitScriptIndicator); - const getDefaultDeleteBranch = useAppStore((s) => s.getDefaultDeleteBranch); - const setDefaultDeleteBranch = useAppStore((s) => s.setDefaultDeleteBranch); - const getAutoDismissInitScriptIndicator = useAppStore((s) => s.getAutoDismissInitScriptIndicator); - const setAutoDismissInitScriptIndicator = useAppStore((s) => s.setAutoDismissInitScriptIndicator); - const [scriptContent, setScriptContent] = useState(''); - const [originalContent, setOriginalContent] = useState(''); - const [scriptExists, setScriptExists] = useState(false); - const [isLoading, setIsLoading] = useState(true); - const [isSaving, setIsSaving] = useState(false); - const [isDeleting, setIsDeleting] = useState(false); - - // Get the current show indicator setting - const showIndicator = currentProject?.path - ? getShowInitScriptIndicator(currentProject.path) - : true; - - // Get the default delete branch setting - const defaultDeleteBranch = currentProject?.path - ? getDefaultDeleteBranch(currentProject.path) - : false; - - // Get the auto-dismiss setting - const autoDismiss = currentProject?.path - ? getAutoDismissInitScriptIndicator(currentProject.path) - : true; - - // Check if there are unsaved changes - const hasChanges = scriptContent !== originalContent; - - // Load init script content when project changes - useEffect(() => { - if (!currentProject?.path) { - setScriptContent(''); - setOriginalContent(''); - setScriptExists(false); - setIsLoading(false); - return; - } - - const loadInitScript = async () => { - setIsLoading(true); - try { - const response = await apiGet( - `/api/worktree/init-script?projectPath=${encodeURIComponent(currentProject.path)}` - ); - if (response.success) { - const content = response.content || ''; - setScriptContent(content); - setOriginalContent(content); - setScriptExists(response.exists); - } - } catch (error) { - console.error('Failed to load init script:', error); - } finally { - setIsLoading(false); - } - }; - - loadInitScript(); - }, [currentProject?.path]); - - // Save script - const handleSave = useCallback(async () => { - if (!currentProject?.path) return; - - setIsSaving(true); - try { - const response = await apiPut<{ success: boolean; error?: string }>( - '/api/worktree/init-script', - { - projectPath: currentProject.path, - content: scriptContent, - } - ); - if (response.success) { - setOriginalContent(scriptContent); - setScriptExists(true); - toast.success('Init script saved'); - } else { - toast.error('Failed to save init script', { - description: response.error, - }); - } - } catch (error) { - console.error('Failed to save init script:', error); - toast.error('Failed to save init script'); - } finally { - setIsSaving(false); - } - }, [currentProject?.path, scriptContent]); - - // Reset to original content - const handleReset = useCallback(() => { - setScriptContent(originalContent); - }, [originalContent]); - - // Delete script - const handleDelete = useCallback(async () => { - if (!currentProject?.path) return; - - setIsDeleting(true); - try { - const response = await apiDelete<{ success: boolean; error?: string }>( - '/api/worktree/init-script', - { - body: { projectPath: currentProject.path }, - } - ); - if (response.success) { - setScriptContent(''); - setOriginalContent(''); - setScriptExists(false); - toast.success('Init script deleted'); - } else { - toast.error('Failed to delete init script', { - description: response.error, - }); - } - } catch (error) { - console.error('Failed to delete init script:', error); - toast.error('Failed to delete init script'); - } finally { - setIsDeleting(false); - } - }, [currentProject?.path]); - - // Handle content change (no auto-save) - const handleContentChange = useCallback((value: string) => { - setScriptContent(value); - }, []); - return (
Worktrees

- Configure git worktree isolation and initialization scripts. + Configure git worktree isolation for feature development.

@@ -212,217 +54,12 @@ export function WorktreesSection({ useWorktrees, onUseWorktreesChange }: Worktre
- {/* Show Init Script Indicator Toggle */} - {currentProject && ( -
- { - if (currentProject?.path) { - const value = checked === true; - setShowInitScriptIndicator(currentProject.path, value); - // Persist to server - try { - const httpClient = getHttpApiClient(); - await httpClient.settings.updateProject(currentProject.path, { - showInitScriptIndicator: value, - }); - } catch (error) { - console.error('Failed to persist showInitScriptIndicator:', error); - } - } - }} - className="mt-1" - /> -
- -

- Display a floating panel in the bottom-right corner showing init script execution - status and output when a worktree is created. -

-
-
- )} - - {/* Auto-dismiss Init Script Indicator Toggle */} - {currentProject && showIndicator && ( -
- { - if (currentProject?.path) { - const value = checked === true; - setAutoDismissInitScriptIndicator(currentProject.path, value); - // Persist to server - try { - const httpClient = getHttpApiClient(); - await httpClient.settings.updateProject(currentProject.path, { - autoDismissInitScriptIndicator: value, - }); - } catch (error) { - console.error('Failed to persist autoDismissInitScriptIndicator:', error); - } - } - }} - className="mt-1" - /> -
- -

- Automatically hide the indicator 5 seconds after the script completes. -

-
-
- )} - - {/* Default Delete Branch Toggle */} - {currentProject && ( -
- { - if (currentProject?.path) { - const value = checked === true; - setDefaultDeleteBranch(currentProject.path, value); - // Persist to server - try { - const httpClient = getHttpApiClient(); - await httpClient.settings.updateProject(currentProject.path, { - defaultDeleteBranch: value, - }); - } catch (error) { - console.error('Failed to persist defaultDeleteBranch:', error); - } - } - }} - className="mt-1" - /> -
- -

- When deleting a worktree, automatically check the "Also delete the branch" option. -

-
-
- )} - - {/* Separator */} -
- - {/* Init Script Section */} -
-
-
- - -
-
-

- Shell commands to run after a worktree is created. Runs once per worktree. Uses Git Bash - on Windows for cross-platform compatibility. + {/* Info about project-specific settings */} +

+

+ Project-specific worktree preferences (init script, delete branch behavior) can be + configured in each project's settings via the sidebar.

- - {currentProject ? ( - <> - {/* File path indicator */} -
- - .automaker/worktree-init.sh - {hasChanges && ( - (unsaved changes) - )} -
- - {isLoading ? ( -
- -
- ) : ( - <> - - - {/* Action buttons */} -
- - - -
- - )} - - ) : ( -
- Select a project to configure the init script. -
- )}
diff --git a/apps/ui/src/lib/http-api-client.ts b/apps/ui/src/lib/http-api-client.ts index 90781b59..26e1f308 100644 --- a/apps/ui/src/lib/http-api-client.ts +++ b/apps/ui/src/lib/http-api-client.ts @@ -2171,6 +2171,9 @@ export class HttpApiClient implements ElectronAPI { hideScrollbar: boolean; }; worktreePanelVisible?: boolean; + showInitScriptIndicator?: boolean; + defaultDeleteBranchWithWorktree?: boolean; + autoDismissInitScriptIndicator?: boolean; lastSelectedSessionId?: string; }; error?: string; diff --git a/apps/ui/src/routes/project-settings.tsx b/apps/ui/src/routes/project-settings.tsx new file mode 100644 index 00000000..e933d58d --- /dev/null +++ b/apps/ui/src/routes/project-settings.tsx @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/react-router'; +import { ProjectSettingsView } from '@/components/views/project-settings-view'; + +export const Route = createFileRoute('/project-settings')({ + component: ProjectSettingsView, +}); diff --git a/apps/ui/src/store/app-store.ts b/apps/ui/src/store/app-store.ts index 23fa5371..23886ab6 100644 --- a/apps/ui/src/store/app-store.ts +++ b/apps/ui/src/store/app-store.ts @@ -231,6 +231,7 @@ export interface KeyboardShortcuts { context: string; memory: string; settings: string; + projectSettings: string; terminal: string; ideation: string; githubIssues: string; @@ -266,6 +267,7 @@ export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = { context: 'C', memory: 'Y', settings: 'S', + projectSettings: 'Shift+S', terminal: 'T', ideation: 'I', githubIssues: 'G', @@ -730,6 +732,10 @@ export interface AppState { // Whether to auto-dismiss the indicator after completion (default: true) autoDismissInitScriptIndicatorByProject: Record; + // Use Worktrees Override (per-project, keyed by project path) + // undefined = use global setting, true/false = project-specific override + useWorktreesByProject: Record; + // UI State (previously in localStorage, now synced via API) /** Whether worktree panel is collapsed in board view */ worktreePanelCollapsed: boolean; @@ -1183,6 +1189,11 @@ export interface AppActions { setAutoDismissInitScriptIndicator: (projectPath: string, autoDismiss: boolean) => void; getAutoDismissInitScriptIndicator: (projectPath: string) => boolean; + // Use Worktrees Override actions (per-project) + setProjectUseWorktrees: (projectPath: string, useWorktrees: boolean | null) => void; // null = use global + getProjectUseWorktrees: (projectPath: string) => boolean | undefined; // undefined = using global + getEffectiveUseWorktrees: (projectPath: string) => boolean; // Returns actual value (project or global fallback) + // UI State actions (previously in localStorage, now synced via API) setWorktreePanelCollapsed: (collapsed: boolean) => void; setLastProjectDir: (dir: string) => void; @@ -1343,6 +1354,7 @@ const initialState: AppState = { showInitScriptIndicatorByProject: {}, defaultDeleteBranchByProject: {}, autoDismissInitScriptIndicatorByProject: {}, + useWorktreesByProject: {}, // UI State (previously in localStorage, now synced via API) worktreePanelCollapsed: false, lastProjectDir: '', @@ -3526,6 +3538,31 @@ export const useAppStore = create()((set, get) => ({ return get().autoDismissInitScriptIndicatorByProject[projectPath] ?? true; }, + // Use Worktrees Override actions (per-project) + setProjectUseWorktrees: (projectPath, useWorktrees) => { + const newValue = useWorktrees === null ? undefined : useWorktrees; + set({ + useWorktreesByProject: { + ...get().useWorktreesByProject, + [projectPath]: newValue, + }, + }); + }, + + getProjectUseWorktrees: (projectPath) => { + // Returns undefined if using global setting, true/false if project-specific + return get().useWorktreesByProject[projectPath]; + }, + + getEffectiveUseWorktrees: (projectPath) => { + // Returns the actual value to use (project override or global fallback) + const projectSetting = get().useWorktreesByProject[projectPath]; + if (projectSetting !== undefined) { + return projectSetting; + } + return get().useWorktrees; + }, + // UI State actions (previously in localStorage, now synced via API) setWorktreePanelCollapsed: (collapsed) => set({ worktreePanelCollapsed: collapsed }), setLastProjectDir: (dir) => set({ lastProjectDir: dir }), diff --git a/libs/types/src/settings.ts b/libs/types/src/settings.ts index 6e807f66..0715cfc1 100644 --- a/libs/types/src/settings.ts +++ b/libs/types/src/settings.ts @@ -296,6 +296,8 @@ export interface KeyboardShortcuts { context: string; /** Open settings */ settings: string; + /** Open project settings */ + projectSettings: string; /** Open terminal */ terminal: string; /** Toggle sidebar visibility */ @@ -799,6 +801,7 @@ export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = { spec: 'D', context: 'C', settings: 'S', + projectSettings: 'Shift+S', terminal: 'T', toggleSidebar: '`', addFeature: 'N', diff --git a/package-lock.json b/package-lock.json index 1f9e8037..66065929 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "automaker", - "version": "0.12.0rc", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "automaker", - "version": "0.12.0rc", + "version": "1.0.0", "hasInstallScript": true, "workspaces": [ "apps/*", @@ -29,7 +29,7 @@ }, "apps/server": { "name": "@automaker/server", - "version": "0.12.0", + "version": "0.11.0", "license": "SEE LICENSE IN LICENSE", "dependencies": { "@anthropic-ai/claude-agent-sdk": "0.1.76", @@ -80,7 +80,7 @@ }, "apps/ui": { "name": "@automaker/ui", - "version": "0.12.0", + "version": "0.11.0", "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { @@ -2127,76 +2127,11 @@ "node": ">= 10.0.0" } }, - "node_modules/@electron/windows-sign": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz", - "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "dependencies": { - "cross-dirname": "^0.1.0", - "debug": "^4.3.4", - "fs-extra": "^11.1.1", - "minimist": "^1.2.8", - "postject": "^1.0.0-alpha.6" - }, - "bin": { - "electron-windows-sign": "bin/electron-windows-sign.js" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/windows-sign/node_modules/fs-extra": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", - "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/windows-sign/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/windows-sign/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@emnapi/runtime": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -2950,17 +2885,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", @@ -3069,57 +2993,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", - "cpu": [ - "riscv64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@img/sharp-libvips-linux-x64": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", @@ -3212,75 +3085,6 @@ "@img/sharp-libvips-linux-arm64": "1.0.4" } }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", - "cpu": [ - "riscv64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" - } - }, "node_modules/@img/sharp-linux-x64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", @@ -3347,66 +3151,6 @@ "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "peer": true, - "dependencies": { - "@emnapi/runtime": "^1.7.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@img/sharp-win32-x64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", @@ -3795,149 +3539,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, - "node_modules/@next/env": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz", - "integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==", - "license": "MIT", - "peer": true - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.10.tgz", - "integrity": "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.10.tgz", - "integrity": "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.10.tgz", - "integrity": "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.10.tgz", - "integrity": "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.10.tgz", - "integrity": "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.10.tgz", - "integrity": "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.10.tgz", - "integrity": "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.10.tgz", - "integrity": "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/@npmcli/agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", @@ -4031,7 +3632,7 @@ "version": "1.57.0", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "playwright": "1.57.0" @@ -5499,16 +5100,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@swc/helpers": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "tslib": "^2.8.0" - } - }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -6405,6 +5996,7 @@ "version": "19.2.7", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -6414,7 +6006,7 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "devOptional": true, + "dev": true, "license": "MIT", "peerDependencies": { "@types/react": "^19.2.0" @@ -8074,6 +7666,7 @@ "version": "1.0.30001760", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "dev": true, "funding": [ { "type": "opencollective", @@ -8297,13 +7890,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT", - "peer": true - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -8601,15 +8187,6 @@ "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "license": "MIT" }, - "node_modules/cross-dirname": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", - "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/cross-env": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", @@ -8646,6 +8223,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, "license": "MIT" }, "node_modules/d3-color": { @@ -8922,7 +8500,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -9212,19 +8790,6 @@ "node": ">=14.0.0" } }, - "node_modules/electron-builder-squirrel-windows": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz", - "integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", - "electron-winstaller": "5.4.0" - } - }, "node_modules/electron-builder/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -9325,44 +8890,6 @@ "dev": true, "license": "ISC" }, - "node_modules/electron-winstaller": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz", - "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@electron/asar": "^3.2.1", - "debug": "^4.1.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.21", - "temp": "^0.9.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "@electron/windows-sign": "^1.1.2" - } - }, - "node_modules/electron-winstaller/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, "node_modules/electron/node_modules/@types/node": { "version": "22.19.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz", @@ -10810,16 +10337,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hono": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.3.tgz", - "integrity": "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=16.9.0" - } - }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -11585,7 +11102,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11607,7 +11123,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11629,7 +11144,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11651,7 +11165,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11673,7 +11186,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11695,7 +11207,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11717,7 +11228,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11739,7 +11249,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11761,7 +11270,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11783,7 +11291,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -11805,7 +11312,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -13363,6 +12869,7 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, "funding": [ { "type": "github", @@ -13393,59 +12900,6 @@ "node": ">= 0.6" } }, - "node_modules/next": { - "version": "16.0.10", - "resolved": "https://registry.npmjs.org/next/-/next-16.0.10.tgz", - "integrity": "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@next/env": "16.0.10", - "@swc/helpers": "0.5.15", - "caniuse-lite": "^1.0.30001579", - "postcss": "8.4.31", - "styled-jsx": "5.1.6" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=20.9.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "16.0.10", - "@next/swc-darwin-x64": "16.0.10", - "@next/swc-linux-arm64-gnu": "16.0.10", - "@next/swc-linux-arm64-musl": "16.0.10", - "@next/swc-linux-x64-gnu": "16.0.10", - "@next/swc-linux-x64-musl": "16.0.10", - "@next/swc-win32-arm64-msvc": "16.0.10", - "@next/swc-win32-x64-msvc": "16.0.10", - "sharp": "^0.34.4" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.51.1", - "babel-plugin-react-compiler": "*", - "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "babel-plugin-react-compiler": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, "node_modules/node-abi": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.24.0.tgz", @@ -13975,6 +13429,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -14016,7 +13471,7 @@ "version": "1.57.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "playwright-core": "1.57.0" @@ -14035,7 +13490,7 @@ "version": "1.57.0", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" @@ -14074,65 +13529,6 @@ "node": ">=10.4.0" } }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postject": { - "version": "1.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", - "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "commander": "^9.4.0" - }, - "bin": { - "postject": "dist/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/postject/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -14677,21 +14073,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -14808,7 +14189,7 @@ "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "devOptional": true, + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -14914,352 +14295,6 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, - "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" - } - }, - "node_modules/sharp/node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" - } - }, - "node_modules/sharp/node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" - } - }, - "node_modules/sharp/node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" - } - }, - "node_modules/sharp/node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" - } - }, - "node_modules/sharp/node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" - } - }, - "node_modules/sharp/node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" - } - }, - "node_modules/sharp/node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" - } - }, - "node_modules/sharp/node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -15476,6 +14511,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -15716,30 +14752,6 @@ "inline-style-parser": "0.2.7" } }, - "node_modules/styled-jsx": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", - "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", - "license": "MIT", - "peer": true, - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -15885,21 +14897,6 @@ "dev": true, "license": "ISC" }, - "node_modules/temp": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "mkdirp": "^0.5.1", - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/temp-file": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", @@ -15949,20 +14946,6 @@ "node": ">= 10.0.0" } }, - "node_modules/temp/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/tiny-async-pool": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz",