node@v1
Hygiene checks for Node.js / npm / pnpm / yarn projects. Adopt it with:
extends: - alint://bundled/node@v1Gated with when: facts.has_node (true if any package.json
exists anywhere in the tree) plus a per-rule
scope_filter: { has_ancestor: package.json } on per-file
content rules so they only apply to files inside a Node package
— useful in polyglot monorepos where Node packages sit
alongside Rust / Python / Go subdirectories. Override
has_node with your own facts: block if you need a different
heuristic (e.g. detect deno.json or bun.lock).
node-package-json-exists
Section titled “node-package-json-exists”- kind:
file_exists - level:
error - when:
facts.has_node
Node project: package.json at the root is required.
node-has-lockfile
Section titled “node-has-lockfile”- kind:
file_exists - level:
warning - when:
facts.has_node - policy: https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json
A lockfile should be committed (package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lock).
node-no-tracked-node-modules
Section titled “node-no-tracked-node-modules”- kind:
dir_absent - level:
error - when:
facts.has_node
node_modules/must not be committed; add it to .gitignore.
node-no-tracked-dist
Section titled “node-no-tracked-dist”- kind:
dir_absent - level:
info - when:
facts.has_node
Build-output directories shouldn’t be tracked. Set
level: offif this one is intentionally shipped.
node-engine-or-nvmrc
Section titled “node-engine-or-nvmrc”- kind:
file_exists - level:
info - when:
facts.has_node
Pin the Node.js version with
.nvmrc,.node-version, or.tool-versionsso local and CI installs match.
node-sources-final-newline
Section titled “node-sources-final-newline”- kind:
final_newline - level:
info - when:
facts.has_node
node-sources-no-trailing-whitespace
Section titled “node-sources-no-trailing-whitespace”- kind:
no_trailing_whitespace - level:
info - when:
facts.has_node
node-sources-no-bidi
Section titled “node-sources-no-bidi”- kind:
no_bidi_controls - level:
error - when:
facts.has_node - policy: https://trojansource.codes/
Trojan Source (CVE-2021-42574): bidi override chars are rejected in JS/TS sources.
Source
Section titled “Source”The full ruleset definition is committed at crates/alint-dsl/rulesets/v1/node.yml in the alint repo (the snapshot below is generated verbatim from that file).
# alint://bundled/node@v1## Hygiene checks for Node.js / npm / pnpm / yarn projects. Adopt# it with:## extends:# - alint://bundled/node@v1## Gated with `when: facts.has_node` (true if any `package.json`# exists anywhere in the tree) plus a per-rule# `scope_filter: { has_ancestor: package.json }` on per-file# content rules so they only apply to files inside a Node package# — useful in polyglot monorepos where Node packages sit# alongside Rust / Python / Go subdirectories. Override# `has_node` with your own `facts:` block if you need a different# heuristic (e.g. detect `deno.json` or `bun.lock`).
version: 1
facts: - id: has_node any_file_exists: [package.json, "**/package.json"]
rules: # --- Manifest + lockfiles ----------------------------------------- - id: node-package-json-exists when: facts.has_node kind: file_exists paths: package.json root_only: true level: error message: "Node project: package.json at the root is required."
- id: node-has-lockfile when: facts.has_node # Accept any of the four common lockfiles — npm, pnpm, yarn, # bun. At least one should be committed for reproducible installs. kind: file_exists paths: - "package-lock.json" - "pnpm-lock.yaml" - "yarn.lock" - "bun.lock" - "bun.lockb" root_only: true level: warning message: "A lockfile should be committed (package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lock)." policy_url: "https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json"
# --- Build artefacts must not be tracked -------------------------- - id: node-no-tracked-node-modules when: facts.has_node kind: dir_absent paths: "**/node_modules" level: error message: "`node_modules/` must not be committed; add it to .gitignore."
- id: node-no-tracked-dist when: facts.has_node # Common build-output directory names. Users with legitimate # reasons to ship a built `dist/` (e.g. a typed-package # preview) can set this rule's `level: off`. # # v0.9.18: gated on `has_ancestor: package.json` to scope the # check per-JS-package — without this gate the rule fires on # every `dist/` repo-wide once any `package.json` exists, which # causes false positives in polyglot monorepos (Rust crate # source dirs named `dist/`, etc.). kind: dir_absent paths: ["**/dist", "**/.next", "**/.nuxt", "**/coverage", "**/.turbo"] scope_filter: has_ancestor: package.json level: info message: >- Build-output directories shouldn't be tracked. Set `level: off` if this one is intentionally shipped.
# --- Node version pinning ---------------------------------------- - id: node-engine-or-nvmrc when: facts.has_node kind: file_exists paths: [".nvmrc", ".node-version", ".tool-versions"] root_only: true level: info message: >- Pin the Node.js version with `.nvmrc`, `.node-version`, or `.tool-versions` so local and CI installs match.
# --- Source-file hygiene on JS / TS sources ----------------------- - id: node-sources-final-newline when: facts.has_node kind: final_newline paths: ["src/**/*.{js,jsx,ts,tsx,mjs,cjs}", "lib/**/*.{js,jsx,ts,tsx,mjs,cjs}"] scope_filter: has_ancestor: package.json level: info fix: file_append_final_newline: {}
- id: node-sources-no-trailing-whitespace when: facts.has_node kind: no_trailing_whitespace paths: ["src/**/*.{js,jsx,ts,tsx,mjs,cjs}", "lib/**/*.{js,jsx,ts,tsx,mjs,cjs}"] scope_filter: has_ancestor: package.json level: info fix: file_trim_trailing_whitespace: {}
- id: node-sources-no-bidi when: facts.has_node kind: no_bidi_controls paths: ["src/**/*.{js,jsx,ts,tsx,mjs,cjs}", "lib/**/*.{js,jsx,ts,tsx,mjs,cjs}"] scope_filter: has_ancestor: package.json level: error message: "Trojan Source (CVE-2021-42574): bidi override chars are rejected in JS/TS sources." policy_url: "https://trojansource.codes/"