### Install Dependencies and Setup Linters Source: https://github.com/factory-ai/eslint-plugin/blob/main/examples/typescript-project/README.md Run these commands to install project dependencies and set up the Factory linters. ```bash npm install npx factory-linters-setup ``` -------------------------------- ### Install @factory/eslint-plugin and ESLint Source: https://github.com/factory-ai/eslint-plugin/blob/main/README.md Install the @factory/eslint-plugin and ESLint as development dependencies. ```bash npm install @factory/eslint-plugin eslint --save-dev ``` -------------------------------- ### Correct File Structure Example Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-tsx-test-stories-files/README.md Demonstrates a file structure that adheres to the rule, showing TSX components with their required test and Storybook files, as well as examples of exempt files. ```text src/ components/ Button.tsx Button.test.tsx Button.stories.tsx Card.tsx Card.test.tsx Card.stories.tsx index.tsx # Exempt - barrel file app/ page.tsx # Exempt - Next.js page layout.tsx # Exempt - Next.js layout ``` -------------------------------- ### Correct Test File Content Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/test-file-location/README.md Provides an example of a valid test file containing the necessary `describe` and `it` blocks. ```typescript // format.test.ts describe('format', () => { it('should format dates correctly', () => { expect(formatDate(new Date())).toBe('2024-01-01'); }); }); ``` -------------------------------- ### Correct Component Declarations Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/restrict-tsx-components/README.md These examples demonstrate correct component declarations within files that adhere to the specified naming conventions for different component types. ```tsx // pages/Dashboard.page.tsx export const DashboardPage = () => { return
Dashboard
; }; // components/Sidebar.module.tsx export function SidebarModule() { return ; } // layouts/App.layout.tsx export const AppLayout = ({ children }) => { return
{children}
; }; // providers/Theme.provider.tsx export const ThemeProvider = ({ children }) => { return {children}; }; ``` -------------------------------- ### Correct: Types File Organization Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/types-file-organization/README.md This example demonstrates the correct placement of types and interfaces within a `types.ts` file, adhering to import restrictions. ```typescript // src/types.ts import { Status } from './enums'; import type { BaseSchema } from './schema'; export interface User { id: string; name: string; status: Status; } export type UserId = string; export type Config = { schema: BaseSchema; enabled: boolean; }; ``` -------------------------------- ### Configuring Ignored Files Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/filename-match-export/README.md This example shows how to configure the rule to ignore specific filenames, such as utility or constant files, which may contain multiple exports. ```javascript { "rules": { "@factory/filename-match-export": ["error", { "ignoredFiles": ["utils.ts", "constants.ts", "types.ts"] }] } } ``` -------------------------------- ### Incorrect File Structure Example Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-tsx-test-stories-files/README.md Illustrates a file structure where TSX components are missing their corresponding test and Storybook files, violating the rule. ```text src/ components/ Button.tsx # Missing Button.test.tsx and Button.stories.tsx Card.tsx # Missing Card.test.tsx and Card.stories.tsx ``` -------------------------------- ### Correct Route Handler - Admin Middleware Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-route-middleware/README.md This example demonstrates a route handler using `handleAdminRouteMiddleware` as the first statement, ensuring administrative-specific middleware runs before the main logic. ```typescript export async function POST(request: Request) { return handleAdminRouteMiddleware(request, async (user) => { const body = await request.json(); return NextResponse.json({ success: true }); }); } ``` -------------------------------- ### Correct v0 Route Handler - Using handleV0RouteMiddleware Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-v0-route-handle-middleware/README.md This example demonstrates the correct implementation where the route handler in an API v0 route properly calls `handleV0RouteMiddleware`. This ensures consistent API behavior. ```typescript export const { GET } = route({ listUsers: routeOperation({ method: 'GET' }) .outputs([]) .handler(async (req) => handleV0RouteMiddleware(req, async (user) => { const users = await getUsers(); return NextResponse.json(users); }) ), }); ``` -------------------------------- ### Correct Filename/Export Matches Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/filename-match-export/README.md These examples demonstrate correct usage where filenames align with their exported React components or functions, including those with special suffixes. ```typescript // Button.tsx export const Button = () => ; ``` ```typescript // Sessions.page.tsx export const SessionsPage = () =>
Sessions
; ``` ```typescript // UserProfile.page.tsx export const UserProfilePage = () =>
Profile
; ``` ```typescript // Theme.provider.tsx export const ThemeProvider = ({ children }) => ( {children} ); ``` -------------------------------- ### Incorrect Test File Content Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/test-file-location/README.md Shows an example of an invalid test file that lacks the required `describe`, `it`, or `test` blocks. ```typescript // format.test.ts - empty test file // No describe/it/test blocks export {}; ``` -------------------------------- ### Incorrect Component Declarations Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/restrict-tsx-components/README.md These examples show component declarations in files that do not follow the required naming conventions (.page.tsx, .module.tsx, .layout.tsx, .view.tsx, .provider.tsx). ```tsx // components/Dashboard.tsx - should be Dashboard.page.tsx or Dashboard.module.tsx export const Dashboard = () => { return
Dashboard
; }; // components/Sidebar.tsx - should be Sidebar.module.tsx or Sidebar.layout.tsx export function Sidebar() { return ; } ``` -------------------------------- ### Correct: Test utilities in `test-utils` directory Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/test-utils-organization/README.md This example demonstrates the correct organization of test utilities within a `test-utils` directory, including shared mocks, fixtures, and helpers. ```typescript // src/test-utils/mocks.ts export function mockFetchData() { return { data: 'test' }; } export const createMockUser = (overrides = {}) => ({ id: '1', name: 'Test User', ...overrides, }); ``` -------------------------------- ### Correct Route Handler - Middleware as First Statement Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-route-middleware/README.md This example shows a correctly implemented route handler where `handleRouteMiddleware` is called as the first statement, ensuring middleware execution before route logic. ```typescript // route.ts export async function GET(request: Request) { return handleRouteMiddleware(request, async () => { const data = await fetchData(); return NextResponse.json(data); }); } ``` -------------------------------- ### Incorrect Filename/Export Mismatches Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/filename-match-export/README.md These examples show common violations where the component name does not match the filename or the expected suffix for special file types. ```typescript // Button.tsx - component name doesn't match filename export const PrimaryButton = () => ; ``` ```typescript // Sessions.page.tsx - should export SessionsPage, not Sessions export const Sessions = () =>
Sessions
; ``` ```typescript // UserProfile.tsx - should be in UserProfile.page.tsx if it's a page export const UserProfilePage = () =>
Profile
; ``` -------------------------------- ### Incorrect jest.mock() calls Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/jest-mock-require-actual/README.md These examples show incorrect usage of jest.mock() where the second argument is missing or does not preserve actual exports. ```ts jest.mock('@/utils/api'); ``` ```ts jest.mock('@/utils/api', () => ({ fetchData: jest.fn() })); ``` ```ts jest.mock('@/utils/api', () => ({ ...jest.requireActual('@/utils/api') })); ``` -------------------------------- ### Correct: Constants in constants.ts Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/constants-file-organization/README.md This example shows the correct way to define exported constants in a `constants.ts` file, including imports from other internal modules. ```typescript // src/constants.ts import { Environment } from './enums'; export const API_URL = 'https://api.example.com'; export const MAX_RETRIES = 3; export const TIMEOUT_MS = 5000; export const CONFIG = { environment: Environment.Production, debug: false, }; ``` -------------------------------- ### Correct File Structure Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-test-files/README.md Shows a file structure that adheres to the rule, with each TypeScript file having a corresponding test file, and also includes examples of exempt files. ```plaintext src/ utils/ format.ts format.test.ts validate.ts validate.test.ts types.ts # Exempt - type definitions constants.ts # Exempt - constants ``` -------------------------------- ### Correct jest.mock() calls with jest.requireActual() Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/jest-mock-require-actual/README.md These examples demonstrate correct usage of jest.mock() by including jest.requireActual() to preserve existing exports while mocking specific functions. ```ts jest.mock('@/utils/api', () => ({ ...jest.requireActual('@/utils/api'), fetchData: jest.fn() })); ``` ```ts jest.mock('@/services/auth', () => ({ ...jest.requireActual('@/services/auth'), login: jest.fn().mockResolvedValue({ token: 'test' }), logout: jest.fn() })); ``` -------------------------------- ### Incorrect: Mock functions in source files Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/test-utils-organization/README.md This example shows mock functions placed incorrectly within source files, which this rule aims to prevent. ```typescript // src/utils/api.ts - mock functions don't belong in source files export function mockFetchData() { return { data: 'test' }; } export const createMockUser = () => ({ id: '1', name: 'Test' }); ``` -------------------------------- ### Correct Zod Schema with .strict() Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-v0-strict-schemas/README.md This example demonstrates the correct way to define Zod schemas using .strict() to reject unknown properties. It also shows how to apply .strict() to extended schemas. ```typescript // api/v0/users/schemas/create-user.ts import { z } from 'zod'; export const CreateUserSchema = z .object({ name: z.string(), email: z.string().email(), }) .strict(); // Extended schemas also need .strict() export const UpdateUserSchema = CreateUserSchema.extend({ id: z.string(), }).strict(); ``` -------------------------------- ### Incorrect v0 Route Handler - Missing handleV0RouteMiddleware Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-v0-route-handle-middleware/README.md This example shows an incorrect implementation where the route handler in an API v0 route does not call `handleV0RouteMiddleware`. This violates the rule and should be corrected. ```typescript export const { GET } = route({ listUsers: routeOperation({ method: 'GET' }) .outputs([]) .handler(async (req) => { const users = await getUsers(); return NextResponse.json(users); }), }); ``` -------------------------------- ### Incorrect Route Handler - Missing Middleware Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-route-middleware/README.md This example shows a route handler where the middleware call is completely omitted, leaving the route unprotected. ```typescript // route.ts - missing middleware call export async function GET(request: Request) { const data = await fetchData(); return NextResponse.json(data); } ``` -------------------------------- ### Incorrect Enum Placement Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/enum-file-organization/README.md Enums should not be placed in utility files. This example shows an enum defined in `src/utils.ts`, which violates the rule. ```typescript // src/utils.ts - enums should not be in utility files export enum Status { Active = 'ACTIVE', Inactive = 'INACTIVE', } ``` -------------------------------- ### Incorrect Route Handler - Middleware Not First Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-route-middleware/README.md This example demonstrates a route handler where middleware is called, but not as the very first statement, potentially allowing logic to execute before security checks. ```typescript // route.ts - middleware not first statement export async function POST(request: Request) { const body = await request.json(); return handleRouteMiddleware(request, async () => { // ... }); } ``` -------------------------------- ### Correct: Error classes in errors.ts Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/errors-file-organization/README.md This example demonstrates the correct placement and structure for custom Error classes within an `errors.ts` file, including necessary imports. ```typescript // src/errors.ts import { ErrorCode } from './enums'; import type { ErrorDetails } from './types'; export class ValidationError extends Error { constructor(message: string) { super(message); this.name = 'ValidationError'; } } export class ApiError extends Error { code: ErrorCode; constructor(message: string, code: ErrorCode) { super(message); this.name = 'ApiError'; this.code = code; } } ``` -------------------------------- ### Configure Ignored Files for Filename Match Rule Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Example of how to configure the 'ignoredFiles' option for the '@factory/filename-match-export' ESLint rule in an '.eslintrc.js' file. This allows specific files like utility or constant files to be excluded from the naming convention check. ```javascript // .eslintrc.js — override ignored files "@factory/filename-match-export": ["error", { "ignoredFiles": ["utils.ts", "constants.ts", "types.ts", "helpers.ts"] }] ``` -------------------------------- ### Incorrect Import in enums.ts Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/enum-file-organization/README.md Files named `enums.ts` are not allowed to contain import statements. This example demonstrates an enum in `src/enums.ts` with an import, which is disallowed. ```typescript // src/enums.ts - enums.ts files cannot have imports import { something } from './other'; export enum Direction { Up = 'UP', Down = 'DOWN', } ``` -------------------------------- ### Correct Enum Declaration in enums.ts Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/enum-file-organization/README.md This example shows the correct way to define multiple enums and type exports within an `enums.ts` file. It adheres to the rule by having no imports and only enum/type declarations. ```typescript // src/enums.ts export enum Status { Active = 'ACTIVE', Inactive = 'INACTIVE', } export enum Direction { Up = 'UP', Down = 'DOWN', } // Type exports are allowed export type StatusType = keyof typeof Status; ``` -------------------------------- ### Incorrect Zod Schema without .strict() Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-v0-strict-schemas/README.md This example shows an incorrect Zod schema definition where unknown properties in request payloads would be silently accepted. Ensure .strict() is used for API safety. ```typescript // api/v0/users/schemas/create-user.ts import { z } from 'zod'; export const CreateUserSchema = z.object({ name: z.string(), email: z.string().email(), }); // Unknown properties like { name: "John", emial: "typo@test.com" } // would be silently accepted ``` -------------------------------- ### Disallow useEffect in Custom Hooks Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-use-effect-in-hooks/README.md Custom hooks should not contain side effects like those managed by useEffect. This example shows an incorrect usage within a custom hook. ```tsx function useUserData(userId: string) { const [user, setUser] = useState(null); useEffect(() => { fetchUser(userId).then(setUser); }, [userId]); return user; } ``` ```tsx const useWindowSize = () => { const [size, setSize] = useState({ width: 0, height: 0 }); useLayoutEffect(() => { const handleResize = () => { setSize({ width: window.innerWidth, height: window.innerHeight }); }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return size; }; ``` -------------------------------- ### Require Middleware in Next.js Route Handlers Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Ensures that exported HTTP method handlers (GET, POST, etc.) in route.ts files invoke a recognized handle*Middleware function as their first statement. Excludes v0 routes. ```typescript // ❌ — missing middleware export async function GET(request: Request) { const data = await fetchData(); return NextResponse.json(data); } // ✅ export async function GET(request: Request) { return handleRouteMiddleware(request, async () => { const data = await fetchData(); return NextResponse.json(data); }); } export async function POST(request: Request) { return handleAdminRouteMiddleware(request, async (user) => { const body = await request.json(); await createRecord({ ...body, createdBy: user.id }); return NextResponse.json({ success: true }); }); } ``` -------------------------------- ### Rule Configuration with Allowlist Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/restrict-tsx-components/README.md This configuration shows how to set up the rule and specify an allowlist of component names that are permitted in any file, overriding the strict naming convention for specific components. ```js { "rules": { "@factory/restrict-tsx-components": ["error", { "allowlist": ["Button", "Icon", "Avatar"] }] } } ``` -------------------------------- ### Run ESLint Source: https://github.com/factory-ai/eslint-plugin/blob/main/examples/typescript-project/README.md Execute this command to run ESLint for code linting. ```bash npm run lint ``` -------------------------------- ### Correct Test File Structure Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/test-file-location/README.md Demonstrates the correct structure where test files are colocated with their source files. ```text src/ utils/ format.ts format.test.ts # Colocated with source file components/ Button.tsx Button.test.tsx # Colocated with source file ``` -------------------------------- ### Configure @factory/frontend ESLint for React/Vite Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Extend the recommended configuration with React-specific rules for JSX, React Compiler integration, and TanStack Router. ```javascript module.exports = { root: true, plugins: ['@factory'], extends: ['plugin:@factory/frontend'], rules: { // Allow component allowlist for shared UI primitives '@factory/restrict-tsx-components': ['error', { allowlist: ['Button', 'Icon', 'Avatar', 'Spinner'], }], '@factory/filename-match-export': ['error', { ignoredFiles: ['utils.ts', 'constants.ts', 'types.ts'], }], }, }; ``` -------------------------------- ### Correct: Log and handle locally Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-log-exception-with-throw/README.md When an error occurs, log it and then handle it locally by returning a result or performing a fallback action, instead of throwing. ```ts function processData(data) { try { validate(data); } catch (error) { logException(error, 'Validation failed'); return { success: false, error: 'Invalid data' }; } } ``` -------------------------------- ### Incorrect Test File Structure Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/test-file-location/README.md Illustrates incorrect placement of test files in separate `__tests__` or `test/` directories instead of colocating them with source files. ```text src/ utils/ format.ts __tests__/ # Tests should not be in __tests__ format.test.ts test/ # Tests should not be in test/ utils/ format.test.ts ``` -------------------------------- ### Configure @factory/base ESLint Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Extend the base configuration for core TypeScript/JavaScript rules, including Airbnb base and Jest recommended. ```javascript module.exports = { root: true, plugins: ['@factory'], extends: ['plugin:@factory/base'], }; ``` -------------------------------- ### ESLint Configuration for Frontend Applications Source: https://github.com/factory-ai/eslint-plugin/blob/main/README.md Configure ESLint for React/Vite frontend applications using the plugin's frontend configuration. ```javascript module.exports = { root: true, plugins: ['@factory'], extends: ['plugin:@factory/frontend'], }; ``` -------------------------------- ### Correct Usage: Effects in Components, Not Custom Hooks Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-use-effect-in-hooks/README.md This demonstrates correct patterns where effects are managed in components, or custom hooks manage derived state without side effects. ```tsx function useUserQuery(userId: string) { return useQuery(['user', userId], () => fetchUser(userId)); } ``` ```tsx function UserProfile({ userId }) { const [user, setUser] = useState(null); useEffect(() => { fetchUser(userId).then(setUser); }, [userId]); return
{user?.name}
; } ``` ```tsx function useFormattedDate(date: Date) { return useMemo(() => formatDate(date), [date]); } ``` -------------------------------- ### ESLint Configuration for Backend Applications Source: https://github.com/factory-ai/eslint-plugin/blob/main/README.md Configure ESLint for backend applications using the plugin's backend configuration. ```javascript module.exports = { root: true, plugins: ['@factory'], extends: ['plugin:@factory/backend'], }; ``` -------------------------------- ### ESLint Configuration for TypeScript Packages Source: https://github.com/factory-ai/eslint-plugin/blob/main/README.md Configure ESLint for TypeScript packages and libraries using the plugin's recommended configuration. ```javascript module.exports = { root: true, plugins: ['@factory'], extends: ['plugin:@factory/recommended'], }; ``` -------------------------------- ### Incorrect: Logging then throwing Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-log-exception-with-throw/README.md Avoid logging an exception and then throwing a new error in the same block, as this causes duplicate error reporting. ```ts function processData(data) { try { validate(data); } catch (error) { logException(error, 'Validation failed'); throw new Error('Invalid data'); } } ``` ```ts if (condition) { logError('Something went wrong'); throw new Error('Failed'); } ``` -------------------------------- ### Correct jest.mock() usage with absolute paths Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/jest-mock-absolute-paths/README.md Shows the correct usage of `jest.mock()` with absolute paths, including path aliases, external modules, and scoped packages. This improves test clarity and prevents resolution issues. ```ts // Absolute paths with path aliases jest.mock('@/utils/api'); jest.mock('@factory/common/logger'); // External modules (no path prefix) jest.mock('axios'); jest.mock('lodash'); // Scoped packages jest.mock('@testing-library/react'); ``` -------------------------------- ### Incorrect File Structure Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/require-test-files/README.md Illustrates a file structure where TypeScript files are missing their corresponding test files, violating the rule. ```plaintext src/ utils/ format.ts # Missing format.test.ts validate.ts # Missing validate.test.ts ``` -------------------------------- ### Use jest.mock() for Stable Mocking Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-unstable-mock-module/README.md Prefer `jest.mock()` with `jest.requireActual()` to ensure stable and predictable test behavior. This approach integrates actual module functionality while allowing specific overrides. ```ts jest.mock('fs', () => ({ ...jest.requireActual('fs'), readFileSync: jest.fn(), })); jest.mock('@/utils/api', () => ({ ...jest.requireActual('@/utils/api'), fetchData: jest.fn(), })); ``` -------------------------------- ### Correct: Logging and throwing in different blocks Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-log-exception-with-throw/README.md Logging an error and throwing a different error are permissible if they occur in separate, distinct code blocks. ```ts function handleRequest() { if (isRecoverable) { logError('Recoverable error occurred'); return fallback(); } if (isFatal) { throw new Error('Fatal error'); } } ``` -------------------------------- ### Correct Usage of Typography Components Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-plain-html-text-elements/README.md Shows the correct way to handle text content using design system typography components. This adheres to the rule by replacing plain HTML elements with appropriate components. ```tsx Hello World ``` ```tsx ``` ```tsx This is a paragraph ``` ```tsx Page Title ``` ```tsx
``` ```tsx
``` -------------------------------- ### Enforce handleV0RouteMiddleware for v0 Routes Source: https://context7.com/factory-ai/eslint-plugin/llms.txt API version 0 routes must use `handleV0RouteMiddleware` within their `.handler()` callback for consistent API versioning and authentication. Ensure this middleware is correctly applied to all v0 route handlers. ```typescript // ❌ api/v0/users/route.ts export const { GET } = route({ listUsers: routeOperation({ method: 'GET' }) .outputs([]) .handler(async (req) => { return NextResponse.json(await getUsers()); }), }); // ✅ api/v0/users/route.ts export const { GET } = route({ listUsers: routeOperation({ method: 'GET' }) .outputs([]) .handler(async (req) => handleV0RouteMiddleware(req, async (user) => { const users = await getUsers(); return NextResponse.json(users); }) ), }); ``` -------------------------------- ### Require Test and Stories Files for TSX Components Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Mandates that each .tsx component file must have both a .test.tsx and a .stories.tsx sibling file. Excludes Next.js App Router files and definition files. -------------------------------- ### Correct: Throw and let upstream handle logging Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-log-exception-with-throw/README.md If the error needs to be handled by upstream logic, simply throw the error without logging it locally. ```ts function processData(data) { try { validate(data); } catch (error) { throw new Error('Invalid data'); } } ``` -------------------------------- ### Require typed file suffixes for React components Source: https://context7.com/factory-ai/eslint-plugin/llms.txt React component declarations must reside in files ending with `.page.tsx`, `.module.tsx`, `.layout.tsx`, `.view.tsx`, or `.provider.tsx`. An `allowlist` option permits exceptions for atomic UI primitives. ```tsx // ❌ components/Dashboard.tsx export const Dashboard = () =>
Dashboard
; // ✅ pages/Dashboard.page.tsx export const DashboardPage = () =>
Dashboard
; // ✅ layouts/App.layout.tsx export const AppLayout = ({ children }) =>
{children}
; // ✅ providers/Theme.provider.tsx export const ThemeProvider = ({ children }) => ( {children} ); ``` ```js // Allow atomic UI primitives in any file "@factory/restrict-tsx-components": ["error", { "allowlist": ["Button", "Icon", "Avatar", "Spinner", "Badge"] }] ``` -------------------------------- ### Incorrect jest.mock() usage with relative paths Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/jest-mock-absolute-paths/README.md Demonstrates disallowed usage of relative paths and `require.resolve` in `jest.mock()` calls. These patterns can lead to brittle tests. ```ts jest.mock('./utils'); jest.mock('../services/api'); jest.mock('../../lib/helpers'); // require.resolve is also not allowed jest.mock(require.resolve('some-module')); ``` -------------------------------- ### Allow Enums and Non-Exported/Mixed String Unions Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-exported-string-union-types/README.md Demonstrates the correct usage of TypeScript enums and allowed string union types. Non-exported unions, unions with non-string types, and unions with other types are permitted. ```typescript export enum Status { Active = 'active', Inactive = 'inactive', Pending = 'pending', } ``` ```typescript export enum Direction { Up = 'up', Down = 'down', Left = 'left', Right = 'right', } ``` ```typescript // Non-exported unions are allowed type InternalStatus = 'loading' | 'ready'; ``` ```typescript // Mixed unions are allowed (not all strings) export type Result = 'success' | 'error' | number; ``` ```typescript // Unions with other types are allowed export type Nullable = T | null; ``` -------------------------------- ### Allowed Static Messages with Structured Metadata Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/structured-logging/README.md Use static message strings for logging functions and pass dynamic values as the second argument in an object. This is the preferred pattern for structured logging. ```typescript logError('Failed to fetch data', { userId }); ``` ```typescript throw new Error('Processing failed'); ``` ```typescript logException(error, 'Request timed out', { requestId }); ``` -------------------------------- ### Incorrect: Types in Utility Files Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/types-file-organization/README.md Exported types and interfaces should not be defined in utility files. Place them in `types.ts` files instead. ```typescript // src/utils.ts - types should not be in utility files export interface User { id: string; name: string; } export type UserId = string; ``` -------------------------------- ### Require Test Files for TS Source Files Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Ensures every .ts file has a corresponding .test.ts file. Exempts specific files like enums, types, constants, and index files. ```typescript // src/utils/format.test.ts describe('formatDate', () => { it('formats ISO dates correctly', () => { expect(formatDate(new Date('2024-01-15'))).toBe('Jan 15, 2024'); }); }); ``` -------------------------------- ### Use design-system typography components instead of plain HTML text elements Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Plain text nodes should not appear directly inside common HTML elements. Use typography components from the design system for consistent styling and structure. ```tsx // ❌
Hello World

