@creo-team/eslint-config

中文文档
5.0.2发布于 2026/10/30ISCTypeScriptESM + CJS构建来源已验证近 30 天下载 2104

ESLint flat config: TypeScript (strict), Prettier, JSDoc, complexity, no-magic-numbers. createConfig() for options.

原始使用文档
文档目录24 节
  1. Install
  2. Usage patterns
  3. 1. Single repo (default)
  4. 2. Single repo with options
  5. 3. Monorepo — one root config (recommended)
  6. 4. Monorepo — per-workspace config
  7. Scripts
  8. TypeScript
  9. Extending
  10. Customizing rules
  11. Why this config
  12. Optional: lock in project structure
  13. Monorepo — lock workspace dirs
  14. Monorepo + app structure
  15. Single repo — app structure only
  16. App structure presets
  17. Custom dirs
  18. Constants ( @creo-team/eslint-config/constants )
  19. What’s included
  20. Docs
  21. Release flow
  22. Examples
  23. Development
  24. License

@creo-team/eslint-config

ESLint flat config for TypeScript/React: strict type-checking, Prettier, JSDoc, complexity limits, async correctness, and no magic numbers. One style and one set of rules so code stays consistent and reviewable — and so tools like Cursor and Claude can fix and generate code that matches. Works with the ESLint MCP server.

npm version License

Install

npm install @creo-team/eslint-config --save-dev

Node: ^22.22.2 || >=24.15.0. Prefer Node 24. TypeScript 7 works alongside this config; see TypeScript.

Usage patterns

1. Single repo (default)

One app or package, one tsconfig. Use the preset as-is.

ESM (eslint.config.mjs):

import eslintConfig from '@creo-team/eslint-config'
export default eslintConfig

CommonJS (eslint.config.js):

const eslintConfig = require('@creo-team/eslint-config')
module.exports = eslintConfig

2. Single repo with options

Customize ignores or which tsconfig to use:

const { createConfig } = require('@creo-team/eslint-config')

module.exports = createConfig({
  ignores: ['dist/**', 'build/**'],
  tsconfig: 'tsconfig.app.json', // optional; default: getTsConfigFile()
})

In ESM (eslint.config.mjs), use import { createConfig } from '@creo-team/eslint-config'.

Multiple packages (e.g. app/, lib/, infra/), each with its own tsconfig.json. Use projectService so type-aware rules resolve the nearest tsconfig per file. One eslint.config.js at the repo root; run eslint . from the root.

const { createConfig } = require('@creo-team/eslint-config')

module.exports = createConfig({
  ignores: [
    '**/node_modules/**',
    '**/dist/**',
    '**/.next/**',
    '**/build/**',
    '**/out/**',
    '**/cdk.out/**',
    '**/*.config.js',
    '**/*.config.mjs',
    '**/*.config.ts',
  ],
  projectService: true,
})

Root package.json (npm workspaces):

{
  "workspaces": ["nextjs", "aws/infra", "shared"],
  "scripts": {
    "lint": "eslint .",
    "fix": "eslint . --fix"
  },
  "devDependencies": {
    "@creo-team/eslint-config": "^5.0.0",
    "eslint": "^10.11.0"
  }
}

Requirements: Each package with TypeScript has a tsconfig.json in that directory. No root tsconfig required. See typescript-eslint project service.

Example: See examples/monorepo/ in this repo. Run cd examples/monorepo && npm install && npm run lint to validate.

4. Monorepo — per-workspace config

Lint is run per workspace (npm run lint -w nextjs). Each workspace has its own eslint.config.js and its own tsconfig. Use the default preset (no projectService); the config runs with that workspace as cwd, so getTsConfigFile() finds that package’s tsconfig.

  • Root package.json: "lint": "npm run lint -w nextjs" (or run each workspace).
  • Workspace (e.g. nextjs/eslint.config.js): use the preset as-is or with createConfig({ ignores: ['.next/**', ...] }).

Single-repo and per-workspace configs do not need projectService.

Scripts

In any setup, add to the package that runs ESLint:

{
  "scripts": {
    "lint": "eslint .",
    "fix": "eslint . --fix"
  }
}

TypeScript

Type-aware rules need a tsconfig.json (or tsconfig.eslint.json) that includes your source. With projectService (monorepo), each file uses the nearest tsconfig. Without it, one tsconfig is used (see typed linting).

