@devenvy/code-guidelines

中文文档
4.0.0发布于 2026/11/11MITTypeScriptES Module构建来源已验证近 30 天下载 4831

DevEnvy code guidelines for JavaScript, TypeScript and Angular: ESLint, Prettier, tsconfig bases and a repo baseline CLI.

原始使用文档
文档目录12 节
  1. Quick start
  2. ESLint
  3. Options
  4. Adding and relaxing rules
  5. What is enforced
  6. Prettier
  7. TypeScript
  8. CLI
  9. Alongside code-guidelines-dotnet
  10. CI and releases
  11. Changes
  12. License

@devenvy/code-guidelines

Shared lint, format, TypeScript, editor and git baseline for DevEnvy JavaScript, TypeScript and Angular repositories. The ECMAScript sibling of code-guidelines-dotnet.

  • ESLint — one createConfig() call: core, typescript-eslint (type-aware), import ordering, angular-eslint (TypeScript + templates) and Vitest, with every rule explicitly decided.
  • Prettier — formatting for everything; ESLint never fights it.
  • tsconfig bases — strict compiler settings for Node, browser, Angular and plain JavaScript.
  • CLI — init sets a repo up, check fails CI on drift or a weakened config, sync updates managed files.

Quick start

# Plain JavaScript (browser)
pnpm add -D --allow-build '!unrs-resolver' @devenvy/code-guidelines eslint prettier knip
pnpm exec code-guidelines init --env browser --no-typescript

# Node / TypeScript
pnpm add -D --allow-build '!unrs-resolver' @devenvy/code-guidelines eslint prettier knip typescript typescript-eslint @types/node
pnpm exec code-guidelines init --env node

# Angular
pnpm add -D --allow-build '!unrs-resolver' @devenvy/code-guidelines eslint prettier knip typescript typescript-eslint angular-eslint
pnpm exec code-guidelines init --angular --prefix app

npm works the same way (npm i -D …, npx code-guidelines …).