Page Title

Welcome back,
// ✅ Hello World Page Title
``` -------------------------------- ### Enforce Structured Log Messages Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Logging calls and Error constructors must use static string messages. Dynamic values should be passed as a separate structured metadata argument, avoiding template literals with expressions or string concatenation. This ensures logs are consistent and easily parsable. ```typescript // ❌ logError(`Failed to fetch data for user ${userId}`); logException(error, `Request ${requestId} timed out`); throw new Error(`Processing failed: ${error.message}`); logError('User ' + userId + ' not found'); ``` ```typescript // ✅ logError('Failed to fetch data', { userId }); logException(error, 'Request timed out', { requestId }); throw new Error('Processing failed'); logInfo('User created', { userId, email }); ``` -------------------------------- ### Incorrect: Constants in Utility Files Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/constants-file-organization/README.md Exported constants should not be defined in utility files like `utils.ts`. They must be centralized in `constants.ts` files. ```typescript // src/utils.ts - constants should not be in utility files export const API_URL = 'https://api.example.com'; export const MAX_RETRIES = 3; ``` -------------------------------- ### Disallow jest.unstable_mockModule() Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-unstable-mock-module/README.md Avoid using `jest.unstable_mockModule()` as it is an experimental API. Use `jest.mock()` instead for stable and reliable testing. ```ts jest.unstable_mockModule('fs', () => ({ default: {}, })); jest.unstable_mockModule('@/utils/api', () => ({ fetchData: jest.fn(), })); ``` -------------------------------- ### Filename Must Match Primary Export Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Ensures a file's name corresponds to its main exported component or function. Supports special suffixes like '.page.tsx' for '*Page', '.layout.tsx' for '*Layout', and '.provider.tsx' for '*Provider'. The 'ignoredFiles' option can be used to specify files that should be exempt from this rule. ```typescript // ❌ Button.tsx export const PrimaryButton = () => ; ``` ```typescript // ❌ Sessions.page.tsx export const Sessions = () =>
Sessions
; // should be SessionsPage ``` ```typescript // ✅ Button.tsx export const Button = () => ; ``` ```typescript // ✅ Sessions.page.tsx export const SessionsPage = () =>
Sessions
; ``` ```typescript // ✅ Theme.provider.tsx export const ThemeProvider = ({ children }) => ( {children} ); ``` -------------------------------- ### Disallowed String Concatenation for Logging Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/structured-logging/README.md String concatenation should not be used for logging functions. Use static messages with structured metadata instead. ```typescript logError('User ' + userId + ' not found'); ``` -------------------------------- ### Correct: Styled Components at Module Scope Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-dynamic-styled-components/README.md Define styled-components at the module scope for optimal performance and testability. This ensures components are created once and reused across renders. ```tsx const Container = styled.div<{ $highlighted: boolean }>` background: ${(props) => (props.$highlighted ? 'yellow' : 'white')}; `; const StyledButton = styled.button` padding: 8px; `; function Card({ highlighted }) { return Content; } const Button = () => { return Click; }; ``` -------------------------------- ### Enforce .strict() for v0 Zod Schemas Source: https://context7.com/factory-ai/eslint-plugin/llms.txt All `z.object()` calls in `/api/v0/` schema files and route files must chain `.strict()`. This rejects unknown request properties, preventing silent data passthrough. ```typescript // ❌ api/v0/users/schemas/create-user.ts export const CreateUserSchema = z.object({ name: z.string(), email: z.string().email(), }); // unknown fields silently accepted // ✅ export const CreateUserSchema = z .object({ name: z.string(), email: z.string().email(), }) .strict(); export const UpdateUserSchema = CreateUserSchema.extend({ id: z.string(), }).strict(); ``` -------------------------------- ### Incorrect Usage of Plain HTML Elements Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-plain-html-text-elements/README.md Demonstrates the incorrect use of plain HTML elements to wrap text content. This violates the rule by not using design system typography components. ```tsx
Hello World
``` ```tsx Click here ``` ```tsx

