chore(eslint): enforce consistent import paths (#8)

This commit is contained in:
Dominic Elm 2024-07-24 17:43:32 +02:00 committed by GitHub
parent d45b95dd11
commit 2a3d5f569e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 102 additions and 85 deletions

View File

@ -1,9 +1,10 @@
import blitzPlugin from '@blitz/eslint-plugin';
import { getNamingConventionRule } from '@blitz/eslint-plugin/dist/configs/typescript.js';
import { jsFileExtensions } from '@blitz/eslint-plugin/dist/configs/javascript.js';
import { getNamingConventionRule, tsFileExtensions } from '@blitz/eslint-plugin/dist/configs/typescript.js';
export default [
{
ignores: ['**/dist', '**/node_modules'],
ignores: ['**/dist', '**/node_modules', '**/.wrangler', '**/bolt/build'],
},
...blitzPlugin.configs.recommended(),
{
@ -25,4 +26,20 @@ export default [
'@typescript-eslint/no-empty-object-type': 'off',
},
},
{
files: [...tsFileExtensions, ...jsFileExtensions, '**/*.tsx'],
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['../'],
message: `Relative imports are not allowed. Please use '~/' instead.`,
},
],
},
],
},
},
];

View File

@ -3,11 +3,11 @@ import { AnimatePresence, motion } from 'framer-motion';
import { computed } from 'nanostores';
import { memo, useEffect, useRef, useState } from 'react';
import { createHighlighter, type BundledLanguage, type BundledTheme, type HighlighterGeneric } from 'shiki';
import type { ActionState } from '../../lib/runtime/action-runner';
import { chatStore } from '../../lib/stores/chat';
import { workbenchStore } from '../../lib/stores/workbench';
import { classNames } from '../../utils/classNames';
import { cubicEasingFn } from '../../utils/easings';
import type { ActionState } from '~/lib/runtime/action-runner';
import { chatStore } from '~/lib/stores/chat';
import { workbenchStore } from '~/lib/stores/workbench';
import { classNames } from '~/utils/classNames';
import { cubicEasingFn } from '~/utils/easings';
const highlighterOptions = {
langs: ['shell'],

View File

@ -1,9 +1,9 @@
import type { Message } from 'ai';
import React, { type LegacyRef, type RefCallback } from 'react';
import { ClientOnly } from 'remix-utils/client-only';
import { classNames } from '../../utils/classNames';
import { IconButton } from '../ui/IconButton';
import { Workbench } from '../workbench/Workbench.client';
import { IconButton } from '~/components/ui/IconButton';
import { Workbench } from '~/components/workbench/Workbench.client';
import { classNames } from '~/utils/classNames';
import { Messages } from './Messages.client';
import { SendButton } from './SendButton.client';

View File

@ -2,11 +2,11 @@ import { useChat } from 'ai/react';
import { useAnimate } from 'framer-motion';
import { useEffect, useRef, useState } from 'react';
import { ToastContainer, cssTransition } from 'react-toastify';
import { useMessageParser, usePromptEnhancer, useSnapScroll } from '../../lib/hooks';
import { chatStore } from '../../lib/stores/chat';
import { workbenchStore } from '../../lib/stores/workbench';
import { cubicEasingFn } from '../../utils/easings';
import { createScopedLogger } from '../../utils/logger';
import { useMessageParser, usePromptEnhancer, useSnapScroll } from '~/lib/hooks';
import { chatStore } from '~/lib/stores/chat';
import { workbenchStore } from '~/lib/stores/workbench';
import { cubicEasingFn } from '~/utils/easings';
import { createScopedLogger } from '~/utils/logger';
import { BaseChat } from './BaseChat';
const toastAnimation = cssTransition({

View File

@ -1,7 +1,7 @@
import { memo, useEffect, useState } from 'react';
import { bundledLanguages, codeToHtml, isSpecialLang, type BundledLanguage, type SpecialLanguage } from 'shiki';
import { classNames } from '../../utils/classNames';
import { createScopedLogger } from '../../utils/logger';
import { classNames } from '~/utils/classNames';
import { createScopedLogger } from '~/utils/logger';
import styles from './CodeBlock.module.scss';
const logger = createScopedLogger('CodeBlock');

View File

@ -1,8 +1,8 @@
import { memo, useMemo } from 'react';
import ReactMarkdown, { type Components } from 'react-markdown';
import type { BundledLanguage } from 'shiki';
import { createScopedLogger } from '../../utils/logger';
import { rehypePlugins, remarkPlugins } from '../../utils/markdown';
import { createScopedLogger } from '~/utils/logger';
import { rehypePlugins, remarkPlugins } from '~/utils/markdown';
import { Artifact } from './Artifact';
import { CodeBlock } from './CodeBlock';

View File

@ -1,8 +1,8 @@
import type { Message } from 'ai';
import { classNames } from '../../utils/classNames';
import React from 'react';
import { classNames } from '~/utils/classNames';
import { AssistantMessage } from './AssistantMessage';
import { UserMessage } from './UserMessage';
import React from 'react';
interface MessagesProps {
id?: string;

View File

@ -14,10 +14,10 @@ import {
scrollPastEnd,
} from '@codemirror/view';
import { memo, useEffect, useRef, useState, type MutableRefObject } from 'react';
import type { Theme } from '../../../types/theme';
import { classNames } from '../../../utils/classNames';
import { debounce } from '../../../utils/debounce';
import { createScopedLogger, renderLogger } from '../../../utils/logger';
import type { Theme } from '~/types/theme';
import { classNames } from '~/utils/classNames';
import { debounce } from '~/utils/debounce';
import { createScopedLogger, renderLogger } from '~/utils/logger';
import { BinaryContent } from './BinaryContent';
import { getTheme, reconfigureTheme } from './cm-theme';
import { indentKeyBinding } from './indent';

View File

@ -1,7 +1,7 @@
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
import { Compartment, type Extension } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import type { Theme } from '../../../types/theme.js';
import type { Theme } from '~/types/theme.js';
import type { EditorSettings } from './CodeMirrorEditor.js';
import { vscodeDarkTheme } from './themes/vscode-dark.js';

View File

@ -1,5 +1,5 @@
import { memo } from 'react';
import { classNames } from '../../utils/classNames';
import { classNames } from '~/utils/classNames';
type IconSize = 'sm' | 'md' | 'xl' | 'xxl';

View File

@ -1,5 +1,5 @@
import { memo } from 'react';
import { classNames } from '../../utils/classNames';
import { classNames } from '~/utils/classNames';
interface PanelHeaderButtonProps {
className?: string;

View File

@ -1,10 +1,6 @@
import { useStore } from '@nanostores/react';
import { memo, useMemo } from 'react';
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import type { FileMap } from '../../lib/stores/files';
import { themeStore } from '../../lib/stores/theme';
import { renderLogger } from '../../utils/logger';
import { isMobile } from '../../utils/mobile';
import {
CodeMirrorEditor,
type EditorDocument,
@ -12,8 +8,12 @@ import {
type OnChangeCallback as OnEditorChange,
type OnSaveCallback as OnEditorSave,
type OnScrollCallback as OnEditorScroll,
} from '../editor/codemirror/CodeMirrorEditor';
import { PanelHeaderButton } from '../ui/PanelHeaderButton';
} from '~/components/editor/codemirror/CodeMirrorEditor';
import { PanelHeaderButton } from '~/components/ui/PanelHeaderButton';
import type { FileMap } from '~/lib/stores/files';
import { themeStore } from '~/lib/stores/theme';
import { renderLogger } from '~/utils/logger';
import { isMobile } from '~/utils/mobile';
import { FileTreePanel } from './FileTreePanel';
interface EditorPanelProps {

View File

@ -1,7 +1,7 @@
import { memo, useEffect, useMemo, useState, type ReactNode } from 'react';
import type { FileMap } from '../../lib/stores/files';
import { classNames } from '../../utils/classNames';
import { renderLogger } from '../../utils/logger';
import type { FileMap } from '~/lib/stores/files';
import { classNames } from '~/utils/classNames';
import { renderLogger } from '~/utils/logger';
const NODE_PADDING_LEFT = 12;
const DEFAULT_HIDDEN_FILES = [/\/node_modules\//];

View File

@ -1,7 +1,7 @@
import { memo } from 'react';
import type { FileMap } from '../../lib/stores/files';
import { WORK_DIR } from '../../utils/constants';
import { renderLogger } from '../../utils/logger';
import type { FileMap } from '~/lib/stores/files';
import { WORK_DIR } from '~/utils/constants';
import { renderLogger } from '~/utils/logger';
import { FileTree } from './FileTree';
interface FileTreePanelProps {

View File

@ -1,7 +1,7 @@
import { useStore } from '@nanostores/react';
import { memo, useEffect, useRef, useState } from 'react';
import { workbenchStore } from '../../lib/stores/workbench';
import { IconButton } from '../ui/IconButton';
import { IconButton } from '~/components/ui/IconButton';
import { workbenchStore } from '~/lib/stores/workbench';
export const Preview = memo(() => {
const iframeRef = useRef<HTMLIFrameElement>(null);

View File

@ -3,14 +3,14 @@ import { AnimatePresence, motion, type Variants } from 'framer-motion';
import { memo, useCallback, useEffect } from 'react';
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import { toast } from 'react-toastify';
import { workbenchStore } from '../../lib/stores/workbench';
import { cubicEasingFn } from '../../utils/easings';
import { renderLogger } from '../../utils/logger';
import {
type OnChangeCallback as OnEditorChange,
type OnScrollCallback as OnEditorScroll,
} from '../editor/codemirror/CodeMirrorEditor';
import { IconButton } from '../ui/IconButton';
} from '~/components/editor/codemirror/CodeMirrorEditor';
import { IconButton } from '~/components/ui/IconButton';
import { workbenchStore } from '~/lib/stores/workbench';
import { cubicEasingFn } from '~/utils/easings';
import { renderLogger } from '~/utils/logger';
import { EditorPanel } from './EditorPanel';
import { Preview } from './Preview';

View File

@ -1,5 +1,5 @@
import { WORK_DIR } from '../../../utils/constants';
import { stripIndents } from '../../../utils/stripIndent';
import { WORK_DIR } from '~/utils/constants';
import { stripIndents } from '~/utils/stripIndent';
export const getSystemPrompt = (cwd: string = WORK_DIR) => `
You are Bolt, an expert AI assistant and exceptional senior software developer with vast knowledge across multiple programming languages, frameworks, and best practices.

View File

@ -1,6 +1,6 @@
import { streamText as _streamText, convertToCoreMessages } from 'ai';
import { getAPIKey } from '../llm/api-key';
import { getAnthropicModel } from '../llm/model';
import { getAPIKey } from '~/lib/.server/llm/api-key';
import { getAnthropicModel } from '~/lib/.server/llm/model';
import { MAX_TOKENS } from './constants';
import { getSystemPrompt } from './prompts';

View File

@ -1,8 +1,8 @@
import type { Message } from 'ai';
import { useCallback, useState } from 'react';
import { createScopedLogger } from '../../utils/logger';
import { StreamingMessageParser } from '../runtime/message-parser';
import { workbenchStore } from '../stores/workbench';
import { StreamingMessageParser } from '~/lib/runtime/message-parser';
import { workbenchStore } from '~/lib/stores/workbench';
import { createScopedLogger } from '~/utils/logger';
const logger = createScopedLogger('useMessageParser');

View File

@ -1,5 +1,5 @@
import { useState } from 'react';
import { createScopedLogger } from '../../utils/logger';
import { createScopedLogger } from '~/utils/logger';
const logger = createScopedLogger('usePromptEnhancement');

View File

@ -1,9 +1,9 @@
import { WebContainer } from '@webcontainer/api';
import { map, type MapStore } from 'nanostores';
import * as nodePath from 'node:path';
import type { BoltAction } from '../../types/actions';
import { createScopedLogger } from '../../utils/logger';
import { unreachable } from '../../utils/unreachable';
import type { BoltAction } from '~/types/actions';
import { createScopedLogger } from '~/utils/logger';
import { unreachable } from '~/utils/unreachable';
import type { ActionCallbackData } from './message-parser';
const logger = createScopedLogger('ActionRunner');

View File

@ -1,7 +1,7 @@
import type { ActionType, BoltAction, BoltActionData, FileAction, ShellAction } from '../../types/actions';
import type { BoltArtifactData } from '../../types/artifact';
import { createScopedLogger } from '../../utils/logger';
import { unreachable } from '../../utils/unreachable';
import type { ActionType, BoltAction, BoltActionData, FileAction, ShellAction } from '~/types/actions';
import type { BoltArtifactData } from '~/types/artifact';
import { createScopedLogger } from '~/utils/logger';
import { unreachable } from '~/utils/unreachable';
const ARTIFACT_TAG_OPEN = '<boltArtifact';
const ARTIFACT_TAG_CLOSE = '</boltArtifact>';

View File

@ -1,5 +1,5 @@
import { atom, computed, map, type MapStore, type WritableAtom } from 'nanostores';
import type { EditorDocument, ScrollPosition } from '../../components/editor/codemirror/CodeMirrorEditor';
import type { EditorDocument, ScrollPosition } from '~/components/editor/codemirror/CodeMirrorEditor';
import type { FileMap, FilesStore } from './files';
export type EditorDocuments = Record<string, EditorDocument>;

View File

@ -1,9 +1,9 @@
import type { PathWatcherEvent, WebContainer } from '@webcontainer/api';
import { map, type MapStore } from 'nanostores';
import * as nodePath from 'node:path';
import { bufferWatchEvents } from '../../utils/buffer';
import { WORK_DIR } from '../../utils/constants';
import { createScopedLogger } from '../../utils/logger';
import { bufferWatchEvents } from '~/utils/buffer';
import { WORK_DIR } from '~/utils/constants';
import { createScopedLogger } from '~/utils/logger';
const logger = createScopedLogger('FilesStore');

View File

@ -1,9 +1,9 @@
import { atom, map, type MapStore, type ReadableAtom, type WritableAtom } from 'nanostores';
import type { EditorDocument, ScrollPosition } from '../../components/editor/codemirror/CodeMirrorEditor';
import { unreachable } from '../../utils/unreachable';
import { ActionRunner } from '../runtime/action-runner';
import type { ActionCallbackData, ArtifactCallbackData } from '../runtime/message-parser';
import { webcontainer } from '../webcontainer';
import type { EditorDocument, ScrollPosition } from '~/components/editor/codemirror/CodeMirrorEditor';
import { ActionRunner } from '~/lib/runtime/action-runner';
import type { ActionCallbackData, ArtifactCallbackData } from '~/lib/runtime/message-parser';
import { webcontainer } from '~/lib/webcontainer';
import { unreachable } from '~/utils/unreachable';
import { EditorStore } from './editor';
import { FilesStore, type FileMap } from './files';
import { PreviewsStore } from './previews';

View File

@ -1,5 +1,5 @@
import { WebContainer } from '@webcontainer/api';
import { WORK_DIR_NAME } from '../../utils/constants';
import { WORK_DIR_NAME } from '~/utils/constants';
interface WebContainerContext {
loaded: boolean;

View File

@ -1,9 +1,9 @@
import { json, redirect, type LoaderFunctionArgs, type MetaFunction } from '@remix-run/cloudflare';
import { ClientOnly } from 'remix-utils/client-only';
import { BaseChat } from '../components/chat/BaseChat';
import { Chat } from '../components/chat/Chat.client';
import { Header } from '../components/Header';
import { isAuthenticated } from '../lib/.server/sessions';
import { BaseChat } from '~/components/chat/BaseChat';
import { Chat } from '~/components/chat/Chat.client';
import { Header } from '~/components/Header';
import { isAuthenticated } from '~/lib/.server/sessions';
export const meta: MetaFunction = () => {
return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }];

View File

@ -1,9 +1,9 @@
import { type ActionFunctionArgs } from '@remix-run/cloudflare';
import { StreamingTextResponse } from 'ai';
import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '../lib/.server/llm/constants';
import { CONTINUE_PROMPT } from '../lib/.server/llm/prompts';
import { streamText, type Messages, type StreamingOptions } from '../lib/.server/llm/stream-text';
import SwitchableStream from '../lib/.server/llm/switchable-stream';
import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants';
import { CONTINUE_PROMPT } from '~/lib/.server/llm/prompts';
import { streamText, type Messages, type StreamingOptions } from '~/lib/.server/llm/stream-text';
import SwitchableStream from '~/lib/.server/llm/switchable-stream';
export async function action({ context, request }: ActionFunctionArgs) {
const { messages } = await request.json<{ messages: Messages }>();

View File

@ -1,7 +1,7 @@
import { type ActionFunctionArgs } from '@remix-run/cloudflare';
import { StreamingTextResponse, parseStreamPart } from 'ai';
import { streamText } from '../lib/.server/llm/stream-text';
import { stripIndents } from '../utils/stripIndent';
import { streamText } from '~/lib/.server/llm/stream-text';
import { stripIndents } from '~/utils/stripIndent';
const encoder = new TextEncoder();
const decoder = new TextDecoder();

View File

@ -6,8 +6,8 @@ import {
type TypedResponse,
} from '@remix-run/cloudflare';
import { Form, useActionData } from '@remix-run/react';
import { verifyPassword } from '../lib/.server/login';
import { createUserSession, isAuthenticated } from '../lib/.server/sessions';
import { verifyPassword } from '~/lib/.server/login';
import { createUserSession, isAuthenticated } from '~/lib/.server/sessions';
interface Errors {
password?: string;

View File

@ -2,7 +2,7 @@ import type { ServerBuild } from '@remix-run/cloudflare';
import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages';
// @ts-ignore because the server build file is generated by `remix vite:build`
import * as serverBuild from '../build/server';
import * as serverBuild from '~/build/server';
export const onRequest = createPagesFunctionHandler({
build: serverBuild as unknown as ServerBuild,