TypeScript 7. TypeScript 7 ships no JavaScript API yet, so typescript-eslint runs on the TypeScript 6 API (typescript-eslint#10940). This config depends on it, so a monorepo with TypeScript 7 only inside its workspaces lints as-is. If the package that runs ESLint installs typescript@7 itself, lint crashes. Use the official side-by-side setup instead: tsc stays TypeScript 7 and tsc6 is TypeScript 6.

{
  "devDependencies": {
    "@typescript/native": "npm:typescript@^7.0.2",
    "typescript": "npm:@typescript/typescript6@^6.0.2"
  }
}

Extending

Spread and override:

const { error, warn } = require('@creo-team/eslint-config/constants')
const base = require('@creo-team/eslint-config')
module.exports = [...base, { rules: { 'no-console': warn } }]

Customizing rules

Override any rule by spreading the base config and adding your own. Use constants from @creo-team/eslint-config/constants — no magic strings.

1. Naming convention — allow UPPER_SNAKE for constants

Default: camelCase for variables, PascalCase for types and enum members. To allow UPPER_SNAKE for constants:

const { createConfig } = require('@creo-team/eslint-config')
const { error, FilesPattern, namingConvention } = require('@creo-team/eslint-config/constants')

const base = createConfig()

module.exports = [
  ...base,
  {
    files: FilesPattern.TsAndTsx,
    rules: {
      '@typescript-eslint/naming-convention': [error, ...namingConvention.withUpperCaseVariables],
    },
  },
]

2. File naming — enforce kebab-case for .ts / .tsx files

Install eslint-plugin-unicorn, then add:

const { createConfig } = require('@creo-team/eslint-config')
const { error, FilenameCase, FilesPattern } = require('@creo-team/eslint-config/constants')
const { default: unicorn } = require('eslint-plugin-unicorn') // ESM-only; require(esm) returns the module namespace

const base = createConfig()

module.exports = [
  ...base,
  {
    files: FilesPattern.TsAndTsx,
    plugins: { unicorn },
    rules: {
      'unicorn/filename-case': [error, { case: FilenameCase.KebabCase }],
    },
  },
]

3. Relax JSDoc or no-magic-numbers

const { createConfig } = require('@creo-team/eslint-config')
const { off } = require('@creo-team/eslint-config/constants')

module.exports = [
  ...createConfig(),
  {
    rules: {
      'jsdoc/require-jsdoc': off,
      'no-magic-numbers': off,
    },
  },
]

4. Rule severity and naming constants

Import from @creo-team/eslint-config/constants for consistent, typo-free overrides:

const { createConfig } = require('@creo-team/eslint-config')
const { error, off, warn } = require('@creo-team/eslint-config/constants')

module.exports = [
  ...createConfig(),
  {
    rules: {
      'no-console': warn,
      'jsdoc/require-jsdoc': off,
      'some-rule': [error, { option: true }],
    },
  },
]

5. Custom naming convention — build your own

Use NamingFormat and NamingSelector for full control:

const { createConfig } = require('@creo-team/eslint-config')
const {
  error,
  FilesPattern,
  NamingFormat,
  NamingSelector,
} = require('@creo-team/eslint-config/constants')

const base = createConfig()

module.exports = [
  ...base,
  {
    files: FilesPattern.TsAndTsx,
    rules: {
      '@typescript-eslint/naming-convention': [
        error,
        { format: [NamingFormat.CamelCase], selector: NamingSelector.Default },
        { format: [NamingFormat.PascalCase], selector: NamingSelector.TypeLike },
        { format: [NamingFormat.PascalCase], selector: NamingSelector.EnumMember },
        // ... add more as needed
      ],
    },
  },
]

Examples: See examples/rule-overrides/ for working configs and tests.

Why this config

Predictable, reviewable code. The rules are chosen so that style is decided once (Prettier + stylistic), intent is documented (JSDoc), and structure stays within bounds (complexity, line limits, no magic numbers). That reduces pointless formatting debates and makes diffs easier to read.

Key rules and what they give you:

Rule / areaBenefit
Strict type-checked (typescript-eslint)Catches type errors and unsafe any before runtime. Fewer “works until it doesn’t” bugs
JSDoc (params, returns, descriptions)Public API is self-describing. IDE hints and “go to definition” work without opening the implementation
complexity (max 15)Branches and conditionals stay bounded. Functions stay testable and easier to reason about
max-lines-per-function (200)Long functions get split. Easier to name, test, and reuse
no-magic-numbers (warn)Literals become named constants. Changing a threshold or status code happens in one place
no-promise-executor-returnCatches returning values from Promise executors — always a bug
no-await-in-loop (warn)Flags sequential awaits that should be Promise.all()
no-console (warn)Catches leftover debug logging, especially from AI-generated code
Import rules (no-cycle, order, resolver)No circular deps; consistent import order; TypeScript path resolution works
PrettierOne formatter. No style churn in code review

LLM- and assistant-friendly. Cursor, Claude, and other tools behave better when the codebase is consistent and documented. This config enforces one style (so generated code matches), requires JSDoc on public surfaces (so the model has context), and keeps complexity and magic numbers in check (so suggestions stay in the same style and refactors are local). Use the ESLint MCP server so the assistant can run ESLint and fix violations in your editor.

Optional: lock in project structure

Lock in monorepo workspace dirs and app directory structure. Requires eslint-plugin-project-structure:

npm install eslint-plugin-project-structure --save-dev

Monorepo — lock workspace dirs

Enforce that only nextjs, aws/infra, and shared exist at the root:

const { createConfig } = require('@creo-team/eslint-config')

module.exports = createConfig({
  projectService: true,
  structure: {
    workspaces: ['nextjs', 'aws/infra', 'shared'],
  },
  ignores: ['**/node_modules/**', '**/dist/**', '**/.next/**', '**/cdk.out/**', '**/*.config.*'],
})

Monorepo + app structure

Lock workspaces and enforce app layout (e.g. components, lib, utils) inside the nextjs package:

const { createConfig } = require('@creo-team/eslint-config')

module.exports = createConfig({
  projectService: true,
  structure: {
    workspaces: ['nextjs', 'aws/infra', 'shared'],
    appStructure: 'nextjs',  // preset: app/, components/, lib/, utils/, hooks/, styles/, public/
    appPath: 'nextjs',       // which workspace gets app structure
  },
  ignores: ['**/node_modules/**', '**/dist/**', '**/.next/**', '**/cdk.out/**', '**/*.config.*'],
})

Single repo — app structure only

Enforce structure for a single Next.js app:

const { createConfig } = require('@creo-team/eslint-config')

module.exports = createConfig({
  structure: {
    appStructure: 'nextjs',  // app/, components/, lib/, utils/, hooks/, styles/, public/
  },
  ignores: ['.next/**', 'node_modules/**'],
})

App structure presets

PresetDirs
nextjsapp, components, lib, utils, hooks, styles, public
nextjsAppRouterSame + settings
reactsrc/{components, lib, utils, hooks, styles}, public
expresssrc/{routes, controllers, services, utils, middleware}
srcsrc/{components, lib, utils, settings}

Custom dirs

Pass an array of dir names instead of a preset:

structure: {
  appStructure: ['components', 'lib', 'utils', 'hooks', 'settings'],
}

Constants (@creo-team/eslint-config/constants)

Import rule values and presets — no magic strings:

ExportUse
error, warn, offRule severity
NamingFormatCamelCase, PascalCase, UpperCase
NamingSelectorDefault, Import, Variable, TypeLike, EnumMember
namingConventiondefault, withUpperCaseVariables presets
FilesPatternTsAndTsx — ['**/*.ts', '**/*.tsx']
FilenameCaseKebabCase, CamelCase, PascalCase (unicorn)
AppStructurePresetNextJs, Express, React, etc.

What’s included

  • TypeScript ESLint — recommended + strict type-checked, stylistic
  • Prettier — formatting (tabs, 120 print width, no semicolons)
  • JSDoc — require descriptions, params, returns on declarations/methods (not arrow functions)
  • Import — order, no cycles, resolver TypeScript
  • Perfectionist — alphabetical sort (imports sort disabled)
  • Async correctness — no-promise-executor-return (error), no-await-in-loop (warn)
  • Quality — complexity (max 15), max-lines, max-lines-per-function, no-magic-numbers (warn), no-console (warn)

Docs

Release flow

Trunk-based. Bump version in package.json, push main → github-release creates tag + GitHub Release → npm-publish publishes to npm. OIDC Trusted Publishing, no tokens.

Examples

  • Monorepo: examples/monorepo/ — root config with projectService, npm workspaces. See examples/README.md.
  • Structure: examples/structure/ — lock in workspaces and app dirs with structure option. See examples/structure/README.md.

Development

See CONTRIBUTING.md. Test locally with npm link:

# In eslint-config repo
npm link

# In consuming project
npm link @creo-team/eslint-config

Environment variables (optional):

  • ESLINT_DEBUG — enable debug logging
  • ESLINT_TSCONFIG — override tsconfig file
  • ESLINT_FALLBACK_TSCONFIG — override fallback tsconfig
  • ESLINT_START_DIR — search start directory

License

ISC.

版本与发布记录

@creo-team/eslint-config 共发布 15 个版本,首次发布于 2026/02/21;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
5.0.2latest2026/10/3015 天前
5.0.12026/10/131 个月前
5.0.02026/09/291 个月前
4.0.02026/03/247 个月前
2.5.62026/02/238 个月前
2.5.52026/02/228 个月前

关于 @creo-team/eslint-config 的常见问题

@creo-team/eslint-config 是什么?

ESLint flat config: TypeScript (strict), Prettier, JSDoc, complexity, no-magic-numbers. createConfig() for options.

如何安装 @creo-team/eslint-config?

在项目目录运行 npm install @creo-team/eslint-config,或使用 pnpm add / yarn add / bun add。

@creo-team/eslint-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@creo-team/eslint-config 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@creo-team/eslint-config 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^22.22.2 || >=24.15.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@creo-team/eslint-config 可以商用吗?

@creo-team/eslint-config 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@creo-team/eslint-config 的下载量有多少?

根据 npm 官方下载统计,@creo-team/eslint-config 在 2026/10/11 – 2026/11/09 这 30 天内被下载 2,104 次,日均约 70 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@creo-team/eslint-config 还在维护吗?

最新版本 5.0.2 发布于 2026/10/30(15 天前);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/02/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。