-
+
-
-
-
-
- {activeWorkspace?.worktreePath && (
-
- )}
+
+
+
+
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceInitEffects.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceInitEffects.tsx
deleted file mode 100644
index 3cce23d23..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceInitEffects.tsx
+++ /dev/null
@@ -1,206 +0,0 @@
-import { toast } from "@superset/ui/sonner";
-import { useCallback, useEffect, useRef } from "react";
-import { trpc } from "renderer/lib/trpc";
-import { useOpenConfigModal } from "renderer/stores/config-modal";
-import { useTabsStore } from "renderer/stores/tabs/store";
-import {
- type PendingTerminalSetup,
- useWorkspaceInitStore,
-} from "renderer/stores/workspace-init";
-
-/**
- * Renderless component that handles terminal setup when workspaces become ready.
- *
- * This is mounted at the app root (MainScreen) so it survives dialog unmounts.
- * When a workspace creation is initiated from a dialog (e.g., InitGitDialog,
- * CloneRepoDialog), the dialog may close before initialization completes.
- * This component ensures the terminal is still created when the workspace
- * becomes ready.
- *
- * Also handles the case where pending setup data is lost (e.g., after retry
- * or app restart) by fetching setup commands from the backend on demand.
- */
-export function WorkspaceInitEffects() {
- const initProgress = useWorkspaceInitStore((s) => s.initProgress);
- const pendingTerminalSetups = useWorkspaceInitStore(
- (s) => s.pendingTerminalSetups,
- );
- const removePendingTerminalSetup = useWorkspaceInitStore(
- (s) => s.removePendingTerminalSetup,
- );
- const clearProgress = useWorkspaceInitStore((s) => s.clearProgress);
-
- // Track which setups are currently being processed to prevent duplicate handling
- const processingRef = useRef
>(new Set());
-
- const addTab = useTabsStore((state) => state.addTab);
- const setTabAutoTitle = useTabsStore((state) => state.setTabAutoTitle);
- const createOrAttach = trpc.terminal.createOrAttach.useMutation();
- const openConfigModal = useOpenConfigModal();
- const dismissConfigToast = trpc.config.dismissConfigToast.useMutation();
- const utils = trpc.useUtils();
-
- // Helper to create terminal with setup commands
- const handleTerminalSetup = useCallback(
- (setup: PendingTerminalSetup, onComplete: () => void) => {
- if (
- Array.isArray(setup.initialCommands) &&
- setup.initialCommands.length > 0
- ) {
- const { tabId, paneId } = addTab(setup.workspaceId);
- setTabAutoTitle(tabId, "Workspace Setup");
- createOrAttach.mutate(
- {
- paneId,
- tabId,
- workspaceId: setup.workspaceId,
- initialCommands: setup.initialCommands,
- },
- {
- onSuccess: () => {
- onComplete();
- },
- onError: (error) => {
- console.error(
- "[WorkspaceInitEffects] Failed to create terminal:",
- error,
- );
- toast.error("Failed to create terminal", {
- description:
- error.message || "Terminal setup failed. Please try again.",
- action: {
- label: "Open Terminal",
- onClick: () => {
- // Allow user to manually trigger terminal creation
- const { tabId: newTabId, paneId: newPaneId } = addTab(
- setup.workspaceId,
- );
- createOrAttach.mutate({
- paneId: newPaneId,
- tabId: newTabId,
- workspaceId: setup.workspaceId,
- initialCommands: setup.initialCommands ?? undefined,
- });
- },
- },
- });
- // Still complete to prevent infinite retries
- onComplete();
- },
- },
- );
- } else {
- // Show config toast if no setup commands
- toast.info("No setup script configured", {
- description: "Automate workspace setup with a config.json file",
- action: {
- label: "Configure",
- onClick: () => openConfigModal(setup.projectId),
- },
- onDismiss: () => {
- dismissConfigToast.mutate({ projectId: setup.projectId });
- },
- });
- onComplete();
- }
- },
- [
- addTab,
- setTabAutoTitle,
- createOrAttach,
- openConfigModal,
- dismissConfigToast,
- ],
- );
-
- useEffect(() => {
- // Process pending setups that have reached ready state
- for (const [workspaceId, setup] of Object.entries(pendingTerminalSetups)) {
- const progress = initProgress[workspaceId];
-
- // Skip if already being processed
- if (processingRef.current.has(workspaceId)) {
- continue;
- }
-
- // Create terminal when workspace becomes ready
- if (progress?.step === "ready") {
- // Mark as processing to prevent duplicate handling
- processingRef.current.add(workspaceId);
-
- handleTerminalSetup(setup, () => {
- // Only remove from pending after successful handling
- removePendingTerminalSetup(workspaceId);
- clearProgress(workspaceId);
- processingRef.current.delete(workspaceId);
- });
- }
-
- // Clean up pending if failed (user will use retry or delete)
- // Note: losing pending data is OK now - we fetch on demand when ready
- if (progress?.step === "failed") {
- removePendingTerminalSetup(workspaceId);
- }
- }
-
- // Handle workspaces that became ready without pending setup data
- // (e.g., after retry or app restart during init)
- for (const [workspaceId, progress] of Object.entries(initProgress)) {
- // Only process ready workspaces that don't have pending setup
- if (progress.step !== "ready") {
- continue;
- }
- if (pendingTerminalSetups[workspaceId]) {
- continue; // Already handled above
- }
- if (processingRef.current.has(workspaceId)) {
- continue;
- }
-
- // Mark as processing and fetch setup commands from backend
- processingRef.current.add(workspaceId);
-
- utils.workspaces.getSetupCommands
- .fetch({ workspaceId })
- .then((setupData) => {
- if (!setupData) {
- // Workspace not found or no project - just clear progress
- clearProgress(workspaceId);
- processingRef.current.delete(workspaceId);
- return;
- }
-
- // Create a pending setup from fetched data and handle it
- const fetchedSetup: PendingTerminalSetup = {
- workspaceId,
- projectId: setupData.projectId,
- initialCommands: setupData.initialCommands,
- };
-
- handleTerminalSetup(fetchedSetup, () => {
- clearProgress(workspaceId);
- processingRef.current.delete(workspaceId);
- });
- })
- .catch((error) => {
- console.error(
- "[WorkspaceInitEffects] Failed to fetch setup commands:",
- error,
- );
- // Still clear progress to avoid being stuck
- clearProgress(workspaceId);
- processingRef.current.delete(workspaceId);
- });
- }
- }, [
- initProgress,
- pendingTerminalSetups,
- removePendingTerminalSetup,
- clearProgress,
- handleTerminalSetup,
- utils.workspaces.getSetupCommands,
- ]);
-
- // Renderless component
- return null;
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/index.ts
deleted file mode 100644
index 7f04b50ce..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { PortsList } from "./PortsList";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectHeader.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectHeader.tsx
deleted file mode 100644
index 64bfb4671..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectHeader.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import {
- ContextMenu,
- ContextMenuContent,
- ContextMenuItem,
- ContextMenuSeparator,
- ContextMenuTrigger,
-} from "@superset/ui/context-menu";
-import { toast } from "@superset/ui/sonner";
-import { cn } from "@superset/ui/utils";
-import { LuFolderOpen, LuSettings, LuX } from "react-icons/lu";
-import { trpc } from "renderer/lib/trpc";
-import { useOpenSettings } from "renderer/stores/app-state";
-
-interface ProjectHeaderProps {
- projectId: string;
- projectName: string;
- mainRepoPath: string;
- isCollapsed: boolean;
- onToggleCollapse: () => void;
- workspaceCount: number;
-}
-
-export function ProjectHeader({
- projectId,
- projectName,
- mainRepoPath,
- isCollapsed,
- onToggleCollapse,
- workspaceCount,
-}: ProjectHeaderProps) {
- const utils = trpc.useUtils();
- const openSettings = useOpenSettings();
-
- const closeProject = trpc.projects.close.useMutation({
- onSuccess: (data) => {
- utils.workspaces.getAllGrouped.invalidate();
- utils.workspaces.getActive.invalidate();
- utils.projects.getRecents.invalidate();
- if (data.terminalWarning) {
- toast.warning(data.terminalWarning);
- }
- },
- onError: (error) => {
- toast.error(`Failed to close project: ${error.message}`);
- },
- });
-
- const openInFinder = trpc.external.openInFinder.useMutation({
- onError: (error) => toast.error(`Failed to open: ${error.message}`),
- });
-
- const handleCloseProject = () => {
- closeProject.mutate({ id: projectId });
- };
-
- const handleOpenInFinder = () => {
- openInFinder.mutate(mainRepoPath);
- };
-
- const handleOpenSettings = () => {
- openSettings("project");
- };
-
- return (
-
-
-
-
-
-
-
- Open in Finder
-
-
-
- Project Settings
-
-
-
-
- {closeProject.isPending ? "Closing..." : "Close Project"}
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
deleted file mode 100644
index a0e4152f9..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectSection.tsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@superset/ui/dropdown-menu";
-import { toast } from "@superset/ui/sonner";
-import { AnimatePresence, motion } from "framer-motion";
-import { useState } from "react";
-import { HiMiniPlus, HiOutlineBolt } from "react-icons/hi2";
-import { useCreateWorkspace } from "renderer/react-query/workspaces";
-import { useWorkspaceSidebarStore } from "renderer/stores";
-import { useOpenNewWorkspaceModal } from "renderer/stores/new-workspace-modal";
-import { WorkspaceListItem } from "../WorkspaceListItem";
-import { ProjectHeader } from "./ProjectHeader";
-
-interface Workspace {
- id: string;
- projectId: string;
- worktreePath: string;
- type: "worktree" | "branch";
- branch: string;
- name: string;
- tabOrder: number;
- isUnread: boolean;
-}
-
-interface ProjectSectionProps {
- projectId: string;
- projectName: string;
- mainRepoPath: string;
- workspaces: Workspace[];
- activeWorkspaceId: string | null;
- /** Base index for keyboard shortcuts (0-based) */
- shortcutBaseIndex: number;
-}
-
-export function ProjectSection({
- projectId,
- projectName,
- mainRepoPath,
- workspaces,
- activeWorkspaceId,
- shortcutBaseIndex,
-}: ProjectSectionProps) {
- const [dropdownOpen, setDropdownOpen] = useState(false);
- const { isProjectCollapsed, toggleProjectCollapsed } =
- useWorkspaceSidebarStore();
- const createWorkspace = useCreateWorkspace();
- const openModal = useOpenNewWorkspaceModal();
-
- const isCollapsed = isProjectCollapsed(projectId);
-
- const handleQuickCreate = () => {
- setDropdownOpen(false);
- toast.promise(createWorkspace.mutateAsync({ projectId }), {
- loading: "Creating workspace...",
- success: "Workspace created",
- error: (err) =>
- err instanceof Error ? err.message : "Failed to create workspace",
- });
- };
-
- const handleNewWorkspace = () => {
- setDropdownOpen(false);
- openModal(projectId);
- };
-
- return (
-
-
toggleProjectCollapsed(projectId)}
- workspaceCount={workspaces.length}
- />
-
-
- {!isCollapsed && (
-
-
- {workspaces.map((workspace, index) => (
-
- ))}
-
-
-
-
-
-
-
- New Workspace
-
-
-
- Quick Create
-
-
-
-
-
- )}
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/index.ts
deleted file mode 100644
index 2111af01d..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { ProjectHeader } from "./ProjectHeader";
-export { ProjectSection } from "./ProjectSection";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ResizableWorkspaceSidebar.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ResizableWorkspaceSidebar.tsx
deleted file mode 100644
index 526fa283d..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ResizableWorkspaceSidebar.tsx
+++ /dev/null
@@ -1,94 +0,0 @@
-import { cn } from "@superset/ui/utils";
-import { useCallback, useEffect, useRef } from "react";
-import {
- MAX_WORKSPACE_SIDEBAR_WIDTH,
- MIN_WORKSPACE_SIDEBAR_WIDTH,
- useWorkspaceSidebarStore,
-} from "renderer/stores";
-import { WorkspaceSidebar } from "./WorkspaceSidebar";
-
-export function ResizableWorkspaceSidebar() {
- const { isOpen, width, setWidth, isResizing, setIsResizing } =
- useWorkspaceSidebarStore();
-
- const startXRef = useRef(0);
- const startWidthRef = useRef(0);
-
- const handleMouseDown = useCallback(
- (e: React.MouseEvent) => {
- e.preventDefault();
- startXRef.current = e.clientX;
- startWidthRef.current = width;
- setIsResizing(true);
- },
- [width, setIsResizing],
- );
-
- const handleMouseMove = useCallback(
- (e: MouseEvent) => {
- if (!isResizing) return;
-
- const delta = e.clientX - startXRef.current;
- const newWidth = startWidthRef.current + delta;
- const clampedWidth = Math.max(
- MIN_WORKSPACE_SIDEBAR_WIDTH,
- Math.min(MAX_WORKSPACE_SIDEBAR_WIDTH, newWidth),
- );
- setWidth(clampedWidth);
- },
- [isResizing, setWidth],
- );
-
- const handleMouseUp = useCallback(() => {
- if (isResizing) {
- setIsResizing(false);
- }
- }, [isResizing, setIsResizing]);
-
- useEffect(() => {
- if (isResizing) {
- document.addEventListener("mousemove", handleMouseMove);
- document.addEventListener("mouseup", handleMouseUp);
- document.body.style.userSelect = "none";
- document.body.style.cursor = "col-resize";
- }
-
- return () => {
- document.removeEventListener("mousemove", handleMouseMove);
- document.removeEventListener("mouseup", handleMouseUp);
- document.body.style.userSelect = "";
- document.body.style.cursor = "";
- };
- }, [isResizing, handleMouseMove, handleMouseUp]);
-
- if (!isOpen) {
- return null;
- }
-
- return (
-
-
-
- {/* Resize handle */}
- {/* biome-ignore lint/a11y/useSemanticElements:
is not appropriate for interactive resize handles */}
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceDiffStats.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceDiffStats.tsx
deleted file mode 100644
index a2758d40b..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceDiffStats.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-interface WorkspaceDiffStatsProps {
- additions: number;
- deletions: number;
-}
-
-export function WorkspaceDiffStats({
- additions,
- deletions,
-}: WorkspaceDiffStatsProps) {
- return (
-
- +{additions}
- -{deletions}
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceListItem.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceListItem.tsx
deleted file mode 100644
index 81340b17e..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceListItem.tsx
+++ /dev/null
@@ -1,380 +0,0 @@
-import { Button } from "@superset/ui/button";
-import {
- ContextMenu,
- ContextMenuContent,
- ContextMenuItem,
- ContextMenuSeparator,
- ContextMenuTrigger,
-} from "@superset/ui/context-menu";
-import {
- HoverCard,
- HoverCardContent,
- HoverCardTrigger,
-} from "@superset/ui/hover-card";
-import { Input } from "@superset/ui/input";
-import { toast } from "@superset/ui/sonner";
-import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
-import { cn } from "@superset/ui/utils";
-import { useState } from "react";
-import { useDrag, useDrop } from "react-dnd";
-import { HiMiniXMark } from "react-icons/hi2";
-import { LuEye, LuEyeOff, LuGitBranch } from "react-icons/lu";
-import { trpc } from "renderer/lib/trpc";
-import {
- useReorderWorkspaces,
- useSetActiveWorkspace,
- useWorkspaceDeleteHandler,
-} from "renderer/react-query/workspaces";
-import { useWorkspaceRename } from "renderer/screens/main/hooks/useWorkspaceRename";
-import { useCloseWorkspacesList } from "renderer/stores/app-state";
-import { useTabsStore } from "renderer/stores/tabs/store";
-import { extractPaneIdsFromLayout } from "renderer/stores/tabs/utils";
-import {
- BranchSwitcher,
- DeleteWorkspaceDialog,
- WorkspaceHoverCardContent,
-} from "./components";
-import {
- GITHUB_STATUS_STALE_TIME,
- HOVER_CARD_CLOSE_DELAY,
- HOVER_CARD_OPEN_DELAY,
- MAX_KEYBOARD_SHORTCUT_INDEX,
-} from "./constants";
-import { WorkspaceDiffStats } from "./WorkspaceDiffStats";
-import { WorkspaceStatusBadge } from "./WorkspaceStatusBadge";
-
-const WORKSPACE_TYPE = "WORKSPACE";
-
-interface WorkspaceListItemProps {
- id: string;
- projectId: string;
- worktreePath: string;
- name: string;
- branch: string;
- type: "worktree" | "branch";
- isActive: boolean;
- isUnread?: boolean;
- index: number;
- shortcutIndex?: number;
-}
-
-export function WorkspaceListItem({
- id,
- projectId,
- worktreePath,
- name,
- branch,
- type,
- isActive,
- isUnread = false,
- index,
- shortcutIndex,
-}: WorkspaceListItemProps) {
- const isBranchWorkspace = type === "branch";
- const setActiveWorkspace = useSetActiveWorkspace();
- const reorderWorkspaces = useReorderWorkspaces();
- const closeWorkspacesList = useCloseWorkspacesList();
- const [hasHovered, setHasHovered] = useState(false);
- const rename = useWorkspaceRename(id, name);
- const tabs = useTabsStore((s) => s.tabs);
- const panes = useTabsStore((s) => s.panes);
- const clearWorkspaceAttention = useTabsStore(
- (s) => s.clearWorkspaceAttention,
- );
- const utils = trpc.useUtils();
- const openInFinder = trpc.external.openInFinder.useMutation({
- onError: (error) => toast.error(`Failed to open: ${error.message}`),
- });
- const setUnread = trpc.workspaces.setUnread.useMutation({
- onSuccess: () => {
- utils.workspaces.getAllGrouped.invalidate();
- },
- onError: (error) =>
- toast.error(`Failed to update unread status: ${error.message}`),
- });
-
- // Shared delete logic
- const { showDeleteDialog, setShowDeleteDialog, handleDeleteClick } =
- useWorkspaceDeleteHandler();
-
- // Lazy-load GitHub status on hover to avoid N+1 queries
- const { data: githubStatus } = trpc.workspaces.getGitHubStatus.useQuery(
- { workspaceId: id },
- {
- enabled: hasHovered && type === "worktree",
- staleTime: GITHUB_STATUS_STALE_TIME,
- },
- );
-
- // Check if any pane in tabs belonging to this workspace needs attention (agent notifications)
- const workspaceTabs = tabs.filter((t) => t.workspaceId === id);
- const workspacePaneIds = new Set(
- workspaceTabs.flatMap((t) => extractPaneIdsFromLayout(t.layout)),
- );
- const hasPaneAttention = Object.values(panes)
- .filter((p) => p != null && workspacePaneIds.has(p.id))
- .some((p) => p.needsAttention);
-
- // Show indicator if workspace is manually marked as unread OR has pane-level attention
- const needsAttention = isUnread || hasPaneAttention;
-
- const handleClick = () => {
- if (!rename.isRenaming) {
- setActiveWorkspace.mutate({ id });
- clearWorkspaceAttention(id);
- // Close workspaces list view if open, to show the workspace's terminal view
- closeWorkspacesList();
- }
- };
-
- const handleMouseEnter = () => {
- if (!hasHovered) {
- setHasHovered(true);
- }
- };
-
- const handleOpenInFinder = () => {
- if (worktreePath) {
- openInFinder.mutate(worktreePath);
- }
- };
-
- const handleToggleUnread = () => {
- setUnread.mutate({ id, isUnread: !isUnread });
- };
-
- // Drag and drop
- const [{ isDragging }, drag] = useDrag(
- () => ({
- type: WORKSPACE_TYPE,
- item: { id, projectId, index },
- collect: (monitor) => ({
- isDragging: monitor.isDragging(),
- }),
- }),
- [id, projectId, index],
- );
-
- const [, drop] = useDrop({
- accept: WORKSPACE_TYPE,
- hover: (item: { id: string; projectId: string; index: number }) => {
- if (item.projectId === projectId && item.index !== index) {
- reorderWorkspaces.mutate(
- {
- projectId,
- fromIndex: item.index,
- toIndex: index,
- },
- {
- onError: (error) =>
- toast.error(`Failed to reorder workspace: ${error.message}`),
- },
- );
- item.index = index;
- }
- },
- });
-
- const pr = githubStatus?.pr;
- const showDiffStats = pr && (pr.additions > 0 || pr.deletions > 0);
-
- const content = (
-
- );
-
- const unreadMenuItem = (
-
- {isUnread ? (
- <>
-
- Mark as Read
- >
- ) : (
- <>
-
- Mark as Unread
- >
- )}
-
- );
-
- // Wrap with context menu and hover card
- if (isBranchWorkspace) {
- return (
- <>
-
- {content}
-
-
- Open in Finder
-
-
- {unreadMenuItem}
-
-
-
- >
- );
- }
-
- return (
- <>
-
-
-
- {content}
-
-
-
- Rename
-
-
-
- Open in Finder
-
-
- {unreadMenuItem}
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceStatusBadge.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceStatusBadge.tsx
deleted file mode 100644
index d6eb509d7..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceStatusBadge.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import { cn } from "@superset/ui/utils";
-import { LuCircleDot, LuGitMerge, LuGitPullRequest } from "react-icons/lu";
-
-type PRState = "open" | "merged" | "closed" | "draft";
-
-interface WorkspaceStatusBadgeProps {
- state: PRState;
- prNumber?: number;
-}
-
-export function WorkspaceStatusBadge({
- state,
- prNumber,
-}: WorkspaceStatusBadgeProps) {
- const iconClass = "w-3 h-3";
-
- const config = {
- open: {
- icon: ,
- bgColor: "bg-emerald-500/10",
- },
- merged: {
- icon: ,
- bgColor: "bg-purple-500/10",
- },
- closed: {
- icon: ,
- bgColor: "bg-destructive/10",
- },
- draft: {
- icon: (
-
- ),
- bgColor: "bg-muted",
- },
- };
-
- const { icon, bgColor } = config[state];
-
- return (
-
- {icon}
- {prNumber && (
- #{prNumber}
- )}
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/index.ts
deleted file mode 100644
index 369ca7198..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { DeleteWorkspaceDialog } from "./DeleteWorkspaceDialog";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/index.ts
deleted file mode 100644
index 282bf9f9a..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export { BranchSwitcher } from "./BranchSwitcher";
-export { DeleteWorkspaceDialog } from "./DeleteWorkspaceDialog";
-export { WorkspaceHoverCardContent } from "./WorkspaceHoverCard";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/constants.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/constants.ts
deleted file mode 100644
index b6768dfb7..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/constants.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Constants for workspace list item behavior
- */
-
-/** Maximum index for keyboard shortcuts (Cmd+1 through Cmd+9) */
-export const MAX_KEYBOARD_SHORTCUT_INDEX = 9;
-
-/** Stale time for GitHub status queries (30 seconds) */
-export const GITHUB_STATUS_STALE_TIME = 30_000;
-
-/** Delay before showing hover card (ms) */
-export const HOVER_CARD_OPEN_DELAY = 400;
-
-/** Delay before hiding hover card (ms) */
-export const HOVER_CARD_CLOSE_DELAY = 100;
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/index.ts
deleted file mode 100644
index 4dd9ef18a..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export { WorkspaceDiffStats } from "./WorkspaceDiffStats";
-export { WorkspaceListItem } from "./WorkspaceListItem";
-export { WorkspaceStatusBadge } from "./WorkspaceStatusBadge";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsx
deleted file mode 100644
index 4ffc0650a..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebar.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { useMemo } from "react";
-import { useWorkspaceShortcuts } from "renderer/hooks/useWorkspaceShortcuts";
-import { PortsList } from "./PortsList";
-import { ProjectSection } from "./ProjectSection";
-import { WorkspaceSidebarFooter } from "./WorkspaceSidebarFooter";
-import { WorkspaceSidebarHeader } from "./WorkspaceSidebarHeader";
-
-export function WorkspaceSidebar() {
- const { groups, activeWorkspaceId } = useWorkspaceShortcuts();
-
- // Calculate shortcut base indices for each project group using cumulative offsets
- const projectShortcutIndices = useMemo(
- () =>
- groups.reduce<{ indices: number[]; cumulative: number }>(
- (acc, group) => ({
- indices: [...acc.indices, acc.cumulative],
- cumulative: acc.cumulative + group.workspaces.length,
- }),
- { indices: [], cumulative: 0 },
- ).indices,
- [groups],
- );
-
- return (
-
-
-
-
- {groups.map((group, index) => (
-
- ))}
-
- {groups.length === 0 && (
-
- No workspaces yet
- Add a project to get started
-
- )}
-
-
-
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarFooter.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarFooter.tsx
deleted file mode 100644
index 3a0b6d1c7..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarFooter.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { Button } from "@superset/ui/button";
-import { toast } from "@superset/ui/sonner";
-import { LuFolderOpen } from "react-icons/lu";
-import { useOpenNew } from "renderer/react-query/projects";
-import { useCreateBranchWorkspace } from "renderer/react-query/workspaces";
-
-export function WorkspaceSidebarFooter() {
- const openNew = useOpenNew();
- const createBranchWorkspace = useCreateBranchWorkspace();
-
- const handleOpenNewProject = async () => {
- try {
- const result = await openNew.mutateAsync(undefined);
- if (result.canceled) {
- return;
- }
- if ("error" in result) {
- toast.error("Failed to open project", {
- description: result.error,
- });
- return;
- }
- if ("needsGitInit" in result) {
- toast.error("Selected folder is not a git repository", {
- description:
- "Please use 'Open project' from the start view to initialize git.",
- });
- return;
- }
- // Create a main workspace on the current branch for the new project
- toast.promise(
- createBranchWorkspace.mutateAsync({ projectId: result.project.id }),
- {
- loading: "Opening project...",
- success: "Project opened",
- error: (err) =>
- err instanceof Error ? err.message : "Failed to open project",
- },
- );
- } catch (error) {
- toast.error("Failed to open project", {
- description:
- error instanceof Error ? error.message : "An unknown error occurred",
- });
- }
- };
-
- return (
-
-
-
- Add repository
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/NewWorkspaceButton.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/NewWorkspaceButton.tsx
deleted file mode 100644
index 0f392fe62..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/NewWorkspaceButton.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { LuPlus } from "react-icons/lu";
-import { trpc } from "renderer/lib/trpc";
-import { useOpenNewWorkspaceModal } from "renderer/stores/new-workspace-modal";
-
-export function NewWorkspaceButton() {
- const openModal = useOpenNewWorkspaceModal();
- const { data: activeWorkspace, isLoading } =
- trpc.workspaces.getActive.useQuery();
-
- const handleClick = () => {
- // projectId may be undefined if no workspace is active or query failed
- // openModal handles undefined by opening without a pre-selected project
- const projectId = activeWorkspace?.projectId;
- openModal(projectId);
- };
-
- return (
-
-
-
-
- New Workspace
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx
deleted file mode 100644
index 9103919cf..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { cn } from "@superset/ui/utils";
-import { LuLayers } from "react-icons/lu";
-import {
- useCloseWorkspacesList,
- useCurrentView,
- useOpenWorkspacesList,
-} from "renderer/stores/app-state";
-import { NewWorkspaceButton } from "./NewWorkspaceButton";
-
-export function WorkspaceSidebarHeader() {
- const currentView = useCurrentView();
- const openWorkspacesList = useOpenWorkspacesList();
- const closeWorkspacesList = useCloseWorkspacesList();
-
- const isWorkspacesListOpen = currentView === "workspaces-list";
-
- const handleClick = () => {
- if (isWorkspacesListOpen) {
- closeWorkspacesList();
- } else {
- openWorkspacesList();
- }
- };
-
- return (
-
-
-
-
-
- Workspaces
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/index.ts
deleted file mode 100644
index 844ddc41e..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { WorkspaceSidebarHeader } from "./WorkspaceSidebarHeader";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/index.ts
deleted file mode 100644
index d8dc22673..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { ResizableWorkspaceSidebar } from "./ResizableWorkspaceSidebar";
-export { WorkspaceSidebar } from "./WorkspaceSidebar";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
index 355d70a1c..abcc51d51 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/DiffViewer.tsx
@@ -1,15 +1,16 @@
import { DiffEditor, type DiffOnMount } from "@monaco-editor/react";
import type * as Monaco from "monaco-editor";
-import { useCallback, useEffect, useRef, useState } from "react";
+import { useCallback, useRef } from "react";
import { LuLoader } from "react-icons/lu";
import {
- MONACO_EDITOR_OPTIONS,
- registerSaveAction,
SUPERSET_THEME,
useMonacoReady,
} from "renderer/contexts/MonacoProvider";
import type { DiffViewMode, FileContents } from "shared/changes-types";
-import { registerCopyPathLineAction } from "./editor-actions";
+import {
+ registerCopyPathLineAction,
+ registerSaveCommand,
+} from "./editor-actions";
interface DiffViewerProps {
contents: FileContents;
@@ -17,7 +18,6 @@ interface DiffViewerProps {
filePath: string;
editable?: boolean;
onSave?: (content: string) => void;
- onChange?: (content: string) => void;
}
export function DiffViewer({
@@ -26,23 +26,17 @@ export function DiffViewer({
filePath,
editable = false,
onSave,
- onChange,
}: DiffViewerProps) {
const isMonacoReady = useMonacoReady();
const modifiedEditorRef = useRef(
null,
);
- // Track when editor is mounted to trigger effects at the right time
- const [isEditorMounted, setIsEditorMounted] = useState(false);
const handleSave = useCallback(() => {
if (!editable || !onSave || !modifiedEditorRef.current) return;
onSave(modifiedEditorRef.current.getValue());
}, [editable, onSave]);
- // Store disposable for content change listener cleanup
- const changeListenerRef = useRef(null);
-
const handleMount: DiffOnMount = useCallback(
(editor) => {
const originalEditor = editor.getOriginalEditor();
@@ -52,43 +46,13 @@ export function DiffViewer({
registerCopyPathLineAction(originalEditor, filePath);
registerCopyPathLineAction(modifiedEditor, filePath);
- setIsEditorMounted(true);
+ if (editable) {
+ registerSaveCommand(modifiedEditor, handleSave);
+ }
},
- [filePath],
+ [editable, handleSave, filePath],
);
- // Update readOnly and register save action when editable changes or editor mounts
- // Using addAction with an ID allows replacing the action on subsequent calls
- useEffect(() => {
- if (!isEditorMounted || !modifiedEditorRef.current) return;
-
- modifiedEditorRef.current.updateOptions({ readOnly: !editable });
-
- if (editable) {
- registerSaveAction(modifiedEditorRef.current, handleSave);
- }
- }, [isEditorMounted, editable, handleSave]);
-
- // Set up content change listener for dirty tracking
- useEffect(() => {
- if (!isEditorMounted || !modifiedEditorRef.current || !onChange) return;
-
- // Clean up previous listener
- changeListenerRef.current?.dispose();
-
- changeListenerRef.current =
- modifiedEditorRef.current.onDidChangeModelContent(() => {
- if (modifiedEditorRef.current) {
- onChange(modifiedEditorRef.current.getValue());
- }
- });
-
- return () => {
- changeListenerRef.current?.dispose();
- changeListenerRef.current = null;
- };
- }, [isEditorMounted, onChange]);
-
if (!isMonacoReady) {
return (
@@ -114,12 +78,23 @@ export function DiffViewer({
}
options={{
- ...MONACO_EDITOR_OPTIONS,
renderSideBySide: viewMode === "side-by-side",
readOnly: !editable,
originalEditable: false,
+ minimap: { enabled: false },
+ scrollBeyondLastLine: false,
renderOverviewRuler: false,
+ wordWrap: "on",
diffWordWrap: "on",
+ fontSize: 13,
+ lineHeight: 20,
+ fontFamily:
+ "ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace",
+ padding: { top: 8, bottom: 8 },
+ scrollbar: {
+ verticalScrollbarSize: 8,
+ horizontalScrollbarSize: 8,
+ },
}}
/>
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/editor-actions.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/editor-actions.ts
index 447ffe35f..7a5bb9c59 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/editor-actions.ts
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ChangesContent/components/DiffViewer/editor-actions.ts
@@ -27,3 +27,10 @@ export function registerCopyPathLineAction(
},
});
}
+
+export function registerSaveCommand(
+ editor: Monaco.editor.IStandaloneCodeEditor,
+ onSave: () => void,
+) {
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, onSave);
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ContentHeader/ContentHeader.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ContentHeader/ContentHeader.tsx
deleted file mode 100644
index cbc1deac5..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ContentHeader/ContentHeader.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { ReactNode } from "react";
-
-interface ContentHeaderProps {
- /** Optional leading action */
- leadingAction?: ReactNode;
- /** Mode-specific header content (e.g., GroupStrip or file info) */
- children: ReactNode;
- /** Optional trailing action (e.g., SidebarControl) */
- trailingAction?: ReactNode;
-}
-
-export function ContentHeader({
- leadingAction,
- children,
- trailingAction,
-}: ContentHeaderProps) {
- return (
-
- {leadingAction && (
-
{leadingAction}
- )}
-
{children}
- {trailingAction && (
-
{trailingAction}
- )}
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ContentHeader/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ContentHeader/index.ts
deleted file mode 100644
index 26fb6ccbc..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ContentHeader/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ContentHeader } from "./ContentHeader";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/EmptyTabView.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/EmptyTabView.tsx
index 3d984e3aa..0f9a435a8 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/EmptyTabView.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/EmptyTabView.tsx
@@ -3,16 +3,16 @@ import { HiMiniCommandLine } from "react-icons/hi2";
import { useHotkeyDisplay } from "renderer/stores/hotkeys";
export function EmptyTabView() {
- const newGroupDisplay = useHotkeyDisplay("NEW_GROUP");
+ const newTerminalDisplay = useHotkeyDisplay("NEW_TERMINAL");
const openInAppDisplay = useHotkeyDisplay("OPEN_IN_APP");
const shortcuts = [
- { label: "New Tab", display: newGroupDisplay },
+ { label: "New Terminal", display: newTerminalDisplay },
{ label: "Open in App", display: openInAppDisplay },
];
return (
-
+
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx
deleted file mode 100644
index 5154b0d01..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import { Button } from "@superset/ui/button";
-import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
-import { cn } from "@superset/ui/utils";
-import { HiMiniXMark } from "react-icons/hi2";
-import type { Tab } from "renderer/stores/tabs/types";
-import { getTabDisplayName } from "renderer/stores/tabs/utils";
-
-interface GroupItemProps {
- tab: Tab;
- isActive: boolean;
- needsAttention: boolean;
- onSelect: () => void;
- onClose: () => void;
-}
-
-export function GroupItem({
- tab,
- isActive,
- needsAttention,
- onSelect,
- onClose,
-}: GroupItemProps) {
- const displayName = getTabDisplayName(tab);
-
- return (
-
-
-
-
-
- {displayName}
-
- {needsAttention && (
-
-
-
-
- )}
-
-
-
- {displayName}
-
-
-
-
- {
- e.stopPropagation();
- onClose();
- }}
- className={cn(
- "absolute right-1 top-1/2 -translate-y-1/2 cursor-pointer size-5 group-hover:opacity-100",
- isActive ? "opacity-90" : "opacity-0",
- )}
- aria-label="Close group"
- >
-
-
-
-
- Close group
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx
deleted file mode 100644
index 54863a005..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx
+++ /dev/null
@@ -1,220 +0,0 @@
-import type { TerminalPreset } from "@superset/local-db";
-import { Button } from "@superset/ui/button";
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuSeparator,
- DropdownMenuTrigger,
-} from "@superset/ui/dropdown-menu";
-import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
-import { useCallback, useMemo, useRef, useState } from "react";
-import {
- HiMiniChevronDown,
- HiMiniCog6Tooth,
- HiMiniCommandLine,
- HiMiniPlus,
-} from "react-icons/hi2";
-import {
- getPresetIcon,
- useIsDarkTheme,
-} from "renderer/assets/app-icons/preset-icons";
-import { HotkeyTooltipContent } from "renderer/components/HotkeyTooltipContent";
-import { trpc } from "renderer/lib/trpc";
-import { usePresets } from "renderer/react-query/presets";
-import { useOpenSettings } from "renderer/stores";
-import { useTabsStore } from "renderer/stores/tabs/store";
-import { GroupItem } from "./GroupItem";
-
-export function GroupStrip() {
- const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
- const activeWorkspaceId = activeWorkspace?.id;
-
- const allTabs = useTabsStore((s) => s.tabs);
- const panes = useTabsStore((s) => s.panes);
- const activeTabIds = useTabsStore((s) => s.activeTabIds);
- const addTab = useTabsStore((s) => s.addTab);
- const renameTab = useTabsStore((s) => s.renameTab);
- const removeTab = useTabsStore((s) => s.removeTab);
- const setActiveTab = useTabsStore((s) => s.setActiveTab);
-
- const { presets } = usePresets();
- const isDark = useIsDarkTheme();
- const openSettings = useOpenSettings();
- const [dropdownOpen, setDropdownOpen] = useState(false);
- const hoverTimeoutRef = useRef
| null>(null);
-
- const handleDropdownMouseEnter = useCallback(() => {
- if (hoverTimeoutRef.current) {
- clearTimeout(hoverTimeoutRef.current);
- }
- hoverTimeoutRef.current = setTimeout(() => {
- setDropdownOpen(true);
- }, 150);
- }, []);
-
- const handleDropdownMouseLeave = useCallback(() => {
- if (hoverTimeoutRef.current) {
- clearTimeout(hoverTimeoutRef.current);
- }
- hoverTimeoutRef.current = setTimeout(() => {
- setDropdownOpen(false);
- }, 150);
- }, []);
-
- const tabs = useMemo(
- () =>
- activeWorkspaceId
- ? allTabs.filter((tab) => tab.workspaceId === activeWorkspaceId)
- : [],
- [activeWorkspaceId, allTabs],
- );
-
- const activeTabId = activeWorkspaceId
- ? activeTabIds[activeWorkspaceId]
- : null;
-
- // Check which tabs have panes that need attention
- const tabsWithAttention = useMemo(() => {
- const result = new Set();
- for (const pane of Object.values(panes)) {
- if (pane.needsAttention) {
- result.add(pane.tabId);
- }
- }
- return result;
- }, [panes]);
-
- const handleAddGroup = () => {
- if (activeWorkspaceId) {
- addTab(activeWorkspaceId);
- }
- };
-
- const handleSelectPreset = (preset: TerminalPreset) => {
- if (!activeWorkspaceId) return;
-
- const { tabId } = addTab(activeWorkspaceId, {
- initialCommands: preset.commands,
- initialCwd: preset.cwd || undefined,
- });
-
- if (preset.name) {
- renameTab(tabId, preset.name);
- }
-
- setDropdownOpen(false);
- };
-
- const handleOpenPresetsSettings = () => {
- openSettings("presets");
- setDropdownOpen(false);
- };
-
- const handleSelectGroup = (tabId: string) => {
- if (activeWorkspaceId) {
- setActiveTab(activeWorkspaceId, tabId);
- }
- };
-
- const handleCloseGroup = (tabId: string) => {
- removeTab(tabId);
- };
-
- return (
-
- {tabs.length > 0 && (
-
- {tabs.map((tab) => (
-
- handleSelectGroup(tab.id)}
- onClose={() => handleCloseGroup(tab.id)}
- />
-
- ))}
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {presets.length > 0 && (
- <>
- {presets.map((preset) => {
- const presetIcon = getPresetIcon(preset.name, isDark);
- return (
- handleSelectPreset(preset)}
- className="gap-2"
- >
- {presetIcon ? (
-
- ) : (
-
- )}
- {preset.name || "default"}
-
- );
- })}
-
- >
- )}
-
-
- Configure Presets
-
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/index.ts
deleted file mode 100644
index e905a6c8b..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { GroupStrip } from "./GroupStrip";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
deleted file mode 100644
index 146be2b36..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
+++ /dev/null
@@ -1,304 +0,0 @@
-import type * as Monaco from "monaco-editor";
-import { useCallback, useEffect, useRef, useState } from "react";
-import type { MosaicBranch } from "react-mosaic-component";
-import { useTabsStore } from "renderer/stores/tabs/store";
-import type { Pane } from "renderer/stores/tabs/types";
-import type { FileViewerMode } from "shared/tabs-types";
-import { BasePaneWindow } from "../components";
-import { FileViewerContent } from "./components/FileViewerContent";
-import { FileViewerToolbar } from "./components/FileViewerToolbar";
-import { useFileContent } from "./hooks/useFileContent";
-import { useFileSave } from "./hooks/useFileSave";
-import { UnsavedChangesDialog } from "./UnsavedChangesDialog";
-
-interface FileViewerPaneProps {
- paneId: string;
- path: MosaicBranch[];
- pane: Pane;
- isActive: boolean;
- tabId: string;
- worktreePath: string;
- splitPaneAuto: (
- tabId: string,
- sourcePaneId: string,
- dimensions: { width: number; height: number },
- path?: MosaicBranch[],
- ) => void;
- removePane: (paneId: string) => void;
- setFocusedPane: (tabId: string, paneId: string) => void;
-}
-
-export function FileViewerPane({
- paneId,
- path,
- pane,
- isActive,
- tabId,
- worktreePath,
- splitPaneAuto,
- removePane,
- setFocusedPane,
-}: FileViewerPaneProps) {
- const editorRef = useRef(null);
- const [isDirty, setIsDirty] = useState(false);
- const originalContentRef = useRef("");
- const draftContentRef = useRef(null);
- const originalDiffContentRef = useRef("");
- const currentDiffContentRef = useRef("");
- const [showUnsavedDialog, setShowUnsavedDialog] = useState(false);
- const [isSavingAndSwitching, setIsSavingAndSwitching] = useState(false);
- const pendingModeRef = useRef(null);
-
- const fileViewer = pane.fileViewer;
- const filePath = fileViewer?.filePath ?? "";
- const viewMode = fileViewer?.viewMode ?? "raw";
- const isLocked = fileViewer?.isLocked ?? false;
- const diffCategory = fileViewer?.diffCategory;
- const commitHash = fileViewer?.commitHash;
- const oldPath = fileViewer?.oldPath;
- const initialLine = fileViewer?.initialLine;
- const initialColumn = fileViewer?.initialColumn;
-
- const { handleSaveRaw, handleSaveDiff, isSaving } = useFileSave({
- worktreePath,
- filePath,
- paneId,
- diffCategory,
- editorRef,
- originalContentRef,
- originalDiffContentRef,
- draftContentRef,
- setIsDirty,
- });
-
- const { rawFileData, isLoadingRaw, diffData, isLoadingDiff } = useFileContent(
- {
- worktreePath,
- filePath,
- viewMode,
- diffCategory,
- commitHash,
- oldPath,
- isDirty,
- originalContentRef,
- originalDiffContentRef,
- },
- );
-
- const handleEditorChange = useCallback((value: string | undefined) => {
- if (value === undefined) return;
- if (originalContentRef.current === "") {
- originalContentRef.current = value;
- return;
- }
- setIsDirty(value !== originalContentRef.current);
- }, []);
-
- // biome-ignore lint/correctness/useExhaustiveDependencies: Reset on file change only
- useEffect(() => {
- setIsDirty(false);
- originalContentRef.current = "";
- draftContentRef.current = null;
- }, [filePath]);
-
- const handleDiffChange = useCallback((content: string) => {
- currentDiffContentRef.current = content;
- if (originalDiffContentRef.current === "") {
- originalDiffContentRef.current = content;
- return;
- }
- setIsDirty(content !== originalDiffContentRef.current);
- }, []);
-
- if (!fileViewer) {
- return (
- }
- >
-
- No file viewer state
-
-
- );
- }
-
- const handleToggleLock = () => {
- const panes = useTabsStore.getState().panes;
- const currentPane = panes[paneId];
- if (currentPane?.fileViewer) {
- useTabsStore.setState({
- panes: {
- ...panes,
- [paneId]: {
- ...currentPane,
- fileViewer: {
- ...currentPane.fileViewer,
- isLocked: !currentPane.fileViewer.isLocked,
- },
- },
- },
- });
- }
- };
-
- const switchToMode = (newMode: FileViewerMode) => {
- const panes = useTabsStore.getState().panes;
- const currentPane = panes[paneId];
- if (currentPane?.fileViewer) {
- useTabsStore.setState({
- panes: {
- ...panes,
- [paneId]: {
- ...currentPane,
- fileViewer: {
- ...currentPane.fileViewer,
- viewMode: newMode,
- },
- },
- },
- });
- }
- };
-
- const handleViewModeChange = (value: string) => {
- if (!value) return;
- const newMode = value as FileViewerMode;
-
- if (isDirty && newMode !== viewMode) {
- pendingModeRef.current = newMode;
- setShowUnsavedDialog(true);
- return;
- }
-
- switchToMode(newMode);
- };
-
- const handleSaveAndSwitch = async () => {
- if (!pendingModeRef.current) return;
-
- setIsSavingAndSwitching(true);
- try {
- if (viewMode === "raw" && editorRef.current) {
- const savedContent = editorRef.current.getValue();
- await handleSaveRaw();
- originalContentRef.current = savedContent;
- originalDiffContentRef.current = "";
- } else if (
- viewMode === "diff" &&
- currentDiffContentRef.current !== undefined
- ) {
- const savedContent = currentDiffContentRef.current;
- await handleSaveDiff(savedContent);
- originalDiffContentRef.current = savedContent;
- originalContentRef.current = "";
- }
-
- setIsDirty(false);
- draftContentRef.current = null;
- currentDiffContentRef.current = "";
-
- switchToMode(pendingModeRef.current);
- pendingModeRef.current = null;
- setShowUnsavedDialog(false);
- } catch (error) {
- console.error("[FileViewerPane] Save failed:", error);
- } finally {
- setIsSavingAndSwitching(false);
- }
- };
-
- const handleDiscardAndSwitch = () => {
- if (!pendingModeRef.current) return;
-
- if (viewMode === "raw" && editorRef.current) {
- editorRef.current.setValue(originalContentRef.current);
- }
-
- setIsDirty(false);
- draftContentRef.current = null;
- currentDiffContentRef.current = "";
-
- switchToMode(pendingModeRef.current);
- pendingModeRef.current = null;
- };
-
- const fileName = filePath.split("/").pop() || filePath;
- const isMarkdown =
- filePath.endsWith(".md") ||
- filePath.endsWith(".markdown") ||
- filePath.endsWith(".mdx");
- const hasDiff = !!diffCategory;
- const hasDraft = draftContentRef.current !== null;
- const isDiffEditable =
- (diffCategory === "staged" || diffCategory === "unstaged") && !hasDraft;
- const showEditableBadge =
- viewMode === "raw" || (viewMode === "diff" && isDiffEditable);
-
- return (
- <>
- (
-
-
-
- )}
- >
-
-
-
- >
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/UnsavedChangesDialog.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/UnsavedChangesDialog.tsx
deleted file mode 100644
index 98c47db44..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/UnsavedChangesDialog.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import {
- AlertDialog,
- AlertDialogAction,
- AlertDialogCancel,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogTitle,
-} from "@superset/ui/alert-dialog";
-import { Button } from "@superset/ui/button";
-import { LuLoader } from "react-icons/lu";
-
-interface UnsavedChangesDialogProps {
- open: boolean;
- onOpenChange: (open: boolean) => void;
- onSaveAndSwitch: () => void;
- onDiscardAndSwitch: () => void;
- isSaving?: boolean;
-}
-
-export function UnsavedChangesDialog({
- open,
- onOpenChange,
- onSaveAndSwitch,
- onDiscardAndSwitch,
- isSaving = false,
-}: UnsavedChangesDialogProps) {
- const handleSaveAndSwitch = (e: React.MouseEvent) => {
- e.preventDefault();
- onSaveAndSwitch();
- // Don't close dialog - parent will close on success
- };
-
- const handleDiscardAndSwitch = (e: React.MouseEvent) => {
- e.preventDefault();
- onDiscardAndSwitch();
- onOpenChange(false);
- };
-
- return (
-
-
-
- Unsaved Changes
-
- You have unsaved changes. What would you like to do?
-
-
-
- Cancel
-
- Discard & Switch
-
-
- {isSaving ? (
- <>
-
- Saving...
- >
- ) : (
- "Save & Switch"
- )}
-
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
deleted file mode 100644
index f6945203d..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
+++ /dev/null
@@ -1,232 +0,0 @@
-import Editor, { type OnMount } from "@monaco-editor/react";
-import type * as Monaco from "monaco-editor";
-import { type MutableRefObject, useCallback, useEffect, useRef } from "react";
-import { LuLoader } from "react-icons/lu";
-import { MarkdownRenderer } from "renderer/components/MarkdownRenderer";
-import {
- MONACO_EDITOR_OPTIONS,
- registerSaveAction,
- SUPERSET_THEME,
- useMonacoReady,
-} from "renderer/contexts/MonacoProvider";
-import { detectLanguage } from "shared/detect-language";
-import type { FileViewerMode } from "shared/tabs-types";
-import { DiffViewer } from "../../../../../ChangesContent/components/DiffViewer";
-
-interface RawFileData {
- ok: true;
- content: string;
-}
-
-interface RawFileError {
- ok: false;
- reason:
- | "too-large"
- | "binary"
- | "outside-worktree"
- | "symlink-escape"
- | "not-found";
-}
-
-type RawFileResult = RawFileData | RawFileError | undefined;
-
-interface DiffData {
- original: string;
- modified: string;
- language: string;
-}
-
-interface FileViewerContentProps {
- viewMode: FileViewerMode;
- filePath: string;
- isLoadingRaw: boolean;
- isLoadingDiff: boolean;
- rawFileData: RawFileResult;
- diffData: DiffData | undefined;
- isDiffEditable: boolean;
- editorRef: MutableRefObject;
- originalContentRef: MutableRefObject;
- draftContentRef: MutableRefObject;
- initialLine?: number;
- initialColumn?: number;
- onSaveRaw: () => Promise;
- onSaveDiff?: (content: string) => Promise;
- onEditorChange: (value: string | undefined) => void;
- onDiffChange?: (content: string) => void;
- setIsDirty: (dirty: boolean) => void;
-}
-
-export function FileViewerContent({
- viewMode,
- filePath,
- isLoadingRaw,
- isLoadingDiff,
- rawFileData,
- diffData,
- isDiffEditable,
- editorRef,
- originalContentRef,
- draftContentRef,
- initialLine,
- initialColumn,
- onSaveRaw,
- onSaveDiff,
- onEditorChange,
- onDiffChange,
- setIsDirty,
-}: FileViewerContentProps) {
- const isMonacoReady = useMonacoReady();
- const hasAppliedInitialLocationRef = useRef(false);
-
- // biome-ignore lint/correctness/useExhaustiveDependencies: Reset on file change only
- useEffect(() => {
- hasAppliedInitialLocationRef.current = false;
- }, [filePath]);
-
- // biome-ignore lint/correctness/useExhaustiveDependencies: Only reset when coordinates change
- useEffect(() => {
- hasAppliedInitialLocationRef.current = false;
- }, [initialLine, initialColumn]);
-
- const handleEditorMount: OnMount = useCallback(
- (editor) => {
- editorRef.current = editor;
- if (!draftContentRef.current) {
- originalContentRef.current = editor.getValue();
- }
- setIsDirty(editor.getValue() !== originalContentRef.current);
- registerSaveAction(editor, onSaveRaw);
- },
- [onSaveRaw, editorRef, originalContentRef, draftContentRef, setIsDirty],
- );
-
- useEffect(() => {
- if (
- viewMode !== "raw" ||
- !editorRef.current ||
- !initialLine ||
- hasAppliedInitialLocationRef.current ||
- isLoadingRaw ||
- !rawFileData?.ok
- ) {
- return;
- }
-
- const editor = editorRef.current;
- const model = editor.getModel();
- if (!model) return;
-
- const lineCount = model.getLineCount();
- const safeLine = Math.max(1, Math.min(initialLine, lineCount));
- const maxColumn = model.getLineMaxColumn(safeLine);
- const safeColumn = Math.max(1, Math.min(initialColumn ?? 1, maxColumn));
-
- const position = { lineNumber: safeLine, column: safeColumn };
- editor.setPosition(position);
- editor.revealPositionInCenter(position);
- editor.focus();
-
- hasAppliedInitialLocationRef.current = true;
- }, [
- viewMode,
- initialLine,
- initialColumn,
- isLoadingRaw,
- rawFileData,
- editorRef,
- ]);
-
- if (viewMode === "diff") {
- if (isLoadingDiff) {
- return (
-
- Loading diff...
-
- );
- }
- if (!diffData) {
- return (
-
- No diff available
-
- );
- }
- return (
-
- );
- }
-
- if (isLoadingRaw) {
- return (
-
- Loading...
-
- );
- }
-
- if (!rawFileData?.ok) {
- const errorMessage =
- rawFileData?.reason === "too-large"
- ? "File is too large to preview"
- : rawFileData?.reason === "binary"
- ? "Binary file preview not supported"
- : rawFileData?.reason === "outside-worktree"
- ? "File is outside worktree"
- : rawFileData?.reason === "symlink-escape"
- ? "File is a symlink pointing outside worktree"
- : "File not found";
- return (
-
- {errorMessage}
-
- );
- }
-
- if (viewMode === "rendered") {
- return (
-
-
-
- );
- }
-
- if (!isMonacoReady) {
- return (
-
-
- Loading editor...
-
- );
- }
-
- return (
-
-
- Loading editor...
-
- }
- options={MONACO_EDITOR_OPTIONS}
- />
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/index.ts
deleted file mode 100644
index 15337eaf3..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { FileViewerContent } from "./FileViewerContent";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerToolbar/FileViewerToolbar.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerToolbar/FileViewerToolbar.tsx
deleted file mode 100644
index 7232e304b..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerToolbar/FileViewerToolbar.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import { Badge } from "@superset/ui/badge";
-import { ToggleGroup, ToggleGroupItem } from "@superset/ui/toggle-group";
-import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
-import {
- HiMiniLockClosed,
- HiMiniLockOpen,
- HiMiniPencil,
-} from "react-icons/hi2";
-import type { FileViewerMode } from "shared/tabs-types";
-import { PaneToolbarActions } from "../../../components";
-import type { SplitOrientation } from "../../../hooks";
-
-interface FileViewerToolbarProps {
- fileName: string;
- isDirty: boolean;
- isSaving: boolean;
- viewMode: FileViewerMode;
- isLocked: boolean;
- isMarkdown: boolean;
- hasDiff: boolean;
- showEditableBadge: boolean;
- splitOrientation: SplitOrientation;
- onViewModeChange: (value: string) => void;
- onSplitPane: (e: React.MouseEvent) => void;
- onToggleLock: () => void;
- onClosePane: (e: React.MouseEvent) => void;
-}
-
-export function FileViewerToolbar({
- fileName,
- isDirty,
- isSaving,
- viewMode,
- isLocked,
- isMarkdown,
- hasDiff,
- showEditableBadge,
- splitOrientation,
- onViewModeChange,
- onSplitPane,
- onToggleLock,
- onClosePane,
-}: FileViewerToolbarProps) {
- return (
-
-
-
- {isDirty && ●}
- {fileName}
-
- {showEditableBadge && (
-
-
- {isSaving ? "Saving..." : "⌘S"}
-
- )}
-
-
-
- {isMarkdown && (
-
- Rendered
-
- )}
-
- Raw
-
- {hasDiff && (
-
- Diff
-
- )}
-
-
-
-
- {isLocked ? (
-
- ) : (
-
- )}
-
-
-
- {isLocked
- ? "Unlock (allow file replacement)"
- : "Lock (prevent file replacement)"}
-
-
- }
- />
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerToolbar/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerToolbar/index.ts
deleted file mode 100644
index 843916763..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerToolbar/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { FileViewerToolbar } from "./FileViewerToolbar";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileContent/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileContent/index.ts
deleted file mode 100644
index ba24b334c..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileContent/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { useFileContent } from "./useFileContent";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileContent/useFileContent.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileContent/useFileContent.ts
deleted file mode 100644
index 2c4bbd68f..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileContent/useFileContent.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { useEffect } from "react";
-import { trpc } from "renderer/lib/trpc";
-import type { ChangeCategory } from "shared/changes-types";
-
-interface UseFileContentParams {
- worktreePath: string;
- filePath: string;
- viewMode: "raw" | "diff" | "rendered";
- diffCategory?: ChangeCategory;
- commitHash?: string;
- oldPath?: string;
- isDirty: boolean;
- originalContentRef: React.MutableRefObject
;
- originalDiffContentRef: React.MutableRefObject;
-}
-
-export function useFileContent({
- worktreePath,
- filePath,
- viewMode,
- diffCategory,
- commitHash,
- oldPath,
- isDirty,
- originalContentRef,
- originalDiffContentRef,
-}: UseFileContentParams) {
- const { data: branchData } = trpc.changes.getBranches.useQuery(
- { worktreePath },
- { enabled: !!worktreePath && diffCategory === "against-base" },
- );
- const effectiveBaseBranch = branchData?.defaultBranch ?? "main";
-
- const { data: rawFileData, isLoading: isLoadingRaw } =
- trpc.changes.readWorkingFile.useQuery(
- { worktreePath, filePath },
- {
- enabled: viewMode !== "diff" && !!filePath && !!worktreePath,
- },
- );
-
- const { data: diffData, isLoading: isLoadingDiff } =
- trpc.changes.getFileContents.useQuery(
- {
- worktreePath,
- filePath,
- oldPath,
- category: diffCategory ?? "unstaged",
- commitHash,
- defaultBranch:
- diffCategory === "against-base" ? effectiveBaseBranch : undefined,
- },
- {
- enabled:
- viewMode === "diff" && !!diffCategory && !!filePath && !!worktreePath,
- },
- );
-
- // biome-ignore lint/correctness/useExhaustiveDependencies: Only update baseline when content loads
- useEffect(() => {
- if (rawFileData?.ok === true && !isDirty) {
- originalContentRef.current = rawFileData.content;
- }
- }, [rawFileData]);
-
- // biome-ignore lint/correctness/useExhaustiveDependencies: Only update baseline when diff loads
- useEffect(() => {
- if (diffData?.modified && !isDirty) {
- originalDiffContentRef.current = diffData.modified;
- }
- }, [diffData]);
-
- return {
- rawFileData,
- isLoadingRaw,
- diffData,
- isLoadingDiff,
- };
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileSave/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileSave/index.ts
deleted file mode 100644
index 215fc763c..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileSave/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { useFileSave } from "./useFileSave";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileSave/useFileSave.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileSave/useFileSave.ts
deleted file mode 100644
index 074553ac2..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/hooks/useFileSave/useFileSave.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-import type * as Monaco from "monaco-editor";
-import { type MutableRefObject, useCallback, useRef } from "react";
-import { trpc } from "renderer/lib/trpc";
-import { useTabsStore } from "renderer/stores/tabs/store";
-import type { ChangeCategory } from "shared/changes-types";
-
-interface UseFileSaveParams {
- worktreePath: string;
- filePath: string;
- paneId: string;
- diffCategory?: ChangeCategory;
- editorRef: MutableRefObject;
- originalContentRef: MutableRefObject;
- originalDiffContentRef: MutableRefObject;
- draftContentRef: MutableRefObject;
- setIsDirty: (dirty: boolean) => void;
-}
-
-export function useFileSave({
- worktreePath,
- filePath,
- paneId,
- diffCategory,
- editorRef,
- originalContentRef,
- originalDiffContentRef,
- draftContentRef,
- setIsDirty,
-}: UseFileSaveParams) {
- const savingFromRawRef = useRef(false);
- const savingDiffContentRef = useRef(null);
- const utils = trpc.useUtils();
-
- const saveFileMutation = trpc.changes.saveFile.useMutation({
- onSuccess: () => {
- setIsDirty(false);
- if (editorRef.current) {
- originalContentRef.current = editorRef.current.getValue();
- }
- if (savingDiffContentRef.current !== null) {
- originalDiffContentRef.current = savingDiffContentRef.current;
- savingDiffContentRef.current = null;
- }
- if (savingFromRawRef.current) {
- draftContentRef.current = null;
- }
- savingFromRawRef.current = false;
-
- utils.changes.readWorkingFile.invalidate();
- utils.changes.getFileContents.invalidate();
- utils.changes.getStatus.invalidate();
-
- if (diffCategory === "staged") {
- const panes = useTabsStore.getState().panes;
- const currentPane = panes[paneId];
- if (currentPane?.fileViewer) {
- useTabsStore.setState({
- panes: {
- ...panes,
- [paneId]: {
- ...currentPane,
- fileViewer: {
- ...currentPane.fileViewer,
- diffCategory: "unstaged",
- },
- },
- },
- });
- }
- }
- },
- });
-
- const handleSaveRaw = useCallback(async () => {
- if (!editorRef.current || !filePath || !worktreePath) return;
- savingFromRawRef.current = true;
- await saveFileMutation.mutateAsync({
- worktreePath,
- filePath,
- content: editorRef.current.getValue(),
- });
- }, [worktreePath, filePath, saveFileMutation, editorRef]);
-
- const handleSaveDiff = useCallback(
- async (content: string) => {
- if (!filePath || !worktreePath) return;
- savingFromRawRef.current = false;
- savingDiffContentRef.current = content;
- await saveFileMutation.mutateAsync({
- worktreePath,
- filePath,
- content,
- });
- },
- [worktreePath, filePath, saveFileMutation],
- );
-
- return {
- handleSaveRaw,
- handleSaveDiff,
- isSaving: saveFileMutation.isPending,
- };
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/index.ts
deleted file mode 100644
index 96c33fa0b..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { FileViewerPane } from "./FileViewerPane";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
index a72f6e168..6e09a646d 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
@@ -1,5 +1,10 @@
-import { useEffect, useRef } from "react";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
+import { useEffect, useRef, useState } from "react";
+import { HiMiniXMark } from "react-icons/hi2";
+import { TbLayoutColumns, TbLayoutRows } from "react-icons/tb";
import type { MosaicBranch } from "react-mosaic-component";
+import { MosaicWindow } from "react-mosaic-component";
+import { HotkeyTooltipContent } from "renderer/components/HotkeyTooltipContent";
import {
registerPaneRef,
unregisterPaneRef,
@@ -9,7 +14,8 @@ import type { Pane, Tab } from "renderer/stores/tabs/types";
import { TabContentContextMenu } from "../TabContentContextMenu";
import { Terminal } from "../Terminal";
import { DirectoryNavigator } from "../Terminal/DirectoryNavigator";
-import { BasePaneWindow, PaneToolbarActions } from "./components";
+
+type SplitOrientation = "vertical" | "horizontal";
interface TabPaneProps {
paneId: string;
@@ -57,11 +63,12 @@ export function TabPane({
onMoveToTab,
onMoveToNewTab,
}: TabPaneProps) {
- const terminalContainerRef = useRef(null);
- const getClearCallback = useTerminalCallbacksStore((s) => s.getClearCallback);
+ const containerRef = useRef(null);
+ const [splitOrientation, setSplitOrientation] =
+ useState("vertical");
useEffect(() => {
- const container = terminalContainerRef.current;
+ const container = containerRef.current;
if (container) {
registerPaneRef(paneId, container);
}
@@ -70,21 +77,61 @@ export function TabPane({
};
}, [paneId]);
+ useEffect(() => {
+ const container = containerRef.current;
+ if (!container) return;
+
+ const updateOrientation = () => {
+ const { width, height } = container.getBoundingClientRect();
+ setSplitOrientation(width >= height ? "vertical" : "horizontal");
+ };
+
+ updateOrientation();
+
+ const resizeObserver = new ResizeObserver(updateOrientation);
+ resizeObserver.observe(container);
+
+ return () => {
+ resizeObserver.disconnect();
+ };
+ }, []);
+
+ const handleFocus = () => {
+ setFocusedPane(tabId, paneId);
+ };
+
+ const handleClosePane = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ removePane(paneId);
+ };
+
+ const handleSplitPane = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ const container = containerRef.current;
+ if (!container) return;
+
+ const { width, height } = container.getBoundingClientRect();
+ splitPaneAuto(tabId, paneId, { width, height }, path);
+ };
+
+ const getClearCallback = useTerminalCallbacksStore((s) => s.getClearCallback);
const handleClearTerminal = () => {
getClearCallback(paneId)?.();
};
+ const splitIcon =
+ splitOrientation === "vertical" ? (
+
+ ) : (
+
+ );
+
return (
-
path={path}
- tabId={tabId}
- isActive={isActive}
- splitPaneAuto={splitPaneAuto}
- removePane={removePane}
- setFocusedPane={setFocusedPane}
- renderToolbar={(handlers) => (
-
+ title=""
+ renderToolbar={() => (
+
-
+
+
+
+
+ {splitIcon}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)}
+ className={isActive ? "mosaic-window-focused" : ""}
>
splitPaneHorizontal(tabId, paneId, path)}
@@ -111,10 +189,15 @@ export function TabPane({
onMoveToTab={onMoveToTab}
onMoveToNewTab={onMoveToNewTab}
>
-
+ {/* biome-ignore lint/a11y/useKeyWithClickEvents lint/a11y/noStaticElementInteractions: Terminal handles its own keyboard events and focus */}
+
-
+
);
}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/BasePaneWindow/BasePaneWindow.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/BasePaneWindow/BasePaneWindow.tsx
deleted file mode 100644
index 7e7c3d0b2..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/BasePaneWindow/BasePaneWindow.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import { useRef } from "react";
-import type { MosaicBranch } from "react-mosaic-component";
-import { MosaicWindow } from "react-mosaic-component";
-import type { SplitOrientation } from "../../hooks";
-import { useSplitOrientation } from "../../hooks";
-
-export interface PaneHandlers {
- onFocus: () => void;
- onClosePane: (e: React.MouseEvent) => void;
- onSplitPane: (e: React.MouseEvent) => void;
- splitOrientation: SplitOrientation;
-}
-
-interface BasePaneWindowProps {
- paneId: string;
- path: MosaicBranch[];
- tabId: string;
- isActive: boolean;
- splitPaneAuto: (
- tabId: string,
- sourcePaneId: string,
- dimensions: { width: number; height: number },
- path?: MosaicBranch[],
- ) => void;
- removePane: (paneId: string) => void;
- setFocusedPane: (tabId: string, paneId: string) => void;
- renderToolbar: (handlers: PaneHandlers) => React.ReactElement;
- children: React.ReactNode;
- contentClassName?: string;
-}
-
-export function BasePaneWindow({
- paneId,
- path,
- tabId,
- isActive,
- splitPaneAuto,
- removePane,
- setFocusedPane,
- renderToolbar,
- children,
- contentClassName = "w-full h-full overflow-hidden",
-}: BasePaneWindowProps) {
- const containerRef = useRef
(null);
- const splitOrientation = useSplitOrientation(containerRef);
-
- const handleFocus = () => {
- setFocusedPane(tabId, paneId);
- };
-
- const handleClosePane = (e: React.MouseEvent) => {
- e.stopPropagation();
- removePane(paneId);
- };
-
- const handleSplitPane = (e: React.MouseEvent) => {
- e.stopPropagation();
- const container = containerRef.current;
- if (!container) return;
-
- const { width, height } = container.getBoundingClientRect();
- splitPaneAuto(tabId, paneId, { width, height }, path);
- };
-
- const handlers: PaneHandlers = {
- onFocus: handleFocus,
- onClosePane: handleClosePane,
- onSplitPane: handleSplitPane,
- splitOrientation,
- };
-
- return (
-
- path={path}
- title=""
- renderToolbar={() => renderToolbar(handlers)}
- className={isActive ? "mosaic-window-focused" : ""}
- >
- {/* biome-ignore lint/a11y/useKeyWithClickEvents lint/a11y/noStaticElementInteractions: Focus handler for pane */}
-
- {children}
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/BasePaneWindow/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/BasePaneWindow/index.ts
deleted file mode 100644
index b93b72278..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/BasePaneWindow/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { BasePaneWindow, type PaneHandlers } from "./BasePaneWindow";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/PaneToolbarActions/PaneToolbarActions.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/PaneToolbarActions/PaneToolbarActions.tsx
deleted file mode 100644
index 5d15fbd1f..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/PaneToolbarActions/PaneToolbarActions.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
-import { HiMiniXMark } from "react-icons/hi2";
-import { TbLayoutColumns, TbLayoutRows } from "react-icons/tb";
-import { HotkeyTooltipContent } from "renderer/components/HotkeyTooltipContent";
-import type { HotkeyId } from "shared/hotkeys";
-import type { SplitOrientation } from "../../hooks";
-
-interface PaneToolbarActionsProps {
- splitOrientation: SplitOrientation;
- onSplitPane: (e: React.MouseEvent) => void;
- onClosePane: (e: React.MouseEvent) => void;
- leadingActions?: React.ReactNode;
- /** Hotkey ID to display for the close action. Defaults to CLOSE_PANE. */
- closeHotkeyId?: HotkeyId;
-}
-
-export function PaneToolbarActions({
- splitOrientation,
- onSplitPane,
- onClosePane,
- leadingActions,
- closeHotkeyId = "CLOSE_PANE",
-}: PaneToolbarActionsProps) {
- const splitIcon =
- splitOrientation === "vertical" ? (
-
- ) : (
-
- );
-
- return (
-
- {leadingActions}
-
-
-
- {splitIcon}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/PaneToolbarActions/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/PaneToolbarActions/index.ts
deleted file mode 100644
index adc90aacc..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/PaneToolbarActions/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { PaneToolbarActions } from "./PaneToolbarActions";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/index.ts
deleted file mode 100644
index 81c4b584b..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { BasePaneWindow, type PaneHandlers } from "./BasePaneWindow";
-export { PaneToolbarActions } from "./PaneToolbarActions";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/index.ts
deleted file mode 100644
index 7ade988b9..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export {
- type SplitOrientation,
- useSplitOrientation,
-} from "./useSplitOrientation";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/useSplitOrientation/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/useSplitOrientation/index.ts
deleted file mode 100644
index 7ade988b9..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/useSplitOrientation/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export {
- type SplitOrientation,
- useSplitOrientation,
-} from "./useSplitOrientation";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/useSplitOrientation/useSplitOrientation.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/useSplitOrientation/useSplitOrientation.ts
deleted file mode 100644
index a239d6e86..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/hooks/useSplitOrientation/useSplitOrientation.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { type RefObject, useEffect, useState } from "react";
-
-export type SplitOrientation = "vertical" | "horizontal";
-
-export function useSplitOrientation(
- containerRef: RefObject,
-): SplitOrientation {
- const [splitOrientation, setSplitOrientation] =
- useState("vertical");
-
- useEffect(() => {
- const container = containerRef.current;
- if (!container) return;
-
- const updateOrientation = () => {
- const { width, height } = container.getBoundingClientRect();
- setSplitOrientation(width >= height ? "vertical" : "horizontal");
- };
-
- updateOrientation();
-
- const resizeObserver = new ResizeObserver(updateOrientation);
- resizeObserver.observe(container);
-
- return () => {
- resizeObserver.disconnect();
- };
- }, [containerRef]);
-
- return splitOrientation;
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
index 766f486ae..b6df3608e 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
@@ -8,7 +8,6 @@ import {
type MosaicNode,
} from "react-mosaic-component";
import { dragDropManager } from "renderer/lib/dnd";
-import { trpc } from "renderer/lib/trpc";
import { useTabsStore } from "renderer/stores/tabs/store";
import type { Pane, Tab } from "renderer/stores/tabs/types";
import {
@@ -16,7 +15,6 @@ import {
extractPaneIdsFromLayout,
getPaneIdsForTab,
} from "renderer/stores/tabs/utils";
-import { FileViewerPane } from "./FileViewerPane";
import { TabPane } from "./TabPane";
interface TabViewProps {
@@ -37,10 +35,6 @@ export function TabView({ tab, panes }: TabViewProps) {
const movePaneToNewTab = useTabsStore((s) => s.movePaneToNewTab);
const allTabs = useTabsStore((s) => s.tabs);
- // Get worktree path for file viewer panes
- const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
- const worktreePath = activeWorkspace?.worktreePath ?? "";
-
// Get tabs in the same workspace for move targets
const workspaceTabs = allTabs.filter(
(t) => t.workspaceId === tab.workspaceId,
@@ -96,31 +90,6 @@ export function TabView({ tab, panes }: TabViewProps) {
);
}
- // Route file-viewer panes to FileViewerPane component
- if (pane.type === "file-viewer") {
- if (!worktreePath) {
- return (
-
- Workspace path unavailable
-
- );
- }
- return (
-
- );
- }
-
- // Default: terminal panes
return (
{
const setTabAutoTitle = useTabsStore((s) => s.setTabAutoTitle);
const updatePaneCwd = useTabsStore((s) => s.updatePaneCwd);
const focusedPaneIds = useTabsStore((s) => s.focusedPaneIds);
- const addFileViewerPane = useTabsStore((s) => s.addFileViewerPane);
const terminalTheme = useTerminalTheme();
// Ref for initial theme to avoid recreating terminal on theme change
@@ -71,76 +68,6 @@ export const Terminal = ({ tabId, workspaceId }: TerminalProps) => {
const { data: workspaceCwd } =
trpc.terminal.getWorkspaceCwd.useQuery(workspaceId);
- // Query terminal link behavior setting
- const { data: terminalLinkBehavior } =
- trpc.settings.getTerminalLinkBehavior.useQuery();
-
- // Handler for file link clicks - uses current setting value
- const handleFileLinkClick = useCallback(
- (path: string, line?: number, column?: number) => {
- const behavior = terminalLinkBehavior ?? "external-editor";
-
- // Helper to open in external editor
- const openInExternalEditor = () => {
- trpcClient.external.openFileInEditor
- .mutate({
- path,
- line,
- column,
- cwd: workspaceCwd ?? undefined,
- })
- .catch((error) => {
- console.error(
- "[Terminal] Failed to open file in editor:",
- path,
- error,
- );
- toast.error("Failed to open file in editor", {
- description: path,
- });
- });
- };
-
- if (behavior === "file-viewer") {
- // If workspaceCwd is not loaded yet, fall back to external editor
- // This prevents confusing errors when the workspace is still initializing
- if (!workspaceCwd) {
- console.warn(
- "[Terminal] workspaceCwd not loaded, falling back to external editor",
- );
- openInExternalEditor();
- return;
- }
-
- // Normalize absolute paths to worktree-relative paths for file viewer
- // File viewer expects relative paths, but terminal links can be absolute
- let filePath = path;
- // Use path boundary check to avoid incorrect prefix stripping
- // e.g., /repo vs /repo-other should not match
- if (path === workspaceCwd) {
- filePath = ".";
- } else if (path.startsWith(`${workspaceCwd}/`)) {
- filePath = path.slice(workspaceCwd.length + 1);
- } else if (path.startsWith("/")) {
- // Absolute path outside workspace - show warning and don't attempt to open
- toast.warning("File is outside the workspace", {
- description:
- "Switch to 'External editor' in Settings to open this file",
- });
- return;
- }
- addFileViewerPane(workspaceId, { filePath, line, column });
- } else {
- openInExternalEditor();
- }
- },
- [terminalLinkBehavior, workspaceId, workspaceCwd, addFileViewerPane],
- );
-
- // Ref to avoid terminal recreation when callback changes
- const handleFileLinkClickRef = useRef(handleFileLinkClick);
- handleFileLinkClickRef.current = handleFileLinkClick;
-
// Seed cwd from initialCwd or workspace path (shell spawns there)
// OSC-7 will override if/when the shell reports directory changes
useEffect(() => {
@@ -270,12 +197,11 @@ export const Terminal = ({ tabId, workspaceId }: TerminalProps) => {
xterm,
fitAddon,
cleanup: cleanupQuerySuppression,
- } = createTerminalInstance(container, {
- cwd: workspaceCwd,
- initialTheme: initialThemeRef.current,
- onFileLinkClick: (path, line, column) =>
- handleFileLinkClickRef.current(path, line, column),
- });
+ } = createTerminalInstance(
+ container,
+ workspaceCwd ?? undefined,
+ initialThemeRef.current,
+ );
xtermRef.current = xterm;
fitAddonRef.current = fitAddon;
isExitedRef.current = false;
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
index fbd1b980b..3c92f907d 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
@@ -93,26 +93,19 @@ function loadRenderer(xterm: XTerm): { dispose: () => void } {
};
}
-export interface CreateTerminalOptions {
- cwd?: string;
- initialTheme?: ITheme | null;
- onFileLinkClick?: (path: string, line?: number, column?: number) => void;
-}
-
export function createTerminalInstance(
container: HTMLDivElement,
- options: CreateTerminalOptions = {},
+ cwd?: string,
+ initialTheme?: ITheme | null,
): {
xterm: XTerm;
fitAddon: FitAddon;
cleanup: () => void;
} {
- const { cwd, initialTheme, onFileLinkClick } = options;
-
// Use provided theme, or fall back to localStorage-based default to prevent flash
const theme = initialTheme ?? getDefaultTerminalTheme();
- const terminalOptions = { ...TERMINAL_OPTIONS, theme };
- const xterm = new XTerm(terminalOptions);
+ const options = { ...TERMINAL_OPTIONS, theme };
+ const xterm = new XTerm(options);
const fitAddon = new FitAddon();
const clipboardAddon = new ClipboardAddon();
@@ -156,25 +149,20 @@ export function createTerminalInstance(
const filePathLinkProvider = new FilePathLinkProvider(
xterm,
(_event, path, line, column) => {
- if (onFileLinkClick) {
- onFileLinkClick(path, line, column);
- } else {
- // Fallback to default behavior (external editor)
- trpcClient.external.openFileInEditor
- .mutate({
+ trpcClient.external.openFileInEditor
+ .mutate({
+ path,
+ line,
+ column,
+ cwd,
+ })
+ .catch((error) => {
+ console.error(
+ "[Terminal] Failed to open file in editor:",
path,
- line,
- column,
- cwd,
- })
- .catch((error) => {
- console.error(
- "[Terminal] Failed to open file in editor:",
- path,
- error,
- );
- });
- }
+ error,
+ );
+ });
},
);
xterm.registerLinkProvider(filePathLinkProvider);
@@ -245,7 +233,7 @@ export function setupPasteHandler(
/**
* Setup keyboard handling for xterm including:
- * - Shortcut forwarding: App hotkeys bubble to document where useAppHotkey listens
+ * - Shortcut forwarding: App hotkeys are re-dispatched to document for react-hotkeys-hook
* - Shift+Enter: Sends ESC+CR sequence (to avoid \ appearing in Claude Code while keeping line continuation behavior)
* - Clear terminal: Uses the configured clear shortcut
*
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/index.tsx
index b62872350..e04866eb6 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/index.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/index.tsx
@@ -1,7 +1,6 @@
import { useMemo } from "react";
import { trpc } from "renderer/lib/trpc";
import { useTabsStore } from "renderer/stores/tabs/store";
-import { ResizableSidebar } from "../../../WorkspaceView/ResizableSidebar";
import { EmptyTabView } from "./EmptyTabView";
import { TabView } from "./TabView";
@@ -20,16 +19,9 @@ export function TabsContent() {
return allTabs.find((tab) => tab.id === activeTabId) || null;
}, [activeWorkspaceId, activeTabIds, allTabs]);
- return (
-
-
- {tabToRender ? (
-
- ) : (
-
- )}
-
-
-
- );
+ if (!tabToRender) {
+ return ;
+ }
+
+ return ;
}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/index.tsx
index ecc345fae..1a2e20bd0 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/index.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/index.tsx
@@ -1,15 +1,19 @@
-import { SidebarControl } from "../../SidebarControl";
-import { ContentHeader } from "./ContentHeader";
+import { SidebarMode, useSidebarStore } from "renderer/stores";
+import { ChangesContent } from "./ChangesContent";
import { TabsContent } from "./TabsContent";
-import { GroupStrip } from "./TabsContent/GroupStrip";
export function ContentView() {
- return (
-
- }>
-
-
-
-
- );
+ const { currentMode } = useSidebarStore();
+
+ if (currentMode === SidebarMode.Changes) {
+ return (
+
+ );
+ }
+
+ return ;
}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ResizableSidebar/ResizableSidebar.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ResizableSidebar/ResizableSidebar.tsx
index f6a00b367..05d9d7b04 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ResizableSidebar/ResizableSidebar.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ResizableSidebar/ResizableSidebar.tsx
@@ -33,8 +33,8 @@ export function ResizableSidebar() {
(e: MouseEvent) => {
if (!isResizing) return;
- const draggedLeftBy = startXRef.current - e.clientX;
- const newWidth = startWidthRef.current + draggedLeftBy;
+ const delta = e.clientX - startXRef.current;
+ const newWidth = startWidthRef.current + delta;
const clampedWidth = Math.max(
MIN_SIDEBAR_WIDTH,
Math.min(MAX_SIDEBAR_WIDTH, newWidth),
@@ -87,8 +87,8 @@ export function ResizableSidebar() {
tabIndex={0}
onMouseDown={handleMouseDown}
className={cn(
- "absolute top-0 -left-2 w-5 h-full cursor-col-resize z-10",
- "after:absolute after:top-0 after:right-2 after:w-1 after:h-full after:transition-colors",
+ "absolute top-0 -right-2 w-5 h-full cursor-col-resize z-10",
+ "after:absolute after:top-0 after:left-2 after:w-1 after:h-full after:transition-colors",
"hover:after:bg-border focus:outline-none focus:after:bg-border",
isResizing && "after:bg-border",
)}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
index 2ba11f811..ee0ec6d2e 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/ChangesView.tsx
@@ -6,22 +6,13 @@ import { HiMiniMinus, HiMiniPlus } from "react-icons/hi2";
import { trpc } from "renderer/lib/trpc";
import { useChangesStore } from "renderer/stores/changes";
import type { ChangeCategory, ChangedFile } from "shared/changes-types";
-
import { CategorySection } from "./components/CategorySection";
import { ChangesHeader } from "./components/ChangesHeader";
import { CommitInput } from "./components/CommitInput";
import { CommitItem } from "./components/CommitItem";
import { FileList } from "./components/FileList";
-interface ChangesViewProps {
- onFileOpen?: (
- file: ChangedFile,
- category: ChangeCategory,
- commitHash?: string,
- ) => void;
-}
-
-export function ChangesView({ onFileOpen }: ChangesViewProps) {
+export function ChangesView() {
const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
const worktreePath = activeWorkspace?.worktreePath;
@@ -137,13 +128,11 @@ export function ChangesView({ onFileOpen }: ChangesViewProps) {
const handleFileSelect = (file: ChangedFile, category: ChangeCategory) => {
if (!worktreePath) return;
selectFile(worktreePath, file, category, null);
- onFileOpen?.(file, category);
};
const handleCommitFileSelect = (file: ChangedFile, commitHash: string) => {
if (!worktreePath) return;
selectFile(worktreePath, file, "committed", commitHash);
- onFileOpen?.(file, "committed", commitHash);
};
const handleCommitToggle = (hash: string) => {
@@ -217,7 +206,6 @@ export function ChangesView({ onFileOpen }: ChangesViewProps) {
viewMode={fileListViewMode}
onViewModeChange={setFileListViewMode}
worktreePath={worktreePath}
- workspaceId={activeWorkspace?.id}
/>
- {availableBranches
- .filter((branch) => branch)
- .map((branch) => (
-
- {branch}
- {branch === branchData.defaultBranch && (
- (default)
- )}
-
- ))}
+ {availableBranches.map((branch) => (
+
+ {branch}
+ {branch === branchData.defaultBranch && (
+ (default)
+ )}
+
+ ))}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx
index e1e2b8421..0c93c0153 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx
@@ -8,10 +8,7 @@ import {
} from "@superset/ui/select";
import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
import { HiArrowPath } from "react-icons/hi2";
-import { LuLoaderCircle } from "react-icons/lu";
import { trpc } from "renderer/lib/trpc";
-import { PRIcon } from "renderer/screens/main/components/PRIcon";
-import { usePRStatus } from "renderer/screens/main/hooks";
import { useChangesStore } from "renderer/stores/changes";
import type { ChangesViewMode } from "../../types";
import { ViewModeToggle } from "../ViewModeToggle";
@@ -24,7 +21,6 @@ interface ChangesHeaderProps {
viewMode: ChangesViewMode;
onViewModeChange: (mode: ChangesViewMode) => void;
worktreePath: string;
- workspaceId?: string;
}
export function ChangesHeader({
@@ -35,7 +31,6 @@ export function ChangesHeader({
viewMode,
onViewModeChange,
worktreePath,
- workspaceId,
}: ChangesHeaderProps) {
const { baseBranch, setBaseBranch } = useChangesStore();
@@ -44,11 +39,6 @@ export function ChangesHeader({
{ enabled: !!worktreePath },
);
- const { pr, isLoading: isPRLoading } = usePRStatus({
- workspaceId,
- refetchInterval: 10000,
- });
-
const effectiveBaseBranch = baseBranch ?? branchData?.defaultBranch ?? "main";
const availableBranches = branchData?.remote ?? [];
@@ -84,18 +74,16 @@ export function ChangesHeader({
- {sortedBranches
- .filter((branch) => branch)
- .map((branch) => (
-
- {branch}
- {branch === branchData.defaultBranch && (
-
- (default)
-
- )}
-
- ))}
+ {sortedBranches.map((branch) => (
+
+ {branch}
+ {branch === branchData.defaultBranch && (
+
+ (default)
+
+ )}
+
+ ))}
@@ -125,30 +113,6 @@ export function ChangesHeader({
Refresh changes
-
- {/* PR Status Icon */}
- {isPRLoading ? (
-
- ) : pr ? (
-
-
-
-
-
- #{pr.number}
-
-
-
-
- View PR on GitHub
-
-
- ) : null}
);
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/PortsList.tsx
similarity index 100%
rename from apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx
rename to apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/PortsList.tsx
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/PresetContextMenu/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/PresetContextMenu/index.tsx
new file mode 100644
index 000000000..a9b7009d4
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/PresetContextMenu/index.tsx
@@ -0,0 +1,62 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuItem,
+ ContextMenuSeparator,
+ ContextMenuTrigger,
+} from "@superset/ui/context-menu";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
+import type React from "react";
+
+interface PresetContextMenuProps {
+ hasActiveTab: boolean;
+ tooltipText?: string;
+ onOpenAsNewTab: () => void;
+ onOpenAsPane: () => void;
+ children: React.ReactNode;
+}
+
+export function PresetContextMenu({
+ hasActiveTab,
+ tooltipText,
+ onOpenAsNewTab,
+ onOpenAsPane,
+ children,
+}: PresetContextMenuProps) {
+ const contextMenuContent = (
+
+
+ Open as New Tab
+
+ {hasActiveTab && (
+ <>
+
+
+ Open as Pane in Current Tab
+
+ >
+ )}
+
+ );
+
+ if (!tooltipText) {
+ return (
+
+ {children}
+ {contextMenuContent}
+
+ );
+ }
+
+ return (
+
+
+
+ {children}
+
+ {contextMenuContent}
+
+ {tooltipText}
+
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabItem/TabContextMenu.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabItem/TabContextMenu.tsx
new file mode 100644
index 000000000..0ce5492de
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabItem/TabContextMenu.tsx
@@ -0,0 +1,72 @@
+import {
+ ContextMenu,
+ ContextMenuContent,
+ ContextMenuItem,
+ ContextMenuSeparator,
+ ContextMenuTrigger,
+} from "@superset/ui/context-menu";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
+import type React from "react";
+
+interface TabContextMenuProps {
+ paneCount: number;
+ onClose: () => void;
+ onRename: () => void;
+ children: React.ReactNode;
+}
+
+export function TabContextMenu({
+ paneCount,
+ onClose,
+ onRename,
+ children,
+}: TabContextMenuProps) {
+ const hasMultiplePanes = paneCount > 1;
+
+ const handleRenameSelect = (event: Event) => {
+ // Prevent default to stop Radix from restoring focus to the trigger
+ event.preventDefault();
+ onRename();
+ };
+
+ const contextMenuContent = (
+
+ {children}
+
+
+ Rename Tab
+
+
+
+ Close Tab
+
+
+
+ );
+
+ if (!hasMultiplePanes) {
+ return contextMenuContent;
+ }
+
+ return (
+
+
+
+ {children}
+
+
+
+ Rename Tab
+
+
+
+ Close Tab
+
+
+
+
+ {paneCount} terminals
+
+
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabItem/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabItem/index.tsx
new file mode 100644
index 000000000..07a860bed
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabItem/index.tsx
@@ -0,0 +1,218 @@
+import { Button } from "@superset/ui/button";
+import { Input } from "@superset/ui/input";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useDrag, useDrop } from "react-dnd";
+import { HiMiniCommandLine, HiMiniXMark } from "react-icons/hi2";
+import { trpc } from "renderer/lib/trpc";
+import { useTabsStore } from "renderer/stores/tabs/store";
+import type { Tab } from "renderer/stores/tabs/types";
+import { getTabDisplayName } from "renderer/stores/tabs/utils";
+import { TabContextMenu } from "./TabContextMenu";
+
+const DRAG_TYPE = "TAB";
+
+interface DragItem {
+ type: typeof DRAG_TYPE;
+ tabId: string;
+ index: number;
+}
+
+interface TabItemProps {
+ tab: Tab;
+ index: number;
+ isActive: boolean;
+}
+
+export function TabItem({ tab, index, isActive }: TabItemProps) {
+ const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
+ const activeWorkspaceId = activeWorkspace?.id;
+ const removeTab = useTabsStore((s) => s.removeTab);
+ const setActiveTab = useTabsStore((s) => s.setActiveTab);
+ const renameTab = useTabsStore((s) => s.renameTab);
+ const panes = useTabsStore((s) => s.panes);
+ const needsAttention = useTabsStore((s) =>
+ Object.values(s.panes).some((p) => p.tabId === tab.id && p.needsAttention),
+ );
+
+ const paneCount = useMemo(
+ () => Object.values(panes).filter((p) => p.tabId === tab.id).length,
+ [panes, tab.id],
+ );
+
+ const [isRenaming, setIsRenaming] = useState(false);
+ const [renameValue, setRenameValue] = useState("");
+ const inputRef = useRef
(null);
+
+ // Drag source for tab reordering
+ const [{ isDragging }, drag] = useDrag<
+ DragItem,
+ void,
+ { isDragging: boolean }
+ >({
+ type: DRAG_TYPE,
+ item: { type: DRAG_TYPE, tabId: tab.id, index },
+ collect: (monitor) => ({
+ isDragging: monitor.isDragging(),
+ }),
+ });
+
+ // Drop target (just for visual feedback, actual drop is handled by parent)
+ const [{ isDragOver }, drop] = useDrop<
+ DragItem,
+ void,
+ { isDragOver: boolean }
+ >({
+ accept: DRAG_TYPE,
+ collect: (monitor) => ({
+ isDragOver: monitor.isOver(),
+ }),
+ });
+
+ const displayName = getTabDisplayName(tab);
+
+ const handleRemoveTab = (e?: React.MouseEvent) => {
+ e?.stopPropagation();
+ removeTab(tab.id);
+ };
+
+ const handleTabClick = () => {
+ if (isRenaming) return;
+ if (activeWorkspaceId) {
+ setActiveTab(activeWorkspaceId, tab.id);
+ }
+ };
+
+ const startRename = () => {
+ setRenameValue(tab.userTitle ?? tab.name ?? displayName);
+ setIsRenaming(true);
+ };
+
+ // Focus input when entering rename mode
+ useEffect(() => {
+ if (isRenaming && inputRef.current) {
+ inputRef.current.focus();
+ inputRef.current.select();
+ }
+ }, [isRenaming]);
+
+ const submitRename = () => {
+ const trimmedValue = renameValue.trim();
+ const currentUserTitle = tab.userTitle?.trim() ?? "";
+ if (trimmedValue !== currentUserTitle) {
+ renameTab(tab.id, trimmedValue);
+ }
+ setIsRenaming(false);
+ };
+
+ const handleKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ submitRename();
+ } else if (e.key === "Escape") {
+ setIsRenaming(false);
+ }
+ };
+
+ const attachRef = (el: HTMLElement | null) => {
+ drag(el);
+ drop(el);
+ };
+
+ // When renaming, render outside TabContextMenu to avoid Radix focus interference
+ if (isRenaming) {
+ return (
+
+
+
+
+
+ setRenameValue(e.target.value)}
+ onBlur={submitRename}
+ onKeyDown={handleKeyDown}
+ onClick={(e) => e.stopPropagation()}
+ className="flex-1"
+ />
+
+
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
{
+ if (e.key === "Enter" || e.key === " ") {
+ e.preventDefault();
+ handleTabClick();
+ }
+ }}
+ tabIndex={0}
+ className={`
+ w-full text-start px-3 py-2 rounded-md cursor-pointer flex items-center justify-between pr-8
+ ${isActive ? "bg-tertiary-active" : ""}
+ ${isDragging ? "opacity-50" : ""}
+ ${isDragOver ? "bg-tertiary-active/50" : ""}
+ `}
+ >
+
+
+ {displayName}
+ {needsAttention && (
+
+
+
+
+
+
+
+ Agent completed
+
+ )}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsx
new file mode 100644
index 000000000..63ee4320e
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsx
@@ -0,0 +1,96 @@
+import type { TerminalPreset } from "@superset/local-db";
+import {
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@superset/ui/command";
+import {
+ HiMiniCommandLine,
+ HiMiniPlus,
+ HiOutlineCog6Tooth,
+} from "react-icons/hi2";
+import {
+ getPresetIcon,
+ useIsDarkTheme,
+} from "renderer/assets/app-icons/preset-icons";
+
+interface TabsCommandDialogProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ onAddTab: () => void;
+ onOpenPresetsSettings: () => void;
+ presets: TerminalPreset[];
+ onSelectPreset: (preset: TerminalPreset) => void;
+}
+
+export function TabsCommandDialog({
+ open,
+ onOpenChange,
+ onAddTab,
+ onOpenPresetsSettings,
+ presets,
+ onSelectPreset,
+}: TabsCommandDialogProps) {
+ const isDark = useIsDarkTheme();
+
+ return (
+
+
+
+ No results found.
+
+
+
+ New Terminal
+
+
+ {presets.length > 0 && (
+
+ {presets.map((preset) => {
+ const presetIcon = getPresetIcon(preset.name, isDark);
+ return (
+ onSelectPreset(preset)}
+ >
+ {presetIcon ? (
+
+ ) : (
+
+ )}
+
+ {preset.name || "default"}
+
+ {preset.description ? (
+
+ {preset.description}
+
+ ) : (
+ preset.cwd && (
+
+ {preset.cwd}
+
+ )
+ )}
+
+ );
+ })}
+
+ )}
+
+
+
+ Configure Presets
+
+
+
+
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsx
new file mode 100644
index 000000000..2baa29305
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsx
@@ -0,0 +1,284 @@
+import type { TerminalPreset } from "@superset/local-db";
+import { Button } from "@superset/ui/button";
+import { ButtonGroup } from "@superset/ui/button-group";
+import { LayoutGroup, motion } from "framer-motion";
+import { useMemo, useRef, useState } from "react";
+import { useDrop } from "react-dnd";
+import {
+ HiMiniCommandLine,
+ HiMiniEllipsisHorizontal,
+ HiMiniPlus,
+} from "react-icons/hi2";
+import {
+ getPresetIcon,
+ useIsDarkTheme,
+} from "renderer/assets/app-icons/preset-icons";
+import { trpc } from "renderer/lib/trpc";
+import { usePresets } from "renderer/react-query/presets";
+import { useOpenSettings, useSidebarStore } from "renderer/stores";
+import { useTabsStore } from "renderer/stores/tabs/store";
+import { PortsList } from "./PortsList";
+import { PresetContextMenu } from "./PresetContextMenu";
+import { TabItem } from "./TabItem";
+import { TabsCommandDialog } from "./TabsCommandDialog";
+
+const DRAG_TYPE = "TAB";
+
+interface DragItem {
+ type: typeof DRAG_TYPE;
+ tabId: string;
+ index: number;
+}
+
+export function TabsView() {
+ const isResizing = useSidebarStore((s) => s.isResizing);
+ const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
+ const activeWorkspaceId = activeWorkspace?.id;
+ const allTabs = useTabsStore((s) => s.tabs);
+ const addTab = useTabsStore((s) => s.addTab);
+ const addPane = useTabsStore((s) => s.addPane);
+ const renameTab = useTabsStore((s) => s.renameTab);
+ const reorderTabById = useTabsStore((s) => s.reorderTabById);
+ const activeTabIds = useTabsStore((s) => s.activeTabIds);
+ const [dropIndex, setDropIndex] = useState(null);
+ const [commandOpen, setCommandOpen] = useState(false);
+ const openSettings = useOpenSettings();
+ const containerRef = useRef(null);
+
+ const { presets } = usePresets();
+ const isDark = useIsDarkTheme();
+
+ const tabs = useMemo(
+ () =>
+ activeWorkspaceId
+ ? allTabs.filter((tab) => tab.workspaceId === activeWorkspaceId)
+ : [],
+ [activeWorkspaceId, allTabs],
+ );
+
+ const handleAddTab = () => {
+ if (activeWorkspaceId) {
+ addTab(activeWorkspaceId);
+ setCommandOpen(false);
+ }
+ };
+
+ const handleAddPane = () => {
+ if (!activeWorkspaceId) return;
+
+ const activeTabId = activeTabIds[activeWorkspaceId];
+ if (!activeTabId) {
+ // Fall back to creating a new tab if no active tab
+ handleAddTab();
+ return;
+ }
+
+ addPane(activeTabId);
+ setCommandOpen(false);
+ };
+
+ const handleOpenPresetsSettings = () => {
+ openSettings("presets");
+ setCommandOpen(false);
+ };
+
+ const handleSelectPreset = (preset: TerminalPreset) => {
+ if (!activeWorkspaceId) return;
+
+ // Pass preset options to addTab - Terminal component will read them from pane state
+ const { tabId } = addTab(activeWorkspaceId, {
+ initialCommands: preset.commands,
+ initialCwd: preset.cwd || undefined,
+ });
+
+ // Rename the tab to the preset name
+ if (preset.name) {
+ renameTab(tabId, preset.name);
+ }
+
+ setCommandOpen(false);
+ };
+
+ const handleSelectPresetAsPane = (preset: TerminalPreset) => {
+ if (!activeWorkspaceId) return;
+
+ const activeTabId = activeTabIds[activeWorkspaceId];
+ if (!activeTabId) {
+ // Fall back to opening as new tab if no active tab
+ handleSelectPreset(preset);
+ return;
+ }
+
+ // Add pane to current tab with preset options
+ addPane(activeTabId, {
+ initialCommands: preset.commands,
+ initialCwd: preset.cwd || undefined,
+ });
+
+ setCommandOpen(false);
+ };
+
+ const [{ isOver }, drop] = useDrop({
+ accept: DRAG_TYPE,
+ hover: (item, monitor) => {
+ if (!containerRef.current) return;
+
+ const clientOffset = monitor.getClientOffset();
+ if (!clientOffset) return;
+
+ const tabItems = containerRef.current.querySelectorAll("[data-tab-item]");
+ let newDropIndex = tabs.length;
+
+ tabItems.forEach((element, index) => {
+ const rect = element.getBoundingClientRect();
+ const midY = rect.top + rect.height / 2;
+
+ if (clientOffset.y < midY && index < newDropIndex) {
+ newDropIndex = index;
+ }
+ });
+
+ if (newDropIndex === item.index || newDropIndex === item.index + 1) {
+ setDropIndex(null);
+ } else {
+ setDropIndex(newDropIndex);
+ }
+ },
+ drop: (item) => {
+ if (dropIndex !== null && dropIndex !== item.index) {
+ const targetIndex = dropIndex > item.index ? dropIndex - 1 : dropIndex;
+ reorderTabById(item.tabId, targetIndex);
+ }
+ setDropIndex(null);
+ },
+ collect: (monitor) => ({
+ isOver: monitor.isOver(),
+ }),
+ });
+
+ if (!isOver && dropIndex !== null) {
+ setDropIndex(null);
+ }
+
+ return (
+
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/index.tsx
index 86b5df975..751158761 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/index.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/index.tsx
@@ -1,28 +1,29 @@
-import { trpc } from "renderer/lib/trpc";
-import { useTabsStore } from "renderer/stores/tabs/store";
-import type { ChangeCategory, ChangedFile } from "shared/changes-types";
+import { useSidebarStore } from "renderer/stores";
+import { SidebarMode } from "renderer/stores/sidebar-state";
import { ChangesView } from "./ChangesView";
+import { ModeCarousel } from "./ModeCarousel";
+import { TabsView } from "./TabsView";
export function Sidebar() {
- const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
- const workspaceId = activeWorkspace?.id;
+ const { currentMode, setMode } = useSidebarStore();
- const addFileViewerPane = useTabsStore((s) => s.addFileViewerPane);
-
- const handleFileOpen = workspaceId
- ? (file: ChangedFile, category: ChangeCategory, commitHash?: string) => {
- addFileViewerPane(workspaceId, {
- filePath: file.path,
- diffCategory: category,
- commitHash,
- oldPath: file.oldPath,
- });
- }
- : undefined;
+ const modes: SidebarMode[] = [SidebarMode.Tabs, SidebarMode.Changes];
return (
);
}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/WorkspaceActionBar.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/WorkspaceActionBar.tsx
new file mode 100644
index 000000000..f641fde5a
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/WorkspaceActionBar.tsx
@@ -0,0 +1,21 @@
+import { WorkspaceActionBarLeft } from "./components/WorkspaceActionBarLeft";
+import { WorkspaceActionBarRight } from "./components/WorkspaceActionBarRight";
+
+interface WorkspaceActionBarProps {
+ worktreePath: string | undefined;
+}
+
+export function WorkspaceActionBar({ worktreePath }: WorkspaceActionBarProps) {
+ if (!worktreePath) return null;
+
+ return (
+
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarLeft/WorkspaceActionBarLeft.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarLeft/WorkspaceActionBarLeft.tsx
new file mode 100644
index 000000000..0db773eb9
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarLeft/WorkspaceActionBarLeft.tsx
@@ -0,0 +1,41 @@
+import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
+import { GoGitBranch } from "react-icons/go";
+import { trpc } from "renderer/lib/trpc";
+
+export function WorkspaceActionBarLeft() {
+ const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
+ const currentBranch = activeWorkspace?.worktree?.branch;
+ const baseBranch = activeWorkspace?.worktree?.baseBranch;
+ return (
+ <>
+ {currentBranch && (
+
+
+
+
+
+ {currentBranch}
+
+
+
+
+ Current branch
+
+
+ )}
+ {baseBranch && baseBranch !== currentBranch && (
+
+
+
+ from
+ {baseBranch}
+
+
+
+ Based on {baseBranch}
+
+
+ )}
+ >
+ );
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarLeft/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarLeft/index.ts
new file mode 100644
index 000000000..9a42acaa8
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarLeft/index.ts
@@ -0,0 +1 @@
+export { WorkspaceActionBarLeft } from "./WorkspaceActionBarLeft";
diff --git a/apps/desktop/src/renderer/screens/main/components/TopBar/OpenInMenuButton.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarRight/WorkspaceActionBarRight.tsx
similarity index 50%
rename from apps/desktop/src/renderer/screens/main/components/TopBar/OpenInMenuButton.tsx
rename to apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarRight/WorkspaceActionBarRight.tsx
index 698e7d366..222cade48 100644
--- a/apps/desktop/src/renderer/screens/main/components/TopBar/OpenInMenuButton.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarRight/WorkspaceActionBarRight.tsx
@@ -10,12 +10,9 @@ import {
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@superset/ui/dropdown-menu";
-import { toast } from "@superset/ui/sonner";
import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
-import { cn } from "@superset/ui/utils";
-import { memo, useCallback, useMemo } from "react";
import { HiChevronDown } from "react-icons/hi2";
-import { LuCopy } from "react-icons/lu";
+import { LuArrowUpRight, LuCopy } from "react-icons/lu";
import jetbrainsIcon from "renderer/assets/app-icons/jetbrains.svg";
import vscodeIcon from "renderer/assets/app-icons/vscode.svg";
import {
@@ -24,127 +21,121 @@ import {
JETBRAINS_OPTIONS,
VSCODE_OPTIONS,
} from "renderer/components/OpenInButton";
+import { shortenHomePath } from "renderer/lib/formatPath";
import { trpc } from "renderer/lib/trpc";
import { useHotkeyText } from "renderer/stores/hotkeys";
-interface OpenInMenuButtonProps {
+interface FormattedPath {
+ prefix: string;
+ worktreeName: string;
+}
+
+function formatWorktreePath(
+ path: string,
+ homeDir: string | undefined,
+): FormattedPath {
+ const shortenedPath = shortenHomePath(path, homeDir);
+
+ // Split into prefix and worktree name (last segment)
+ const lastSlashIndex = shortenedPath.lastIndexOf("/");
+ if (lastSlashIndex !== -1) {
+ return {
+ prefix: shortenedPath.slice(0, lastSlashIndex + 1),
+ worktreeName: shortenedPath.slice(lastSlashIndex + 1),
+ };
+ }
+
+ return { prefix: "", worktreeName: shortenedPath };
+}
+
+interface WorkspaceActionBarRightProps {
worktreePath: string;
- branch?: string;
}
-export const OpenInMenuButton = memo(function OpenInMenuButton({
+export function WorkspaceActionBarRight({
worktreePath,
- branch,
-}: OpenInMenuButtonProps) {
+}: WorkspaceActionBarRightProps) {
+ const { data: homeDir } = trpc.window.getHomeDir.useQuery();
const utils = trpc.useUtils();
const { data: lastUsedApp = "cursor" } =
- trpc.settings.getLastUsedApp.useQuery(undefined, {
- staleTime: 30000,
- });
+ trpc.settings.getLastUsedApp.useQuery();
const openInApp = trpc.external.openInApp.useMutation({
onSuccess: () => utils.settings.getLastUsedApp.invalidate(),
- onError: (error) => toast.error(`Failed to open: ${error.message}`),
- });
- const copyPath = trpc.external.copyPath.useMutation({
- onSuccess: () => toast.success("Path copied to clipboard"),
- onError: (error) => toast.error(`Failed to copy path: ${error.message}`),
});
+ const copyPath = trpc.external.copyPath.useMutation();
- const currentApp = useMemo(() => getAppOption(lastUsedApp), [lastUsedApp]);
+ const formattedPath = formatWorktreePath(worktreePath, homeDir);
+ const currentApp = getAppOption(lastUsedApp);
const openInShortcut = useHotkeyText("OPEN_IN_APP");
const copyPathShortcut = useHotkeyText("COPY_PATH");
const showOpenInShortcut = openInShortcut !== "Unassigned";
const showCopyPathShortcut = copyPathShortcut !== "Unassigned";
- const isLoading = openInApp.isPending || copyPath.isPending;
- const handleOpenInEditor = useCallback(() => {
- if (openInApp.isPending || copyPath.isPending) return;
+ const handleOpenInEditor = () => {
openInApp.mutate({ path: worktreePath, app: lastUsedApp });
- }, [worktreePath, lastUsedApp, openInApp, copyPath.isPending]);
+ };
- const handleOpenInOtherApp = useCallback(
- (appId: ExternalApp) => {
- if (openInApp.isPending || copyPath.isPending) return;
- openInApp.mutate({ path: worktreePath, app: appId });
- },
- [worktreePath, openInApp, copyPath.isPending],
- );
+ const handleOpenInOtherApp = (appId: ExternalApp) => {
+ openInApp.mutate({ path: worktreePath, app: appId });
+ };
- const handleCopyPath = useCallback(() => {
- if (openInApp.isPending || copyPath.isPending) return;
+ const handleCopyPath = () => {
copyPath.mutate(worktreePath);
- }, [worktreePath, copyPath, openInApp.isPending]);
+ };
+
+ const BUTTON_HEIGHT = 24;
return (
-
- {/* Main button - opens in last used app */}
+ <>
+ {/* Path - clickable to open */}
- {branch && (
-
- /{branch}
-
- )}
- Open
+
+ {formattedPath.prefix}
+
+
+ {formattedPath.worktreeName}
+
+
-
-
-
- Open in {currentApp.displayLabel ?? currentApp.label}
- {showOpenInShortcut && (
-
- {openInShortcut}
-
- )}
-
- {branch && (
-
- /{branch}
-
- )}
-
+
+
+ Open in {currentApp.displayLabel ?? currentApp.label}
+
+ {showOpenInShortcut ? openInShortcut : "—"}
+
+
- {/* Dropdown trigger */}
+ {/* Open dropdown button */}
-
+
+ Open
+
+
-
+
{APP_OPTIONS.map((app) => (
{app.label}
@@ -165,12 +156,12 @@ export const OpenInMenuButton = memo(function OpenInMenuButton({
VS Code
-
+
{VSCODE_OPTIONS.map((app) => (
{app.label}
- {app.id === lastUsedApp && showOpenInShortcut && (
-
- {openInShortcut}
-
+ {app.id === lastUsedApp && (
+ ⌘O
)}
))}
@@ -195,12 +184,12 @@ export const OpenInMenuButton = memo(function OpenInMenuButton({
JetBrains
-
+
{JETBRAINS_OPTIONS.map((app) => (
{app.label}
@@ -226,6 +215,6 @@ export const OpenInMenuButton = memo(function OpenInMenuButton({
-
+ >
);
-});
+}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarRight/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarRight/index.ts
new file mode 100644
index 000000000..da70bada5
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/components/WorkspaceActionBarRight/index.ts
@@ -0,0 +1 @@
+export { WorkspaceActionBarRight } from "./WorkspaceActionBarRight";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/index.ts
new file mode 100644
index 000000000..c8caa3fbc
--- /dev/null
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceActionBar/index.ts
@@ -0,0 +1 @@
+export { WorkspaceActionBar } from "./WorkspaceActionBar";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/WorkspaceInitializingView.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/WorkspaceInitializingView.tsx
deleted file mode 100644
index 3140858c2..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/WorkspaceInitializingView.tsx
+++ /dev/null
@@ -1,328 +0,0 @@
-import {
- AlertDialog,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogTitle,
-} from "@superset/ui/alert-dialog";
-import { Button } from "@superset/ui/button";
-import { cn } from "@superset/ui/utils";
-import { useState } from "react";
-import { HiExclamationTriangle } from "react-icons/hi2";
-import { LuCheck, LuCircle, LuGitBranch, LuLoader } from "react-icons/lu";
-import { trpc } from "renderer/lib/trpc";
-import {
- useHasWorkspaceFailed,
- useWorkspaceInitProgress,
-} from "renderer/stores/workspace-init";
-import {
- INIT_STEP_MESSAGES,
- INIT_STEP_ORDER,
- isStepComplete,
- type WorkspaceInitStep,
-} from "shared/types/workspace-init";
-
-interface WorkspaceInitializingViewProps {
- workspaceId: string;
- workspaceName: string;
- /** True if init was interrupted (e.g., app restart during init) */
- isInterrupted?: boolean;
-}
-
-// Steps to display in the progress view (skip pending and ready)
-const DISPLAY_STEPS: WorkspaceInitStep[] = INIT_STEP_ORDER.filter(
- (step) => step !== "pending" && step !== "ready",
-);
-
-export function WorkspaceInitializingView({
- workspaceId,
- workspaceName,
- isInterrupted = false,
-}: WorkspaceInitializingViewProps) {
- const progress = useWorkspaceInitProgress(workspaceId);
- const hasFailed = useHasWorkspaceFailed(workspaceId);
- const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
-
- const retryMutation = trpc.workspaces.retryInit.useMutation();
- const deleteMutation = trpc.workspaces.delete.useMutation();
- const utils = trpc.useUtils();
-
- const handleRetry = () => {
- retryMutation.mutate(
- { workspaceId },
- {
- onSuccess: () => {
- utils.workspaces.invalidate();
- },
- },
- );
- };
-
- const handleDelete = () => {
- setShowDeleteConfirm(false);
- deleteMutation.mutate(
- { id: workspaceId },
- {
- onSuccess: () => {
- utils.workspaces.invalidate();
- },
- },
- );
- };
-
- const currentStep = progress?.step ?? "pending";
-
- // Interrupted state (app restart during init - no in-memory progress)
- if (isInterrupted && !progress) {
- return (
- <>
-
-
- {/* Warning icon */}
-
-
-
-
- {/* Title and description */}
-
-
- Setup was interrupted
-
-
{workspaceName}
-
- The app was closed before workspace setup completed. You can
- retry the setup or delete this workspace.
-
-
-
- {/* Action buttons */}
-
- setShowDeleteConfirm(true)}
- disabled={deleteMutation.isPending}
- >
- {deleteMutation.isPending ? "Deleting..." : "Delete Workspace"}
-
-
- {retryMutation.isPending ? (
- <>
-
- Retrying...
- >
- ) : (
- "Retry Setup"
- )}
-
-
-
-
-
- {/* Delete confirmation dialog */}
-
-
-
-
- Delete workspace "{workspaceName}"?
-
-
-
- This workspace was not fully set up. Deleting will clean up
- any partial files that were created.
-
-
-
-
- setShowDeleteConfirm(false)}
- >
- Cancel
-
-
- Delete
-
-
-
-
- >
- );
- }
-
- // Failed state
- if (hasFailed) {
- return (
- <>
-
-
- {/* Error icon */}
-
-
-
-
- {/* Title and description */}
-
-
- Workspace setup failed
-
-
{workspaceName}
- {progress?.error && (
-
- {progress.error}
-
- )}
-
-
- {/* Action buttons */}
-
- setShowDeleteConfirm(true)}
- disabled={deleteMutation.isPending}
- >
- {deleteMutation.isPending ? "Deleting..." : "Delete Workspace"}
-
-
- {retryMutation.isPending ? (
- <>
-
- Retrying...
- >
- ) : (
- "Retry"
- )}
-
-
-
-
-
- {/* Delete confirmation dialog */}
-
-
-
-
- Delete workspace "{workspaceName}"?
-
-
-
- This workspace failed to initialize. Deleting will clean up
- any partial files that were created.
-
-
-
-
- setShowDeleteConfirm(false)}
- >
- Cancel
-
-
- Delete
-
-
-
-
- >
- );
- }
-
- // Initializing state
- return (
-
-
- {/* Icon with pulse animation */}
-
-
- {/* Title and description */}
-
-
- Setting up workspace
-
-
{workspaceName}
-
-
- {/* Step list */}
-
- {DISPLAY_STEPS.map((step) => {
- const isComplete = isStepComplete(step, currentStep);
- const isCurrent = step === currentStep;
-
- return (
-
- {/* Step icon */}
- {isComplete ? (
-
- ) : isCurrent ? (
-
- ) : (
-
- )}
-
- {/* Step label */}
-
- {INIT_STEP_MESSAGES[step]}
-
-
- );
- })}
-
-
- {/* Helper text */}
-
- Takes 10s to a few minutes depending on the size of your repo
-
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/index.ts
deleted file mode 100644
index 6685f11c9..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { WorkspaceInitializingView } from "./WorkspaceInitializingView";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/index.tsx
index ac24a87d6..661543c85 100644
--- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/index.tsx
+++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/index.tsx
@@ -3,33 +3,13 @@ import { trpc } from "renderer/lib/trpc";
import { useAppHotkey } from "renderer/stores/hotkeys";
import { useTabsStore } from "renderer/stores/tabs/store";
import { getNextPaneId, getPreviousPaneId } from "renderer/stores/tabs/utils";
-import {
- useHasWorkspaceFailed,
- useIsWorkspaceInitializing,
-} from "renderer/stores/workspace-init";
import { ContentView } from "./ContentView";
-import { WorkspaceInitializingView } from "./WorkspaceInitializingView";
+import { ResizableSidebar } from "./ResizableSidebar";
+import { WorkspaceActionBar } from "./WorkspaceActionBar";
export function WorkspaceView() {
const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
const activeWorkspaceId = activeWorkspace?.id;
-
- // Check if active workspace is initializing or failed
- const isInitializing = useIsWorkspaceInitializing(activeWorkspaceId ?? "");
- const hasFailed = useHasWorkspaceFailed(activeWorkspaceId ?? "");
-
- // Also check for incomplete init after app restart:
- // - worktree type workspace with null/undefined gitStatus means init never completed
- // - This handles the case where app restarts during init (in-memory progress lost)
- // - Uses explicit check instead of == null to avoid lint issues
- const gitStatus = activeWorkspace?.worktree?.gitStatus;
- const hasIncompleteInit =
- activeWorkspace?.type === "worktree" &&
- (gitStatus === null || gitStatus === undefined);
-
- const showInitView =
- activeWorkspaceId && (isInitializing || hasFailed || hasIncompleteInit);
-
const allTabs = useTabsStore((s) => s.tabs);
const activeTabIds = useTabsStore((s) => s.activeTabIds);
const focusedPaneIds = useTabsStore((s) => s.focusedPaneIds);
@@ -61,7 +41,7 @@ export function WorkspaceView() {
// Tab management shortcuts
useAppHotkey(
- "NEW_GROUP",
+ "NEW_TERMINAL",
() => {
if (activeWorkspaceId) {
addTab(activeWorkspaceId);
@@ -83,7 +63,7 @@ export function WorkspaceView() {
[focusedPaneId, removePane],
);
- // Switch between tabs (⌘+Up/Down)
+ // Switch between tabs (configurable shortcut)
useAppHotkey(
"PREV_TERMINAL",
() => {
@@ -110,7 +90,7 @@ export function WorkspaceView() {
[activeWorkspaceId, activeTabId, tabs, setActiveTab],
);
- // Switch between panes within a tab (⌘+⌥+Left/Right)
+ // Switch between panes within a tab (configurable shortcut)
useAppHotkey(
"PREV_PANE",
() => {
@@ -170,16 +150,14 @@ export function WorkspaceView() {
return (
-
- {showInitView && activeWorkspaceId ? (
-
- ) : (
-
- )}
+
);
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspaceRow/WorkspaceRow.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspaceRow/WorkspaceRow.tsx
deleted file mode 100644
index 8f06de0e4..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspaceRow/WorkspaceRow.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { cn } from "@superset/ui/utils";
-import { useState } from "react";
-import {
- LuArrowRight,
- LuGitBranch,
- LuGitFork,
- LuRotateCw,
-} from "react-icons/lu";
-import { trpc } from "renderer/lib/trpc";
-import type { WorkspaceItem } from "../types";
-import { getRelativeTime } from "../utils";
-
-const GITHUB_STATUS_STALE_TIME = 5 * 60 * 1000; // 5 minutes
-
-interface WorkspaceRowProps {
- workspace: WorkspaceItem;
- isActive: boolean;
- onSwitch: () => void;
- onReopen: () => void;
- isOpening?: boolean;
-}
-
-export function WorkspaceRow({
- workspace,
- isActive,
- onSwitch,
- onReopen,
- isOpening,
-}: WorkspaceRowProps) {
- const isBranch = workspace.type === "branch";
- const [hasHovered, setHasHovered] = useState(false);
-
- // Lazy-load GitHub status on hover to avoid N+1 queries
- const { data: githubStatus } = trpc.workspaces.getGitHubStatus.useQuery(
- { workspaceId: workspace.workspaceId ?? "" },
- {
- enabled:
- hasHovered && workspace.type === "worktree" && !!workspace.workspaceId,
- staleTime: GITHUB_STATUS_STALE_TIME,
- },
- );
-
- const pr = githubStatus?.pr;
- const showDiffStats = pr && (pr.additions > 0 || pr.deletions > 0);
-
- const timeText = workspace.isOpen
- ? `Opened ${getRelativeTime(workspace.lastOpenedAt)}`
- : `Created ${getRelativeTime(workspace.createdAt)}`;
-
- const handleClick = () => {
- if (workspace.isOpen) {
- onSwitch();
- } else {
- onReopen();
- }
- };
-
- return (
-
!hasHovered && setHasHovered(true)}
- className={cn(
- "flex items-center gap-3 w-full px-4 py-2 group text-left",
- "hover:bg-background/50 transition-colors",
- isActive && "bg-background/70",
- isOpening && "opacity-50 cursor-wait",
- )}
- >
- {/* Icon */}
-
- {isBranch ? (
-
- ) : (
-
- )}
-
-
- {/* Workspace/branch name */}
-
- {workspace.name}
-
-
- {/* Active indicator */}
- {isActive && (
-
- )}
-
- {/* Unread indicator */}
- {workspace.isUnread && !isActive && (
-
-
-
-
- )}
-
- {/* Diff stats */}
- {showDiffStats && (
-
- +{pr.additions}
- -{pr.deletions}
-
- )}
-
- {/* Spacer */}
-
-
- {/* Time context */}
-
- {timeText}
-
-
- {/* Action indicator - visible on hover */}
-
- {isOpening ? (
- <>
-
- Opening...
- >
- ) : workspace.isOpen ? (
- <>
- Switch to
-
- >
- ) : (
- <>
- Reopen
-
- >
- )}
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspaceRow/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspaceRow/index.ts
deleted file mode 100644
index 0a45a4a84..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspaceRow/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./WorkspaceRow";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspacesListView.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspacesListView.tsx
deleted file mode 100644
index 8a3d50a2c..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/WorkspacesListView.tsx
+++ /dev/null
@@ -1,282 +0,0 @@
-import { Button } from "@superset/ui/button";
-import { Input } from "@superset/ui/input";
-import { toast } from "@superset/ui/sonner";
-import { cn } from "@superset/ui/utils";
-import { useMemo, useState } from "react";
-import { LuSearch, LuX } from "react-icons/lu";
-import { trpc } from "renderer/lib/trpc";
-import { useSetActiveWorkspace } from "renderer/react-query/workspaces";
-import { useCloseWorkspacesList } from "renderer/stores/app-state";
-import type { FilterMode, ProjectGroup, WorkspaceItem } from "./types";
-import { WorkspaceRow } from "./WorkspaceRow";
-
-const FILTER_OPTIONS: { value: FilterMode; label: string }[] = [
- { value: "all", label: "All" },
- { value: "active", label: "Active" },
- { value: "closed", label: "Closed" },
-];
-
-export function WorkspacesListView() {
- const [searchQuery, setSearchQuery] = useState("");
- const [filterMode, setFilterMode] = useState
("all");
- const utils = trpc.useUtils();
-
- // Fetch all data
- const { data: groups = [] } = trpc.workspaces.getAllGrouped.useQuery();
- const { data: allProjects = [] } = trpc.projects.getRecents.useQuery();
- const { data: activeWorkspace } = trpc.workspaces.getActive.useQuery();
-
- // Fetch worktrees for all projects
- const worktreeQueries = trpc.useQueries((t) =>
- allProjects.map((project) =>
- t.workspaces.getWorktreesByProject({ projectId: project.id }),
- ),
- );
-
- const setActiveWorkspace = useSetActiveWorkspace();
- const closeWorkspacesList = useCloseWorkspacesList();
-
- const openWorktree = trpc.workspaces.openWorktree.useMutation({
- onSuccess: () => {
- utils.workspaces.getAllGrouped.invalidate();
- utils.workspaces.getActive.invalidate();
- closeWorkspacesList();
- },
- onError: (error) => {
- toast.error(`Failed to open workspace: ${error.message}`);
- },
- });
-
- // Combine open workspaces and closed worktrees into a single list
- const allItems = useMemo(() => {
- const items: WorkspaceItem[] = [];
-
- // First, add all open workspaces from groups
- for (const group of groups) {
- for (const ws of group.workspaces) {
- items.push({
- uniqueId: ws.id,
- workspaceId: ws.id,
- worktreeId: null,
- projectId: ws.projectId,
- projectName: group.project.name,
- worktreePath: ws.worktreePath,
- type: ws.type,
- branch: ws.branch,
- name: ws.name,
- lastOpenedAt: ws.lastOpenedAt,
- createdAt: ws.createdAt,
- isUnread: ws.isUnread,
- isOpen: true,
- });
- }
- }
-
- // Add closed worktrees (those without active workspaces)
- for (let i = 0; i < allProjects.length; i++) {
- const project = allProjects[i];
- const worktrees = worktreeQueries[i]?.data;
-
- if (!worktrees) continue;
-
- for (const wt of worktrees) {
- // Skip if this worktree has an active workspace
- if (wt.hasActiveWorkspace) continue;
-
- items.push({
- uniqueId: `wt-${wt.id}`,
- workspaceId: null,
- worktreeId: wt.id,
- projectId: project.id,
- projectName: project.name,
- worktreePath: wt.path,
- type: "worktree",
- branch: wt.branch,
- name: wt.branch,
- lastOpenedAt: wt.createdAt,
- createdAt: wt.createdAt,
- isUnread: false,
- isOpen: false,
- });
- }
- }
-
- return items;
- }, [groups, allProjects, worktreeQueries]);
-
- // Filter by search query and filter mode
- const filteredItems = useMemo(() => {
- let items = allItems;
-
- // Apply filter mode
- if (filterMode === "active") {
- items = items.filter((ws) => ws.isOpen);
- } else if (filterMode === "closed") {
- items = items.filter((ws) => !ws.isOpen);
- }
-
- // Apply search filter
- if (searchQuery.trim()) {
- const query = searchQuery.toLowerCase();
- items = items.filter(
- (ws) =>
- ws.name.toLowerCase().includes(query) ||
- ws.projectName.toLowerCase().includes(query) ||
- ws.branch.toLowerCase().includes(query),
- );
- }
-
- return items;
- }, [allItems, searchQuery, filterMode]);
-
- // Group by project
- const projectGroups = useMemo(() => {
- const groupsMap = new Map();
-
- for (const item of filteredItems) {
- if (!groupsMap.has(item.projectId)) {
- groupsMap.set(item.projectId, {
- projectId: item.projectId,
- projectName: item.projectName,
- workspaces: [],
- });
- }
- groupsMap.get(item.projectId)?.workspaces.push(item);
- }
-
- // Sort workspaces within each group: active first, then by lastOpenedAt
- for (const group of groupsMap.values()) {
- group.workspaces.sort((a, b) => {
- // Active workspaces first
- if (a.isOpen !== b.isOpen) return a.isOpen ? -1 : 1;
- // Then by most recently opened/created
- return b.lastOpenedAt - a.lastOpenedAt;
- });
- }
-
- // Sort groups by most recent activity
- return Array.from(groupsMap.values()).sort((a, b) => {
- const aRecent = Math.max(...a.workspaces.map((w) => w.lastOpenedAt));
- const bRecent = Math.max(...b.workspaces.map((w) => w.lastOpenedAt));
- return bRecent - aRecent;
- });
- }, [filteredItems]);
-
- const handleSwitch = (item: WorkspaceItem) => {
- if (item.workspaceId) {
- setActiveWorkspace.mutate({ id: item.workspaceId });
- closeWorkspacesList();
- }
- };
-
- const handleReopen = (item: WorkspaceItem) => {
- if (item.worktreeId) {
- openWorktree.mutate({ worktreeId: item.worktreeId });
- }
- };
-
- // Count stats for filter badges
- const activeCount = allItems.filter((w) => w.isOpen).length;
- const closedCount = allItems.filter((w) => !w.isOpen).length;
-
- return (
-
- {/* Header */}
-
- {/* Filter toggle */}
-
- {FILTER_OPTIONS.map((option) => {
- const count =
- option.value === "all"
- ? allItems.length
- : option.value === "active"
- ? activeCount
- : closedCount;
- return (
- setFilterMode(option.value)}
- className={cn(
- "px-2 py-1 text-xs rounded transition-colors",
- filterMode === option.value
- ? "bg-accent text-foreground"
- : "text-foreground/60 hover:text-foreground",
- )}
- >
- {option.label}
- {count}
-
- );
- })}
-
-
- {/* Search */}
-
-
- setSearchQuery(e.target.value)}
- className="pl-9 h-8 bg-background/50"
- />
-
-
- {/* Close button */}
-
-
-
-
-
- {/* Workspaces list grouped by project */}
-
- {projectGroups.map((group) => (
-
- {/* Project header */}
-
-
- {group.projectName}
-
-
- {group.workspaces.length}
-
-
-
- {/* Workspaces in this project */}
- {group.workspaces.map((ws) => (
-
handleSwitch(ws)}
- onReopen={() => handleReopen(ws)}
- isOpening={
- openWorktree.isPending &&
- openWorktree.variables?.worktreeId === ws.worktreeId
- }
- />
- ))}
-
- ))}
-
- {filteredItems.length === 0 && (
-
- {searchQuery
- ? "No workspaces match your search"
- : filterMode === "active"
- ? "No active workspaces"
- : filterMode === "closed"
- ? "No closed workspaces"
- : "No workspaces yet"}
-
- )}
-
-
- );
-}
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/index.ts
deleted file mode 100644
index 7d55b16cb..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { WorkspacesListView } from "./WorkspacesListView";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/types.ts b/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/types.ts
deleted file mode 100644
index 587000def..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/types.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export interface WorkspaceItem {
- // Unique identifier - either workspace id or worktree id for closed ones
- uniqueId: string;
- // If open, this is the workspace id
- workspaceId: string | null;
- // For closed worktrees, this is the worktree id
- worktreeId: string | null;
- projectId: string;
- projectName: string;
- worktreePath: string;
- type: "worktree" | "branch";
- branch: string;
- name: string;
- lastOpenedAt: number;
- createdAt: number;
- isUnread: boolean;
- isOpen: boolean;
-}
-
-export interface ProjectGroup {
- projectId: string;
- projectName: string;
- workspaces: WorkspaceItem[];
-}
-
-export type FilterMode = "all" | "active" | "closed";
diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/utils.ts b/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/utils.ts
deleted file mode 100644
index 1640b1688..000000000
--- a/apps/desktop/src/renderer/screens/main/components/WorkspacesListView/utils.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-// Time unit constants (in milliseconds)
-const MS_PER_SECOND = 1000;
-const MS_PER_MINUTE = MS_PER_SECOND * 60;
-const MS_PER_HOUR = MS_PER_MINUTE * 60;
-const MS_PER_DAY = MS_PER_HOUR * 24;
-
-// Time threshold constants (in their respective units)
-const MINUTES_PER_HOUR = 60;
-const HOURS_PER_DAY = 24;
-const DAYS_PER_WEEK = 7;
-const DAYS_PER_MONTH = 30;
-const DAYS_PER_YEAR = 365;
-
-// Relative time display thresholds (in days)
-const TWO_WEEKS_DAYS = 14;
-const TWO_MONTHS_DAYS = 60;
-
-/**
- * Returns a human-readable relative time string
- * e.g., "2 hours ago", "yesterday", "3 days ago"
- */
-export function getRelativeTime(timestamp: number): string {
- const now = Date.now();
- const diff = now - timestamp;
-
- const minutes = Math.floor(diff / MS_PER_MINUTE);
- const hours = Math.floor(diff / MS_PER_HOUR);
- const days = Math.floor(diff / MS_PER_DAY);
-
- if (minutes < 1) return "just now";
- if (minutes < MINUTES_PER_HOUR) return `${minutes}m ago`;
- if (hours < HOURS_PER_DAY) return `${hours}h ago`;
- if (days === 1) return "yesterday";
- if (days < DAYS_PER_WEEK) return `${days} days ago`;
- if (days < TWO_WEEKS_DAYS) return "1 week ago";
- if (days < DAYS_PER_MONTH)
- return `${Math.floor(days / DAYS_PER_WEEK)} weeks ago`;
- if (days < TWO_MONTHS_DAYS) return "1 month ago";
- if (days < DAYS_PER_YEAR)
- return `${Math.floor(days / DAYS_PER_MONTH)} months ago`;
- return "over a year ago";
-}
diff --git a/apps/desktop/src/renderer/screens/main/hooks/index.ts b/apps/desktop/src/renderer/screens/main/hooks/index.ts
index 8b8a83fbc..8337712ea 100644
--- a/apps/desktop/src/renderer/screens/main/hooks/index.ts
+++ b/apps/desktop/src/renderer/screens/main/hooks/index.ts
@@ -1,2 +1 @@
-export { usePRStatus } from "./usePRStatus";
-export { useWorkspaceRename } from "./useWorkspaceRename";
+//
diff --git a/apps/desktop/src/renderer/screens/main/hooks/usePRStatus/index.ts b/apps/desktop/src/renderer/screens/main/hooks/usePRStatus/index.ts
deleted file mode 100644
index f552343f7..000000000
--- a/apps/desktop/src/renderer/screens/main/hooks/usePRStatus/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { usePRStatus } from "./usePRStatus";
diff --git a/apps/desktop/src/renderer/screens/main/hooks/usePRStatus/usePRStatus.ts b/apps/desktop/src/renderer/screens/main/hooks/usePRStatus/usePRStatus.ts
deleted file mode 100644
index 713d7ff91..000000000
--- a/apps/desktop/src/renderer/screens/main/hooks/usePRStatus/usePRStatus.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import type { GitHubStatus } from "@superset/local-db";
-import { trpc } from "renderer/lib/trpc";
-
-interface UsePRStatusOptions {
- workspaceId: string | undefined;
- enabled?: boolean;
- refetchInterval?: number;
-}
-
-interface UsePRStatusResult {
- pr: GitHubStatus["pr"] | null;
- repoUrl: string | null;
- branchExistsOnRemote: boolean;
- isLoading: boolean;
- refetch: () => void;
-}
-
-/**
- * Hook to fetch and manage GitHub PR status for a workspace.
- * Returns PR info, loading state, and refetch function.
- */
-export function usePRStatus({
- workspaceId,
- enabled = true,
- refetchInterval,
-}: UsePRStatusOptions): UsePRStatusResult {
- const {
- data: githubStatus,
- isLoading,
- refetch,
- } = trpc.workspaces.getGitHubStatus.useQuery(
- { workspaceId: workspaceId ?? "" },
- {
- enabled: enabled && !!workspaceId,
- refetchInterval,
- },
- );
-
- return {
- pr: githubStatus?.pr ?? null,
- repoUrl: githubStatus?.repoUrl ?? null,
- branchExistsOnRemote: githubStatus?.branchExistsOnRemote ?? false,
- isLoading,
- refetch,
- };
-}
diff --git a/apps/desktop/src/renderer/screens/main/hooks/useWorkspaceRename/index.ts b/apps/desktop/src/renderer/screens/main/hooks/useWorkspaceRename/index.ts
deleted file mode 100644
index 4b8035beb..000000000
--- a/apps/desktop/src/renderer/screens/main/hooks/useWorkspaceRename/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { useWorkspaceRename } from "./useWorkspaceRename";
diff --git a/apps/desktop/src/renderer/screens/main/index.tsx b/apps/desktop/src/renderer/screens/main/index.tsx
index e339381a8..98f2cc947 100644
--- a/apps/desktop/src/renderer/screens/main/index.tsx
+++ b/apps/desktop/src/renderer/screens/main/index.tsx
@@ -19,8 +19,6 @@ import { useTabsStore } from "renderer/stores/tabs/store";
import type { Tab } from "renderer/stores/tabs/types";
import { useAgentHookListener } from "renderer/stores/tabs/useAgentHookListener";
import { findPanePath, getFirstPaneId } from "renderer/stores/tabs/utils";
-import { useWorkspaceInitStore } from "renderer/stores/workspace-init";
-import { useWorkspaceSidebarStore } from "renderer/stores/workspace-sidebar-state";
import { dragDropManager } from "../../lib/dnd";
import { AppFrame } from "./components/AppFrame";
import { Background } from "./components/Background";
@@ -28,9 +26,6 @@ import { SettingsView } from "./components/SettingsView";
import { StartView } from "./components/StartView";
import { TasksView } from "./components/TasksView";
import { TopBar } from "./components/TopBar";
-import { WorkspaceInitEffects } from "./components/WorkspaceInitEffects";
-import { ResizableWorkspaceSidebar } from "./components/WorkspaceSidebar";
-import { WorkspacesListView } from "./components/WorkspacesListView";
import { WorkspaceView } from "./components/WorkspaceView";
function LoadingSpinner() {
@@ -59,27 +54,12 @@ export function MainScreen() {
onData: () => utils.auth.getState.invalidate(),
});
- // Subscribe to workspace initialization progress
- const updateInitProgress = useWorkspaceInitStore((s) => s.updateProgress);
- trpc.workspaces.onInitProgress.useSubscription(undefined, {
- onData: (progress) => {
- updateInitProgress(progress);
- // Invalidate workspace queries when initialization completes or fails
- if (progress.step === "ready" || progress.step === "failed") {
- utils.workspaces.getActive.invalidate();
- utils.workspaces.getAllGrouped.invalidate();
- }
- },
- });
-
const currentView = useCurrentView();
const openSettings = useOpenSettings();
- const toggleSidebar = useSidebarStore((s) => s.toggleSidebar);
- const toggleWorkspaceSidebar = useWorkspaceSidebarStore((s) => s.toggleOpen);
+ const { toggleSidebar } = useSidebarStore();
const hasTasksAccess = useFeatureFlagEnabled(
FEATURE_FLAGS.ELECTRIC_TASKS_ACCESS,
);
-
const {
data: activeWorkspace,
isLoading: isWorkspaceLoading,
@@ -131,15 +111,6 @@ export function MainScreen() {
[toggleSidebar, isWorkspaceView],
);
- useAppHotkey(
- "TOGGLE_WORKSPACE_SIDEBAR",
- () => {
- toggleWorkspaceSidebar();
- },
- undefined,
- [toggleWorkspaceSidebar],
- );
-
/**
* Resolves the target pane for split operations.
* If the focused pane is desynced from layout (e.g., was removed),
@@ -296,9 +267,6 @@ export function MainScreen() {
if (currentView === "tasks" && hasTasksAccess) {
return ;
}
- if (currentView === "workspaces-list") {
- return ;
- }
return ;
};
@@ -369,16 +337,12 @@ export function MainScreen() {
) : (
-
-
- {renderContent()}
-
+
{renderContent()}
)}
-
);
}
diff --git a/apps/desktop/src/renderer/screens/sign-in/index.tsx b/apps/desktop/src/renderer/screens/sign-in/index.tsx
index 032ebb07a..3fe2118f9 100644
--- a/apps/desktop/src/renderer/screens/sign-in/index.tsx
+++ b/apps/desktop/src/renderer/screens/sign-in/index.tsx
@@ -1,11 +1,10 @@
-import { COMPANY } from "@superset/shared/constants";
+import { type AuthProvider, COMPANY } from "@superset/shared/constants";
import { Button } from "@superset/ui/button";
import { useEffect } from "react";
import { FaGithub } from "react-icons/fa";
import { FcGoogle } from "react-icons/fc";
import { posthog } from "renderer/lib/posthog";
import { trpc } from "renderer/lib/trpc";
-import type { AuthProvider } from "shared/auth";
import { SupersetLogo } from "./components/SupersetLogo";
export function SignInScreen() {
diff --git a/apps/desktop/src/renderer/stores/app-state.ts b/apps/desktop/src/renderer/stores/app-state.ts
index ba6ffcd1c..296752c34 100644
--- a/apps/desktop/src/renderer/stores/app-state.ts
+++ b/apps/desktop/src/renderer/stores/app-state.ts
@@ -1,7 +1,7 @@
import { create } from "zustand";
import { devtools } from "zustand/middleware";
-export type AppView = "workspace" | "settings" | "tasks" | "workspaces-list";
+export type AppView = "workspace" | "settings" | "tasks";
export type SettingsSection =
| "account"
| "project"
@@ -16,7 +16,6 @@ interface AppState {
currentView: AppView;
isSettingsTabOpen: boolean;
isTasksTabOpen: boolean;
- isWorkspacesListOpen: boolean;
settingsSection: SettingsSection;
setView: (view: AppView) => void;
openSettings: (section?: SettingsSection) => void;
@@ -25,8 +24,6 @@ interface AppState {
setSettingsSection: (section: SettingsSection) => void;
openTasks: () => void;
closeTasks: () => void;
- openWorkspacesList: () => void;
- closeWorkspacesList: () => void;
}
export const useAppStore = create()(
@@ -35,7 +32,6 @@ export const useAppStore = create()(
currentView: "workspace",
isSettingsTabOpen: false,
isTasksTabOpen: false,
- isWorkspacesListOpen: false,
settingsSection: "project",
setView: (view) => {
@@ -69,14 +65,6 @@ export const useAppStore = create()(
closeTasks: () => {
set({ currentView: "workspace", isTasksTabOpen: false });
},
-
- openWorkspacesList: () => {
- set({ currentView: "workspaces-list", isWorkspacesListOpen: true });
- },
-
- closeWorkspacesList: () => {
- set({ currentView: "workspace", isWorkspacesListOpen: false });
- },
}),
{ name: "AppStore" },
),
@@ -99,7 +87,3 @@ export const useCloseSettingsTab = () =>
useAppStore((state) => state.closeSettingsTab);
export const useOpenTasks = () => useAppStore((state) => state.openTasks);
export const useCloseTasks = () => useAppStore((state) => state.closeTasks);
-export const useOpenWorkspacesList = () =>
- useAppStore((state) => state.openWorkspacesList);
-export const useCloseWorkspacesList = () =>
- useAppStore((state) => state.closeWorkspacesList);
diff --git a/apps/desktop/src/renderer/stores/index.ts b/apps/desktop/src/renderer/stores/index.ts
index 824bd5107..b289f0bfb 100644
--- a/apps/desktop/src/renderer/stores/index.ts
+++ b/apps/desktop/src/renderer/stores/index.ts
@@ -6,5 +6,3 @@ export * from "./ringtone";
export * from "./sidebar-state";
export * from "./tabs";
export * from "./theme";
-export * from "./workspace-init";
-export * from "./workspace-sidebar-state";
diff --git a/apps/desktop/src/renderer/stores/new-workspace-modal.ts b/apps/desktop/src/renderer/stores/new-workspace-modal.ts
index 38b18916b..0890c7797 100644
--- a/apps/desktop/src/renderer/stores/new-workspace-modal.ts
+++ b/apps/desktop/src/renderer/stores/new-workspace-modal.ts
@@ -3,8 +3,7 @@ import { devtools } from "zustand/middleware";
interface NewWorkspaceModalState {
isOpen: boolean;
- preSelectedProjectId: string | null;
- openModal: (projectId?: string) => void;
+ openModal: () => void;
closeModal: () => void;
}
@@ -12,14 +11,13 @@ export const useNewWorkspaceModalStore = create()(
devtools(
(set) => ({
isOpen: false,
- preSelectedProjectId: null,
- openModal: (projectId?: string) => {
- set({ isOpen: true, preSelectedProjectId: projectId ?? null });
+ openModal: () => {
+ set({ isOpen: true });
},
closeModal: () => {
- set({ isOpen: false, preSelectedProjectId: null });
+ set({ isOpen: false });
},
}),
{ name: "NewWorkspaceModalStore" },
@@ -33,5 +31,3 @@ export const useOpenNewWorkspaceModal = () =>
useNewWorkspaceModalStore((state) => state.openModal);
export const useCloseNewWorkspaceModal = () =>
useNewWorkspaceModalStore((state) => state.closeModal);
-export const usePreSelectedProjectId = () =>
- useNewWorkspaceModalStore((state) => state.preSelectedProjectId);
diff --git a/apps/desktop/src/renderer/stores/tabs/store.ts b/apps/desktop/src/renderer/stores/tabs/store.ts
index 828d0679d..d28d8316a 100644
--- a/apps/desktop/src/renderer/stores/tabs/store.ts
+++ b/apps/desktop/src/renderer/stores/tabs/store.ts
@@ -4,10 +4,9 @@ import { create } from "zustand";
import { devtools, persist } from "zustand/middleware";
import { trpcTabsStorage } from "../../lib/trpc-storage";
import { movePaneToNewTab, movePaneToTab } from "./actions/move-pane";
-import type { AddFileViewerPaneOptions, TabsState, TabsStore } from "./types";
+import type { TabsState, TabsStore } from "./types";
import {
type CreatePaneOptions,
- createFileViewerPane,
createPane,
createTabWithPane,
extractPaneIdsFromLayout,
@@ -126,11 +125,7 @@ export const useTabsStore = create()(
const paneIds = getPaneIdsForTab(state.panes, tabId);
for (const paneId of paneIds) {
- // Only kill terminal sessions for terminal panes (avoids unnecessary IPC for file-viewers)
- const pane = state.panes[paneId];
- if (pane?.type === "terminal") {
- killTerminalForPane(paneId);
- }
+ killTerminalForPane(paneId);
}
const newPanes = { ...state.panes };
@@ -290,10 +285,7 @@ export const useTabsStore = create()(
const newPanes = { ...state.panes };
for (const paneId of removedPaneIds) {
- // P2: Only kill terminal for actual terminal panes (avoid unnecessary IPC)
- if (state.panes[paneId]?.type === "terminal") {
- killTerminalForPane(paneId);
- }
+ killTerminalForPane(paneId);
delete newPanes[paneId];
}
@@ -348,112 +340,6 @@ export const useTabsStore = create()(
return newPane.id;
},
- addFileViewerPane: (
- workspaceId: string,
- options: AddFileViewerPaneOptions,
- ) => {
- const state = get();
- const activeTabId = state.activeTabIds[workspaceId];
- const activeTab = state.tabs.find((t) => t.id === activeTabId);
-
- // If no active tab, create a new one (this shouldn't normally happen)
- if (!activeTab) {
- const { tabId, paneId } = get().addTab(workspaceId);
- // Update the pane to be a file-viewer (must use set() to get fresh state after addTab)
- const fileViewerPane = createFileViewerPane(tabId, options);
- set((s) => ({
- panes: {
- ...s.panes,
- [paneId]: {
- ...fileViewerPane,
- id: paneId, // Keep the original ID
- },
- },
- }));
- return paneId;
- }
-
- // Look for an existing unlocked file-viewer pane in the active tab
- const tabPaneIds = extractPaneIdsFromLayout(activeTab.layout);
- const fileViewerPanes = tabPaneIds
- .map((id) => state.panes[id])
- .filter(
- (p) =>
- p?.type === "file-viewer" &&
- p.fileViewer &&
- !p.fileViewer.isLocked,
- );
-
- // If we found an unlocked file-viewer pane, reuse it
- if (fileViewerPanes.length > 0) {
- const paneToReuse = fileViewerPanes[0];
- const fileName =
- options.filePath.split("/").pop() || options.filePath;
-
- // Determine default view mode
- let viewMode: "raw" | "rendered" | "diff" = "raw";
- if (options.diffCategory) {
- viewMode = "diff";
- } else if (
- options.filePath.endsWith(".md") ||
- options.filePath.endsWith(".markdown") ||
- options.filePath.endsWith(".mdx")
- ) {
- viewMode = "rendered";
- }
-
- set({
- panes: {
- ...state.panes,
- [paneToReuse.id]: {
- ...paneToReuse,
- name: fileName,
- fileViewer: {
- filePath: options.filePath,
- viewMode,
- isLocked: false,
- diffLayout: "inline",
- diffCategory: options.diffCategory,
- commitHash: options.commitHash,
- oldPath: options.oldPath,
- initialLine: options.line,
- initialColumn: options.column,
- },
- },
- },
- focusedPaneIds: {
- ...state.focusedPaneIds,
- [activeTab.id]: paneToReuse.id,
- },
- });
-
- return paneToReuse.id;
- }
-
- // No reusable pane found, create a new one
- const newPane = createFileViewerPane(activeTab.id, options);
-
- const newLayout: MosaicNode = {
- direction: "row",
- first: activeTab.layout,
- second: newPane.id,
- splitPercentage: 50,
- };
-
- set({
- tabs: state.tabs.map((t) =>
- t.id === activeTab.id ? { ...t, layout: newLayout } : t,
- ),
- panes: { ...state.panes, [newPane.id]: newPane },
- focusedPaneIds: {
- ...state.focusedPaneIds,
- [activeTab.id]: newPane.id,
- },
- });
-
- return newPane.id;
- },
-
removePane: (paneId) => {
const state = get();
const pane = state.panes[paneId];
@@ -468,10 +354,7 @@ export const useTabsStore = create()(
return;
}
- // Only kill terminal sessions for terminal panes (avoids unnecessary IPC for file-viewers)
- if (pane.type === "terminal") {
- killTerminalForPane(paneId);
- }
+ killTerminalForPane(paneId);
const newLayout = removePaneFromLayout(tab.layout, paneId);
if (!newLayout) {
@@ -545,33 +428,6 @@ export const useTabsStore = create()(
}));
},
- clearWorkspaceAttention: (workspaceId) => {
- const state = get();
- const workspaceTabs = state.tabs.filter(
- (t) => t.workspaceId === workspaceId,
- );
- const workspacePaneIds = workspaceTabs.flatMap((t) =>
- extractPaneIdsFromLayout(t.layout),
- );
-
- if (workspacePaneIds.length === 0) {
- return;
- }
-
- const newPanes = { ...state.panes };
- let hasChanges = false;
- for (const paneId of workspacePaneIds) {
- if (newPanes[paneId]?.needsAttention) {
- newPanes[paneId] = { ...newPanes[paneId], needsAttention: false };
- hasChanges = true;
- }
- }
-
- if (hasChanges) {
- set({ panes: newPanes });
- }
- },
-
updatePaneCwd: (paneId, cwd, confirmed) => {
set((state) => ({
panes: {
@@ -607,19 +463,7 @@ export const useTabsStore = create()(
const sourcePane = state.panes[sourcePaneId];
if (!sourcePane || sourcePane.tabId !== tabId) return;
- // Clone file-viewer panes instead of creating a terminal
- const newPane =
- sourcePane.type === "file-viewer" && sourcePane.fileViewer
- ? createFileViewerPane(tabId, {
- filePath: sourcePane.fileViewer.filePath,
- viewMode: sourcePane.fileViewer.viewMode,
- isLocked: true, // Lock the cloned pane
- diffLayout: sourcePane.fileViewer.diffLayout,
- diffCategory: sourcePane.fileViewer.diffCategory,
- commitHash: sourcePane.fileViewer.commitHash,
- oldPath: sourcePane.fileViewer.oldPath,
- })
- : createPane(tabId);
+ const newPane = createPane(tabId);
let newLayout: MosaicNode;
if (path && path.length > 0) {
@@ -667,19 +511,7 @@ export const useTabsStore = create()(
const sourcePane = state.panes[sourcePaneId];
if (!sourcePane || sourcePane.tabId !== tabId) return;
- // Clone file-viewer panes instead of creating a terminal
- const newPane =
- sourcePane.type === "file-viewer" && sourcePane.fileViewer
- ? createFileViewerPane(tabId, {
- filePath: sourcePane.fileViewer.filePath,
- viewMode: sourcePane.fileViewer.viewMode,
- isLocked: true, // Lock the cloned pane
- diffLayout: sourcePane.fileViewer.diffLayout,
- diffCategory: sourcePane.fileViewer.diffCategory,
- commitHash: sourcePane.fileViewer.commitHash,
- oldPath: sourcePane.fileViewer.oldPath,
- })
- : createPane(tabId);
+ const newPane = createPane(tabId);
let newLayout: MosaicNode;
if (path && path.length > 0) {
diff --git a/apps/desktop/src/renderer/stores/tabs/types.ts b/apps/desktop/src/renderer/stores/tabs/types.ts
index 9638df6e0..bcb0f70af 100644
--- a/apps/desktop/src/renderer/stores/tabs/types.ts
+++ b/apps/desktop/src/renderer/stores/tabs/types.ts
@@ -1,5 +1,4 @@
import type { MosaicBranch, MosaicNode } from "react-mosaic-component";
-import type { ChangeCategory } from "shared/changes-types";
import type { BaseTab, BaseTabsState, Pane, PaneType } from "shared/tabs-types";
// Re-export shared types
@@ -29,20 +28,6 @@ export interface AddTabOptions {
initialCwd?: string;
}
-/**
- * Options for opening a file in a file-viewer pane
- */
-export interface AddFileViewerPaneOptions {
- filePath: string;
- diffCategory?: ChangeCategory;
- commitHash?: string;
- oldPath?: string;
- /** Line to scroll to (raw mode only) */
- line?: number;
- /** Column to scroll to (raw mode only) */
- column?: number;
-}
-
/**
* Actions available on the tabs store
*/
@@ -66,15 +51,10 @@ export interface TabsStore extends TabsState {
// Pane operations
addPane: (tabId: string, options?: AddTabOptions) => string;
- addFileViewerPane: (
- workspaceId: string,
- options: AddFileViewerPaneOptions,
- ) => string;
removePane: (paneId: string) => void;
setFocusedPane: (tabId: string, paneId: string) => void;
markPaneAsUsed: (paneId: string) => void;
setNeedsAttention: (paneId: string, needsAttention: boolean) => void;
- clearWorkspaceAttention: (workspaceId: string) => void;
updatePaneCwd: (
paneId: string,
cwd: string | null,
diff --git a/apps/desktop/src/renderer/stores/tabs/utils.ts b/apps/desktop/src/renderer/stores/tabs/utils.ts
index 62ee90aad..a1e7bef16 100644
--- a/apps/desktop/src/renderer/stores/tabs/utils.ts
+++ b/apps/desktop/src/renderer/stores/tabs/utils.ts
@@ -1,14 +1,6 @@
import type { MosaicBranch, MosaicNode } from "react-mosaic-component";
-import type { ChangeCategory } from "shared/changes-types";
-import type {
- DiffLayout,
- FileViewerMode,
- FileViewerState,
-} from "shared/tabs-types";
import type { Pane, PaneType, Tab } from "./types";
-const MARKDOWN_EXTENSIONS = [".md", ".markdown", ".mdx"] as const;
-
/**
* Generates a unique ID with the given prefix
*/
@@ -90,66 +82,6 @@ export const createPane = (
};
};
-/**
- * Options for creating a file-viewer pane
- */
-export interface CreateFileViewerPaneOptions {
- filePath: string;
- viewMode?: FileViewerMode;
- isLocked?: boolean;
- diffLayout?: DiffLayout;
- diffCategory?: ChangeCategory;
- commitHash?: string;
- oldPath?: string;
- /** Line to scroll to (raw mode only) */
- line?: number;
- /** Column to scroll to (raw mode only) */
- column?: number;
-}
-
-/**
- * Creates a new file-viewer pane with the given properties
- */
-export const createFileViewerPane = (
- tabId: string,
- options: CreateFileViewerPaneOptions,
-): Pane => {
- const id = generateId("pane");
-
- // Determine default view mode based on file and category
- let defaultViewMode: FileViewerMode = "raw";
- if (options.diffCategory) {
- defaultViewMode = "diff";
- } else if (
- MARKDOWN_EXTENSIONS.some((ext) => options.filePath.endsWith(ext))
- ) {
- defaultViewMode = "rendered";
- }
-
- const fileViewer: FileViewerState = {
- filePath: options.filePath,
- viewMode: options.viewMode ?? defaultViewMode,
- isLocked: options.isLocked ?? false,
- diffLayout: options.diffLayout ?? "inline",
- diffCategory: options.diffCategory,
- commitHash: options.commitHash,
- oldPath: options.oldPath,
- initialLine: options.line,
- initialColumn: options.column,
- };
-
- // Use filename for display name
- const fileName = options.filePath.split("/").pop() || options.filePath;
-
- return {
- id,
- tabId,
- type: "file-viewer",
- name: fileName,
- fileViewer,
- };
-};
-
/**
* Generates a static tab name based on existing tabs
* (e.g., "Terminal 1", "Terminal 2", finding the next available number)
diff --git a/apps/desktop/src/renderer/stores/workspace-init.ts b/apps/desktop/src/renderer/stores/workspace-init.ts
deleted file mode 100644
index b3f4d30f5..000000000
--- a/apps/desktop/src/renderer/stores/workspace-init.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import type { WorkspaceInitProgress } from "shared/types/workspace-init";
-import { create } from "zustand";
-import { devtools } from "zustand/middleware";
-
-/**
- * Data needed to create a terminal when workspace becomes ready.
- * Stored globally so it survives dialog/hook unmounts.
- */
-export interface PendingTerminalSetup {
- workspaceId: string;
- projectId: string;
- initialCommands: string[] | null;
-}
-
-interface WorkspaceInitState {
- // Map of workspaceId -> progress
- initProgress: Record;
-
- // Map of workspaceId -> pending terminal setup (survives dialog unmount)
- pendingTerminalSetups: Record;
-
- // Actions
- updateProgress: (progress: WorkspaceInitProgress) => void;
- clearProgress: (workspaceId: string) => void;
- addPendingTerminalSetup: (setup: PendingTerminalSetup) => void;
- removePendingTerminalSetup: (workspaceId: string) => void;
-}
-
-export const useWorkspaceInitStore = create()(
- devtools(
- (set, get) => ({
- initProgress: {},
- pendingTerminalSetups: {},
-
- updateProgress: (progress) => {
- set((state) => ({
- initProgress: {
- ...state.initProgress,
- [progress.workspaceId]: progress,
- },
- }));
-
- // For memory hygiene, clear "ready" progress after 5 minutes
- // (long enough that WorkspaceInitEffects will have processed it)
- if (progress.step === "ready") {
- setTimeout(
- () => {
- const current = get().initProgress[progress.workspaceId];
- if (current?.step === "ready") {
- get().clearProgress(progress.workspaceId);
- }
- },
- 5 * 60 * 1000,
- ); // 5 minutes
- }
- },
-
- clearProgress: (workspaceId) => {
- set((state) => {
- const { [workspaceId]: _, ...rest } = state.initProgress;
- return { initProgress: rest };
- });
- },
-
- addPendingTerminalSetup: (setup) => {
- set((state) => ({
- pendingTerminalSetups: {
- ...state.pendingTerminalSetups,
- [setup.workspaceId]: setup,
- },
- }));
- },
-
- removePendingTerminalSetup: (workspaceId) => {
- set((state) => {
- const { [workspaceId]: _, ...rest } = state.pendingTerminalSetups;
- return { pendingTerminalSetups: rest };
- });
- },
- }),
- { name: "WorkspaceInitStore" },
- ),
-);
-
-export const useWorkspaceInitProgress = (workspaceId: string) =>
- useWorkspaceInitStore((state) => state.initProgress[workspaceId]);
-
-export const useIsWorkspaceInitializing = (workspaceId: string) =>
- useWorkspaceInitStore((state) => {
- const progress = state.initProgress[workspaceId];
- return (
- progress !== undefined &&
- progress.step !== "ready" &&
- progress.step !== "failed"
- );
- });
-
-export const useHasWorkspaceFailed = (workspaceId: string) =>
- useWorkspaceInitStore((state) => {
- const progress = state.initProgress[workspaceId];
- return progress?.step === "failed";
- });
diff --git a/apps/desktop/src/renderer/stores/workspace-sidebar-state.ts b/apps/desktop/src/renderer/stores/workspace-sidebar-state.ts
deleted file mode 100644
index adb12801e..000000000
--- a/apps/desktop/src/renderer/stores/workspace-sidebar-state.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import { create } from "zustand";
-import { devtools, persist } from "zustand/middleware";
-
-const DEFAULT_WORKSPACE_SIDEBAR_WIDTH = 280;
-export const MIN_WORKSPACE_SIDEBAR_WIDTH = 220;
-export const MAX_WORKSPACE_SIDEBAR_WIDTH = 400;
-
-interface WorkspaceSidebarState {
- isOpen: boolean;
- width: number;
- lastOpenWidth: number;
- // Use string[] instead of Set for JSON serialization with Zustand persist
- collapsedProjectIds: string[];
- isResizing: boolean;
-
- toggleOpen: () => void;
- setOpen: (open: boolean) => void;
- setWidth: (width: number) => void;
- setIsResizing: (isResizing: boolean) => void;
- toggleProjectCollapsed: (projectId: string) => void;
- isProjectCollapsed: (projectId: string) => boolean;
-}
-
-export const useWorkspaceSidebarStore = create()(
- devtools(
- persist(
- (set, get) => ({
- isOpen: true,
- width: DEFAULT_WORKSPACE_SIDEBAR_WIDTH,
- lastOpenWidth: DEFAULT_WORKSPACE_SIDEBAR_WIDTH,
- collapsedProjectIds: [],
- isResizing: false,
-
- toggleOpen: () => {
- const { isOpen, lastOpenWidth } = get();
- if (isOpen) {
- set({ isOpen: false, width: 0 });
- } else {
- set({
- isOpen: true,
- width: lastOpenWidth,
- });
- }
- },
-
- setOpen: (open) => {
- const { lastOpenWidth } = get();
- set({
- isOpen: open,
- width: open ? lastOpenWidth : 0,
- });
- },
-
- setWidth: (width) => {
- const clampedWidth = Math.max(
- MIN_WORKSPACE_SIDEBAR_WIDTH,
- Math.min(MAX_WORKSPACE_SIDEBAR_WIDTH, width),
- );
-
- if (width > 0) {
- set({
- width: clampedWidth,
- lastOpenWidth: clampedWidth,
- isOpen: true,
- });
- } else {
- set({
- width: 0,
- isOpen: false,
- });
- }
- },
-
- setIsResizing: (isResizing) => {
- set({ isResizing });
- },
-
- toggleProjectCollapsed: (projectId) => {
- set((state) => ({
- collapsedProjectIds: state.collapsedProjectIds.includes(projectId)
- ? state.collapsedProjectIds.filter((id) => id !== projectId)
- : [...state.collapsedProjectIds, projectId],
- }));
- },
-
- isProjectCollapsed: (projectId) => {
- return get().collapsedProjectIds.includes(projectId);
- },
- }),
- {
- name: "workspace-sidebar-store",
- version: 1,
- // Exclude ephemeral state from persistence
- partialize: (state) => ({
- isOpen: state.isOpen,
- width: state.width,
- lastOpenWidth: state.lastOpenWidth,
- collapsedProjectIds: state.collapsedProjectIds,
- // isResizing intentionally excluded - ephemeral UI state
- }),
- },
- ),
- { name: "WorkspaceSidebarStore" },
- ),
-);
diff --git a/apps/desktop/src/shared/auth.ts b/apps/desktop/src/shared/auth.ts
deleted file mode 100644
index 2f3348da3..000000000
--- a/apps/desktop/src/shared/auth.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export { AUTH_PROVIDERS, type AuthProvider } from "@superset/shared/constants";
-
-/**
- * Auth session - just tokens, user data fetched separately via tRPC
- */
-export interface AuthSession {
- accessToken: string;
- accessTokenExpiresAt: number;
- refreshToken: string;
- refreshTokenExpiresAt: number;
-}
-
-export interface SignInResult {
- success: boolean;
- error?: string;
-}
diff --git a/apps/desktop/src/shared/constants.ts b/apps/desktop/src/shared/constants.ts
index 1ec904ae1..6bc788cea 100644
--- a/apps/desktop/src/shared/constants.ts
+++ b/apps/desktop/src/shared/constants.ts
@@ -46,4 +46,3 @@ export const NOTIFICATION_EVENTS = {
// Default user preference values
export const DEFAULT_CONFIRM_ON_QUIT = true;
-export const DEFAULT_TERMINAL_LINK_BEHAVIOR = "external-editor" as const;
diff --git a/apps/desktop/src/shared/detect-language.ts b/apps/desktop/src/shared/detect-language.ts
deleted file mode 100644
index 7f305cd2b..000000000
--- a/apps/desktop/src/shared/detect-language.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-export function detectLanguage(filePath: string): string {
- const ext = filePath.split(".").pop()?.toLowerCase();
-
- const languageMap: Record = {
- // JavaScript/TypeScript
- ts: "typescript",
- tsx: "typescript",
- js: "javascript",
- jsx: "javascript",
- mjs: "javascript",
- cjs: "javascript",
-
- // Web
- html: "html",
- htm: "html",
- css: "css",
- scss: "scss",
- less: "less",
-
- // Data formats
- json: "json",
- yaml: "yaml",
- yml: "yaml",
- xml: "xml",
- toml: "toml",
-
- // Markdown/Documentation
- md: "markdown",
- mdx: "markdown",
-
- // Shell
- sh: "shell",
- bash: "shell",
- zsh: "shell",
- fish: "shell",
-
- // Config
- dockerfile: "dockerfile",
- makefile: "makefile",
-
- // Other languages
- py: "python",
- rb: "ruby",
- go: "go",
- rs: "rust",
- java: "java",
- kt: "kotlin",
- swift: "swift",
- c: "c",
- cpp: "cpp",
- h: "c",
- hpp: "cpp",
- cs: "csharp",
- php: "php",
- sql: "sql",
- graphql: "graphql",
- gql: "graphql",
- };
-
- return languageMap[ext || ""] || "plaintext";
-}
diff --git a/apps/desktop/src/shared/hotkeys.ts b/apps/desktop/src/shared/hotkeys.ts
index c889f1127..c4e38007b 100644
--- a/apps/desktop/src/shared/hotkeys.ts
+++ b/apps/desktop/src/shared/hotkeys.ts
@@ -410,25 +410,20 @@ export const HOTKEYS = {
category: "Workspace",
}),
PREV_WORKSPACE: defineHotkey({
- keys: "meta+up",
+ keys: "meta+left",
label: "Previous Workspace",
category: "Workspace",
}),
NEXT_WORKSPACE: defineHotkey({
- keys: "meta+down",
+ keys: "meta+right",
label: "Next Workspace",
category: "Workspace",
}),
// Layout
TOGGLE_SIDEBAR: defineHotkey({
- keys: "meta+l",
- label: "Toggle Changes Tab",
- category: "Layout",
- }),
- TOGGLE_WORKSPACE_SIDEBAR: defineHotkey({
keys: "meta+b",
- label: "Toggle Workspaces Sidebar",
+ label: "Toggle Sidebar",
category: "Layout",
}),
SPLIT_RIGHT: defineHotkey({
@@ -449,12 +444,6 @@ export const HOTKEYS = {
category: "Layout",
description: "Split the current pane along its longer side",
}),
- CLOSE_PANE: defineHotkey({
- keys: "meta+w",
- label: "Close Pane",
- category: "Layout",
- description: "Close the current pane",
- }),
// Terminal
FIND_IN_TERMINAL: defineHotkey({
@@ -463,9 +452,9 @@ export const HOTKEYS = {
category: "Terminal",
description: "Search text in the active terminal",
}),
- NEW_GROUP: defineHotkey({
+ NEW_TERMINAL: defineHotkey({
keys: "meta+t",
- label: "New Tab",
+ label: "New Terminal",
category: "Terminal",
}),
CLOSE_TERMINAL: defineHotkey({
@@ -479,12 +468,12 @@ export const HOTKEYS = {
category: "Terminal",
}),
PREV_TERMINAL: defineHotkey({
- keys: "meta+left",
+ keys: "meta+up",
label: "Previous Terminal",
category: "Terminal",
}),
NEXT_TERMINAL: defineHotkey({
- keys: "meta+right",
+ keys: "meta+down",
label: "Next Terminal",
category: "Terminal",
}),
@@ -586,15 +575,6 @@ export function getDefaultHotkey(
return HOTKEYS[id].defaults[platform];
}
-/**
- * Get the hotkey binding for the current platform.
- * Convenience wrapper around getDefaultHotkey.
- * Returns empty string if no hotkey is defined (safe for useHotkeys).
- */
-export function getHotkey(id: HotkeyId): string {
- return getDefaultHotkey(id, getCurrentPlatform()) ?? "";
-}
-
export function getEffectiveHotkey(
id: HotkeyId,
overrides: Partial>,
diff --git a/apps/desktop/src/shared/tabs-types.ts b/apps/desktop/src/shared/tabs-types.ts
index d8c921186..8ae323601 100644
--- a/apps/desktop/src/shared/tabs-types.ts
+++ b/apps/desktop/src/shared/tabs-types.ts
@@ -3,46 +3,10 @@
* Renderer extends these with MosaicNode layout specifics.
*/
-import type { ChangeCategory } from "./changes-types";
-
/**
* Pane types that can be displayed within a tab
*/
-export type PaneType = "terminal" | "webview" | "file-viewer";
-
-/**
- * File viewer display modes
- */
-export type FileViewerMode = "rendered" | "raw" | "diff";
-
-/**
- * Diff layout options for file viewer
- */
-export type DiffLayout = "inline" | "side-by-side";
-
-/**
- * File viewer pane-specific properties
- */
-export interface FileViewerState {
- /** Worktree-relative file path */
- filePath: string;
- /** Display mode: rendered (markdown), raw (source), or diff */
- viewMode: FileViewerMode;
- /** If true, this pane won't be reused for new file clicks */
- isLocked: boolean;
- /** Diff display layout */
- diffLayout: DiffLayout;
- /** Category for diff source (against-main, committed, staged, unstaged) */
- diffCategory?: ChangeCategory;
- /** Commit hash for committed category diffs */
- commitHash?: string;
- /** Original path for renamed files */
- oldPath?: string;
- /** Initial line to scroll to (raw mode only, transient - applied once) */
- initialLine?: number;
- /** Initial column to scroll to (raw mode only, transient - applied once) */
- initialColumn?: number;
-}
+export type PaneType = "terminal" | "webview";
/**
* Base Pane interface - shared between main and renderer
@@ -59,7 +23,6 @@ export interface Pane {
url?: string; // For webview panes
cwd?: string | null; // Current working directory
cwdConfirmed?: boolean; // True if cwd confirmed via OSC-7, false if seeded
- fileViewer?: FileViewerState; // For file-viewer panes
}
/**
diff --git a/apps/desktop/src/shared/types/index.ts b/apps/desktop/src/shared/types/index.ts
index 72711f77a..a47714c62 100644
--- a/apps/desktop/src/shared/types/index.ts
+++ b/apps/desktop/src/shared/types/index.ts
@@ -5,5 +5,4 @@ export * from "./mosaic";
export * from "./ports";
export * from "./tab";
export * from "./workspace";
-export * from "./workspace-init";
export * from "./worktree";
diff --git a/apps/desktop/src/shared/types/workspace-init.ts b/apps/desktop/src/shared/types/workspace-init.ts
deleted file mode 100644
index b19d22a42..000000000
--- a/apps/desktop/src/shared/types/workspace-init.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Workspace initialization progress types.
- * Used for streaming progress updates during workspace creation.
- */
-
-export type WorkspaceInitStep =
- | "pending"
- | "syncing" // Syncing with remote
- | "verifying" // Verifying base branch exists
- | "fetching" // Fetching latest changes
- | "creating_worktree" // Creating git worktree
- | "copying_config" // Copying .superset configuration
- | "finalizing" // Final DB operations
- | "ready"
- | "failed";
-
-export interface WorkspaceInitProgress {
- workspaceId: string;
- projectId: string;
- step: WorkspaceInitStep;
- message: string;
- error?: string;
-}
-
-export const INIT_STEP_MESSAGES: Record = {
- pending: "Preparing...",
- syncing: "Syncing with remote...",
- verifying: "Verifying base branch...",
- fetching: "Fetching latest changes...",
- creating_worktree: "Creating git worktree...",
- copying_config: "Copying configuration...",
- finalizing: "Finalizing setup...",
- ready: "Ready",
- failed: "Failed",
-};
-
-/**
- * Order of steps for UI progress display.
- * Used to show completed/current/pending steps in the progress view.
- */
-export const INIT_STEP_ORDER: WorkspaceInitStep[] = [
- "pending",
- "syncing",
- "verifying",
- "fetching",
- "creating_worktree",
- "copying_config",
- "finalizing",
- "ready",
-];
-
-/**
- * Get the index of a step in the progress order.
- * Returns -1 for "failed" since it's not part of the normal flow.
- */
-export function getStepIndex(step: WorkspaceInitStep): number {
- if (step === "failed") return -1;
- return INIT_STEP_ORDER.indexOf(step);
-}
-
-/**
- * Check if a step is complete based on the current step.
- */
-export function isStepComplete(
- step: WorkspaceInitStep,
- currentStep: WorkspaceInitStep,
-): boolean {
- if (currentStep === "failed") return false;
- const stepIndex = getStepIndex(step);
- const currentIndex = getStepIndex(currentStep);
- return stepIndex < currentIndex;
-}
diff --git a/apps/desktop/test-setup.ts b/apps/desktop/test-setup.ts
index 2bf5535b0..b14e1c4af 100644
--- a/apps/desktop/test-setup.ts
+++ b/apps/desktop/test-setup.ts
@@ -118,14 +118,7 @@ mock.module("electron", () => ({
screen: {
getPrimaryDisplay: mock(() => ({
workAreaSize: { width: 1920, height: 1080 },
- bounds: { x: 0, y: 0, width: 1920, height: 1080 },
})),
- getAllDisplays: mock(() => [
- {
- bounds: { x: 0, y: 0, width: 1920, height: 1080 },
- workAreaSize: { width: 1920, height: 1080 },
- },
- ]),
},
Notification: mock(() => ({
show: mock(),
diff --git a/apps/marketing/package.json b/apps/marketing/package.json
index 52fab968e..af17cd237 100644
--- a/apps/marketing/package.json
+++ b/apps/marketing/package.json
@@ -11,10 +11,10 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
- "@clerk/nextjs": "^6.36.2",
"@react-three/drei": "^10.7.6",
"@react-three/fiber": "^9.4.0",
"@sentry/nextjs": "^10.32.1",
+ "@superset/auth": "workspace:*",
"@superset/shared": "workspace:*",
"@superset/ui": "workspace:*",
"@t3-oss/env-nextjs": "^0.13.8",
diff --git a/apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx b/apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx
index 53f41fa7d..2c0c76855 100644
--- a/apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx
+++ b/apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx
@@ -1,13 +1,14 @@
-import { auth } from "@clerk/nextjs/server";
+import { auth } from "@superset/auth";
import { DOWNLOAD_URL_MAC_ARM64 } from "@superset/shared/constants";
import { Download } from "lucide-react";
+import { headers } from "next/headers";
import { env } from "@/env";
export async function CTAButtons() {
- const { userId } = await auth();
+ const session = await auth.api.getSession({ headers: await headers() });
- if (userId) {
+ if (session) {
return (
<>
) {
return (
-
-
-
-
-
-
-
- } />
- {children}
-
-
-
-
-
-
+
+
+
+
+
+
+ } />
+ {children}
+
+
+
+
+
);
}
diff --git a/apps/marketing/src/env.ts b/apps/marketing/src/env.ts
index a8fc0d027..f1312f39e 100644
--- a/apps/marketing/src/env.ts
+++ b/apps/marketing/src/env.ts
@@ -10,14 +10,11 @@ export const env = createEnv({
.default("development"),
},
server: {
- CLERK_SECRET_KEY: z.string(),
SENTRY_AUTH_TOKEN: z.string().optional(),
},
client: {
NEXT_PUBLIC_API_URL: z.string().url(),
NEXT_PUBLIC_WEB_URL: z.string().url(),
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string(),
- NEXT_PUBLIC_COOKIE_DOMAIN: z.string(),
NEXT_PUBLIC_POSTHOG_KEY: z.string(),
NEXT_PUBLIC_POSTHOG_HOST: z.string().url(),
NEXT_PUBLIC_SENTRY_DSN_MARKETING: z.string().optional(),
@@ -29,9 +26,6 @@ export const env = createEnv({
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
NEXT_PUBLIC_WEB_URL: process.env.NEXT_PUBLIC_WEB_URL,
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
- process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
- NEXT_PUBLIC_COOKIE_DOMAIN: process.env.NEXT_PUBLIC_COOKIE_DOMAIN,
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
NEXT_PUBLIC_SENTRY_DSN_MARKETING:
diff --git a/apps/marketing/src/proxy.ts b/apps/marketing/src/proxy.ts
deleted file mode 100644
index 29446eb2b..000000000
--- a/apps/marketing/src/proxy.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { clerkMiddleware } from "@clerk/nextjs/server";
-
-export default clerkMiddleware();
-
-export const config = {
- matcher: [
- "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
- "/(api|trpc)(.*)",
- ],
-};
diff --git a/apps/web/package.json b/apps/web/package.json
index ee74c1742..b95e05f91 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -11,8 +11,8 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
- "@clerk/nextjs": "^6.36.2",
"@sentry/nextjs": "^10.32.1",
+ "@superset/auth": "workspace:*",
"@superset/db": "workspace:*",
"@superset/shared": "workspace:*",
"@superset/trpc": "workspace:*",
@@ -24,6 +24,7 @@
"@trpc/server": "^11.7.1",
"@trpc/tanstack-react-query": "^11.7.1",
"@uiw/react-md-editor": "^4.0.11",
+ "better-auth": "^1.4.9",
"framer-motion": "^12.23.26",
"geist": "^1.5.1",
"import-in-the-middle": "2.0.1",
diff --git a/apps/web/src/app/(auth)/layout.tsx b/apps/web/src/app/(auth)/layout.tsx
index b5903f597..d07d16eb0 100644
--- a/apps/web/src/app/(auth)/layout.tsx
+++ b/apps/web/src/app/(auth)/layout.tsx
@@ -1,4 +1,5 @@
-import { auth } from "@clerk/nextjs/server";
+import { auth } from "@superset/auth";
+import { headers } from "next/headers";
import Image from "next/image";
import { redirect } from "next/navigation";
@@ -9,10 +10,11 @@ export default async function AuthLayout({
}: {
children: React.ReactNode;
}) {
- const { userId } = await auth();
+ const session = await auth.api.getSession({
+ headers: await headers(),
+ });
- // Redirect authenticated users to home
- if (userId) {
+ if (session) {
redirect("/");
}
diff --git a/apps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx b/apps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx
index 4e0c9c51b..c05643f6a 100644
--- a/apps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx
+++ b/apps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx
@@ -1,56 +1,46 @@
"use client";
-import { useSignIn } from "@clerk/nextjs";
+import { authClient } from "@superset/auth/client";
import { Button } from "@superset/ui/button";
import Link from "next/link";
import { useState } from "react";
import { FaGithub } from "react-icons/fa";
import { FcGoogle } from "react-icons/fc";
-
import { env } from "@/env";
export default function SignInPage() {
- const { signIn, isLoaded } = useSignIn();
const [isLoadingGoogle, setIsLoadingGoogle] = useState(false);
const [isLoadingGithub, setIsLoadingGithub] = useState(false);
const [error, setError] = useState(null);
const signInWithGoogle = async () => {
- if (!isLoaded) return;
-
setIsLoadingGoogle(true);
setError(null);
try {
- await signIn.authenticateWithRedirect({
- strategy: "oauth_google",
- redirectUrl: "/sso-callback",
- redirectUrlComplete: "/",
+ await authClient.signIn.social({
+ provider: "google",
+ callbackURL: env.NEXT_PUBLIC_WEB_URL,
});
} catch (err) {
console.error("Sign in failed:", err);
setError("Failed to sign in. Please try again.");
- } finally {
setIsLoadingGoogle(false);
}
};
const signInWithGithub = async () => {
- if (!isLoaded) return;
-
setIsLoadingGithub(true);
setError(null);
try {
- await signIn.authenticateWithRedirect({
- strategy: "oauth_github",
- redirectUrl: "/sso-callback",
- redirectUrlComplete: "/",
+ await authClient.signIn.social({
+ provider: "github",
+ callbackURL: env.NEXT_PUBLIC_WEB_URL,
});
} catch (err) {
console.error("Sign in failed:", err);
setError("Failed to sign in. Please try again.");
- } finally {
setIsLoadingGithub(false);
}
};
@@ -71,7 +61,7 @@ export default function SignInPage() {
)}
@@ -80,7 +70,7 @@ export default function SignInPage() {
diff --git a/apps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx b/apps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx
index 35b9fdeb7..dd9b579cd 100644
--- a/apps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx
+++ b/apps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx
@@ -1,56 +1,46 @@
"use client";
-import { useSignUp } from "@clerk/nextjs";
+import { authClient } from "@superset/auth/client";
import { Button } from "@superset/ui/button";
import Link from "next/link";
import { useState } from "react";
import { FaGithub } from "react-icons/fa";
import { FcGoogle } from "react-icons/fc";
-
import { env } from "@/env";
export default function SignUpPage() {
- const { signUp, isLoaded } = useSignUp();
const [isLoadingGoogle, setIsLoadingGoogle] = useState(false);
const [isLoadingGithub, setIsLoadingGithub] = useState(false);
const [error, setError] = useState(null);
const signUpWithGoogle = async () => {
- if (!isLoaded) return;
-
setIsLoadingGoogle(true);
setError(null);
try {
- await signUp.authenticateWithRedirect({
- strategy: "oauth_google",
- redirectUrl: "/sso-callback",
- redirectUrlComplete: "/",
+ await authClient.signIn.social({
+ provider: "google",
+ callbackURL: env.NEXT_PUBLIC_WEB_URL,
});
} catch (err) {
console.error("Sign up failed:", err);
setError("Failed to sign up. Please try again.");
- } finally {
setIsLoadingGoogle(false);
}
};
const signUpWithGithub = async () => {
- if (!isLoaded) return;
-
setIsLoadingGithub(true);
setError(null);
try {
- await signUp.authenticateWithRedirect({
- strategy: "oauth_github",
- redirectUrl: "/sso-callback",
- redirectUrlComplete: "/",
+ await authClient.signIn.social({
+ provider: "github",
+ callbackURL: env.NEXT_PUBLIC_WEB_URL,
});
} catch (err) {
console.error("Sign up failed:", err);
setError("Failed to sign up. Please try again.");
- } finally {
setIsLoadingGithub(false);
}
};
@@ -73,7 +63,7 @@ export default function SignUpPage() {
)}
@@ -82,7 +72,7 @@ export default function SignUpPage() {
diff --git a/apps/web/src/app/(auth)/sso-callback/page.tsx b/apps/web/src/app/(auth)/sso-callback/page.tsx
deleted file mode 100644
index 033b8ecc8..000000000
--- a/apps/web/src/app/(auth)/sso-callback/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { AuthenticateWithRedirectCallback } from "@clerk/nextjs";
-
-export default function SSOCallbackPage() {
- return ;
-}
diff --git a/apps/web/src/app/(dashboard)/components/Header/Header.tsx b/apps/web/src/app/(dashboard)/components/Header/Header.tsx
index 47dd869a3..df03b021a 100644
--- a/apps/web/src/app/(dashboard)/components/Header/Header.tsx
+++ b/apps/web/src/app/(dashboard)/components/Header/Header.tsx
@@ -1,6 +1,6 @@
"use client";
-import { SignOutButton, useUser } from "@clerk/nextjs";
+import { authClient } from "@superset/auth/client";
import { getInitials } from "@superset/shared/names";
import { Avatar, AvatarFallback, AvatarImage } from "@superset/ui/avatar";
import {
@@ -12,14 +12,19 @@ import {
import { LogOut } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
+import { useRouter } from "next/navigation";
export function Header() {
- const { user } = useUser();
+ const { data: session } = authClient.useSession();
+ const router = useRouter();
- const initials = getInitials(
- user?.fullName,
- user?.primaryEmailAddress?.emailAddress,
- );
+ const user = session?.user;
+ const initials = getInitials(user?.name, user?.email);
+
+ const handleSignOut = async () => {
+ await authClient.signOut();
+ router.push("/sign-in");
+ };
return (
@@ -40,18 +45,22 @@ export function Header() {
className="cursor-pointer rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
-
+
{initials}
-
-
-
- Logout
-
-
+
+
+ Logout
+
diff --git a/apps/web/src/app/(dashboard)/layout.tsx b/apps/web/src/app/(dashboard)/layout.tsx
index a20ca12c3..2ec1eaeb8 100644
--- a/apps/web/src/app/(dashboard)/layout.tsx
+++ b/apps/web/src/app/(dashboard)/layout.tsx
@@ -1,3 +1,7 @@
+import { auth } from "@superset/auth";
+import { headers } from "next/headers";
+import { redirect } from "next/navigation";
+
import { api } from "@/trpc/server";
import { Footer } from "./components/Footer";
import { Header } from "./components/Header";
@@ -8,6 +12,14 @@ export default async function DashboardLayout({
}: {
children: React.ReactNode;
}) {
+ const session = await auth.api.getSession({
+ headers: await headers(),
+ });
+
+ if (!session) {
+ redirect("/sign-in");
+ }
+
const trpc = await api();
const organization = await trpc.user.myOrganization.query();
const displayName = organization?.name ?? "Superset";
diff --git a/apps/web/src/app/api/auth/desktop/github/route.ts b/apps/web/src/app/api/auth/desktop/github/route.ts
deleted file mode 100644
index 0cdc4819c..000000000
--- a/apps/web/src/app/api/auth/desktop/github/route.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import { redirect } from "next/navigation";
-import { env } from "@/env";
-
-export async function GET(request: Request) {
- const url = new URL(request.url);
- const code = url.searchParams.get("code");
- const state = url.searchParams.get("state");
- const error = url.searchParams.get("error");
- const errorDescription = url.searchParams.get("error_description");
-
- if (error) {
- const errorUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- errorUrl.searchParams.set("error", errorDescription || error);
- redirect(errorUrl.toString());
- }
-
- if (!code || !state) {
- const errorUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- errorUrl.searchParams.set("error", "Missing authentication parameters");
- redirect(errorUrl.toString());
- }
-
- let tokenData: {
- accessToken: string;
- accessTokenExpiresAt: number;
- refreshToken: string;
- refreshTokenExpiresAt: number;
- } | null = null;
- let exchangeError: string | null = null;
-
- try {
- const response = await fetch(
- `${env.NEXT_PUBLIC_API_URL}/api/auth/desktop/github`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- code,
- redirectUri: `${env.NEXT_PUBLIC_WEB_URL}/api/auth/desktop/github`,
- }),
- },
- );
-
- if (!response.ok) {
- const errorData = await response.json().catch(() => ({}));
- exchangeError = errorData.error || "Failed to complete sign in";
- } else {
- tokenData = (await response.json()) as {
- accessToken: string;
- accessTokenExpiresAt: number;
- refreshToken: string;
- refreshTokenExpiresAt: number;
- };
- }
- } catch (err) {
- console.error("[api/auth/desktop/github] Error:", err);
- exchangeError = "An unexpected error occurred";
- }
-
- if (exchangeError || !tokenData) {
- const errorUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- errorUrl.searchParams.set("error", exchangeError || "Failed to sign in");
- redirect(errorUrl.toString());
- }
-
- const successUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- successUrl.searchParams.set("accessToken", tokenData.accessToken);
- successUrl.searchParams.set(
- "accessTokenExpiresAt",
- tokenData.accessTokenExpiresAt.toString(),
- );
- successUrl.searchParams.set("refreshToken", tokenData.refreshToken);
- successUrl.searchParams.set(
- "refreshTokenExpiresAt",
- tokenData.refreshTokenExpiresAt.toString(),
- );
- successUrl.searchParams.set("state", state);
- redirect(successUrl.toString());
-}
diff --git a/apps/web/src/app/api/auth/desktop/google/route.ts b/apps/web/src/app/api/auth/desktop/google/route.ts
deleted file mode 100644
index affa5d6d8..000000000
--- a/apps/web/src/app/api/auth/desktop/google/route.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import { redirect } from "next/navigation";
-import { env } from "@/env";
-
-export async function GET(request: Request) {
- const url = new URL(request.url);
- const code = url.searchParams.get("code");
- const state = url.searchParams.get("state");
- const error = url.searchParams.get("error");
- const errorDescription = url.searchParams.get("error_description");
-
- if (error) {
- const errorUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- errorUrl.searchParams.set("error", errorDescription || error);
- redirect(errorUrl.toString());
- }
-
- if (!code || !state) {
- const errorUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- errorUrl.searchParams.set("error", "Missing authentication parameters");
- redirect(errorUrl.toString());
- }
-
- let tokenData: {
- accessToken: string;
- accessTokenExpiresAt: number;
- refreshToken: string;
- refreshTokenExpiresAt: number;
- } | null = null;
- let exchangeError: string | null = null;
-
- try {
- const response = await fetch(
- `${env.NEXT_PUBLIC_API_URL}/api/auth/desktop/google`,
- {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- code,
- redirectUri: `${env.NEXT_PUBLIC_WEB_URL}/api/auth/desktop/google`,
- }),
- },
- );
-
- if (!response.ok) {
- const errorData = await response.json().catch(() => ({}));
- exchangeError = errorData.error || "Failed to complete sign in";
- } else {
- tokenData = (await response.json()) as {
- accessToken: string;
- accessTokenExpiresAt: number;
- refreshToken: string;
- refreshTokenExpiresAt: number;
- };
- }
- } catch (err) {
- console.error("[api/auth/desktop/google] Error:", err);
- exchangeError = "An unexpected error occurred";
- }
-
- if (exchangeError || !tokenData) {
- const errorUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- errorUrl.searchParams.set("error", exchangeError || "Failed to sign in");
- redirect(errorUrl.toString());
- }
-
- const successUrl = new URL("/auth/desktop/success", env.NEXT_PUBLIC_WEB_URL);
- successUrl.searchParams.set("accessToken", tokenData.accessToken);
- successUrl.searchParams.set(
- "accessTokenExpiresAt",
- tokenData.accessTokenExpiresAt.toString(),
- );
- successUrl.searchParams.set("refreshToken", tokenData.refreshToken);
- successUrl.searchParams.set(
- "refreshTokenExpiresAt",
- tokenData.refreshTokenExpiresAt.toString(),
- );
- successUrl.searchParams.set("state", state);
- redirect(successUrl.toString());
-}
diff --git a/apps/web/src/app/auth/desktop/success/components/DesktopAuthSuccess/DesktopAuthSuccess.tsx b/apps/web/src/app/auth/desktop/success/components/DesktopAuthSuccess/DesktopAuthSuccess.tsx
deleted file mode 100644
index 8e84163d1..000000000
--- a/apps/web/src/app/auth/desktop/success/components/DesktopAuthSuccess/DesktopAuthSuccess.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-"use client";
-
-import Image from "next/image";
-import Link from "next/link";
-import { useSearchParams } from "next/navigation";
-import { useCallback, useEffect, useState } from "react";
-
-const DESKTOP_PROTOCOL =
- process.env.NODE_ENV === "development" ? "superset-dev" : "superset";
-
-export function DesktopAuthSuccess() {
- const searchParams = useSearchParams();
- const accessToken = searchParams.get("accessToken");
- const accessTokenExpiresAt = searchParams.get("accessTokenExpiresAt");
- const refreshToken = searchParams.get("refreshToken");
- const refreshTokenExpiresAt = searchParams.get("refreshTokenExpiresAt");
- const state = searchParams.get("state");
- const error = searchParams.get("error");
-
- const [hasAttempted, setHasAttempted] = useState(false);
-
- const hasAllTokens =
- accessToken &&
- accessTokenExpiresAt &&
- refreshToken &&
- refreshTokenExpiresAt &&
- state;
-
- const desktopUrl = hasAllTokens
- ? `${DESKTOP_PROTOCOL}://auth/callback?accessToken=${encodeURIComponent(accessToken)}&accessTokenExpiresAt=${encodeURIComponent(accessTokenExpiresAt)}&refreshToken=${encodeURIComponent(refreshToken)}&refreshTokenExpiresAt=${encodeURIComponent(refreshTokenExpiresAt)}&state=${encodeURIComponent(state)}`
- : null;
-
- const openDesktopApp = useCallback(() => {
- if (!desktopUrl) return;
- window.location.href = desktopUrl;
- }, [desktopUrl]);
-
- useEffect(() => {
- if (error || !desktopUrl || hasAttempted) return;
- setHasAttempted(true);
- openDesktopApp();
- }, [error, desktopUrl, hasAttempted, openDesktopApp]);
-
- if (error) {
- return (
-
-
-
Authentication failed
-
{error}
-
- );
- }
-
- if (!hasAllTokens) {
- return (
-
-
-
Invalid request
-
- Missing authentication parameters. Please try again.
-
-
- );
- }
-
- return (
-
-
-
- Redirecting to the desktop app...
-
-
- {desktopUrl && (
-
- If you weren't redirected, click here.
-
- )}
-
-
- );
-}
diff --git a/apps/web/src/app/auth/desktop/success/components/DesktopAuthSuccess/index.ts b/apps/web/src/app/auth/desktop/success/components/DesktopAuthSuccess/index.ts
deleted file mode 100644
index 94e4dc63f..000000000
--- a/apps/web/src/app/auth/desktop/success/components/DesktopAuthSuccess/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { DesktopAuthSuccess } from "./DesktopAuthSuccess";
diff --git a/apps/web/src/app/auth/desktop/success/components/DesktopRedirect/DesktopRedirect.tsx b/apps/web/src/app/auth/desktop/success/components/DesktopRedirect/DesktopRedirect.tsx
new file mode 100644
index 000000000..678b3ae48
--- /dev/null
+++ b/apps/web/src/app/auth/desktop/success/components/DesktopRedirect/DesktopRedirect.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import Image from "next/image";
+import Link from "next/link";
+import { useEffect } from "react";
+
+export function DesktopRedirect({ url }: { url: string }) {
+ useEffect(() => {
+ window.location.href = url;
+ }, [url]);
+
+ return (
+
+
+
+ Redirecting to desktop app...
+
+
+ Click here if not redirected
+
+
+ );
+}
diff --git a/apps/web/src/app/auth/desktop/success/components/DesktopRedirect/index.ts b/apps/web/src/app/auth/desktop/success/components/DesktopRedirect/index.ts
new file mode 100644
index 000000000..9f8d53871
--- /dev/null
+++ b/apps/web/src/app/auth/desktop/success/components/DesktopRedirect/index.ts
@@ -0,0 +1 @@
+export { DesktopRedirect } from "./DesktopRedirect";
diff --git a/apps/web/src/app/auth/desktop/success/components/LoadingFallback/LoadingFallback.tsx b/apps/web/src/app/auth/desktop/success/components/LoadingFallback/LoadingFallback.tsx
deleted file mode 100644
index b99538a47..000000000
--- a/apps/web/src/app/auth/desktop/success/components/LoadingFallback/LoadingFallback.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import Image from "next/image";
-
-export function LoadingFallback() {
- return (
-
- );
-}
diff --git a/apps/web/src/app/auth/desktop/success/components/LoadingFallback/index.ts b/apps/web/src/app/auth/desktop/success/components/LoadingFallback/index.ts
deleted file mode 100644
index ac26b6d3b..000000000
--- a/apps/web/src/app/auth/desktop/success/components/LoadingFallback/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { LoadingFallback } from "./LoadingFallback";
diff --git a/apps/web/src/app/auth/desktop/success/page.tsx b/apps/web/src/app/auth/desktop/success/page.tsx
index 595722bf5..7f0780c81 100644
--- a/apps/web/src/app/auth/desktop/success/page.tsx
+++ b/apps/web/src/app/auth/desktop/success/page.tsx
@@ -1,16 +1,89 @@
-"use client";
+import { auth } from "@superset/auth";
+import { db } from "@superset/db/client";
+import { sessions } from "@superset/db/schema/auth";
+import { headers } from "next/headers";
-import { Suspense } from "react";
+import { DesktopRedirect } from "./components/DesktopRedirect";
-import { DesktopAuthSuccess } from "./components/DesktopAuthSuccess";
-import { LoadingFallback } from "./components/LoadingFallback";
+export default async function DesktopSuccessPage({
+ searchParams,
+}: {
+ searchParams: Promise<{ desktop_state?: string }>;
+}) {
+ const { desktop_state: state } = await searchParams;
+
+ if (!state) {
+ return (
+
+
Missing auth state
+
+ Please try signing in again from the desktop app.
+
+
+ );
+ }
+
+ // Get session from Better Auth
+ let session: Awaited> | null = null;
+ try {
+ session = await auth.api.getSession({ headers: await headers() });
+ } catch (error) {
+ console.error("Failed to get session for desktop auth:", error);
+ return (
+
+
Authentication failed
+
+ Please try signing in again from the desktop app.
+
+
+ );
+ }
+
+ if (!session) {
+ return (
+
+
Authentication failed
+
+ Please try signing in again from the desktop app.
+
+
+ );
+ }
+
+ // Create a separate session for the desktop app instead of reusing the browser session
+ // This ensures desktop and web have independent sessions with separate activeOrganizationId
+ const headersObj = await headers();
+ const userAgent = headersObj.get("user-agent") || "Superset Desktop App";
+ const ipAddress =
+ headersObj.get("x-forwarded-for")?.split(",")[0] ||
+ headersObj.get("x-real-ip") ||
+ undefined;
+
+ // Generate a unique session token for the desktop app
+ const crypto = await import("node:crypto");
+ const token = crypto.randomBytes(32).toString("base64url");
+ const now = new Date();
+ const expiresAt = new Date(
+ Date.now() + 60 * 60 * 24 * 30 * 1000, // 30 days (matching auth config)
+ );
+
+ // Create a new session record in the database
+ await db.insert(sessions).values({
+ token,
+ userId: session.user.id,
+ expiresAt,
+ ipAddress,
+ userAgent,
+ activeOrganizationId: session.session.activeOrganizationId,
+ updatedAt: now,
+ });
+ const protocol =
+ process.env.NODE_ENV === "development" ? "superset-dev" : "superset";
+ const desktopUrl = `${protocol}://auth/callback?token=${encodeURIComponent(token)}&expiresAt=${encodeURIComponent(expiresAt.toISOString())}&state=${encodeURIComponent(state)}`;
-export default function Page() {
return (
- }>
-
-
+
);
}
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 4bbd4d7ec..48b154dfd 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -1,11 +1,8 @@
-import { ClerkProvider } from "@clerk/nextjs";
import { Toaster } from "@superset/ui/sonner";
import { cn } from "@superset/ui/utils";
import type { Metadata, Viewport } from "next";
import { IBM_Plex_Mono, Inter } from "next/font/google";
-import { env } from "@/env";
-
import "./globals.css";
import { Providers } from "./providers";
@@ -40,28 +37,19 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
-
-
-
-
- {children}
-
-
-
-
-
+
+
+
+ {children}
+
+
+
+
);
}
diff --git a/apps/web/src/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx b/apps/web/src/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
index 68f00c993..ef0e3ba87 100644
--- a/apps/web/src/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
+++ b/apps/web/src/components/PostHogUserIdentifier/PostHogUserIdentifier.tsx
@@ -1,27 +1,22 @@
"use client";
-import { useUser } from "@clerk/nextjs";
-import { useQuery } from "@tanstack/react-query";
+import { authClient } from "@superset/auth/client";
import posthog from "posthog-js";
import { useEffect } from "react";
-import { useTRPC } from "../../trpc/react";
export function PostHogUserIdentifier() {
- const { isSignedIn } = useUser();
- const trpc = useTRPC();
-
- const { data: user } = useQuery({
- ...trpc.user.me.queryOptions(),
- enabled: isSignedIn,
- });
+ const { data: session } = authClient.useSession();
useEffect(() => {
- if (user) {
- posthog.identify(user.id, { email: user.email, name: user.name });
- } else if (isSignedIn === false) {
+ if (session?.user) {
+ posthog.identify(session.user.id, {
+ email: session.user.email,
+ name: session.user.name,
+ });
+ } else if (session === null) {
posthog.reset();
}
- }, [user, isSignedIn]);
+ }, [session]);
return null;
}
diff --git a/apps/web/src/env.ts b/apps/web/src/env.ts
index f82811e94..25a96d455 100644
--- a/apps/web/src/env.ts
+++ b/apps/web/src/env.ts
@@ -13,8 +13,6 @@ export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
DATABASE_URL_UNPOOLED: z.string().url(),
- CLERK_SECRET_KEY: z.string(),
- DESKTOP_AUTH_SECRET: z.string().min(32),
SENTRY_AUTH_TOKEN: z.string().optional(),
},
@@ -23,8 +21,6 @@ export const env = createEnv({
NEXT_PUBLIC_WEB_URL: z.string().url(),
NEXT_PUBLIC_MARKETING_URL: z.string().url(),
NEXT_PUBLIC_DOCS_URL: z.string().url(),
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string(),
- NEXT_PUBLIC_COOKIE_DOMAIN: z.string(),
NEXT_PUBLIC_POSTHOG_KEY: z.string(),
NEXT_PUBLIC_POSTHOG_HOST: z.string().url(),
NEXT_PUBLIC_SENTRY_DSN_WEB: z.string().optional(),
@@ -39,9 +35,6 @@ export const env = createEnv({
NEXT_PUBLIC_WEB_URL: process.env.NEXT_PUBLIC_WEB_URL,
NEXT_PUBLIC_MARKETING_URL: process.env.NEXT_PUBLIC_MARKETING_URL,
NEXT_PUBLIC_DOCS_URL: process.env.NEXT_PUBLIC_DOCS_URL,
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
- process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
- NEXT_PUBLIC_COOKIE_DOMAIN: process.env.NEXT_PUBLIC_COOKIE_DOMAIN,
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
NEXT_PUBLIC_SENTRY_DSN_WEB: process.env.NEXT_PUBLIC_SENTRY_DSN_WEB,
diff --git a/apps/web/src/proxy.ts b/apps/web/src/proxy.ts
index e8965f1fd..3f4158f9c 100644
--- a/apps/web/src/proxy.ts
+++ b/apps/web/src/proxy.ts
@@ -1,39 +1,42 @@
-import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
-import { NextResponse } from "next/server";
-
-const isPublicRoute = createRouteMatcher([
- "/sign-in(.*)",
- "/sign-up(.*)",
- "/sso-callback(.*)",
- "/auth/desktop(.*)",
- "/api/auth/desktop(.*)",
- "/ingest(.*)",
- "/monitoring(.*)",
-]);
-
-export default clerkMiddleware(async (auth, req) => {
- const { userId } = await auth();
-
- // Redirect authenticated users away from auth pages
+import { auth } from "@superset/auth";
+import { headers } from "next/headers";
+import { type NextRequest, NextResponse } from "next/server";
+
+const publicRoutes = [
+ "/sign-in",
+ "/sign-up",
+ "/auth/desktop",
+ "/api/auth/desktop",
+];
+
+function isPublicRoute(pathname: string): boolean {
+ return publicRoutes.some((route) => pathname.startsWith(route));
+}
+
+export default async function proxy(req: NextRequest) {
+ const session = await auth.api.getSession({
+ headers: await headers(),
+ });
+
+ const pathname = req.nextUrl.pathname;
+
if (
- userId &&
- (req.nextUrl.pathname.startsWith("/sign-in") ||
- req.nextUrl.pathname.startsWith("/sign-up"))
+ session &&
+ (pathname.startsWith("/sign-in") || pathname.startsWith("/sign-up"))
) {
return NextResponse.redirect(new URL("/", req.url));
}
- // Redirect unauthenticated users to sign-in
- if (!userId && !isPublicRoute(req)) {
+ if (!session && !isPublicRoute(pathname)) {
return NextResponse.redirect(new URL("/sign-in", req.url));
}
return NextResponse.next();
-});
+}
export const config = {
matcher: [
- "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
+ "/((?!_next|ingest|monitoring|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
"/(api|trpc)(.*)",
],
};
diff --git a/apps/web/src/trpc/react.tsx b/apps/web/src/trpc/react.tsx
index 95db3b924..78f7c07f9 100644
--- a/apps/web/src/trpc/react.tsx
+++ b/apps/web/src/trpc/react.tsx
@@ -1,6 +1,5 @@
"use client";
-import { useAuth } from "@clerk/nextjs";
import type { AppRouter } from "@superset/trpc";
import type { QueryClient } from "@tanstack/react-query";
import { QueryClientProvider } from "@tanstack/react-query";
@@ -33,7 +32,6 @@ export type UseTRPC = typeof useTRPC;
export function TRPCReactProvider(props: { children: React.ReactNode }) {
const queryClient = getQueryClient();
- const { getToken } = useAuth();
const [trpcClient] = useState(() =>
createTRPCClient({
@@ -46,12 +44,11 @@ export function TRPCReactProvider(props: { children: React.ReactNode }) {
httpBatchStreamLink({
transformer: SuperJSON,
url: `${env.NEXT_PUBLIC_API_URL}/api/trpc`,
- async headers() {
- const token = await getToken();
- return {
- "x-trpc-source": "nextjs-react",
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
- };
+ headers() {
+ return { "x-trpc-source": "nextjs-react" };
+ },
+ fetch(url, options) {
+ return fetch(url, { ...options, credentials: "include" });
},
}),
],
diff --git a/biome.jsonc b/biome.jsonc
index ce8290bd6..e779f28b1 100644
--- a/biome.jsonc
+++ b/biome.jsonc
@@ -1,5 +1,5 @@
{
- "$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
+ "$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
diff --git a/bun.lock b/bun.lock
index cbb3e7cbc..fc9a3d22d 100644
--- a/bun.lock
+++ b/bun.lock
@@ -14,8 +14,8 @@
"name": "@superset/admin",
"version": "0.1.0",
"dependencies": {
- "@clerk/nextjs": "^6.36.2",
"@sentry/nextjs": "^10.32.1",
+ "@superset/auth": "workspace:*",
"@superset/db": "workspace:*",
"@superset/shared": "workspace:*",
"@superset/trpc": "workspace:*",
@@ -26,6 +26,7 @@
"@trpc/client": "^11.7.1",
"@trpc/server": "^11.7.1",
"@trpc/tanstack-react-query": "^11.7.1",
+ "better-auth": "^1.4.9",
"date-fns": "^4.1.0",
"drizzle-orm": "0.45.1",
"import-in-the-middle": "2.0.1",
@@ -57,11 +58,10 @@
"name": "@superset/api",
"version": "0.1.0",
"dependencies": {
- "@clerk/backend": "^2.27.0",
- "@clerk/nextjs": "^6.36.2",
"@electric-sql/client": "^1.3.1",
"@linear/sdk": "^68.1.0",
"@sentry/nextjs": "^10.32.1",
+ "@superset/auth": "workspace:*",
"@superset/db": "workspace:*",
"@superset/shared": "workspace:*",
"@superset/trpc": "workspace:*",
@@ -69,6 +69,7 @@
"@trpc/server": "^11.7.1",
"@upstash/qstash": "^2.8.4",
"@vercel/blob": "^2.0.0",
+ "better-auth": "^1.4.9",
"drizzle-orm": "0.45.1",
"import-in-the-middle": "2.0.1",
"jose": "^6.1.3",
@@ -130,6 +131,7 @@
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.8",
"@sentry/electron": "^7.5.0",
+ "@superset/auth": "workspace:*",
"@superset/db": "workspace:*",
"@superset/local-db": "workspace:*",
"@superset/shared": "workspace:*",
@@ -190,6 +192,7 @@
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^19.2.3",
+ "react-hotkeys-hook": "^5.2.1",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-mosaic-component": "^6.1.1",
@@ -229,6 +232,7 @@
"bun-types": "^1.3.1",
"code-inspector-plugin": "^1.2.2",
"cross-env": "^10.0.0",
+ "drizzle-kit": "0.31.8",
"electron": "39.1.2",
"electron-builder": "^26.0.12",
"electron-extension-installer": "^2.0.0",
@@ -283,10 +287,10 @@
"name": "@superset/marketing",
"version": "0.1.0",
"dependencies": {
- "@clerk/nextjs": "^6.36.2",
"@react-three/drei": "^10.7.6",
"@react-three/fiber": "^9.4.0",
"@sentry/nextjs": "^10.32.1",
+ "@superset/auth": "workspace:*",
"@superset/shared": "workspace:*",
"@superset/ui": "workspace:*",
"@t3-oss/env-nextjs": "^0.13.8",
@@ -324,8 +328,8 @@
"name": "@superset/web",
"version": "0.1.0",
"dependencies": {
- "@clerk/nextjs": "^6.36.2",
"@sentry/nextjs": "^10.32.1",
+ "@superset/auth": "workspace:*",
"@superset/db": "workspace:*",
"@superset/shared": "workspace:*",
"@superset/trpc": "workspace:*",
@@ -337,6 +341,7 @@
"@trpc/server": "^11.7.1",
"@trpc/tanstack-react-query": "^11.7.1",
"@uiw/react-md-editor": "^4.0.11",
+ "better-auth": "^1.4.9",
"framer-motion": "^12.23.26",
"geist": "^1.5.1",
"import-in-the-middle": "2.0.1",
@@ -365,6 +370,24 @@
"typescript": "^5.9.3",
},
},
+ "packages/auth": {
+ "name": "@superset/auth",
+ "version": "0.1.0",
+ "dependencies": {
+ "@superset/db": "workspace:*",
+ "@t3-oss/env-core": "^0.13.8",
+ "@t3-oss/env-nextjs": "^0.13.8",
+ "better-auth": "^1.4.9",
+ "dotenv": "^17.2.3",
+ "drizzle-orm": "0.45.1",
+ "zod": "^4.1.13",
+ },
+ "devDependencies": {
+ "@superset/typescript": "workspace:*",
+ "@types/node": "^24.9.1",
+ "typescript": "^5.9.3",
+ },
+ },
"packages/db": {
"name": "@superset/db",
"version": "0.1.0",
@@ -413,8 +436,8 @@
"name": "@superset/trpc",
"version": "0.1.0",
"dependencies": {
- "@clerk/backend": "^2.27.0",
"@linear/sdk": "^68.1.0",
+ "@superset/auth": "workspace:*",
"@superset/db": "workspace:*",
"@superset/shared": "workspace:*",
"@t3-oss/env-core": "^0.13.8",
@@ -511,13 +534,13 @@
"packages": {
"7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="],
- "@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.24", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-mflk80YF8hj8vrF9e1IHhovGKC1ubX+sY88pesSk3pUiXfH5VPO8dgzNnxjwsqsCZrnkHcztxS5cSl4TzSiEuA=="],
+ "@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA=="],
- "@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="],
+ "@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="],
- "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="],
+ "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="],
- "@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.2.3", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-jsElTJ0sQ4wHRz+C45tfect76BwbTbgkgKByOzpCN9xG61N5V6u/glvg1CsNJhq2xJIFpKHSwG3D2wPPuEYOrQ=="],
+ "@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.2.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-mkOh+Wwawzuf5wa30bvc4nA+Qb6DIrGWgBhRR/Pw4T9nsgYait8izvXkNyU78D6Wcu3Z+KUdwCmLCxlWjEotYA=="],
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
@@ -569,23 +592,31 @@
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
- "@biomejs/biome": ["@biomejs/biome@2.3.10", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.10", "@biomejs/cli-darwin-x64": "2.3.10", "@biomejs/cli-linux-arm64": "2.3.10", "@biomejs/cli-linux-arm64-musl": "2.3.10", "@biomejs/cli-linux-x64": "2.3.10", "@biomejs/cli-linux-x64-musl": "2.3.10", "@biomejs/cli-win32-arm64": "2.3.10", "@biomejs/cli-win32-x64": "2.3.10" }, "bin": { "biome": "bin/biome" } }, "sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ=="],
+ "@better-auth/core": ["@better-auth/core@1.4.9", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.7", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-JT2q4NDkQzN22KclUEoZ7qU6tl9HUTfK1ctg2oWlT87SEagkwJcnrUwS9VznL+u9ziOIfY27P0f7/jSnmvLcoQ=="],
+
+ "@better-auth/telemetry": ["@better-auth/telemetry@1.4.9", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.9" } }, "sha512-Tthy1/Gmx+pYlbvRQPBTKfVei8+pJwvH1NZp+5SbhwA6K2EXIaoonx/K6N/AXYs2aKUpyR4/gzqDesDjL7zd6A=="],
- "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w=="],
+ "@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="],
- "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-Vae7+V6t/Avr8tVbFNjnFSTKZogZHFYl7MMH62P/J1kZtr0tyRQ9Fe0onjqjS2Ek9lmNLmZc/VR5uSekh+p1fg=="],
+ "@better-fetch/fetch": ["@better-fetch/fetch@1.1.21", "", {}, "sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A=="],
- "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-hhPw2V3/EpHKsileVOFynuWiKRgFEV48cLe0eA+G2wO4SzlwEhLEB9LhlSrVeu2mtSn205W283LkX7Fh48CaxA=="],
+ "@biomejs/biome": ["@biomejs/biome@2.3.8", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.8", "@biomejs/cli-darwin-x64": "2.3.8", "@biomejs/cli-linux-arm64": "2.3.8", "@biomejs/cli-linux-arm64-musl": "2.3.8", "@biomejs/cli-linux-x64": "2.3.8", "@biomejs/cli-linux-x64-musl": "2.3.8", "@biomejs/cli-win32-arm64": "2.3.8", "@biomejs/cli-win32-x64": "2.3.8" }, "bin": { "biome": "bin/biome" } }, "sha512-Qjsgoe6FEBxWAUzwFGFrB+1+M8y/y5kwmg5CHac+GSVOdmOIqsAiXM5QMVGZJ1eCUCLlPZtq4aFAQ0eawEUuUA=="],
- "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-B9DszIHkuKtOH2IFeeVkQmSMVUjss9KtHaNXquYYWCjH8IstNgXgx5B0aSBQNr6mn4RcKKRQZXn9Zu1rM3O0/A=="],
+ "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HM4Zg9CGQ3txTPflxD19n8MFPrmUAjaC7PQdLkugeeC0cQ+PiVrd7i09gaBS/11QKsTDBJhVg85CEIK9f50Qww=="],
- "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-wwAkWD1MR95u+J4LkWP74/vGz+tRrIQvr8kfMMJY8KOQ8+HMVleREOcPYsQX82S7uueco60L58Wc6M1I9WA9Dw=="],
+ "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-lUDQ03D7y/qEao7RgdjWVGCu+BLYadhKTm40HkpJIi6kn8LSv5PAwRlew/DmwP4YZ9ke9XXoTIQDO1vAnbRZlA=="],
- "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QTfHZQh62SDFdYc2nfmZFuTm5yYb4eO1zwfB+90YxUumRCR171tS1GoTX5OD0wrv4UsziMPmrePMtkTnNyYG3g=="],
+ "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-Uo1OJnIkJgSgF+USx970fsM/drtPcQ39I+JO+Fjsaa9ZdCN1oysQmy6oAGbyESlouz+rzEckLTF6DS7cWse95g=="],
- "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-o7lYc9n+CfRbHvkjPhm8s9FgbKdYZu5HCcGVMItLjz93EhgJ8AM44W+QckDqLA9MKDNFrR8nPbO4b73VC5kGGQ=="],
+ "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-PShR4mM0sjksUMyxbyPNMxoKFPVF48fU8Qe8Sfx6w6F42verbwRLbz+QiKNiDPRJwUoMG1nPM50OBL3aOnTevA=="],
- "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.10", "", { "os": "win32", "cpu": "x64" }, "sha512-pHEFgq7dUEsKnqG9mx9bXihxGI49X+ar+UBrEIj3Wqj3UCZp1rNgV+OoyjFgcXsjCWpuEAF4VJdkZr3TrWdCbQ=="],
+ "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.8", "", { "os": "linux", "cpu": "x64" }, "sha512-QDPMD5bQz6qOVb3kiBui0zKZXASLo0NIQ9JVJio5RveBEFgDgsvJFUvZIbMbUZT3T00M/1wdzwWXk4GIh0KaAw=="],
+
+ "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.8", "", { "os": "linux", "cpu": "x64" }, "sha512-YGLkqU91r1276uwSjiUD/xaVikdxgV1QpsicT0bIA1TaieM6E5ibMZeSyjQ/izBn4tKQthUSsVZacmoJfa3pDA=="],
+
+ "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-H4IoCHvL1fXKDrTALeTKMiE7GGWFAraDwBYFquE/L/5r1927Te0mYIGseXi4F+lrrwhSWbSGt5qPFswNoBaCxg=="],
+
+ "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.8", "", { "os": "win32", "cpu": "x64" }, "sha512-RguzimPoZWtBapfKhKjcWXBVI91tiSprqdBYu7tWhgN8pKRZhw24rFeNZTNf6UiBfjCYCi9eFQs/JzJZIhuK4w=="],
"@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.1", "", {}, "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw=="],
@@ -599,27 +630,17 @@
"@chevrotain/utils": ["@chevrotain/utils@11.0.3", "", {}, "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ=="],
- "@clerk/backend": ["@clerk/backend@2.29.0", "", { "dependencies": { "@clerk/shared": "^3.41.1", "@clerk/types": "^4.101.9", "cookie": "1.0.2", "standardwebhooks": "^1.0.0", "tslib": "2.8.1" } }, "sha512-cw4CK6ZHgeFROirlIOawelqRBxZAyH6v3GPSYZEEzYAL0WWUHx7cMXzoQcTMruH7w6UM7s3Ox+uUcINESWkQPA=="],
-
- "@clerk/clerk-react": ["@clerk/clerk-react@5.59.2", "", { "dependencies": { "@clerk/shared": "^3.41.1", "tslib": "2.8.1" }, "peerDependencies": { "react": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0", "react-dom": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0" } }, "sha512-vFZ4LWPenbNnui4GqGGkicH/3SL7KhS9egTMv/m0Dj/sS7mUgmLqAFpqWkhbzN8s8/rybuvJsMyIU7M0kx8+Cw=="],
-
- "@clerk/nextjs": ["@clerk/nextjs@6.36.5", "", { "dependencies": { "@clerk/backend": "^2.29.0", "@clerk/clerk-react": "^5.59.2", "@clerk/shared": "^3.41.1", "@clerk/types": "^4.101.9", "server-only": "0.0.1", "tslib": "2.8.1" }, "peerDependencies": { "next": "^13.5.7 || ^14.2.25 || ^15.2.3 || ^16", "react": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0", "react-dom": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0" } }, "sha512-qHNNbxhAZMHanv47DKc08Xc+y0gbsoQBFVYA+WRzwii5OWOoWmLlydTGKaqukqNw9km9IN9b2KWSAvs1oklp2g=="],
+ "@code-inspector/core": ["@code-inspector/core@1.3.2", "", { "dependencies": { "@vue/compiler-dom": "^3.5.13", "chalk": "^4.1.1", "dotenv": "^16.1.4", "launch-ide": "1.3.0", "portfinder": "^1.0.28" } }, "sha512-6bwCW7AbX/gYaoiZPFqkHAP5f/C0nXj29AixqBUNl1sRrsWFPHHfiaWH8WPmjx9IXI/nln109GvMiFHUpm2Mvg=="],
- "@clerk/shared": ["@clerk/shared@3.41.1", "", { "dependencies": { "csstype": "3.1.3", "dequal": "2.0.3", "glob-to-regexp": "0.4.1", "js-cookie": "3.0.5", "std-env": "^3.9.0", "swr": "2.3.4" }, "peerDependencies": { "react": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0", "react-dom": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-BCbT7Xodk2rndA2nV/lW8X5LMNTvFP5UG2wNN9cYuAcTaI6hYZP18/z2zef2gG4xIrK7WAEjGVzHscikqNtzFQ=="],
+ "@code-inspector/esbuild": ["@code-inspector/esbuild@1.3.2", "", { "dependencies": { "@code-inspector/core": "1.3.2" } }, "sha512-AlcMO+pfwvh+m9L7bOeonTjgeJKaUsfEJxJIjyqUZMjk+F+ujhxFUKtZZU7RUvuQLr4e/flPdN+yxvWKfymr+g=="],
- "@clerk/types": ["@clerk/types@4.101.9", "", { "dependencies": { "@clerk/shared": "^3.41.1" } }, "sha512-RO00JqqmkIoI1o0XCtvudjaLpqEoe8PRDHlLS1r/aNZazUQCO0TT6nZOx1F3X+QJDjqYVY7YmYl3mtO2QVEk1g=="],
+ "@code-inspector/mako": ["@code-inspector/mako@1.3.2", "", { "dependencies": { "@code-inspector/core": "1.3.2" } }, "sha512-WAeCAruJ5N73jqPWQgnsqyLp4Fn9hrn5vHohxhqqXyjD+qqCUKZNLrZeuD5kyku8k51LRJWQUe6MblW3IWyUJA=="],
- "@code-inspector/core": ["@code-inspector/core@1.3.4", "", { "dependencies": { "@vue/compiler-dom": "^3.5.13", "chalk": "^4.1.1", "dotenv": "^16.1.4", "launch-ide": "1.3.1", "portfinder": "^1.0.28" } }, "sha512-AUFtDH/hngBHrNVwW1z44ogZkaGhfmFQJZjyQrSCp+mERVQqa4QNGQpRqiIEWVCwJ2e3GCuwxeAr/k48r1nscA=="],
+ "@code-inspector/turbopack": ["@code-inspector/turbopack@1.3.2", "", { "dependencies": { "@code-inspector/core": "1.3.2", "@code-inspector/webpack": "1.3.2" } }, "sha512-e7HJIwgGInSHLpHv1ZdAaILnJsREiwDL5363Gs6H0ZB2JvdHvLTpYFc6wlPLrZG4fp53FwsnULFhHtXDrjVYRg=="],
- "@code-inspector/esbuild": ["@code-inspector/esbuild@1.3.4", "", { "dependencies": { "@code-inspector/core": "1.3.4" } }, "sha512-VVZLPnaUNtX4fm07bKBkdIn2t1H0jPzah3fHd/CtNO82mnT1H3hZCuvtlO4jQZnErWC1KYJUEDrEe4T5TA5giQ=="],
+ "@code-inspector/vite": ["@code-inspector/vite@1.3.2", "", { "dependencies": { "@code-inspector/core": "1.3.2", "chalk": "4.1.1" } }, "sha512-uwtZ2JTA7eh19LUWhwsngwhgn7S1K8y9cqHK4vu2tEDbmahiQkQM/XytzPrsdAPxGu4M7huBJoGKXn32Tjrvgg=="],
- "@code-inspector/mako": ["@code-inspector/mako@1.3.4", "", { "dependencies": { "@code-inspector/core": "1.3.4" } }, "sha512-SvjZSfLXgiWDMmJ9+YfPqbE2WVbXCNPjREclEJfqkM2qS/oRPmHw/O81p5wh6dN48gzVadLKEOPtSE0+FURJgQ=="],
-
- "@code-inspector/turbopack": ["@code-inspector/turbopack@1.3.4", "", { "dependencies": { "@code-inspector/core": "1.3.4", "@code-inspector/webpack": "1.3.4" } }, "sha512-zsv2ppMFedNZetrlN4PEW4B2vAheu3yUfrmSKfZlXEb8YT378sq+49+57aP/E1Q8cHRzowy4GItuPKwAy7TTVQ=="],
-
- "@code-inspector/vite": ["@code-inspector/vite@1.3.4", "", { "dependencies": { "@code-inspector/core": "1.3.4", "chalk": "4.1.1" } }, "sha512-BcRnQFwt8yQ4CcbN7yPf/Vmon3yfS5lPpcH0QAcjD03r61if5fmix29f65Rf/WxzlVyBkk7148xaIVQ3iT2Yjg=="],
-
- "@code-inspector/webpack": ["@code-inspector/webpack@1.3.4", "", { "dependencies": { "@code-inspector/core": "1.3.4" } }, "sha512-lqsDOSmKXgOYvlurWL4SHaNItNCNZDVbFJlroM4ECnOGt/iNUI0UwaFxn9U5NeKff7fnTmdH8Hrz2IaMR4FVTg=="],
+ "@code-inspector/webpack": ["@code-inspector/webpack@1.3.2", "", { "dependencies": { "@code-inspector/core": "1.3.2" } }, "sha512-P9jrU7Hpca4y+ukaHRVP7w1rOIcNTPQONb5uITkt/dHDmI6/KDW5FfydcDI6Jc8HFRHLkTVZsZyUcllItA2VVQ=="],
"@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
@@ -639,6 +660,8 @@
"@electric-sql/client": ["@electric-sql/client@1.3.1", "", { "dependencies": { "@microsoft/fetch-event-source": "^2.0.1" }, "optionalDependencies": { "@rollup/rollup-darwin-arm64": "^4.18.1" } }, "sha512-Tr7jY60acKfxuODOzGcJYzEXtTJyiE8l237hMpCPHjflr+qSGYVZ0NkOnFgAE2xIPFgP1zn05nQb3+mkUu8qUQ=="],
+ "@electric-sql/pglite": ["@electric-sql/pglite@0.3.14", "", {}, "sha512-3DB258dhqdsArOI1fIt7cb9RpUOgcDg5hXWVgVHAeqVQ/qxtFy605QKs4gx6mFq3jWsSPqDN8TgSEsqC3OfV9Q=="],
+
"@electron/asar": ["@electron/asar@3.2.18", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg=="],
"@electron/fuses": ["@electron/fuses@1.8.0", "", { "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", "minimist": "^1.2.5" }, "bin": { "electron-fuses": "dist/bin.js" } }, "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw=="],
@@ -869,23 +892,27 @@
"@neondatabase/serverless": ["@neondatabase/serverless@1.0.2", "", { "dependencies": { "@types/node": "^22.15.30", "@types/pg": "^8.8.0" } }, "sha512-I5sbpSIAHiB+b6UttofhrN/UJXII+4tZPAq1qugzwCwLIL8EZLV7F/JyHUrEIiGgQpEXzpnjlJ+zwcEhheGvCw=="],
- "@next/env": ["@next/env@16.1.1", "", {}, "sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA=="],
+ "@next/env": ["@next/env@16.0.10", "", {}, "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang=="],
+
+ "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg=="],
+
+ "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw=="],
- "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA=="],
+ "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw=="],
- "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw=="],
+ "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw=="],
- "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ=="],
+ "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.10", "", { "os": "linux", "cpu": "x64" }, "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA=="],
- "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg=="],
+ "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.10", "", { "os": "linux", "cpu": "x64" }, "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g=="],
- "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ=="],
+ "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg=="],
- "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.1", "", { "os": "linux", "cpu": "x64" }, "sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA=="],
+ "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.10", "", { "os": "win32", "cpu": "x64" }, "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q=="],
- "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA=="],
+ "@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="],
- "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.1", "", { "os": "win32", "cpu": "x64" }, "sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw=="],
+ "@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
@@ -1075,13 +1102,13 @@
"@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
- "@react-aria/focus": ["@react-aria/focus@3.21.3", "", { "dependencies": { "@react-aria/interactions": "^3.26.0", "@react-aria/utils": "^3.32.0", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw=="],
+ "@react-aria/focus": ["@react-aria/focus@3.21.2", "", { "dependencies": { "@react-aria/interactions": "^3.25.6", "@react-aria/utils": "^3.31.0", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ=="],
- "@react-aria/interactions": ["@react-aria/interactions@3.26.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-aria/utils": "^3.32.0", "@react-stately/flags": "^3.1.2", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q=="],
+ "@react-aria/interactions": ["@react-aria/interactions@3.25.6", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-aria/utils": "^3.31.0", "@react-stately/flags": "^3.1.2", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw=="],
"@react-aria/ssr": ["@react-aria/ssr@3.9.10", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ=="],
- "@react-aria/utils": ["@react-aria/utils@3.32.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.11.0", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg=="],
+ "@react-aria/utils": ["@react-aria/utils@3.31.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.10.8", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig=="],
"@react-dnd/asap": ["@react-dnd/asap@5.0.2", "", {}, "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A=="],
@@ -1091,11 +1118,11 @@
"@react-stately/flags": ["@react-stately/flags@3.1.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg=="],
- "@react-stately/utils": ["@react-stately/utils@3.11.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw=="],
+ "@react-stately/utils": ["@react-stately/utils@3.10.8", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g=="],
"@react-three/drei": ["@react-three/drei@10.7.7", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mediapipe/tasks-vision": "0.10.17", "@monogrid/gainmap-js": "^3.0.6", "@use-gesture/react": "^10.3.1", "camera-controls": "^3.1.0", "cross-env": "^7.0.3", "detect-gpu": "^5.0.56", "glsl-noise": "^0.0.0", "hls.js": "^1.5.17", "maath": "^0.10.8", "meshline": "^3.3.1", "stats-gl": "^2.2.8", "stats.js": "^0.17.0", "suspend-react": "^0.1.3", "three-mesh-bvh": "^0.8.3", "three-stdlib": "^2.35.6", "troika-three-text": "^0.52.4", "tunnel-rat": "^0.1.2", "use-sync-external-store": "^1.4.0", "utility-types": "^3.11.0", "zustand": "^5.0.1" }, "peerDependencies": { "@react-three/fiber": "^9.0.0", "react": "^19", "react-dom": "^19", "three": ">=0.159" }, "optionalPeers": ["react-dom"] }, "sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ=="],
- "@react-three/fiber": ["@react-three/fiber@9.5.0", "", { "dependencies": { "@babel/runtime": "^7.17.8", "@types/webxr": "*", "base64-js": "^1.5.1", "buffer": "^6.0.3", "its-fine": "^2.0.0", "react-use-measure": "^2.1.7", "scheduler": "^0.27.0", "suspend-react": "^0.1.3", "use-sync-external-store": "^1.4.0", "zustand": "^5.0.3" }, "peerDependencies": { "expo": ">=43.0", "expo-asset": ">=8.4", "expo-file-system": ">=11.0", "expo-gl": ">=11.0", "react": ">=19 <19.3", "react-dom": ">=19 <19.3", "react-native": ">=0.78", "three": ">=0.156" }, "optionalPeers": ["expo", "expo-asset", "expo-file-system", "expo-gl", "react-dom", "react-native"] }, "sha512-FiUzfYW4wB1+PpmsE47UM+mCads7j2+giRBltfwH7SNhah95rqJs3ltEs9V3pP8rYdS0QlNne+9Aj8dS/SiaIA=="],
+ "@react-three/fiber": ["@react-three/fiber@9.4.2", "", { "dependencies": { "@babel/runtime": "^7.17.8", "@types/react-reconciler": "^0.32.0", "@types/webxr": "*", "base64-js": "^1.5.1", "buffer": "^6.0.3", "its-fine": "^2.0.0", "react-reconciler": "^0.31.0", "react-use-measure": "^2.1.7", "scheduler": "^0.25.0", "suspend-react": "^0.1.3", "use-sync-external-store": "^1.4.0", "zustand": "^5.0.3" }, "peerDependencies": { "expo": ">=43.0", "expo-asset": ">=8.4", "expo-file-system": ">=11.0", "expo-gl": ">=11.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-native": ">=0.78", "three": ">=0.156" }, "optionalPeers": ["expo", "expo-asset", "expo-file-system", "expo-gl", "react-dom", "react-native"] }, "sha512-H4B4+FDNHpvIb4FmphH4ubxOfX5bxmfOw0+3pkQwR9u9wFiyMS7wUDkNn0m4RqQuiLWeia9jfN1eBvtyAVGEog=="],
"@react-types/shared": ["@react-types/shared@3.32.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w=="],
@@ -1105,49 +1132,49 @@
"@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
- "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.54.0", "", { "os": "android", "cpu": "arm" }, "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng=="],
+ "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.3", "", { "os": "android", "cpu": "arm" }, "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w=="],
- "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.54.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw=="],
+ "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.53.3", "", { "os": "android", "cpu": "arm64" }, "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w=="],
- "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.54.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw=="],
+ "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.53.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA=="],
- "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.54.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A=="],
+ "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.53.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ=="],
- "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.54.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA=="],
+ "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.53.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w=="],
- "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.54.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ=="],
+ "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.53.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q=="],
- "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ=="],
+ "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw=="],
- "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA=="],
+ "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg=="],
- "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng=="],
+ "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w=="],
- "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg=="],
+ "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A=="],
- "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw=="],
+ "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g=="],
- "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.54.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA=="],
+ "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.53.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw=="],
- "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ=="],
+ "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g=="],
- "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A=="],
+ "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A=="],
- "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.54.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ=="],
+ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.53.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg=="],
- "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ=="],
+ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w=="],
- "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw=="],
+ "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q=="],
- "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.54.0", "", { "os": "none", "cpu": "arm64" }, "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg=="],
+ "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.53.3", "", { "os": "none", "cpu": "arm64" }, "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw=="],
- "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.54.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw=="],
+ "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.53.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw=="],
- "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.54.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ=="],
+ "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.53.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA=="],
- "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.54.0", "", { "os": "win32", "cpu": "x64" }, "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ=="],
+ "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg=="],
- "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.54.0", "", { "os": "win32", "cpu": "x64" }, "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg=="],
+ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ=="],
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
@@ -1201,19 +1228,19 @@
"@sentry/webpack-plugin": ["@sentry/webpack-plugin@4.6.1", "", { "dependencies": { "@sentry/bundler-plugin-core": "4.6.1", "unplugin": "1.0.1", "uuid": "^9.0.0" }, "peerDependencies": { "webpack": ">=4.40.0" } }, "sha512-CJgT/t2pQWsPsMx9VJ86goU/orCQhL2HhDj5ZYBol6fPPoEGeTqKOPCnv/xsbCAfGSp1uHpyRLTA/Gx96u7VVA=="],
- "@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="],
+ "@shikijs/core": ["@shikijs/core@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-L7SrRibU7ZoYi1/TrZsJOFAnnHyLTE1SwHG1yNWjZIVCqjOEmCSuK2ZO9thnRbJG6TOkPp+Z963JmpCNw5nzvA=="],
- "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="],
+ "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-ZfWJNm2VMhKkQIKT9qXbs76RRcT0SF/CAvEz0+RkpUDAoDaCx0uFdCGzSRiD9gSlhm6AHkjdieOBJMaO2eC1rQ=="],
- "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ=="],
+ "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1hRxtYIJfJSZeM5ivbUXv9hcJP3PWRo5prG/V2sWwiubUKTa+7P62d2qxCW8jiVFX4pgRHhnHNp+qeR7Xl+6kg=="],
- "@shikijs/langs": ["@shikijs/langs@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA=="],
+ "@shikijs/langs": ["@shikijs/langs@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0" } }, "sha512-dBMFzzg1QiXqCVQ5ONc0z2ebyoi5BKz+MtfByLm0o5/nbUu3Iz8uaTCa5uzGiscQKm7lVShfZHU1+OG3t5hgwg=="],
- "@shikijs/themes": ["@shikijs/themes@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ=="],
+ "@shikijs/themes": ["@shikijs/themes@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0" } }, "sha512-H36qw+oh91Y0s6OlFfdSuQ0Ld+5CgB/VE6gNPK+Hk4VRbVG/XQgkjnt4KzfnnoO6tZPtKJKHPjwebOCfjd6F8A=="],
- "@shikijs/twoslash": ["@shikijs/twoslash@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/types": "3.20.0", "twoslash": "^0.3.4" }, "peerDependencies": { "typescript": ">=5.5.0" } }, "sha512-fZz6vB9a0M8iuVF/ydIV4ToC09sbOh/TqxXZFWAh5J8bLiPsyQGtygKMDQ9L0Sdop3co0TIC/JsrLmsbmZwwsw=="],
+ "@shikijs/twoslash": ["@shikijs/twoslash@3.19.0", "", { "dependencies": { "@shikijs/core": "3.19.0", "@shikijs/types": "3.19.0", "twoslash": "^0.3.4" }, "peerDependencies": { "typescript": ">=5.5.0" } }, "sha512-DnkH4slSLPC7dJPhZ9Eofy1X/ZgXiWsvOl/ERK7799ZqXsJwtsq2e8RgHBQUX4Y2lf6aoMojirocLY0AbPF3Dg=="],
- "@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="],
+ "@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="],
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
@@ -1221,9 +1248,7 @@
"@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="],
- "@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="],
-
- "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
+ "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
"@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="],
@@ -1231,6 +1256,8 @@
"@superset/api": ["@superset/api@workspace:apps/api"],
+ "@superset/auth": ["@superset/auth@workspace:packages/auth"],
+
"@superset/cli": ["@superset/cli@workspace:apps/cli"],
"@superset/db": ["@superset/db@workspace:packages/db"],
@@ -1257,9 +1284,9 @@
"@szmarczak/http-timer": ["@szmarczak/http-timer@4.0.6", "", { "dependencies": { "defer-to-connect": "^2.0.0" } }, "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w=="],
- "@t3-oss/env-core": ["@t3-oss/env-core@0.13.10", "", { "peerDependencies": { "arktype": "^2.1.0", "typescript": ">=5.0.0", "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["arktype", "typescript", "valibot", "zod"] }, "sha512-NNFfdlJ+HmPHkLi2HKy7nwuat9SIYOxei9K10lO2YlcSObDILY7mHZNSHsieIM3A0/5OOzw/P/b+yLvPdaG52g=="],
+ "@t3-oss/env-core": ["@t3-oss/env-core@0.13.8", "", { "peerDependencies": { "arktype": "^2.1.0", "typescript": ">=5.0.0", "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0 || ^4.0.0-beta.0" }, "optionalPeers": ["arktype", "typescript", "valibot", "zod"] }, "sha512-L1inmpzLQyYu4+Q1DyrXsGJYCXbtXjC4cICw1uAKv0ppYPQv656lhZPU91Qd1VS6SO/bou1/q5ufVzBGbNsUpw=="],
- "@t3-oss/env-nextjs": ["@t3-oss/env-nextjs@0.13.10", "", { "dependencies": { "@t3-oss/env-core": "0.13.10" }, "peerDependencies": { "arktype": "^2.1.0", "typescript": ">=5.0.0", "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["arktype", "typescript", "valibot", "zod"] }, "sha512-JfSA2WXOnvcc/uMdp31paMsfbYhhdvLLRxlwvrnlPE9bwM/n0Z+Qb9xRv48nPpvfMhOrkrTYw1I5Yc06WIKBJQ=="],
+ "@t3-oss/env-nextjs": ["@t3-oss/env-nextjs@0.13.8", "", { "dependencies": { "@t3-oss/env-core": "0.13.8" }, "peerDependencies": { "arktype": "^2.1.0", "typescript": ">=5.0.0", "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0 || ^4.0.0-beta.0" }, "optionalPeers": ["arktype", "typescript", "valibot", "zod"] }, "sha512-QmTLnsdQJ8BiQad2W2nvV6oUpH4oMZMqnFEjhVpzU0h3sI9hn8zb8crjWJ1Amq453mGZs6A4v4ihIeBFDOrLeQ=="],
"@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="],
@@ -1301,21 +1328,21 @@
"@tanstack/pacer-lite": ["@tanstack/pacer-lite@0.1.1", "", {}, "sha512-y/xtNPNt/YeyoVxE/JCx+T7yjEzpezmbb+toK8DDD1P4m7Kzs5YR956+7OKexG3f8aXgC3rLZl7b1V+yNUSy5w=="],
- "@tanstack/query-core": ["@tanstack/query-core@5.90.16", "", {}, "sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww=="],
+ "@tanstack/query-core": ["@tanstack/query-core@5.90.12", "", {}, "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg=="],
- "@tanstack/query-devtools": ["@tanstack/query-devtools@5.92.0", "", {}, "sha512-N8D27KH1vEpVacvZgJL27xC6yPFUy0Zkezn5gnB3L3gRCxlDeSuiya7fKge8Y91uMTnC8aSxBQhcK6ocY7alpQ=="],
+ "@tanstack/query-devtools": ["@tanstack/query-devtools@5.91.1", "", {}, "sha512-l8bxjk6BMsCaVQH6NzQEE/bEgFy1hAs5qbgXl0xhzezlaQbPk6Mgz9BqEg2vTLPOHD8N4k+w/gdgCbEzecGyNg=="],
"@tanstack/react-db": ["@tanstack/react-db@0.1.60", "", { "dependencies": { "@tanstack/db": "0.5.16", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-Pz3pwH4vgRxlS/L3+BszINjNlIUXahJ6EqSEsYBMBT19G36GzTzyd5Qq98JaOXuu8V0dkiFWEoyEoTv3BiHcrg=="],
- "@tanstack/react-query": ["@tanstack/react-query@5.90.16", "", { "dependencies": { "@tanstack/query-core": "5.90.16" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-bpMGOmV4OPmif7TNMteU/Ehf/hoC0Kf98PDc0F4BZkFrEapRMEqI/V6YS0lyzwSV6PQpY1y4xxArUIfBW5LVxQ=="],
+ "@tanstack/react-query": ["@tanstack/react-query@5.90.12", "", { "dependencies": { "@tanstack/query-core": "5.90.12" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg=="],
- "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.91.2", "", { "dependencies": { "@tanstack/query-devtools": "5.92.0" }, "peerDependencies": { "@tanstack/react-query": "^5.90.14", "react": "^18 || ^19" } }, "sha512-ZJ1503ay5fFeEYFUdo7LMNFzZryi6B0Cacrgr2h1JRkvikK1khgIq6Nq2EcblqEdIlgB/r7XDW8f8DQ89RuUgg=="],
+ "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.91.1", "", { "dependencies": { "@tanstack/query-devtools": "5.91.1" }, "peerDependencies": { "@tanstack/react-query": "^5.90.10", "react": "^18 || ^19" } }, "sha512-tRnJYwEbH0kAOuToy8Ew7bJw1lX3AjkkgSlf/vzb+NpnqmHPdWM+lA2DSdGQSLi1SU0PDRrrCI1vnZnci96CsQ=="],
- "@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.14", "", { "dependencies": { "@tanstack/virtual-core": "3.13.14" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-WG0d7mBD54eA7dgA3+sO5csS0B49QKqM6Gy5Rf31+Oq/LTKROQSao9m2N/vz1IqVragOKU5t5k1LAcqh/DfTxw=="],
+ "@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.13", "", { "dependencies": { "@tanstack/virtual-core": "3.13.13" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-4o6oPMDvQv+9gMi8rE6gWmsOjtUZUYIJHv7EB+GblyYdi8U6OqLl8rhHWIUZSL1dUU2dPwTdTgybCKf9EjIrQg=="],
"@tanstack/store": ["@tanstack/store@0.8.0", "", {}, "sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ=="],
- "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.14", "", {}, "sha512-b5Uvd8J2dc7ICeX9SRb/wkCxWk7pUwN214eEPAQsqrsktSKTCmyLxOQWSMgogBByXclZeAdgZ3k4o0fIYUIBqQ=="],
+ "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.13", "", {}, "sha512-uQFoSdKKf5S8k51W5t7b2qpfkyIbdHMzAn+AMQvHPxKUPeo1SsGaA4JRISQT87jm28b7z8OEqPcg1IOZagQHcA=="],
"@theguild/remark-mermaid": ["@theguild/remark-mermaid@0.3.0", "", { "dependencies": { "mermaid": "^11.0.0", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "react": "^18.2.0 || ^19.0.0" } }, "sha512-Fy1J4FSj8totuHsHFpaeWyWRaRSIvpzGTRoEfnNJc1JmLV9uV70sYE3zcT+Jj5Yw20Xq4iCsiT+3Ho49BBZcBQ=="],
@@ -1331,13 +1358,13 @@
"@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="],
- "@trpc/client": ["@trpc/client@11.8.1", "", { "peerDependencies": { "@trpc/server": "11.8.1", "typescript": ">=5.7.2" } }, "sha512-L/SJFGanr9xGABmuDoeXR4xAdHJmsXsiF9OuH+apecJ+8sUITzVT1EPeqp0ebqA6lBhEl5pPfg3rngVhi/h60Q=="],
+ "@trpc/client": ["@trpc/client@11.7.2", "", { "peerDependencies": { "@trpc/server": "11.7.2", "typescript": ">=5.7.2" } }, "sha512-OQxqUMfpDvjcszo9dbnqWQXnW2L5IbrKSz2H7l8s+mVM3EvYw7ztQ/gjFIN3iy0NcamiQfd4eE6qjcb9Lm+63A=="],
- "@trpc/react-query": ["@trpc/react-query@11.8.1", "", { "peerDependencies": { "@tanstack/react-query": "^5.80.3", "@trpc/client": "11.8.1", "@trpc/server": "11.8.1", "react": ">=18.2.0", "react-dom": ">=18.2.0", "typescript": ">=5.7.2" } }, "sha512-0Vu55ld/oINb4U6nIPPi7eZMhxUop6K+4QUK90RVsfSD5r+957sM80M4c8bjh/JBZUxMFv9JOhxxlWcrgHxHow=="],
+ "@trpc/react-query": ["@trpc/react-query@11.7.2", "", { "peerDependencies": { "@tanstack/react-query": "^5.80.3", "@trpc/client": "11.7.2", "@trpc/server": "11.7.2", "react": ">=18.2.0", "react-dom": ">=18.2.0", "typescript": ">=5.7.2" } }, "sha512-IcLDMqx2mvlGRxkr0/m37TtPvRQ8nonITH3EwYv436x0Igx8eduR9z4tdgGBsjJY9e5W1G7cZ4zKCwrizSimFQ=="],
- "@trpc/server": ["@trpc/server@11.8.1", "", { "peerDependencies": { "typescript": ">=5.7.2" } }, "sha512-P4rzZRpEL7zDFgjxK65IdyH0e41FMFfTkQkuq0BA5tKcr7E6v9/v38DEklCpoDN6sPiB1Sigy/PUEzHENhswDA=="],
+ "@trpc/server": ["@trpc/server@11.7.2", "", { "peerDependencies": { "typescript": ">=5.7.2" } }, "sha512-AgB26PXY69sckherIhCacKLY49rxE2XP5h38vr/KMZTbLCL1p8IuIoKPjALTcugC2kbyQ7Lbqo2JDVfRSmPmfQ=="],
- "@trpc/tanstack-react-query": ["@trpc/tanstack-react-query@11.8.1", "", { "peerDependencies": { "@tanstack/react-query": "^5.80.3", "@trpc/client": "11.8.1", "@trpc/server": "11.8.1", "react": ">=18.2.0", "react-dom": ">=18.2.0", "typescript": ">=5.7.2" } }, "sha512-0gBbRmRuU9/IVZgNFJuzY7k6ktnkmqjyP78PtcUBO7EgPlBu1y2MA2TdI5GT/VtNNOOhzkVeQpJqtt+0xQ8TOQ=="],
+ "@trpc/tanstack-react-query": ["@trpc/tanstack-react-query@11.7.2", "", { "peerDependencies": { "@tanstack/react-query": "^5.80.3", "@trpc/client": "11.7.2", "@trpc/server": "11.7.2", "react": ">=18.2.0", "react-dom": ">=18.2.0", "typescript": ">=5.7.2" } }, "sha512-3XrY0b8lV0Fhj4Z2hVn1d1ZJzq2/stbc2F1e9Y6RrUWOfLmOKHlEVHYO1QfDGM6rqj66DkUj7eA593hAI0VTkQ=="],
"@ts-morph/common": ["@ts-morph/common@0.28.1", "", { "dependencies": { "minimatch": "^10.0.1", "path-browserify": "^1.0.1", "tinyglobby": "^0.2.14" } }, "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g=="],
@@ -1473,7 +1500,7 @@
"@types/nlcst": ["@types/nlcst@2.0.3", "", { "dependencies": { "@types/unist": "*" } }, "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA=="],
- "@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="],
+ "@types/node": ["@types/node@24.10.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-gqkrWUsS8hcm0r44yn7/xZeV1ERva/nLgrLxFRUGb7aoNMIJfZJ3AC261zDQuOAKC7MiXai1WCpYc48jAHoShQ=="],
"@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="],
@@ -1495,7 +1522,7 @@
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
- "@types/react-reconciler": ["@types/react-reconciler@0.28.9", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="],
+ "@types/react-reconciler": ["@types/react-reconciler@0.32.3", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-cMi5ZrLG7UtbL7LTK6hq9w/EZIRk4Mf1Z5qHoI+qBh7/WkYkFXQ7gOto2yfUvPzF5ERMAhaXS5eTQ2SAnHjLzA=="],
"@types/react-syntax-highlighter": ["@types/react-syntax-highlighter@15.5.13", "", { "dependencies": { "@types/react": "*" } }, "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA=="],
@@ -1539,7 +1566,7 @@
"@upstash/qstash": ["@upstash/qstash@2.8.4", "", { "dependencies": { "crypto-js": ">=4.2.0", "jose": "^5.2.3", "neverthrow": "^7.0.1" } }, "sha512-iojHWUlRoC3M2e4XQ1NFEgC+7Orurrm5uIrPn5WilU7LvWQoocyjYBXR0VUalXkeMAmFyk4blF0EOYZY4igdIQ=="],
- "@upstash/redis": ["@upstash/redis@1.36.0", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-9zN2UV9QJGPnXfWU3yZBLVQaqqENDh7g+Y4J2vJuSxBCi9FQ0aUOtaXlzuFhnsiZvCqM+eS27ic+tgmkWUsfOg=="],
+ "@upstash/redis": ["@upstash/redis@1.35.8", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-QqLpVCD9PCPE6hlRzOkz864nfijSdazxtyJLIy9ZeTh6kU2nBIKKfjT5HMHjIRD4BCm6TK1dbUT9pxhFjcvpng=="],
"@use-gesture/core": ["@use-gesture/core@10.3.1", "", {}, "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw=="],
@@ -1553,11 +1580,11 @@
"@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.2", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.53", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ=="],
- "@vue/compiler-core": ["@vue/compiler-core@3.5.26", "", { "dependencies": { "@babel/parser": "^7.28.5", "@vue/shared": "3.5.26", "entities": "^7.0.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w=="],
+ "@vue/compiler-core": ["@vue/compiler-core@3.5.25", "", { "dependencies": { "@babel/parser": "^7.28.5", "@vue/shared": "3.5.25", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw=="],
- "@vue/compiler-dom": ["@vue/compiler-dom@3.5.26", "", { "dependencies": { "@vue/compiler-core": "3.5.26", "@vue/shared": "3.5.26" } }, "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A=="],
+ "@vue/compiler-dom": ["@vue/compiler-dom@3.5.25", "", { "dependencies": { "@vue/compiler-core": "3.5.25", "@vue/shared": "3.5.25" } }, "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q=="],
- "@vue/shared": ["@vue/shared@3.5.26", "", {}, "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A=="],
+ "@vue/shared": ["@vue/shared@3.5.25", "", {}, "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg=="],
"@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="],
@@ -1589,7 +1616,7 @@
"@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="],
- "@webgpu/types": ["@webgpu/types@0.1.68", "", {}, "sha512-3ab1B59Ojb6RwjOspYLsTpCzbNB3ZaamIAxBMmvnNkiDoLTZUOBXZ9p5nAYVEkQlDdf6qAZWi1pqj9+ypiqznA=="],
+ "@webgpu/types": ["@webgpu/types@0.1.67", "", {}, "sha512-uk53+2ECGUkWoDFez/hymwpRfdgdIn6y1ref70fEecGMe5607f4sozNFgBk0oxlr7j2CRGWBEc3IBYMmFdGGTQ=="],
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="],
@@ -1641,7 +1668,7 @@
"aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
- "ai": ["ai@5.0.117", "", { "dependencies": { "@ai-sdk/gateway": "2.0.24", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-uE6HNkdSwxbeHGKP/YbvapwD8fMOpj87wyfT9Z00pbzOh2fpnw5acak/4kzU00SX2vtI9K0uuy+9Tf9ytw5RwA=="],
+ "ai": ["ai@5.0.112", "", { "dependencies": { "@ai-sdk/gateway": "2.0.21", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Y0dluYpe5wn81UkfHbZL78mH6CsceUfMiu4oPRaWZvjlmcoXSPdEAsPcYbOjvX8ZPvQc6m4kNZhkcEXmT2ln4w=="],
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
@@ -1697,10 +1724,14 @@
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
- "baseline-browser-mapping": ["baseline-browser-mapping@2.9.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ=="],
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.9.6", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg=="],
"bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="],
+ "better-auth": ["better-auth@1.4.9", "", { "dependencies": { "@better-auth/core": "1.4.9", "@better-auth/telemetry": "1.4.9", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.7", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.12" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-usSdjuyTzZwIvM8fjF8YGhPncxV3MAg3dHUO9uPUnf0yklXUSYISiH1+imk6/Z+UBqsscyyPRnbIyjyK97p7YA=="],
+
+ "better-call": ["better-call@1.1.7", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.7.10", "set-cookie-parser": "^2.7.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-6gaJe1bBIEgVebQu/7q9saahVzvBsGaByEnE8aDVncZEDiJO7sdNB28ot9I6iXSbR25egGmmZ6aIURXyQHRraQ=="],
+
"better-react-mathjax": ["better-react-mathjax@2.3.0", "", { "dependencies": { "mathjax-full": "^3.2.2" }, "peerDependencies": { "react": ">=16.8" } }, "sha512-K0ceQC+jQmB+NLDogO5HCpqmYf18AU2FxDbLdduYgkHYWZApFggkHE4dIaXCV1NqeoscESYXXo1GSkY6fA295w=="],
"better-sqlite3": ["better-sqlite3@12.5.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-WwCZ/5Diz7rsF29o27o0Gcc1Du+l7Zsv7SYtVPG0X3G/uUI1LqdxrQI7c9Hs2FWpqXXERjW9hp6g3/tH7DlVKg=="],
@@ -1735,7 +1766,7 @@
"builder-util-runtime": ["builder-util-runtime@9.3.1", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ=="],
- "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
+ "bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="],
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
@@ -1757,7 +1788,7 @@
"camera-controls": ["camera-controls@3.1.2", "", { "peerDependencies": { "three": ">=0.126.1" } }, "sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA=="],
- "caniuse-lite": ["caniuse-lite@1.0.30001762", "", {}, "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw=="],
+ "caniuse-lite": ["caniuse-lite@1.0.30001760", "", {}, "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
@@ -1821,7 +1852,7 @@
"code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="],
- "code-inspector-plugin": ["code-inspector-plugin@1.3.4", "", { "dependencies": { "@code-inspector/core": "1.3.4", "@code-inspector/esbuild": "1.3.4", "@code-inspector/mako": "1.3.4", "@code-inspector/turbopack": "1.3.4", "@code-inspector/vite": "1.3.4", "@code-inspector/webpack": "1.3.4", "chalk": "4.1.1" } }, "sha512-735rAAc655oSAMd/6+PIsjpgB5jwugDISom9WFwhNUbOuFHiL2PYwshMmfIhAtOgECl+7g6o50rBIIYwCEa8xg=="],
+ "code-inspector-plugin": ["code-inspector-plugin@1.3.2", "", { "dependencies": { "@code-inspector/core": "1.3.2", "@code-inspector/esbuild": "1.3.2", "@code-inspector/mako": "1.3.2", "@code-inspector/turbopack": "1.3.2", "@code-inspector/vite": "1.3.2", "@code-inspector/webpack": "1.3.2", "chalk": "4.1.1" } }, "sha512-cnS4OlrHPI1xEj8H2efWVBsV9i8pJJYHHjZdjz/qSt6BVyJjvVkkTXI5Hl4I7vTgoAam1h4xTuEDkwisDQy2Xg=="],
"collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="],
@@ -1855,7 +1886,7 @@
"convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
- "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
+ "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
@@ -1985,6 +2016,8 @@
"define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
+ "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
+
"delaunator": ["delaunator@5.0.1", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw=="],
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
@@ -2093,7 +2126,7 @@
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
- "es-toolkit": ["es-toolkit@1.43.0", "", {}, "sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA=="],
+ "es-toolkit": ["es-toolkit@1.42.0", "", {}, "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA=="],
"es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="],
@@ -2159,17 +2192,15 @@
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
- "fast-equals": ["fast-equals@5.4.0", "", {}, "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw=="],
+ "fast-equals": ["fast-equals@5.3.3", "", {}, "sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw=="],
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
- "fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="],
-
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
- "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
+ "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
"fault": ["fault@1.0.4", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA=="],
@@ -2383,7 +2414,7 @@
"ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
- "ink": ["ink@6.6.0", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.2.1", "ansi-escapes": "^7.2.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.6.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^5.1.1", "code-excerpt": "^4.0.0", "es-toolkit": "^1.39.10", "indent-string": "^5.0.0", "is-in-ci": "^2.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.33.0", "signal-exit": "^3.0.7", "slice-ansi": "^7.1.0", "stack-utils": "^2.0.6", "string-width": "^8.1.0", "type-fest": "^4.27.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=19.0.0", "react": ">=19.0.0", "react-devtools-core": "^6.1.2" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-QDt6FgJxgmSxAelcOvOHUvFxbIUjVpCH5bx+Slvc5m7IEcpGt3dYwbz/L+oRnqEGeRvwy1tineKK4ect3nW1vQ=="],
+ "ink": ["ink@6.5.1", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.2.1", "ansi-escapes": "^7.2.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.6.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^5.1.1", "code-excerpt": "^4.0.0", "es-toolkit": "^1.39.10", "indent-string": "^5.0.0", "is-in-ci": "^2.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.33.0", "signal-exit": "^3.0.7", "slice-ansi": "^7.1.0", "stack-utils": "^2.0.6", "string-width": "^8.1.0", "type-fest": "^4.27.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=19.0.0", "react": ">=19.0.0", "react-devtools-core": "^6.1.2" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-wF3j/DmkM8q5E+OtfdQhCRw8/0ahkc8CUTgEddxZzpEWPslu7YPL3t64MWRoI9m6upVGpfAg4ms2BBvxCdKRLQ=="],
"ink-select-input": ["ink-select-input@6.2.0", "", { "dependencies": { "figures": "^6.1.0", "to-rotated": "^1.0.0" }, "peerDependencies": { "ink": ">=5.0.0", "react": ">=18.0.0" } }, "sha512-304fZXxkpYxJ9si5lxRCaX01GNlmPBgOZumXXRnPYbHW/iI31cgQynqk2tRypGLOF1cMIwPUzL2LSm6q4I5rQQ=="],
@@ -2479,8 +2510,6 @@
"js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="],
- "js-cookie": ["js-cookie@3.0.5", "", {}, "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="],
-
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
@@ -2511,9 +2540,11 @@
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
+ "kysely": ["kysely@0.28.9", "", {}, "sha512-3BeXMoiOhpOwu62CiVpO6lxfq4eS6KMYfQdMsN/2kUCRNuF2YiEr7u0HLHaQU+O4Xu8YXE3bHVkwaQ85i72EuA=="],
+
"langium": ["langium@3.3.1", "", { "dependencies": { "chevrotain": "~11.0.3", "chevrotain-allstar": "~0.3.0", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.0.8" } }, "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w=="],
- "launch-ide": ["launch-ide@1.3.1", "", { "dependencies": { "chalk": "^4.1.1", "dotenv": "^16.1.4" } }, "sha512-opTthrpkuhi1Y8yFn6TWUeycyiI1aiZpVuTV4HQFUfVut7nMYGr5nQ8heYHrRJH2KYISLVYwz+QFRNZxFlbQmA=="],
+ "launch-ide": ["launch-ide@1.3.0", "", { "dependencies": { "chalk": "^4.1.1", "dotenv": "^16.1.4" } }, "sha512-pxiF+HVNMV0dDc6Z0q89RDmzMF9XmSGaOn4ueTegjMy3cUkezc3zrki5PCiz68zZIqAuhW7iwoWX7JO4Kn6B0A=="],
"layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
@@ -2557,7 +2588,7 @@
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
- "lodash-es": ["lodash-es@4.17.22", "", {}, "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q=="],
+ "lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
"lodash.chunk": ["lodash.chunk@4.2.0", "", {}, "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="],
@@ -2791,6 +2822,8 @@
"nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
+ "nanostores": ["nanostores@1.1.0", "", {}, "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA=="],
+
"napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
@@ -2799,7 +2832,7 @@
"neverthrow": ["neverthrow@7.2.0", "", {}, "sha512-iGBUfFB7yPczHHtA8dksKTJ9E8TESNTAx1UQWW6TzMF280vo9jdPYpLUXrMN1BCkPdHFdNG3fxOt2CUad8KhAw=="],
- "next": ["next@16.1.1", "", { "dependencies": { "@next/env": "16.1.1", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.1.1", "@next/swc-darwin-x64": "16.1.1", "@next/swc-linux-arm64-gnu": "16.1.1", "@next/swc-linux-arm64-musl": "16.1.1", "@next/swc-linux-x64-gnu": "16.1.1", "@next/swc-linux-x64-musl": "16.1.1", "@next/swc-win32-arm64-msvc": "16.1.1", "@next/swc-win32-x64-msvc": "16.1.1", "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" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w=="],
+ "next": ["next@16.0.10", "", { "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" }, "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" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA=="],
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
@@ -2939,7 +2972,7 @@
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
- "postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
+ "postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
"postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
@@ -2947,13 +2980,13 @@
"posthog-js": ["posthog-js@1.310.1", "", { "dependencies": { "@posthog/core": "1.9.0", "core-js": "^3.38.1", "fflate": "^0.4.8", "preact": "^10.19.3", "web-vitals": "^4.2.4" } }, "sha512-UkR6zzlWNtqHDXHJl2Yk062DOmZyVKTPL5mX4j4V+u3RiYbMHJe47+PpMMUsvK1R2e1r/m9uSlHaJMJRzyUjGg=="],
- "posthog-node": ["posthog-node@5.18.1", "", { "dependencies": { "@posthog/core": "1.9.0" } }, "sha512-Hi7cRqAlvuEitdiurXJFdMip+BxcwYoX66at5RErMVP91V+Ph9BspGiawC3mJx/4znjwUjF29kAhf8oZQ2uJ5Q=="],
+ "posthog-node": ["posthog-node@5.18.0", "", { "dependencies": { "@posthog/core": "1.9.0" } }, "sha512-SLBEs+sCThxzTGSSDEe97nZHuFFYh6DupObR1yQdvQND3CJh0ogZ0Sa1Vb+Tbrnf0cWbfBC9XNkm44yhaWf3aA=="],
"postject": ["postject@1.0.0-alpha.6", "", { "dependencies": { "commander": "^9.4.0" }, "bin": { "postject": "dist/cli.js" } }, "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A=="],
"potpack": ["potpack@1.0.2", "", {}, "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ=="],
- "preact": ["preact@10.28.1", "", {}, "sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw=="],
+ "preact": ["preact@10.28.0", "", {}, "sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA=="],
"prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
@@ -2987,7 +3020,7 @@
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
- "qs": ["qs@6.14.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ=="],
+ "qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
@@ -3009,7 +3042,7 @@
"react-compiler-runtime": ["react-compiler-runtime@19.1.0-rc.1-rc-af1b7da-20250421", "", { "peerDependencies": { "react": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental" } }, "sha512-Til/juI+Zfq+eYpGYn9lFxqW5RyJDs3ThOxmg0757aMrPpfx/Zb0SnGMVJhF3vw+bEQjJiD+xPFD3+kE0WbyeA=="],
- "react-day-picker": ["react-day-picker@9.13.0", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "date-fns": "^4.1.0", "date-fns-jalali": "^4.1.0-0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-euzj5Hlq+lOHqI53NiuNhCP8HWgsPf/bBAVijR50hNaY1XwjKjShAnIe8jm8RD2W9IJUvihDIZ+KrmqfFzNhFQ=="],
+ "react-day-picker": ["react-day-picker@9.12.0", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "date-fns": "^4.1.0", "date-fns-jalali": "^4.1.0-0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-t8OvG/Zrciso5CQJu5b1A7yzEmebvST+S3pOVQJWxwjjVngyG/CA2htN/D15dLI4uTEuLLkbZyS4YYt480FAtA=="],
"react-devtools-core": ["react-devtools-core@7.0.1", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-C3yNvRHaizlpiASzy7b9vbnBGLrhvdhl1CbdU6EnZgxPNbai60szdLtl+VL76UNOt5bOoVTOz5rNWZxgGt+Gsw=="],
@@ -3027,7 +3060,9 @@
"react-fast-marquee": ["react-fast-marquee@1.6.5", "", { "peerDependencies": { "react": ">= 16.8.0 || ^18.0.0", "react-dom": ">= 16.8.0 || ^18.0.0" } }, "sha512-swDnPqrT2XISAih0o74zQVE2wQJFMvkx+9VZXYYNSLb/CUcAzU9pNj637Ar2+hyRw6b4tP6xh4GQZip2ZCpQpg=="],
- "react-hook-form": ["react-hook-form@7.69.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-yt6ZGME9f4F6WHwevrvpAjh42HMvocuSnSIHUGycBqXIJdhqGSPQzTpGF+1NLREk/58IdPxEMfPcFCjlMhclGw=="],
+ "react-hook-form": ["react-hook-form@7.68.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-oNN3fjrZ/Xo40SWlHf1yCjlMK417JxoSJVUXQjGdvdRCU07NTFei1i1f8ApUAts+IVh14e4EdakeLEA+BEAs/Q=="],
+
+ "react-hotkeys-hook": ["react-hotkeys-hook@5.2.1", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg=="],
"react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="],
@@ -3049,9 +3084,9 @@
"react-resizable-panels": ["react-resizable-panels@3.0.6", "", { "peerDependencies": { "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-b3qKHQ3MLqOgSS+FRYKapNkJZf5EQzuf6+RLiq1/IlTHw99YrZ2NJZLk4hQIzTnnIkRg2LUqyVinu6YWWpUYew=="],
- "react-router": ["react-router@7.11.0", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-uI4JkMmjbWCZc01WVP2cH7ZfSzH91JAZUDd7/nIprDgWxBV1TkkmLToFh7EbMTcMak8URFRa2YoBL/W8GWnCTQ=="],
+ "react-router": ["react-router@7.10.1", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw=="],
- "react-router-dom": ["react-router-dom@7.11.0", "", { "dependencies": { "react-router": "7.11.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-e49Ir/kMGRzFOOrYQBdoitq3ULigw4lKbAyKusnvtDu2t4dBX4AGYPrzNvorXmVuOyeakai6FUPW5MmibvVG8g=="],
+ "react-router-dom": ["react-router-dom@7.10.1", "", { "dependencies": { "react-router": "7.10.1" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-JNBANI6ChGVjA5bwsUIwJk7LHKmqB4JYnYfzFwyp2t12Izva11elds2jx7Yfoup2zssedntwU0oZ5DEmk5Sdaw=="],
"react-smooth": ["react-smooth@4.0.4", "", { "dependencies": { "fast-equals": "^5.0.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q=="],
@@ -3195,10 +3230,12 @@
"robust-predicates": ["robust-predicates@3.0.2", "", {}, "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="],
- "rollup": ["rollup@4.54.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.54.0", "@rollup/rollup-android-arm64": "4.54.0", "@rollup/rollup-darwin-arm64": "4.54.0", "@rollup/rollup-darwin-x64": "4.54.0", "@rollup/rollup-freebsd-arm64": "4.54.0", "@rollup/rollup-freebsd-x64": "4.54.0", "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", "@rollup/rollup-linux-arm-musleabihf": "4.54.0", "@rollup/rollup-linux-arm64-gnu": "4.54.0", "@rollup/rollup-linux-arm64-musl": "4.54.0", "@rollup/rollup-linux-loong64-gnu": "4.54.0", "@rollup/rollup-linux-ppc64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-musl": "4.54.0", "@rollup/rollup-linux-s390x-gnu": "4.54.0", "@rollup/rollup-linux-x64-gnu": "4.54.0", "@rollup/rollup-linux-x64-musl": "4.54.0", "@rollup/rollup-openharmony-arm64": "4.54.0", "@rollup/rollup-win32-arm64-msvc": "4.54.0", "@rollup/rollup-win32-ia32-msvc": "4.54.0", "@rollup/rollup-win32-x64-gnu": "4.54.0", "@rollup/rollup-win32-x64-msvc": "4.54.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw=="],
+ "rollup": ["rollup@4.53.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.53.3", "@rollup/rollup-android-arm64": "4.53.3", "@rollup/rollup-darwin-arm64": "4.53.3", "@rollup/rollup-darwin-x64": "4.53.3", "@rollup/rollup-freebsd-arm64": "4.53.3", "@rollup/rollup-freebsd-x64": "4.53.3", "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", "@rollup/rollup-linux-arm-musleabihf": "4.53.3", "@rollup/rollup-linux-arm64-gnu": "4.53.3", "@rollup/rollup-linux-arm64-musl": "4.53.3", "@rollup/rollup-linux-loong64-gnu": "4.53.3", "@rollup/rollup-linux-ppc64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-musl": "4.53.3", "@rollup/rollup-linux-s390x-gnu": "4.53.3", "@rollup/rollup-linux-x64-gnu": "4.53.3", "@rollup/rollup-linux-x64-musl": "4.53.3", "@rollup/rollup-openharmony-arm64": "4.53.3", "@rollup/rollup-win32-arm64-msvc": "4.53.3", "@rollup/rollup-win32-ia32-msvc": "4.53.3", "@rollup/rollup-win32-x64-gnu": "4.53.3", "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA=="],
"rollup-plugin-inject-process-env": ["rollup-plugin-inject-process-env@1.3.1", "", { "dependencies": { "magic-string": "^0.25.7" } }, "sha512-kKDoL30IZr0wxbNVJjq+OS92RJSKRbKV6B5eNW4q3mZTFqoWDh6lHy+mPDYuuGuERFNKXkG+AKxvYqC9+DRpKQ=="],
+ "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="],
+
"roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
@@ -3225,13 +3262,13 @@
"semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="],
- "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
+ "send": ["send@1.2.0", "", { "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.0", "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.1" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="],
"serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="],
"serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="],
- "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
+ "serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="],
"server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="],
@@ -3267,7 +3304,7 @@
"sherif-windows-x64": ["sherif-windows-x64@1.9.0", "", { "os": "win32", "cpu": "x64" }, "sha512-3cL+XVGLpmyLC3UOZYiPr4vY2OFBQqPZnCoCwoRKN+ONm8VfGMirO9iqI0OckgFBUtJoG4AQY/MWxoPhNmzD8A=="],
- "shiki": ["shiki@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/engine-javascript": "3.20.0", "@shikijs/engine-oniguruma": "3.20.0", "@shikijs/langs": "3.20.0", "@shikijs/themes": "3.20.0", "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg=="],
+ "shiki": ["shiki@3.19.0", "", { "dependencies": { "@shikijs/core": "3.19.0", "@shikijs/engine-javascript": "3.19.0", "@shikijs/engine-oniguruma": "3.19.0", "@shikijs/langs": "3.19.0", "@shikijs/themes": "3.19.0", "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-77VJr3OR/VUZzPiStyRhADmO2jApMM0V2b1qf0RpfWya8Zr1PeZev5AEpPGAAKWdiYUtcZGBE4F5QvJml1PvWA=="],
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
@@ -3329,8 +3366,6 @@
"stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="],
- "standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="],
-
"stat-mode": ["stat-mode@1.0.0", "", {}, "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg=="],
"state-local": ["state-local@1.0.7", "", {}, "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="],
@@ -3341,8 +3376,6 @@
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
- "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
-
"steno": ["steno@4.0.2", "", {}, "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A=="],
"streamdown": ["streamdown@1.6.10", "", { "dependencies": { "clsx": "^2.1.1", "hast": "^1.0.0", "hast-util-to-jsx-runtime": "^2.3.6", "html-url-attributes": "^3.0.1", "katex": "^0.16.22", "lucide-react": "^0.542.0", "marked": "^16.2.1", "mermaid": "^11.11.0", "rehype-harden": "^1.1.6", "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", "remark-cjk-friendly": "^1.2.3", "remark-cjk-friendly-gfm-strikethrough": "^1.2.3", "remark-gfm": "^4.0.1", "remark-math": "^6.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remend": "1.0.1", "shiki": "^3.12.2", "tailwind-merge": "^3.3.1", "unified": "^11.0.5", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-B4Y3Z/qiXl1Dc+LzAB5c52Cd1QGRiFjaDwP+ERoj1JtCykdRDM8X6HwQnn3YkpkSk0x3R7S/6LrGe1nQiElHQQ=="],
@@ -3385,11 +3418,9 @@
"suspend-react": ["suspend-react@0.1.3", "", { "peerDependencies": { "react": ">=17.0" } }, "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ=="],
- "swr": ["swr@2.3.4", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg=="],
-
"system-architecture": ["system-architecture@0.1.0", "", {}, "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA=="],
- "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
+ "tabbable": ["tabbable@6.3.0", "", {}, "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ=="],
"tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="],
@@ -3477,25 +3508,25 @@
"tunnel-rat": ["tunnel-rat@0.1.2", "", { "dependencies": { "zustand": "^4.3.2" } }, "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ=="],
- "turbo": ["turbo@2.7.2", "", { "optionalDependencies": { "turbo-darwin-64": "2.7.2", "turbo-darwin-arm64": "2.7.2", "turbo-linux-64": "2.7.2", "turbo-linux-arm64": "2.7.2", "turbo-windows-64": "2.7.2", "turbo-windows-arm64": "2.7.2" }, "bin": { "turbo": "bin/turbo" } }, "sha512-5JIA5aYBAJSAhrhbyag1ZuMSgUZnHtI+Sq3H8D3an4fL8PeF+L1yYvbEJg47akP1PFfATMf5ehkqFnxfkmuwZQ=="],
+ "turbo": ["turbo@2.6.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.6.3", "turbo-darwin-arm64": "2.6.3", "turbo-linux-64": "2.6.3", "turbo-linux-arm64": "2.6.3", "turbo-windows-64": "2.6.3", "turbo-windows-arm64": "2.6.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-bf6YKUv11l5Xfcmg76PyWoy/e2vbkkxFNBGJSnfdSXQC33ZiUfutYh6IXidc5MhsnrFkWfdNNLyaRk+kHMLlwA=="],
- "turbo-darwin-64": ["turbo-darwin-64@2.7.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-dxY3X6ezcT5vm3coK6VGixbrhplbQMwgNsCsvZamS/+/6JiebqW9DKt4NwpgYXhDY2HdH00I7FWs3wkVuan4rA=="],
+ "turbo-darwin-64": ["turbo-darwin-64@2.6.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-BlJJDc1CQ7SK5Y5qnl7AzpkvKSnpkfPmnA+HeU/sgny3oHZckPV2776ebO2M33CYDSor7+8HQwaodY++IINhYg=="],
- "turbo-darwin-arm64": ["turbo-darwin-arm64@2.7.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1bXmuwPLqNFt3mzrtYcVx1sdJ8UYb124Bf48nIgcpMCGZy3kDhgxNv1503kmuK/37OGOZbsWSQFU4I08feIuSg=="],
+ "turbo-darwin-arm64": ["turbo-darwin-arm64@2.6.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MwVt7rBKiOK7zdYerenfCRTypefw4kZCue35IJga9CH1+S50+KTiCkT6LBqo0hHeoH2iKuI0ldTF2a0aB72z3w=="],
- "turbo-linux-64": ["turbo-linux-64@2.7.2", "", { "os": "linux", "cpu": "x64" }, "sha512-kP+TiiMaiPugbRlv57VGLfcjFNsFbo8H64wMBCPV2270Or2TpDCBULMzZrvEsvWFjT3pBFvToYbdp8/Kw0jAQg=="],
+ "turbo-linux-64": ["turbo-linux-64@2.6.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cqpcw+dXxbnPtNnzeeSyWprjmuFVpHJqKcs7Jym5oXlu/ZcovEASUIUZVN3OGEM6Y/OTyyw0z09tOHNt5yBAVg=="],
- "turbo-linux-arm64": ["turbo-linux-arm64@2.7.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-VDJwQ0+8zjAfbyY6boNaWfP6RIez4ypKHxwkuB6SrWbOSk+vxTyW5/hEjytTwK8w/TsbKVcMDyvpora8tEsRFw=="],
+ "turbo-linux-arm64": ["turbo-linux-arm64@2.6.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-MterpZQmjXyr4uM7zOgFSFL3oRdNKeflY7nsjxJb2TklsYqiu3Z9pQ4zRVFFH8n0mLGna7MbQMZuKoWqqHb45w=="],
- "turbo-windows-64": ["turbo-windows-64@2.7.2", "", { "os": "win32", "cpu": "x64" }, "sha512-rPjqQXVnI6A6oxgzNEE8DNb6Vdj2Wwyhfv3oDc+YM3U9P7CAcBIlKv/868mKl4vsBtz4ouWpTQNXG8vljgJO+w=="],
+ "turbo-windows-64": ["turbo-windows-64@2.6.3", "", { "os": "win32", "cpu": "x64" }, "sha512-biDU70v9dLwnBdLf+daoDlNJVvqOOP8YEjqNipBHzgclbQlXbsi6Gqqelp5er81Qo3BiRgmTNx79oaZQTPb07Q=="],
- "turbo-windows-arm64": ["turbo-windows-arm64@2.7.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-tcnHvBhO515OheIFWdxA+qUvZzNqqcHbLVFc1+n+TJ1rrp8prYicQtbtmsiKgMvr/54jb9jOabU62URAobnB7g=="],
+ "turbo-windows-arm64": ["turbo-windows-arm64@2.6.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-dDHVKpSeukah3VsI/xMEKeTnV9V9cjlpFSUs4bmsUiLu3Yv2ENlgVEZv65wxbeE0bh0jjpmElDT+P1KaCxArQQ=="],
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
- "twoslash": ["twoslash@0.3.6", "", { "dependencies": { "@typescript/vfs": "^1.6.2", "twoslash-protocol": "0.3.6" }, "peerDependencies": { "typescript": "^5.5.0" } }, "sha512-VuI5OKl+MaUO9UIW3rXKoPgHI3X40ZgB/j12VY6h98Ae1mCBihjPvhOPeJWlxCYcmSbmeZt5ZKkK0dsVtp+6pA=="],
+ "twoslash": ["twoslash@0.3.4", "", { "dependencies": { "@typescript/vfs": "^1.6.1", "twoslash-protocol": "0.3.4" }, "peerDependencies": { "typescript": "^5.5.0" } }, "sha512-RtJURJlGRxrkJmTcZMjpr7jdYly1rfgpujJr1sBM9ch7SKVht/SjFk23IOAyvwT1NLCk+SJiMrvW4rIAUM2Wug=="],
- "twoslash-protocol": ["twoslash-protocol@0.3.6", "", {}, "sha512-FHGsJ9Q+EsNr5bEbgG3hnbkvEBdW5STgPU824AHUjB4kw0Dn4p8tABT7Ncg1Ie6V0+mDg3Qpy41VafZXcQhWMA=="],
+ "twoslash-protocol": ["twoslash-protocol@0.3.4", "", {}, "sha512-HHd7lzZNLUvjPzG/IE6js502gEzLC1x7HaO1up/f72d8G8ScWAs9Yfa97igelQRDl5h9tGcdFsRp+lNVre1EeQ=="],
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
@@ -3551,7 +3582,7 @@
"unplugin": ["unplugin@1.0.1", "", { "dependencies": { "acorn": "^8.8.1", "chokidar": "^3.5.3", "webpack-sources": "^3.2.3", "webpack-virtual-modules": "^0.5.0" } }, "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA=="],
- "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
+ "update-browserslist-db": ["update-browserslist-db@1.2.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA=="],
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
@@ -3587,7 +3618,7 @@
"victory-vendor": ["victory-vendor@36.9.2", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="],
- "vite": ["vite@7.3.0", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg=="],
+ "vite": ["vite@7.2.7", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ=="],
"vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="],
@@ -3603,7 +3634,7 @@
"vscode-uri": ["vscode-uri@3.0.8", "", {}, "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="],
- "watchpack": ["watchpack@2.5.0", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA=="],
+ "watchpack": ["watchpack@2.4.4", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA=="],
"wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
@@ -3661,7 +3692,7 @@
"yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
- "zod": ["zod@4.3.4", "", {}, "sha512-Zw/uYiiyF6pUT1qmKbZziChgNPRu+ZRneAsMUDU6IwmXdWt5JwcUfy2bvLOCUtz5UniaN/Zx5aFttZYbYc7O/A=="],
+ "zod": ["zod@4.1.13", "", {}, "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig=="],
"zustand": ["zustand@5.0.9", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-ALBtUj0AfjJt3uNRQoL1tL2tMvj6Gp/6e39dnfT6uzpelGru8v1tPOGBzayOWbPJvujM8JojDk3E1LxeFisBNg=="],
@@ -3673,12 +3704,6 @@
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
- "@chevrotain/cst-dts-gen/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
-
- "@chevrotain/gast/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
-
- "@clerk/shared/csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
-
"@code-inspector/core/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@code-inspector/core/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
@@ -3707,9 +3732,9 @@
"@electron/rebuild/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
- "@electron/universal/fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="],
+ "@electron/universal/fs-extra": ["fs-extra@11.3.2", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A=="],
- "@electron/windows-sign/fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="],
+ "@electron/windows-sign/fs-extra": ["fs-extra@11.3.2", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A=="],
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
@@ -3721,7 +3746,7 @@
"@mdx-js/mdx/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
- "@neondatabase/serverless/@types/node": ["@types/node@22.19.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA=="],
+ "@neondatabase/serverless/@types/node": ["@types/node@22.19.2", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw=="],
"@npmcli/move-file/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
@@ -3759,6 +3784,10 @@
"@react-three/drei/cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="],
+ "@react-three/fiber/react-reconciler": ["react-reconciler@0.31.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ=="],
+
+ "@react-three/fiber/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="],
+
"@sentry-internal/feedback/@sentry/core": ["@sentry/core@10.29.0", "", {}, "sha512-olQ2DU9dA/Bwsz3PtA9KNXRMqBWRQSkPw+MxwWEoU1K1qtiM9L0j6lbEFb5iSY3d7WYD5MB+1d5COugjSBrHtw=="],
"@sentry-internal/replay/@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.29.0", "", { "dependencies": { "@sentry/core": "10.29.0" } }, "sha512-M3kycMY6f3KY9a8jDYac+yG0E3ZgWVWSxlOEC5MhYyX+g7mqxkwrb3LFQyuxSm/m+CCgMTCaPOOaB2twXP6EQg=="],
@@ -3793,7 +3822,7 @@
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
- "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
+ "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.0", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA=="],
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
@@ -3809,7 +3838,7 @@
"@upstash/qstash/jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="],
- "@vue/compiler-core/entities": ["entities@7.0.0", "", {}, "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ=="],
+ "@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@xyflow/react/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="],
@@ -3845,8 +3874,6 @@
"camelcase-keys/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="],
- "chevrotain/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
-
"clipboardy/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
"cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
@@ -3879,11 +3906,9 @@
"dir-compare/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
- "dom-helpers/csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
-
"dotenv-expand/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
- "electron/@types/node": ["@types/node@22.19.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA=="],
+ "electron/@types/node": ["@types/node@22.19.2", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw=="],
"electron-builder/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
@@ -3897,8 +3922,6 @@
"execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
- "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
-
"extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
"filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
@@ -3921,6 +3944,8 @@
"iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="],
+ "its-fine/@types/react-reconciler": ["@types/react-reconciler@0.28.9", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="],
+
"jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
"katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
@@ -3953,8 +3978,6 @@
"meow/type-fest": ["type-fest@3.13.1", "", {}, "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g=="],
- "mermaid/dompurify": ["dompurify@3.3.1", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q=="],
-
"mermaid/marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
"mermaid/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
@@ -4003,8 +4026,6 @@
"prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
- "randombytes/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
-
"raw-body/iconv-lite": ["iconv-lite@0.7.1", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw=="],
"react-arborist/react-dnd": ["react-dnd@14.0.5", "", { "dependencies": { "@react-dnd/invariant": "^2.0.0", "@react-dnd/shallowequal": "^2.0.0", "dnd-core": "14.0.1", "fast-deep-equal": "^3.1.3", "hoist-non-react-statics": "^3.3.2" }, "peerDependencies": { "@types/hoist-non-react-statics": ">= 3.3.1", "@types/node": ">= 12", "@types/react": ">= 16", "react": ">= 16.14" }, "optionalPeers": ["@types/hoist-non-react-statics", "@types/node", "@types/react"] }, "sha512-9i1jSgbyVw0ELlEVt/NkCUkxy1hmhJOkePoCH713u75vzHGyXhPDm28oLfc2NMSBjZRM1Y+wRjHXJT3sPrTy+A=="],
@@ -4017,6 +4038,8 @@
"react-mosaic-component/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
+ "react-router/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
+
"read-pkg/normalize-package-data": ["normalize-package-data@3.0.3", "", { "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" } }, "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA=="],
"read-pkg/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="],
@@ -4083,14 +4106,10 @@
"tiny-async-pool/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
- "tsx/esbuild": ["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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
-
- "tunnel-agent/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+ "tsx/esbuild": ["esbuild@0.27.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.1", "@esbuild/android-arm": "0.27.1", "@esbuild/android-arm64": "0.27.1", "@esbuild/android-x64": "0.27.1", "@esbuild/darwin-arm64": "0.27.1", "@esbuild/darwin-x64": "0.27.1", "@esbuild/freebsd-arm64": "0.27.1", "@esbuild/freebsd-x64": "0.27.1", "@esbuild/linux-arm": "0.27.1", "@esbuild/linux-arm64": "0.27.1", "@esbuild/linux-ia32": "0.27.1", "@esbuild/linux-loong64": "0.27.1", "@esbuild/linux-mips64el": "0.27.1", "@esbuild/linux-ppc64": "0.27.1", "@esbuild/linux-riscv64": "0.27.1", "@esbuild/linux-s390x": "0.27.1", "@esbuild/linux-x64": "0.27.1", "@esbuild/netbsd-arm64": "0.27.1", "@esbuild/netbsd-x64": "0.27.1", "@esbuild/openbsd-arm64": "0.27.1", "@esbuild/openbsd-x64": "0.27.1", "@esbuild/openharmony-arm64": "0.27.1", "@esbuild/sunos-x64": "0.27.1", "@esbuild/win32-arm64": "0.27.1", "@esbuild/win32-ia32": "0.27.1", "@esbuild/win32-x64": "0.27.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA=="],
"tunnel-rat/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="],
- "vite/esbuild": ["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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
-
"webpack/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
"widest-line/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
@@ -4191,8 +4210,6 @@
"ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
- "bl/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
-
"builder-util/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"cacache/glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
@@ -4293,113 +4310,59 @@
"string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
- "tar-stream/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
-
"temp/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
- "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
-
- "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="],
-
- "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="],
-
- "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="],
-
- "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="],
-
- "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="],
-
- "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="],
-
- "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="],
+ "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA=="],
- "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="],
+ "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.1", "", { "os": "android", "cpu": "arm" }, "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg=="],
- "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="],
+ "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.1", "", { "os": "android", "cpu": "arm64" }, "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ=="],
- "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="],
+ "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.1", "", { "os": "android", "cpu": "x64" }, "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ=="],
- "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="],
+ "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ=="],
- "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="],
+ "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ=="],
- "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="],
+ "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg=="],
- "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="],
+ "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ=="],
- "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="],
+ "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.1", "", { "os": "linux", "cpu": "arm" }, "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA=="],
- "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="],
+ "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q=="],
- "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="],
+ "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw=="],
- "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="],
+ "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg=="],
- "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="],
+ "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA=="],
- "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="],
+ "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ=="],
- "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="],
+ "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ=="],
- "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="],
+ "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw=="],
- "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="],
+ "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.1", "", { "os": "linux", "cpu": "x64" }, "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA=="],
- "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="],
+ "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.1", "", { "os": "none", "cpu": "arm64" }, "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ=="],
- "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="],
+ "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.1", "", { "os": "none", "cpu": "x64" }, "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg=="],
- "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
+ "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g=="],
- "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="],
+ "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg=="],
- "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="],
+ "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg=="],
- "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="],
+ "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA=="],
- "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="],
+ "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg=="],
- "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="],
+ "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ=="],
- "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="],
-
- "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="],
-
- "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="],
-
- "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="],
-
- "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="],
-
- "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="],
-
- "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="],
-
- "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="],
-
- "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="],
-
- "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="],
-
- "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="],
-
- "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="],
-
- "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="],
-
- "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="],
-
- "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="],
-
- "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="],
-
- "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="],
-
- "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="],
-
- "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="],
-
- "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="],
+ "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.1", "", { "os": "win32", "cpu": "x64" }, "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw=="],
"webpack/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
@@ -4423,8 +4386,6 @@
"@uiw/react-markdown-preview/rehype-prism-plus/refractor/hastscript": ["hastscript@7.2.0", "", { "dependencies": { "@types/hast": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^3.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw=="],
- "bl/readable-stream/string_decoder/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
-
"cacache/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"clipboardy/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
@@ -4461,8 +4422,6 @@
"rehype-prism-plus/refractor/hastscript/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="],
- "tar-stream/readable-stream/string_decoder/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
-
"temp/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
diff --git a/opencode.json b/opencode.json
deleted file mode 100644
index f06f35457..000000000
--- a/opencode.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "$schema": "https://opencode.ai/config.json",
- "permission": {
- "external_directory": "allow"
- }
-}
diff --git a/packages/auth/package.json b/packages/auth/package.json
new file mode 100644
index 000000000..75c35148f
--- /dev/null
+++ b/packages/auth/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@superset/auth",
+ "version": "0.1.0",
+ "private": true,
+ "type": "module",
+ "exports": {
+ ".": {
+ "types": "./src/index.ts",
+ "default": "./src/index.ts"
+ },
+ "./client": {
+ "types": "./src/client.ts",
+ "default": "./src/client.ts"
+ }
+ },
+ "scripts": {
+ "clean": "git clean -xdf .cache .turbo dist node_modules",
+ "typecheck": "tsc --noEmit --emitDeclarationOnly false"
+ },
+ "dependencies": {
+ "@superset/db": "workspace:*",
+ "@t3-oss/env-core": "^0.13.8",
+ "@t3-oss/env-nextjs": "^0.13.8",
+ "better-auth": "^1.4.9",
+ "dotenv": "^17.2.3",
+ "drizzle-orm": "0.45.1",
+ "zod": "^4.1.13"
+ },
+ "devDependencies": {
+ "@superset/typescript": "workspace:*",
+ "@types/node": "^24.9.1",
+ "typescript": "^5.9.3"
+ }
+}
diff --git a/packages/auth/src/client.ts b/packages/auth/src/client.ts
new file mode 100644
index 000000000..ff1c1b8d7
--- /dev/null
+++ b/packages/auth/src/client.ts
@@ -0,0 +1,9 @@
+"use client";
+
+import { organizationClient } from "better-auth/client/plugins";
+import { createAuthClient } from "better-auth/react";
+
+export const authClient = createAuthClient({
+ baseURL: process.env.NEXT_PUBLIC_API_URL,
+ plugins: [organizationClient()],
+});
diff --git a/packages/auth/src/env.ts b/packages/auth/src/env.ts
new file mode 100644
index 000000000..3f47ba0f5
--- /dev/null
+++ b/packages/auth/src/env.ts
@@ -0,0 +1,27 @@
+import path from "node:path";
+import { createEnv } from "@t3-oss/env-core";
+import { config } from "dotenv";
+import { z } from "zod";
+
+config({ path: path.resolve(process.cwd(), "../../../.env") });
+
+export const env = createEnv({
+ server: {
+ GH_CLIENT_ID: z.string(),
+ GH_CLIENT_SECRET: z.string(),
+ GOOGLE_CLIENT_ID: z.string(),
+ GOOGLE_CLIENT_SECRET: z.string(),
+ BETTER_AUTH_SECRET: z.string(),
+ },
+ clientPrefix: "NEXT_PUBLIC_",
+ client: {
+ NEXT_PUBLIC_COOKIE_DOMAIN: z.string(),
+ NEXT_PUBLIC_API_URL: z.string().url(),
+ NEXT_PUBLIC_WEB_URL: z.string().url(),
+ NEXT_PUBLIC_ADMIN_URL: z.string().url(),
+ NEXT_PUBLIC_MARKETING_URL: z.string().url(),
+ },
+ runtimeEnv: process.env,
+ emptyStringAsUndefined: true,
+ skipValidation: true,
+});
diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts
new file mode 100644
index 000000000..6a5482bb0
--- /dev/null
+++ b/packages/auth/src/index.ts
@@ -0,0 +1,104 @@
+import { db } from "@superset/db/client";
+import { members } from "@superset/db/schema";
+import * as authSchema from "@superset/db/schema/auth";
+import { betterAuth } from "better-auth";
+import { drizzleAdapter } from "better-auth/adapters/drizzle";
+import { bearer, organization } from "better-auth/plugins";
+import { eq } from "drizzle-orm";
+
+import { env } from "./env";
+
+export const auth = betterAuth({
+ baseURL: env.NEXT_PUBLIC_API_URL,
+ secret: env.BETTER_AUTH_SECRET,
+ database: drizzleAdapter(db, {
+ provider: "pg",
+ usePlural: true,
+ schema: authSchema,
+ }),
+ trustedOrigins: [
+ env.NEXT_PUBLIC_WEB_URL,
+ env.NEXT_PUBLIC_API_URL,
+ env.NEXT_PUBLIC_MARKETING_URL,
+ env.NEXT_PUBLIC_ADMIN_URL,
+ ],
+ session: {
+ expiresIn: 60 * 60 * 24 * 30, // 30 days
+ updateAge: 60 * 60 * 24, // refresh daily on activity
+ cookieCache: {
+ enabled: true,
+ maxAge: 60 * 5, // 5 minutes
+ },
+ },
+ advanced: {
+ crossSubDomainCookies: {
+ enabled: true,
+ domain: env.NEXT_PUBLIC_COOKIE_DOMAIN,
+ },
+ database: {
+ generateId: false,
+ },
+ },
+ socialProviders: {
+ github: {
+ clientId: env.GH_CLIENT_ID,
+ clientSecret: env.GH_CLIENT_SECRET,
+ },
+ google: {
+ clientId: env.GOOGLE_CLIENT_ID,
+ clientSecret: env.GOOGLE_CLIENT_SECRET,
+ },
+ },
+ databaseHooks: {
+ user: {
+ create: {
+ after: async (user) => {
+ // Create organization for new user
+ const org = await auth.api.createOrganization({
+ body: {
+ name: `${user.name}'s Workspace`,
+ slug: `${user.id.slice(0, 8)}-workspace`,
+ userId: user.id,
+ },
+ });
+
+ // Update all sessions for this user to set the active organization
+ // This handles sessions created during signup before the org existed
+ if (org?.id) {
+ await db
+ .update(authSchema.sessions)
+ .set({ activeOrganizationId: org.id })
+ .where(eq(authSchema.sessions.userId, user.id));
+ }
+ },
+ },
+ },
+ session: {
+ create: {
+ before: async (session) => {
+ // Set initial active organization when session is created
+ // This handles existing users who already have organizations
+ const membership = await db.query.members.findFirst({
+ where: eq(members.userId, session.userId),
+ });
+
+ return {
+ data: {
+ ...session,
+ activeOrganizationId: membership?.organizationId,
+ },
+ };
+ },
+ },
+ },
+ },
+ plugins: [
+ organization({
+ creatorRole: "owner",
+ }),
+ bearer(),
+ ],
+});
+
+export type Session = typeof auth.$Infer.Session;
+export type User = typeof auth.$Infer.Session.user;
diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json
new file mode 100644
index 000000000..840bf8c9a
--- /dev/null
+++ b/packages/auth/tsconfig.json
@@ -0,0 +1,5 @@
+{
+ "extends": "@superset/typescript/internal-package.json",
+ "include": ["src"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/packages/db/drizzle/0005_back_up_user_tables.sql b/packages/db/drizzle/0005_back_up_user_tables.sql
new file mode 100644
index 000000000..6b205836e
--- /dev/null
+++ b/packages/db/drizzle/0005_back_up_user_tables.sql
@@ -0,0 +1,51 @@
+ALTER TABLE "organization_members" RENAME TO "organization_members_backup";--> statement-breakpoint
+ALTER TABLE "organizations" RENAME TO "organizations_backup";--> statement-breakpoint
+ALTER TABLE "users" RENAME TO "users_backup";--> statement-breakpoint
+ALTER TABLE "organization_members_backup" DROP CONSTRAINT "organization_members_unique";--> statement-breakpoint
+ALTER TABLE "organizations_backup" DROP CONSTRAINT "organizations_clerk_org_id_unique";--> statement-breakpoint
+ALTER TABLE "organizations_backup" DROP CONSTRAINT "organizations_slug_unique";--> statement-breakpoint
+ALTER TABLE "users_backup" DROP CONSTRAINT "users_clerk_id_unique";--> statement-breakpoint
+ALTER TABLE "users_backup" DROP CONSTRAINT "users_email_unique";--> statement-breakpoint
+ALTER TABLE "integration_connections" DROP CONSTRAINT "integration_connections_organization_id_organizations_id_fk";
+--> statement-breakpoint
+ALTER TABLE "integration_connections" DROP CONSTRAINT "integration_connections_connected_by_user_id_users_id_fk";
+--> statement-breakpoint
+ALTER TABLE "organization_members_backup" DROP CONSTRAINT "organization_members_organization_id_organizations_id_fk";
+--> statement-breakpoint
+ALTER TABLE "organization_members_backup" DROP CONSTRAINT "organization_members_user_id_users_id_fk";
+--> statement-breakpoint
+ALTER TABLE "repositories" DROP CONSTRAINT "repositories_organization_id_organizations_id_fk";
+--> statement-breakpoint
+ALTER TABLE "tasks" DROP CONSTRAINT "tasks_organization_id_organizations_id_fk";
+--> statement-breakpoint
+ALTER TABLE "tasks" DROP CONSTRAINT "tasks_assignee_id_users_id_fk";
+--> statement-breakpoint
+ALTER TABLE "tasks" DROP CONSTRAINT "tasks_creator_id_users_id_fk";
+--> statement-breakpoint
+DROP INDEX "organization_members_organization_id_idx";--> statement-breakpoint
+DROP INDEX "organization_members_user_id_idx";--> statement-breakpoint
+DROP INDEX "organizations_slug_idx";--> statement-breakpoint
+DROP INDEX "organizations_clerk_org_id_idx";--> statement-breakpoint
+DROP INDEX "users_email_idx";--> statement-breakpoint
+DROP INDEX "users_clerk_id_idx";--> statement-breakpoint
+DROP INDEX "users_deleted_at_idx";--> statement-breakpoint
+ALTER TABLE "integration_connections" ADD CONSTRAINT "integration_connections_organization_id_organizations_backup_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations_backup"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "integration_connections" ADD CONSTRAINT "integration_connections_connected_by_user_id_users_backup_id_fk" FOREIGN KEY ("connected_by_user_id") REFERENCES "public"."users_backup"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "organization_members_backup" ADD CONSTRAINT "organization_members_backup_organization_id_organizations_backup_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations_backup"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "organization_members_backup" ADD CONSTRAINT "organization_members_backup_user_id_users_backup_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users_backup"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "repositories" ADD CONSTRAINT "repositories_organization_id_organizations_backup_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations_backup"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "tasks" ADD CONSTRAINT "tasks_organization_id_organizations_backup_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations_backup"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "tasks" ADD CONSTRAINT "tasks_assignee_id_users_backup_id_fk" FOREIGN KEY ("assignee_id") REFERENCES "public"."users_backup"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "tasks" ADD CONSTRAINT "tasks_creator_id_users_backup_id_fk" FOREIGN KEY ("creator_id") REFERENCES "public"."users_backup"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+CREATE INDEX "organization_members_backup_organization_id_idx" ON "organization_members_backup" USING btree ("organization_id");--> statement-breakpoint
+CREATE INDEX "organization_members_backup_user_id_idx" ON "organization_members_backup" USING btree ("user_id");--> statement-breakpoint
+CREATE INDEX "organizations_backup_slug_idx" ON "organizations_backup" USING btree ("slug");--> statement-breakpoint
+CREATE INDEX "organizations_backup_clerk_org_id_idx" ON "organizations_backup" USING btree ("clerk_org_id");--> statement-breakpoint
+CREATE INDEX "users_backup_email_idx" ON "users_backup" USING btree ("email");--> statement-breakpoint
+CREATE INDEX "users_backup_clerk_id_idx" ON "users_backup" USING btree ("clerk_id");--> statement-breakpoint
+CREATE INDEX "users_backup_deleted_at_idx" ON "users_backup" USING btree ("deleted_at");--> statement-breakpoint
+ALTER TABLE "organization_members_backup" ADD CONSTRAINT "organization_members_backup_unique" UNIQUE("organization_id","user_id");--> statement-breakpoint
+ALTER TABLE "organizations_backup" ADD CONSTRAINT "organizations_backup_clerk_org_id_unique" UNIQUE("clerk_org_id");--> statement-breakpoint
+ALTER TABLE "organizations_backup" ADD CONSTRAINT "organizations_backup_slug_unique" UNIQUE("slug");--> statement-breakpoint
+ALTER TABLE "users_backup" ADD CONSTRAINT "users_backup_clerk_id_unique" UNIQUE("clerk_id");--> statement-breakpoint
+ALTER TABLE "users_backup" ADD CONSTRAINT "users_backup_email_unique" UNIQUE("email");
\ No newline at end of file
diff --git a/packages/db/drizzle/0006_add_better_auth_tables.sql b/packages/db/drizzle/0006_add_better_auth_tables.sql
new file mode 100644
index 000000000..4ea536feb
--- /dev/null
+++ b/packages/db/drizzle/0006_add_better_auth_tables.sql
@@ -0,0 +1,179 @@
+CREATE SCHEMA "auth";
+--> statement-breakpoint
+CREATE TABLE "auth"."accounts" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "account_id" text NOT NULL,
+ "provider_id" text NOT NULL,
+ "user_id" uuid NOT NULL,
+ "access_token" text,
+ "refresh_token" text,
+ "id_token" text,
+ "access_token_expires_at" timestamp,
+ "refresh_token_expires_at" timestamp,
+ "scope" text,
+ "password" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "auth"."invitations" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "organization_id" uuid NOT NULL,
+ "email" text NOT NULL,
+ "role" text,
+ "status" text DEFAULT 'pending' NOT NULL,
+ "expires_at" timestamp NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "inviter_id" uuid NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "auth"."members" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "organization_id" uuid NOT NULL,
+ "user_id" uuid NOT NULL,
+ "role" text DEFAULT 'member' NOT NULL,
+ "created_at" timestamp NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "auth"."organizations" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "name" text NOT NULL,
+ "slug" text NOT NULL,
+ "logo" text,
+ "created_at" timestamp NOT NULL,
+ "metadata" text,
+ CONSTRAINT "organizations_slug_unique" UNIQUE("slug")
+);
+--> statement-breakpoint
+CREATE TABLE "auth"."sessions" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "expires_at" timestamp NOT NULL,
+ "token" text NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp NOT NULL,
+ "ip_address" text,
+ "user_agent" text,
+ "user_id" uuid NOT NULL,
+ "active_organization_id" uuid,
+ CONSTRAINT "sessions_token_unique" UNIQUE("token")
+);
+--> statement-breakpoint
+CREATE TABLE "auth"."users" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "name" text NOT NULL,
+ "email" text NOT NULL,
+ "email_verified" boolean DEFAULT false NOT NULL,
+ "image" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "users_email_unique" UNIQUE("email")
+);
+--> statement-breakpoint
+CREATE TABLE "auth"."verifications" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "identifier" text NOT NULL,
+ "value" text NOT NULL,
+ "expires_at" timestamp NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+-- Migrate users from backup (keeping same UUIDs)
+INSERT INTO "auth"."users" (id, name, email, email_verified, image, created_at, updated_at)
+SELECT
+ id,
+ name,
+ email,
+ true,
+ NULL,
+ created_at,
+ updated_at
+FROM users_backup
+WHERE deleted_at IS NULL
+ON CONFLICT (id) DO NOTHING;
+--> statement-breakpoint
+-- Migrate organizations from backup (keeping same UUIDs)
+INSERT INTO "auth"."organizations" (id, name, slug, logo, created_at, metadata)
+SELECT
+ id,
+ name,
+ slug,
+ avatar_url,
+ created_at,
+ NULL
+FROM organizations_backup
+ON CONFLICT (id) DO NOTHING;
+--> statement-breakpoint
+-- Migrate members from backup (keeping same UUIDs)
+INSERT INTO "auth"."members" (id, organization_id, user_id, role, created_at)
+SELECT
+ id,
+ organization_id,
+ user_id,
+ role,
+ created_at
+FROM organization_members_backup
+WHERE user_id IN (SELECT id FROM users_backup WHERE deleted_at IS NULL)
+ON CONFLICT (id) DO NOTHING;
+--> statement-breakpoint
+-- Backfill: Create personal workspace for users without an org
+INSERT INTO "auth"."organizations" (id, name, slug, created_at)
+SELECT
+ gen_random_uuid(),
+ u.name || '''s Workspace',
+ LEFT(u.id::text, 8) || '-workspace',
+ NOW()
+FROM "auth"."users" u
+WHERE NOT EXISTS (
+ SELECT 1 FROM "auth"."members" m WHERE m.user_id = u.id
+);
+--> statement-breakpoint
+-- Backfill: Add users as owners of their new workspaces
+INSERT INTO "auth"."members" (id, organization_id, user_id, role, created_at)
+SELECT
+ gen_random_uuid(),
+ o.id,
+ u.id,
+ 'owner',
+ NOW()
+FROM "auth"."users" u
+JOIN "auth"."organizations" o ON o.slug = LEFT(u.id::text, 8) || '-workspace'
+WHERE NOT EXISTS (
+ SELECT 1 FROM "auth"."members" m WHERE m.user_id = u.id
+);
+--> statement-breakpoint
+DROP TABLE IF EXISTS "organization_members_backup" CASCADE;--> statement-breakpoint
+DROP TABLE IF EXISTS "organizations_backup" CASCADE;--> statement-breakpoint
+DROP TABLE IF EXISTS "users_backup" CASCADE;--> statement-breakpoint
+ALTER TABLE "integration_connections" DROP CONSTRAINT IF EXISTS "integration_connections_organization_id_organizations_backup_id_fk";
+--> statement-breakpoint
+ALTER TABLE "integration_connections" DROP CONSTRAINT IF EXISTS "integration_connections_connected_by_user_id_users_backup_id_fk";
+--> statement-breakpoint
+ALTER TABLE "repositories" DROP CONSTRAINT IF EXISTS "repositories_organization_id_organizations_backup_id_fk";
+--> statement-breakpoint
+ALTER TABLE "tasks" DROP CONSTRAINT IF EXISTS "tasks_organization_id_organizations_backup_id_fk";
+--> statement-breakpoint
+ALTER TABLE "tasks" DROP CONSTRAINT IF EXISTS "tasks_assignee_id_users_backup_id_fk";
+--> statement-breakpoint
+ALTER TABLE "tasks" DROP CONSTRAINT IF EXISTS "tasks_creator_id_users_backup_id_fk";
+--> statement-breakpoint
+ALTER TABLE "auth"."accounts" ADD CONSTRAINT "accounts_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "auth"."invitations" ADD CONSTRAINT "invitations_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "auth"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "auth"."invitations" ADD CONSTRAINT "invitations_inviter_id_users_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "auth"."members" ADD CONSTRAINT "members_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "auth"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "auth"."members" ADD CONSTRAINT "members_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "auth"."sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+CREATE INDEX "accounts_user_id_idx" ON "auth"."accounts" USING btree ("user_id");--> statement-breakpoint
+CREATE INDEX "invitations_organization_id_idx" ON "auth"."invitations" USING btree ("organization_id");--> statement-breakpoint
+CREATE INDEX "invitations_email_idx" ON "auth"."invitations" USING btree ("email");--> statement-breakpoint
+CREATE INDEX "members_organization_id_idx" ON "auth"."members" USING btree ("organization_id");--> statement-breakpoint
+CREATE INDEX "members_user_id_idx" ON "auth"."members" USING btree ("user_id");--> statement-breakpoint
+CREATE UNIQUE INDEX "organizations_slug_idx" ON "auth"."organizations" USING btree ("slug");--> statement-breakpoint
+CREATE INDEX "sessions_user_id_idx" ON "auth"."sessions" USING btree ("user_id");--> statement-breakpoint
+CREATE INDEX "verifications_identifier_idx" ON "auth"."verifications" USING btree ("identifier");--> statement-breakpoint
+ALTER TABLE "integration_connections" ADD CONSTRAINT "integration_connections_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "auth"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "integration_connections" ADD CONSTRAINT "integration_connections_connected_by_user_id_users_id_fk" FOREIGN KEY ("connected_by_user_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "repositories" ADD CONSTRAINT "repositories_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "auth"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "tasks" ADD CONSTRAINT "tasks_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "auth"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "tasks" ADD CONSTRAINT "tasks_assignee_id_users_id_fk" FOREIGN KEY ("assignee_id") REFERENCES "auth"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "tasks" ADD CONSTRAINT "tasks_creator_id_users_id_fk" FOREIGN KEY ("creator_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;
\ No newline at end of file
diff --git a/packages/db/drizzle/0007_add_created_at_default.sql b/packages/db/drizzle/0007_add_created_at_default.sql
new file mode 100644
index 000000000..ec35981eb
--- /dev/null
+++ b/packages/db/drizzle/0007_add_created_at_default.sql
@@ -0,0 +1,2 @@
+ALTER TABLE "auth"."members" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
+ALTER TABLE "auth"."organizations" ALTER COLUMN "created_at" SET DEFAULT now();
\ No newline at end of file
diff --git a/packages/db/drizzle/meta/0005_snapshot.json b/packages/db/drizzle/meta/0005_snapshot.json
new file mode 100644
index 000000000..edb566a02
--- /dev/null
+++ b/packages/db/drizzle/meta/0005_snapshot.json
@@ -0,0 +1,1194 @@
+{
+ "id": "2bbde624-dc07-4526-ad9b-c4bb89d91b11",
+ "prevId": "a3a097c7-d242-4bec-8d35-7085b03b73c2",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "ingest.webhook_events": {
+ "name": "webhook_events",
+ "schema": "ingest",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "provider": {
+ "name": "provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "event_id": {
+ "name": "event_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "event_type": {
+ "name": "event_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payload": {
+ "name": "payload",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "processed_at": {
+ "name": "processed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retry_count": {
+ "name": "retry_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "received_at": {
+ "name": "received_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "webhook_events_provider_status_idx": {
+ "name": "webhook_events_provider_status_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "webhook_events_provider_event_id_idx": {
+ "name": "webhook_events_provider_event_id_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "event_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "webhook_events_received_at_idx": {
+ "name": "webhook_events_received_at_idx",
+ "columns": [
+ {
+ "expression": "received_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.integration_connections": {
+ "name": "integration_connections",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "connected_by_user_id": {
+ "name": "connected_by_user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider": {
+ "name": "provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "token_expires_at": {
+ "name": "token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_org_id": {
+ "name": "external_org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_org_name": {
+ "name": "external_org_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "config": {
+ "name": "config",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "integration_connections_org_idx": {
+ "name": "integration_connections_org_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "integration_connections_organization_id_organizations_backup_id_fk": {
+ "name": "integration_connections_organization_id_organizations_backup_id_fk",
+ "tableFrom": "integration_connections",
+ "tableTo": "organizations_backup",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integration_connections_connected_by_user_id_users_backup_id_fk": {
+ "name": "integration_connections_connected_by_user_id_users_backup_id_fk",
+ "tableFrom": "integration_connections",
+ "tableTo": "users_backup",
+ "columnsFrom": [
+ "connected_by_user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "integration_connections_unique": {
+ "name": "integration_connections_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "organization_id",
+ "provider"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.organization_members_backup": {
+ "name": "organization_members_backup",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "role": {
+ "name": "role",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'member'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "organization_members_backup_organization_id_idx": {
+ "name": "organization_members_backup_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "organization_members_backup_user_id_idx": {
+ "name": "organization_members_backup_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "organization_members_backup_organization_id_organizations_backup_id_fk": {
+ "name": "organization_members_backup_organization_id_organizations_backup_id_fk",
+ "tableFrom": "organization_members_backup",
+ "tableTo": "organizations_backup",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "organization_members_backup_user_id_users_backup_id_fk": {
+ "name": "organization_members_backup_user_id_users_backup_id_fk",
+ "tableFrom": "organization_members_backup",
+ "tableTo": "users_backup",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "organization_members_backup_unique": {
+ "name": "organization_members_backup_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "organization_id",
+ "user_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.organizations_backup": {
+ "name": "organizations_backup",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "clerk_org_id": {
+ "name": "clerk_org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "github_org": {
+ "name": "github_org",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "avatar_url": {
+ "name": "avatar_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "organizations_backup_slug_idx": {
+ "name": "organizations_backup_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "organizations_backup_clerk_org_id_idx": {
+ "name": "organizations_backup_clerk_org_id_idx",
+ "columns": [
+ {
+ "expression": "clerk_org_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "organizations_backup_clerk_org_id_unique": {
+ "name": "organizations_backup_clerk_org_id_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "clerk_org_id"
+ ]
+ },
+ "organizations_backup_slug_unique": {
+ "name": "organizations_backup_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.repositories": {
+ "name": "repositories",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_url": {
+ "name": "repo_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_owner": {
+ "name": "repo_owner",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_name": {
+ "name": "repo_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "default_branch": {
+ "name": "default_branch",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'main'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "repositories_organization_id_idx": {
+ "name": "repositories_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "repositories_slug_idx": {
+ "name": "repositories_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "repositories_organization_id_organizations_backup_id_fk": {
+ "name": "repositories_organization_id_organizations_backup_id_fk",
+ "tableFrom": "repositories",
+ "tableTo": "organizations_backup",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "repositories_org_slug_unique": {
+ "name": "repositories_org_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "organization_id",
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.tasks": {
+ "name": "tasks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status_color": {
+ "name": "status_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status_type": {
+ "name": "status_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status_position": {
+ "name": "status_position",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "priority": {
+ "name": "priority",
+ "type": "task_priority",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'none'"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repository_id": {
+ "name": "repository_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "assignee_id": {
+ "name": "assignee_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "estimate": {
+ "name": "estimate",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "due_date": {
+ "name": "due_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "labels": {
+ "name": "labels",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "'[]'::jsonb"
+ },
+ "branch": {
+ "name": "branch",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pr_url": {
+ "name": "pr_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_provider": {
+ "name": "external_provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_id": {
+ "name": "external_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_key": {
+ "name": "external_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_url": {
+ "name": "external_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_synced_at": {
+ "name": "last_synced_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sync_error": {
+ "name": "sync_error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "deleted_at": {
+ "name": "deleted_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "tasks_slug_idx": {
+ "name": "tasks_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_organization_id_idx": {
+ "name": "tasks_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_repository_id_idx": {
+ "name": "tasks_repository_id_idx",
+ "columns": [
+ {
+ "expression": "repository_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_assignee_id_idx": {
+ "name": "tasks_assignee_id_idx",
+ "columns": [
+ {
+ "expression": "assignee_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_creator_id_idx": {
+ "name": "tasks_creator_id_idx",
+ "columns": [
+ {
+ "expression": "creator_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_status_idx": {
+ "name": "tasks_status_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_created_at_idx": {
+ "name": "tasks_created_at_idx",
+ "columns": [
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_external_provider_idx": {
+ "name": "tasks_external_provider_idx",
+ "columns": [
+ {
+ "expression": "external_provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "tasks_organization_id_organizations_backup_id_fk": {
+ "name": "tasks_organization_id_organizations_backup_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "organizations_backup",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "tasks_repository_id_repositories_id_fk": {
+ "name": "tasks_repository_id_repositories_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "repositories",
+ "columnsFrom": [
+ "repository_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "tasks_assignee_id_users_backup_id_fk": {
+ "name": "tasks_assignee_id_users_backup_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "users_backup",
+ "columnsFrom": [
+ "assignee_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "tasks_creator_id_users_backup_id_fk": {
+ "name": "tasks_creator_id_users_backup_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "users_backup",
+ "columnsFrom": [
+ "creator_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "tasks_slug_unique": {
+ "name": "tasks_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ },
+ "tasks_external_unique": {
+ "name": "tasks_external_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "external_provider",
+ "external_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.users_backup": {
+ "name": "users_backup",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "clerk_id": {
+ "name": "clerk_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "avatar_url": {
+ "name": "avatar_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "deleted_at": {
+ "name": "deleted_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "users_backup_email_idx": {
+ "name": "users_backup_email_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_backup_clerk_id_idx": {
+ "name": "users_backup_clerk_id_idx",
+ "columns": [
+ {
+ "expression": "clerk_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_backup_deleted_at_idx": {
+ "name": "users_backup_deleted_at_idx",
+ "columns": [
+ {
+ "expression": "deleted_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_backup_clerk_id_unique": {
+ "name": "users_backup_clerk_id_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "clerk_id"
+ ]
+ },
+ "users_backup_email_unique": {
+ "name": "users_backup_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.integration_provider": {
+ "name": "integration_provider",
+ "schema": "public",
+ "values": [
+ "linear"
+ ]
+ },
+ "public.task_priority": {
+ "name": "task_priority",
+ "schema": "public",
+ "values": [
+ "urgent",
+ "high",
+ "medium",
+ "low",
+ "none"
+ ]
+ },
+ "public.task_status": {
+ "name": "task_status",
+ "schema": "public",
+ "values": [
+ "backlog",
+ "todo",
+ "planning",
+ "working",
+ "needs-feedback",
+ "ready-to-merge",
+ "completed",
+ "canceled"
+ ]
+ }
+ },
+ "schemas": {
+ "ingest": "ingest"
+ },
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/packages/db/drizzle/meta/0006_snapshot.json b/packages/db/drizzle/meta/0006_snapshot.json
new file mode 100644
index 000000000..113cceb67
--- /dev/null
+++ b/packages/db/drizzle/meta/0006_snapshot.json
@@ -0,0 +1,1523 @@
+{
+ "id": "711d4546-1abc-4aad-ac38-edd0f1be7be4",
+ "prevId": "2bbde624-dc07-4526-ad9b-c4bb89d91b11",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "auth.accounts": {
+ "name": "accounts",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_id": {
+ "name": "provider_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_token_expires_at": {
+ "name": "access_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token_expires_at": {
+ "name": "refresh_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "accounts_user_id_idx": {
+ "name": "accounts_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "accounts_user_id_users_id_fk": {
+ "name": "accounts_user_id_users_id_fk",
+ "tableFrom": "accounts",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.invitations": {
+ "name": "invitations",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "role": {
+ "name": "role",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "inviter_id": {
+ "name": "inviter_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "invitations_organization_id_idx": {
+ "name": "invitations_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "invitations_email_idx": {
+ "name": "invitations_email_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "invitations_organization_id_organizations_id_fk": {
+ "name": "invitations_organization_id_organizations_id_fk",
+ "tableFrom": "invitations",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "invitations_inviter_id_users_id_fk": {
+ "name": "invitations_inviter_id_users_id_fk",
+ "tableFrom": "invitations",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "inviter_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.members": {
+ "name": "members",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "role": {
+ "name": "role",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'member'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "members_organization_id_idx": {
+ "name": "members_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_user_id_idx": {
+ "name": "members_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "members_organization_id_organizations_id_fk": {
+ "name": "members_organization_id_organizations_id_fk",
+ "tableFrom": "members",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "members_user_id_users_id_fk": {
+ "name": "members_user_id_users_id_fk",
+ "tableFrom": "members",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.organizations": {
+ "name": "organizations",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "logo": {
+ "name": "logo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "organizations_slug_idx": {
+ "name": "organizations_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "organizations_slug_unique": {
+ "name": "organizations_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.sessions": {
+ "name": "sessions",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ip_address": {
+ "name": "ip_address",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_agent": {
+ "name": "user_agent",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "active_organization_id": {
+ "name": "active_organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "sessions_user_id_idx": {
+ "name": "sessions_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "sessions_user_id_users_id_fk": {
+ "name": "sessions_user_id_users_id_fk",
+ "tableFrom": "sessions",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "sessions_token_unique": {
+ "name": "sessions_token_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "token"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.users": {
+ "name": "users",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.verifications": {
+ "name": "verifications",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "identifier": {
+ "name": "identifier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "verifications_identifier_idx": {
+ "name": "verifications_identifier_idx",
+ "columns": [
+ {
+ "expression": "identifier",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "ingest.webhook_events": {
+ "name": "webhook_events",
+ "schema": "ingest",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "provider": {
+ "name": "provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "event_id": {
+ "name": "event_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "event_type": {
+ "name": "event_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payload": {
+ "name": "payload",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "processed_at": {
+ "name": "processed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retry_count": {
+ "name": "retry_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "received_at": {
+ "name": "received_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "webhook_events_provider_status_idx": {
+ "name": "webhook_events_provider_status_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "webhook_events_provider_event_id_idx": {
+ "name": "webhook_events_provider_event_id_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "event_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "webhook_events_received_at_idx": {
+ "name": "webhook_events_received_at_idx",
+ "columns": [
+ {
+ "expression": "received_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.integration_connections": {
+ "name": "integration_connections",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "connected_by_user_id": {
+ "name": "connected_by_user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider": {
+ "name": "provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "token_expires_at": {
+ "name": "token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_org_id": {
+ "name": "external_org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_org_name": {
+ "name": "external_org_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "config": {
+ "name": "config",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "integration_connections_org_idx": {
+ "name": "integration_connections_org_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "integration_connections_organization_id_organizations_id_fk": {
+ "name": "integration_connections_organization_id_organizations_id_fk",
+ "tableFrom": "integration_connections",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integration_connections_connected_by_user_id_users_id_fk": {
+ "name": "integration_connections_connected_by_user_id_users_id_fk",
+ "tableFrom": "integration_connections",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "connected_by_user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "integration_connections_unique": {
+ "name": "integration_connections_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "organization_id",
+ "provider"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.repositories": {
+ "name": "repositories",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_url": {
+ "name": "repo_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_owner": {
+ "name": "repo_owner",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_name": {
+ "name": "repo_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "default_branch": {
+ "name": "default_branch",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'main'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "repositories_organization_id_idx": {
+ "name": "repositories_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "repositories_slug_idx": {
+ "name": "repositories_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "repositories_organization_id_organizations_id_fk": {
+ "name": "repositories_organization_id_organizations_id_fk",
+ "tableFrom": "repositories",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "repositories_org_slug_unique": {
+ "name": "repositories_org_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "organization_id",
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.tasks": {
+ "name": "tasks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status_color": {
+ "name": "status_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status_type": {
+ "name": "status_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status_position": {
+ "name": "status_position",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "priority": {
+ "name": "priority",
+ "type": "task_priority",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'none'"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repository_id": {
+ "name": "repository_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "assignee_id": {
+ "name": "assignee_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "estimate": {
+ "name": "estimate",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "due_date": {
+ "name": "due_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "labels": {
+ "name": "labels",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "'[]'::jsonb"
+ },
+ "branch": {
+ "name": "branch",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pr_url": {
+ "name": "pr_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_provider": {
+ "name": "external_provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_id": {
+ "name": "external_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_key": {
+ "name": "external_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_url": {
+ "name": "external_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_synced_at": {
+ "name": "last_synced_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sync_error": {
+ "name": "sync_error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "deleted_at": {
+ "name": "deleted_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "tasks_slug_idx": {
+ "name": "tasks_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_organization_id_idx": {
+ "name": "tasks_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_repository_id_idx": {
+ "name": "tasks_repository_id_idx",
+ "columns": [
+ {
+ "expression": "repository_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_assignee_id_idx": {
+ "name": "tasks_assignee_id_idx",
+ "columns": [
+ {
+ "expression": "assignee_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_creator_id_idx": {
+ "name": "tasks_creator_id_idx",
+ "columns": [
+ {
+ "expression": "creator_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_status_idx": {
+ "name": "tasks_status_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_created_at_idx": {
+ "name": "tasks_created_at_idx",
+ "columns": [
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_external_provider_idx": {
+ "name": "tasks_external_provider_idx",
+ "columns": [
+ {
+ "expression": "external_provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "tasks_organization_id_organizations_id_fk": {
+ "name": "tasks_organization_id_organizations_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "tasks_repository_id_repositories_id_fk": {
+ "name": "tasks_repository_id_repositories_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "repositories",
+ "columnsFrom": [
+ "repository_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "tasks_assignee_id_users_id_fk": {
+ "name": "tasks_assignee_id_users_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "assignee_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "tasks_creator_id_users_id_fk": {
+ "name": "tasks_creator_id_users_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "creator_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "tasks_slug_unique": {
+ "name": "tasks_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ },
+ "tasks_external_unique": {
+ "name": "tasks_external_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "external_provider",
+ "external_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.integration_provider": {
+ "name": "integration_provider",
+ "schema": "public",
+ "values": [
+ "linear"
+ ]
+ },
+ "public.task_priority": {
+ "name": "task_priority",
+ "schema": "public",
+ "values": [
+ "urgent",
+ "high",
+ "medium",
+ "low",
+ "none"
+ ]
+ },
+ "public.task_status": {
+ "name": "task_status",
+ "schema": "public",
+ "values": [
+ "backlog",
+ "todo",
+ "planning",
+ "working",
+ "needs-feedback",
+ "ready-to-merge",
+ "completed",
+ "canceled"
+ ]
+ }
+ },
+ "schemas": {
+ "auth": "auth",
+ "ingest": "ingest"
+ },
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/packages/db/drizzle/meta/0007_snapshot.json b/packages/db/drizzle/meta/0007_snapshot.json
new file mode 100644
index 000000000..7ebd32ed7
--- /dev/null
+++ b/packages/db/drizzle/meta/0007_snapshot.json
@@ -0,0 +1,1525 @@
+{
+ "id": "fa87a301-b667-4c9c-9e1f-15b9d9130bb0",
+ "prevId": "711d4546-1abc-4aad-ac38-edd0f1be7be4",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "auth.accounts": {
+ "name": "accounts",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_id": {
+ "name": "provider_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_token_expires_at": {
+ "name": "access_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token_expires_at": {
+ "name": "refresh_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "accounts_user_id_idx": {
+ "name": "accounts_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "accounts_user_id_users_id_fk": {
+ "name": "accounts_user_id_users_id_fk",
+ "tableFrom": "accounts",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.invitations": {
+ "name": "invitations",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "role": {
+ "name": "role",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "inviter_id": {
+ "name": "inviter_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "invitations_organization_id_idx": {
+ "name": "invitations_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "invitations_email_idx": {
+ "name": "invitations_email_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "invitations_organization_id_organizations_id_fk": {
+ "name": "invitations_organization_id_organizations_id_fk",
+ "tableFrom": "invitations",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "invitations_inviter_id_users_id_fk": {
+ "name": "invitations_inviter_id_users_id_fk",
+ "tableFrom": "invitations",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "inviter_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.members": {
+ "name": "members",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "role": {
+ "name": "role",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'member'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "members_organization_id_idx": {
+ "name": "members_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_user_id_idx": {
+ "name": "members_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "members_organization_id_organizations_id_fk": {
+ "name": "members_organization_id_organizations_id_fk",
+ "tableFrom": "members",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "members_user_id_users_id_fk": {
+ "name": "members_user_id_users_id_fk",
+ "tableFrom": "members",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.organizations": {
+ "name": "organizations",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "logo": {
+ "name": "logo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "organizations_slug_idx": {
+ "name": "organizations_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "organizations_slug_unique": {
+ "name": "organizations_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.sessions": {
+ "name": "sessions",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ip_address": {
+ "name": "ip_address",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_agent": {
+ "name": "user_agent",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "active_organization_id": {
+ "name": "active_organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "sessions_user_id_idx": {
+ "name": "sessions_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "sessions_user_id_users_id_fk": {
+ "name": "sessions_user_id_users_id_fk",
+ "tableFrom": "sessions",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "sessions_token_unique": {
+ "name": "sessions_token_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "token"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.users": {
+ "name": "users",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "auth.verifications": {
+ "name": "verifications",
+ "schema": "auth",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "identifier": {
+ "name": "identifier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "verifications_identifier_idx": {
+ "name": "verifications_identifier_idx",
+ "columns": [
+ {
+ "expression": "identifier",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "ingest.webhook_events": {
+ "name": "webhook_events",
+ "schema": "ingest",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "provider": {
+ "name": "provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "event_id": {
+ "name": "event_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "event_type": {
+ "name": "event_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payload": {
+ "name": "payload",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "processed_at": {
+ "name": "processed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retry_count": {
+ "name": "retry_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "received_at": {
+ "name": "received_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "webhook_events_provider_status_idx": {
+ "name": "webhook_events_provider_status_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "webhook_events_provider_event_id_idx": {
+ "name": "webhook_events_provider_event_id_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "event_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "webhook_events_received_at_idx": {
+ "name": "webhook_events_received_at_idx",
+ "columns": [
+ {
+ "expression": "received_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.integration_connections": {
+ "name": "integration_connections",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "connected_by_user_id": {
+ "name": "connected_by_user_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider": {
+ "name": "provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "token_expires_at": {
+ "name": "token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_org_id": {
+ "name": "external_org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_org_name": {
+ "name": "external_org_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "config": {
+ "name": "config",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "integration_connections_org_idx": {
+ "name": "integration_connections_org_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "integration_connections_organization_id_organizations_id_fk": {
+ "name": "integration_connections_organization_id_organizations_id_fk",
+ "tableFrom": "integration_connections",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "integration_connections_connected_by_user_id_users_id_fk": {
+ "name": "integration_connections_connected_by_user_id_users_id_fk",
+ "tableFrom": "integration_connections",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "connected_by_user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "integration_connections_unique": {
+ "name": "integration_connections_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "organization_id",
+ "provider"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.repositories": {
+ "name": "repositories",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_url": {
+ "name": "repo_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_owner": {
+ "name": "repo_owner",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repo_name": {
+ "name": "repo_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "default_branch": {
+ "name": "default_branch",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'main'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "repositories_organization_id_idx": {
+ "name": "repositories_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "repositories_slug_idx": {
+ "name": "repositories_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "repositories_organization_id_organizations_id_fk": {
+ "name": "repositories_organization_id_organizations_id_fk",
+ "tableFrom": "repositories",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "repositories_org_slug_unique": {
+ "name": "repositories_org_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "organization_id",
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.tasks": {
+ "name": "tasks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status_color": {
+ "name": "status_color",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status_type": {
+ "name": "status_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status_position": {
+ "name": "status_position",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "priority": {
+ "name": "priority",
+ "type": "task_priority",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'none'"
+ },
+ "organization_id": {
+ "name": "organization_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "repository_id": {
+ "name": "repository_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "assignee_id": {
+ "name": "assignee_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creator_id": {
+ "name": "creator_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "estimate": {
+ "name": "estimate",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "due_date": {
+ "name": "due_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "labels": {
+ "name": "labels",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "'[]'::jsonb"
+ },
+ "branch": {
+ "name": "branch",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pr_url": {
+ "name": "pr_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_provider": {
+ "name": "external_provider",
+ "type": "integration_provider",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_id": {
+ "name": "external_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_key": {
+ "name": "external_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_url": {
+ "name": "external_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_synced_at": {
+ "name": "last_synced_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sync_error": {
+ "name": "sync_error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "deleted_at": {
+ "name": "deleted_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "tasks_slug_idx": {
+ "name": "tasks_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_organization_id_idx": {
+ "name": "tasks_organization_id_idx",
+ "columns": [
+ {
+ "expression": "organization_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_repository_id_idx": {
+ "name": "tasks_repository_id_idx",
+ "columns": [
+ {
+ "expression": "repository_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_assignee_id_idx": {
+ "name": "tasks_assignee_id_idx",
+ "columns": [
+ {
+ "expression": "assignee_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_creator_id_idx": {
+ "name": "tasks_creator_id_idx",
+ "columns": [
+ {
+ "expression": "creator_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_status_idx": {
+ "name": "tasks_status_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_created_at_idx": {
+ "name": "tasks_created_at_idx",
+ "columns": [
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tasks_external_provider_idx": {
+ "name": "tasks_external_provider_idx",
+ "columns": [
+ {
+ "expression": "external_provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "tasks_organization_id_organizations_id_fk": {
+ "name": "tasks_organization_id_organizations_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "organizations",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "organization_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "tasks_repository_id_repositories_id_fk": {
+ "name": "tasks_repository_id_repositories_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "repositories",
+ "columnsFrom": [
+ "repository_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "tasks_assignee_id_users_id_fk": {
+ "name": "tasks_assignee_id_users_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "assignee_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "tasks_creator_id_users_id_fk": {
+ "name": "tasks_creator_id_users_id_fk",
+ "tableFrom": "tasks",
+ "tableTo": "users",
+ "schemaTo": "auth",
+ "columnsFrom": [
+ "creator_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "tasks_slug_unique": {
+ "name": "tasks_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ },
+ "tasks_external_unique": {
+ "name": "tasks_external_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "external_provider",
+ "external_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.integration_provider": {
+ "name": "integration_provider",
+ "schema": "public",
+ "values": [
+ "linear"
+ ]
+ },
+ "public.task_priority": {
+ "name": "task_priority",
+ "schema": "public",
+ "values": [
+ "urgent",
+ "high",
+ "medium",
+ "low",
+ "none"
+ ]
+ },
+ "public.task_status": {
+ "name": "task_status",
+ "schema": "public",
+ "values": [
+ "backlog",
+ "todo",
+ "planning",
+ "working",
+ "needs-feedback",
+ "ready-to-merge",
+ "completed",
+ "canceled"
+ ]
+ }
+ },
+ "schemas": {
+ "auth": "auth",
+ "ingest": "ingest"
+ },
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json
index af9d90179..b6e6ceabf 100644
--- a/packages/db/drizzle/meta/_journal.json
+++ b/packages/db/drizzle/meta/_journal.json
@@ -36,6 +36,27 @@
"when": 1766710371092,
"tag": "0004_webhook_events_idempotency",
"breakpoints": true
+ },
+ {
+ "idx": 5,
+ "version": "7",
+ "when": 1766942895219,
+ "tag": "0005_back_up_user_tables",
+ "breakpoints": true
+ },
+ {
+ "idx": 6,
+ "version": "7",
+ "when": 1766991848204,
+ "tag": "0006_add_better_auth_tables",
+ "breakpoints": true
+ },
+ {
+ "idx": 7,
+ "version": "7",
+ "when": 1767049518603,
+ "tag": "0007_add_created_at_default",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/packages/db/package.json b/packages/db/package.json
index 9ded8de44..e8ccd3d9c 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -20,6 +20,10 @@
"types": "./src/schema/index.ts",
"default": "./src/schema/index.ts"
},
+ "./schema/auth": {
+ "types": "./src/schema/auth.ts",
+ "default": "./src/schema/auth.ts"
+ },
"./utils": {
"types": "./src/utils/index.ts",
"default": "./src/utils/index.ts"
diff --git a/packages/db/src/env.ts b/packages/db/src/env.ts
index 1ae470b29..2c51f729c 100644
--- a/packages/db/src/env.ts
+++ b/packages/db/src/env.ts
@@ -12,33 +12,12 @@ export const env = createEnv({
DATABASE_URL_UNPOOLED: z.string().url(),
},
- /**
- * The prefix that client-side variables must have. This is enforced both at
- * a type-level and at runtime.
- */
clientPrefix: "PUBLIC_",
client: {},
- /**
- * What object holds the environment variables at runtime. This is usually
- * `process.env` or `import.meta.env`.
- */
runtimeEnv: process.env,
- /**
- * By default, this library will feed the environment variables directly to
- * the Zod validator.
- *
- * This means that if you have an empty string for a value that is supposed
- * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag
- * it as a type mismatch violation. Additionally, if you have an empty string
- * for a value that is supposed to be a string with a default value (e.g.
- * `DOMAIN=` in an ".env" file), the default value will never be applied.
- *
- * In order to solve these issues, we recommend that all new projects
- * explicitly specify this option as true.
- */
emptyStringAsUndefined: true,
- skipValidation: !!process.env.SKIP_ENV_VALIDATION,
+ skipValidation: true,
});
diff --git a/packages/db/src/schema/auth.ts b/packages/db/src/schema/auth.ts
new file mode 100644
index 000000000..f810053e0
--- /dev/null
+++ b/packages/db/src/schema/auth.ts
@@ -0,0 +1,147 @@
+import {
+ boolean,
+ index,
+ pgSchema,
+ text,
+ timestamp,
+ uniqueIndex,
+ uuid,
+} from "drizzle-orm/pg-core";
+
+export const authSchema = pgSchema("auth");
+
+export const users = authSchema.table("users", {
+ id: uuid("id").primaryKey().defaultRandom(),
+ name: text("name").notNull(),
+ email: text("email").notNull().unique(),
+ emailVerified: boolean("email_verified").default(false).notNull(),
+ image: text("image"),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ updatedAt: timestamp("updated_at")
+ .defaultNow()
+ .$onUpdate(() => new Date())
+ .notNull(),
+});
+
+export type SelectUser = typeof users.$inferSelect;
+export type InsertUser = typeof users.$inferInsert;
+
+export const sessions = authSchema.table(
+ "sessions",
+ {
+ id: uuid("id").primaryKey().defaultRandom(),
+ expiresAt: timestamp("expires_at").notNull(),
+ token: text("token").notNull().unique(),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ updatedAt: timestamp("updated_at")
+ .$onUpdate(() => new Date())
+ .notNull(),
+ ipAddress: text("ip_address"),
+ userAgent: text("user_agent"),
+ userId: uuid("user_id")
+ .notNull()
+ .references(() => users.id, { onDelete: "cascade" }),
+ activeOrganizationId: uuid("active_organization_id"),
+ },
+ (table) => [index("sessions_user_id_idx").on(table.userId)],
+);
+
+export const accounts = authSchema.table(
+ "accounts",
+ {
+ id: uuid("id").primaryKey().defaultRandom(),
+ accountId: text("account_id").notNull(),
+ providerId: text("provider_id").notNull(),
+ userId: uuid("user_id")
+ .notNull()
+ .references(() => users.id, { onDelete: "cascade" }),
+ accessToken: text("access_token"),
+ refreshToken: text("refresh_token"),
+ idToken: text("id_token"),
+ accessTokenExpiresAt: timestamp("access_token_expires_at"),
+ refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
+ scope: text("scope"),
+ password: text("password"),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ updatedAt: timestamp("updated_at")
+ .$onUpdate(() => new Date())
+ .notNull(),
+ },
+ (table) => [index("accounts_user_id_idx").on(table.userId)],
+);
+
+export const verifications = authSchema.table(
+ "verifications",
+ {
+ id: uuid("id").primaryKey().defaultRandom(),
+ identifier: text("identifier").notNull(),
+ value: text("value").notNull(),
+ expiresAt: timestamp("expires_at").notNull(),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ updatedAt: timestamp("updated_at")
+ .defaultNow()
+ .$onUpdate(() => new Date())
+ .notNull(),
+ },
+ (table) => [index("verifications_identifier_idx").on(table.identifier)],
+);
+
+export const organizations = authSchema.table(
+ "organizations",
+ {
+ id: uuid("id").primaryKey().defaultRandom(),
+ name: text("name").notNull(),
+ slug: text("slug").notNull().unique(),
+ logo: text("logo"),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ metadata: text("metadata"),
+ },
+ (table) => [uniqueIndex("organizations_slug_idx").on(table.slug)],
+);
+
+export type SelectOrganization = typeof organizations.$inferSelect;
+export type InsertOrganization = typeof organizations.$inferInsert;
+
+export const members = authSchema.table(
+ "members",
+ {
+ id: uuid("id").primaryKey().defaultRandom(),
+ organizationId: uuid("organization_id")
+ .notNull()
+ .references(() => organizations.id, { onDelete: "cascade" }),
+ userId: uuid("user_id")
+ .notNull()
+ .references(() => users.id, { onDelete: "cascade" }),
+ role: text("role").default("member").notNull(),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ },
+ (table) => [
+ index("members_organization_id_idx").on(table.organizationId),
+ index("members_user_id_idx").on(table.userId),
+ ],
+);
+
+export type SelectMember = typeof members.$inferSelect;
+export type InsertMember = typeof members.$inferInsert;
+
+export const invitations = authSchema.table(
+ "invitations",
+ {
+ id: uuid("id").primaryKey().defaultRandom(),
+ organizationId: uuid("organization_id")
+ .notNull()
+ .references(() => organizations.id, { onDelete: "cascade" }),
+ email: text("email").notNull(),
+ role: text("role"),
+ status: text("status").default("pending").notNull(),
+ expiresAt: timestamp("expires_at").notNull(),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ inviterId: uuid("inviter_id")
+ .notNull()
+ .references(() => users.id, { onDelete: "cascade" }),
+ },
+ (table) => [
+ index("invitations_organization_id_idx").on(table.organizationId),
+ index("invitations_email_idx").on(table.email),
+ ],
+);
diff --git a/packages/db/src/schema/index.ts b/packages/db/src/schema/index.ts
index aec9abc1f..54196ae0b 100644
--- a/packages/db/src/schema/index.ts
+++ b/packages/db/src/schema/index.ts
@@ -1,3 +1,4 @@
+export * from "./auth";
export * from "./ingest";
export * from "./relations";
export * from "./schema";
diff --git a/packages/db/src/schema/relations.ts b/packages/db/src/schema/relations.ts
index 07a4fd226..0528be976 100644
--- a/packages/db/src/schema/relations.ts
+++ b/packages/db/src/schema/relations.ts
@@ -1,41 +1,68 @@
import { relations } from "drizzle-orm";
import {
- integrationConnections,
- organizationMembers,
+ accounts,
+ invitations,
+ members,
organizations,
- repositories,
- tasks,
+ sessions,
users,
-} from "./schema";
+} from "./auth";
+import { integrationConnections, repositories, tasks } from "./schema";
export const usersRelations = relations(users, ({ many }) => ({
- organizationMembers: many(organizationMembers),
+ sessions: many(sessions),
+ accounts: many(accounts),
+ members: many(members),
+ invitations: many(invitations),
createdTasks: many(tasks, { relationName: "creator" }),
assignedTasks: many(tasks, { relationName: "assignee" }),
connectedIntegrations: many(integrationConnections),
}));
+export const sessionsRelations = relations(sessions, ({ one }) => ({
+ user: one(users, {
+ fields: [sessions.userId],
+ references: [users.id],
+ }),
+}));
+
+export const accountsRelations = relations(accounts, ({ one }) => ({
+ user: one(users, {
+ fields: [accounts.userId],
+ references: [users.id],
+ }),
+}));
+
export const organizationsRelations = relations(organizations, ({ many }) => ({
- members: many(organizationMembers),
+ members: many(members),
+ invitations: many(invitations),
repositories: many(repositories),
tasks: many(tasks),
integrations: many(integrationConnections),
}));
-export const organizationMembersRelations = relations(
- organizationMembers,
- ({ one }) => ({
- organization: one(organizations, {
- fields: [organizationMembers.organizationId],
- references: [organizations.id],
- }),
- user: one(users, {
- fields: [organizationMembers.userId],
- references: [users.id],
- }),
+export const membersRelations = relations(members, ({ one }) => ({
+ organization: one(organizations, {
+ fields: [members.organizationId],
+ references: [organizations.id],
}),
-);
+ user: one(users, {
+ fields: [members.userId],
+ references: [users.id],
+ }),
+}));
+
+export const invitationsRelations = relations(invitations, ({ one }) => ({
+ organization: one(organizations, {
+ fields: [invitations.organizationId],
+ references: [organizations.id],
+ }),
+ inviter: one(users, {
+ fields: [invitations.inviterId],
+ references: [users.id],
+ }),
+}));
export const repositoriesRelations = relations(
repositories,
diff --git a/packages/db/src/schema/schema.ts b/packages/db/src/schema/schema.ts
index eed43d017..c85b2d194 100644
--- a/packages/db/src/schema/schema.ts
+++ b/packages/db/src/schema/schema.ts
@@ -11,6 +11,7 @@ import {
uuid,
} from "drizzle-orm/pg-core";
+import { organizations, users } from "./auth";
import {
integrationProviderValues,
taskPriorityValues,
@@ -25,81 +26,6 @@ export const integrationProvider = pgEnum(
integrationProviderValues,
);
-export const users = pgTable(
- "users",
- {
- id: uuid().primaryKey().defaultRandom(),
- clerkId: text("clerk_id").notNull().unique(),
- name: text().notNull(),
- email: text().notNull().unique(),
- avatarUrl: text("avatar_url"),
- deletedAt: timestamp("deleted_at"),
- createdAt: timestamp("created_at").notNull().defaultNow(),
- updatedAt: timestamp("updated_at")
- .notNull()
- .defaultNow()
- .$onUpdate(() => new Date()),
- },
- (table) => [
- index("users_email_idx").on(table.email),
- index("users_clerk_id_idx").on(table.clerkId),
- index("users_deleted_at_idx").on(table.deletedAt),
- ],
-);
-
-export type InsertUser = typeof users.$inferInsert;
-export type SelectUser = typeof users.$inferSelect;
-
-export const organizations = pgTable(
- "organizations",
- {
- id: uuid().primaryKey().defaultRandom(),
- clerkOrgId: text("clerk_org_id").unique(), // Clerk org ID - null until synced to Clerk
- name: text().notNull(),
- slug: text().notNull().unique(),
- githubOrg: text("github_org"),
- avatarUrl: text("avatar_url"),
- createdAt: timestamp("created_at").notNull().defaultNow(),
- updatedAt: timestamp("updated_at")
- .notNull()
- .defaultNow()
- .$onUpdate(() => new Date()),
- },
- (table) => [
- index("organizations_slug_idx").on(table.slug),
- index("organizations_clerk_org_id_idx").on(table.clerkOrgId),
- ],
-);
-
-export type InsertOrganization = typeof organizations.$inferInsert;
-export type SelectOrganization = typeof organizations.$inferSelect;
-
-export const organizationMembers = pgTable(
- "organization_members",
- {
- id: uuid().primaryKey().defaultRandom(),
- organizationId: uuid("organization_id")
- .notNull()
- .references(() => organizations.id, { onDelete: "cascade" }),
- userId: uuid("user_id")
- .notNull()
- .references(() => users.id, { onDelete: "cascade" }),
- role: text().notNull().default("member"), // "admin" | "member" | custom roles
- createdAt: timestamp("created_at").notNull().defaultNow(),
- },
- (table) => [
- index("organization_members_organization_id_idx").on(table.organizationId),
- index("organization_members_user_id_idx").on(table.userId),
- unique("organization_members_unique").on(
- table.organizationId,
- table.userId,
- ),
- ],
-);
-
-export type InsertOrganizationMember = typeof organizationMembers.$inferInsert;
-export type SelectOrganizationMember = typeof organizationMembers.$inferSelect;
-
export const repositories = pgTable(
"repositories",
{
@@ -150,7 +76,7 @@ export const tasks = pgTable(
.references(() => organizations.id, { onDelete: "cascade" }),
repositoryId: uuid("repository_id").references(() => repositories.id, {
onDelete: "cascade",
- }), // Optional - Linear tasks won't have this
+ }),
assigneeId: uuid("assignee_id").references(() => users.id, {
onDelete: "set null",
}),
diff --git a/packages/db/src/utils/sql.ts b/packages/db/src/utils/sql.ts
index 3628996b6..95d8ecd58 100644
--- a/packages/db/src/utils/sql.ts
+++ b/packages/db/src/utils/sql.ts
@@ -21,7 +21,13 @@ export async function getCurrentTxid(
tx: PgTransaction,
): Promise {
const result = await tx.execute<{ txid: string }>(
- sql`SELECT txid_current()::text as txid`,
+ sql`SELECT pg_current_xact_id()::text as txid`,
);
- return Number.parseInt(result.rows[0]?.txid ?? "", 10);
+
+ const txid = result.rows[0]?.txid;
+ if (!txid) {
+ throw new Error("Failed to get current transaction ID");
+ }
+
+ return Number.parseInt(txid, 10);
}
diff --git a/packages/local-db/drizzle/0004_add_terminal_link_behavior_setting.sql b/packages/local-db/drizzle/0004_add_terminal_link_behavior_setting.sql
deleted file mode 100644
index ad70f21f3..000000000
--- a/packages/local-db/drizzle/0004_add_terminal_link_behavior_setting.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE `settings` ADD `terminal_link_behavior` text;
\ No newline at end of file
diff --git a/packages/local-db/drizzle/0005_add_navigation_style.sql b/packages/local-db/drizzle/0005_add_navigation_style.sql
deleted file mode 100644
index c3c175a03..000000000
--- a/packages/local-db/drizzle/0005_add_navigation_style.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE `settings` ADD `navigation_style` text;
\ No newline at end of file
diff --git a/packages/local-db/drizzle/0006_add_unique_branch_workspace_index.sql b/packages/local-db/drizzle/0006_add_unique_branch_workspace_index.sql
deleted file mode 100644
index ac308f5f3..000000000
--- a/packages/local-db/drizzle/0006_add_unique_branch_workspace_index.sql
+++ /dev/null
@@ -1,47 +0,0 @@
--- Dedupe existing duplicate branch workspaces before creating unique index.
--- Keep the most recently used one (highest last_opened_at), with id ASC as tiebreaker.
--- First, update settings.last_active_workspace_id if it points to a workspace we're about to delete
-UPDATE settings
-SET last_active_workspace_id = (
- SELECT w1.id FROM workspaces w1
- WHERE w1.type = 'branch'
- AND w1.project_id = (
- SELECT w2.project_id FROM workspaces w2 WHERE w2.id = settings.last_active_workspace_id
- )
- ORDER BY w1.last_opened_at DESC NULLS LAST, w1.id ASC
- LIMIT 1
-)
-WHERE last_active_workspace_id IN (
- SELECT w1.id FROM workspaces w1
- WHERE w1.type = 'branch'
- AND EXISTS (
- SELECT 1 FROM workspaces w2
- WHERE w2.type = 'branch'
- AND w2.project_id = w1.project_id
- AND (
- w2.last_opened_at > w1.last_opened_at
- OR (w2.last_opened_at = w1.last_opened_at AND w2.id < w1.id)
- OR (w2.last_opened_at IS NOT NULL AND w1.last_opened_at IS NULL)
- OR (w1.last_opened_at IS NULL AND w2.last_opened_at IS NULL AND w2.id < w1.id)
- )
- )
-);
---> statement-breakpoint
--- Delete duplicate branch workspaces, keeping the most recently used per project
--- Survivor selection: highest last_opened_at, then lowest id as tiebreaker
-DELETE FROM workspaces
-WHERE type = 'branch'
-AND id NOT IN (
- SELECT id FROM (
- SELECT id, ROW_NUMBER() OVER (
- PARTITION BY project_id
- ORDER BY last_opened_at DESC NULLS LAST, id ASC
- ) as rn
- FROM workspaces
- WHERE type = 'branch'
- ) ranked
- WHERE rn = 1
-);
---> statement-breakpoint
--- Now safe to create the unique index
-CREATE UNIQUE INDEX IF NOT EXISTS `workspaces_unique_branch_per_project` ON `workspaces` (`project_id`) WHERE `type` = 'branch';
diff --git a/packages/local-db/drizzle/0007_add_workspace_is_unread.sql b/packages/local-db/drizzle/0007_add_workspace_is_unread.sql
deleted file mode 100644
index 9f3ca8ec3..000000000
--- a/packages/local-db/drizzle/0007_add_workspace_is_unread.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE `workspaces` ADD `is_unread` integer DEFAULT false;
diff --git a/packages/local-db/drizzle/0008_add_group_tabs_position.sql b/packages/local-db/drizzle/0008_add_group_tabs_position.sql
deleted file mode 100644
index 2be007e2a..000000000
--- a/packages/local-db/drizzle/0008_add_group_tabs_position.sql
+++ /dev/null
@@ -1 +0,0 @@
-ALTER TABLE `settings` ADD `group_tabs_position` text;
diff --git a/packages/local-db/drizzle/meta/0004_snapshot.json b/packages/local-db/drizzle/meta/0004_snapshot.json
deleted file mode 100644
index 991b5469e..000000000
--- a/packages/local-db/drizzle/meta/0004_snapshot.json
+++ /dev/null
@@ -1,977 +0,0 @@
-{
- "version": "6",
- "dialect": "sqlite",
- "id": "bb9f9f85-bcbb-4003-b20f-4c172a1c6fc8",
- "prevId": "d5a52ac9-bc1e-4529-89bf-5748d4df5006",
- "tables": {
- "organization_members": {
- "name": "organization_members",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "role": {
- "name": "role",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organization_members_organization_id_idx": {
- "name": "organization_members_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "organization_members_user_id_idx": {
- "name": "organization_members_user_id_idx",
- "columns": [
- "user_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "organization_members_organization_id_organizations_id_fk": {
- "name": "organization_members_organization_id_organizations_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "organization_members_user_id_users_id_fk": {
- "name": "organization_members_user_id_users_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "users",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "organizations": {
- "name": "organizations",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_org_id": {
- "name": "clerk_org_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "github_org": {
- "name": "github_org",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organizations_clerk_org_id_unique": {
- "name": "organizations_clerk_org_id_unique",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": true
- },
- "organizations_slug_unique": {
- "name": "organizations_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "organizations_slug_idx": {
- "name": "organizations_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "organizations_clerk_org_id_idx": {
- "name": "organizations_clerk_org_id_idx",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "projects": {
- "name": "projects",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "main_repo_path": {
- "name": "main_repo_path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "color": {
- "name": "color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "config_toast_dismissed": {
- "name": "config_toast_dismissed",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "default_branch": {
- "name": "default_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "projects_main_repo_path_idx": {
- "name": "projects_main_repo_path_idx",
- "columns": [
- "main_repo_path"
- ],
- "isUnique": false
- },
- "projects_last_opened_at_idx": {
- "name": "projects_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "settings": {
- "name": "settings",
- "columns": {
- "id": {
- "name": "id",
- "type": "integer",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false,
- "default": 1
- },
- "last_active_workspace_id": {
- "name": "last_active_workspace_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_used_app": {
- "name": "last_used_app",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets": {
- "name": "terminal_presets",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets_initialized": {
- "name": "terminal_presets_initialized",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "selected_ringtone_id": {
- "name": "selected_ringtone_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "active_organization_id": {
- "name": "active_organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "confirm_on_quit": {
- "name": "confirm_on_quit",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_link_behavior": {
- "name": "terminal_link_behavior",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "tasks": {
- "name": "tasks",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "title": {
- "name": "title",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status": {
- "name": "status",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "status_color": {
- "name": "status_color",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_type": {
- "name": "status_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_position": {
- "name": "status_position",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "priority": {
- "name": "priority",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "repository_id": {
- "name": "repository_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "assignee_id": {
- "name": "assignee_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "creator_id": {
- "name": "creator_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "estimate": {
- "name": "estimate",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "due_date": {
- "name": "due_date",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "labels": {
- "name": "labels",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "pr_url": {
- "name": "pr_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_provider": {
- "name": "external_provider",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_id": {
- "name": "external_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_key": {
- "name": "external_key",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_url": {
- "name": "external_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_synced_at": {
- "name": "last_synced_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "sync_error": {
- "name": "sync_error",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "started_at": {
- "name": "started_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "completed_at": {
- "name": "completed_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "tasks_slug_unique": {
- "name": "tasks_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "tasks_slug_idx": {
- "name": "tasks_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "tasks_organization_id_idx": {
- "name": "tasks_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "tasks_assignee_id_idx": {
- "name": "tasks_assignee_id_idx",
- "columns": [
- "assignee_id"
- ],
- "isUnique": false
- },
- "tasks_status_idx": {
- "name": "tasks_status_idx",
- "columns": [
- "status"
- ],
- "isUnique": false
- },
- "tasks_created_at_idx": {
- "name": "tasks_created_at_idx",
- "columns": [
- "created_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "tasks_organization_id_organizations_id_fk": {
- "name": "tasks_organization_id_organizations_id_fk",
- "tableFrom": "tasks",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "tasks_assignee_id_users_id_fk": {
- "name": "tasks_assignee_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "assignee_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "tasks_creator_id_users_id_fk": {
- "name": "tasks_creator_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "creator_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "users": {
- "name": "users",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_id": {
- "name": "clerk_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "users_clerk_id_unique": {
- "name": "users_clerk_id_unique",
- "columns": [
- "clerk_id"
- ],
- "isUnique": true
- },
- "users_email_unique": {
- "name": "users_email_unique",
- "columns": [
- "email"
- ],
- "isUnique": true
- },
- "users_email_idx": {
- "name": "users_email_idx",
- "columns": [
- "email"
- ],
- "isUnique": false
- },
- "users_clerk_id_idx": {
- "name": "users_clerk_id_idx",
- "columns": [
- "clerk_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "workspaces": {
- "name": "workspaces",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "worktree_id": {
- "name": "worktree_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "type": {
- "name": "type",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "workspaces_project_id_idx": {
- "name": "workspaces_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "workspaces_worktree_id_idx": {
- "name": "workspaces_worktree_id_idx",
- "columns": [
- "worktree_id"
- ],
- "isUnique": false
- },
- "workspaces_last_opened_at_idx": {
- "name": "workspaces_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "workspaces_project_id_projects_id_fk": {
- "name": "workspaces_project_id_projects_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "workspaces_worktree_id_worktrees_id_fk": {
- "name": "workspaces_worktree_id_worktrees_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "worktrees",
- "columnsFrom": [
- "worktree_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "worktrees": {
- "name": "worktrees",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "path": {
- "name": "path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "base_branch": {
- "name": "base_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "git_status": {
- "name": "git_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "github_status": {
- "name": "github_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "worktrees_project_id_idx": {
- "name": "worktrees_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "worktrees_branch_idx": {
- "name": "worktrees_branch_idx",
- "columns": [
- "branch"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "worktrees_project_id_projects_id_fk": {
- "name": "worktrees_project_id_projects_id_fk",
- "tableFrom": "worktrees",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- }
- },
- "views": {},
- "enums": {},
- "_meta": {
- "schemas": {},
- "tables": {},
- "columns": {}
- },
- "internal": {
- "indexes": {}
- }
-}
\ No newline at end of file
diff --git a/packages/local-db/drizzle/meta/0005_snapshot.json b/packages/local-db/drizzle/meta/0005_snapshot.json
deleted file mode 100644
index 14c02c328..000000000
--- a/packages/local-db/drizzle/meta/0005_snapshot.json
+++ /dev/null
@@ -1,984 +0,0 @@
-{
- "version": "6",
- "dialect": "sqlite",
- "id": "ac200b80-657f-4cd7-b338-2d6adeb925e7",
- "prevId": "bb9f9f85-bcbb-4003-b20f-4c172a1c6fc8",
- "tables": {
- "organization_members": {
- "name": "organization_members",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "role": {
- "name": "role",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organization_members_organization_id_idx": {
- "name": "organization_members_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "organization_members_user_id_idx": {
- "name": "organization_members_user_id_idx",
- "columns": [
- "user_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "organization_members_organization_id_organizations_id_fk": {
- "name": "organization_members_organization_id_organizations_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "organization_members_user_id_users_id_fk": {
- "name": "organization_members_user_id_users_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "users",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "organizations": {
- "name": "organizations",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_org_id": {
- "name": "clerk_org_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "github_org": {
- "name": "github_org",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organizations_clerk_org_id_unique": {
- "name": "organizations_clerk_org_id_unique",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": true
- },
- "organizations_slug_unique": {
- "name": "organizations_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "organizations_slug_idx": {
- "name": "organizations_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "organizations_clerk_org_id_idx": {
- "name": "organizations_clerk_org_id_idx",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "projects": {
- "name": "projects",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "main_repo_path": {
- "name": "main_repo_path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "color": {
- "name": "color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "config_toast_dismissed": {
- "name": "config_toast_dismissed",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "default_branch": {
- "name": "default_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "projects_main_repo_path_idx": {
- "name": "projects_main_repo_path_idx",
- "columns": [
- "main_repo_path"
- ],
- "isUnique": false
- },
- "projects_last_opened_at_idx": {
- "name": "projects_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "settings": {
- "name": "settings",
- "columns": {
- "id": {
- "name": "id",
- "type": "integer",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false,
- "default": 1
- },
- "last_active_workspace_id": {
- "name": "last_active_workspace_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_used_app": {
- "name": "last_used_app",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets": {
- "name": "terminal_presets",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets_initialized": {
- "name": "terminal_presets_initialized",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "selected_ringtone_id": {
- "name": "selected_ringtone_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "active_organization_id": {
- "name": "active_organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "confirm_on_quit": {
- "name": "confirm_on_quit",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_link_behavior": {
- "name": "terminal_link_behavior",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "navigation_style": {
- "name": "navigation_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "tasks": {
- "name": "tasks",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "title": {
- "name": "title",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status": {
- "name": "status",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "status_color": {
- "name": "status_color",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_type": {
- "name": "status_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_position": {
- "name": "status_position",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "priority": {
- "name": "priority",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "repository_id": {
- "name": "repository_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "assignee_id": {
- "name": "assignee_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "creator_id": {
- "name": "creator_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "estimate": {
- "name": "estimate",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "due_date": {
- "name": "due_date",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "labels": {
- "name": "labels",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "pr_url": {
- "name": "pr_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_provider": {
- "name": "external_provider",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_id": {
- "name": "external_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_key": {
- "name": "external_key",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_url": {
- "name": "external_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_synced_at": {
- "name": "last_synced_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "sync_error": {
- "name": "sync_error",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "started_at": {
- "name": "started_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "completed_at": {
- "name": "completed_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "tasks_slug_unique": {
- "name": "tasks_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "tasks_slug_idx": {
- "name": "tasks_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "tasks_organization_id_idx": {
- "name": "tasks_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "tasks_assignee_id_idx": {
- "name": "tasks_assignee_id_idx",
- "columns": [
- "assignee_id"
- ],
- "isUnique": false
- },
- "tasks_status_idx": {
- "name": "tasks_status_idx",
- "columns": [
- "status"
- ],
- "isUnique": false
- },
- "tasks_created_at_idx": {
- "name": "tasks_created_at_idx",
- "columns": [
- "created_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "tasks_organization_id_organizations_id_fk": {
- "name": "tasks_organization_id_organizations_id_fk",
- "tableFrom": "tasks",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "tasks_assignee_id_users_id_fk": {
- "name": "tasks_assignee_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "assignee_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "tasks_creator_id_users_id_fk": {
- "name": "tasks_creator_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "creator_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "users": {
- "name": "users",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_id": {
- "name": "clerk_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "users_clerk_id_unique": {
- "name": "users_clerk_id_unique",
- "columns": [
- "clerk_id"
- ],
- "isUnique": true
- },
- "users_email_unique": {
- "name": "users_email_unique",
- "columns": [
- "email"
- ],
- "isUnique": true
- },
- "users_email_idx": {
- "name": "users_email_idx",
- "columns": [
- "email"
- ],
- "isUnique": false
- },
- "users_clerk_id_idx": {
- "name": "users_clerk_id_idx",
- "columns": [
- "clerk_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "workspaces": {
- "name": "workspaces",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "worktree_id": {
- "name": "worktree_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "type": {
- "name": "type",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "workspaces_project_id_idx": {
- "name": "workspaces_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "workspaces_worktree_id_idx": {
- "name": "workspaces_worktree_id_idx",
- "columns": [
- "worktree_id"
- ],
- "isUnique": false
- },
- "workspaces_last_opened_at_idx": {
- "name": "workspaces_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "workspaces_project_id_projects_id_fk": {
- "name": "workspaces_project_id_projects_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "workspaces_worktree_id_worktrees_id_fk": {
- "name": "workspaces_worktree_id_worktrees_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "worktrees",
- "columnsFrom": [
- "worktree_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "worktrees": {
- "name": "worktrees",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "path": {
- "name": "path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "base_branch": {
- "name": "base_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "git_status": {
- "name": "git_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "github_status": {
- "name": "github_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "worktrees_project_id_idx": {
- "name": "worktrees_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "worktrees_branch_idx": {
- "name": "worktrees_branch_idx",
- "columns": [
- "branch"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "worktrees_project_id_projects_id_fk": {
- "name": "worktrees_project_id_projects_id_fk",
- "tableFrom": "worktrees",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- }
- },
- "views": {},
- "enums": {},
- "_meta": {
- "schemas": {},
- "tables": {},
- "columns": {}
- },
- "internal": {
- "indexes": {}
- }
-}
\ No newline at end of file
diff --git a/packages/local-db/drizzle/meta/0006_snapshot.json b/packages/local-db/drizzle/meta/0006_snapshot.json
deleted file mode 100644
index 5362480f6..000000000
--- a/packages/local-db/drizzle/meta/0006_snapshot.json
+++ /dev/null
@@ -1,984 +0,0 @@
-{
- "version": "6",
- "dialect": "sqlite",
- "id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
- "prevId": "ac200b80-657f-4cd7-b338-2d6adeb925e7",
- "tables": {
- "organization_members": {
- "name": "organization_members",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "role": {
- "name": "role",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organization_members_organization_id_idx": {
- "name": "organization_members_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "organization_members_user_id_idx": {
- "name": "organization_members_user_id_idx",
- "columns": [
- "user_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "organization_members_organization_id_organizations_id_fk": {
- "name": "organization_members_organization_id_organizations_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "organization_members_user_id_users_id_fk": {
- "name": "organization_members_user_id_users_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "users",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "organizations": {
- "name": "organizations",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_org_id": {
- "name": "clerk_org_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "github_org": {
- "name": "github_org",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organizations_clerk_org_id_unique": {
- "name": "organizations_clerk_org_id_unique",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": true
- },
- "organizations_slug_unique": {
- "name": "organizations_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "organizations_slug_idx": {
- "name": "organizations_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "organizations_clerk_org_id_idx": {
- "name": "organizations_clerk_org_id_idx",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "projects": {
- "name": "projects",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "main_repo_path": {
- "name": "main_repo_path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "color": {
- "name": "color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "config_toast_dismissed": {
- "name": "config_toast_dismissed",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "default_branch": {
- "name": "default_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "projects_main_repo_path_idx": {
- "name": "projects_main_repo_path_idx",
- "columns": [
- "main_repo_path"
- ],
- "isUnique": false
- },
- "projects_last_opened_at_idx": {
- "name": "projects_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "settings": {
- "name": "settings",
- "columns": {
- "id": {
- "name": "id",
- "type": "integer",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false,
- "default": 1
- },
- "last_active_workspace_id": {
- "name": "last_active_workspace_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_used_app": {
- "name": "last_used_app",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets": {
- "name": "terminal_presets",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets_initialized": {
- "name": "terminal_presets_initialized",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "selected_ringtone_id": {
- "name": "selected_ringtone_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "active_organization_id": {
- "name": "active_organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "confirm_on_quit": {
- "name": "confirm_on_quit",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_link_behavior": {
- "name": "terminal_link_behavior",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "navigation_style": {
- "name": "navigation_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "tasks": {
- "name": "tasks",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "title": {
- "name": "title",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status": {
- "name": "status",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "status_color": {
- "name": "status_color",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_type": {
- "name": "status_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_position": {
- "name": "status_position",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "priority": {
- "name": "priority",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "repository_id": {
- "name": "repository_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "assignee_id": {
- "name": "assignee_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "creator_id": {
- "name": "creator_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "estimate": {
- "name": "estimate",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "due_date": {
- "name": "due_date",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "labels": {
- "name": "labels",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "pr_url": {
- "name": "pr_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_provider": {
- "name": "external_provider",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_id": {
- "name": "external_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_key": {
- "name": "external_key",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_url": {
- "name": "external_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_synced_at": {
- "name": "last_synced_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "sync_error": {
- "name": "sync_error",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "started_at": {
- "name": "started_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "completed_at": {
- "name": "completed_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "tasks_slug_unique": {
- "name": "tasks_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "tasks_slug_idx": {
- "name": "tasks_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "tasks_organization_id_idx": {
- "name": "tasks_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "tasks_assignee_id_idx": {
- "name": "tasks_assignee_id_idx",
- "columns": [
- "assignee_id"
- ],
- "isUnique": false
- },
- "tasks_status_idx": {
- "name": "tasks_status_idx",
- "columns": [
- "status"
- ],
- "isUnique": false
- },
- "tasks_created_at_idx": {
- "name": "tasks_created_at_idx",
- "columns": [
- "created_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "tasks_organization_id_organizations_id_fk": {
- "name": "tasks_organization_id_organizations_id_fk",
- "tableFrom": "tasks",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "tasks_assignee_id_users_id_fk": {
- "name": "tasks_assignee_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "assignee_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "tasks_creator_id_users_id_fk": {
- "name": "tasks_creator_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "creator_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "users": {
- "name": "users",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_id": {
- "name": "clerk_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "users_clerk_id_unique": {
- "name": "users_clerk_id_unique",
- "columns": [
- "clerk_id"
- ],
- "isUnique": true
- },
- "users_email_unique": {
- "name": "users_email_unique",
- "columns": [
- "email"
- ],
- "isUnique": true
- },
- "users_email_idx": {
- "name": "users_email_idx",
- "columns": [
- "email"
- ],
- "isUnique": false
- },
- "users_clerk_id_idx": {
- "name": "users_clerk_id_idx",
- "columns": [
- "clerk_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "workspaces": {
- "name": "workspaces",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "worktree_id": {
- "name": "worktree_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "type": {
- "name": "type",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "workspaces_project_id_idx": {
- "name": "workspaces_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "workspaces_worktree_id_idx": {
- "name": "workspaces_worktree_id_idx",
- "columns": [
- "worktree_id"
- ],
- "isUnique": false
- },
- "workspaces_last_opened_at_idx": {
- "name": "workspaces_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "workspaces_project_id_projects_id_fk": {
- "name": "workspaces_project_id_projects_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "workspaces_worktree_id_worktrees_id_fk": {
- "name": "workspaces_worktree_id_worktrees_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "worktrees",
- "columnsFrom": [
- "worktree_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "worktrees": {
- "name": "worktrees",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "path": {
- "name": "path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "base_branch": {
- "name": "base_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "git_status": {
- "name": "git_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "github_status": {
- "name": "github_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "worktrees_project_id_idx": {
- "name": "worktrees_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "worktrees_branch_idx": {
- "name": "worktrees_branch_idx",
- "columns": [
- "branch"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "worktrees_project_id_projects_id_fk": {
- "name": "worktrees_project_id_projects_id_fk",
- "tableFrom": "worktrees",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- }
- },
- "views": {},
- "enums": {},
- "_meta": {
- "schemas": {},
- "tables": {},
- "columns": {}
- },
- "internal": {
- "indexes": {}
- }
-}
diff --git a/packages/local-db/drizzle/meta/0007_snapshot.json b/packages/local-db/drizzle/meta/0007_snapshot.json
deleted file mode 100644
index dbf24a697..000000000
--- a/packages/local-db/drizzle/meta/0007_snapshot.json
+++ /dev/null
@@ -1,992 +0,0 @@
-{
- "version": "6",
- "dialect": "sqlite",
- "id": "a7b8c9d0-e1f2-3456-7890-abcdef123456",
- "prevId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
- "tables": {
- "organization_members": {
- "name": "organization_members",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "role": {
- "name": "role",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organization_members_organization_id_idx": {
- "name": "organization_members_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "organization_members_user_id_idx": {
- "name": "organization_members_user_id_idx",
- "columns": [
- "user_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "organization_members_organization_id_organizations_id_fk": {
- "name": "organization_members_organization_id_organizations_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "organization_members_user_id_users_id_fk": {
- "name": "organization_members_user_id_users_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "users",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "organizations": {
- "name": "organizations",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_org_id": {
- "name": "clerk_org_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "github_org": {
- "name": "github_org",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organizations_clerk_org_id_unique": {
- "name": "organizations_clerk_org_id_unique",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": true
- },
- "organizations_slug_unique": {
- "name": "organizations_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "organizations_slug_idx": {
- "name": "organizations_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "organizations_clerk_org_id_idx": {
- "name": "organizations_clerk_org_id_idx",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "projects": {
- "name": "projects",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "main_repo_path": {
- "name": "main_repo_path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "color": {
- "name": "color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "config_toast_dismissed": {
- "name": "config_toast_dismissed",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "default_branch": {
- "name": "default_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "projects_main_repo_path_idx": {
- "name": "projects_main_repo_path_idx",
- "columns": [
- "main_repo_path"
- ],
- "isUnique": false
- },
- "projects_last_opened_at_idx": {
- "name": "projects_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "settings": {
- "name": "settings",
- "columns": {
- "id": {
- "name": "id",
- "type": "integer",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false,
- "default": 1
- },
- "last_active_workspace_id": {
- "name": "last_active_workspace_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_used_app": {
- "name": "last_used_app",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets": {
- "name": "terminal_presets",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets_initialized": {
- "name": "terminal_presets_initialized",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "selected_ringtone_id": {
- "name": "selected_ringtone_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "active_organization_id": {
- "name": "active_organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "confirm_on_quit": {
- "name": "confirm_on_quit",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_link_behavior": {
- "name": "terminal_link_behavior",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "navigation_style": {
- "name": "navigation_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "tasks": {
- "name": "tasks",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "title": {
- "name": "title",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status": {
- "name": "status",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "status_color": {
- "name": "status_color",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_type": {
- "name": "status_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_position": {
- "name": "status_position",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "priority": {
- "name": "priority",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "repository_id": {
- "name": "repository_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "assignee_id": {
- "name": "assignee_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "creator_id": {
- "name": "creator_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "estimate": {
- "name": "estimate",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "due_date": {
- "name": "due_date",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "labels": {
- "name": "labels",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "pr_url": {
- "name": "pr_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_provider": {
- "name": "external_provider",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_id": {
- "name": "external_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_key": {
- "name": "external_key",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_url": {
- "name": "external_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_synced_at": {
- "name": "last_synced_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "sync_error": {
- "name": "sync_error",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "started_at": {
- "name": "started_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "completed_at": {
- "name": "completed_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "tasks_slug_unique": {
- "name": "tasks_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "tasks_slug_idx": {
- "name": "tasks_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "tasks_organization_id_idx": {
- "name": "tasks_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "tasks_assignee_id_idx": {
- "name": "tasks_assignee_id_idx",
- "columns": [
- "assignee_id"
- ],
- "isUnique": false
- },
- "tasks_status_idx": {
- "name": "tasks_status_idx",
- "columns": [
- "status"
- ],
- "isUnique": false
- },
- "tasks_created_at_idx": {
- "name": "tasks_created_at_idx",
- "columns": [
- "created_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "tasks_organization_id_organizations_id_fk": {
- "name": "tasks_organization_id_organizations_id_fk",
- "tableFrom": "tasks",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "tasks_assignee_id_users_id_fk": {
- "name": "tasks_assignee_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "assignee_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "tasks_creator_id_users_id_fk": {
- "name": "tasks_creator_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "creator_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "users": {
- "name": "users",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_id": {
- "name": "clerk_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "users_clerk_id_unique": {
- "name": "users_clerk_id_unique",
- "columns": [
- "clerk_id"
- ],
- "isUnique": true
- },
- "users_email_unique": {
- "name": "users_email_unique",
- "columns": [
- "email"
- ],
- "isUnique": true
- },
- "users_email_idx": {
- "name": "users_email_idx",
- "columns": [
- "email"
- ],
- "isUnique": false
- },
- "users_clerk_id_idx": {
- "name": "users_clerk_id_idx",
- "columns": [
- "clerk_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "workspaces": {
- "name": "workspaces",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "worktree_id": {
- "name": "worktree_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "type": {
- "name": "type",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "is_unread": {
- "name": "is_unread",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false,
- "default": false
- }
- },
- "indexes": {
- "workspaces_project_id_idx": {
- "name": "workspaces_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "workspaces_worktree_id_idx": {
- "name": "workspaces_worktree_id_idx",
- "columns": [
- "worktree_id"
- ],
- "isUnique": false
- },
- "workspaces_last_opened_at_idx": {
- "name": "workspaces_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "workspaces_project_id_projects_id_fk": {
- "name": "workspaces_project_id_projects_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "workspaces_worktree_id_worktrees_id_fk": {
- "name": "workspaces_worktree_id_worktrees_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "worktrees",
- "columnsFrom": [
- "worktree_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "worktrees": {
- "name": "worktrees",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "path": {
- "name": "path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "base_branch": {
- "name": "base_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "git_status": {
- "name": "git_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "github_status": {
- "name": "github_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "worktrees_project_id_idx": {
- "name": "worktrees_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "worktrees_branch_idx": {
- "name": "worktrees_branch_idx",
- "columns": [
- "branch"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "worktrees_project_id_projects_id_fk": {
- "name": "worktrees_project_id_projects_id_fk",
- "tableFrom": "worktrees",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- }
- },
- "views": {},
- "enums": {},
- "_meta": {
- "schemas": {},
- "tables": {},
- "columns": {}
- },
- "internal": {
- "indexes": {}
- }
-}
diff --git a/packages/local-db/drizzle/meta/0008_snapshot.json b/packages/local-db/drizzle/meta/0008_snapshot.json
deleted file mode 100644
index 3c3664f7a..000000000
--- a/packages/local-db/drizzle/meta/0008_snapshot.json
+++ /dev/null
@@ -1,999 +0,0 @@
-{
- "version": "6",
- "dialect": "sqlite",
- "id": "160d23b9-a426-4e93-866a-3d6e6fc3c704",
- "prevId": "a7b8c9d0-e1f2-3456-7890-abcdef123456",
- "tables": {
- "organization_members": {
- "name": "organization_members",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "role": {
- "name": "role",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organization_members_organization_id_idx": {
- "name": "organization_members_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "organization_members_user_id_idx": {
- "name": "organization_members_user_id_idx",
- "columns": [
- "user_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "organization_members_organization_id_organizations_id_fk": {
- "name": "organization_members_organization_id_organizations_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "organization_members_user_id_users_id_fk": {
- "name": "organization_members_user_id_users_id_fk",
- "tableFrom": "organization_members",
- "tableTo": "users",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "organizations": {
- "name": "organizations",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_org_id": {
- "name": "clerk_org_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "github_org": {
- "name": "github_org",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "organizations_clerk_org_id_unique": {
- "name": "organizations_clerk_org_id_unique",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": true
- },
- "organizations_slug_unique": {
- "name": "organizations_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "organizations_slug_idx": {
- "name": "organizations_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "organizations_clerk_org_id_idx": {
- "name": "organizations_clerk_org_id_idx",
- "columns": [
- "clerk_org_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "projects": {
- "name": "projects",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "main_repo_path": {
- "name": "main_repo_path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "color": {
- "name": "color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "config_toast_dismissed": {
- "name": "config_toast_dismissed",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "default_branch": {
- "name": "default_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "projects_main_repo_path_idx": {
- "name": "projects_main_repo_path_idx",
- "columns": [
- "main_repo_path"
- ],
- "isUnique": false
- },
- "projects_last_opened_at_idx": {
- "name": "projects_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "settings": {
- "name": "settings",
- "columns": {
- "id": {
- "name": "id",
- "type": "integer",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false,
- "default": 1
- },
- "last_active_workspace_id": {
- "name": "last_active_workspace_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_used_app": {
- "name": "last_used_app",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets": {
- "name": "terminal_presets",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_presets_initialized": {
- "name": "terminal_presets_initialized",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "selected_ringtone_id": {
- "name": "selected_ringtone_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "active_organization_id": {
- "name": "active_organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "confirm_on_quit": {
- "name": "confirm_on_quit",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "terminal_link_behavior": {
- "name": "terminal_link_behavior",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "navigation_style": {
- "name": "navigation_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "group_tabs_position": {
- "name": "group_tabs_position",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "tasks": {
- "name": "tasks",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "slug": {
- "name": "slug",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "title": {
- "name": "title",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status": {
- "name": "status",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "status_color": {
- "name": "status_color",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_type": {
- "name": "status_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "status_position": {
- "name": "status_position",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "priority": {
- "name": "priority",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "organization_id": {
- "name": "organization_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "repository_id": {
- "name": "repository_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "assignee_id": {
- "name": "assignee_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "creator_id": {
- "name": "creator_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "estimate": {
- "name": "estimate",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "due_date": {
- "name": "due_date",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "labels": {
- "name": "labels",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "pr_url": {
- "name": "pr_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_provider": {
- "name": "external_provider",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_id": {
- "name": "external_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_key": {
- "name": "external_key",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "external_url": {
- "name": "external_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "last_synced_at": {
- "name": "last_synced_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "sync_error": {
- "name": "sync_error",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "started_at": {
- "name": "started_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "completed_at": {
- "name": "completed_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "tasks_slug_unique": {
- "name": "tasks_slug_unique",
- "columns": [
- "slug"
- ],
- "isUnique": true
- },
- "tasks_slug_idx": {
- "name": "tasks_slug_idx",
- "columns": [
- "slug"
- ],
- "isUnique": false
- },
- "tasks_organization_id_idx": {
- "name": "tasks_organization_id_idx",
- "columns": [
- "organization_id"
- ],
- "isUnique": false
- },
- "tasks_assignee_id_idx": {
- "name": "tasks_assignee_id_idx",
- "columns": [
- "assignee_id"
- ],
- "isUnique": false
- },
- "tasks_status_idx": {
- "name": "tasks_status_idx",
- "columns": [
- "status"
- ],
- "isUnique": false
- },
- "tasks_created_at_idx": {
- "name": "tasks_created_at_idx",
- "columns": [
- "created_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "tasks_organization_id_organizations_id_fk": {
- "name": "tasks_organization_id_organizations_id_fk",
- "tableFrom": "tasks",
- "tableTo": "organizations",
- "columnsFrom": [
- "organization_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "tasks_assignee_id_users_id_fk": {
- "name": "tasks_assignee_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "assignee_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "tasks_creator_id_users_id_fk": {
- "name": "tasks_creator_id_users_id_fk",
- "tableFrom": "tasks",
- "tableTo": "users",
- "columnsFrom": [
- "creator_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "users": {
- "name": "users",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "clerk_id": {
- "name": "clerk_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "avatar_url": {
- "name": "avatar_url",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "deleted_at": {
- "name": "deleted_at",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- }
- },
- "indexes": {
- "users_clerk_id_unique": {
- "name": "users_clerk_id_unique",
- "columns": [
- "clerk_id"
- ],
- "isUnique": true
- },
- "users_email_unique": {
- "name": "users_email_unique",
- "columns": [
- "email"
- ],
- "isUnique": true
- },
- "users_email_idx": {
- "name": "users_email_idx",
- "columns": [
- "email"
- ],
- "isUnique": false
- },
- "users_clerk_id_idx": {
- "name": "users_clerk_id_idx",
- "columns": [
- "clerk_id"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "workspaces": {
- "name": "workspaces",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "worktree_id": {
- "name": "worktree_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "type": {
- "name": "type",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "tab_order": {
- "name": "tab_order",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "updated_at": {
- "name": "updated_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "last_opened_at": {
- "name": "last_opened_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "is_unread": {
- "name": "is_unread",
- "type": "integer",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false,
- "default": false
- }
- },
- "indexes": {
- "workspaces_project_id_idx": {
- "name": "workspaces_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "workspaces_worktree_id_idx": {
- "name": "workspaces_worktree_id_idx",
- "columns": [
- "worktree_id"
- ],
- "isUnique": false
- },
- "workspaces_last_opened_at_idx": {
- "name": "workspaces_last_opened_at_idx",
- "columns": [
- "last_opened_at"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "workspaces_project_id_projects_id_fk": {
- "name": "workspaces_project_id_projects_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "workspaces_worktree_id_worktrees_id_fk": {
- "name": "workspaces_worktree_id_worktrees_id_fk",
- "tableFrom": "workspaces",
- "tableTo": "worktrees",
- "columnsFrom": [
- "worktree_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- },
- "worktrees": {
- "name": "worktrees",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true,
- "autoincrement": false
- },
- "project_id": {
- "name": "project_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "path": {
- "name": "path",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "branch": {
- "name": "branch",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "base_branch": {
- "name": "base_branch",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "created_at": {
- "name": "created_at",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "autoincrement": false
- },
- "git_status": {
- "name": "git_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- },
- "github_status": {
- "name": "github_status",
- "type": "text",
- "primaryKey": false,
- "notNull": false,
- "autoincrement": false
- }
- },
- "indexes": {
- "worktrees_project_id_idx": {
- "name": "worktrees_project_id_idx",
- "columns": [
- "project_id"
- ],
- "isUnique": false
- },
- "worktrees_branch_idx": {
- "name": "worktrees_branch_idx",
- "columns": [
- "branch"
- ],
- "isUnique": false
- }
- },
- "foreignKeys": {
- "worktrees_project_id_projects_id_fk": {
- "name": "worktrees_project_id_projects_id_fk",
- "tableFrom": "worktrees",
- "tableTo": "projects",
- "columnsFrom": [
- "project_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "checkConstraints": {}
- }
- },
- "views": {},
- "enums": {},
- "_meta": {
- "schemas": {},
- "tables": {},
- "columns": {}
- },
- "internal": {
- "indexes": {}
- }
-}
\ No newline at end of file
diff --git a/packages/local-db/drizzle/meta/_journal.json b/packages/local-db/drizzle/meta/_journal.json
index 3b06ca4a7..3117a6e22 100644
--- a/packages/local-db/drizzle/meta/_journal.json
+++ b/packages/local-db/drizzle/meta/_journal.json
@@ -29,41 +29,6 @@
"when": 1766932805546,
"tag": "0003_add_confirm_on_quit_setting",
"breakpoints": true
- },
- {
- "idx": 4,
- "version": "6",
- "when": 1767166138761,
- "tag": "0004_add_terminal_link_behavior_setting",
- "breakpoints": true
- },
- {
- "idx": 5,
- "version": "6",
- "when": 1767166547886,
- "tag": "0005_add_navigation_style",
- "breakpoints": true
- },
- {
- "idx": 6,
- "version": "6",
- "when": 1767230000000,
- "tag": "0006_add_unique_branch_workspace_index",
- "breakpoints": true
- },
- {
- "idx": 7,
- "version": "6",
- "when": 1767350000000,
- "tag": "0007_add_workspace_is_unread",
- "breakpoints": true
- },
- {
- "idx": 8,
- "version": "6",
- "when": 1767548339097,
- "tag": "0008_add_group_tabs_position",
- "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/packages/local-db/src/schema/schema.ts b/packages/local-db/src/schema/schema.ts
index 4da25f609..9b0639805 100644
--- a/packages/local-db/src/schema/schema.ts
+++ b/packages/local-db/src/schema/schema.ts
@@ -5,7 +5,6 @@ import type {
ExternalApp,
GitHubStatus,
GitStatus,
- TerminalLinkBehavior,
TerminalPreset,
WorkspaceType,
} from "./zod";
@@ -101,24 +100,20 @@ export const workspaces = sqliteTable(
lastOpenedAt: integer("last_opened_at")
.notNull()
.$defaultFn(() => Date.now()),
- isUnread: integer("is_unread", { mode: "boolean" }).default(false),
},
(table) => [
index("workspaces_project_id_idx").on(table.projectId),
index("workspaces_worktree_id_idx").on(table.worktreeId),
index("workspaces_last_opened_at_idx").on(table.lastOpenedAt),
- // NOTE: Migration 0006 creates an additional partial unique index:
- // CREATE UNIQUE INDEX workspaces_unique_branch_per_project
- // ON workspaces(project_id) WHERE type = 'branch'
- // This enforces one branch workspace per project. Drizzle's schema DSL
- // doesn't support partial/filtered indexes, so this constraint is only
- // applied via the migration, not schema push. See migration 0006 for details.
],
);
export type InsertWorkspace = typeof workspaces.$inferInsert;
export type SelectWorkspace = typeof workspaces.$inferSelect;
+/**
+ * Settings table - single row with typed columns
+ */
export const settings = sqliteTable("settings", {
id: integer("id").primaryKey().default(1),
lastActiveWorkspaceId: text("last_active_workspace_id"),
@@ -132,9 +127,6 @@ export const settings = sqliteTable("settings", {
selectedRingtoneId: text("selected_ringtone_id"),
activeOrganizationId: text("active_organization_id"),
confirmOnQuit: integer("confirm_on_quit", { mode: "boolean" }),
- terminalLinkBehavior: text(
- "terminal_link_behavior",
- ).$type(),
});
export type InsertSettings = typeof settings.$inferInsert;
diff --git a/packages/local-db/src/schema/zod.ts b/packages/local-db/src/schema/zod.ts
index ca8221e40..bb33e1d15 100644
--- a/packages/local-db/src/schema/zod.ts
+++ b/packages/local-db/src/schema/zod.ts
@@ -96,13 +96,3 @@ export const EXTERNAL_APPS = [
] as const;
export type ExternalApp = (typeof EXTERNAL_APPS)[number];
-
-/**
- * Terminal link behavior options
- */
-export const TERMINAL_LINK_BEHAVIORS = [
- "external-editor",
- "file-viewer",
-] as const;
-
-export type TerminalLinkBehavior = (typeof TERMINAL_LINK_BEHAVIORS)[number];
diff --git a/packages/trpc/package.json b/packages/trpc/package.json
index 3a1f8edca..238b65aee 100644
--- a/packages/trpc/package.json
+++ b/packages/trpc/package.json
@@ -18,8 +18,8 @@
"typecheck": "tsc --noEmit --emitDeclarationOnly false"
},
"dependencies": {
- "@clerk/backend": "^2.27.0",
"@linear/sdk": "^68.1.0",
+ "@superset/auth": "workspace:*",
"@superset/db": "workspace:*",
"@superset/shared": "workspace:*",
"@t3-oss/env-core": "^0.13.8",
diff --git a/packages/trpc/src/env.ts b/packages/trpc/src/env.ts
index 34600e60b..f799bc134 100644
--- a/packages/trpc/src/env.ts
+++ b/packages/trpc/src/env.ts
@@ -6,7 +6,6 @@ export const env = createEnv({
NODE_ENV: z
.enum(["development", "production", "test"])
.default("development"),
- CLERK_SECRET_KEY: z.string().min(1),
BLOB_READ_WRITE_TOKEN: z.string().min(1),
POSTHOG_API_KEY: z.string(),
POSTHOG_API_HOST: z.string().url().default("https://us.posthog.com"),
diff --git a/packages/trpc/src/router/admin/admin.ts b/packages/trpc/src/router/admin/admin.ts
index c8bc2e956..bcc361405 100644
--- a/packages/trpc/src/router/admin/admin.ts
+++ b/packages/trpc/src/router/admin/admin.ts
@@ -1,53 +1,23 @@
import { db } from "@superset/db/client";
import { users } from "@superset/db/schema";
-import { TRPCError, type TRPCRouterRecord } from "@trpc/server";
-import { desc, eq, isNotNull, isNull } from "drizzle-orm";
+import type { TRPCRouterRecord } from "@trpc/server";
+import { desc, eq } from "drizzle-orm";
import { z } from "zod";
import { adminProcedure } from "../../trpc";
export const adminRouter = {
- listActiveUsers: adminProcedure.query(() => {
+ listUsers: adminProcedure.query(() => {
return db.query.users.findMany({
- where: isNull(users.deletedAt),
orderBy: desc(users.createdAt),
});
}),
- listDeletedUsers: adminProcedure.query(() => {
- return db.query.users.findMany({
- where: isNotNull(users.deletedAt),
- orderBy: desc(users.deletedAt),
- });
- }),
-
- restoreUser: adminProcedure
- .input(z.object({ userId: z.string().uuid() }))
+ deleteUser: adminProcedure
+ .input(z.object({ userId: z.string() }))
.mutation(async ({ input }) => {
- const [user] = await db
- .update(users)
- .set({ deletedAt: null })
- .where(eq(users.id, input.userId))
- .returning();
-
- if (!user) {
- throw new TRPCError({
- code: "NOT_FOUND",
- message: "User not found",
- });
- }
-
- return user;
- }),
-
- permanentlyDeleteUser: adminProcedure
- .input(z.object({ userId: z.string().uuid() }))
- .mutation(async () => {
- // TODO: Implement Clerk user deletion, avatar cleanup, etc.
- throw new TRPCError({
- code: "NOT_IMPLEMENTED",
- message:
- "Permanent deletion not yet implemented - requires Clerk cleanup",
- });
+ // Delete user - Better Auth handles cascading session cleanup
+ await db.delete(users).where(eq(users.id, input.userId));
+ return { success: true };
}),
} satisfies TRPCRouterRecord;
diff --git a/packages/trpc/src/router/analytics/analytics.ts b/packages/trpc/src/router/analytics/analytics.ts
index 11dc8796e..b996f2f41 100644
--- a/packages/trpc/src/router/analytics/analytics.ts
+++ b/packages/trpc/src/router/analytics/analytics.ts
@@ -25,7 +25,7 @@ export interface LeaderboardEntry {
userId: string;
name: string;
email: string;
- avatarUrl: string | null;
+ image: string | null;
count: number;
}
@@ -255,7 +255,7 @@ export const analyticsRouter = {
userId: user.id,
name: user.name,
email: user.email,
- avatarUrl: user.avatarUrl,
+ image: user.image,
count,
};
})
diff --git a/packages/trpc/src/router/integration/integration.ts b/packages/trpc/src/router/integration/integration.ts
index 56c05234a..7d0ba16e5 100644
--- a/packages/trpc/src/router/integration/integration.ts
+++ b/packages/trpc/src/router/integration/integration.ts
@@ -1,9 +1,5 @@
import { db } from "@superset/db/client";
-import {
- integrationConnections,
- organizationMembers,
- users,
-} from "@superset/db/schema";
+import { integrationConnections, members } from "@superset/db/schema";
import type { TRPCRouterRecord } from "@trpc/server";
import { and, eq } from "drizzle-orm";
import { z } from "zod";
@@ -14,19 +10,12 @@ export const integrationRouter = {
linear: linearRouter,
list: protectedProcedure
- .input(z.object({ organizationId: z.string().uuid() }))
+ .input(z.object({ organizationId: z.uuid() }))
.query(async ({ ctx, input }) => {
- const user = await db.query.users.findFirst({
- where: eq(users.clerkId, ctx.userId),
- });
- if (!user) {
- throw new Error("User not found");
- }
-
- const membership = await db.query.organizationMembers.findFirst({
+ const membership = await db.query.members.findFirst({
where: and(
- eq(organizationMembers.organizationId, input.organizationId),
- eq(organizationMembers.userId, user.id),
+ eq(members.organizationId, input.organizationId),
+ eq(members.userId, ctx.session.user.id),
),
});
if (!membership) {
diff --git a/packages/trpc/src/router/integration/linear/linear.ts b/packages/trpc/src/router/integration/linear/linear.ts
index dc10cdb08..47f43d48f 100644
--- a/packages/trpc/src/router/integration/linear/linear.ts
+++ b/packages/trpc/src/router/integration/linear/linear.ts
@@ -10,7 +10,7 @@ export const linearRouter = {
getConnection: protectedProcedure
.input(z.object({ organizationId: z.uuid() }))
.query(async ({ ctx, input }) => {
- await verifyOrgMembership(ctx.userId, input.organizationId);
+ await verifyOrgMembership(ctx.session.user.id, input.organizationId);
const connection = await db.query.integrationConnections.findFirst({
where: and(
eq(integrationConnections.organizationId, input.organizationId),
@@ -25,7 +25,7 @@ export const linearRouter = {
disconnect: protectedProcedure
.input(z.object({ organizationId: z.uuid() }))
.mutation(async ({ ctx, input }) => {
- await verifyOrgAdmin(ctx.userId, input.organizationId);
+ await verifyOrgAdmin(ctx.session.user.id, input.organizationId);
const result = await db
.delete(integrationConnections)
@@ -47,7 +47,7 @@ export const linearRouter = {
getTeams: protectedProcedure
.input(z.object({ organizationId: z.uuid() }))
.query(async ({ ctx, input }) => {
- await verifyOrgMembership(ctx.userId, input.organizationId);
+ await verifyOrgMembership(ctx.session.user.id, input.organizationId);
const client = await getLinearClient(input.organizationId);
if (!client) return [];
const teams = await client.teams();
@@ -62,7 +62,7 @@ export const linearRouter = {
}),
)
.mutation(async ({ ctx, input }) => {
- await verifyOrgAdmin(ctx.userId, input.organizationId);
+ await verifyOrgAdmin(ctx.session.user.id, input.organizationId);
const config: LinearConfig = {
provider: "linear",
diff --git a/packages/trpc/src/router/integration/linear/utils.ts b/packages/trpc/src/router/integration/linear/utils.ts
index 781a7ed5a..6afe04071 100644
--- a/packages/trpc/src/router/integration/linear/utils.ts
+++ b/packages/trpc/src/router/integration/linear/utils.ts
@@ -1,10 +1,6 @@
import { LinearClient } from "@linear/sdk";
import { db } from "@superset/db/client";
-import {
- integrationConnections,
- organizationMembers,
- users,
-} from "@superset/db/schema";
+import { integrationConnections, members } from "@superset/db/schema";
import { and, eq } from "drizzle-orm";
type Priority = "urgent" | "high" | "medium" | "low" | "none";
@@ -57,21 +53,13 @@ export async function getLinearClient(
}
export async function verifyOrgMembership(
- clerkUserId: string,
+ userId: string,
organizationId: string,
) {
- const user = await db.query.users.findFirst({
- where: eq(users.clerkId, clerkUserId),
- });
-
- if (!user) {
- throw new Error("User not found");
- }
-
- const membership = await db.query.organizationMembers.findFirst({
+ const membership = await db.query.members.findFirst({
where: and(
- eq(organizationMembers.organizationId, organizationId),
- eq(organizationMembers.userId, user.id),
+ eq(members.organizationId, organizationId),
+ eq(members.userId, userId),
),
});
@@ -79,21 +67,15 @@ export async function verifyOrgMembership(
throw new Error("Not a member of this organization");
}
- return { user, membership };
+ return { membership };
}
-export async function verifyOrgAdmin(
- clerkUserId: string,
- organizationId: string,
-) {
- const { user, membership } = await verifyOrgMembership(
- clerkUserId,
- organizationId,
- );
+export async function verifyOrgAdmin(userId: string, organizationId: string) {
+ const { membership } = await verifyOrgMembership(userId, organizationId);
- if (membership.role !== "admin") {
+ if (membership.role !== "admin" && membership.role !== "owner") {
throw new Error("Admin access required");
}
- return { user, membership };
+ return { membership };
}
diff --git a/packages/trpc/src/router/organization/organization.ts b/packages/trpc/src/router/organization/organization.ts
index 31057c1db..79adb907b 100644
--- a/packages/trpc/src/router/organization/organization.ts
+++ b/packages/trpc/src/router/organization/organization.ts
@@ -1,5 +1,5 @@
import { db } from "@superset/db/client";
-import { organizationMembers, organizations, users } from "@superset/db/schema";
+import { members, organizations } from "@superset/db/schema";
import type { TRPCRouterRecord } from "@trpc/server";
import { and, desc, eq } from "drizzle-orm";
import { z } from "zod";
@@ -52,24 +52,24 @@ export const organizationRouter = {
z.object({
name: z.string().min(1),
slug: z.string().min(1),
- githubOrg: z.string().optional(),
- avatarUrl: z.string().url().optional(),
+ logo: z.string().url().optional(),
}),
)
.mutation(async ({ ctx, input }) => {
- const user = await db.query.users.findFirst({
- where: eq(users.clerkId, ctx.userId),
- });
-
const [organization] = await db
.insert(organizations)
- .values(input)
+ .values({
+ name: input.name,
+ slug: input.slug,
+ logo: input.logo,
+ })
.returning();
- if (user && organization) {
- await db.insert(organizationMembers).values({
+ if (organization) {
+ await db.insert(members).values({
organizationId: organization.id,
- userId: user.id,
+ userId: ctx.session.user.id,
+ role: "owner",
});
}
@@ -79,10 +79,9 @@ export const organizationRouter = {
update: protectedProcedure
.input(
z.object({
- id: z.string().uuid(),
+ id: z.string(),
name: z.string().min(1).optional(),
- githubOrg: z.string().optional(),
- avatarUrl: z.string().url().optional(),
+ logo: z.string().url().optional(),
}),
)
.mutation(async ({ input }) => {
@@ -111,8 +110,12 @@ export const organizationRouter = {
)
.mutation(async ({ input }) => {
const [member] = await db
- .insert(organizationMembers)
- .values(input)
+ .insert(members)
+ .values({
+ organizationId: input.organizationId,
+ userId: input.userId,
+ role: "member",
+ })
.returning();
return member;
}),
@@ -126,11 +129,11 @@ export const organizationRouter = {
)
.mutation(async ({ input }) => {
await db
- .delete(organizationMembers)
+ .delete(members)
.where(
and(
- eq(organizationMembers.organizationId, input.organizationId),
- eq(organizationMembers.userId, input.userId),
+ eq(members.organizationId, input.organizationId),
+ eq(members.userId, input.userId),
),
);
return { success: true };
diff --git a/packages/trpc/src/router/task/task.ts b/packages/trpc/src/router/task/task.ts
index da1d9b620..a99b6de76 100644
--- a/packages/trpc/src/router/task/task.ts
+++ b/packages/trpc/src/router/task/task.ts
@@ -20,12 +20,12 @@ export const taskRouter = {
assignee: {
id: assignee.id,
name: assignee.name,
- avatarUrl: assignee.avatarUrl,
+ image: assignee.image,
},
creator: {
id: creator.id,
name: creator.name,
- avatarUrl: creator.avatarUrl,
+ image: creator.image,
},
})
.from(tasks)
@@ -74,19 +74,12 @@ export const taskRouter = {
create: protectedProcedure
.input(createTaskSchema)
.mutation(async ({ ctx, input }) => {
- const [user] = await dbWs
- .select()
- .from(users)
- .where(eq(users.clerkId, ctx.userId))
- .limit(1);
- if (!user) throw new Error("User not found");
-
const result = await dbWs.transaction(async (tx) => {
const [task] = await tx
.insert(tasks)
.values({
...input,
- creatorId: user.id,
+ creatorId: ctx.session.user.id,
labels: input.labels ?? [],
})
.returning();
diff --git a/packages/trpc/src/router/user/user.ts b/packages/trpc/src/router/user/user.ts
index d47cd4aa2..53aaaef10 100644
--- a/packages/trpc/src/router/user/user.ts
+++ b/packages/trpc/src/router/user/user.ts
@@ -1,38 +1,16 @@
import { db } from "@superset/db/client";
-import { organizationMembers, users } from "@superset/db/schema";
-import { TRPCError, type TRPCRouterRecord } from "@trpc/server";
+import { members } from "@superset/db/schema";
+import type { TRPCRouterRecord } from "@trpc/server";
import { eq } from "drizzle-orm";
import { protectedProcedure } from "../../trpc";
-import { syncUserFromClerk } from "./utils/sync-user-from-clerk";
export const userRouter = {
- me: protectedProcedure.query(async ({ ctx }) => {
- const existingUser = await db.query.users.findFirst({
- where: eq(users.clerkId, ctx.userId),
- });
-
- if (existingUser) {
- return existingUser;
- }
-
- return syncUserFromClerk(ctx.userId);
- }),
+ me: protectedProcedure.query(({ ctx }) => ctx.session.user),
myOrganization: protectedProcedure.query(async ({ ctx }) => {
- const user = await db.query.users.findFirst({
- where: eq(users.clerkId, ctx.userId),
- });
-
- if (!user) {
- throw new TRPCError({
- code: "INTERNAL_SERVER_ERROR",
- message: "User record not found",
- });
- }
-
- const membership = await db.query.organizationMembers.findFirst({
- where: eq(organizationMembers.userId, user.id),
+ const membership = await db.query.members.findFirst({
+ where: eq(members.userId, ctx.session.user.id),
with: {
organization: true,
},
@@ -42,19 +20,8 @@ export const userRouter = {
}),
myOrganizations: protectedProcedure.query(async ({ ctx }) => {
- const user = await db.query.users.findFirst({
- where: eq(users.clerkId, ctx.userId),
- });
-
- if (!user) {
- throw new TRPCError({
- code: "INTERNAL_SERVER_ERROR",
- message: "User record not found",
- });
- }
-
- const memberships = await db.query.organizationMembers.findMany({
- where: eq(organizationMembers.userId, user.id),
+ const memberships = await db.query.members.findMany({
+ where: eq(members.userId, ctx.session.user.id),
with: {
organization: true,
},
diff --git a/packages/trpc/src/router/user/utils/sync-user-from-clerk.ts b/packages/trpc/src/router/user/utils/sync-user-from-clerk.ts
deleted file mode 100644
index 7b8b24193..000000000
--- a/packages/trpc/src/router/user/utils/sync-user-from-clerk.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { createClerkClient } from "@clerk/backend";
-import { db } from "@superset/db/client";
-import { users } from "@superset/db/schema";
-import { put } from "@vercel/blob";
-import { eq } from "drizzle-orm";
-
-import { env } from "../../../env";
-
-const clerkClient = createClerkClient({
- secretKey: env.CLERK_SECRET_KEY,
-});
-
-async function uploadAvatar(
- imageUrl: string,
- userId: string,
-): Promise {
- try {
- const response = await fetch(imageUrl);
- if (!response.ok) return null;
-
- const blob = await response.blob();
- const { url } = await put(`users/${userId}/avatar.png`, blob, {
- access: "public",
- token: env.BLOB_READ_WRITE_TOKEN,
- });
- return url;
- } catch {
- return null;
- }
-}
-
-/**
- * Fetch user from Clerk and create in our database.
- * Only called when user doesn't exist locally.
- */
-export async function syncUserFromClerk(clerkId: string) {
- const clerkUser = await clerkClient.users.getUser(clerkId);
-
- const primaryEmail = clerkUser.emailAddresses.find(
- (email) => email.id === clerkUser.primaryEmailAddressId,
- )?.emailAddress;
-
- if (!primaryEmail) {
- return null;
- }
-
- const name =
- [clerkUser.firstName, clerkUser.lastName].filter(Boolean).join(" ") ||
- primaryEmail.split("@")[0] ||
- "User";
-
- // Upsert user - email is source of truth
- const [user] = await db
- .insert(users)
- .values({
- clerkId,
- email: primaryEmail,
- name,
- })
- .onConflictDoUpdate({
- target: users.email,
- set: {
- clerkId,
- name,
- },
- })
- .returning();
-
- if (!user) {
- return null;
- }
-
- // Upload avatar if needed
- if (!user.avatarUrl && clerkUser.imageUrl) {
- const avatarUrl = await uploadAvatar(clerkUser.imageUrl, user.id);
- if (avatarUrl) {
- await db.update(users).set({ avatarUrl }).where(eq(users.id, user.id));
- return { ...user, avatarUrl };
- }
- }
-
- return user;
-}
diff --git a/packages/trpc/src/trpc.ts b/packages/trpc/src/trpc.ts
index 8f0d1a0d5..2842f07a0 100644
--- a/packages/trpc/src/trpc.ts
+++ b/packages/trpc/src/trpc.ts
@@ -1,27 +1,14 @@
-import { db } from "@superset/db/client";
-import { users } from "@superset/db/schema";
+import type { Session } from "@superset/auth";
import { COMPANY } from "@superset/shared/constants";
import { initTRPC, TRPCError } from "@trpc/server";
-import { eq } from "drizzle-orm";
import superjson from "superjson";
import { ZodError } from "zod";
-/**
- * tRPC Context
- *
- * Simple auth context with just userId. Supports both:
- * - Clerk sessions (web/admin via cookies)
- * - Desktop auth (custom JWT tokens)
- */
export type TRPCContext = {
- userId: string | null;
+ session: Session | null;
};
-export const createTRPCContext = (opts: {
- userId: string | null;
-}): TRPCContext => {
- return { userId: opts.userId };
-};
+export const createTRPCContext = (opts: TRPCContext): TRPCContext => opts;
const t = initTRPC.context().create({
transformer: superjson,
@@ -44,42 +31,23 @@ export const createCallerFactory = t.createCallerFactory;
export const publicProcedure = t.procedure;
export const protectedProcedure = t.procedure.use(async ({ ctx, next }) => {
- if (!ctx.userId) {
+ if (!ctx.session) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "Not authenticated. Please sign in.",
});
}
- return next({
- ctx: {
- userId: ctx.userId,
- },
- });
+ return next({ ctx: { session: ctx.session } });
});
export const adminProcedure = protectedProcedure.use(async ({ ctx, next }) => {
- const user = await db.query.users.findFirst({
- where: eq(users.clerkId, ctx.userId),
- });
-
- if (!user) {
- throw new TRPCError({
- code: "UNAUTHORIZED",
- message: "User not found in database.",
- });
- }
-
- if (!user.email.endsWith(COMPANY.EMAIL_DOMAIN)) {
+ if (!ctx.session.user.email.endsWith(COMPANY.EMAIL_DOMAIN)) {
throw new TRPCError({
code: "FORBIDDEN",
message: `Admin access requires ${COMPANY.EMAIL_DOMAIN} email.`,
});
}
- return next({
- ctx: {
- user,
- },
- });
+ return next({ ctx });
});