@bfra.me/eslint-config
Version:
Shared ESLint configuration for bfra.me
273 lines (260 loc) • 8.74 kB
text/typescript
import type {Config} from '../config'
import {sortOrder} from 'sort-package-json'
import {GLOB_RENOVATE_CONFIG, GLOB_TS_CONFIG} from '../globs'
import {jsonSchema} from './json-schema'
/**
* Creates an ESLint configuration for sorting package.json files.
*
* This function returns a configuration that enforces consistent ordering of:
* - Array values in the `files` field (ascending order)
* - Object keys at the root level using a custom sort order
* - Dependencies sections (dependencies, devDependencies, etc.) in alphabetical order
* - Package manager overrides (resolutions, overrides, pnpm.overrides) in alphabetical order
* - Workspace catalog entries in alphabetical order
* - Export conditions in a specific order (types, import, require, default)
* - Git hooks in execution order for client-side hooks
*
* @returns An array containing a single ESLint configuration object for package.json files
*/
export function sortPackageJson(): Config[] {
return [
{
name: '@bfra.me/sort/package-json',
files: ['**/package.json'],
rules: {
'jsonc/sort-array-values': [
'error',
{
order: {type: 'asc'},
pathPattern: '^files$',
},
],
'jsonc/sort-keys': [
'error',
{
order: sortOrder,
pathPattern: '^$',
},
{
order: {type: 'asc'},
pathPattern: '^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$',
},
{
order: {type: 'asc'},
pathPattern: '^(?:resolutions|overrides|pnpm.overrides)$',
},
{
order: {type: 'asc'},
pathPattern: String.raw`^workspaces\.catalog$`,
},
{
order: {type: 'asc'},
pathPattern: String.raw`^workspaces\.catalogs\.[^.]+$`,
},
{
order: ['types', 'import', 'require', 'default'],
pathPattern: '^exports.*$',
},
{
order: [
// client hooks only
'pre-commit',
'prepare-commit-msg',
'commit-msg',
'post-commit',
'pre-rebase',
'post-rewrite',
'post-checkout',
'post-merge',
'pre-push',
'pre-auto-gc',
],
pathPattern: '^(?:gitHooks|husky|simple-git-hooks)$',
},
],
},
},
]
}
/**
* Creates ESLint configuration for sorting Renovate configuration files.
*
* This function returns an array of ESLint configurations that enforce sorting rules
* for Renovate config files, including:
* - Sorting array values in ascending order (except for 'extends' arrays where order matters)
* - Sorting object keys according to Renovate's recommended structure
*
* The key sorting order follows the pattern defined in the Sanity.io renovate-config
* repository for consistent configuration structure.
*
* @returns A promise that resolves to an array of ESLint configurations for Renovate files
*/
export async function sortRenovateConfig(): Promise<Config[]> {
return [
{
name: '@bfra.me/sort/renovate-config',
files: GLOB_RENOVATE_CONFIG,
rules: {
'jsonc/sort-array-values': [
'error',
{
// Don't sort 'extends' or 'postUpgradeTasks.commands' arrays, as order matters
order: {type: 'asc'},
pathPattern: '^(?!extends$|postUpgradeTasks\.commands$).*',
},
],
'jsonc/sort-keys': [
'error',
{
// Based on the order defined here:
// https://github.com/sanity-io/renovate-config/blob/8c1fdebe125f16087924216f97838e93824109d1/scripts/update-sorting.js#L30
order: [
'$schema',
'description',
'extends',
'onboardingConfigFileName',
'lockFileMaintenance',
'packageRules',
'postUpgradeTasks',
],
pathPattern: '^$',
},
],
},
},
...(await jsonSchema('renovate-config', GLOB_RENOVATE_CONFIG)),
]
}
/**
* Creates ESLint configuration for sorting TypeScript configuration files.
*
* This function generates rules to enforce a specific order of properties in tsconfig.json files:
* - Root level properties are ordered: extends, compilerOptions, references, files, include, exclude
* - CompilerOptions properties are grouped and ordered by TypeScript compiler categories:
* Projects, Language and Environment, Modules, JavaScript Support, Type Checking,
* Emit, Interop Constraints, and Completeness
*
* @returns A promise that resolves to an array of ESLint configurations for tsconfig files
*/
export async function sortTsconfig(): Promise<Config[]> {
return [
{
name: '@bfra.me/sort/tsconfig',
files: GLOB_TS_CONFIG,
rules: {
'jsonc/sort-keys': [
'error',
{
order: ['extends', 'compilerOptions', 'references', 'files', 'include', 'exclude'],
pathPattern: '^$',
},
{
order: [
/* Projects */
'incremental',
'composite',
'tsBuildInfoFile',
'disableSourceOfProjectReferenceRedirect',
'disableSolutionSearching',
'disableReferencedProjectLoad',
/* Language and Environment */
'target',
'jsx',
'jsxFactory',
'jsxFragmentFactory',
'jsxImportSource',
'lib',
'moduleDetection',
'noLib',
'reactNamespace',
'useDefineForClassFields',
'emitDecoratorMetadata',
'experimentalDecorators',
'libReplacement',
/* Modules */
'baseUrl',
'rootDir',
'rootDirs',
'customConditions',
'module',
'moduleResolution',
'moduleSuffixes',
'noResolve',
'paths',
'resolveJsonModule',
'resolvePackageJsonExports',
'resolvePackageJsonImports',
'typeRoots',
'types',
'allowArbitraryExtensions',
'allowImportingTsExtensions',
'allowUmdGlobalAccess',
/* JavaScript Support */
'allowJs',
'checkJs',
'maxNodeModuleJsDepth',
/* Type Checking */
'strict',
'strictBindCallApply',
'strictFunctionTypes',
'strictNullChecks',
'strictPropertyInitialization',
'allowUnreachableCode',
'allowUnusedLabels',
'alwaysStrict',
'exactOptionalPropertyTypes',
'noFallthroughCasesInSwitch',
'noImplicitAny',
'noImplicitOverride',
'noImplicitReturns',
'noImplicitThis',
'noPropertyAccessFromIndexSignature',
'noUncheckedIndexedAccess',
'noUnusedLocals',
'noUnusedParameters',
'useUnknownInCatchVariables',
/* Emit */
'declaration',
'declarationDir',
'declarationMap',
'downlevelIteration',
'emitBOM',
'emitDeclarationOnly',
'importHelpers',
'importsNotUsedAsValues',
'inlineSourceMap',
'inlineSources',
'mapRoot',
'newLine',
'noEmit',
'noEmitHelpers',
'noEmitOnError',
'outDir',
'outFile',
'preserveConstEnums',
'preserveValueImports',
'removeComments',
'sourceMap',
'sourceRoot',
'stripInternal',
/* Interop Constraints */
'allowSyntheticDefaultImports',
'esModuleInterop',
'forceConsistentCasingInFileNames',
'isolatedDeclarations',
'isolatedModules',
'preserveSymlinks',
'verbatimModuleSyntax',
'erasableSyntaxOnly',
/* Completeness */
'skipDefaultLibCheck',
'skipLibCheck',
],
pathPattern: '^compilerOptions$',
},
],
},
},
...(await jsonSchema('tsconfig', GLOB_TS_CONFIG)),
]
}