@hyperfrontend/versioning/commits/validatevalidate/
Pure rule engine for commit-message validation.
Overview
Runs a configurable ruleset over a parsed ConventionalCommit and returns a structured ValidationResult containing warn-level and error-level messages. Mirrors the semantics of @commitlint/config-conventional's baseline but is bundled with @hyperfrontend/versioning and TTY-free.
The same engine powers three consumers:
- Inline step validators during interactive authoring (
commits/author/). - Preview-step warnings that render before the user confirms a commit.
- The out-of-band
clbin wired into.git/hooks/commit-msg.
Usage
Validate a parsed commit
import { parseConventionalCommit, validateCommit, conventionalPreset } from '@hyperfrontend/versioning'
const commit = parseConventionalCommit('feat: add login')
const result = validateCommit(commit, conventionalPreset)
result.valid // true
result.warnings // []
result.errors // []
Validate a raw message (for the cl bin)
import { validateCommitMessage, conventionalPreset } from '@hyperfrontend/versioning'
const result = validateCommitMessage('feat: added login', conventionalPreset)
result.valid // true — `imperative-mood` is a warning, not an error
result.warnings // [{ level: 'warn', ruleName: 'imperative-mood', message: '...' }]
Extend the preset
import type { Ruleset } from '@hyperfrontend/versioning'
import { conventionalPreset } from '@hyperfrontend/versioning'
const dogfoodRuleset: Ruleset = {
...conventionalPreset,
'subject-case': ['off'],
'header-max-length': ['warn', { maxLength: 72 }],
}
Authoring New Rules
- Create
rules/<name>.tsexporting aRule<YourOptions>whosecheck()returns a list of violation strings. - Register it in
rules/index.tsand inBUILT_IN_RULESinside engine.ts. - Write a colocated
.spec.tscovering: happy path, each failure branch, theoff/empty-options pass-through paths. - If it should ship in the default preset, add it to presets/conventional.ts.
The engine is intentionally dumb about rule semantics — rules own both the check and the message wording. Keep messages specific enough to act on ('type must be one of [feat, fix] but was "wip"', not 'invalid type').
See Also
- ../README.md — Parsing primitives this engine consumes
API Reference
ƒ Functions
Runs every rule configured in the ruleset against a parsed commit and aggregates the resulting warnings and errors.
Rules whose config is
Rules whose config is
'off' (or absent from the ruleset) are skipped. Unknown rule names in the ruleset are ignored — consumers extend the engine by calling validateCommitWithRules() and supplying additional rules.Parameters
Returns
ValidationResultAggregated validation result
Example
Validating a commit against a preset ruleset
validateCommit(parseConventionalCommit('feat: add login'), conventionalPreset)
// => { valid: true, warnings: [], errors: [] }Parses a raw commit message and validates the resulting commit against the supplied ruleset. Used by the
cl bin and anywhere else validation must start from a string rather than a parsed commit.Parameters
Returns
ValidationResultAggregated validation result
Example
Validating a raw commit message
validateCommitMessage('feat: add login', conventionalPreset)
// => { valid: true, warnings: [], errors: [] }
validateCommitMessage('feat: added login', conventionalPreset).warnings
// => [{ level: 'warn', ruleName: 'imperative-mood', message: ... }]§function
validateCommitWithRules(commit: ConventionalCommit, ruleset: Ruleset, rules: Readonly<Record<string, Rule<never>>>): ValidationResult
Variant of
validateCommit that accepts a caller-supplied rule registry. Useful for consumers that want to add project-specific rules without forking the built-in set.Parameters
Returns
ValidationResultAggregated validation result
Example
Extending the built-in rules with a custom rule
const customRules = { ...BUILT_IN_RULES, 'no-wip': noWipRule }
validateCommitWithRules(commit, { 'no-wip': ['error'] }, customRules)◈ Interfaces
Options for the header-max-length rule.
Properties
Options for the imperative-mood rule.
Properties
§
readonly wordlist?:Readonly<Record<string, string>>— Map of past-tense words (lowercase) to their suggested imperative forms. Overrides
DEFAULT_IMPERATIVE_WORDLIST when provided.Pure rule definition. Implementations inspect a
ConventionalCommit and return zero or more violation messages. The engine applies severity from the ruleset config and aggregates RuleMessages across all rules.Properties
Runtime context passed to a rule invocation.
A single violation reported by the engine, tagged with its effective severity.
Options for the scope-enum rule.
Properties
Options for the subject-case rule.
Properties
§
readonly cases:unknown— One or more accepted case forms. A subject passing any accepted form is valid.
Options for the type-enum rule.
Properties
◆ Types
Configuration tuple for a single rule in a ruleset.
A bare
A bare
[level] entry disables the rule when level is 'off', or enables it with no options otherwise. The [level, options] form passes rule-specific options through to the rule's check() implementation.type RuleConfig = unknown | unknownAggregated list of violations produced by the engine for a single ruleset run.
type RuleResult = unknownMapping from rule name to its config tuple. Rules not present in the map are treated as
'off' by the engine.type Ruleset = Readonly<Record<string, RuleConfig>>Supported subject-case modes.
type SubjectCase = "sentence-case" | "lower-case" | "upper-case" | "kebab-case" | "snake-case" | "start-case"● Variables
Registry of built-in rules the engine knows how to run, keyed by rule name.
Conventional Commits default type enum used by the preset.
Default ruleset mirroring
| Rule | Level | Options | | ------------------ | ----- | ------------------------ | | type-enum | error |
@commitlint/config-conventional's baseline. | Rule | Level | Options | | ------------------ | ----- | ------------------------ | | type-enum | error |
CONVENTIONAL_TYPES | | subject-empty | error | — | | scope-enum | off | — | | subject-case | off | — | | header-max-length | warn | { maxLength: 72 } | | imperative-mood | warn | — |Default past-tense → imperative word map used when options are omitted.
Rule that fails when the reconstructed header (
type(scope)!: subject) exceeds the configured maximum length.Rule that reports a warning when the first subject word (case-insensitive) matches a known past-tense form. Never blocks; intended as a nudge.
Rule that fails when any scope on the commit is not in the configured allow-list. A commit with no scopes (empty array) always passes; when scopes are required, pair this rule with a separate scope-empty check.
Rule that fails when the commit subject does not match any of the configured case forms. An empty subject always passes (handled by subject-empty).
Rule that fails when the commit subject is empty or whitespace-only.
Rule that fails when the commit type is not in the configured allow-list.