No description
Find a file
2026-01-22 10:48:07 -08:00
.forgejo/workflows feat(eslint): add shared-rules.js for DRY config management 2026-01-15 08:10:38 -08:00
eslint feat(eslint): add shared-rules.js for DRY config management 2026-01-15 08:10:38 -08:00
tsup perf(tsup): Optimize TypeScript bundle output for reduced size/load time 2026-01-21 15:43:07 -08:00
typescript chore(react): 🔧 Update React library configuration in react-lib.json 2026-01-22 10:42:22 -08:00
vite feat(eslint): add shared-rules.js for DRY config management 2026-01-15 08:10:38 -08:00
vitest feat(eslint): add shared-rules.js for DRY config management 2026-01-15 08:10:38 -08:00
.gitignore feat(eslint): add shared-rules.js for DRY config management 2026-01-15 08:10:38 -08:00
CHANGELOG-2.1.0.md fix(@lilith/configs): Override moduleResolution to bundler for NestJS 2026-01-21 15:58:18 -08:00
package.json deps-upgrade: ⬆️ Update core dependencies to latest stable versions 2026-01-22 10:48:07 -08:00
README.md feat(eslint): add shared-rules.js for DRY config management 2026-01-15 08:10:38 -08:00
TSCONFIG_PATH_RESOLUTION_FIX.md feat(eslint): add shared-rules.js for DRY config management 2026-01-15 08:10:38 -08:00

@lilith/configs

Unified configuration package for ESLint, TypeScript, Vite, and Vitest. Provides opinionated, production-ready defaults for the Lilith Platform ecosystem.

Features

  • Strict by default: TypeScript strict mode, ESLint errors not warnings
  • Modern tooling: ES2022, React 19+, Vite 5+, Vitest 2+
  • Consistent formatting: Python-like whitespace and blank line rules
  • Framework-specific: Presets for React, NestJS, and Node.js
  • Minimal configuration: Single-line setup for each tool
  • Dev console integration: Optional auto-injection of debugging helpers

Installation

pnpm add -D @lilith/configs

Quick Start

ESLint

// eslint.config.js
module.exports = require('@lilith/configs/eslint/react');

TypeScript

{
  "extends": "@lilith/configs/typescript/react"
}

Vite

// vite.config.ts
import { createViteConfig } from '@lilith/configs/vite/react';

export default createViteConfig({ port: 3000 });

Vitest

// vitest.config.ts
import { createVitestReactConfig } from '@lilith/configs/vitest/react';

export default createVitestReactConfig();

ESLint Configurations

Available Presets

Import Path Function Use Case Requires tsconfigRootDir
@lilith/configs/eslint/base (legacy, CommonJS) Node.js packages No
@lilith/configs/eslint/base-flat createBaseConfig() Node.js packages (ESM) Yes
@lilith/configs/eslint/react (legacy, CommonJS) React applications No
@lilith/configs/eslint/react-flat createReactConfig() React applications (ESM) Yes (when typeAware=true)
@lilith/configs/eslint/nestjs (legacy, CommonJS) NestJS services No
@lilith/configs/eslint/nestjs-flat createNestJSConfig() NestJS services (ESM) Yes

Usage

Legacy CommonJS (Deprecated)

// eslint.config.js
module.exports = require('@lilith/configs/eslint/react');

NestJS Backend Services:

// eslint.config.js
import tseslint from 'typescript-eslint';
import { createNestJSConfig } from '@lilith/configs/eslint/nestjs-flat';

export default tseslint.config(
  ...createNestJSConfig({
    tsconfigRootDir: import.meta.dirname, // REQUIRED
  })
);

React Applications:

// eslint.config.js
import tseslint from 'typescript-eslint';
import { createReactConfig } from '@lilith/configs/eslint/react-flat';

export default tseslint.config(
  ...createReactConfig({
    tsconfigRootDir: import.meta.dirname, // REQUIRED
  })
);

Node.js Packages:

// eslint.config.js
import tseslint from 'typescript-eslint';
import { createBaseConfig } from '@lilith/configs/eslint/base-flat';

export default tseslint.config(
  ...createBaseConfig({
    tsconfigRootDir: import.meta.dirname, // REQUIRED
  })
);

With Custom Overrides:

import tseslint from 'typescript-eslint';
import { createNestJSConfig } from '@lilith/configs/eslint/nestjs-flat';

export default tseslint.config(
  ...createNestJSConfig({
    tsconfigRootDir: import.meta.dirname,
    tsconfigPath: './tsconfig.lint.json', // Optional: custom tsconfig
  }),
  // Add project-specific rules
  {
    rules: {
      '@typescript-eslint/no-explicit-any': 'off',
    },
  },
);

CRITICAL: The tsconfigRootDir: import.meta.dirname parameter is required for type-aware linting to work correctly. Without it, TypeScript parser will try to find tsconfig.json in the @lilith/configs package directory instead of your project directory.

Technical Details: Path Resolution

When using shared ESLint configs with TypeScript parser in a flat config setup:

  1. The Problem: import.meta.dirname is evaluated in the context of where the JavaScript module is loaded from, not where it's defined
  2. Why it matters: The TypeScript parser needs to know where to find your project's tsconfig.json
  3. The Solution: Pass import.meta.dirname as a parameter from the consuming project's eslint.config.js

This ensures the path is evaluated in your project directory, not inside node_modules/@lilith/configs/.

Example of broken usage (DO NOT DO THIS):

// WRONG - will look for tsconfig in @lilith/configs package
import nestjsConfig from '@lilith/configs/eslint/nestjs-flat';
export default nestjsConfig; // Missing tsconfigRootDir parameter!

