diff --git a/app/lib/api/debug.ts b/app/.client/api/debug.ts similarity index 100% rename from app/lib/api/debug.ts rename to app/.client/api/debug.ts diff --git a/app/lib/api/notifications.ts b/app/.client/api/notifications.ts similarity index 94% rename from app/lib/api/notifications.ts rename to app/.client/api/notifications.ts index efd5a58..fc891b1 100644 --- a/app/lib/api/notifications.ts +++ b/app/.client/api/notifications.ts @@ -1,5 +1,5 @@ -import type { LogEntry } from '~/lib/stores/logs'; -import { logStore } from '~/lib/stores/logs'; +import type { LogEntry } from '~/stores/logs'; +import { logStore } from '~/stores/logs'; export interface Notification { id: string; diff --git a/app/lib/bridge/index.ts b/app/.client/bridge/index.ts similarity index 98% rename from app/lib/bridge/index.ts rename to app/.client/bridge/index.ts index b86d988..4ddb185 100644 --- a/app/lib/bridge/index.ts +++ b/app/.client/bridge/index.ts @@ -34,7 +34,7 @@ type SectionProps = { }; /** - * 构筑一个运行在 node 环境下的,editor 的 bridge。 + * 构筑一个无头的 editor 的 bridge。 * 所有操作编辑器的方法,都需要经由此 bridge 进行广播。 * 其内部所保存的 pages 与 sections 均为虚拟数据,与 editor 所需的实际数据有一定差异。 */ diff --git a/app/components/@settings/core/AvatarDropdown.tsx b/app/.client/components/@settings/core/AvatarDropdown.tsx similarity index 98% rename from app/components/@settings/core/AvatarDropdown.tsx rename to app/.client/components/@settings/core/AvatarDropdown.tsx index be49edc..123f0da 100644 --- a/app/components/@settings/core/AvatarDropdown.tsx +++ b/app/.client/components/@settings/core/AvatarDropdown.tsx @@ -2,7 +2,7 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; import classNames from 'classnames'; import { motion } from 'framer-motion'; import { useMemo } from 'react'; -import { useAuth } from '~/lib/hooks/useAuth'; +import { useAuth } from '~/.client/hooks/useAuth'; import type { TabType } from './types'; interface AvatarDropdownProps { diff --git a/app/components/@settings/core/ControlPanel.tsx b/app/.client/components/@settings/core/ControlPanel.tsx similarity index 90% rename from app/components/@settings/core/ControlPanel.tsx rename to app/.client/components/@settings/core/ControlPanel.tsx index a8e5f31..232db8e 100644 --- a/app/components/@settings/core/ControlPanel.tsx +++ b/app/.client/components/@settings/core/ControlPanel.tsx @@ -3,22 +3,24 @@ import * as RadixDialog from '@radix-ui/react-dialog'; import classNames from 'classnames'; import { AnimatePresence, motion, type Variants } from 'framer-motion'; import { useEffect, useMemo, useState } from 'react'; -import { TabTile } from '~/components/@settings/core/TabTile'; -import DebugTab from '~/components/@settings/tabs/debug/DebugTab'; -import { EventLogsTab } from '~/components/@settings/tabs/event-logs/EventLogsTab'; -import NotificationsTab from '~/components/@settings/tabs/notifications/NotificationsTab'; -import SettingsTab from '~/components/@settings/tabs/settings/SettingsTab'; -import TaskManagerTab from '~/components/@settings/tabs/task-manager/TaskManagerTab'; -import BackgroundRays from '~/components/ui/BackgroundRays'; -import { useDebugStatus } from '~/lib/hooks/useDebugStatus'; -import { useNotifications } from '~/lib/hooks/useNotifications'; -import { profileStore } from '~/lib/stores/profile'; -import { resetTabConfiguration, tabConfigurationStore } from '~/lib/stores/settings'; -import { logger } from '~/utils/logger'; +import { TabTile } from '~/.client/components/@settings/core/TabTile'; +import DebugTab from '~/.client/components/@settings/tabs/debug/DebugTab'; +import { EventLogsTab } from '~/.client/components/@settings/tabs/event-logs/EventLogsTab'; +import NotificationsTab from '~/.client/components/@settings/tabs/notifications/NotificationsTab'; +import SettingsTab from '~/.client/components/@settings/tabs/settings/SettingsTab'; +import TaskManagerTab from '~/.client/components/@settings/tabs/task-manager/TaskManagerTab'; +import BackgroundRays from '~/.client/components/ui/BackgroundRays'; +import { useDebugStatus } from '~/.client/hooks/useDebugStatus'; +import { useNotifications } from '~/.client/hooks/useNotifications'; +import { profileStore } from '~/.client/stores/profile'; +import { resetTabConfiguration, tabConfigurationStore } from '~/.client/stores/settings'; +import { createScopedLogger } from '~/utils/logger'; import { AvatarDropdown } from './AvatarDropdown'; import { DEFAULT_TAB_CONFIG, TAB_DESCRIPTIONS } from './constants'; import type { Profile, TabType, TabVisibilityConfig } from './types'; +const logger = createScopedLogger('ControlPanel'); + interface ControlPanelProps { open: boolean; onClose: () => void; @@ -83,8 +85,8 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { }; // Process tabs in priority order - tabConfiguration.developerTabs?.forEach((tab) => processTab(tab as BaseTabConfig)); - tabConfiguration.userTabs.forEach((tab) => processTab(tab as BaseTabConfig)); + tabConfiguration.developerTabs?.forEach((tab: any) => processTab(tab as BaseTabConfig)); + tabConfiguration.userTabs.forEach((tab: any) => processTab(tab as BaseTabConfig)); DEFAULT_TAB_CONFIG.forEach((tab) => processTab(tab as BaseTabConfig)); return devTabs.sort((a, b) => a.order - b.order); diff --git a/app/components/@settings/core/TabTile.tsx b/app/.client/components/@settings/core/TabTile.tsx similarity index 96% rename from app/components/@settings/core/TabTile.tsx rename to app/.client/components/@settings/core/TabTile.tsx index 9010be8..edef517 100644 --- a/app/components/@settings/core/TabTile.tsx +++ b/app/.client/components/@settings/core/TabTile.tsx @@ -1,8 +1,8 @@ import * as Tooltip from '@radix-ui/react-tooltip'; import classNames from 'classnames'; import { motion } from 'framer-motion'; -import { TAB_ICONS, TAB_LABELS } from '~/components/@settings/core/constants'; -import type { TabVisibilityConfig } from '~/components/@settings/core/types'; +import { TAB_ICONS, TAB_LABELS } from '~/.client/components/@settings/core/constants'; +import type { TabVisibilityConfig } from '~/.client/components/@settings/core/types'; interface TabTileProps { tab: TabVisibilityConfig; diff --git a/app/components/@settings/core/constants.ts b/app/.client/components/@settings/core/constants.ts similarity index 100% rename from app/components/@settings/core/constants.ts rename to app/.client/components/@settings/core/constants.ts diff --git a/app/components/@settings/core/types.ts b/app/.client/components/@settings/core/types.ts similarity index 100% rename from app/components/@settings/core/types.ts rename to app/.client/components/@settings/core/types.ts diff --git a/app/components/@settings/index.ts b/app/.client/components/@settings/index.ts similarity index 100% rename from app/components/@settings/index.ts rename to app/.client/components/@settings/index.ts diff --git a/app/components/@settings/tabs/debug/DebugTab.tsx b/app/.client/components/@settings/tabs/debug/DebugTab.tsx similarity index 99% rename from app/components/@settings/tabs/debug/DebugTab.tsx rename to app/.client/components/@settings/tabs/debug/DebugTab.tsx index 86aae95..1f3193e 100644 --- a/app/components/@settings/tabs/debug/DebugTab.tsx +++ b/app/.client/components/@settings/tabs/debug/DebugTab.tsx @@ -3,12 +3,12 @@ import classNames from 'classnames'; import { jsPDF } from 'jspdf'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { Badge } from '~/components/ui/Badge'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/components/ui/Collapsible'; -import { Dialog, DialogRoot, DialogTitle } from '~/components/ui/Dialog'; -import { Progress } from '~/components/ui/Progress'; -import { ScrollArea } from '~/components/ui/ScrollArea'; -import { type LogEntry, logStore } from '~/lib/stores/logs'; +import { Badge } from '~/.client/components/ui/Badge'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/.client/components/ui/Collapsible'; +import { Dialog, DialogRoot, DialogTitle } from '~/.client/components/ui/Dialog'; +import { Progress } from '~/.client/components/ui/Progress'; +import { ScrollArea } from '~/.client/components/ui/ScrollArea'; +import { type LogEntry, logStore } from '~/stores/logs'; interface SystemInfo { os: string; diff --git a/app/components/@settings/tabs/event-logs/EventLogsTab.tsx b/app/.client/components/@settings/tabs/event-logs/EventLogsTab.tsx similarity index 99% rename from app/components/@settings/tabs/event-logs/EventLogsTab.tsx rename to app/.client/components/@settings/tabs/event-logs/EventLogsTab.tsx index a66b1ca..1d0f6e1 100644 --- a/app/components/@settings/tabs/event-logs/EventLogsTab.tsx +++ b/app/.client/components/@settings/tabs/event-logs/EventLogsTab.tsx @@ -5,9 +5,9 @@ import { motion } from 'framer-motion'; import { jsPDF } from 'jspdf'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { toast } from 'sonner'; -import { Dialog, DialogRoot, DialogTitle } from '~/components/ui/Dialog'; -import { Switch } from '~/components/ui/Switch'; -import { type LogEntry, logStore } from '~/lib/stores/logs'; +import { Dialog, DialogRoot, DialogTitle } from '~/.client/components/ui/Dialog'; +import { Switch } from '~/.client/components/ui/Switch'; +import { type LogEntry, logStore } from '~/stores/logs'; interface SelectOption { value: string; diff --git a/app/components/@settings/tabs/notifications/NotificationsTab.tsx b/app/.client/components/@settings/tabs/notifications/NotificationsTab.tsx similarity index 99% rename from app/components/@settings/tabs/notifications/NotificationsTab.tsx rename to app/.client/components/@settings/tabs/notifications/NotificationsTab.tsx index c804146..496848b 100644 --- a/app/components/@settings/tabs/notifications/NotificationsTab.tsx +++ b/app/.client/components/@settings/tabs/notifications/NotificationsTab.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import { formatDistanceToNow } from 'date-fns'; import { motion } from 'framer-motion'; import { useEffect, useState } from 'react'; -import { logStore } from '~/lib/stores/logs'; +import { logStore } from '~/stores/logs'; interface NotificationDetails { type?: string; diff --git a/app/components/@settings/tabs/settings/SettingsTab.tsx b/app/.client/components/@settings/tabs/settings/SettingsTab.tsx similarity index 97% rename from app/components/@settings/tabs/settings/SettingsTab.tsx rename to app/.client/components/@settings/tabs/settings/SettingsTab.tsx index 07d4fe8..44f1241 100644 --- a/app/components/@settings/tabs/settings/SettingsTab.tsx +++ b/app/.client/components/@settings/tabs/settings/SettingsTab.tsx @@ -2,9 +2,9 @@ import classNames from 'classnames'; import { motion } from 'framer-motion'; import { useEffect, useState } from 'react'; import { toast } from 'sonner'; -import type { UserProfile } from '~/components/@settings/core/types'; -import { Switch } from '~/components/ui/Switch'; -import { isMac } from '~/utils/os'; +import type { UserProfile } from '~/.client/components/@settings/core/types'; +import { Switch } from '~/.client/components/ui/Switch'; +import { isMac } from '~/.client/utils/os'; // Helper to get modifier key symbols/text const getModifierSymbol = (modifier: string): string => { diff --git a/app/components/@settings/tabs/task-manager/TaskManagerTab.tsx b/app/.client/components/@settings/tabs/task-manager/TaskManagerTab.tsx similarity index 99% rename from app/components/@settings/tabs/task-manager/TaskManagerTab.tsx rename to app/.client/components/@settings/tabs/task-manager/TaskManagerTab.tsx index bdeb771..7c3cd68 100644 --- a/app/components/@settings/tabs/task-manager/TaskManagerTab.tsx +++ b/app/.client/components/@settings/tabs/task-manager/TaskManagerTab.tsx @@ -15,7 +15,7 @@ import * as React from 'react'; import { useCallback, useEffect, useState } from 'react'; import { Line } from 'react-chartjs-2'; import { toast } from 'sonner'; -import { tabConfigurationStore } from '~/lib/stores/settings'; +import { tabConfigurationStore } from '~/.client/stores/settings'; // Register ChartJS components ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend); diff --git a/app/components/@settings/utils/animations.ts b/app/.client/components/@settings/utils/animations.ts similarity index 100% rename from app/components/@settings/utils/animations.ts rename to app/.client/components/@settings/utils/animations.ts diff --git a/app/components/@settings/utils/tab-helpers.ts b/app/.client/components/@settings/utils/tab-helpers.ts similarity index 94% rename from app/components/@settings/utils/tab-helpers.ts rename to app/.client/components/@settings/utils/tab-helpers.ts index cec852e..deead1e 100644 --- a/app/components/@settings/utils/tab-helpers.ts +++ b/app/.client/components/@settings/utils/tab-helpers.ts @@ -1,5 +1,5 @@ -import { DEFAULT_TAB_CONFIG } from '~/components/@settings/core/constants'; -import type { TabType, TabVisibilityConfig } from '~/components/@settings/core/types'; +import { DEFAULT_TAB_CONFIG } from '~/.client/components/@settings/core/constants'; +import type { TabType, TabVisibilityConfig } from '~/.client/components/@settings/core/types'; export const getVisibleTabs = ( tabConfiguration: { userTabs: TabVisibilityConfig[]; developerTabs?: TabVisibilityConfig[] }, diff --git a/app/components/AuthErrorToast.client.tsx b/app/.client/components/AuthErrorToast.client.tsx similarity index 100% rename from app/components/AuthErrorToast.client.tsx rename to app/.client/components/AuthErrorToast.client.tsx diff --git a/app/components/ErrorBoundary.tsx b/app/.client/components/ErrorBoundary.tsx similarity index 100% rename from app/components/ErrorBoundary.tsx rename to app/.client/components/ErrorBoundary.tsx diff --git a/app/components/auth/AuthButtons.tsx b/app/.client/components/auth/AuthButtons.tsx similarity index 94% rename from app/components/auth/AuthButtons.tsx rename to app/.client/components/auth/AuthButtons.tsx index c062c9b..982ca26 100644 --- a/app/components/auth/AuthButtons.tsx +++ b/app/.client/components/auth/AuthButtons.tsx @@ -1,7 +1,7 @@ import { useNavigate } from '@remix-run/react'; import { useEffect, useState } from 'react'; -import { Button } from '~/components/ui/Button'; -import { useAuth } from '~/lib/hooks/useAuth'; +import { Button } from '~/.client/components/ui/Button'; +import { useAuth } from '~/.client/hooks/useAuth'; export function SignInButton({ className, children = '登录' }: { className?: string; children?: React.ReactNode }) { const { signIn, isAuthenticated } = useAuth(); diff --git a/app/components/auth/UserProfile.tsx b/app/.client/components/auth/UserProfile.tsx similarity index 94% rename from app/components/auth/UserProfile.tsx rename to app/.client/components/auth/UserProfile.tsx index bf0d6d7..8318b13 100644 --- a/app/components/auth/UserProfile.tsx +++ b/app/.client/components/auth/UserProfile.tsx @@ -1,4 +1,4 @@ -import { useAuth } from '~/lib/hooks/useAuth'; +import { useAuth } from '~/.client/hooks/useAuth'; export function UserProfile({ className }: { className?: string }) { const { isAuthenticated, userInfo, isLoading } = useAuth(); diff --git a/app/components/chat/Artifact.tsx b/app/.client/components/chat/Artifact.tsx similarity index 97% rename from app/components/chat/Artifact.tsx rename to app/.client/components/chat/Artifact.tsx index d741aa2..9baaf61 100644 --- a/app/components/chat/Artifact.tsx +++ b/app/.client/components/chat/Artifact.tsx @@ -4,9 +4,9 @@ import { AnimatePresence, motion } from 'framer-motion'; import { computed } from 'nanostores'; import { memo, useEffect, useMemo, useRef, useState } from 'react'; import { type BundledLanguage, type BundledTheme, createHighlighter, type HighlighterGeneric } from 'shiki'; -import type { ActionState } from '~/lib/runtime/action-runner'; -import { webBuilderStore } from '~/lib/stores/web-builder'; -import { cubicEasingFn } from '~/utils/easings'; +import type { ActionState } from '~/.client/runtime/action-runner'; +import { webBuilderStore } from '~/.client/stores/web-builder'; +import { cubicEasingFn } from '~/.client/utils/easings'; const highlighterOptions = { langs: ['shell'], diff --git a/app/components/chat/AssistantMessage.tsx b/app/.client/components/chat/AssistantMessage.tsx similarity index 92% rename from app/components/chat/AssistantMessage.tsx rename to app/.client/components/chat/AssistantMessage.tsx index 269b0b9..87ea7c3 100644 --- a/app/components/chat/AssistantMessage.tsx +++ b/app/.client/components/chat/AssistantMessage.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; -import Popover from '~/components/ui/Popover'; -import Tooltip from '~/components/ui/Tooltip'; -import type { ParsedUIMessage } from '~/lib/stores/ai-state'; +import Popover from '~/.client/components/ui/Popover'; +import Tooltip from '~/.client/components/ui/Tooltip'; +import type { ParsedUIMessage } from '~/.client/stores/ai-state'; import { Markdown } from './Markdown'; export const AssistantMessage = memo(({ message }: { message: ParsedUIMessage }) => { diff --git a/app/components/chat/BaseChat.module.scss b/app/.client/components/chat/BaseChat.module.scss similarity index 100% rename from app/components/chat/BaseChat.module.scss rename to app/.client/components/chat/BaseChat.module.scss diff --git a/app/components/chat/Chat.client.tsx b/app/.client/components/chat/Chat.client.tsx similarity index 95% rename from app/components/chat/Chat.client.tsx rename to app/.client/components/chat/Chat.client.tsx index 5907f67..1c21b00 100644 --- a/app/components/chat/Chat.client.tsx +++ b/app/.client/components/chat/Chat.client.tsx @@ -5,10 +5,10 @@ import classNames from 'classnames'; import { useAnimate } from 'framer-motion'; import { useEffect, useState } from 'react'; import { ClientOnly } from 'remix-utils/client-only'; -import { useShortcuts, useSnapScroll } from '~/lib/hooks'; -import { useChatMessage } from '~/lib/hooks/useChatMessage'; -import { aiState, setChatId, setChatStarted } from '~/lib/stores/ai-state'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import { useShortcuts, useSnapScroll } from '~/.client/hooks'; +import { useChatMessage } from '~/.client/hooks/useChatMessage'; +import { aiState, setChatId, setChatStarted } from '~/.client/stores/ai-state'; +import { webBuilderStore } from '~/.client/stores/web-builder'; import type { ChatMessage, ChatWithMessages } from '~/types/chat'; import { renderLogger } from '~/utils/logger'; import { Menu } from '../sidebar/Menu.client'; diff --git a/app/components/chat/ChatAlert.tsx b/app/.client/components/chat/ChatAlert.tsx similarity index 98% rename from app/components/chat/ChatAlert.tsx rename to app/.client/components/chat/ChatAlert.tsx index 8c02a2b..81fefe4 100644 --- a/app/components/chat/ChatAlert.tsx +++ b/app/.client/components/chat/ChatAlert.tsx @@ -2,7 +2,7 @@ import { useStore } from '@nanostores/react'; import classNames from 'classnames'; import { AnimatePresence, motion } from 'framer-motion'; import { useCallback, useMemo } from 'react'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import { webBuilderStore } from '~/.client/stores/web-builder'; interface Props { postMessage: (message: string) => void; diff --git a/app/components/chat/ChatTextarea.tsx b/app/.client/components/chat/ChatTextarea.tsx similarity index 98% rename from app/components/chat/ChatTextarea.tsx rename to app/.client/components/chat/ChatTextarea.tsx index 4548532..50c6ae1 100644 --- a/app/components/chat/ChatTextarea.tsx +++ b/app/.client/components/chat/ChatTextarea.tsx @@ -2,8 +2,8 @@ import { useStore } from '@nanostores/react'; import classNames from 'classnames'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { ClientOnly } from 'remix-utils/client-only'; -import { useAuth, usePromptEnhancer } from '~/lib/hooks'; -import { aiState } from '~/lib/stores/ai-state'; +import { useAuth, usePromptEnhancer } from '~/.client/hooks'; +import { aiState } from '~/.client/stores/ai-state'; import { IconButton } from '../ui/IconButton'; import { SendButton } from './SendButton.client'; diff --git a/app/components/chat/CodeBlock.module.scss b/app/.client/components/chat/CodeBlock.module.scss similarity index 100% rename from app/components/chat/CodeBlock.module.scss rename to app/.client/components/chat/CodeBlock.module.scss diff --git a/app/components/chat/CodeBlock.tsx b/app/.client/components/chat/CodeBlock.tsx similarity index 100% rename from app/components/chat/CodeBlock.tsx rename to app/.client/components/chat/CodeBlock.tsx diff --git a/app/components/chat/ElementEditPreview.tsx b/app/.client/components/chat/ElementEditPreview.tsx similarity index 97% rename from app/components/chat/ElementEditPreview.tsx rename to app/.client/components/chat/ElementEditPreview.tsx index 0f748ed..849fcfd 100644 --- a/app/components/chat/ElementEditPreview.tsx +++ b/app/.client/components/chat/ElementEditPreview.tsx @@ -1,7 +1,7 @@ import { AnimatePresence, motion } from 'framer-motion'; import React, { useState } from 'react'; +import { cubicEasingFn } from '~/.client/utils/easings'; import type { ElementInfoMetadata } from '~/types/message'; -import { cubicEasingFn } from '~/utils/easings'; import { ElementPreview } from './ElementPreview'; interface ElementEditPreviewProps { diff --git a/app/components/chat/ElementPreview.tsx b/app/.client/components/chat/ElementPreview.tsx similarity index 100% rename from app/components/chat/ElementPreview.tsx rename to app/.client/components/chat/ElementPreview.tsx diff --git a/app/components/chat/ExamplePrompts.tsx b/app/.client/components/chat/ExamplePrompts.tsx similarity index 100% rename from app/components/chat/ExamplePrompts.tsx rename to app/.client/components/chat/ExamplePrompts.tsx diff --git a/app/components/chat/FilePreview.tsx b/app/.client/components/chat/FilePreview.tsx similarity index 100% rename from app/components/chat/FilePreview.tsx rename to app/.client/components/chat/FilePreview.tsx diff --git a/app/components/chat/Markdown.module.scss b/app/.client/components/chat/Markdown.module.scss similarity index 100% rename from app/components/chat/Markdown.module.scss rename to app/.client/components/chat/Markdown.module.scss diff --git a/app/components/chat/Markdown.spec.ts b/app/.client/components/chat/Markdown.spec.ts similarity index 100% rename from app/components/chat/Markdown.spec.ts rename to app/.client/components/chat/Markdown.spec.ts diff --git a/app/components/chat/Markdown.tsx b/app/.client/components/chat/Markdown.tsx similarity index 100% rename from app/components/chat/Markdown.tsx rename to app/.client/components/chat/Markdown.tsx diff --git a/app/components/chat/Messages.client.tsx b/app/.client/components/chat/Messages.client.tsx similarity index 95% rename from app/components/chat/Messages.client.tsx rename to app/.client/components/chat/Messages.client.tsx index a64edc6..33b780c 100644 --- a/app/components/chat/Messages.client.tsx +++ b/app/.client/components/chat/Messages.client.tsx @@ -4,11 +4,11 @@ import classNames from 'classnames'; import type { ForwardedRef } from 'react'; import { Fragment, forwardRef, memo, useEffect, useMemo, useRef } from 'react'; import { toast } from 'sonner'; -import WithTooltip from '~/components/ui/Tooltip'; -import { useAuth } from '~/lib/hooks/useAuth'; -import { useChatOperate } from '~/lib/hooks/useChatOperate'; -import { useSnapScroll } from '~/lib/hooks/useSnapScroll'; -import { aiState, type ParsedUIMessage } from '~/lib/stores/ai-state'; +import WithTooltip from '~/.client/components/ui/Tooltip'; +import { useAuth } from '~/.client/hooks/useAuth'; +import { useChatOperate } from '~/.client/hooks/useChatOperate'; +import { useSnapScroll } from '~/.client/hooks/useSnapScroll'; +import { aiState, type ParsedUIMessage } from '~/.client/stores/ai-state'; import { AssistantMessage } from './AssistantMessage'; import styles from './Messages.module.scss'; import { UserMessage } from './UserMessage'; diff --git a/app/components/chat/Messages.module.scss b/app/.client/components/chat/Messages.module.scss similarity index 100% rename from app/components/chat/Messages.module.scss rename to app/.client/components/chat/Messages.module.scss diff --git a/app/components/chat/ModelSelector.tsx b/app/.client/components/chat/ModelSelector.tsx similarity index 99% rename from app/components/chat/ModelSelector.tsx rename to app/.client/components/chat/ModelSelector.tsx index 2989c7f..9866daf 100644 --- a/app/components/chat/ModelSelector.tsx +++ b/app/.client/components/chat/ModelSelector.tsx @@ -1,7 +1,7 @@ import classNames from 'classnames'; import type { KeyboardEvent } from 'react'; import { useEffect, useRef, useState } from 'react'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { ProviderInfo } from '~/types/model'; interface ModelSelectorProps { diff --git a/app/components/chat/NetlifyDeploymentLink.client.tsx b/app/.client/components/chat/NetlifyDeploymentLink.client.tsx similarity index 95% rename from app/components/chat/NetlifyDeploymentLink.client.tsx rename to app/.client/components/chat/NetlifyDeploymentLink.client.tsx index bd24090..ce1c2fd 100644 --- a/app/components/chat/NetlifyDeploymentLink.client.tsx +++ b/app/.client/components/chat/NetlifyDeploymentLink.client.tsx @@ -1,6 +1,6 @@ import * as Tooltip from '@radix-ui/react-tooltip'; import { useEffect, useState } from 'react'; -import { useChatDeployment } from '~/lib/hooks/useChatDeployment'; +import { useChatDeployment } from '~/.client/hooks/useChatDeployment'; import { DeploymentPlatformEnum } from '~/types/deployment'; export function NetlifyDeploymentLink() { diff --git a/app/components/chat/ProgressCompilation.tsx b/app/.client/components/chat/ProgressCompilation.tsx similarity index 98% rename from app/components/chat/ProgressCompilation.tsx rename to app/.client/components/chat/ProgressCompilation.tsx index eb3403f..ee6b0f8 100644 --- a/app/components/chat/ProgressCompilation.tsx +++ b/app/.client/components/chat/ProgressCompilation.tsx @@ -1,8 +1,8 @@ import classNames from 'classnames'; import { AnimatePresence, motion } from 'framer-motion'; import { useMemo, useState } from 'react'; +import { cubicEasingFn } from '~/.client/utils/easings'; import type { ProgressAnnotation } from '~/types/message'; -import { cubicEasingFn } from '~/utils/easings'; export default function ProgressCompilation({ data }: { data?: ProgressAnnotation[] }) { const [expanded, setExpanded] = useState(false); diff --git a/app/components/chat/ScreenshotStateManager.tsx b/app/.client/components/chat/ScreenshotStateManager.tsx similarity index 100% rename from app/components/chat/ScreenshotStateManager.tsx rename to app/.client/components/chat/ScreenshotStateManager.tsx diff --git a/app/components/chat/SendButton.client.tsx b/app/.client/components/chat/SendButton.client.tsx similarity index 100% rename from app/components/chat/SendButton.client.tsx rename to app/.client/components/chat/SendButton.client.tsx diff --git a/app/components/chat/SpeechRecognition.tsx b/app/.client/components/chat/SpeechRecognition.tsx similarity index 91% rename from app/components/chat/SpeechRecognition.tsx rename to app/.client/components/chat/SpeechRecognition.tsx index f9e8445..740bc64 100644 --- a/app/components/chat/SpeechRecognition.tsx +++ b/app/.client/components/chat/SpeechRecognition.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames'; -import { IconButton } from '~/components/ui/IconButton'; +import { IconButton } from '~/.client/components/ui/IconButton'; export const SpeechRecognitionButton = ({ isListening, diff --git a/app/components/chat/ThoughtBox.tsx b/app/.client/components/chat/ThoughtBox.tsx similarity index 100% rename from app/components/chat/ThoughtBox.tsx rename to app/.client/components/chat/ThoughtBox.tsx diff --git a/app/components/chat/UserMessage.tsx b/app/.client/components/chat/UserMessage.tsx similarity index 94% rename from app/components/chat/UserMessage.tsx rename to app/.client/components/chat/UserMessage.tsx index e87f040..fc9ea61 100644 --- a/app/components/chat/UserMessage.tsx +++ b/app/.client/components/chat/UserMessage.tsx @@ -1,6 +1,6 @@ import type { FileUIPart } from 'ai'; +import { MODEL_REGEX, PROVIDER_REGEX } from '~/.client/utils/constants'; import type { UPageUIMessage } from '~/types/message'; -import { MODEL_REGEX, PROVIDER_REGEX } from '~/utils/constants'; import { ElementEditPreview } from './ElementEditPreview'; import { Markdown } from './Markdown'; diff --git a/app/components/chat/VercelDeploymentLink.client.tsx b/app/.client/components/chat/VercelDeploymentLink.client.tsx similarity index 95% rename from app/components/chat/VercelDeploymentLink.client.tsx rename to app/.client/components/chat/VercelDeploymentLink.client.tsx index 92248c4..81affb9 100644 --- a/app/components/chat/VercelDeploymentLink.client.tsx +++ b/app/.client/components/chat/VercelDeploymentLink.client.tsx @@ -1,6 +1,6 @@ import * as Tooltip from '@radix-ui/react-tooltip'; import { useEffect, useState } from 'react'; -import { useChatDeployment } from '~/lib/hooks/useChatDeployment'; +import { useChatDeployment } from '~/.client/hooks/useChatDeployment'; import { DeploymentPlatformEnum } from '~/types/deployment'; export function VercelDeploymentLink() { diff --git a/app/components/chat/_1PanelDeploymentLink.client.tsx b/app/.client/components/chat/_1PanelDeploymentLink.client.tsx similarity index 95% rename from app/components/chat/_1PanelDeploymentLink.client.tsx rename to app/.client/components/chat/_1PanelDeploymentLink.client.tsx index 5587ba8..2a4ac7b 100644 --- a/app/components/chat/_1PanelDeploymentLink.client.tsx +++ b/app/.client/components/chat/_1PanelDeploymentLink.client.tsx @@ -1,6 +1,6 @@ import * as Tooltip from '@radix-ui/react-tooltip'; import { useEffect, useState } from 'react'; -import { useChatDeployment } from '~/lib/hooks/useChatDeployment'; +import { useChatDeployment } from '~/.client/hooks/useChatDeployment'; import { DeploymentPlatformEnum } from '~/types/deployment'; export function _1PanelDeploymentLink() { diff --git a/app/components/chat/chatExportAndImport/ExportChatButton.tsx b/app/.client/components/chat/chatExportAndImport/ExportChatButton.tsx similarity index 71% rename from app/components/chat/chatExportAndImport/ExportChatButton.tsx rename to app/.client/components/chat/chatExportAndImport/ExportChatButton.tsx index 348a735..58b18d2 100644 --- a/app/components/chat/chatExportAndImport/ExportChatButton.tsx +++ b/app/.client/components/chat/chatExportAndImport/ExportChatButton.tsx @@ -1,5 +1,5 @@ -import { IconButton } from '~/components/ui/IconButton'; -import WithTooltip from '~/components/ui/Tooltip'; +import { IconButton } from '~/.client/components/ui/IconButton'; +import WithTooltip from '~/.client/components/ui/Tooltip'; export const ExportChatButton = ({ exportChat }: { exportChat?: () => void }) => { return ( diff --git a/app/components/chat/usage/ChatUsageDialog.tsx b/app/.client/components/chat/usage/ChatUsageDialog.tsx similarity index 99% rename from app/components/chat/usage/ChatUsageDialog.tsx rename to app/.client/components/chat/usage/ChatUsageDialog.tsx index 540b039..9368eda 100644 --- a/app/components/chat/usage/ChatUsageDialog.tsx +++ b/app/.client/components/chat/usage/ChatUsageDialog.tsx @@ -2,7 +2,7 @@ import * as RadixDialog from '@radix-ui/react-dialog'; import classNames from 'classnames'; import { motion, type Transition, type Variants } from 'framer-motion'; import { memo } from 'react'; -import { useChatUsage } from '~/lib/hooks/useChatUsage'; +import { useChatUsage } from '~/.client/hooks/useChatUsage'; import { DialogDescription, DialogTitle } from '../../ui/Dialog'; import { IconButton } from '../../ui/IconButton'; import { ChatUsageVisualization } from './ChatUsageVisualization'; diff --git a/app/components/chat/usage/ChatUsageVisualization.tsx b/app/.client/components/chat/usage/ChatUsageVisualization.tsx similarity index 98% rename from app/components/chat/usage/ChatUsageVisualization.tsx rename to app/.client/components/chat/usage/ChatUsageVisualization.tsx index e1f3145..3445b69 100644 --- a/app/components/chat/usage/ChatUsageVisualization.tsx +++ b/app/.client/components/chat/usage/ChatUsageVisualization.tsx @@ -14,8 +14,8 @@ import { import classNames from 'classnames'; import { useMemo } from 'react'; import { Doughnut, Line, Pie } from 'react-chartjs-2'; -import type { ChatUsageStats } from '~/lib/hooks/useChatUsage'; -import { themeStore } from '~/lib/stores/theme'; +import type { ChatUsageStats } from '~/.client/hooks/useChatUsage'; +import { themeStore } from '~/stores/theme'; ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend, ArcElement, PointElement, LineElement); diff --git a/app/components/chat/usage/DeploymentRecordsDialog.tsx b/app/.client/components/chat/usage/DeploymentRecordsDialog.tsx similarity index 99% rename from app/components/chat/usage/DeploymentRecordsDialog.tsx rename to app/.client/components/chat/usage/DeploymentRecordsDialog.tsx index c07b9a4..f3cec17 100644 --- a/app/components/chat/usage/DeploymentRecordsDialog.tsx +++ b/app/.client/components/chat/usage/DeploymentRecordsDialog.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import { motion, type Transition, type Variants } from 'framer-motion'; import { memo, useCallback, useEffect, useRef, useState } from 'react'; import { toast } from 'sonner'; -import { type DeploymentRecord, useDeploymentRecords } from '~/lib/hooks/useDeploymentRecords'; +import { type DeploymentRecord, useDeploymentRecords } from '~/.client/hooks/useDeploymentRecords'; import { DeploymentPlatformEnum, DeploymentStatusEnum } from '~/types/deployment'; import { ConfirmationDialog, DialogDescription, DialogTitle } from '../../ui/Dialog'; import { IconButton } from '../../ui/IconButton'; diff --git a/app/components/editor/EditDialog.tsx b/app/.client/components/editor/EditDialog.tsx similarity index 98% rename from app/components/editor/EditDialog.tsx rename to app/.client/components/editor/EditDialog.tsx index f99a944..6844bcc 100644 --- a/app/components/editor/EditDialog.tsx +++ b/app/.client/components/editor/EditDialog.tsx @@ -1,5 +1,5 @@ import React, { useRef } from 'react'; -import { sendChatMessageStore } from '~/lib/stores/chat-message'; +import { sendChatMessageStore } from '~/.client/stores/chat-message'; import { DefaultEditor } from './editors/DefaultEditor'; import type { EditorProps } from './editors/EditorProps'; import { IconEditor } from './editors/IconEditor'; diff --git a/app/components/editor/Editor.tsx b/app/.client/components/editor/Editor.tsx similarity index 96% rename from app/components/editor/Editor.tsx rename to app/.client/components/editor/Editor.tsx index 827cb1e..c22aa8a 100644 --- a/app/components/editor/Editor.tsx +++ b/app/.client/components/editor/Editor.tsx @@ -1,10 +1,10 @@ import { memo, useCallback, useEffect, useRef } from 'react'; -import { useChatHistory } from '~/lib/persistence'; +import { useChatHistory } from '~/.client/persistence'; +import { isValidContent } from '~/.client/utils/html-parse'; +import { throttleWithTrailing } from '~/.client/utils/throttle'; import type { Section } from '~/types/actions'; import type { DocumentProperties, Editor } from '~/types/editor'; -import { isValidContent } from '~/utils/html-parse'; import { logger } from '~/utils/logger'; -import { throttleWithTrailing } from '~/utils/throttle'; import { EditorComponent } from './EditorComponent'; export interface ScrollPosition { diff --git a/app/components/editor/EditorComponent.tsx b/app/.client/components/editor/EditorComponent.tsx similarity index 98% rename from app/components/editor/EditorComponent.tsx rename to app/.client/components/editor/EditorComponent.tsx index cd8d1d3..5707669 100644 --- a/app/components/editor/EditorComponent.tsx +++ b/app/.client/components/editor/EditorComponent.tsx @@ -1,6 +1,6 @@ import type { RefObject } from 'react'; import { createRef, useCallback, useEffect, useRef } from 'react'; -import { useEditorCommands } from '~/lib/hooks'; +import { useEditorCommands } from '~/.client/hooks'; import type { DocumentProperties, Editor } from '~/types/editor'; import { EditorController } from './EditorController'; import { EditorRender } from './EditorRender'; diff --git a/app/components/editor/EditorController.tsx b/app/.client/components/editor/EditorController.tsx similarity index 97% rename from app/components/editor/EditorController.tsx rename to app/.client/components/editor/EditorController.tsx index 621583d..0617fdf 100644 --- a/app/components/editor/EditorController.tsx +++ b/app/.client/components/editor/EditorController.tsx @@ -1,6 +1,6 @@ +import { executeScript } from '~/.client/utils/execute-scripts'; +import { isScriptContent } from '~/.client/utils/html-parse'; import type { Editor, EditorControllerProps } from '~/types/editor'; -import { executeScript } from '~/utils/execute-scripts'; -import { isScriptContent } from '~/utils/html-parse'; export class EditorController implements Editor { private props: EditorControllerProps; diff --git a/app/components/editor/EditorOverlay.tsx b/app/.client/components/editor/EditorOverlay.tsx similarity index 100% rename from app/components/editor/EditorOverlay.tsx rename to app/.client/components/editor/EditorOverlay.tsx diff --git a/app/components/editor/EditorRender.tsx b/app/.client/components/editor/EditorRender.tsx similarity index 100% rename from app/components/editor/EditorRender.tsx rename to app/.client/components/editor/EditorRender.tsx diff --git a/app/components/editor/PageRender.tsx b/app/.client/components/editor/PageRender.tsx similarity index 99% rename from app/components/editor/PageRender.tsx rename to app/.client/components/editor/PageRender.tsx index f9fdb14..6c206d0 100644 --- a/app/components/editor/PageRender.tsx +++ b/app/.client/components/editor/PageRender.tsx @@ -1,9 +1,9 @@ import { motion, type Variants } from 'framer-motion'; import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'; import Frame from 'react-frame-component'; +import { executeScripts } from '~/.client/utils/execute-scripts'; +import { isMac } from '~/.client/utils/os'; import type { DocumentProperties } from '~/types/editor'; -import { executeScripts } from '~/utils/execute-scripts'; -import { isMac } from '~/utils/os'; import { EditorOverlay } from './EditorOverlay'; export interface PageRenderRef { diff --git a/app/components/editor/editors/DefaultEditor.tsx b/app/.client/components/editor/editors/DefaultEditor.tsx similarity index 100% rename from app/components/editor/editors/DefaultEditor.tsx rename to app/.client/components/editor/editors/DefaultEditor.tsx diff --git a/app/components/editor/editors/EditorProps.ts b/app/.client/components/editor/editors/EditorProps.ts similarity index 100% rename from app/components/editor/editors/EditorProps.ts rename to app/.client/components/editor/editors/EditorProps.ts diff --git a/app/components/editor/editors/IconEditor.tsx b/app/.client/components/editor/editors/IconEditor.tsx similarity index 100% rename from app/components/editor/editors/IconEditor.tsx rename to app/.client/components/editor/editors/IconEditor.tsx diff --git a/app/components/editor/editors/ImageEditor.tsx b/app/.client/components/editor/editors/ImageEditor.tsx similarity index 100% rename from app/components/editor/editors/ImageEditor.tsx rename to app/.client/components/editor/editors/ImageEditor.tsx diff --git a/app/components/editor/editors/LinkEditor.tsx b/app/.client/components/editor/editors/LinkEditor.tsx similarity index 100% rename from app/components/editor/editors/LinkEditor.tsx rename to app/.client/components/editor/editors/LinkEditor.tsx diff --git a/app/components/editor/editors/TextEditor.tsx b/app/.client/components/editor/editors/TextEditor.tsx similarity index 100% rename from app/components/editor/editors/TextEditor.tsx rename to app/.client/components/editor/editors/TextEditor.tsx diff --git a/app/components/editor/editors/index.ts b/app/.client/components/editor/editors/index.ts similarity index 100% rename from app/components/editor/editors/index.ts rename to app/.client/components/editor/editors/index.ts diff --git a/app/components/editor/icons/close.svg b/app/.client/components/editor/icons/close.svg similarity index 100% rename from app/components/editor/icons/close.svg rename to app/.client/components/editor/icons/close.svg diff --git a/app/components/editor/icons/loading.svg b/app/.client/components/editor/icons/loading.svg similarity index 100% rename from app/components/editor/icons/loading.svg rename to app/.client/components/editor/icons/loading.svg diff --git a/app/components/editor/icons/send.svg b/app/.client/components/editor/icons/send.svg similarity index 100% rename from app/components/editor/icons/send.svg rename to app/.client/components/editor/icons/send.svg diff --git a/app/components/editor/icons/upload.svg b/app/.client/components/editor/icons/upload.svg similarity index 100% rename from app/components/editor/icons/upload.svg rename to app/.client/components/editor/icons/upload.svg diff --git a/app/components/header/ChatDescription.client.tsx b/app/.client/components/header/ChatDescription.client.tsx similarity index 91% rename from app/components/header/ChatDescription.client.tsx rename to app/.client/components/header/ChatDescription.client.tsx index cd5c682..2d7f384 100644 --- a/app/components/header/ChatDescription.client.tsx +++ b/app/.client/components/header/ChatDescription.client.tsx @@ -1,10 +1,10 @@ import { useStore } from '@nanostores/react'; import { TooltipProvider } from '@radix-ui/react-tooltip'; import { useEffect } from 'react'; -import WithTooltip from '~/components/ui/Tooltip'; -import { useEditChatDescription } from '~/lib/hooks'; -import { useChatHistory } from '~/lib/hooks/useChatHistory'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import WithTooltip from '~/.client/components/ui/Tooltip'; +import { useEditChatDescription } from '~/.client/hooks'; +import { useChatHistory } from '~/.client/hooks/useChatHistory'; +import { webBuilderStore } from '~/.client/stores/web-builder'; export function ChatDescription() { const { getChatLatestDescription } = useChatHistory(); diff --git a/app/components/header/DeployTo1PanelDialog.tsx b/app/.client/components/header/DeployTo1PanelDialog.tsx similarity index 97% rename from app/components/header/DeployTo1PanelDialog.tsx rename to app/.client/components/header/DeployTo1PanelDialog.tsx index 193ccc9..7616e7f 100644 --- a/app/components/header/DeployTo1PanelDialog.tsx +++ b/app/.client/components/header/DeployTo1PanelDialog.tsx @@ -2,9 +2,9 @@ import { useStore } from '@nanostores/react'; import * as Dialog from '@radix-ui/react-dialog'; import { motion } from 'framer-motion'; import { useEffect, useState } from 'react'; -import _1PanelConnection from '~/components/header/connections/_1PanelConnection'; -import { useChatDeployment } from '~/lib/hooks/useChatDeployment'; -import { _1PanelConnectionStore } from '~/lib/stores/1panel'; +import _1PanelConnection from '~/.client/components/header/connections/_1PanelConnection'; +import { useChatDeployment } from '~/.client/hooks/useChatDeployment'; +import { _1PanelConnectionStore } from '~/.client/stores/1panel'; import { DeploymentPlatformEnum } from '~/types/deployment'; interface DeployTo1PanelDialogProps { diff --git a/app/components/header/DeployToNetlifyDialog.tsx b/app/.client/components/header/DeployToNetlifyDialog.tsx similarity index 96% rename from app/components/header/DeployToNetlifyDialog.tsx rename to app/.client/components/header/DeployToNetlifyDialog.tsx index 9f76ee4..ccdf047 100644 --- a/app/components/header/DeployToNetlifyDialog.tsx +++ b/app/.client/components/header/DeployToNetlifyDialog.tsx @@ -2,11 +2,11 @@ import { useStore } from '@nanostores/react'; import * as Dialog from '@radix-ui/react-dialog'; import { motion } from 'framer-motion'; import React, { Suspense, useEffect, useState } from 'react'; -import { useChatDeployment } from '~/lib/hooks/useChatDeployment'; -import { netlifyConnection } from '~/lib/stores/netlify'; +import { useChatDeployment } from '~/.client/hooks/useChatDeployment'; +import { netlifyConnection } from '~/.client/stores/netlify'; import { DeploymentPlatformEnum } from '~/types/deployment'; -const NetlifyConnection = React.lazy(() => import('~/components/header/connections/NetlifyConnection')); +const NetlifyConnection = React.lazy(() => import('~/.client/components/header/connections/NetlifyConnection')); interface DeployToNetlifyDialogProps { isOpen: boolean; diff --git a/app/components/header/DeployToVercelDialog.tsx b/app/.client/components/header/DeployToVercelDialog.tsx similarity index 96% rename from app/components/header/DeployToVercelDialog.tsx rename to app/.client/components/header/DeployToVercelDialog.tsx index e54667b..5008fc5 100644 --- a/app/components/header/DeployToVercelDialog.tsx +++ b/app/.client/components/header/DeployToVercelDialog.tsx @@ -2,9 +2,9 @@ import { useStore } from '@nanostores/react'; import * as Dialog from '@radix-ui/react-dialog'; import { motion } from 'framer-motion'; import { useEffect, useState } from 'react'; -import VercelConnection from '~/components/header/connections/VercelConnection'; -import { useChatDeployment } from '~/lib/hooks/useChatDeployment'; -import { vercelConnection } from '~/lib/stores/vercel'; +import VercelConnection from '~/.client/components/header/connections/VercelConnection'; +import { useChatDeployment } from '~/.client/hooks/useChatDeployment'; +import { vercelConnection } from '~/.client/stores/vercel'; import { DeploymentPlatformEnum } from '~/types/deployment'; interface DeployToVercelDialogProps { diff --git a/app/components/header/Header.tsx b/app/.client/components/header/Header.tsx similarity index 93% rename from app/components/header/Header.tsx rename to app/.client/components/header/Header.tsx index cfde437..8ea3d83 100644 --- a/app/components/header/Header.tsx +++ b/app/.client/components/header/Header.tsx @@ -2,9 +2,9 @@ import { useStore } from '@nanostores/react'; import classNames from 'classnames'; import { useMemo } from 'react'; import { ClientOnly } from 'remix-utils/client-only'; -import { useAuth } from '~/lib/hooks'; -import { aiState } from '~/lib/stores/ai-state'; -import { themeStore } from '~/lib/stores/theme'; +import { useAuth } from '~/.client/hooks'; +import { aiState } from '~/.client/stores/ai-state'; +import { themeStore } from '~/stores/theme'; import { HistorySwitch } from '../sidebar/HistorySwitch'; import { ThemeSwitch } from '../ui/ThemeSwitch'; import { ChatDescription } from './ChatDescription.client'; diff --git a/app/components/header/HeaderActionButtons.tsx b/app/.client/components/header/HeaderActionButtons.tsx similarity index 97% rename from app/components/header/HeaderActionButtons.tsx rename to app/.client/components/header/HeaderActionButtons.tsx index 75f072f..0bd47b6 100644 --- a/app/components/header/HeaderActionButtons.tsx +++ b/app/.client/components/header/HeaderActionButtons.tsx @@ -4,11 +4,11 @@ import classNames from 'classnames'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { toast } from 'sonner'; -import { NetlifyDeploymentLink } from '~/components/chat/NetlifyDeploymentLink.client'; -import useViewport from '~/lib/hooks'; -import { setLocalStorage } from '~/lib/persistence'; -import { aiState, setShowChat } from '~/lib/stores/ai-state'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import { NetlifyDeploymentLink } from '~/.client/components/chat/NetlifyDeploymentLink.client'; +import useViewport from '~/.client/hooks'; +import { setLocalStorage } from '~/.client/persistence'; +import { aiState, setShowChat } from '~/.client/stores/ai-state'; +import { webBuilderStore } from '~/.client/stores/web-builder'; import type { _1PanelDeployResponse } from '~/types/1panel'; import { DeploymentPlatformEnum } from '~/types/deployment'; import type { ApiResponse } from '~/types/global'; diff --git a/app/components/header/MinimalAvatarDropdown.tsx b/app/.client/components/header/MinimalAvatarDropdown.tsx similarity index 94% rename from app/components/header/MinimalAvatarDropdown.tsx rename to app/.client/components/header/MinimalAvatarDropdown.tsx index cef48ef..d086153 100644 --- a/app/components/header/MinimalAvatarDropdown.tsx +++ b/app/.client/components/header/MinimalAvatarDropdown.tsx @@ -2,12 +2,12 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; import classNames from 'classnames'; import { motion } from 'framer-motion'; import { useMemo, useState } from 'react'; -import { ChatUsageDialog } from '~/components/chat/usage/ChatUsageDialog'; -import { DeploymentRecordsDialog } from '~/components/chat/usage/DeploymentRecordsDialog'; -import { Button } from '~/components/ui/Button'; -import { ConfirmationDialog } from '~/components/ui/Dialog'; -import { useAuth } from '~/lib/hooks/useAuth'; -import { useChatUsage } from '~/lib/hooks/useChatUsage'; +import { ChatUsageDialog } from '~/.client/components/chat/usage/ChatUsageDialog'; +import { DeploymentRecordsDialog } from '~/.client/components/chat/usage/DeploymentRecordsDialog'; +import { Button } from '~/.client/components/ui/Button'; +import { ConfirmationDialog } from '~/.client/components/ui/Dialog'; +import { useAuth } from '~/.client/hooks/useAuth'; +import { useChatUsage } from '~/.client/hooks/useChatUsage'; interface MinimalAvatarDropdownProps {} diff --git a/app/components/header/connections/GithubConnection.tsx b/app/.client/components/header/connections/GithubConnection.tsx similarity index 99% rename from app/components/header/connections/GithubConnection.tsx rename to app/.client/components/header/connections/GithubConnection.tsx index 335a280..8148ed3 100644 --- a/app/components/header/connections/GithubConnection.tsx +++ b/app/.client/components/header/connections/GithubConnection.tsx @@ -2,9 +2,9 @@ import classNames from 'classnames'; import Cookies from 'js-cookie'; import React, { useEffect, useState } from 'react'; import { toast } from 'sonner'; -import { Button } from '~/components/ui/Button'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/components/ui/Collapsible'; -import { logStore } from '~/lib/stores/logs'; +import { Button } from '~/.client/components/ui/Button'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/.client/components/ui/Collapsible'; +import { logStore } from '~/stores/logs'; import ConnectionBorder from './components/ConnectionBorder'; interface GitHubUserResponse { diff --git a/app/components/header/connections/NetlifyConnection.tsx b/app/.client/components/header/connections/NetlifyConnection.tsx similarity index 99% rename from app/components/header/connections/NetlifyConnection.tsx rename to app/.client/components/header/connections/NetlifyConnection.tsx index bdb6760..ed192e4 100644 --- a/app/components/header/connections/NetlifyConnection.tsx +++ b/app/.client/components/header/connections/NetlifyConnection.tsx @@ -5,10 +5,15 @@ import { formatDistanceToNow } from 'date-fns'; import { zhCN } from 'date-fns/locale/zh-CN'; import { useEffect, useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { Badge } from '~/components/ui/Badge'; -import { Button } from '~/components/ui/Button'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/components/ui/Collapsible'; -import { fetchNetlifyStats, isFetchingStats, netlifyConnection, updateNetlifyConnection } from '~/lib/stores/netlify'; +import { Badge } from '~/.client/components/ui/Badge'; +import { Button } from '~/.client/components/ui/Button'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/.client/components/ui/Collapsible'; +import { + fetchNetlifyStats, + isFetchingStats, + netlifyConnection, + updateNetlifyConnection, +} from '~/.client/stores/netlify'; import type { ConnectionSettings } from '~/root'; import type { ApiResponse } from '~/types/global'; import type { NetlifyBuild, NetlifyDeploy, NetlifySite } from '~/types/netlify'; diff --git a/app/components/header/connections/VercelConnection.tsx b/app/.client/components/header/connections/VercelConnection.tsx similarity index 99% rename from app/components/header/connections/VercelConnection.tsx rename to app/.client/components/header/connections/VercelConnection.tsx index 5674a58..486da58 100644 --- a/app/components/header/connections/VercelConnection.tsx +++ b/app/.client/components/header/connections/VercelConnection.tsx @@ -3,9 +3,9 @@ import { useFetcher, useRouteLoaderData } from '@remix-run/react'; import classNames from 'classnames'; import React, { useEffect, useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { logStore } from '~/lib/stores/logs'; -import { fetchVercelStats, isFetchingStats, updateVercelConnection, vercelConnection } from '~/lib/stores/vercel'; +import { fetchVercelStats, isFetchingStats, updateVercelConnection, vercelConnection } from '~/.client/stores/vercel'; import type { ConnectionSettings } from '~/root'; +import { logStore } from '~/stores/logs'; import { logger } from '~/utils/logger'; import ConnectionBorder from './components/ConnectionBorder'; diff --git a/app/components/header/connections/_1PanelConnection.tsx b/app/.client/components/header/connections/_1PanelConnection.tsx similarity index 98% rename from app/components/header/connections/_1PanelConnection.tsx rename to app/.client/components/header/connections/_1PanelConnection.tsx index 485bcd5..fda8d0f 100644 --- a/app/components/header/connections/_1PanelConnection.tsx +++ b/app/.client/components/header/connections/_1PanelConnection.tsx @@ -6,11 +6,16 @@ import { zhCN } from 'date-fns/locale/zh-CN'; import { motion } from 'framer-motion'; import React, { useEffect, useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { Badge } from '~/components/ui/Badge'; -import { Button } from '~/components/ui/Button'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/components/ui/Collapsible'; -import { _1PanelConnectionStore, fetch1PanelStats, isFetchingStats, update1PanelConnection } from '~/lib/stores/1panel'; -import { getChatId } from '~/lib/stores/ai-state'; +import { Badge } from '~/.client/components/ui/Badge'; +import { Button } from '~/.client/components/ui/Button'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/.client/components/ui/Collapsible'; +import { + _1PanelConnectionStore, + fetch1PanelStats, + isFetchingStats, + update1PanelConnection, +} from '~/.client/stores/1panel'; +import { getChatId } from '~/.client/stores/ai-state'; import type { ConnectionSettings } from '~/root'; import type { _1PanelWebsite } from '~/types/1panel'; import type { ApiResponse } from '~/types/global'; diff --git a/app/components/header/connections/components/ConnectionBorder.tsx b/app/.client/components/header/connections/components/ConnectionBorder.tsx similarity index 100% rename from app/components/header/connections/components/ConnectionBorder.tsx rename to app/.client/components/header/connections/components/ConnectionBorder.tsx diff --git a/app/components/header/connections/components/PushToGitHubDialog.tsx b/app/.client/components/header/connections/components/PushToGitHubDialog.tsx similarity index 98% rename from app/components/header/connections/components/PushToGitHubDialog.tsx rename to app/.client/components/header/connections/components/PushToGitHubDialog.tsx index e0aae1b..3fff8ac 100644 --- a/app/components/header/connections/components/PushToGitHubDialog.tsx +++ b/app/.client/components/header/connections/components/PushToGitHubDialog.tsx @@ -4,14 +4,14 @@ import classNames from 'classnames'; import { motion } from 'framer-motion'; import React, { Suspense, useEffect, useState } from 'react'; import { toast } from 'sonner'; -import { getLocalStorage } from '~/lib/persistence'; -import { logStore } from '~/lib/stores/logs'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import { getLocalStorage } from '~/.client/persistence'; +import { webBuilderStore } from '~/.client/stores/web-builder'; +import { formatSize } from '~/.client/utils/format'; +import { logStore } from '~/stores/logs'; import type { GitHubUserResponse } from '~/types/github'; -import { formatSize } from '~/utils/format'; import { logger } from '~/utils/logger'; -const GitHubConnection = React.lazy(() => import('~/components/header/connections/GithubConnection')); +const GitHubConnection = React.lazy(() => import('~/.client/components/header/connections/GithubConnection')); interface PushToGitHubDialogProps { isOpen: boolean; diff --git a/app/components/sidebar/HistoryItem.client.tsx b/app/.client/components/sidebar/HistoryItem.client.tsx similarity index 95% rename from app/components/sidebar/HistoryItem.client.tsx rename to app/.client/components/sidebar/HistoryItem.client.tsx index 35344c6..d2cc0cc 100644 --- a/app/components/sidebar/HistoryItem.client.tsx +++ b/app/.client/components/sidebar/HistoryItem.client.tsx @@ -1,10 +1,10 @@ import { useParams } from '@remix-run/react'; import classNames from 'classnames'; import { type ForwardedRef, forwardRef, useCallback } from 'react'; -import { Checkbox } from '~/components/ui/Checkbox'; -import WithTooltip from '~/components/ui/Tooltip'; -import { useEditChatDescription } from '~/lib/hooks'; -import type { ServerChatItem } from '~/lib/hooks/useChatEntries'; +import { Checkbox } from '~/.client/components/ui/Checkbox'; +import WithTooltip from '~/.client/components/ui/Tooltip'; +import { useEditChatDescription } from '~/.client/hooks'; +import type { ServerChatItem } from '~/.client/hooks/useChatEntries'; interface HistoryItemProps { item: ServerChatItem; diff --git a/app/components/sidebar/HistorySwitch.tsx b/app/.client/components/sidebar/HistorySwitch.tsx similarity index 80% rename from app/components/sidebar/HistorySwitch.tsx rename to app/.client/components/sidebar/HistorySwitch.tsx index febfb9e..5c72f20 100644 --- a/app/components/sidebar/HistorySwitch.tsx +++ b/app/.client/components/sidebar/HistorySwitch.tsx @@ -1,6 +1,6 @@ import { memo, useEffect, useState } from 'react'; -import { IconButton } from '~/components/ui/IconButton'; -import { toggleSidebar } from '~/lib/stores/sidebar'; +import { IconButton } from '~/.client/components/ui/IconButton'; +import { toggleSidebar } from '~/.client/stores/sidebar'; interface HistorySwitchProps { className?: string; diff --git a/app/components/sidebar/Menu.client.tsx b/app/.client/components/sidebar/Menu.client.tsx similarity index 96% rename from app/components/sidebar/Menu.client.tsx rename to app/.client/components/sidebar/Menu.client.tsx index 08ffc34..7214b99 100644 --- a/app/components/sidebar/Menu.client.tsx +++ b/app/.client/components/sidebar/Menu.client.tsx @@ -3,15 +3,15 @@ import classNames from 'classnames'; import { motion, type Variants } from 'framer-motion'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { toast } from 'sonner'; -import { ControlPanel } from '~/components/@settings/core/ControlPanel'; -import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog'; -import { SettingsButton } from '~/components/ui/SettingsButton'; -import { useAuth } from '~/lib/hooks'; -import { type ServerChatItem, useChatEntries } from '~/lib/hooks/useChatEntries'; -import { useChatOperate } from '~/lib/hooks/useChatOperate'; -import { aiState } from '~/lib/stores/ai-state'; -import { sidebarStore } from '~/lib/stores/sidebar'; -import { cubicEasingFn } from '~/utils/easings'; +import { ControlPanel } from '~/.client/components/@settings/core/ControlPanel'; +import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/.client/components/ui/Dialog'; +import { SettingsButton } from '~/.client/components/ui/SettingsButton'; +import { useAuth } from '~/.client/hooks'; +import { type ServerChatItem, useChatEntries } from '~/.client/hooks/useChatEntries'; +import { useChatOperate } from '~/.client/hooks/useChatOperate'; +import { aiState } from '~/.client/stores/ai-state'; +import { sidebarStore } from '~/.client/stores/sidebar'; +import { cubicEasingFn } from '~/.client/utils/easings'; import WithTooltip from '../ui/Tooltip'; import { binDates } from './date-binning'; import { HistoryItem } from './HistoryItem.client'; diff --git a/app/components/sidebar/date-binning.ts b/app/.client/components/sidebar/date-binning.ts similarity index 95% rename from app/components/sidebar/date-binning.ts rename to app/.client/components/sidebar/date-binning.ts index dc60121..25a21f5 100644 --- a/app/components/sidebar/date-binning.ts +++ b/app/.client/components/sidebar/date-binning.ts @@ -1,6 +1,6 @@ import { format, isAfter, isThisWeek, isThisYear, isToday, isYesterday, subDays } from 'date-fns'; import { zhCN } from 'date-fns/locale/zh-CN'; -import type { ServerChatItem } from '~/lib/hooks/useChatEntries'; +import type { ServerChatItem } from '~/.client/hooks/useChatEntries'; type Bin = { category: string; items: ServerChatItem[] }; diff --git a/app/components/ui/BackgroundRays/index.tsx b/app/.client/components/ui/BackgroundRays/index.tsx similarity index 100% rename from app/components/ui/BackgroundRays/index.tsx rename to app/.client/components/ui/BackgroundRays/index.tsx diff --git a/app/components/ui/BackgroundRays/styles.module.scss b/app/.client/components/ui/BackgroundRays/styles.module.scss similarity index 100% rename from app/components/ui/BackgroundRays/styles.module.scss rename to app/.client/components/ui/BackgroundRays/styles.module.scss diff --git a/app/components/ui/Badge.tsx b/app/.client/components/ui/Badge.tsx similarity index 100% rename from app/components/ui/Badge.tsx rename to app/.client/components/ui/Badge.tsx diff --git a/app/components/ui/Button.tsx b/app/.client/components/ui/Button.tsx similarity index 100% rename from app/components/ui/Button.tsx rename to app/.client/components/ui/Button.tsx diff --git a/app/components/ui/Card.tsx b/app/.client/components/ui/Card.tsx similarity index 100% rename from app/components/ui/Card.tsx rename to app/.client/components/ui/Card.tsx diff --git a/app/components/ui/Checkbox.tsx b/app/.client/components/ui/Checkbox.tsx similarity index 100% rename from app/components/ui/Checkbox.tsx rename to app/.client/components/ui/Checkbox.tsx diff --git a/app/components/ui/Collapsible.tsx b/app/.client/components/ui/Collapsible.tsx similarity index 100% rename from app/components/ui/Collapsible.tsx rename to app/.client/components/ui/Collapsible.tsx diff --git a/app/components/ui/Dialog.tsx b/app/.client/components/ui/Dialog.tsx similarity index 99% rename from app/components/ui/Dialog.tsx rename to app/.client/components/ui/Dialog.tsx index 439473c..5e3554c 100644 --- a/app/components/ui/Dialog.tsx +++ b/app/.client/components/ui/Dialog.tsx @@ -3,7 +3,7 @@ import classNames from 'classnames'; import { motion, type Variants } from 'framer-motion'; import React, { memo, type ReactNode, useEffect, useMemo, useState } from 'react'; import { List, type RowComponentProps } from 'react-window'; -import { cubicEasingFn } from '~/utils/easings'; +import { cubicEasingFn } from '~/.client/utils/easings'; import { Button } from './Button'; import { Checkbox } from './Checkbox'; import { IconButton } from './IconButton'; diff --git a/app/components/ui/Dropdown.tsx b/app/.client/components/ui/Dropdown.tsx similarity index 100% rename from app/components/ui/Dropdown.tsx rename to app/.client/components/ui/Dropdown.tsx diff --git a/app/components/ui/IconButton.tsx b/app/.client/components/ui/IconButton.tsx similarity index 100% rename from app/components/ui/IconButton.tsx rename to app/.client/components/ui/IconButton.tsx diff --git a/app/components/ui/Input.tsx b/app/.client/components/ui/Input.tsx similarity index 100% rename from app/components/ui/Input.tsx rename to app/.client/components/ui/Input.tsx diff --git a/app/components/ui/Label.tsx b/app/.client/components/ui/Label.tsx similarity index 100% rename from app/components/ui/Label.tsx rename to app/.client/components/ui/Label.tsx diff --git a/app/components/ui/LoadingDots.tsx b/app/.client/components/ui/LoadingDots.tsx similarity index 100% rename from app/components/ui/LoadingDots.tsx rename to app/.client/components/ui/LoadingDots.tsx diff --git a/app/components/ui/LoadingOverlay.tsx b/app/.client/components/ui/LoadingOverlay.tsx similarity index 100% rename from app/components/ui/LoadingOverlay.tsx rename to app/.client/components/ui/LoadingOverlay.tsx diff --git a/app/components/ui/PanelHeader.tsx b/app/.client/components/ui/PanelHeader.tsx similarity index 100% rename from app/components/ui/PanelHeader.tsx rename to app/.client/components/ui/PanelHeader.tsx diff --git a/app/components/ui/PanelHeaderButton.tsx b/app/.client/components/ui/PanelHeaderButton.tsx similarity index 100% rename from app/components/ui/PanelHeaderButton.tsx rename to app/.client/components/ui/PanelHeaderButton.tsx diff --git a/app/components/ui/Popover.tsx b/app/.client/components/ui/Popover.tsx similarity index 100% rename from app/components/ui/Popover.tsx rename to app/.client/components/ui/Popover.tsx diff --git a/app/components/ui/Progress.tsx b/app/.client/components/ui/Progress.tsx similarity index 100% rename from app/components/ui/Progress.tsx rename to app/.client/components/ui/Progress.tsx diff --git a/app/components/ui/ScrollArea.tsx b/app/.client/components/ui/ScrollArea.tsx similarity index 100% rename from app/components/ui/ScrollArea.tsx rename to app/.client/components/ui/ScrollArea.tsx diff --git a/app/components/ui/Separator.tsx b/app/.client/components/ui/Separator.tsx similarity index 100% rename from app/components/ui/Separator.tsx rename to app/.client/components/ui/Separator.tsx diff --git a/app/components/ui/SettingsButton.tsx b/app/.client/components/ui/SettingsButton.tsx similarity index 87% rename from app/components/ui/SettingsButton.tsx rename to app/.client/components/ui/SettingsButton.tsx index 6c6a7d3..43d25d5 100644 --- a/app/components/ui/SettingsButton.tsx +++ b/app/.client/components/ui/SettingsButton.tsx @@ -1,5 +1,5 @@ import { memo } from 'react'; -import { IconButton } from '~/components/ui/IconButton'; +import { IconButton } from '~/.client/components/ui/IconButton'; interface SettingsButtonProps { onClick: () => void; diff --git a/app/components/ui/Slider.tsx b/app/.client/components/ui/Slider.tsx similarity index 96% rename from app/components/ui/Slider.tsx rename to app/.client/components/ui/Slider.tsx index f7954d7..025401b 100644 --- a/app/components/ui/Slider.tsx +++ b/app/.client/components/ui/Slider.tsx @@ -1,8 +1,8 @@ import classNames from 'classnames'; import { motion } from 'framer-motion'; import { memo } from 'react'; -import { cubicEasingFn } from '~/utils/easings'; -import { genericMemo } from '~/utils/react'; +import { cubicEasingFn } from '~/.client/utils/easings'; +import { genericMemo } from '~/.client/utils/react'; export type SliderOptions = { left: { value: T; text: string }; diff --git a/app/components/ui/Switch.tsx b/app/.client/components/ui/Switch.tsx similarity index 100% rename from app/components/ui/Switch.tsx rename to app/.client/components/ui/Switch.tsx diff --git a/app/components/ui/Tabs.tsx b/app/.client/components/ui/Tabs.tsx similarity index 100% rename from app/components/ui/Tabs.tsx rename to app/.client/components/ui/Tabs.tsx diff --git a/app/components/ui/ThemeSwitch.tsx b/app/.client/components/ui/ThemeSwitch.tsx similarity index 90% rename from app/components/ui/ThemeSwitch.tsx rename to app/.client/components/ui/ThemeSwitch.tsx index bf04007..d13a196 100644 --- a/app/components/ui/ThemeSwitch.tsx +++ b/app/.client/components/ui/ThemeSwitch.tsx @@ -1,8 +1,8 @@ import { useStore } from '@nanostores/react'; import { AnimatePresence, motion } from 'framer-motion'; import { memo, useEffect, useState } from 'react'; -import { themeStore, toggleTheme } from '~/lib/stores/theme'; -import { cubicEasingFn } from '~/utils/easings'; +import { cubicEasingFn } from '~/.client/utils/easings'; +import { themeStore, toggleTheme } from '~/stores/theme'; import { IconButton } from './IconButton'; interface ThemeSwitchProps { diff --git a/app/components/ui/Tooltip.tsx b/app/.client/components/ui/Tooltip.tsx similarity index 100% rename from app/components/ui/Tooltip.tsx rename to app/.client/components/ui/Tooltip.tsx diff --git a/app/components/upage/Brand.tsx b/app/.client/components/upage/Brand.tsx similarity index 100% rename from app/components/upage/Brand.tsx rename to app/.client/components/upage/Brand.tsx diff --git a/app/components/upage/Index.tsx b/app/.client/components/upage/Index.tsx similarity index 100% rename from app/components/upage/Index.tsx rename to app/.client/components/upage/Index.tsx diff --git a/app/components/upage/Share.tsx b/app/.client/components/upage/Share.tsx similarity index 99% rename from app/components/upage/Share.tsx rename to app/.client/components/upage/Share.tsx index 0b04a24..1a47352 100644 --- a/app/components/upage/Share.tsx +++ b/app/.client/components/upage/Share.tsx @@ -1,5 +1,5 @@ import qrcode from 'node_modules/qrcode/build/qrcode?raw'; -import { getLocalStorage } from '~/lib/persistence'; +import { getLocalStorage } from '~/.client/persistence'; import closeIcon from './icons/close.svg?raw'; import copyIcon from './icons/copy.svg?raw'; import shareIcon from './icons/share.svg?raw'; diff --git a/app/components/upage/icons/close.svg b/app/.client/components/upage/icons/close.svg similarity index 100% rename from app/components/upage/icons/close.svg rename to app/.client/components/upage/icons/close.svg diff --git a/app/components/upage/icons/copy.svg b/app/.client/components/upage/icons/copy.svg similarity index 100% rename from app/components/upage/icons/copy.svg rename to app/.client/components/upage/icons/copy.svg diff --git a/app/components/upage/icons/logo.svg b/app/.client/components/upage/icons/logo.svg similarity index 100% rename from app/components/upage/icons/logo.svg rename to app/.client/components/upage/icons/logo.svg diff --git a/app/components/upage/icons/share.svg b/app/.client/components/upage/icons/share.svg similarity index 100% rename from app/components/upage/icons/share.svg rename to app/.client/components/upage/icons/share.svg diff --git a/app/components/upage/icons/twitter.svg b/app/.client/components/upage/icons/twitter.svg similarity index 100% rename from app/components/upage/icons/twitter.svg rename to app/.client/components/upage/icons/twitter.svg diff --git a/app/components/upage/icons/wechat.svg b/app/.client/components/upage/icons/wechat.svg similarity index 100% rename from app/components/upage/icons/wechat.svg rename to app/.client/components/upage/icons/wechat.svg diff --git a/app/components/upage/icons/weibo.svg b/app/.client/components/upage/icons/weibo.svg similarity index 100% rename from app/components/upage/icons/weibo.svg rename to app/.client/components/upage/icons/weibo.svg diff --git a/app/components/webbuilder/DiffView.tsx b/app/.client/components/webbuilder/DiffView.tsx similarity index 99% rename from app/components/webbuilder/DiffView.tsx rename to app/.client/components/webbuilder/DiffView.tsx index e580006..84fe467 100644 --- a/app/components/webbuilder/DiffView.tsx +++ b/app/.client/components/webbuilder/DiffView.tsx @@ -3,9 +3,9 @@ import { type Change, diffLines } from 'diff'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { createHighlighter } from 'shiki'; import '~/styles/diff-view.css'; -import { themeStore } from '~/lib/stores/theme'; -import { webBuilderStore } from '~/lib/stores/web-builder'; -import { formatCode } from '~/utils/prettier'; +import { webBuilderStore } from '~/.client/stores/web-builder'; +import { formatCode } from '~/.client/utils/prettier'; +import { themeStore } from '~/stores/theme'; // 高亮结果缓存,使用 Map 存储已高亮的代码行 const highlightCache = new Map(); diff --git a/app/components/webbuilder/EditorPanel.tsx b/app/.client/components/webbuilder/EditorPanel.tsx similarity index 96% rename from app/components/webbuilder/EditorPanel.tsx rename to app/.client/components/webbuilder/EditorPanel.tsx index 403f6b5..fd2dc03 100644 --- a/app/components/webbuilder/EditorPanel.tsx +++ b/app/.client/components/webbuilder/EditorPanel.tsx @@ -1,10 +1,10 @@ import * as Tabs from '@radix-ui/react-tabs'; import { memo } from 'react'; import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; -import { ErrorBoundary } from '~/components/ErrorBoundary'; -import type { PageMap } from '~/lib/stores/pages'; +import { ErrorBoundary } from '~/.client/components/ErrorBoundary'; import type { PageHistory, Section } from '~/types/actions'; import type { DocumentProperties } from '~/types/editor'; +import type { PageMap } from '~/types/pages'; import { logger, renderLogger } from '~/utils/logger'; import { EditorStudio, diff --git a/app/components/webbuilder/InlineInput.tsx b/app/.client/components/webbuilder/InlineInput.tsx similarity index 100% rename from app/components/webbuilder/InlineInput.tsx rename to app/.client/components/webbuilder/InlineInput.tsx diff --git a/app/components/webbuilder/PageDropdown.tsx b/app/.client/components/webbuilder/PageDropdown.tsx similarity index 95% rename from app/components/webbuilder/PageDropdown.tsx rename to app/.client/components/webbuilder/PageDropdown.tsx index a791f04..0317300 100644 --- a/app/components/webbuilder/PageDropdown.tsx +++ b/app/.client/components/webbuilder/PageDropdown.tsx @@ -1,6 +1,6 @@ import { memo, useEffect, useRef } from 'react'; -import { IconButton } from '~/components/ui/IconButton'; -import type { PreviewInfo } from '~/lib/stores/previews'; +import { IconButton } from '~/.client/components/ui/IconButton'; +import type { PreviewInfo } from '~/.client/stores/previews'; interface PageDropdownProps { activePreviewIndex: number; diff --git a/app/components/webbuilder/PageTree.tsx b/app/.client/components/webbuilder/PageTree.tsx similarity index 98% rename from app/components/webbuilder/PageTree.tsx rename to app/.client/components/webbuilder/PageTree.tsx index a5708e5..af88cad 100644 --- a/app/components/webbuilder/PageTree.tsx +++ b/app/.client/components/webbuilder/PageTree.tsx @@ -4,10 +4,10 @@ import classNames from 'classnames'; import { type Change, diffLines } from 'diff'; import { memo, type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { Button } from '~/components/ui/Button'; -import { ConfirmationDialog, Dialog, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog'; -import type { PageMap } from '~/lib/stores/pages'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import { Button } from '~/.client/components/ui/Button'; +import { ConfirmationDialog, Dialog, DialogDescription, DialogRoot, DialogTitle } from '~/.client/components/ui/Dialog'; +import { webBuilderStore } from '~/.client/stores/web-builder'; +import type { PageMap } from '~/types/pages'; import { createScopedLogger, renderLogger } from '~/utils/logger'; const logger = createScopedLogger('PageTree'); diff --git a/app/components/webbuilder/Preview.tsx b/app/.client/components/webbuilder/Preview.tsx similarity index 99% rename from app/components/webbuilder/Preview.tsx rename to app/.client/components/webbuilder/Preview.tsx index 38f8860..5532d20 100644 --- a/app/components/webbuilder/Preview.tsx +++ b/app/.client/components/webbuilder/Preview.tsx @@ -1,7 +1,7 @@ import { useStore } from '@nanostores/react'; import { memo, useCallback, useEffect, useRef, useState } from 'react'; -import { IconButton } from '~/components/ui/IconButton'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import { IconButton } from '~/.client/components/ui/IconButton'; +import { webBuilderStore } from '~/.client/stores/web-builder'; import { PageDropdown } from './PageDropdown'; import { ScreenshotSelector } from './ScreenshotSelector'; diff --git a/app/components/webbuilder/ScreenshotSelector.tsx b/app/.client/components/webbuilder/ScreenshotSelector.tsx similarity index 100% rename from app/components/webbuilder/ScreenshotSelector.tsx rename to app/.client/components/webbuilder/ScreenshotSelector.tsx diff --git a/app/components/webbuilder/WebBuilder.client.tsx b/app/.client/components/webbuilder/WebBuilder.client.tsx similarity index 95% rename from app/components/webbuilder/WebBuilder.client.tsx rename to app/.client/components/webbuilder/WebBuilder.client.tsx index fe7ce64..5d8b979 100644 --- a/app/components/webbuilder/WebBuilder.client.tsx +++ b/app/.client/components/webbuilder/WebBuilder.client.tsx @@ -5,20 +5,25 @@ import { type Change, diffLines } from 'diff'; import { type HTMLMotionProps, motion, type Variants } from 'framer-motion'; import { memo, useCallback, useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { PushToGitHubDialog } from '~/components/header/connections/components/PushToGitHubDialog'; -import { IconButton } from '~/components/ui/IconButton'; -import { PanelHeaderButton } from '~/components/ui/PanelHeaderButton'; -import { Slider, type SliderOptions } from '~/components/ui/Slider'; -import useViewport from '~/lib/hooks'; -import { useProject } from '~/lib/hooks/useProject'; -import { useChatHistory } from '~/lib/persistence'; -import { aiState } from '~/lib/stores/ai-state'; -import type { PageMap } from '~/lib/stores/pages'; -import { type WebBuilderViewType, webBuilderStore } from '~/lib/stores/web-builder'; +import type { + OnChangeCallback, + OnLoadCallback, + OnReadyCallback, + OnSaveCallback, +} from '~/.client/components/editor/Editor'; +import { PushToGitHubDialog } from '~/.client/components/header/connections/components/PushToGitHubDialog'; +import { IconButton } from '~/.client/components/ui/IconButton'; +import { PanelHeaderButton } from '~/.client/components/ui/PanelHeaderButton'; +import { Slider, type SliderOptions } from '~/.client/components/ui/Slider'; +import useViewport from '~/.client/hooks'; +import { useProject } from '~/.client/hooks/useProject'; +import { useChatHistory } from '~/.client/persistence'; +import { aiState } from '~/.client/stores/ai-state'; +import { type WebBuilderViewType, webBuilderStore } from '~/.client/stores/web-builder'; +import { cubicEasingFn } from '~/.client/utils/easings'; import type { Page } from '~/types/actions'; -import { cubicEasingFn } from '~/utils/easings'; +import type { PageMap } from '~/types/pages'; import { renderLogger } from '~/utils/logger'; -import type { OnChangeCallback, OnLoadCallback, OnReadyCallback, OnSaveCallback } from '../editor/Editor'; import { DiffView } from './DiffView'; import { EditorPanel } from './EditorPanel'; import { Preview } from './Preview'; diff --git a/app/lib/hooks/index.ts b/app/.client/hooks/index.ts similarity index 100% rename from app/lib/hooks/index.ts rename to app/.client/hooks/index.ts diff --git a/app/lib/hooks/useAuth.ts b/app/.client/hooks/useAuth.ts similarity index 100% rename from app/lib/hooks/useAuth.ts rename to app/.client/hooks/useAuth.ts diff --git a/app/lib/hooks/useChatDeployment.ts b/app/.client/hooks/useChatDeployment.ts similarity index 100% rename from app/lib/hooks/useChatDeployment.ts rename to app/.client/hooks/useChatDeployment.ts diff --git a/app/lib/hooks/useChatEntries.ts b/app/.client/hooks/useChatEntries.ts similarity index 97% rename from app/lib/hooks/useChatEntries.ts rename to app/.client/hooks/useChatEntries.ts index 8028be7..221387c 100644 --- a/app/lib/hooks/useChatEntries.ts +++ b/app/.client/hooks/useChatEntries.ts @@ -1,7 +1,7 @@ import { useFetcher } from '@remix-run/react'; import { useCallback, useEffect, useState } from 'react'; +import { debounce } from '~/.client/utils/debounce'; import type { ApiResponse } from '~/types/global'; -import { debounce } from '~/utils/debounce'; export interface ServerChatListResponse { chats: ServerChatItem[]; diff --git a/app/lib/hooks/useChatHistory.ts b/app/.client/hooks/useChatHistory.ts similarity index 100% rename from app/lib/hooks/useChatHistory.ts rename to app/.client/hooks/useChatHistory.ts diff --git a/app/lib/hooks/useChatMessage.ts b/app/.client/hooks/useChatMessage.ts similarity index 96% rename from app/lib/hooks/useChatMessage.ts rename to app/.client/hooks/useChatMessage.ts index 547352f..2726409 100644 --- a/app/lib/hooks/useChatMessage.ts +++ b/app/.client/hooks/useChatMessage.ts @@ -5,11 +5,6 @@ import { DefaultChatTransport, type FileUIPart } from 'ai'; import { animate } from 'framer-motion'; import { useEffect, useMemo, useState } from 'react'; import { toast } from 'sonner'; -import type { ChatMessage } from '~/types/chat'; -import type { ProgressAnnotation, UPageUIMessage } from '~/types/message'; -import { cubicEasingFn } from '~/utils/easings'; -import { createScopedLogger } from '~/utils/logger'; -import { pagesToArtifacts } from '~/utils/page'; import { aiState, getChatStarted, @@ -19,9 +14,14 @@ import { setShowChat, setStreamingState, updateParseMessages, -} from '../stores/ai-state'; -import { type SendChatMessageParams, setSendChatMessage } from '../stores/chat-message'; -import { webBuilderStore } from '../stores/web-builder'; +} from '~/.client/stores/ai-state'; +import { type SendChatMessageParams, setSendChatMessage } from '~/.client/stores/chat-message'; +import { webBuilderStore } from '~/.client/stores/web-builder'; +import { cubicEasingFn } from '~/.client/utils/easings'; +import { pagesToArtifacts } from '~/.client/utils/page'; +import type { ChatMessage } from '~/types/chat'; +import type { ProgressAnnotation, UPageUIMessage } from '~/types/message'; +import { createScopedLogger } from '~/utils/logger'; import { useChatUsage } from './useChatUsage'; import { useMessageParser } from './useMessageParser'; import { useProject } from './useProject'; diff --git a/app/lib/hooks/useChatOperate.ts b/app/.client/hooks/useChatOperate.ts similarity index 98% rename from app/lib/hooks/useChatOperate.ts rename to app/.client/hooks/useChatOperate.ts index fd0f1c6..8da8a04 100644 --- a/app/lib/hooks/useChatOperate.ts +++ b/app/.client/hooks/useChatOperate.ts @@ -6,8 +6,8 @@ import { duplicateEditorProject, forkEditorProject, openEditorDatabase, -} from '../persistence/editor'; -import { getChatId } from '../stores/ai-state'; +} from '~/.client/persistence/editor'; +import { getChatId } from '~/.client/stores/ai-state'; import { useProject } from './useProject'; export const editorDb = await openEditorDatabase(); diff --git a/app/lib/hooks/useChatUsage.ts b/app/.client/hooks/useChatUsage.ts similarity index 100% rename from app/lib/hooks/useChatUsage.ts rename to app/.client/hooks/useChatUsage.ts diff --git a/app/lib/hooks/useDebugStatus.ts b/app/.client/hooks/useDebugStatus.ts similarity index 98% rename from app/lib/hooks/useDebugStatus.ts rename to app/.client/hooks/useDebugStatus.ts index 541f8fe..70ee542 100644 --- a/app/lib/hooks/useDebugStatus.ts +++ b/app/.client/hooks/useDebugStatus.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { acknowledgeError, acknowledgeWarning, type DebugIssue, getDebugStatus } from '~/lib/api/debug'; +import { acknowledgeError, acknowledgeWarning, type DebugIssue, getDebugStatus } from '~/.client/api/debug'; const ACKNOWLEDGED_DEBUG_ISSUES_KEY = 'upage_acknowledged_debug_issues'; diff --git a/app/lib/hooks/useDeploymentRecords.ts b/app/.client/hooks/useDeploymentRecords.ts similarity index 100% rename from app/lib/hooks/useDeploymentRecords.ts rename to app/.client/hooks/useDeploymentRecords.ts diff --git a/app/lib/hooks/useEditChatDescription.ts b/app/.client/hooks/useEditChatDescription.ts similarity index 100% rename from app/lib/hooks/useEditChatDescription.ts rename to app/.client/hooks/useEditChatDescription.ts diff --git a/app/lib/hooks/useEditorCommands.ts b/app/.client/hooks/useEditorCommands.ts similarity index 95% rename from app/lib/hooks/useEditorCommands.ts rename to app/.client/hooks/useEditorCommands.ts index 04c28a8..fe8546a 100644 --- a/app/lib/hooks/useEditorCommands.ts +++ b/app/.client/hooks/useEditorCommands.ts @@ -1,5 +1,5 @@ import { type RefObject, useCallback, useEffect } from 'react'; -import { editorCommands } from '~/lib/stores/editor'; +import { editorCommands } from '~/.client/stores/editor'; import type { Editor } from '~/types/editor'; import { logger } from '~/utils/logger'; diff --git a/app/lib/hooks/useMessageParser.ts b/app/.client/hooks/useMessageParser.ts similarity index 96% rename from app/lib/hooks/useMessageParser.ts rename to app/.client/hooks/useMessageParser.ts index 16b172e..c1b8055 100644 --- a/app/lib/hooks/useMessageParser.ts +++ b/app/.client/hooks/useMessageParser.ts @@ -1,6 +1,6 @@ import { useCallback, useRef, useState } from 'react'; -import { StreamingMessageParser } from '~/lib/runtime/message-parser'; -import { webBuilderStore } from '~/lib/stores/web-builder'; +import { StreamingMessageParser } from '~/.client/runtime/message-parser'; +import { webBuilderStore } from '~/.client/stores/web-builder'; import type { UPageUIMessage } from '~/types/message'; import { createScopedLogger } from '~/utils/logger'; diff --git a/app/lib/hooks/useNotifications.ts b/app/.client/hooks/useNotifications.ts similarity index 95% rename from app/lib/hooks/useNotifications.ts rename to app/.client/hooks/useNotifications.ts index ba7dffd..6e56bee 100644 --- a/app/lib/hooks/useNotifications.ts +++ b/app/.client/hooks/useNotifications.ts @@ -1,7 +1,7 @@ import { useStore } from '@nanostores/react'; import { useEffect, useState } from 'react'; -import { getNotifications, markNotificationRead, type Notification } from '~/lib/api/notifications'; -import { logStore } from '~/lib/stores/logs'; +import { getNotifications, markNotificationRead, type Notification } from '~/.client/api/notifications'; +import { logStore } from '~/stores/logs'; export const useNotifications = () => { const [hasUnreadNotifications, setHasUnreadNotifications] = useState(false); diff --git a/app/lib/hooks/useProject.ts b/app/.client/hooks/useProject.ts similarity index 96% rename from app/lib/hooks/useProject.ts rename to app/.client/hooks/useProject.ts index 44460a4..6b8dfc8 100644 --- a/app/lib/hooks/useProject.ts +++ b/app/.client/hooks/useProject.ts @@ -1,8 +1,8 @@ import { useFetcher } from '@remix-run/react'; +import { useEditorStorage } from '~/.client/persistence/editor'; +import { webBuilderStore } from '~/.client/stores/web-builder'; import type { ApiResponse } from '~/types/global'; import { createScopedLogger } from '~/utils/logger'; -import { useEditorStorage } from '../persistence/editor'; -import { webBuilderStore } from '../stores/web-builder'; const logger = createScopedLogger('useGrapesProject'); diff --git a/app/lib/hooks/usePromptEnhancer.ts b/app/.client/hooks/usePromptEnhancer.ts similarity index 100% rename from app/lib/hooks/usePromptEnhancer.ts rename to app/.client/hooks/usePromptEnhancer.ts diff --git a/app/lib/hooks/useSettings.ts b/app/.client/hooks/useSettings.ts similarity index 93% rename from app/lib/hooks/useSettings.ts rename to app/.client/hooks/useSettings.ts index ab2bd08..6a1e4b9 100644 --- a/app/lib/hooks/useSettings.ts +++ b/app/.client/hooks/useSettings.ts @@ -1,9 +1,8 @@ import { useStore } from '@nanostores/react'; import Cookies from 'js-cookie'; import { useCallback, useState } from 'react'; -import type { TabVisibilityConfig, TabWindowConfig } from '~/components/@settings/core/types'; -import { getLocalStorage, setLocalStorage } from '~/lib/persistence'; -import { logStore } from '~/lib/stores/logs'; +import type { TabVisibilityConfig, TabWindowConfig } from '~/.client/components/@settings/core/types'; +import { getLocalStorage, setLocalStorage } from '~/.client/persistence'; import { isDebugMode, isEventLogsEnabled, @@ -15,7 +14,8 @@ import { updateLatestBranch, updatePromptId, updateTabConfiguration as updateTabConfig, -} from '~/lib/stores/settings'; +} from '~/.client/stores/settings'; +import { logStore } from '~/stores/logs'; export interface Settings { theme: 'light' | 'dark' | 'system'; diff --git a/app/lib/hooks/useShortcuts.ts b/app/.client/hooks/useShortcuts.ts similarity index 96% rename from app/lib/hooks/useShortcuts.ts rename to app/.client/hooks/useShortcuts.ts index 9c38f7e..550b890 100644 --- a/app/lib/hooks/useShortcuts.ts +++ b/app/.client/hooks/useShortcuts.ts @@ -1,7 +1,7 @@ import { useStore } from '@nanostores/react'; import { useEffect } from 'react'; -import { type Shortcuts, shortcutsStore } from '~/lib/stores/settings'; -import { isMac } from '~/utils/os'; +import { type Shortcuts, shortcutsStore } from '~/.client/stores/settings'; +import { isMac } from '~/.client/utils/os'; // List of keys that should not trigger shortcuts when typing in input/textarea const INPUT_ELEMENTS = ['input', 'textarea']; diff --git a/app/lib/hooks/useSnapScroll.ts b/app/.client/hooks/useSnapScroll.ts similarity index 99% rename from app/lib/hooks/useSnapScroll.ts rename to app/.client/hooks/useSnapScroll.ts index 5e4519c..2d002b7 100644 --- a/app/lib/hooks/useSnapScroll.ts +++ b/app/.client/hooks/useSnapScroll.ts @@ -1,5 +1,5 @@ import { useCallback, useRef } from 'react'; -import { throttle } from '~/utils/throttle'; +import { throttle } from '~/.client/utils/throttle'; interface ScrollOptions { duration?: number; diff --git a/app/lib/hooks/useViewport.ts b/app/.client/hooks/useViewport.ts similarity index 100% rename from app/lib/hooks/useViewport.ts rename to app/.client/hooks/useViewport.ts diff --git a/app/lib/persistence/editor.ts b/app/.client/persistence/editor.ts similarity index 99% rename from app/lib/persistence/editor.ts rename to app/.client/persistence/editor.ts index 8d876d7..f0eddca 100644 --- a/app/lib/persistence/editor.ts +++ b/app/.client/persistence/editor.ts @@ -1,7 +1,7 @@ import { useSearchParams } from '@remix-run/react'; +import { getChatId } from '~/.client/stores/ai-state'; import type { Page, Section } from '~/types/actions'; import { createScopedLogger } from '~/utils/logger'; -import { getChatId } from '../stores/ai-state'; /** * 序列化标记常量 diff --git a/app/lib/persistence/index.ts b/app/.client/persistence/index.ts similarity index 100% rename from app/lib/persistence/index.ts rename to app/.client/persistence/index.ts diff --git a/app/lib/persistence/local-storage.ts b/app/.client/persistence/local-storage.ts similarity index 100% rename from app/lib/persistence/local-storage.ts rename to app/.client/persistence/local-storage.ts diff --git a/app/lib/runtime/__snapshots__/message-parser.spec.ts.snap b/app/.client/runtime/__snapshots__/message-parser.spec.ts.snap similarity index 100% rename from app/lib/runtime/__snapshots__/message-parser.spec.ts.snap rename to app/.client/runtime/__snapshots__/message-parser.spec.ts.snap diff --git a/app/lib/runtime/action-runner.ts b/app/.client/runtime/action-runner.ts similarity index 97% rename from app/lib/runtime/action-runner.ts rename to app/.client/runtime/action-runner.ts index 73764ba..394c4e6 100644 --- a/app/lib/runtime/action-runner.ts +++ b/app/.client/runtime/action-runner.ts @@ -1,9 +1,9 @@ import { atom, type MapStore, map } from 'nanostores'; -import type { EditorBridge } from '~/lib/bridge'; +import type { EditorBridge } from '~/.client/bridge'; +import { isValidContent } from '~/.client/utils/html-parse'; +import { unreachable } from '~/.client/utils/unreachable'; import type { ActionAlert, UPageAction } from '~/types/actions'; -import { isValidContent } from '~/utils/html-parse'; import { createScopedLogger } from '~/utils/logger'; -import { unreachable } from '~/utils/unreachable'; import type { ActionCallbackData } from './message-parser'; export type ActionPage = { diff --git a/app/lib/runtime/message-parser.spec.ts b/app/.client/runtime/message-parser.spec.ts similarity index 100% rename from app/lib/runtime/message-parser.spec.ts rename to app/.client/runtime/message-parser.spec.ts diff --git a/app/lib/runtime/message-parser.ts b/app/.client/runtime/message-parser.ts similarity index 99% rename from app/lib/runtime/message-parser.ts rename to app/.client/runtime/message-parser.ts index 1c17d17..4bcf33b 100644 --- a/app/lib/runtime/message-parser.ts +++ b/app/.client/runtime/message-parser.ts @@ -1,7 +1,7 @@ +import { unreachable } from '~/.client/utils/unreachable'; import type { UPageAction, UPageActionData } from '~/types/actions'; import type { UPageArtifactData } from '~/types/artifact'; import { createScopedLogger } from '~/utils/logger'; -import { unreachable } from '~/utils/unreachable'; const ARTIFACT_TAG_OPEN = ' diff --git a/app/lib/stores/netlify.ts b/app/.client/stores/netlify.ts similarity index 97% rename from app/lib/stores/netlify.ts rename to app/.client/stores/netlify.ts index f36380d..20ae04a 100644 --- a/app/lib/stores/netlify.ts +++ b/app/.client/stores/netlify.ts @@ -1,7 +1,7 @@ import { atom } from 'nanostores'; import { toast } from 'sonner'; +import { logStore } from '~/stores/logs'; import type { NetlifyConnection } from '~/types/netlify'; -import { logStore } from './logs'; // Initialize with stored connection or environment variable const storedConnection = typeof window !== 'undefined' ? localStorage.getItem('netlify_connection') : null; diff --git a/app/lib/stores/pages.ts b/app/.client/stores/pages.ts similarity index 96% rename from app/lib/stores/pages.ts rename to app/.client/stores/pages.ts index 65d9c7c..f99ae67 100644 --- a/app/lib/stores/pages.ts +++ b/app/.client/stores/pages.ts @@ -1,21 +1,16 @@ import { diffLines } from 'diff'; import { atom, computed, type MapStore, map, type WritableAtom } from 'nanostores'; -import { type EditorBridge, type EventPayload, editorBridge } from '~/lib/bridge'; -import type { Page, PageHistory, Section } from '~/types/actions'; -import { computePageModifications, diffPages } from '~/utils/diff'; -import { isValidContent } from '~/utils/html-parse'; +import { type EditorBridge, type EventPayload, editorBridge } from '~/.client/bridge'; +import { computePageModifications, diffPages } from '~/.client/utils/diff'; +import { isValidContent } from '~/.client/utils/html-parse'; +import type { Page, PageHistory } from '~/types/actions'; +import type { PageMap, PageSection, SectionMap } from '~/types/pages'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('PagesStore'); -export type PageSection = Section & { - validRootDomId?: boolean; -}; - -export type PageMap = Record; type ActiveSection = WritableAtom; type ActivePage = WritableAtom; -export type SectionMap = Record; /** * 保存与 AI 交互的页面数据, AI 生成的页面数据会保存在此处。 diff --git a/app/lib/stores/previews.ts b/app/.client/stores/previews.ts similarity index 100% rename from app/lib/stores/previews.ts rename to app/.client/stores/previews.ts diff --git a/app/lib/stores/profile.ts b/app/.client/stores/profile.ts similarity index 100% rename from app/lib/stores/profile.ts rename to app/.client/stores/profile.ts diff --git a/app/lib/stores/settings.ts b/app/.client/stores/settings.ts similarity index 97% rename from app/lib/stores/settings.ts rename to app/.client/stores/settings.ts index 9645340..47067da 100644 --- a/app/lib/stores/settings.ts +++ b/app/.client/stores/settings.ts @@ -1,13 +1,13 @@ import Cookies from 'js-cookie'; import { atom, map } from 'nanostores'; -import { DEFAULT_TAB_CONFIG } from '~/components/@settings/core/constants'; +import { DEFAULT_TAB_CONFIG } from '~/.client/components/@settings/core/constants'; import type { DevTabConfig, TabVisibilityConfig, TabWindowConfig, UserTabConfig, -} from '~/components/@settings/core/types'; -import { toggleTheme } from './theme'; +} from '~/.client/components/@settings/core/types'; +import { toggleTheme } from '~/stores/theme'; export interface Shortcut { key: string; diff --git a/app/lib/stores/sidebar.ts b/app/.client/stores/sidebar.ts similarity index 100% rename from app/lib/stores/sidebar.ts rename to app/.client/stores/sidebar.ts diff --git a/app/lib/stores/tab-configuration.ts b/app/.client/stores/tab-configuration.ts similarity index 100% rename from app/lib/stores/tab-configuration.ts rename to app/.client/stores/tab-configuration.ts diff --git a/app/lib/stores/vercel.ts b/app/.client/stores/vercel.ts similarity index 97% rename from app/lib/stores/vercel.ts rename to app/.client/stores/vercel.ts index 5672745..0df785a 100644 --- a/app/lib/stores/vercel.ts +++ b/app/.client/stores/vercel.ts @@ -1,7 +1,7 @@ import { atom } from 'nanostores'; import { toast } from 'sonner'; +import { logStore } from '~/stores/logs'; import type { VercelConnection } from '~/types/vercel'; -import { logStore } from './logs'; // Initialize with stored connection or defaults const storedConnection = typeof window !== 'undefined' ? localStorage.getItem('vercel_connection') : null; diff --git a/app/lib/stores/web-builder.ts b/app/.client/stores/web-builder.ts similarity index 99% rename from app/lib/stores/web-builder.ts rename to app/.client/stores/web-builder.ts index f71082b..e1ec772 100644 --- a/app/lib/stores/web-builder.ts +++ b/app/.client/stores/web-builder.ts @@ -3,13 +3,14 @@ import Cookies from 'js-cookie'; import JSZip from 'jszip'; import { atom, type WritableAtom } from 'nanostores'; import { toast } from 'sonner'; +import { formatFile } from '~/.client/utils/prettier'; import type { Page } from '~/types/actions'; +import type { PageMap } from '~/types/pages'; import { base64ToBinary, getContentType, getExtensionFromMimeType, getFileName } from '~/utils/file-utils'; import { createScopedLogger } from '~/utils/logger'; -import { formatFile } from '~/utils/prettier'; import { ChatStore } from './chat'; import { EditorStore } from './editor'; -import { type PageMap, PagesStore } from './pages'; +import { PagesStore } from './pages'; import { PreviewsStore } from './previews'; const logger = createScopedLogger('WebBuilderStore'); diff --git a/app/utils/constants.ts b/app/.client/utils/constants.ts similarity index 100% rename from app/utils/constants.ts rename to app/.client/utils/constants.ts diff --git a/app/utils/debounce.ts b/app/.client/utils/debounce.ts similarity index 100% rename from app/utils/debounce.ts rename to app/.client/utils/debounce.ts diff --git a/app/utils/diff.ts b/app/.client/utils/diff.ts similarity index 97% rename from app/utils/diff.ts rename to app/.client/utils/diff.ts index 2f1ef5f..efde665 100644 --- a/app/utils/diff.ts +++ b/app/.client/utils/diff.ts @@ -1,6 +1,6 @@ import { createPatch } from 'diff'; -import type { PageMap, SectionMap } from '~/lib/stores/pages'; import type { Section } from '~/types/actions'; +import type { PageMap, SectionMap } from '~/types/pages'; interface ModifiedSection { type: 'diff' | 'section'; diff --git a/app/utils/easings.ts b/app/.client/utils/easings.ts similarity index 100% rename from app/utils/easings.ts rename to app/.client/utils/easings.ts diff --git a/app/utils/execute-scripts.ts b/app/.client/utils/execute-scripts.ts similarity index 100% rename from app/utils/execute-scripts.ts rename to app/.client/utils/execute-scripts.ts diff --git a/app/utils/format.ts b/app/.client/utils/format.ts similarity index 100% rename from app/utils/format.ts rename to app/.client/utils/format.ts diff --git a/app/utils/html-parse.spec.ts b/app/.client/utils/html-parse.spec.ts similarity index 100% rename from app/utils/html-parse.spec.ts rename to app/.client/utils/html-parse.spec.ts diff --git a/app/utils/html-parse.ts b/app/.client/utils/html-parse.ts similarity index 99% rename from app/utils/html-parse.ts rename to app/.client/utils/html-parse.ts index 87c6a12..fa4f4f2 100644 --- a/app/utils/html-parse.ts +++ b/app/.client/utils/html-parse.ts @@ -1,4 +1,4 @@ -import { createScopedLogger } from './logger'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('htmlParse'); diff --git a/app/utils/mobile.ts b/app/.client/utils/mobile.ts similarity index 100% rename from app/utils/mobile.ts rename to app/.client/utils/mobile.ts diff --git a/app/utils/os.ts b/app/.client/utils/os.ts similarity index 100% rename from app/utils/os.ts rename to app/.client/utils/os.ts diff --git a/app/utils/page.ts b/app/.client/utils/page.ts similarity index 94% rename from app/utils/page.ts rename to app/.client/utils/page.ts index 21b0f5f..8adde4f 100644 --- a/app/utils/page.ts +++ b/app/.client/utils/page.ts @@ -1,6 +1,6 @@ import type { MapStore } from 'nanostores'; -import type { SectionMap } from '~/lib/stores/pages'; import type { Page } from '~/types/actions'; +import type { SectionMap } from '~/types/pages'; export const pagesToArtifacts = (pages: { [pageName: string]: Page }, sections: MapStore): string => { return Object.keys(pages) diff --git a/app/utils/prettier.ts b/app/.client/utils/prettier.ts similarity index 96% rename from app/utils/prettier.ts rename to app/.client/utils/prettier.ts index 73e3dfc..3bc82ad 100644 --- a/app/utils/prettier.ts +++ b/app/.client/utils/prettier.ts @@ -2,7 +2,7 @@ import prettier, { type BuiltInParserName, type Options } from 'prettier'; import * as html from 'prettier/plugins/html'; import * as css from 'prettier/plugins/postcss'; import * as javascript from 'prettier/plugins/typescript'; -import { path } from './path'; +import { path } from '../../utils/path'; const ignoreFiles = ['tailwindcss.js', 'iconify-icon.min.js']; diff --git a/app/utils/react.ts b/app/.client/utils/react.ts similarity index 100% rename from app/utils/react.ts rename to app/.client/utils/react.ts diff --git a/app/utils/sampler.ts b/app/.client/utils/sampler.ts similarity index 100% rename from app/utils/sampler.ts rename to app/.client/utils/sampler.ts diff --git a/app/utils/throttle.ts b/app/.client/utils/throttle.ts similarity index 100% rename from app/utils/throttle.ts rename to app/.client/utils/throttle.ts diff --git a/app/utils/unreachable.ts b/app/.client/utils/unreachable.ts similarity index 100% rename from app/utils/unreachable.ts rename to app/.client/utils/unreachable.ts diff --git a/app/lib/.server/llm/chat-stream-text.ts b/app/.server/llm/chat-stream-text.ts similarity index 96% rename from app/lib/.server/llm/chat-stream-text.ts rename to app/.server/llm/chat-stream-text.ts index e5cce52..474c483 100644 --- a/app/lib/.server/llm/chat-stream-text.ts +++ b/app/.server/llm/chat-stream-text.ts @@ -7,10 +7,10 @@ import { type StreamTextOnFinishCallback, stepCountIs, } from 'ai'; -import { getSystemPrompt } from '~/lib/common/prompts/prompts'; +import { getSystemPrompt } from '~/.server/prompts/prompts'; +import { approximatePromptTokenCount, encode } from '~/.server/utils/token'; import type { ElementInfo } from '~/routes/api.chat/chat.server'; import type { UPageUIMessage } from '~/types/message'; -import { approximatePromptTokenCount, encode } from '~/utils/token'; import { MAX_TOKENS } from './constants'; import type { SelectContextResult } from './select-context'; import { tools } from './tools'; diff --git a/app/lib/.server/llm/constants.ts b/app/.server/llm/constants.ts similarity index 100% rename from app/lib/.server/llm/constants.ts rename to app/.server/llm/constants.ts diff --git a/app/lib/.server/llm/create-summary.ts b/app/.server/llm/create-summary.ts similarity index 98% rename from app/lib/.server/llm/create-summary.ts rename to app/.server/llm/create-summary.ts index 0f1802d..6495632 100644 --- a/app/lib/.server/llm/create-summary.ts +++ b/app/.server/llm/create-summary.ts @@ -1,6 +1,6 @@ import { type CallSettings, generateText, type LanguageModel } from 'ai'; -import { createScopedLogger } from '~/lib/.server/logger'; import type { UPageUIMessage } from '~/types/message'; +import { createScopedLogger } from '~/utils/logger'; import { extractCurrentContext, getUserMessageContent, simplifyUPageActions } from './utils'; const logger = createScopedLogger('create-summary'); diff --git a/app/lib/.server/llm/select-context.ts b/app/.server/llm/select-context.ts similarity index 98% rename from app/lib/.server/llm/select-context.ts rename to app/.server/llm/select-context.ts index bbe637f..ce1653b 100644 --- a/app/lib/.server/llm/select-context.ts +++ b/app/.server/llm/select-context.ts @@ -1,8 +1,7 @@ import { type CallSettings, generateText, type LanguageModel } from 'ai'; -import { createScopedLogger } from '~/lib/.server/logger'; - import type { Page } from '~/types/actions'; import type { UPageUIMessage } from '~/types/message'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('select-context'); diff --git a/app/lib/.server/llm/stream-enhancer.ts b/app/.server/llm/stream-enhancer.ts similarity index 92% rename from app/lib/.server/llm/stream-enhancer.ts rename to app/.server/llm/stream-enhancer.ts index edabe44..3277889 100644 --- a/app/lib/.server/llm/stream-enhancer.ts +++ b/app/.server/llm/stream-enhancer.ts @@ -1,6 +1,6 @@ import { convertToModelMessages, type LanguageModel, streamText, type UIMessage } from 'ai'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { DEFAULT_PROVIDER } from '~/lib/modules/constants'; +import { DEFAULT_PROVIDER } from '~/.server/modules/constants'; +import { createScopedLogger } from '~/utils/logger'; import { stripIndents } from '~/utils/strip-indent'; const logger = createScopedLogger('stream-enhancer'); diff --git a/app/lib/.server/llm/structured-page-snapshot.ts b/app/.server/llm/structured-page-snapshot.ts similarity index 100% rename from app/lib/.server/llm/structured-page-snapshot.ts rename to app/.server/llm/structured-page-snapshot.ts diff --git a/app/lib/.server/llm/switchable-stream.ts b/app/.server/llm/switchable-stream.ts similarity index 100% rename from app/lib/.server/llm/switchable-stream.ts rename to app/.server/llm/switchable-stream.ts diff --git a/app/lib/.server/llm/tools/index.ts b/app/.server/llm/tools/index.ts similarity index 100% rename from app/lib/.server/llm/tools/index.ts rename to app/.server/llm/tools/index.ts diff --git a/app/lib/.server/llm/tools/serper.ts b/app/.server/llm/tools/serper.ts similarity index 100% rename from app/lib/.server/llm/tools/serper.ts rename to app/.server/llm/tools/serper.ts diff --git a/app/lib/.server/llm/tools/weather.ts b/app/.server/llm/tools/weather.ts similarity index 100% rename from app/lib/.server/llm/tools/weather.ts rename to app/.server/llm/tools/weather.ts diff --git a/app/lib/.server/llm/utils.ts b/app/.server/llm/utils.ts similarity index 97% rename from app/lib/.server/llm/utils.ts rename to app/.server/llm/utils.ts index 41ee00e..68e6d6b 100644 --- a/app/lib/.server/llm/utils.ts +++ b/app/.server/llm/utils.ts @@ -1,6 +1,6 @@ -import type { PageMap, SectionMap } from '~/lib/stores/pages'; import type { Section } from '~/types/actions'; import type { SummaryAnnotation, UPageUIMessage } from '~/types/message'; +import type { PageMap, SectionMap } from '~/types/pages'; export function getUserMessageContent(message: Omit): string { if (message.role !== 'user') { diff --git a/app/lib/modules/constants.ts b/app/.server/modules/constants.ts similarity index 90% rename from app/lib/modules/constants.ts rename to app/.server/modules/constants.ts index 13b85ad..c764e3e 100644 --- a/app/lib/modules/constants.ts +++ b/app/.server/modules/constants.ts @@ -1,4 +1,4 @@ -import { LLMManager } from '~/lib/modules/llm/manager.server'; +import { LLMManager } from '~/.server/modules/llm/manager.server'; const llmManager = LLMManager.getInstance(); diff --git a/app/lib/modules/llm/base-provider.ts b/app/.server/modules/llm/base-provider.ts similarity index 100% rename from app/lib/modules/llm/base-provider.ts rename to app/.server/modules/llm/base-provider.ts diff --git a/app/lib/modules/llm/manager.server.ts b/app/.server/modules/llm/manager.server.ts similarity index 100% rename from app/lib/modules/llm/manager.server.ts rename to app/.server/modules/llm/manager.server.ts diff --git a/app/lib/modules/llm/providers/amazon-bedrock.ts b/app/.server/modules/llm/providers/amazon-bedrock.ts similarity index 95% rename from app/lib/modules/llm/providers/amazon-bedrock.ts rename to app/.server/modules/llm/providers/amazon-bedrock.ts index 59195e4..faad17d 100644 --- a/app/lib/modules/llm/providers/amazon-bedrock.ts +++ b/app/.server/modules/llm/providers/amazon-bedrock.ts @@ -1,7 +1,7 @@ import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock'; import { type LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; interface AWSBedRockConfig { diff --git a/app/lib/modules/llm/providers/anthropic.ts b/app/.server/modules/llm/providers/anthropic.ts similarity index 94% rename from app/lib/modules/llm/providers/anthropic.ts rename to app/.server/modules/llm/providers/anthropic.ts index 63b6ca9..035aa39 100644 --- a/app/lib/modules/llm/providers/anthropic.ts +++ b/app/.server/modules/llm/providers/anthropic.ts @@ -1,7 +1,7 @@ import { createAnthropic } from '@ai-sdk/anthropic'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class AnthropicProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/cohere.ts b/app/.server/modules/llm/providers/cohere.ts similarity index 93% rename from app/lib/modules/llm/providers/cohere.ts rename to app/.server/modules/llm/providers/cohere.ts index e3487bb..d349663 100644 --- a/app/lib/modules/llm/providers/cohere.ts +++ b/app/.server/modules/llm/providers/cohere.ts @@ -1,7 +1,7 @@ import { createCohere } from '@ai-sdk/cohere'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class CohereProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/deepseek.ts b/app/.server/modules/llm/providers/deepseek.ts similarity index 89% rename from app/lib/modules/llm/providers/deepseek.ts rename to app/.server/modules/llm/providers/deepseek.ts index 815395a..d72b48b 100644 --- a/app/lib/modules/llm/providers/deepseek.ts +++ b/app/.server/modules/llm/providers/deepseek.ts @@ -1,7 +1,7 @@ import { createDeepSeek } from '@ai-sdk/deepseek'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class DeepseekProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/doubao.ts b/app/.server/modules/llm/providers/doubao.ts similarity index 93% rename from app/lib/modules/llm/providers/doubao.ts rename to app/.server/modules/llm/providers/doubao.ts index afcd64c..68877e7 100644 --- a/app/lib/modules/llm/providers/doubao.ts +++ b/app/.server/modules/llm/providers/doubao.ts @@ -1,7 +1,7 @@ import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class DouBaoProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/ernie.ts b/app/.server/modules/llm/providers/ernie.ts similarity index 92% rename from app/lib/modules/llm/providers/ernie.ts rename to app/.server/modules/llm/providers/ernie.ts index d111f02..e23ef40 100644 --- a/app/lib/modules/llm/providers/ernie.ts +++ b/app/.server/modules/llm/providers/ernie.ts @@ -1,7 +1,7 @@ import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class ErnieProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/github.ts b/app/.server/modules/llm/providers/github.ts similarity index 92% rename from app/lib/modules/llm/providers/github.ts rename to app/.server/modules/llm/providers/github.ts index 652b9de..5508548 100644 --- a/app/lib/modules/llm/providers/github.ts +++ b/app/.server/modules/llm/providers/github.ts @@ -1,7 +1,7 @@ import { createOpenAI } from '@ai-sdk/openai'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class GithubProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/google.ts b/app/.server/modules/llm/providers/google.ts similarity index 95% rename from app/lib/modules/llm/providers/google.ts rename to app/.server/modules/llm/providers/google.ts index 58074cb..f03de18 100644 --- a/app/lib/modules/llm/providers/google.ts +++ b/app/.server/modules/llm/providers/google.ts @@ -1,7 +1,7 @@ import { createGoogleGenerativeAI } from '@ai-sdk/google'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class GoogleProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/groq.ts b/app/.server/modules/llm/providers/groq.ts similarity index 95% rename from app/lib/modules/llm/providers/groq.ts rename to app/.server/modules/llm/providers/groq.ts index 3e4708a..37d3b28 100644 --- a/app/lib/modules/llm/providers/groq.ts +++ b/app/.server/modules/llm/providers/groq.ts @@ -1,7 +1,7 @@ import { createOpenAI } from '@ai-sdk/openai'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class GroqProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/huggingface.ts b/app/.server/modules/llm/providers/huggingface.ts similarity index 95% rename from app/lib/modules/llm/providers/huggingface.ts rename to app/.server/modules/llm/providers/huggingface.ts index b6aa82d..06929d7 100644 --- a/app/lib/modules/llm/providers/huggingface.ts +++ b/app/.server/modules/llm/providers/huggingface.ts @@ -1,7 +1,7 @@ import { createOpenAI } from '@ai-sdk/openai'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class HuggingFaceProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/hyperbolic.ts b/app/.server/modules/llm/providers/hyperbolic.ts similarity index 94% rename from app/lib/modules/llm/providers/hyperbolic.ts rename to app/.server/modules/llm/providers/hyperbolic.ts index 2c39f28..188506b 100644 --- a/app/lib/modules/llm/providers/hyperbolic.ts +++ b/app/.server/modules/llm/providers/hyperbolic.ts @@ -1,7 +1,7 @@ import { createOpenAI } from '@ai-sdk/openai'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class HyperbolicProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/kimi.ts b/app/.server/modules/llm/providers/kimi.ts similarity index 92% rename from app/lib/modules/llm/providers/kimi.ts rename to app/.server/modules/llm/providers/kimi.ts index 03c1f45..64aadfe 100644 --- a/app/lib/modules/llm/providers/kimi.ts +++ b/app/.server/modules/llm/providers/kimi.ts @@ -1,7 +1,7 @@ import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class KimiProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/lmstudio.ts b/app/.server/modules/llm/providers/lmstudio.ts similarity index 94% rename from app/lib/modules/llm/providers/lmstudio.ts rename to app/.server/modules/llm/providers/lmstudio.ts index 0781986..62dcdc3 100644 --- a/app/lib/modules/llm/providers/lmstudio.ts +++ b/app/.server/modules/llm/providers/lmstudio.ts @@ -1,7 +1,7 @@ import { createOpenAI } from '@ai-sdk/openai'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; import { logger } from '~/utils/logger'; diff --git a/app/lib/modules/llm/providers/mistral.ts b/app/.server/modules/llm/providers/mistral.ts similarity index 92% rename from app/lib/modules/llm/providers/mistral.ts rename to app/.server/modules/llm/providers/mistral.ts index b318a43..6a686fb 100644 --- a/app/lib/modules/llm/providers/mistral.ts +++ b/app/.server/modules/llm/providers/mistral.ts @@ -1,7 +1,7 @@ import { createMistral } from '@ai-sdk/mistral'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class MistralProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/ollama.ts b/app/.server/modules/llm/providers/ollama.ts similarity index 95% rename from app/lib/modules/llm/providers/ollama.ts rename to app/.server/modules/llm/providers/ollama.ts index 9e89882..f640ed5 100644 --- a/app/lib/modules/llm/providers/ollama.ts +++ b/app/.server/modules/llm/providers/ollama.ts @@ -1,7 +1,7 @@ import type { LanguageModel } from 'ai'; import { createOllama } from 'ollama-ai-provider-v2'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; import { logger } from '~/utils/logger'; diff --git a/app/lib/modules/llm/providers/open-router.ts b/app/.server/modules/llm/providers/open-router.ts similarity index 96% rename from app/lib/modules/llm/providers/open-router.ts rename to app/.server/modules/llm/providers/open-router.ts index 3ee33fd..506fab1 100644 --- a/app/lib/modules/llm/providers/open-router.ts +++ b/app/.server/modules/llm/providers/open-router.ts @@ -1,7 +1,7 @@ import { createOpenRouter } from '@openrouter/ai-sdk-provider'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; interface OpenRouterModel { diff --git a/app/lib/modules/llm/providers/openai.ts b/app/.server/modules/llm/providers/openai.ts similarity index 92% rename from app/lib/modules/llm/providers/openai.ts rename to app/.server/modules/llm/providers/openai.ts index 83c0dcc..7450c98 100644 --- a/app/lib/modules/llm/providers/openai.ts +++ b/app/.server/modules/llm/providers/openai.ts @@ -1,8 +1,8 @@ import { createOpenAI } from '@ai-sdk/openai'; import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class OpenAILikeProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/perplexity.ts b/app/.server/modules/llm/providers/perplexity.ts similarity index 90% rename from app/lib/modules/llm/providers/perplexity.ts rename to app/.server/modules/llm/providers/perplexity.ts index b680b61..becd5af 100644 --- a/app/lib/modules/llm/providers/perplexity.ts +++ b/app/.server/modules/llm/providers/perplexity.ts @@ -1,7 +1,7 @@ import { createOpenAI } from '@ai-sdk/openai'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class PerplexityProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/qwen.ts b/app/.server/modules/llm/providers/qwen.ts similarity index 93% rename from app/lib/modules/llm/providers/qwen.ts rename to app/.server/modules/llm/providers/qwen.ts index 5b436f6..277ecdb 100644 --- a/app/lib/modules/llm/providers/qwen.ts +++ b/app/.server/modules/llm/providers/qwen.ts @@ -1,7 +1,7 @@ import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class QwenProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/together.ts b/app/.server/modules/llm/providers/together.ts similarity index 93% rename from app/lib/modules/llm/providers/together.ts rename to app/.server/modules/llm/providers/together.ts index 743e911..d8164ed 100644 --- a/app/lib/modules/llm/providers/together.ts +++ b/app/.server/modules/llm/providers/together.ts @@ -1,6 +1,6 @@ import type { LanguageModel } from 'ai'; -import { BaseProvider, getOpenAILikeModel } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider, getOpenAILikeModel } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class TogetherProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/xai.ts b/app/.server/modules/llm/providers/xai.ts similarity index 88% rename from app/lib/modules/llm/providers/xai.ts rename to app/.server/modules/llm/providers/xai.ts index c9b7bb4..d5f070e 100644 --- a/app/lib/modules/llm/providers/xai.ts +++ b/app/.server/modules/llm/providers/xai.ts @@ -1,7 +1,7 @@ import { createOpenAI } from '@ai-sdk/openai'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class XAIProvider extends BaseProvider { diff --git a/app/lib/modules/llm/providers/zhipu.ts b/app/.server/modules/llm/providers/zhipu.ts similarity index 93% rename from app/lib/modules/llm/providers/zhipu.ts rename to app/.server/modules/llm/providers/zhipu.ts index 49b9525..05a61a8 100644 --- a/app/lib/modules/llm/providers/zhipu.ts +++ b/app/.server/modules/llm/providers/zhipu.ts @@ -1,7 +1,7 @@ import { createOpenAICompatible } from '@ai-sdk/openai-compatible'; import type { LanguageModel } from 'ai'; -import { BaseProvider } from '~/lib/modules/llm/base-provider'; -import type { ModelInfo } from '~/lib/modules/llm/types'; +import { BaseProvider } from '~/.server/modules/llm/base-provider'; +import type { ModelInfo } from '~/.server/modules/llm/types'; import type { IProviderSetting } from '~/types/model'; export default class ZhiPuProvider extends BaseProvider { diff --git a/app/lib/modules/llm/registry.ts b/app/.server/modules/llm/registry.ts similarity index 100% rename from app/lib/modules/llm/registry.ts rename to app/.server/modules/llm/registry.ts diff --git a/app/lib/modules/llm/types.ts b/app/.server/modules/llm/types.ts similarity index 100% rename from app/lib/modules/llm/types.ts rename to app/.server/modules/llm/types.ts diff --git a/app/lib/common/prompt-library.ts b/app/.server/prompts/prompt-library.ts similarity index 94% rename from app/lib/common/prompt-library.ts rename to app/.server/prompts/prompt-library.ts index ef9062e..bf2ed6c 100644 --- a/app/lib/common/prompt-library.ts +++ b/app/.server/prompts/prompt-library.ts @@ -1,4 +1,4 @@ -import { getSystemPrompt } from './prompts/prompts'; +import { getSystemPrompt } from './prompts'; export interface PromptOptions { cwd: string; diff --git a/app/lib/common/prompts/prompts.ts b/app/.server/prompts/prompts.ts similarity index 100% rename from app/lib/common/prompts/prompts.ts rename to app/.server/prompts/prompts.ts diff --git a/app/lib/.server/auth.ts b/app/.server/service/auth.ts similarity index 99% rename from app/lib/.server/auth.ts rename to app/.server/service/auth.ts index 889b526..72e3c0f 100644 --- a/app/lib/.server/auth.ts +++ b/app/.server/service/auth.ts @@ -2,8 +2,8 @@ import type { IdTokenClaims } from '@logto/node'; import { type LogtoContext, makeLogtoRemix } from '@logto/remix'; import type { LoaderFunctionArgs } from '@remix-run/node'; import { createCookieSessionStorage, redirect } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger.server'; import type { LogtoUser } from '~/types/logto'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('auth.server'); diff --git a/app/lib/.server/chatUsage.ts b/app/.server/service/chat-usage.ts similarity index 98% rename from app/lib/.server/chatUsage.ts rename to app/.server/service/chat-usage.ts index be4ff02..c7e49a3 100644 --- a/app/lib/.server/chatUsage.ts +++ b/app/.server/service/chat-usage.ts @@ -1,5 +1,5 @@ -import { createScopedLogger } from '~/lib/.server/logger'; -import { prisma } from '~/lib/.server/prisma'; +import { prisma } from '~/.server/service/prisma'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('chatUsage.server'); diff --git a/app/lib/.server/chat.ts b/app/.server/service/chat.ts similarity index 98% rename from app/lib/.server/chat.ts rename to app/.server/service/chat.ts index 18bb1ad..81476c5 100644 --- a/app/lib/.server/chat.ts +++ b/app/.server/service/chat.ts @@ -1,5 +1,5 @@ -import { createScopedLogger } from '~/lib/.server/logger'; -import { prisma } from '~/lib/.server/prisma'; +import { prisma } from '~/.server/service/prisma'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('chat.server'); diff --git a/app/lib/.server/connectionSettings.ts b/app/.server/service/connection-settings.ts similarity index 99% rename from app/lib/.server/connectionSettings.ts rename to app/.server/service/connection-settings.ts index 64c97a8..1d5dbf8 100644 --- a/app/lib/.server/connectionSettings.ts +++ b/app/.server/service/connection-settings.ts @@ -1,4 +1,4 @@ -import { deleteUserSetting, deleteUserSettings, getUserSetting, setUserSetting } from '~/lib/.server/userSettings'; +import { deleteUserSetting, deleteUserSettings, getUserSetting, setUserSetting } from '~/.server/service/user-settings'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('connectionSettings.server'); diff --git a/app/lib/.server/deployment.ts b/app/.server/service/deployment.ts similarity index 99% rename from app/lib/.server/deployment.ts rename to app/.server/service/deployment.ts index 5b019b5..41b2f23 100644 --- a/app/lib/.server/deployment.ts +++ b/app/.server/service/deployment.ts @@ -1,4 +1,4 @@ -import { prisma } from '~/lib/.server/prisma'; +import { prisma } from '~/.server/service/prisma'; import type { DeploymentPlatform } from '~/types/deployment'; import { createScopedLogger } from '~/utils/logger'; diff --git a/app/lib/.server/message.ts b/app/.server/service/message.ts similarity index 98% rename from app/lib/.server/message.ts rename to app/.server/service/message.ts index 0150146..0347f09 100644 --- a/app/lib/.server/message.ts +++ b/app/.server/service/message.ts @@ -1,9 +1,9 @@ import type { Message } from '@prisma/client'; import type { JsonArray } from '@prisma/client/runtime/library'; import type { TextUIPart, UIMessagePart } from 'ai'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { prisma } from '~/lib/.server/prisma'; +import { prisma } from '~/.server/service/prisma'; import type { SummaryAnnotation, UPageDataParts, UPageUIMessage } from '~/types/message'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('message.server'); diff --git a/app/lib/.server/page.ts b/app/.server/service/page.ts similarity index 99% rename from app/lib/.server/page.ts rename to app/.server/service/page.ts index f9e92c5..cac364a 100644 --- a/app/lib/.server/page.ts +++ b/app/.server/service/page.ts @@ -1,6 +1,6 @@ import type { JsonArray, JsonObject } from '@prisma/client/runtime/library'; import type { Page } from '~/types/actions'; -import { createScopedLogger } from './logger'; +import { createScopedLogger } from '~/utils/logger'; import { prisma } from './prisma'; const logger = createScopedLogger('page.server'); diff --git a/app/lib/.server/prisma.ts b/app/.server/service/prisma.ts similarity index 100% rename from app/lib/.server/prisma.ts rename to app/.server/service/prisma.ts diff --git a/app/lib/.server/projectService.ts b/app/.server/service/project-service.ts similarity index 98% rename from app/lib/.server/projectService.ts rename to app/.server/service/project-service.ts index 0bc62e5..e8cae06 100644 --- a/app/lib/.server/projectService.ts +++ b/app/.server/service/project-service.ts @@ -1,5 +1,5 @@ -import { createScopedLogger } from '~/lib/.server/logger'; import type { Page } from '~/types/actions'; +import { createScopedLogger } from '~/utils/logger'; import { createOrUpdatePages, getPageByMessageId } from './page'; import { createSection, deleteMessageSections, getMessageSections, type SectionCreateParams } from './section'; diff --git a/app/lib/.server/section.ts b/app/.server/service/section.ts similarity index 98% rename from app/lib/.server/section.ts rename to app/.server/service/section.ts index 2147174..bc3313f 100644 --- a/app/lib/.server/section.ts +++ b/app/.server/service/section.ts @@ -1,6 +1,6 @@ -import { createScopedLogger } from '~/lib/.server/logger'; -import { prisma } from '~/lib/.server/prisma'; +import { prisma } from '~/.server/service/prisma'; import type { Section } from '~/types/actions'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('section.server'); diff --git a/app/lib/.server/userSettings.ts b/app/.server/service/user-settings.ts similarity index 98% rename from app/lib/.server/userSettings.ts rename to app/.server/service/user-settings.ts index fec91e2..8f03af5 100644 --- a/app/lib/.server/userSettings.ts +++ b/app/.server/service/user-settings.ts @@ -1,4 +1,4 @@ -import { prisma } from '~/lib/.server/prisma'; +import { prisma } from '~/.server/service/prisma'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('userSettings.server'); diff --git a/app/lib/storage/base-provider.server.ts b/app/.server/storage/base-provider.server.ts similarity index 100% rename from app/lib/storage/base-provider.server.ts rename to app/.server/storage/base-provider.server.ts diff --git a/app/lib/storage/index.server.ts b/app/.server/storage/index.server.ts similarity index 94% rename from app/lib/storage/index.server.ts rename to app/.server/storage/index.server.ts index d21e619..7794a7a 100644 --- a/app/lib/storage/index.server.ts +++ b/app/.server/storage/index.server.ts @@ -1,4 +1,4 @@ -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; import { LocalStorageProvider } from './local-provider.server'; import type { StorageProvider } from './types'; diff --git a/app/lib/storage/local-provider.server.ts b/app/.server/storage/local-provider.server.ts similarity index 98% rename from app/lib/storage/local-provider.server.ts rename to app/.server/storage/local-provider.server.ts index e77d18f..a7201f5 100644 --- a/app/lib/storage/local-provider.server.ts +++ b/app/.server/storage/local-provider.server.ts @@ -1,6 +1,6 @@ import fs from 'fs'; import path from 'path'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; import { BaseStorageProvider } from './base-provider.server'; import type { StorageFile, StorageUploadOptions } from './types'; diff --git a/app/lib/storage/types.ts b/app/.server/storage/types.ts similarity index 100% rename from app/lib/storage/types.ts rename to app/.server/storage/types.ts diff --git a/app/utils/api-response.ts b/app/.server/utils/api-response.ts similarity index 100% rename from app/utils/api-response.ts rename to app/.server/utils/api-response.ts diff --git a/app/lib/fetch.ts b/app/.server/utils/fetch.ts similarity index 100% rename from app/lib/fetch.ts rename to app/.server/utils/fetch.ts diff --git a/app/utils/token.ts b/app/.server/utils/token.ts similarity index 100% rename from app/utils/token.ts rename to app/.server/utils/token.ts diff --git a/app/lib/.server/logger.server.ts b/app/lib/.server/logger.server.ts deleted file mode 100644 index 7e150b4..0000000 --- a/app/lib/.server/logger.server.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { Chalk } from 'chalk'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as winston from 'winston'; -import DailyRotateFile from 'winston-daily-rotate-file'; -import type { DebugLevel } from '~/utils/logger'; - -const chalk = new Chalk({ level: 3 }); - -type LoggerFunction = (...messages: any[]) => void; - -interface Logger { - trace: LoggerFunction; - debug: LoggerFunction; - info: LoggerFunction; - warn: LoggerFunction; - error: LoggerFunction; - setLevel: (level: DebugLevel) => void; -} - -let currentLevel: DebugLevel = - (process.env.LOG_LEVEL as DebugLevel | undefined) || (import.meta.env.DEV ? 'debug' : 'info'); - -// 文件日志配置 -const enableFileLogging = process.env.USAGE_LOG_FILE !== 'false'; -const logDir = path.join(process.cwd(), 'logs'); - -// 确保日志目录存在 -if (enableFileLogging) { - try { - if (!fs.existsSync(logDir)) { - fs.mkdirSync(logDir, { recursive: true }); - } - } catch (error) { - console.error('Failed to create logs directory:', error); - } -} - -// 创建 Winston logger 实例 -const winstonLogger = enableFileLogging - ? winston.createLogger({ - level: currentLevel, - format: winston.format.combine( - winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), - winston.format.printf((info) => { - const { timestamp, level, message, scope } = info; - return `${timestamp} [${level.toUpperCase()}]${scope ? ` [${scope}]` : ''}: ${message}`; - }), - ), - transports: [ - // 按日期分割的错误日志文件 - new DailyRotateFile({ - filename: path.join(logDir, 'error-%DATE%.log'), - datePattern: 'YYYY-MM-DD', - level: 'error', - maxSize: '10m', // 10MB - maxFiles: 14, // 保留14天 - format: winston.format.combine(winston.format.timestamp(), winston.format.json()), - }) as winston.transport, - // 所有级别日志 - new DailyRotateFile({ - filename: path.join(logDir, 'combined-%DATE%.log'), - datePattern: 'YYYY-MM-DD', - maxSize: '20m', // 20MB - maxFiles: 7, // 保留7天 - format: winston.format.combine(winston.format.timestamp(), winston.format.json()), - }) as winston.transport, - ], - }) - : null; - -export const logger: Logger = { - trace: (...messages: any[]) => log('trace', undefined, messages), - debug: (...messages: any[]) => log('debug', undefined, messages), - info: (...messages: any[]) => log('info', undefined, messages), - warn: (...messages: any[]) => log('warn', undefined, messages), - error: (...messages: any[]) => log('error', undefined, messages), - setLevel, -}; - -export function createScopedLogger(scope: string): Logger { - return { - trace: (...messages: any[]) => log('trace', scope, messages), - debug: (...messages: any[]) => log('debug', scope, messages), - info: (...messages: any[]) => log('info', scope, messages), - warn: (...messages: any[]) => log('warn', scope, messages), - error: (...messages: any[]) => log('error', scope, messages), - setLevel, - }; -} - -function setLevel(level: DebugLevel) { - if ((level === 'trace' || level === 'debug') && import.meta.env.PROD) { - return; - } - - currentLevel = level; - - // 更新 Winston logger 级别 - if (winstonLogger) { - winstonLogger.level = level; - } -} - -function log(level: DebugLevel, scope: string | undefined, messages: any[]) { - const levelOrder: DebugLevel[] = ['trace', 'debug', 'info', 'warn', 'error']; - - if (levelOrder.indexOf(level) < levelOrder.indexOf(currentLevel)) { - return; - } - - const allMessages = messages.reduce((acc, current) => { - if (acc.endsWith('\n')) { - return acc + current; - } - - if (!acc) { - return current; - } - - return `${acc} ${current}`; - }, ''); - - const labelBackgroundColor = getColorForLevel(level); - const labelTextColor = level === 'warn' ? '#000000' : '#FFFFFF'; - - let labelText = formatText(` ${level.toUpperCase()} `, labelTextColor, labelBackgroundColor); - - if (scope) { - labelText = `${labelText} ${formatText(` ${scope} `, '#FFFFFF', '77828D')}`; - } - - // 控制台日志 - console.log(`${labelText}`, allMessages); - - // 写入文件日志 - if (winstonLogger) { - try { - winstonLogger.log({ - level, - message: allMessages, - scope, - }); - } catch (error) { - console.error('Failed to write to log file:', error); - } - } -} - -function formatText(text: string, color: string, bg: string) { - return chalk.bgHex(bg)(chalk.hex(color)(text)); -} - -function getColorForLevel(level: DebugLevel): string { - switch (level) { - case 'trace': - case 'debug': { - return '#77828D'; - } - case 'info': { - return '#1389FD'; - } - case 'warn': { - return '#FFDB6C'; - } - case 'error': { - return '#EE4744'; - } - default: { - return '#000000'; - } - } -} - -export const renderLogger = createScopedLogger('Render'); diff --git a/app/lib/.server/logger.ts b/app/lib/.server/logger.ts deleted file mode 100644 index 7e150b4..0000000 --- a/app/lib/.server/logger.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { Chalk } from 'chalk'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as winston from 'winston'; -import DailyRotateFile from 'winston-daily-rotate-file'; -import type { DebugLevel } from '~/utils/logger'; - -const chalk = new Chalk({ level: 3 }); - -type LoggerFunction = (...messages: any[]) => void; - -interface Logger { - trace: LoggerFunction; - debug: LoggerFunction; - info: LoggerFunction; - warn: LoggerFunction; - error: LoggerFunction; - setLevel: (level: DebugLevel) => void; -} - -let currentLevel: DebugLevel = - (process.env.LOG_LEVEL as DebugLevel | undefined) || (import.meta.env.DEV ? 'debug' : 'info'); - -// 文件日志配置 -const enableFileLogging = process.env.USAGE_LOG_FILE !== 'false'; -const logDir = path.join(process.cwd(), 'logs'); - -// 确保日志目录存在 -if (enableFileLogging) { - try { - if (!fs.existsSync(logDir)) { - fs.mkdirSync(logDir, { recursive: true }); - } - } catch (error) { - console.error('Failed to create logs directory:', error); - } -} - -// 创建 Winston logger 实例 -const winstonLogger = enableFileLogging - ? winston.createLogger({ - level: currentLevel, - format: winston.format.combine( - winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), - winston.format.printf((info) => { - const { timestamp, level, message, scope } = info; - return `${timestamp} [${level.toUpperCase()}]${scope ? ` [${scope}]` : ''}: ${message}`; - }), - ), - transports: [ - // 按日期分割的错误日志文件 - new DailyRotateFile({ - filename: path.join(logDir, 'error-%DATE%.log'), - datePattern: 'YYYY-MM-DD', - level: 'error', - maxSize: '10m', // 10MB - maxFiles: 14, // 保留14天 - format: winston.format.combine(winston.format.timestamp(), winston.format.json()), - }) as winston.transport, - // 所有级别日志 - new DailyRotateFile({ - filename: path.join(logDir, 'combined-%DATE%.log'), - datePattern: 'YYYY-MM-DD', - maxSize: '20m', // 20MB - maxFiles: 7, // 保留7天 - format: winston.format.combine(winston.format.timestamp(), winston.format.json()), - }) as winston.transport, - ], - }) - : null; - -export const logger: Logger = { - trace: (...messages: any[]) => log('trace', undefined, messages), - debug: (...messages: any[]) => log('debug', undefined, messages), - info: (...messages: any[]) => log('info', undefined, messages), - warn: (...messages: any[]) => log('warn', undefined, messages), - error: (...messages: any[]) => log('error', undefined, messages), - setLevel, -}; - -export function createScopedLogger(scope: string): Logger { - return { - trace: (...messages: any[]) => log('trace', scope, messages), - debug: (...messages: any[]) => log('debug', scope, messages), - info: (...messages: any[]) => log('info', scope, messages), - warn: (...messages: any[]) => log('warn', scope, messages), - error: (...messages: any[]) => log('error', scope, messages), - setLevel, - }; -} - -function setLevel(level: DebugLevel) { - if ((level === 'trace' || level === 'debug') && import.meta.env.PROD) { - return; - } - - currentLevel = level; - - // 更新 Winston logger 级别 - if (winstonLogger) { - winstonLogger.level = level; - } -} - -function log(level: DebugLevel, scope: string | undefined, messages: any[]) { - const levelOrder: DebugLevel[] = ['trace', 'debug', 'info', 'warn', 'error']; - - if (levelOrder.indexOf(level) < levelOrder.indexOf(currentLevel)) { - return; - } - - const allMessages = messages.reduce((acc, current) => { - if (acc.endsWith('\n')) { - return acc + current; - } - - if (!acc) { - return current; - } - - return `${acc} ${current}`; - }, ''); - - const labelBackgroundColor = getColorForLevel(level); - const labelTextColor = level === 'warn' ? '#000000' : '#FFFFFF'; - - let labelText = formatText(` ${level.toUpperCase()} `, labelTextColor, labelBackgroundColor); - - if (scope) { - labelText = `${labelText} ${formatText(` ${scope} `, '#FFFFFF', '77828D')}`; - } - - // 控制台日志 - console.log(`${labelText}`, allMessages); - - // 写入文件日志 - if (winstonLogger) { - try { - winstonLogger.log({ - level, - message: allMessages, - scope, - }); - } catch (error) { - console.error('Failed to write to log file:', error); - } - } -} - -function formatText(text: string, color: string, bg: string) { - return chalk.bgHex(bg)(chalk.hex(color)(text)); -} - -function getColorForLevel(level: DebugLevel): string { - switch (level) { - case 'trace': - case 'debug': { - return '#77828D'; - } - case 'info': { - return '#1389FD'; - } - case 'warn': { - return '#FFDB6C'; - } - case 'error': { - return '#EE4744'; - } - default: { - return '#000000'; - } - } -} - -export const renderLogger = createScopedLogger('Render'); diff --git a/app/lib/api/connection.ts b/app/lib/api/connection.ts deleted file mode 100644 index 92bd08f..0000000 --- a/app/lib/api/connection.ts +++ /dev/null @@ -1,63 +0,0 @@ -export interface ConnectionStatus { - connected: boolean; - latency: number; - lastChecked: string; -} - -export const checkConnection = async (): Promise => { - try { - // Check if we have network connectivity - const online = navigator.onLine; - - if (!online) { - return { - connected: false, - latency: 0, - lastChecked: new Date().toISOString(), - }; - } - - // Try multiple endpoints in case one fails - const endpoints = [ - '/api/health', - '/', // Fallback to root route - '/favicon.ico', // Another common fallback - ]; - - let latency = 0; - let connected = false; - - for (const endpoint of endpoints) { - try { - const start = performance.now(); - const response = await fetch(endpoint, { - method: 'HEAD', - cache: 'no-cache', - }); - const end = performance.now(); - - if (response.ok) { - latency = Math.round(end - start); - connected = true; - break; - } - } catch (endpointError) { - console.debug(`Failed to connect to ${endpoint}:`, endpointError); - continue; - } - } - - return { - connected, - latency, - lastChecked: new Date().toISOString(), - }; - } catch (error) { - console.error('Connection check failed:', error); - return { - connected: false, - latency: 0, - lastChecked: new Date().toISOString(), - }; - } -}; diff --git a/app/lib/api/cookies.ts b/app/lib/api/cookies.ts deleted file mode 100644 index fa6862e..0000000 --- a/app/lib/api/cookies.ts +++ /dev/null @@ -1,33 +0,0 @@ -export function parseCookies(cookieHeader: string | null) { - const cookies: Record = {}; - - if (!cookieHeader) { - return cookies; - } - - // Split the cookie string by semicolons and spaces - const items = cookieHeader.split(';').map((cookie) => cookie.trim()); - - items.forEach((item) => { - const [name, ...rest] = item.split('='); - - if (name && rest.length > 0) { - // Decode the name and value, and join value parts in case it contains '=' - const decodedName = decodeURIComponent(name.trim()); - const decodedValue = decodeURIComponent(rest.join('=').trim()); - cookies[decodedName] = decodedValue; - } - }); - - return cookies; -} - -export function getApiKeysFromCookie(cookieHeader: string | null): Record { - const cookies = parseCookies(cookieHeader); - return cookies.apiKeys ? JSON.parse(cookies.apiKeys) : {}; -} - -export function getProviderSettingsFromCookie(cookieHeader: string | null): Record { - const cookies = parseCookies(cookieHeader); - return cookies.providers ? JSON.parse(cookies.providers) : {}; -} diff --git a/app/lib/api/features.ts b/app/lib/api/features.ts deleted file mode 100644 index c3ec533..0000000 --- a/app/lib/api/features.ts +++ /dev/null @@ -1,35 +0,0 @@ -export interface Feature { - id: string; - name: string; - description: string; - viewed: boolean; - releaseDate: string; -} - -export const getFeatureFlags = async (): Promise => { - /* - * TODO: Implement actual feature flags logic - * This is a mock implementation - */ - return [ - { - id: 'feature-1', - name: 'Dark Mode', - description: 'Enable dark mode for better night viewing', - viewed: true, - releaseDate: '2024-03-15', - }, - { - id: 'feature-2', - name: 'Tab Management', - description: 'Customize your tab layout', - viewed: false, - releaseDate: '2024-03-20', - }, - ]; -}; - -export const markFeatureViewed = async (featureId: string): Promise => { - /* TODO: Implement actual feature viewed logic */ - console.log(`Marking feature ${featureId} as viewed`); -}; diff --git a/app/root.tsx b/app/root.tsx index bdd6342..5da89a3 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -17,17 +17,17 @@ import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { ClientOnly } from 'remix-utils/client-only'; import { Toaster } from 'sonner'; -import { getUser } from './lib/.server/auth'; -import { getUserUsageStats } from './lib/.server/chatUsage'; +import { getUser } from '~/.server/service/auth'; +import { getUserUsageStats } from '~/.server/service/chat-usage'; import { get1PanelConnectionSettings, getNetlifyConnectionSettings, getVercelConnectionSettings, -} from './lib/.server/connectionSettings'; -import { logStore } from './lib/stores/logs'; -import { themeStore } from './lib/stores/theme'; +} from '~/.server/service/connection-settings'; +import { logStore } from '~/stores/logs'; +import { themeStore } from '~/stores/theme'; +import { stripIndents } from '~/utils/strip-indent'; import globalStyles from './styles/index.scss?url'; -import { stripIndents } from './utils/strip-indent'; import 'virtual:uno.css'; import type { ComponentType } from 'react'; @@ -236,7 +236,7 @@ const LazyAuthErrorToast = () => { const [AuthErrorToast, setAuthErrorToast] = useState(null); useEffect(() => { - import('./components/AuthErrorToast.client').then((module) => { + import('~/.client/components/AuthErrorToast.client').then((module) => { setAuthErrorToast(() => module.AuthErrorToast); }); }, []); diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index 55ee00d..466aa02 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -1,8 +1,8 @@ import { data, type LoaderFunctionArgs, type MetaFunction } from '@remix-run/node'; -import { Chat } from '~/components/chat/Chat.client'; -import { Header } from '~/components/header/Header'; -import { getUser } from '~/lib/.server/auth'; -import { getUserUsageStats } from '~/lib/.server/chatUsage'; +import { Chat } from '~/.client/components/chat/Chat.client'; +import { Header } from '~/.client/components/header/Header'; +import { getUser } from '~/.server/service/auth'; +import { getUserUsageStats } from '~/.server/service/chat-usage'; export const meta: MetaFunction = () => { return [{ title: 'UPage' }, { name: 'description', content: 'Talk with UPage, an AI assistant from Lxware' }]; diff --git a/app/routes/api.1panel.$action/1panel.server.ts b/app/routes/api.1panel.$action/1panel.server.ts index b122fa9..70e503c 100644 --- a/app/routes/api.1panel.$action/1panel.server.ts +++ b/app/routes/api.1panel.$action/1panel.server.ts @@ -2,7 +2,7 @@ import crypto from 'crypto'; import type { _1PanelPaginationResponse, _1PanelResponse, _1PanelWebsite } from '~/types/1panel'; import { isBinaryString } from '~/utils/file-utils'; import { generateUUID } from '~/utils/uuid'; -import { request } from '../../lib/fetch'; +import { request } from '../../.server/utils/fetch'; export interface _1PanelBaseParams { serverUrl: string; diff --git a/app/routes/api.1panel.$action/auth.server.ts b/app/routes/api.1panel.$action/auth.server.ts index d9027a6..be41c05 100644 --- a/app/routes/api.1panel.$action/auth.server.ts +++ b/app/routes/api.1panel.$action/auth.server.ts @@ -1,7 +1,7 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { delete1PanelConnectionSettings, save1PanelConnectionSettings } from '~/lib/.server/connectionSettings'; +import { delete1PanelConnectionSettings, save1PanelConnectionSettings } from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { getWebsiteList } from '~/routes/api.1panel.$action/1panel.server'; -import { errorResponse, successResponse } from '~/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.1panel.auth'); diff --git a/app/routes/api.1panel.$action/delete.server.ts b/app/routes/api.1panel.$action/delete.server.ts index 2f08082..bf68657 100644 --- a/app/routes/api.1panel.$action/delete.server.ts +++ b/app/routes/api.1panel.$action/delete.server.ts @@ -1,7 +1,7 @@ import type { ActionFunctionArgs } from '@remix-run/node'; -import { get1PanelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { deleteDeploymentById, getDeploymentById } from '~/lib/.server/deployment'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { get1PanelConnectionSettings } from '~/.server/service/connection-settings'; +import { deleteDeploymentById, getDeploymentById } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; import { deleteWebsite } from './1panel.server'; diff --git a/app/routes/api.1panel.$action/deploy.server.ts b/app/routes/api.1panel.$action/deploy.server.ts index 1f66477..3050f17 100644 --- a/app/routes/api.1panel.$action/deploy.server.ts +++ b/app/routes/api.1panel.$action/deploy.server.ts @@ -1,7 +1,7 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { get1PanelConnectionSettings, save1PanelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { createOrUpdateDeployment, getLatestDeployment } from '~/lib/.server/deployment'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { get1PanelConnectionSettings, save1PanelConnectionSettings } from '~/.server/service/connection-settings'; +import { createOrUpdateDeployment, getLatestDeployment } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createWebsite, getWebsite, @@ -11,7 +11,7 @@ import { } from '~/routes/api.1panel.$action/1panel.server'; import type { _1PanelWebsite, _1PanelWebsiteInfo } from '~/types/1panel'; import { DeploymentPlatformEnum, DeploymentStatusEnum } from '~/types/deployment'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; interface DeployRequestBody { websiteId: number; diff --git a/app/routes/api.1panel.$action/route.tsx b/app/routes/api.1panel.$action/route.tsx index 70ba276..fac5c23 100644 --- a/app/routes/api.1panel.$action/route.tsx +++ b/app/routes/api.1panel.$action/route.tsx @@ -1,7 +1,7 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { errorResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { errorResponse } from '~/.server/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; import { handleAuth } from './auth.server'; import { deletePage } from './delete.server'; import { handleDeploy } from './deploy.server'; diff --git a/app/routes/api.1panel.$action/stats.server.ts b/app/routes/api.1panel.$action/stats.server.ts index 5f1d54a..7ceeb66 100644 --- a/app/routes/api.1panel.$action/stats.server.ts +++ b/app/routes/api.1panel.$action/stats.server.ts @@ -1,7 +1,7 @@ import { type LoaderFunctionArgs } from '@remix-run/node'; -import { get1PanelConnectionSettings } from '~/lib/.server/connectionSettings'; +import { get1PanelConnectionSettings } from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { getWebsiteList } from '~/routes/api.1panel.$action/1panel.server'; -import { errorResponse, successResponse } from '~/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.1panel.stats'); diff --git a/app/routes/api.1panel.$action/toggle-access.server.ts b/app/routes/api.1panel.$action/toggle-access.server.ts index 73fbf91..f1e032d 100644 --- a/app/routes/api.1panel.$action/toggle-access.server.ts +++ b/app/routes/api.1panel.$action/toggle-access.server.ts @@ -1,7 +1,7 @@ import type { ActionFunctionArgs } from '@remix-run/node'; -import { get1PanelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { getDeploymentById, updateDeploymentStatus } from '~/lib/.server/deployment'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { get1PanelConnectionSettings } from '~/.server/service/connection-settings'; +import { getDeploymentById, updateDeploymentStatus } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; import { toggleAccessWebsite } from './1panel.server'; diff --git a/app/routes/api.1panel.$action/websites.server.ts b/app/routes/api.1panel.$action/websites.server.ts index 602e721..97f7131 100644 --- a/app/routes/api.1panel.$action/websites.server.ts +++ b/app/routes/api.1panel.$action/websites.server.ts @@ -1,10 +1,10 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { get1PanelConnectionSettings, save1PanelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { deleteDeploymentsByPlatformAndId } from '~/lib/.server/deployment'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { get1PanelConnectionSettings, save1PanelConnectionSettings } from '~/.server/service/connection-settings'; +import { deleteDeploymentsByPlatformAndId } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { deleteWebsite, getWebsiteList } from '~/routes/api.1panel.$action/1panel.server'; import { DeploymentPlatformEnum } from '~/types/deployment'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; interface WebsiteListRequestBody { serverUrl?: string; diff --git a/app/routes/api.auth.$action/check-error.server.ts b/app/routes/api.auth.$action/check-error.server.ts index eb3ca9c..55de943 100644 --- a/app/routes/api.auth.$action/check-error.server.ts +++ b/app/routes/api.auth.$action/check-error.server.ts @@ -1,6 +1,6 @@ import type { LoaderFunctionArgs } from '@remix-run/node'; import { data } from '@remix-run/node'; -import { getAuthError } from '~/lib/.server/auth'; +import { getAuthError } from '~/.server/service/auth'; /** * 检查认证错误信息的路由 diff --git a/app/routes/api.auth.$action/route.tsx b/app/routes/api.auth.$action/route.tsx index 410e0c2..ad83fb1 100644 --- a/app/routes/api.auth.$action/route.tsx +++ b/app/routes/api.auth.$action/route.tsx @@ -1,5 +1,5 @@ import type { LoaderFunctionArgs } from '@remix-run/node'; -import { logto } from '~/lib/.server/auth'; +import { logto } from '~/.server/service/auth'; import { checkErrorLoader } from './check-error.server'; import { userLoader } from './user.server'; diff --git a/app/routes/api.auth.$action/user.server.ts b/app/routes/api.auth.$action/user.server.ts index 75e62ed..a46463b 100644 --- a/app/routes/api.auth.$action/user.server.ts +++ b/app/routes/api.auth.$action/user.server.ts @@ -1,5 +1,5 @@ import { data, type LoaderFunctionArgs } from '@remix-run/node'; -import { getUser } from '~/lib/.server/auth'; +import { getUser } from '~/.server/service/auth'; /** * 用户信息API端点 diff --git a/app/routes/api.chat.$action/delete.server.ts b/app/routes/api.chat.$action/delete.server.ts index e807eb0..1384181 100644 --- a/app/routes/api.chat.$action/delete.server.ts +++ b/app/routes/api.chat.$action/delete.server.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs } from '@remix-run/node'; -import { deleteChat, getUserChatById } from '~/lib/.server/chat'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { deleteChat, getUserChatById } from '~/.server/service/chat'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.chat.delete'); diff --git a/app/routes/api.chat.$action/fork.server.ts b/app/routes/api.chat.$action/fork.server.ts index 917a1ab..ea44f93 100644 --- a/app/routes/api.chat.$action/fork.server.ts +++ b/app/routes/api.chat.$action/fork.server.ts @@ -1,7 +1,7 @@ import type { ActionFunctionArgs } from '@remix-run/node'; -import { getUserChatById } from '~/lib/.server/chat'; -import { prisma } from '~/lib/.server/prisma'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getUserChatById } from '~/.server/service/chat'; +import { prisma } from '~/.server/service/prisma'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.chat.fork'); diff --git a/app/routes/api.chat.$action/list.server.ts b/app/routes/api.chat.$action/list.server.ts index 0fa20b1..6dfb9b2 100644 --- a/app/routes/api.chat.$action/list.server.ts +++ b/app/routes/api.chat.$action/list.server.ts @@ -1,6 +1,6 @@ import type { LoaderFunctionArgs } from '@remix-run/node'; -import { getUserChats } from '~/lib/.server/chat'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getUserChats } from '~/.server/service/chat'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.chat.list'); diff --git a/app/routes/api.chat.$action/route.tsx b/app/routes/api.chat.$action/route.tsx index 43299ac..976658f 100644 --- a/app/routes/api.chat.$action/route.tsx +++ b/app/routes/api.chat.$action/route.tsx @@ -1,6 +1,6 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { errorResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { errorResponse } from '~/.server/utils/api-response'; import { handleDeleteAction } from './delete.server'; import { handleForkAction } from './fork.server'; import { handleListLoader } from './list.server'; diff --git a/app/routes/api.chat.$action/update.server.ts b/app/routes/api.chat.$action/update.server.ts index 78ab45f..9cd3768 100644 --- a/app/routes/api.chat.$action/update.server.ts +++ b/app/routes/api.chat.$action/update.server.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs } from '@remix-run/node'; -import { getUserChatById, updateChat } from '~/lib/.server/chat'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getUserChatById, updateChat } from '~/.server/service/chat'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.chat.update'); diff --git a/app/routes/api.chat/chat.server.ts b/app/routes/api.chat/chat.server.ts index 56e6a15..e68ebbe 100644 --- a/app/routes/api.chat/chat.server.ts +++ b/app/routes/api.chat/chat.server.ts @@ -6,21 +6,21 @@ import { generateId, type UIMessageStreamWriter, } from 'ai'; -import { upsertChat } from '~/lib/.server/chat'; -import { ChatUsageStatus, recordUsage, updateUsageStatus } from '~/lib/.server/chatUsage'; -import { chatStreamText } from '~/lib/.server/llm/chat-stream-text'; -import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants'; -import { createSummary } from '~/lib/.server/llm/create-summary'; -import { type SelectContextResult, selectContext } from '~/lib/.server/llm/select-context'; -import { structuredPageSnapshot } from '~/lib/.server/llm/structured-page-snapshot'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { getHistoryChatMessages, saveChatMessages, updateDiscardedMessage } from '~/lib/.server/message'; -import { getPageByMessageId } from '~/lib/.server/page'; -import { CONTINUE_PROMPT } from '~/lib/common/prompts/prompts'; -import { DEFAULT_MODEL, DEFAULT_MODEL_DETAILS, getModel, MINOR_MODEL } from '~/lib/modules/constants'; +import { chatStreamText } from '~/.server/llm/chat-stream-text'; +import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/.server/llm/constants'; +import { createSummary } from '~/.server/llm/create-summary'; +import { type SelectContextResult, selectContext } from '~/.server/llm/select-context'; +import { structuredPageSnapshot } from '~/.server/llm/structured-page-snapshot'; +import { DEFAULT_MODEL, DEFAULT_MODEL_DETAILS, getModel, MINOR_MODEL } from '~/.server/modules/constants'; +import { CONTINUE_PROMPT } from '~/.server/prompts/prompts'; +import { upsertChat } from '~/.server/service/chat'; +import { ChatUsageStatus, recordUsage, updateUsageStatus } from '~/.server/service/chat-usage'; +import { getHistoryChatMessages, saveChatMessages, updateDiscardedMessage } from '~/.server/service/message'; +import { getPageByMessageId } from '~/.server/service/page'; +import { approximateUsageFromContent } from '~/.server/utils/token'; import type { Page } from '~/types/actions'; import type { UPageUIMessage } from '~/types/message'; -import { approximateUsageFromContent } from '~/utils/token'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.chat.chat'); diff --git a/app/routes/api.chat/mock-chat.server.ts b/app/routes/api.chat/mock-chat.server.ts index a2e3b6e..9541f40 100644 --- a/app/routes/api.chat/mock-chat.server.ts +++ b/app/routes/api.chat/mock-chat.server.ts @@ -2,7 +2,7 @@ import type { ActionFunctionArgs } from '@remix-run/node'; import { generateId } from 'ai'; import { readFile } from 'fs/promises'; import { join } from 'path'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.chat.mock-chat'); diff --git a/app/routes/api.chat/route.tsx b/app/routes/api.chat/route.tsx index 55f02c0..f5e60ba 100644 --- a/app/routes/api.chat/route.tsx +++ b/app/routes/api.chat/route.tsx @@ -1,6 +1,6 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { errorResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { errorResponse } from '~/.server/utils/api-response'; import { chatAction } from './chat.server'; import { mockChat } from './mock-chat.server'; diff --git a/app/routes/api.deployments.$action/route.tsx b/app/routes/api.deployments.$action/route.tsx index 22a5cc4..7f5a4d3 100644 --- a/app/routes/api.deployments.$action/route.tsx +++ b/app/routes/api.deployments.$action/route.tsx @@ -1,6 +1,6 @@ import { type LoaderFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { errorResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { errorResponse } from '~/.server/utils/api-response'; import { getDeploymentStats } from './stats.server'; export async function loader({ request, params }: LoaderFunctionArgs) { diff --git a/app/routes/api.deployments.$action/stats.server.ts b/app/routes/api.deployments.$action/stats.server.ts index 0a2a84d..f038f24 100644 --- a/app/routes/api.deployments.$action/stats.server.ts +++ b/app/routes/api.deployments.$action/stats.server.ts @@ -1,5 +1,5 @@ -import { prisma } from '~/lib/.server/prisma'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { prisma } from '~/.server/service/prisma'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.deployments.stats'); diff --git a/app/routes/api.deployments/route.tsx b/app/routes/api.deployments/route.tsx index 1dc030b..d8a24d2 100644 --- a/app/routes/api.deployments/route.tsx +++ b/app/routes/api.deployments/route.tsx @@ -1,7 +1,7 @@ import { type LoaderFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { getUserPlatformDeploymentsWithPagination } from '~/lib/.server/deployment'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { getUserPlatformDeploymentsWithPagination } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; export async function loader({ request }: LoaderFunctionArgs) { try { diff --git a/app/routes/api.enhancer/route.tsx b/app/routes/api.enhancer/route.tsx index 5122405..8bdeb05 100644 --- a/app/routes/api.enhancer/route.tsx +++ b/app/routes/api.enhancer/route.tsx @@ -1,10 +1,10 @@ import { type ActionFunctionArgs } from '@remix-run/node'; import type { UIMessage } from 'ai'; -import { requireAuth } from '~/lib/.server/auth'; -import { streamEnhancer } from '~/lib/.server/llm/stream-enhancer'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { getModel, MINOR_MODEL } from '~/lib/modules/constants'; -import { errorResponse } from '~/utils/api-response'; +import { streamEnhancer } from '~/.server/llm/stream-enhancer'; +import { getModel, MINOR_MODEL } from '~/.server/modules/constants'; +import { requireAuth } from '~/.server/service/auth'; +import { errorResponse } from '~/.server/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; export async function action(args: ActionFunctionArgs) { const authResult = await requireAuth(args.request, { isApi: true }); diff --git a/app/routes/api.git-proxy.$.ts b/app/routes/api.git-proxy.$.ts index aad0e81..5e56269 100644 --- a/app/routes/api.git-proxy.$.ts +++ b/app/routes/api.git-proxy.$.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/node'; import { json } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; // Allowed headers to forward to the target server const ALLOW_HEADERS = [ diff --git a/app/routes/api.netlify.$action/auth.server.ts b/app/routes/api.netlify.$action/auth.server.ts index 956c9fd..bd129ec 100644 --- a/app/routes/api.netlify.$action/auth.server.ts +++ b/app/routes/api.netlify.$action/auth.server.ts @@ -1,5 +1,5 @@ -import { deleteNetlifyConnectionSettings, saveNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { deleteNetlifyConnectionSettings, saveNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.netlify.auth'); diff --git a/app/routes/api.netlify.$action/delete.server.ts b/app/routes/api.netlify.$action/delete.server.ts index c954568..0005034 100644 --- a/app/routes/api.netlify.$action/delete.server.ts +++ b/app/routes/api.netlify.$action/delete.server.ts @@ -1,6 +1,6 @@ -import { getNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { deleteDeploymentById, getDeploymentById } from '~/lib/.server/deployment'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { deleteDeploymentById, getDeploymentById } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.netlify.delete'); diff --git a/app/routes/api.netlify.$action/deploy.server.ts b/app/routes/api.netlify.$action/deploy.server.ts index 991a1aa..d0fb17a 100644 --- a/app/routes/api.netlify.$action/deploy.server.ts +++ b/app/routes/api.netlify.$action/deploy.server.ts @@ -1,10 +1,10 @@ -import { getNetlifyConnectionSettings, saveNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { createOrUpdateDeployment, getLatestDeployment } from '~/lib/.server/deployment'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { getNetlifyConnectionSettings, saveNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { createOrUpdateDeployment, getLatestDeployment } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { DeploymentPlatformEnum, DeploymentStatusEnum } from '~/types/deployment'; import type { NetlifySiteInfo } from '~/types/netlify'; -import { errorResponse, successResponse } from '~/utils/api-response'; import { binaryStringToUint8Array, isBinaryString } from '~/utils/file-utils'; +import { createScopedLogger } from '~/utils/logger'; export type HandleDeployArgs = { request: Request; diff --git a/app/routes/api.netlify.$action/route.tsx b/app/routes/api.netlify.$action/route.tsx index a92d0a0..f3f6e77 100644 --- a/app/routes/api.netlify.$action/route.tsx +++ b/app/routes/api.netlify.$action/route.tsx @@ -1,7 +1,7 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { errorResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { errorResponse } from '~/.server/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; import { handleNetlifyAuth } from './auth.server'; import { deletePage } from './delete.server'; import { handleDeploy } from './deploy.server'; diff --git a/app/routes/api.netlify.$action/stats.server.ts b/app/routes/api.netlify.$action/stats.server.ts index dde3b6e..9e02db2 100644 --- a/app/routes/api.netlify.$action/stats.server.ts +++ b/app/routes/api.netlify.$action/stats.server.ts @@ -1,5 +1,5 @@ -import { getNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.netlify.stats'); diff --git a/app/routes/api.netlify.$action/toggle-access.server.ts b/app/routes/api.netlify.$action/toggle-access.server.ts index 8cb8131..a85d686 100644 --- a/app/routes/api.netlify.$action/toggle-access.server.ts +++ b/app/routes/api.netlify.$action/toggle-access.server.ts @@ -1,8 +1,8 @@ -import { getNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { getDeploymentById, updateDeploymentStatus } from '~/lib/.server/deployment'; -import { request } from '~/lib/fetch'; +import { getNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { getDeploymentById, updateDeploymentStatus } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; +import { request } from '~/.server/utils/fetch'; import type { NetlifySite } from '~/types/netlify'; -import { errorResponse, successResponse } from '~/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; import { generateUUID } from '~/utils/uuid'; diff --git a/app/routes/api.netlify.deploys.$deployId.$action.ts b/app/routes/api.netlify.deploys.$deployId.$action.ts index 1031172..c62f8c7 100644 --- a/app/routes/api.netlify.deploys.$deployId.$action.ts +++ b/app/routes/api.netlify.deploys.$deployId.$action.ts @@ -1,7 +1,7 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { getNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { getNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.netlify.deploys'); diff --git a/app/routes/api.netlify.sites.$siteId.cache.ts b/app/routes/api.netlify.sites.$siteId.cache.ts index 2be76c8..324cfd7 100644 --- a/app/routes/api.netlify.sites.$siteId.cache.ts +++ b/app/routes/api.netlify.sites.$siteId.cache.ts @@ -1,7 +1,7 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { getNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { getNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.netlify.sites.cache'); diff --git a/app/routes/api.netlify.sites.$siteId.ts b/app/routes/api.netlify.sites.$siteId.ts index 0b0ebac..fdf0304 100644 --- a/app/routes/api.netlify.sites.$siteId.ts +++ b/app/routes/api.netlify.sites.$siteId.ts @@ -1,9 +1,9 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { getNetlifyConnectionSettings } from '~/lib/.server/connectionSettings'; -import { deleteDeploymentsByPlatformAndId } from '~/lib/.server/deployment'; +import { requireAuth } from '~/.server/service/auth'; +import { getNetlifyConnectionSettings } from '~/.server/service/connection-settings'; +import { deleteDeploymentsByPlatformAndId } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { DeploymentPlatformEnum } from '~/types/deployment'; -import { errorResponse, successResponse } from '~/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.netlify.sites'); diff --git a/app/routes/api.project/route.tsx b/app/routes/api.project/route.tsx index 469250a..c7db9a4 100644 --- a/app/routes/api.project/route.tsx +++ b/app/routes/api.project/route.tsx @@ -1,9 +1,9 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger'; -import type { PageCreateParams } from '~/lib/.server/page'; -import { savePagesAndSections } from '~/lib/.server/projectService'; -import type { SectionCreateParams } from '~/lib/.server/section'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import type { PageCreateParams } from '~/.server/service/page'; +import { savePagesAndSections } from '~/.server/service/project-service'; +import type { SectionCreateParams } from '~/.server/service/section'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.project'); diff --git a/app/routes/api.system.$action/app-info.server.ts b/app/routes/api.system.$action/app-info.server.ts index 4eacc69..ea90d35 100644 --- a/app/routes/api.system.$action/app-info.server.ts +++ b/app/routes/api.system.$action/app-info.server.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs, LoaderFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; // These are injected by Vite at build time declare const __PKG_NAME: string; diff --git a/app/routes/api.system.$action/disk.server.ts b/app/routes/api.system.$action/disk.server.ts index 96ae8d5..13c91da 100644 --- a/app/routes/api.system.$action/disk.server.ts +++ b/app/routes/api.system.$action/disk.server.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs, LoaderFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; // Only import child_process if we're not in a Cloudflare environment let execSync: any; diff --git a/app/routes/api.system.$action/git-info.server.ts b/app/routes/api.system.$action/git-info.server.ts index 6a13fef..d0afb09 100644 --- a/app/routes/api.system.$action/git-info.server.ts +++ b/app/routes/api.system.$action/git-info.server.ts @@ -1,5 +1,5 @@ import { json, type LoaderFunction, type LoaderFunctionArgs } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; interface GitInfo { local: { diff --git a/app/routes/api.system.$action/memory.server.ts b/app/routes/api.system.$action/memory.server.ts index d6b74fc..dbaeb71 100644 --- a/app/routes/api.system.$action/memory.server.ts +++ b/app/routes/api.system.$action/memory.server.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs, LoaderFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; // Only import child_process if we're not in a Cloudflare environment let execSync: any; diff --git a/app/routes/api.system.$action/process.server.ts b/app/routes/api.system.$action/process.server.ts index 1c90d0b..fd26b36 100644 --- a/app/routes/api.system.$action/process.server.ts +++ b/app/routes/api.system.$action/process.server.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs, LoaderFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { createScopedLogger } from '~/utils/logger'; // Only import child_process if we're not in a Cloudflare environment let execSync: any; diff --git a/app/routes/api.system.$action/route.tsx b/app/routes/api.system.$action/route.tsx index 2d17f91..7a7fcaf 100644 --- a/app/routes/api.system.$action/route.tsx +++ b/app/routes/api.system.$action/route.tsx @@ -1,5 +1,5 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node'; -import { errorResponse } from '~/utils/api-response'; +import { errorResponse } from '~/.server/utils/api-response'; import { appInfoAction, appInfoLoader } from './app-info.server'; import { diskAction, diskLoader } from './disk.server'; import { gitInfoLoader } from './git-info.server'; diff --git a/app/routes/api.upload/route.tsx b/app/routes/api.upload/route.tsx index 945870b..5af4983 100644 --- a/app/routes/api.upload/route.tsx +++ b/app/routes/api.upload/route.tsx @@ -1,8 +1,8 @@ import { type ActionFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { storageProvider } from '~/lib/storage/index.server'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { storageProvider } from '~/.server/storage/index.server'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.upload'); diff --git a/app/routes/api.user.settings.ts b/app/routes/api.user.settings.ts index 4a78ea8..4c0bc6b 100644 --- a/app/routes/api.user.settings.ts +++ b/app/routes/api.user.settings.ts @@ -1,13 +1,13 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; +import { requireAuth } from '~/.server/service/auth'; import { deleteUserSetting, deleteUserSettings, getUserSetting, getUserSettings, setUserSetting, -} from '~/lib/.server/userSettings'; -import { errorResponse, successResponse } from '~/utils/api-response'; +} from '~/.server/service/user-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.user.settings'); diff --git a/app/routes/api.vercel.$action/auth.server.ts b/app/routes/api.vercel.$action/auth.server.ts index f48ef1e..bfba2ff 100644 --- a/app/routes/api.vercel.$action/auth.server.ts +++ b/app/routes/api.vercel.$action/auth.server.ts @@ -2,8 +2,8 @@ import { deleteVercelConnectionSettings, getVercelConnectionSettings, saveVercelConnectionSettings, -} from '~/lib/.server/connectionSettings'; -import { errorResponse, successResponse } from '~/utils/api-response'; +} from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.vercel.auth'); diff --git a/app/routes/api.vercel.$action/delete.server.ts b/app/routes/api.vercel.$action/delete.server.ts index 6b6e9d2..f2f9dbd 100644 --- a/app/routes/api.vercel.$action/delete.server.ts +++ b/app/routes/api.vercel.$action/delete.server.ts @@ -1,7 +1,7 @@ -import { getVercelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { deleteDeploymentById, getDeploymentById } from '~/lib/.server/deployment'; -import { request } from '~/lib/fetch'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getVercelConnectionSettings } from '~/.server/service/connection-settings'; +import { deleteDeploymentById, getDeploymentById } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; +import { request } from '~/.server/utils/fetch'; import { createScopedLogger } from '~/utils/logger'; import type { VercelResponseError } from './type'; diff --git a/app/routes/api.vercel.$action/deploy.server.ts b/app/routes/api.vercel.$action/deploy.server.ts index 4796928..6b3c326 100644 --- a/app/routes/api.vercel.$action/deploy.server.ts +++ b/app/routes/api.vercel.$action/deploy.server.ts @@ -1,10 +1,10 @@ -import { getVercelConnectionSettings, saveVercelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { createOrUpdateDeployment, getLatestDeployment } from '~/lib/.server/deployment'; -import { createScopedLogger } from '~/lib/.server/logger'; +import { getVercelConnectionSettings, saveVercelConnectionSettings } from '~/.server/service/connection-settings'; +import { createOrUpdateDeployment, getLatestDeployment } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { DeploymentPlatformEnum, DeploymentStatusEnum } from '~/types/deployment'; import type { VercelProjectInfo } from '~/types/vercel'; -import { errorResponse, successResponse } from '~/utils/api-response'; import { isBinaryString } from '~/utils/file-utils'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.vercel.deploy'); diff --git a/app/routes/api.vercel.$action/route.tsx b/app/routes/api.vercel.$action/route.tsx index c4c1c7b..884ce38 100644 --- a/app/routes/api.vercel.$action/route.tsx +++ b/app/routes/api.vercel.$action/route.tsx @@ -1,7 +1,7 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs } from '@remix-run/node'; -import { requireAuth } from '~/lib/.server/auth'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { errorResponse } from '~/utils/api-response'; +import { requireAuth } from '~/.server/service/auth'; +import { errorResponse } from '~/.server/utils/api-response'; +import { createScopedLogger } from '~/utils/logger'; import { handleVercelAuth } from './auth.server'; import { deletePage } from './delete.server'; import { getVercelDeployByProjectId, handleVercelDeploy } from './deploy.server'; diff --git a/app/routes/api.vercel.$action/stats.server.ts b/app/routes/api.vercel.$action/stats.server.ts index f90cd94..095a34f 100644 --- a/app/routes/api.vercel.$action/stats.server.ts +++ b/app/routes/api.vercel.$action/stats.server.ts @@ -1,5 +1,5 @@ -import { getVercelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getVercelConnectionSettings } from '~/.server/service/connection-settings'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.vercel.stats'); diff --git a/app/routes/api.vercel.$action/toggle-access.server.ts b/app/routes/api.vercel.$action/toggle-access.server.ts index b6bd82c..3ef4fee 100644 --- a/app/routes/api.vercel.$action/toggle-access.server.ts +++ b/app/routes/api.vercel.$action/toggle-access.server.ts @@ -1,7 +1,7 @@ -import { getVercelConnectionSettings } from '~/lib/.server/connectionSettings'; -import { getDeploymentById, updateDeploymentStatus } from '~/lib/.server/deployment'; -import { request } from '~/lib/fetch'; -import { errorResponse, successResponse } from '~/utils/api-response'; +import { getVercelConnectionSettings } from '~/.server/service/connection-settings'; +import { getDeploymentById, updateDeploymentStatus } from '~/.server/service/deployment'; +import { errorResponse, successResponse } from '~/.server/utils/api-response'; +import { request } from '~/.server/utils/fetch'; import { createScopedLogger } from '~/utils/logger'; import type { VercelAlias, VercelResponseAliases, VercelResponseError } from './type'; diff --git a/app/routes/assets.$userId.$filename.ts b/app/routes/assets.$userId.$filename.ts index 25b0b50..69ef10f 100644 --- a/app/routes/assets.$userId.$filename.ts +++ b/app/routes/assets.$userId.$filename.ts @@ -1,8 +1,8 @@ import { type LoaderFunctionArgs } from '@remix-run/node'; import fs from 'fs'; -import { getUser } from '~/lib/.server/auth'; -import { createScopedLogger } from '~/lib/.server/logger'; -import { storageProvider } from '~/lib/storage/index.server'; +import { getUser } from '~/.server/service/auth'; +import { storageProvider } from '~/.server/storage/index.server'; +import { createScopedLogger } from '~/utils/logger'; const logger = createScopedLogger('api.assets'); diff --git a/app/routes/chat.$id.tsx b/app/routes/chat.$id.tsx index fa5ab83..390c357 100644 --- a/app/routes/chat.$id.tsx +++ b/app/routes/chat.$id.tsx @@ -1,7 +1,7 @@ import { data, type LoaderFunctionArgs, redirect } from '@remix-run/node'; -import { getUser, requireAuth } from '~/lib/.server/auth'; -import { getUserChatById } from '~/lib/.server/chat'; -import { getChatDeployments } from '~/lib/.server/deployment'; +import { getUser, requireAuth } from '~/.server/service/auth'; +import { getUserChatById } from '~/.server/service/chat'; +import { getChatDeployments } from '~/.server/service/deployment'; import { default as IndexRoute } from './_index'; export async function loader(args: LoaderFunctionArgs) { diff --git a/app/lib/stores/logs.ts b/app/stores/logs.ts similarity index 100% rename from app/lib/stores/logs.ts rename to app/stores/logs.ts diff --git a/app/lib/stores/theme.ts b/app/stores/theme.ts similarity index 100% rename from app/lib/stores/theme.ts rename to app/stores/theme.ts diff --git a/app/types/model.ts b/app/types/model.ts index 8985393..42955ac 100644 --- a/app/types/model.ts +++ b/app/types/model.ts @@ -1,4 +1,4 @@ -import type { ModelInfo } from '~/lib/modules/llm/types'; +import type { ModelInfo } from '~/.server/modules/llm/types'; export type ProviderInfo = { staticModels: ModelInfo[]; diff --git a/app/types/pages.ts b/app/types/pages.ts new file mode 100644 index 0000000..077e645 --- /dev/null +++ b/app/types/pages.ts @@ -0,0 +1,9 @@ +import type { Page, Section } from '~/types/actions'; + +export type PageSection = Section & { + validRootDomId?: boolean; +}; + +export type PageMap = Record; + +export type SectionMap = Record; diff --git a/app/lib/crypto.ts b/app/utils/crypto.ts similarity index 100% rename from app/lib/crypto.ts rename to app/utils/crypto.ts diff --git a/app/utils/logger.ts b/app/utils/logger.ts index 049bbf8..e681867 100644 --- a/app/utils/logger.ts +++ b/app/utils/logger.ts @@ -15,9 +15,82 @@ interface Logger { setLevel: (level: DebugLevel) => void; } +const isServer = typeof window === 'undefined'; + let currentLevel: DebugLevel = (process.env.LOG_LEVEL as DebugLevel | undefined) || (import.meta.env.DEV ? 'debug' : 'info'); +let winstonLogger: any = null; +let winstonInitialized = false; + +async function initializeWinston() { + if (!isServer || winstonInitialized) { + return; + } + + winstonInitialized = true; + + try { + const fs = await import('fs'); + const path = await import('path'); + const winston = await import('winston'); + const { default: DailyRotateFile } = await import('winston-daily-rotate-file'); + + const enableFileLogging = process.env.USAGE_LOG_FILE !== 'false'; + + if (!enableFileLogging) { + return; + } + + const logDir = path.join(process.cwd(), 'logs'); + + try { + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir, { recursive: true }); + } + } catch (error) { + console.error('Failed to create logs directory:', error); + return; + } + + winstonLogger = winston.createLogger({ + level: currentLevel, + format: winston.format.combine( + winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), + winston.format.printf((info) => { + const { timestamp, level, message, scope } = info; + return `${timestamp} [${level.toUpperCase()}]${scope ? ` [${scope}]` : ''}: ${message}`; + }), + ), + transports: [ + // 按日期分割的错误日志文件 + new DailyRotateFile({ + filename: path.join(logDir, 'error-%DATE%.log'), + datePattern: 'YYYY-MM-DD', + level: 'error', + maxSize: '10m', // 10MB + maxFiles: 14, // 保留14天 + format: winston.format.combine(winston.format.timestamp(), winston.format.json()), + }) as any, + // 所有级别日志 + new DailyRotateFile({ + filename: path.join(logDir, 'combined-%DATE%.log'), + datePattern: 'YYYY-MM-DD', + maxSize: '20m', // 20MB + maxFiles: 7, // 保留7天 + format: winston.format.combine(winston.format.timestamp(), winston.format.json()), + }) as any, + ], + }); + } catch (error) { + console.error('Failed to initialize Winston logger:', error); + } +} + +if (isServer) { + initializeWinston(); +} + export const logger: Logger = { trace: (...messages: any[]) => log('trace', undefined, messages), debug: (...messages: any[]) => log('debug', undefined, messages), @@ -44,6 +117,11 @@ function setLevel(level: DebugLevel) { } currentLevel = level; + + // 更新 Winston logger 级别 + if (winstonLogger) { + winstonLogger.level = level; + } } function log(level: DebugLevel, scope: string | undefined, messages: any[]) { @@ -53,41 +131,68 @@ function log(level: DebugLevel, scope: string | undefined, messages: any[]) { return; } - const allMessages = messages.reduce((acc, current) => { - if (acc.endsWith('\n')) { - return acc + current; - } - - if (!acc) { - return current; - } - - return `${acc} ${current}`; - }, ''); - const labelBackgroundColor = getColorForLevel(level); const labelTextColor = level === 'warn' ? '#000000' : '#FFFFFF'; - const labelStyles = getLabelStyles(labelBackgroundColor, labelTextColor); - const scopeStyles = getLabelStyles('#77828D', 'white'); - - const styles = [labelStyles]; - - if (typeof scope === 'string') { - styles.push('', scopeStyles); - } - - let labelText = formatText(` ${level.toUpperCase()} `, labelTextColor, labelBackgroundColor); - - if (scope) { - labelText = `${labelText} ${formatText(` ${scope} `, '#FFFFFF', '77828D')}`; - } - - // 控制台日志 + // 控制台日志 - 根据环境使用不同格式 if (typeof window !== 'undefined') { - console.log(`%c${level.toUpperCase()}${scope ? `%c %c${scope}` : ''}`, ...styles, allMessages); + // 浏览器环境 - 保持对象原样,利用浏览器的原生格式化 + const labelStyles = getLabelStyles(labelBackgroundColor, labelTextColor); + const scopeStyles = getLabelStyles('#77828D', 'white'); + + const styles = [labelStyles]; + + if (typeof scope === 'string') { + styles.push('', scopeStyles); + } + + // 直接传递原始消息,浏览器会自动格式化对象 + console.log(`%c${level.toUpperCase()}${scope ? `%c %c${scope}` : ''}`, ...styles, ...messages); } else { + // Node.js 环境 - 将对象格式化为 JSON 字符串 + const formattedMessages = messages.map((msg) => { + if (typeof msg === 'object' && msg !== null) { + try { + return JSON.stringify(msg, null, 2); + } catch { + return String(msg); + } + } + return msg; + }); + + const allMessages = formattedMessages.reduce((acc, current) => { + if (acc.endsWith('\n')) { + return acc + current; + } + + if (!acc) { + return current; + } + + return `${acc} ${current}`; + }, ''); + + let labelText = formatText(` ${level.toUpperCase()} `, labelTextColor, labelBackgroundColor); + + if (scope) { + labelText = `${labelText} ${formatText(` ${scope} `, '#FFFFFF', '77828D')}`; + } + console.log(`${labelText}`, allMessages); + + // 写入文件日志(仅服务端) + if (winstonLogger) { + try { + winstonLogger.log({ + level, + message: allMessages, + scope, + }); + } catch (error) { + console.error('Failed to write to log file:', error); + } + } } } diff --git a/vite.config.mts b/vite.config.mts index db7a9c2..2a732de 100644 --- a/vite.config.mts +++ b/vite.config.mts @@ -43,6 +43,7 @@ export default defineConfig((config) => { UnoCSS(), tsconfigPaths(), chrome129IssuePlugin(), + excludeUploadsPlugin(), ], css: { preprocessorOptions: { @@ -77,3 +78,25 @@ function chrome129IssuePlugin() { }, }; } + +function excludeUploadsPlugin() { + return { + name: 'exclude-uploads', + apply: 'build' as const, + enforce: 'post' as const, + async closeBundle() { + const fs = await import('fs'); + const path = await import('path'); + const uploadsPath = path.resolve(process.cwd(), 'build/client/uploads'); + + if (fs.existsSync(uploadsPath)) { + try { + fs.rmSync(uploadsPath, { recursive: true, force: true }); + console.log('✓ 已从构建产物中排除 uploads 目录'); + } catch (error) { + console.warn('⚠ 删除 uploads 目录时出错:', error); + } + } + }, + }; +}