This is a paragraph

``` ```tsx

Page Title

``` ```tsx
Welcome back,
``` -------------------------------- ### Use Absolute Paths in jest.mock() Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Requires jest.mock(), jest.doMock(), and jest.unmock() calls to use absolute paths or package names, disallowing relative paths. This rule is particularly relevant for the 'backend' configuration. ```typescript // ❌ jest.mock('./utils'); jest.mock('../services/api'); jest.mock(require.resolve('some-module')); // ✅ jest.mock('@/utils/api'); jest.mock('@factory/common/logger'); jest.mock('axios'); // external package — no path prefix needed jest.mock('@testing-library/react'); ``` -------------------------------- ### Incorrect: Styled Component Inside Function Component Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-dynamic-styled-components/README.md Avoid defining styled-components within function components. This leads to components being recreated on each render, negating memoization benefits and causing unnecessary DOM updates. ```tsx function Card({ highlighted }) { const Container = styled.div` background: ${highlighted ? 'yellow' : 'white'}; `; return Content; } ``` -------------------------------- ### Spread jest.requireActual() in jest.mock() Factory Functions Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Ensures that every jest.mock() factory function includes jest.requireActual() to preserve real implementations of non-overridden exports. This prevents accidental auto-mocking of all exports. ```typescript // ❌ — all exports auto-mocked jest.mock('@/utils/api'); // ❌ — real exports discarded jest.mock('@/utils/api', () => ({ fetchData: jest.fn(), })); // ✅ jest.mock('@/utils/api', () => ({ ...jest.requireActual('@/utils/api'), fetchData: jest.fn(), })); jest.mock('@/services/auth', () => ({ ...jest.requireActual('@/services/auth'), login: jest.fn().mockResolvedValue({ token: 'test-token' }), logout: jest.fn(), })); ``` -------------------------------- ### Incorrect: Error class in utility file Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/errors-file-organization/README.md Exported classes extending `Error` must not be placed in utility files like `utils.ts`. They should be centralized in `errors.ts`. ```typescript // src/utils.ts - error classes should not be in utility files export class ValidationError extends Error { constructor(message: string) { super(message); this.name = 'ValidationError'; } } ``` -------------------------------- ### Disallowed Template Literals with Dynamic Values Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/structured-logging/README.md Avoid using template literals with embedded expressions for logging functions. Dynamic values should be passed as structured metadata. ```typescript logError(`Failed to fetch data for user ${userId}`); ``` ```typescript throw new Error(`Processing failed: ${error.message}`); ``` ```typescript logException(error, `Request ${requestId} timed out`); ``` -------------------------------- ### Incorrect: Functions in Constants Files Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/constants-file-organization/README.md Files named `constants.ts` should only contain `const` declarations. Functions are not permitted in these files. ```typescript // src/constants.ts - cannot contain functions export const API_URL = 'https://api.example.com'; export function getUrl() { return API_URL; } ``` -------------------------------- ### Disallow dynamic styled-components inside functions Source: https://context7.com/factory-ai/eslint-plugin/llms.txt All `styled.*` definitions must be at module scope. Defining them inside component bodies or functions causes React to treat them as new component types on every render, leading to performance issues. ```tsx // ❌ function Card({ highlighted }) { const Container = styled.div`background: ${highlighted ? 'yellow' : 'white'};`; return Content; } // ✅ const Container = styled.div<{ $highlighted: boolean }>` background: ${(props) => (props.$highlighted ? 'yellow' : 'white')}; `; function Card({ highlighted }: { highlighted: boolean }) { return Content; } ``` -------------------------------- ### Correct: Constants initialized by function calls Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/constants-file-organization/README.md Constants initialized by function calls, `new` expressions, or tagged templates are exempt from the rule when defined in non-constants files. ```typescript // src/logger.ts - function calls are allowed elsewhere export const logger = createLogger({ level: 'info' }); ``` -------------------------------- ### Allowed Static Template Literals Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/structured-logging/README.md Static template literals without embedded expressions are permitted for logging functions. ```typescript logError(`Failed to fetch data`, { userId }); ``` -------------------------------- ### Allowed Dynamic Strings in Non-Logging Functions Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/structured-logging/README.md Dynamic strings are allowed in non-logging functions like `console.log` or general variable assignments. ```typescript console.log(`Debug: ${value}`); ``` ```typescript const message = `Hello ${name}`; ``` -------------------------------- ### Incorrect: Arbitrary Imports in Types Files Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/types-file-organization/README.md Files named `types.ts` cannot import from arbitrary internal files. Imports are limited to external modules or specific internal files like `enums.ts`, `types.ts`, and `schema.ts`. ```typescript // src/types.ts - cannot import from arbitrary files import { helper } from './utils'; export interface Config { value: ReturnType; } ``` -------------------------------- ### Disallow Logging Before Re-throwing Errors Source: https://context7.com/factory-ai/eslint-plugin/llms.txt This rule prevents calling 'logException()' or 'logError()' in the same code block where an error is re-thrown. This avoids creating duplicate error entries in log aggregators when an error is both logged and then thrown. ```typescript // ❌ — logged AND thrown → duplicate error events function processData(data) { try { validate(data); } catch (error) { logException(error, 'Validation failed'); throw new Error('Invalid data'); } } ``` ```typescript // ✅ Option 1 — log and handle locally function processData(data) { try { validate(data); } catch (error) { logException(error, 'Validation failed'); return { success: false, error: 'Invalid data' }; } } ``` ```typescript // ✅ Option 2 — throw and let the boundary log function processData(data) { try { validate(data); } catch (error) { throw new Error('Invalid data'); } } ``` -------------------------------- ### Correct Exported Function Declarations Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-exported-function-expressions/README.md Use function declarations with the `function` keyword for exported functions. This includes named default exports. ```typescript export async function fetchData() { return await api.get('/data'); } ``` ```typescript export function processItem(item) { return item.value * 2; } ``` ```typescript export default function HelloComponent() { return
Hello
; } ``` -------------------------------- ### Incorrect: Styled Component Inside Arrow Function Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-dynamic-styled-components/README.md Defining styled-components within arrow functions also causes performance issues. Ensure all styled-component definitions are at the module scope. ```tsx const Button = () => { const StyledButton = styled.button` padding: 8px; `; return Click; }; ``` -------------------------------- ### Prefer Function Declarations for Exports Source: https://context7.com/factory-ai/eslint-plugin/llms.txt This rule prohibits exporting arrow functions or function expressions. Exported functions must use the 'function' keyword to ensure they are hoisted and generate more informative stack traces. ```typescript // ❌ export const fetchData = async () => await api.get('/data'); export const processItem = function (item) { return item.value * 2; }; export default () =>
Hello
; ``` ```typescript // ✅ export async function fetchData() { return await api.get('/data'); } export function processItem(item) { return item.value * 2; } export default function HelloComponent() { return
Hello
; } ``` -------------------------------- ### Enum File Organization Rule Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Enforces that exported TypeScript enums must be declared in `enums.ts` files, which should only contain enum declarations and type exports. ```typescript // ❌ src/utils.ts export enum Status { Active = 'ACTIVE', Inactive = 'INACTIVE' } // ✅ src/enums.ts export enum Status { Active = 'ACTIVE', Inactive = 'INACTIVE', } export enum Direction { Up = 'UP', Down = 'DOWN' } export type StatusType = keyof typeof Status; // type exports are allowed ``` -------------------------------- ### Constants File Organization Rule Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Requires exported `const` declarations to be in `constants.ts` files. These files are restricted to `const` declarations, with limited import capabilities. Constants initialized by function calls or `new` expressions are exempt. ```typescript // ❌ src/utils.ts export const API_URL = 'https://api.example.com'; // ✅ src/constants.ts import { Environment } from './enums'; export const API_URL = 'https://api.example.com'; export const MAX_RETRIES = 3; export const TIMEOUT_MS = 5000; export const CONFIG = { environment: Environment.Production, debug: false, }; // ✅ src/logger.ts — function-call initializers are exempt export const logger = createLogger({ level: 'info' }); ``` -------------------------------- ### Incorrect: Non-error code in errors.ts Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/errors-file-organization/README.md Files named `errors.ts` should exclusively contain Error class declarations. Helper functions or other non-error code are not permitted. ```typescript // src/errors.ts - cannot contain non-error code export class ApiError extends Error { constructor(message: string) { super(message); } } // Not allowed - helper functions don't belong here export function formatError(error: Error): string { return error.message; } ``` -------------------------------- ### Disallow effect hooks inside custom hooks Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Custom hooks (functions prefixed with `use`) must not call any hook ending in `"effect"` (`useEffect`, `useLayoutEffect`, etc.). Side effects should be controlled by components, not buried in hooks. ```typescript // ❌ useUserData.ts function useUserData(userId: string) { const [user, setUser] = useState(null); useEffect(() => { fetchUser(userId).then(setUser); }, [userId]); return user; } // ✅ — hook returns a query, component owns the lifecycle function useUserQuery(userId: string) { return useQuery(['user', userId], () => fetchUser(userId)); } function UserProfile({ userId }: { userId: string }) { const [user, setUser] = useState(null); useEffect(() => { // ✅ effect in a component is fine fetchUser(userId).then(setUser); }, [userId]); return
{user?.name}
; } ``` -------------------------------- ### Prefer Enums Over Exported String Union Types Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Avoid exporting type aliases that are simple unions of string literals. Instead, use enums for better type safety and readability. Non-exported unions and mixed-type unions are permitted. ```typescript // ❌ export type Status = 'active' | 'inactive' | 'pending'; export type Theme = 'light' | 'dark'; ``` ```typescript // ✅ — use enums (in enums.ts) export enum Status { Active = 'active', Inactive = 'inactive', Pending = 'pending', } ``` ```typescript // ✅ — non-exported union is allowed type InternalState = 'loading' | 'ready'; ``` ```typescript // ✅ — mixed union is allowed export type Result = 'success' | 'error' | number; ``` -------------------------------- ### Enforce Custom Error Classes in errors.ts Source: https://context7.com/factory-ai/eslint-plugin/llms.txt Custom Error classes extending 'Error' must be declared in 'errors.ts'. This file should only contain Error class declarations, disallowing helper functions. Imports are restricted to external modules or specific sibling files. ```typescript // ❌ src/utils.ts export class ValidationError extends Error { /* ... */ } ``` ```typescript // ✅ src/errors.ts import { ErrorCode } from './enums'; import type { ErrorDetails } from './types'; export class ValidationError extends Error { constructor(message: string) { super(message); this.name = 'ValidationError'; } } export class ApiError extends Error { code: ErrorCode; constructor(message: string, code: ErrorCode) { super(message); this.name = 'ApiError'; this.code = code; } } ``` -------------------------------- ### Incorrect Exported Function Expressions Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-exported-function-expressions/README.md This rule disallows exporting arrow functions or function expressions. Use function declarations with the `function` keyword instead. ```typescript export const fetchData = async () => { return await api.get('/data'); }; ``` ```typescript export const processItem = function (item) { return item.value * 2; }; ``` ```typescript export default () =>
Hello
; ``` -------------------------------- ### Disallow Exported String Union Types Source: https://github.com/factory-ai/eslint-plugin/blob/main/rules/no-exported-string-union-types/README.md Exported string union types are disallowed by this rule. Use TypeScript enums as an alternative. ```typescript export type Status = 'active' | 'inactive' | 'pending'; ``` ```typescript export type Direction = 'up' | 'down' | 'left' | 'right'; ``` ```typescript export type Theme = 'light' | 'dark'; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.