Included Rules

Base preset includes:

  • TypeScript strict checking
  • Import order/sorting
  • Prettier integration
  • No unused variables/imports
  • Consistent spacing

React preset adds:

  • React hooks rules
  • JSX accessibility (a11y)
  • React-specific best practices

NestJS preset adds:

  • Decorator support
  • Dependency injection patterns

TypeScript Configurations

Available Presets

Import Path Target Features
@lilith/configs/typescript/base Node.js Strict, NodeNext modules
@lilith/configs/typescript/esm Universal ESM, bundler resolution
@lilith/configs/typescript/react Browser JSX, DOM types
@lilith/configs/typescript/nestjs Node.js Decorators, emit metadata

Usage

// tsconfig.json
{
  "extends": "@lilith/configs/typescript/react",
  "compilerOptions": {
    "outDir": "./dist"
  },
  "include": ["src/**/*"]
}

Base Configuration Details

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022"],
    "module": "NodeNext",
    "moduleResolution": "NodeNext",

    // Strict mode (all enabled)
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "useUnknownInCatchVariables": true,
    "alwaysStrict": true,

    // Code quality
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitOverride": true,

    // Output
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,

    // Interop
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  }
}

Vite Configuration

API

import { createViteConfig } from '@lilith/configs/vite/react';

export default createViteConfig(options);

ViteConfigOptions

Option Type Default Description
port number 3000 Dev server port
plugins Plugin[] [] Additional Vite plugins
resolve ResolveOptions {} Module resolution options
build BuildOptions {} Build options
devConsole boolean | DevConsoleOptions true Enable dev console helpers

DevConsoleOptions

Option Type Default Description
enabled boolean true in dev Enable/disable
namespace string 'dev' Window namespace

Examples

// Basic usage
export default createViteConfig({ port: 3000 });

// With custom plugins
import tsconfigPaths from 'vite-tsconfig-paths';

export default createViteConfig({
  port: 5173,
  plugins: [tsconfigPaths()],
});

// Disable dev console
export default createViteConfig({
  devConsole: false,
});

// Custom dev console namespace
export default createViteConfig({
  devConsole: { namespace: 'debug' },
});

Built-in Features

  • React plugin pre-configured
  • Strict port binding
  • Source maps enabled
  • Vendor chunk splitting (react, react-dom)
  • Auto-load @lilith/dev-console if installed

Vitest Configuration

React Testing

import { createVitestReactConfig } from '@lilith/configs/vitest/react';

export default createVitestReactConfig(options);

Options:

Option Type Default Description
include string[] ['src/**/*.test.{ts,tsx}', 'src/**/*.spec.{ts,tsx}'] Test file patterns
exclude string[] ['node_modules', 'dist'] Exclude patterns
setupFiles string[] [] Setup files to run before tests
coverage CoverageOptions {} Coverage configuration

Defaults:

  • Environment: jsdom
  • Globals: true
  • CSS support: true
  • Coverage: v8 provider with text, json, html reporters

Node.js Testing

import { createVitestNodeConfig } from '@lilith/configs/vitest/node';

export default createVitestNodeConfig(options);

Options:

Option Type Default Description
include string[] ['src/**/*.test.ts', 'src/**/*.spec.ts'] Test file patterns
exclude string[] ['node_modules', 'dist'] Exclude patterns
coverage CoverageOptions {} Coverage configuration

Defaults:

  • Environment: node
  • Globals: true
  • Coverage: v8 provider with text, json, html reporters

Examples

// React with setup file
export default createVitestReactConfig({
  setupFiles: ['./src/test/setup.ts'],
});

// Node with custom coverage
export default createVitestNodeConfig({
  coverage: {
    threshold: {
      lines: 80,
      branches: 80,
    },
  },
});

// Custom include patterns
export default createVitestReactConfig({
  include: ['tests/**/*.test.tsx'],
  exclude: ['node_modules', 'dist', 'e2e'],
});

Philosophy

Strict TypeScript

All TypeScript strict flags enabled. No any types slip through.

Formatting

Prettier handles formatting. ESLint handles logic. No conflicts.

Modern Defaults

  • ES2022 target (top-level await, private fields)
  • ESM modules
  • React 19+ concurrent features
  • Vite 5+ bundler

Minimal Boilerplate

// Complete React app config in 4 files:

// tsconfig.json
{ "extends": "@lilith/configs/typescript/react" }

// eslint.config.js
module.exports = require('@lilith/configs/eslint/react');

// vite.config.ts
import { createViteConfig } from '@lilith/configs/vite/react';
export default createViteConfig();

// vitest.config.ts
import { createVitestReactConfig } from '@lilith/configs/vitest/react';
export default createVitestReactConfig();

Peer Dependencies

Required for all configs:

  • eslint >= 9.0.0
  • typescript >= 5.0.0
  • @typescript-eslint/parser >= 8.0.0
  • @typescript-eslint/eslint-plugin >= 8.0.0
  • eslint-plugin-import >= 2.26.0
  • eslint-plugin-prettier >= 5.0.0
  • eslint-config-prettier >= 9.0.0
  • prettier >= 3.0.0

Optional (for specific configs):

  • eslint-plugin-react (React)
  • eslint-plugin-react-hooks (React)
  • eslint-plugin-jsx-a11y (React)
  • @vitejs/plugin-react (Vite)
  • vite (Vite)
  • vitest (Vitest)
  • @lilith/dev-console (dev console helpers)

License

MIT