--allow-build '!unrs-resolver' records pnpm's decision not to run the install script of unrs-resolver (the import plugin's resolver; its prebuilt binary installs without it). pnpm fails installs while a build script is undecided, so init also sets allowBuilds: unrs-resolver: false in pnpm-workspace.yaml (the workspace root's, for a workspace package) unless it is already true or false, and check requires a decision. A project that uses pnpm's permissions setting decides it there instead, and init and check leave the file alone.

A project installs only the tools for the features it uses. Everything beyond ESLint, Prettier and knip is an optional peer that is loaded only when its feature is on:

FeatureInstall
every projecteslint, prettier, knip
TypeScript (default)typescript, typescript-eslint
Angular (--angular)angular-eslint
Vitest (--vitest)@vitest/eslint-plugin

init prints the install command for any of these that are missing, and turning a feature on without its package fails with the command to run. A plain JavaScript project never needs TypeScript, with one exception: @vitest/eslint-plugin is built on typescript-eslint's utilities, so enabling Vitest brings typescript in as a dependency of that plugin (nothing to configure).

init writes:

FileWhat
eslint.config.mjscreateConfig({...}) with your choices (created if absent)
tsconfig.jsonTypeScript projects: extends @devenvy/code-guidelines/tsconfig/<base>.json; an existing one is migrated and options the base already sets are removed
package.json"prettier" key, scripts (lint, format, format:check, typecheck for TypeScript, knip, guidelines:check, test:ci with --vitest) and a codeGuidelines record of your choices
.nvmrc24 (created if absent)
.editorconfig, .gitattributes, .gitignore, .prettierignorea managed block; your own content outside it is kept
.vscode/extensions.json, .vscode/settings.jsonrecommended extensions and format/fix-on-save keys merged in; your other settings are kept
pnpm-workspace.yamlpnpm projects: allowBuilds decision for unrs-resolver if missing; your other settings are kept

Existing eslint.config.*, .eslintrc*, .prettierrc* or prettier.config.* files stop init before it writes anything. Re-run with --force to replace them.

ESLint

// eslint.config.mjs
import { createConfig } from '@devenvy/code-guidelines/eslint';

export default createConfig(
  {
    rootDir: import.meta.dirname,
    env: 'browser',
    vitest: true,
    angular: { prefix: 'app' },
  },
  // any extra flat configs are appended last
  { files: ['scripts/**'], rules: { 'no-warning-comments': 'error' } },
);

Options

OptionDefault
rootDirrequiredDirectory of the root tsconfig, usually import.meta.dirname
envrequired'browser' or 'node' globals for source files. Root tool configs (*.config.*) always get Node globals
typescripttrueType-aware typescript-eslint for .ts/.mts/.cts. false for plain JavaScript (no TypeScript packages needed)
untypedFiles[]TS files outside every tsconfig (e.g. ['scripts/**']), linted without type information. Root *.config.ts files are always untyped
vitestfalsetrue or { files }. Default files: **/*.{spec,test}.{ts,mts,cts,js,mjs,cjs}
angularfalse{ prefix, controlComponents? }. prefix is a string or array for component/directive selectors. controlComponents lists components that render their own form control, for label association
importOrder.internal[]Extra regex sources treated as internal imports, e.g. ['^@app/']. ^@devenvy/, ^@/ and ^~/ are built in
ignores[]Extra global ignores. dist, coverage, .angular, out-tsc, node_modules and *.min.js are always ignored

Every block is named devenvy/<layer>/<part>; use npx eslint --inspect-config to see exactly what applies to a file.

Adding and relaxing rules

Appended configs may turn on rules the shared config leaves off, or raise a severity. code-guidelines check fails on anything weaker than the shared config (see CLI), so a rule is relaxed only where it is visible in review:

  • one line: // eslint-disable-next-line <rule> -- <reason> (unused disables are errors);
  • generated or vendored files: the ignores option;
  • TypeScript files outside every tsconfig: the untypedFiles option.

What is enforced

The rule tables in src/eslint/rules are the effective configuration: every rule each plugin ships is listed with its severity, and surprising offs carry a reason. A rule a newer plugin version adds stays off in your project until a release of this package decides it. Highlights:

  • Promise safety (no-floating-promises, no-misused-promises, await-thenable), the no-unsafe-* family, no-explicit-any, no-unnecessary-condition, no-deprecated.
  • no-magic-numbers (ignoring -1, 0, 1, array indexes, defaults, enums and readonly class properties); relaxed in tests and root tool configs.
  • Angular: OnPush, signals (prefer-signals, prefer-output-emitter-ref), inject() at the top, control flow, template accessibility. No filename-suffix assumptions: Angular 20+ suffixless files (user-profile.ts) are linted the same as *.component.ts.
  • Imports ordered builtin → external → internal → relative → type, alphabetized; no import cycles (import-x/no-cycle, using the TypeScript resolver).

Only these layers turn rules off: no-undef for TS files, untyped files, test-file relaxations, and eslint-config-prettier (with curly re-enabled).

Prettier

{ "prettier": "@devenvy/code-guidelines/prettier" }

Angular projects use @devenvy/code-guidelines/prettier/angular, which formats every *.html with the Angular parser (Prettier only infers it for *.component.html).

Options: printWidth: 100, singleQuote: true, trailingComma: "all", endOfLine: "lf"; everything else is Prettier's default.

TypeScript

// tsconfig.json
{ "extends": "@devenvy/code-guidelines/tsconfig/node.json", "include": ["src"] }
BaseAdds
base.jsonstrict, noImplicitOverride, noImplicitReturns, noFallthroughCasesInSwitch, noPropertyAccessFromIndexSignature, noUncheckedIndexedAccess, isolatedModules, skipLibCheck, forceConsistentCasingInFileNames, target: ES2022
node.jsonmodule/moduleResolution: nodenext, ES2023, types: ["node"]
browser.jsonmodule: preserve, moduleResolution: bundler, DOM libs
angular.jsonbrowser + experimentalDecorators, importHelpers, and angularCompilerOptions strictTemplates, strictInjectionParameters, strictInputAccessModifiers
js.jsonallowJs, checkJs, noEmit for type-checking plain JavaScript with JSDoc types. Not set up by init: opt in by installing typescript and extending it

TypeScript is ~6.0: typescript-eslint and the Angular compiler do not support TypeScript 7 yet.

CLI

code-guidelines check            # read-only; exit 1 with a diff on any drift
code-guidelines sync --dry-run   # show what sync would change
code-guidelines sync             # rewrite managed blocks and keys from the installed version

Besides the managed blocks and keys, check compares what is actually enforced with this package:

  • ESLint: for every .js/.mjs/.cjs/.ts/.mts/.cts/.html file, the project's resolved config (eslint.config.*, as ESLint loads it) against createConfig with the project's own options. A file the shared config lints must not be ignored, every rule it turns on must stay on at the same or a higher severity with the same options, and its parser, processor and linter options must not be replaced. The options must match the codeGuidelines choices.
  • TypeScript: every tsconfig*.json must extend a packaged base (directly or through other tsconfigs, relative or from a package), and none may turn off a check the base turns on (strict and each flag it implies, noUncheckedIndexedAccess, …, and Angular's strictTemplates family).
  • Prettier: package.json#prettier points at this package and no other Prettier config exists.

What it does not cover: eslint-disable comments (each is visible where it is used, and unused ones fail lint), and whether CI actually runs these scripts.

To change a choice later, edit codeGuidelines in package.json (it selects managed content, such as the Angular VS Code extension) and eslint.config.mjs (it selects lint behaviour), then run code-guidelines sync.

Alongside code-guidelines-dotnet

In a full-stack repo both packages manage .editorconfig. This package only owns its marked block, placed first so later sections (such as [*.cs]) take precedence, and writes root = true only when no root line exists.

CI and releases

Each repo owns its workflows (no shared/reusable workflows). The DevEnvy CI convention, with storm-watch as the reference setup, is described here and not checked: workflows differ per repo, and a static check cannot tell a job that works from one that does nothing.

  • ci.yml (pull requests and a weekly run), one job each:
    • lint: guidelines:check, lint, format:check, typecheck (TypeScript projects), knip (unused files, exports and dependencies), actionlint and zizmor (GitHub Actions security).
    • test: test:ci with coverage thresholds and a PR summary.
    • build, plus repo-specific jobs (e.g. a container smoke test, or package checks).
    • audit: production dependency audit, informational on pull requests.
    • dependency-review: fails a PR that adds a vulnerable dependency or a license outside the allow-list.
    • dependabot-auto-merge, and result, which needs every other job and is the single required status check.
  • scorecard.yml: OpenSSF Scorecard on pushes to main and weekly. Its own workflow because publishing results restricts what else the workflow may contain.
  • codeql.yml: CodeQL on the code and the workflows (actions, javascript-typescript) with the security-and-quality queries, on pull requests, main and weekly. A workflow rather than GitHub's default setup, so the queries and languages are in the repository; the main ruleset requires its results. (Turn the default setup off: GitHub rejects a workflow's results while it is on.)
  • SECURITY.md: supported versions and a link to private vulnerability reporting (enabled in the repository settings).
  • .github/dependabot.yml with a 7-day cooldown.
  • Bot actions (Dependabot auto-merge) run as the devenvy-bot GitHub App — org variable DEVENVY_BOT_CLIENT_ID, org secret DEVENVY_BOT_PRIVATE_KEY, both also as Dependabot secrets — so the merges trigger workflows on main, which GITHUB_TOKEN merges do not. Each token requests only the permissions its step needs.

How a repo publishes is its own choice. The two styles in use, both running CI first and attesting what they publish (build provenance, SPDX SBOM via pnpm sbom):

  • Latest from main (apps, e.g. storm-watch): every push to main deploys the site and pushes the container image as latest and sha-<commit>. Merges in quick succession queue up, so only the newest main deploys after the one in progress. Versioned releases are optional.
  • Releases cut by hand (npm packages, e.g. this one): publishing a GitHub release — gh release create v1.2.0 --target main --generate-notes, or the Releases page — publishes that version (the npm package with its version set from the tag, an image as X.Y.Z and X.Y, release assets).

Coverage needs Vitest's json-summary and json reporters; set thresholds in the test config so the test run itself fails when coverage drops.

Changes

What changed in each version is in the release notes.

License

MIT

版本与发布记录

@devenvy/code-guidelines 共发布 5 个版本,首次发布于 2026/10/13;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.0.0latest2026/11/111 天前
3.0.02026/10/1429 天前
2.0.02026/10/1330 天前
1.0.02026/10/1330 天前
0.0.0-stage2026/10/1330 天前

关于 @devenvy/code-guidelines 的常见问题

@devenvy/code-guidelines 是什么?

DevEnvy code guidelines for JavaScript, TypeScript and Angular: ESLint, Prettier, tsconfig bases and a repo baseline CLI.

如何安装 @devenvy/code-guidelines?

在项目目录运行 npm install @devenvy/code-guidelines,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:knip(^6.41.0)、eslint(^10.12.0)、prettier(^3.9.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 code-guidelines,可以用 npx code-guidelines 直接运行。

@devenvy/code-guidelines 支持 TypeScript 吗?

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

@devenvy/code-guidelines 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@devenvy/code-guidelines 需要什么版本的 Node.js?

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

@devenvy/code-guidelines 可以商用吗?

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

@devenvy/code-guidelines 的下载量有多少?

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

@devenvy/code-guidelines 还在维护吗?

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