@baseplate-dev/core-generators
Version:
Core generators for Baseplate
236 lines (208 loc) • 8.45 kB
JavaScript
// @ts-nocheck
import eslint from '@eslint/js';
import eslintConfigPrettier from 'eslint-config-prettier/flat';
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript';
import { importX } from 'eslint-plugin-import-x';
import perfectionist from 'eslint-plugin-perfectionist';
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
import { defineConfig } from 'eslint/config';
import globals from 'globals';
import tsEslint from 'typescript-eslint';
const tsFileGlobs = ['**/*.{mts,cts,ts,tsx}'];
// Specifies which patterns of files are allowed to have dev dependencies
// For example, test files are allowed to have dev dependencies
const FILES_WITH_DEV_DEPENDENCIES = TPL_DEV_DEPENDENCIES;
// Specifies which files are ignored by ESLint
const IGNORE_FILES = TPL_IGNORE_FILES;
// Specifies which files should use the default tsconfig.json project
// This is useful for certain files outside the src directory, e.g. config files
const TS_DEFAULT_PROJECT_FILES = TPL_DEFAULT_PROJECT_FILES;
export default defineConfig(
// ESLint Configs for all files
eslint.configs.recommended,
{
linterOptions: {
reportUnusedDisableDirectives: 'warn',
reportUnusedInlineConfigs: 'warn',
},
languageOptions: {
globals: {
...globals.TPL_GLOBALS,
},
},
rules: {
// disallow console.log since that is typically used for debugging
'no-console': ['error', { allow: ['warn', 'error', 'debug', 'info'] }],
// Enforce object shorthand syntax to keep object properties concise.
'object-shorthand': ['error', 'always'],
// Enforce the use of template literals instead of string concatenation.
'prefer-template': 'error',
// Enforce using concise arrow function syntax when possible.
'arrow-body-style': ['error', 'as-needed'],
// Encourage the use of arrow functions for callbacks to avoid `this` binding issues.
// Allow named functions to be used in arrow functions to support generic functions being passed in
// e.g. generic components using forwardRef
'prefer-arrow-callback': ['error', { allowNamedFunctions: true }],
// Disallow renaming imports, exports, or destructured variables to the same name.
'no-useless-rename': 'error',
// Allow empty patterns in function parameters which are used in test fixtures
'no-empty-pattern': ['error', { allowObjectPatternsAsParameters: true }],
},
},
// Typescript ESLint Configs
{
files: tsFileGlobs,
extends: [
...tsEslint.configs.strictTypeChecked,
...tsEslint.configs.stylisticTypeChecked,
],
languageOptions: {
parserOptions: {
tsconfigRootDir: import.meta.dirname,
projectService: {
// allow default project for root configs
allowDefaultProject: TS_DEFAULT_PROJECT_FILES,
},
},
},
rules: {
// require explicit return types for functions for faster type checking
'@typescript-eslint/explicit-function-return-type': [
'error',
{ allowExpressions: true, allowTypedFunctionExpressions: true },
],
// Ensure consistent usage of type exports
'@typescript-eslint/consistent-type-exports': 'error',
// Ensure consistent usage of type imports
'@typescript-eslint/consistent-type-imports': 'error',
// Allow more relaxed template expression checks
'@typescript-eslint/restrict-template-expressions': [
'error',
{
allowBoolean: true,
allowNumber: true,
},
],
// Allow constant loop conditions
'@typescript-eslint/no-unnecessary-condition': [
'error',
{ allowConstantLoopConditions: true },
],
// Allow ternary operators to be used when checking for empty string
'@typescript-eslint/prefer-nullish-coalescing': [
'error',
{ ignoreTernaryTests: true },
],
// Catch new union members silently falling into a generic `default` case
'@typescript-eslint/switch-exhaustiveness-check': 'error',
},
},
// Import-X Configs
importX.flatConfigs.recommended,
importX.flatConfigs.typescript,
{
rules: {
// Let Typescript handle it since it checks for unresolved imports
'import-x/namespace': 'off',
'import-x/default': 'off',
'import-x/no-unresolved': 'off',
// Allow named default imports without flagging them as errors
'import-x/no-named-as-default': 'off',
// Allow named default members without flagging them as errors
'import-x/no-named-as-default-member': 'off',
// Disallow importing dependencies that aren't explicitly listed in the package.json,
// except for those explicitly allowed under `devDependencies` (e.g., test files)
'import-x/no-extraneous-dependencies': [
'error',
{ devDependencies: FILES_WITH_DEV_DEPENDENCIES },
],
// Disallow import relative packages (e.g., `import '../other-package/foo'`)
'import-x/no-relative-packages': 'error',
},
settings: {
'import-x/resolver-next': [createTypeScriptImportResolver()],
},
},
// Unicorn Configs
eslintPluginUnicorn.configs['unopinionated'],
{
rules: {
// Allow ternary operators to be used when appropriate (this conflicts with https://typescript-eslint.io/rules/prefer-nullish-coalescing/)
'unicorn/prefer-logical-operator-over-ternary': 'off',
// Re-enable with the arrow-function carve-out since the unopinionated preset omits this rule by default
'unicorn/consistent-function-scoping': [
'error',
{ checkArrowFunctions: false },
],
// A bit over-eager flagging any module references
'unicorn/prefer-module': 'off',
// False positives with array-like functions (https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1394)
'unicorn/no-array-method-this-argument': 'off',
// Prevents returning undefined from functions which Typescript assumes is void
'unicorn/no-useless-undefined': 'off',
// While we use CJS, we cannot use top-level await
'unicorn/prefer-top-level-await': 'off',
// Can be too strict if you prefer to have shorter cases for negated conditions
'unicorn/no-negated-condition': 'off',
// Allow usage of utf-8 text encoding since it's consistent with the WHATWG spec
// and autofixing can cause unexpected changes (https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1926)
'unicorn/text-encoding-identifier-case': 'off',
// Enforce for-of/array methods over manual index loops; the unopinionated preset omits this rule by default
'unicorn/no-for-loop': 'error',
// Enforce kebab-case filenames (repo convention); the unopinionated preset omits this rule by default
'unicorn/filename-case': [
'error',
{
cases: {
kebabCase: true,
},
ignore: [
String.raw`^-[a-z0-9\-\.]+$`,
String.raw`^\$[a-zA-Z0-9\.]+$`,
],
},
],
},
},
// Perfectionist Configs
{
plugins: { perfectionist },
rules: {
// Enforces a consistent sorting order for import and export statements
'perfectionist/sort-imports': [
'error',
{
internalPattern: ['^@src/'],
// We use the default groups but ensure we place the side-effect imports last except for instrumentation
groups: [
'instrument',
'type-import',
['value-builtin', 'value-external'],
'type-internal',
'value-internal',
['type-parent', 'type-sibling', 'type-index'],
['value-parent', 'value-sibling', 'value-index'],
'ts-equals-import',
'side-effect',
'unknown',
],
customGroups: [
{
selector: 'side-effect',
groupName: 'instrument',
elementNamePattern: String.raw`instrument(.test-helper)?(\.js)?$`,
},
],
},
],
'perfectionist/sort-exports': ['error'],
'perfectionist/sort-named-imports': ['error'],
'perfectionist/sort-named-exports': ['error'],
},
},
/* TPL_TAILWIND_CONFIG */
/* TPL_EXTRA_CONFIGS */
// Global Ignores
{ ignores: IGNORE_FILES },
eslintConfigPrettier,
);