diff --git a/@commitlint/ensure/package.json b/@commitlint/ensure/package.json index 9a5b2fc3b6..2b46a02b31 100644 --- a/@commitlint/ensure/package.json +++ b/@commitlint/ensure/package.json @@ -38,6 +38,7 @@ "globby": "11.0.0" }, "dependencies": { + "@commitlint/types": "^8.3.4", "lodash": "^4.17.15" } } diff --git a/@commitlint/ensure/src/case.ts b/@commitlint/ensure/src/case.ts index cb72e18633..13701efde5 100644 --- a/@commitlint/ensure/src/case.ts +++ b/@commitlint/ensure/src/case.ts @@ -3,7 +3,7 @@ import kebabCase from 'lodash/kebabCase'; import snakeCase from 'lodash/snakeCase'; import upperFirst from 'lodash/upperFirst'; import startCase from 'lodash/startCase'; -import {TargetCaseType} from '.'; +import {TargetCaseType} from '@commitlint/types'; export default ensureCase; diff --git a/@commitlint/ensure/src/index.ts b/@commitlint/ensure/src/index.ts index 45db1238f8..982e128525 100644 --- a/@commitlint/ensure/src/index.ts +++ b/@commitlint/ensure/src/index.ts @@ -5,7 +5,6 @@ import maxLineLength from './max-line-length'; import minLength from './min-length'; import notEmpty from './not-empty'; -export * from './types'; export {ensureCase as case}; export {ensureEnum as enum}; export {maxLength, maxLineLength, minLength, notEmpty}; diff --git a/@commitlint/ensure/tsconfig.json b/@commitlint/ensure/tsconfig.json index 36dcb6ac74..84537266e0 100644 --- a/@commitlint/ensure/tsconfig.json +++ b/@commitlint/ensure/tsconfig.json @@ -6,5 +6,6 @@ "outDir": "./lib" }, "include": ["./src/**/*.ts"], - "exclude": ["./src/**/*.test.ts", "./lib/**/*"] + "exclude": ["./src/**/*.test.ts", "./lib/**/*"], + "references": [{ "path": "../types" }] } diff --git a/@commitlint/is-ignored/package.json b/@commitlint/is-ignored/package.json index 3ecf9a1d97..5662e358dd 100644 --- a/@commitlint/is-ignored/package.json +++ b/@commitlint/is-ignored/package.json @@ -40,6 +40,7 @@ "@types/semver": "7.1.0" }, "dependencies": { + "@commitlint/types": "^8.3.4", "semver": "7.1.2" } } diff --git a/@commitlint/is-ignored/src/defaults.ts b/@commitlint/is-ignored/src/defaults.ts index bf3e9aab1e..59a5884922 100644 --- a/@commitlint/is-ignored/src/defaults.ts +++ b/@commitlint/is-ignored/src/defaults.ts @@ -1,5 +1,5 @@ import * as semver from 'semver'; -import {Matcher} from './types'; +import {Matcher} from '@commitlint/types'; const isSemver = (c: string): boolean => { const firstLine = c.split('\n').shift(); diff --git a/@commitlint/is-ignored/src/index.ts b/@commitlint/is-ignored/src/index.ts index d5d119ef9e..9d279861bd 100644 --- a/@commitlint/is-ignored/src/index.ts +++ b/@commitlint/is-ignored/src/index.ts @@ -1,2 +1,2 @@ export * from './is-ignored'; -export * from './types'; +export {default} from './is-ignored'; diff --git a/@commitlint/is-ignored/src/is-ignored.ts b/@commitlint/is-ignored/src/is-ignored.ts index 85646b9885..42ba3c8cc0 100644 --- a/@commitlint/is-ignored/src/is-ignored.ts +++ b/@commitlint/is-ignored/src/is-ignored.ts @@ -1,10 +1,5 @@ import {wildcards} from './defaults'; -import {Matcher} from './types'; - -export interface IsIgnoredOptions { - ignores?: Matcher[]; - defaults?: boolean; -} +import {IsIgnoredOptions} from '@commitlint/types'; export default function isIgnored( commit: string = '', diff --git a/@commitlint/is-ignored/src/types.ts b/@commitlint/is-ignored/src/types.ts deleted file mode 100644 index b65554ca37..0000000000 --- a/@commitlint/is-ignored/src/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type Matcher = (commit: string) => boolean; diff --git a/@commitlint/is-ignored/tsconfig.json b/@commitlint/is-ignored/tsconfig.json index f3d0083154..a561833c69 100644 --- a/@commitlint/is-ignored/tsconfig.json +++ b/@commitlint/is-ignored/tsconfig.json @@ -11,5 +11,6 @@ "exclude": [ "./src/**/*.test.ts", "./lib/**/*" - ] + ], + "references": [{"path": "../types"}] } diff --git a/@commitlint/lint/package.json b/@commitlint/lint/package.json index 02bd18f270..89bd869fdf 100644 --- a/@commitlint/lint/package.json +++ b/@commitlint/lint/package.json @@ -2,21 +2,14 @@ "name": "@commitlint/lint", "version": "8.3.5", "description": "Lint a string against commitlint rules", - "main": "lib/index.js", + "main": "lib/lint.js", + "types": "lib/lint.d.ts", "files": [ "lib/" ], "scripts": { - "build": "cross-env NODE_ENV=production babel src --out-dir lib --source-maps", "deps": "dep-check", - "pkg": "pkg-check --skip-import", - "start": "yarn run watch", - "watch": "babel src --out-dir lib --watch --source-maps" - }, - "babel": { - "presets": [ - "babel-preset-commitlint" - ] + "pkg": "pkg-check --skip-import" }, "engines": { "node": ">=4" @@ -53,6 +46,7 @@ "@commitlint/is-ignored": "^8.3.5", "@commitlint/parse": "^8.3.4", "@commitlint/rules": "^8.3.4", + "@commitlint/types": "^8.3.4", "lodash": "^4.17.15" } } diff --git a/@commitlint/lint/src/commit-message.ts b/@commitlint/lint/src/commit-message.ts new file mode 100644 index 0000000000..e27cdc82e3 --- /dev/null +++ b/@commitlint/lint/src/commit-message.ts @@ -0,0 +1,18 @@ +export interface CommitMessageData { + header: string; + body?: string | null; + footer?: string | null; +} + +export const buildCommitMesage = ({ + header, + body, + footer +}: CommitMessageData): string => { + let message = header; + + message = body ? `${message}\n\n${body}` : message; + message = footer ? `${message}\n\n${footer}` : message; + + return message; +}; diff --git a/@commitlint/lint/src/index.test.js b/@commitlint/lint/src/lint.test.ts similarity index 94% rename from @commitlint/lint/src/index.test.js rename to @commitlint/lint/src/lint.test.ts index 60dbc6d37b..c8ff6cc123 100644 --- a/@commitlint/lint/src/index.test.js +++ b/@commitlint/lint/src/lint.test.ts @@ -1,12 +1,12 @@ -import lint from '.'; +import lint from './lint'; test('throws without params', async () => { - const error = lint(); + const error = (lint as any)(); await expect(error).rejects.toThrow('Expected a raw commit'); }); test('throws with empty message', async () => { - const error = lint(''); + const error = (lint as any)(''); await expect(error).rejects.toThrow('Expected a raw commit'); }); @@ -91,7 +91,7 @@ test('throws for invalid rule config', async () => { const error = lint('type(scope): foo', { 'type-enum': 1, 'scope-enum': {0: 2, 1: 'never', 2: ['foo'], length: 3} - }); + } as any); await expect(error).rejects.toThrow('type-enum must be array'); await expect(error).rejects.toThrow('scope-enum must be array'); @@ -109,15 +109,15 @@ test('allows disable shorthand', async () => { }); test('throws for rule with invalid length', async () => { - const error = lint('type(scope): foo', {'scope-enum': [1, 2, 3, 4]}); + const error = lint('type(scope): foo', {'scope-enum': [1, 2, 3, 4]} as any); await expect(error).rejects.toThrow('scope-enum must be 2 or 3 items long'); }); test('throws for rule with invalid level', async () => { const error = lint('type(scope): foo', { - 'type-enum': ['2', 'always'], - 'header-max-length': [{}, 'always'] + 'type-enum': ['2', 'always'] as any, + 'header-max-length': [{}, 'always'] as any }); await expect(error).rejects.toThrow('rule type-enum must be number'); await expect(error).rejects.toThrow('rule header-max-length must be number'); @@ -137,8 +137,8 @@ test('throws for rule with out of range level', async () => { test('throws for rule with invalid condition', async () => { const error = lint('type(scope): foo', { - 'type-enum': [1, 2], - 'header-max-length': [1, {}] + 'type-enum': [1, 2] as any, + 'header-max-length': [1, {}] as any }); await expect(error).rejects.toThrow('type-enum must be string'); @@ -147,8 +147,8 @@ test('throws for rule with invalid condition', async () => { test('throws for rule with out of range condition', async () => { const error = lint('type(scope): foo', { - 'type-enum': [1, 'foo'], - 'header-max-length': [1, 'bar'] + 'type-enum': [1, 'foo'] as any, + 'header-max-length': [1, 'bar'] as any }); await expect(error).rejects.toThrow('type-enum must be "always" or "never"'); diff --git a/@commitlint/lint/src/index.js b/@commitlint/lint/src/lint.ts similarity index 64% rename from @commitlint/lint/src/index.js rename to @commitlint/lint/src/lint.ts index 5a352fa4d1..fb3985734b 100644 --- a/@commitlint/lint/src/index.js +++ b/@commitlint/lint/src/lint.ts @@ -1,20 +1,29 @@ import util from 'util'; import isIgnored from '@commitlint/is-ignored'; import parse from '@commitlint/parse'; -import implementations from '@commitlint/rules'; +import defaultRules from '@commitlint/rules'; import toPairs from 'lodash/toPairs'; import values from 'lodash/values'; +import {buildCommitMesage} from './commit-message'; +import { + LintRuleConfig, + LintOptions, + LintRuleOutcome, + Rule, + Plugin, + RuleSeverity +} from '@commitlint/types'; + +export default async function lint( + message: string, + rawRulesConfig?: LintRuleConfig, + rawOpts?: LintOptions +) { + const opts = rawOpts + ? rawOpts + : {defaultIgnores: undefined, ignores: undefined}; + const rulesConfig = rawRulesConfig || {}; -const buildCommitMesage = ({header, body, footer}) => { - let message = header; - - message = body ? `${message}\n\n${body}` : message; - message = footer ? `${message}\n\n${footer}` : message; - - return message; -}; - -export default async (message, rules = {}, opts = {}) => { // Found a wildcard match, skip if ( isIgnored(message, {defaults: opts.defaultIgnores, ignores: opts.ignores}) @@ -29,25 +38,27 @@ export default async (message, rules = {}, opts = {}) => { // Parse the commit message const parsed = await parse(message, undefined, opts.parserOpts); + const allRules: Map | Rule> = new Map( + Object.entries(defaultRules) + ); - const mergedImplementations = Object.assign({}, implementations); if (opts.plugins) { - values(opts.plugins).forEach(plugin => { + values(opts.plugins).forEach((plugin: Plugin) => { if (plugin.rules) { - Object.keys(plugin.rules).forEach(ruleKey => { - mergedImplementations[ruleKey] = plugin.rules[ruleKey]; - }); + Object.keys(plugin.rules).forEach(ruleKey => + allRules.set(ruleKey, plugin.rules[ruleKey]) + ); } }); } // Find invalid rules configs - const missing = Object.keys(rules).filter( - name => typeof mergedImplementations[name] !== 'function' + const missing = Object.keys(rulesConfig).filter( + name => typeof allRules.get(name) !== 'function' ); if (missing.length > 0) { - const names = Object.keys(mergedImplementations); + const names = [...allRules.keys()]; throw new RangeError( `Found invalid rule names: ${missing.join( ', ' @@ -55,7 +66,7 @@ export default async (message, rules = {}, opts = {}) => { ); } - const invalid = toPairs(rules) + const invalid = toPairs(rulesConfig) .map(([name, config]) => { if (!Array.isArray(config)) { return new Error( @@ -65,7 +76,13 @@ export default async (message, rules = {}, opts = {}) => { ); } - const [level, when] = config; + const [level] = config; + + if (level === RuleSeverity.Disabled && config.length === 1) { + return null; + } + + const [, when] = config; if (typeof level !== 'number' || isNaN(level)) { return new Error( @@ -75,10 +92,6 @@ export default async (message, rules = {}, opts = {}) => { ); } - if (level === 0 && config.length === 1) { - return null; - } - if (config.length !== 2 && config.length !== 3) { return new Error( `config for rule ${name} must be 2 or 3 items long, received ${util.inspect( @@ -113,18 +126,15 @@ export default async (message, rules = {}, opts = {}) => { return null; }) - .filter(item => item instanceof Error); + .filter((item): item is Error => item instanceof Error); if (invalid.length > 0) { throw new Error(invalid.map(i => i.message).join('\n')); } // Validate against all rules - const results = toPairs(rules) - .filter(entry => { - const [, [level]] = toPairs(entry); - return level > 0; - }) + const results = toPairs(rulesConfig) + .filter(([, [level]]) => level > 0) .map(entry => { const [name, config] = entry; const [level, when, value] = config; @@ -134,9 +144,14 @@ export default async (message, rules = {}, opts = {}) => { return null; } - const rule = mergedImplementations[name]; + const rule = allRules.get(name); + + if (!rule) { + throw new Error(`Could not find rule implementation for ${name}`); + } - const [valid, message] = rule(parsed, when, value); + const executableRule = rule as Rule; + const [valid, message] = executableRule(parsed, when, value); return { level, @@ -145,7 +160,7 @@ export default async (message, rules = {}, opts = {}) => { message }; }) - .filter(Boolean); + .filter((result): result is LintRuleOutcome => result !== null); const errors = results.filter(result => result.level === 2 && !result.valid); const warnings = results.filter( @@ -160,4 +175,4 @@ export default async (message, rules = {}, opts = {}) => { warnings, input: buildCommitMesage(parsed) }; -}; +} diff --git a/@commitlint/lint/tsconfig.json b/@commitlint/lint/tsconfig.json new file mode 100644 index 0000000000..7b8a9e3c44 --- /dev/null +++ b/@commitlint/lint/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "outDir": "./lib" + }, + "include": [ + "./src" + ], + "exclude": [ + "./src/**/*.test.ts", + "./lib/**/*" + ], + "references": [ + {"path": "../is-ignored"}, + {"path": "../parse"}, + {"path": "../rules"}, + {"path": "../types"} + ] +} diff --git a/@commitlint/load/package.json b/@commitlint/load/package.json index 76f2c6cfdb..58c82f4617 100644 --- a/@commitlint/load/package.json +++ b/@commitlint/load/package.json @@ -41,6 +41,7 @@ "dependencies": { "@commitlint/execute-rule": "^8.3.4", "@commitlint/resolve-extends": "^8.3.5", + "@commitlint/types": "^8.3.5", "chalk": "3.0.0", "cosmiconfig": "^6.0.0", "lodash": "^4.17.15", diff --git a/@commitlint/load/src/load.ts b/@commitlint/load/src/load.ts index 14cbdf7d94..7f03536529 100644 --- a/@commitlint/load/src/load.ts +++ b/@commitlint/load/src/load.ts @@ -8,8 +8,6 @@ import resolveFrom from 'resolve-from'; import executeRule from '@commitlint/execute-rule'; import resolveExtends from '@commitlint/resolve-extends'; - -import loadPlugin from './utils/loadPlugin'; import { UserConfig, LoadOptions, @@ -17,7 +15,9 @@ import { UserPreset, QualifiedRules, ParserPreset -} from './types'; +} from '@commitlint/types'; + +import loadPlugin from './utils/load-plugin'; import {loadConfig} from './utils/load-config'; import {loadParserOpts} from './utils/load-parser-opts'; import {pickConfig} from './utils/pick-config'; diff --git a/@commitlint/load/src/utils/loadPlugin.test.ts b/@commitlint/load/src/utils/load-plugin.test.ts similarity index 98% rename from @commitlint/load/src/utils/loadPlugin.test.ts rename to @commitlint/load/src/utils/load-plugin.test.ts index 49f074b3c7..65c1fe9cae 100644 --- a/@commitlint/load/src/utils/loadPlugin.test.ts +++ b/@commitlint/load/src/utils/load-plugin.test.ts @@ -1,4 +1,4 @@ -import loadPlugin from './loadPlugin'; +import loadPlugin from './load-plugin'; jest.mock('commitlint-plugin-example', () => ({example: true}), { virtual: true diff --git a/@commitlint/load/src/utils/loadPlugin.ts b/@commitlint/load/src/utils/load-plugin.ts similarity index 93% rename from @commitlint/load/src/utils/loadPlugin.ts rename to @commitlint/load/src/utils/load-plugin.ts index 724f2f7ebc..742a4e6cd5 100644 --- a/@commitlint/load/src/utils/loadPlugin.ts +++ b/@commitlint/load/src/utils/load-plugin.ts @@ -1,8 +1,8 @@ import path from 'path'; import chalk from 'chalk'; -import {normalizePackageName, getShorthandName} from './pluginNaming'; -import {WhitespacePluginError, MissingPluginError} from './pluginErrors'; -import {PluginRecords} from '../types'; +import {normalizePackageName, getShorthandName} from './plugin-naming'; +import {WhitespacePluginError, MissingPluginError} from './plugin-errors'; +import {PluginRecords} from '@commitlint/types'; export default function loadPlugin( plugins: PluginRecords, diff --git a/@commitlint/load/src/utils/pick-config.ts b/@commitlint/load/src/utils/pick-config.ts index ce7187a706..881db12103 100644 --- a/@commitlint/load/src/utils/pick-config.ts +++ b/@commitlint/load/src/utils/pick-config.ts @@ -1,4 +1,4 @@ -import {UserConfig} from '../types'; +import {UserConfig} from '@commitlint/types'; import pick from 'lodash/pick'; export const pickConfig = (input: unknown): UserConfig => diff --git a/@commitlint/load/src/utils/pluginErrors.ts b/@commitlint/load/src/utils/plugin-errors.ts similarity index 100% rename from @commitlint/load/src/utils/pluginErrors.ts rename to @commitlint/load/src/utils/plugin-errors.ts diff --git a/@commitlint/load/src/utils/pluginNaming.ts b/@commitlint/load/src/utils/plugin-naming.ts similarity index 100% rename from @commitlint/load/src/utils/pluginNaming.ts rename to @commitlint/load/src/utils/plugin-naming.ts diff --git a/@commitlint/load/tsconfig.json b/@commitlint/load/tsconfig.json index 08efe81993..baa69a842d 100644 --- a/@commitlint/load/tsconfig.json +++ b/@commitlint/load/tsconfig.json @@ -14,6 +14,7 @@ ], "references": [ { "path": "../execute-rule" }, - { "path": "../resolve-extends" } + { "path": "../resolve-extends" }, + { "path": "../types" } ] } diff --git a/@commitlint/parse/src/index.ts b/@commitlint/parse/src/index.ts index 9834946b57..8074362dc2 100644 --- a/@commitlint/parse/src/index.ts +++ b/@commitlint/parse/src/index.ts @@ -1,12 +1,11 @@ import mergeWith from 'lodash/mergeWith'; import isArray from 'lodash/isArray'; -import {Commit, Parser, ParserOptions} from './types'; +import {Commit, Parser, ParserOptions} from '@commitlint/types'; const {sync} = require('conventional-commits-parser'); const defaultChangelogOpts = require('conventional-changelog-angular'); export default parse; -export * from './types'; async function parse( message: string, diff --git a/@commitlint/parse/tsconfig.json b/@commitlint/parse/tsconfig.json index f4a57643f0..ffd5b0f116 100644 --- a/@commitlint/parse/tsconfig.json +++ b/@commitlint/parse/tsconfig.json @@ -1,15 +1,11 @@ { - "extends": "../../tsconfig.shared.json", - "compilerOptions": { - "composite": true, - "rootDir": "./src", - "outDir": "./lib" - }, - "include": [ - "./src" - ], - "exclude": [ - "./src/**/*.test.ts", - "./lib/**/*" - ] + "extends": "../../tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "outDir": "./lib" + }, + "include": ["./src"], + "exclude": ["./src/**/*.test.ts", "./lib/**/*"], + "references": [{"path": "../types"}] } diff --git a/@commitlint/rules/package.json b/@commitlint/rules/package.json index 07edd0a709..cff30083a6 100644 --- a/@commitlint/rules/package.json +++ b/@commitlint/rules/package.json @@ -44,7 +44,7 @@ "dependencies": { "@commitlint/ensure": "^8.3.4", "@commitlint/message": "^8.3.4", - "@commitlint/parse": "^8.3.4", - "@commitlint/to-lines": "^8.3.4" + "@commitlint/to-lines": "^8.3.4", + "@commitlint/types": "^8.3.4" } } diff --git a/@commitlint/rules/src/body-case.ts b/@commitlint/rules/src/body-case.ts index cef24f86a3..62473783b9 100644 --- a/@commitlint/rules/src/body-case.ts +++ b/@commitlint/rules/src/body-case.ts @@ -1,8 +1,8 @@ -import * as ensure from '@commitlint/ensure'; +import {case as ensureCase} from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {TargetCaseType, Rule} from '@commitlint/types'; -export const bodyCase: Rule = ( +export const bodyCase: Rule = ( parsed, when = 'always', value = undefined @@ -15,7 +15,7 @@ export const bodyCase: Rule = ( const negated = when === 'never'; - const result = ensure.case(body, value); + const result = ensureCase(body, value); return [ negated ? !result : result, message([`body must`, negated ? `not` : null, `be ${value}`]) diff --git a/@commitlint/rules/src/body-empty.ts b/@commitlint/rules/src/body-empty.ts index 8df58844ae..571563bc9c 100644 --- a/@commitlint/rules/src/body-empty.ts +++ b/@commitlint/rules/src/body-empty.ts @@ -1,6 +1,6 @@ import * as ensure from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const bodyEmpty: Rule = (parsed, when = 'always') => { const negated = when === 'never'; diff --git a/@commitlint/rules/src/body-leading-blank.ts b/@commitlint/rules/src/body-leading-blank.ts index 447557b0ff..0b6bdf1d4b 100644 --- a/@commitlint/rules/src/body-leading-blank.ts +++ b/@commitlint/rules/src/body-leading-blank.ts @@ -1,6 +1,6 @@ import toLines from '@commitlint/to-lines'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const bodyLeadingBlank: Rule = (parsed, when) => { // Flunk if no body is found diff --git a/@commitlint/rules/src/body-max-length.ts b/@commitlint/rules/src/body-max-length.ts index 995f29cb11..bc0cc81df3 100644 --- a/@commitlint/rules/src/body-max-length.ts +++ b/@commitlint/rules/src/body-max-length.ts @@ -1,5 +1,5 @@ import {maxLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const bodyMaxLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/body-max-line-length.ts b/@commitlint/rules/src/body-max-line-length.ts index 83019ca195..2746993a97 100644 --- a/@commitlint/rules/src/body-max-line-length.ts +++ b/@commitlint/rules/src/body-max-line-length.ts @@ -1,5 +1,5 @@ import {maxLineLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const bodyMaxLineLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/body-min-length.ts b/@commitlint/rules/src/body-min-length.ts index c554746e5d..3b50e6c4dc 100644 --- a/@commitlint/rules/src/body-min-length.ts +++ b/@commitlint/rules/src/body-min-length.ts @@ -1,5 +1,5 @@ import {minLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const bodyMinLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/footer-empty.ts b/@commitlint/rules/src/footer-empty.ts index 1f4ac03021..810001e8a5 100644 --- a/@commitlint/rules/src/footer-empty.ts +++ b/@commitlint/rules/src/footer-empty.ts @@ -1,6 +1,6 @@ import * as ensure from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const footerEmpty: Rule = (parsed, when = 'always') => { const negated = when === 'never'; diff --git a/@commitlint/rules/src/footer-leading-blank.ts b/@commitlint/rules/src/footer-leading-blank.ts index e4bb637842..094ba93c30 100644 --- a/@commitlint/rules/src/footer-leading-blank.ts +++ b/@commitlint/rules/src/footer-leading-blank.ts @@ -1,6 +1,6 @@ import toLines from '@commitlint/to-lines'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const footerLeadingBlank: Rule = (parsed, when = 'always') => { // Flunk if no footer is found diff --git a/@commitlint/rules/src/footer-max-length.ts b/@commitlint/rules/src/footer-max-length.ts index 82dd42961f..7c2d771be6 100644 --- a/@commitlint/rules/src/footer-max-length.ts +++ b/@commitlint/rules/src/footer-max-length.ts @@ -1,5 +1,5 @@ import {maxLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const footerMaxLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/footer-max-line-length.ts b/@commitlint/rules/src/footer-max-line-length.ts index 5ef7123222..9bc1ffe281 100644 --- a/@commitlint/rules/src/footer-max-line-length.ts +++ b/@commitlint/rules/src/footer-max-line-length.ts @@ -1,5 +1,5 @@ import {maxLineLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const footerMaxLineLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/footer-min-length.ts b/@commitlint/rules/src/footer-min-length.ts index 9447444e10..cd8571d5c5 100644 --- a/@commitlint/rules/src/footer-min-length.ts +++ b/@commitlint/rules/src/footer-min-length.ts @@ -1,5 +1,5 @@ import {minLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const footerMinLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/header-case.ts b/@commitlint/rules/src/header-case.ts index 144ecb39fa..dedb264df3 100644 --- a/@commitlint/rules/src/header-case.ts +++ b/@commitlint/rules/src/header-case.ts @@ -1,6 +1,6 @@ -import {TargetCaseType, case as ensureCase} from '@commitlint/ensure'; +import {case as ensureCase} from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {TargetCaseType, Rule} from '@commitlint/types'; const negated = (when?: string) => when === 'never'; diff --git a/@commitlint/rules/src/header-full-stop.ts b/@commitlint/rules/src/header-full-stop.ts index ffecb8d60c..c22c1a791d 100644 --- a/@commitlint/rules/src/header-full-stop.ts +++ b/@commitlint/rules/src/header-full-stop.ts @@ -1,5 +1,5 @@ import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const headerFullStop: Rule = ( parsed, diff --git a/@commitlint/rules/src/header-max-length.ts b/@commitlint/rules/src/header-max-length.ts index 32bbd65b69..4eab3dc50e 100644 --- a/@commitlint/rules/src/header-max-length.ts +++ b/@commitlint/rules/src/header-max-length.ts @@ -1,5 +1,5 @@ import {maxLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const headerMaxLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/header-min-length.ts b/@commitlint/rules/src/header-min-length.ts index c36b549867..10cf63aa2e 100644 --- a/@commitlint/rules/src/header-min-length.ts +++ b/@commitlint/rules/src/header-min-length.ts @@ -1,5 +1,5 @@ import {minLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const headerMinLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/index.test.ts b/@commitlint/rules/src/index.test.ts index 75838535bc..9ee9603da2 100644 --- a/@commitlint/rules/src/index.test.ts +++ b/@commitlint/rules/src/index.test.ts @@ -16,7 +16,7 @@ test('rules export functions', () => { async function glob(pattern: string | string[]) { const files = await globby(pattern, { - ignore: ['**/index.ts', '**/*.test.ts', '**/types.ts'], + ignore: ['**/index.ts', '**/*.test.ts'], cwd: __dirname }); return files.map(relative).map(toExport); diff --git a/@commitlint/rules/src/index.ts b/@commitlint/rules/src/index.ts index 0a8b1f1f65..f726e45905 100644 --- a/@commitlint/rules/src/index.ts +++ b/@commitlint/rules/src/index.ts @@ -31,8 +31,6 @@ import {typeEnum} from './type-enum'; import {typeMaxLength} from './type-max-length'; import {typeMinLength} from './type-min-length'; -export * from './types'; - export default { 'body-case': bodyCase, 'body-empty': bodyEmpty, diff --git a/@commitlint/rules/src/references-empty.ts b/@commitlint/rules/src/references-empty.ts index 3e3e483981..7582c4e555 100644 --- a/@commitlint/rules/src/references-empty.ts +++ b/@commitlint/rules/src/references-empty.ts @@ -1,5 +1,5 @@ import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const referencesEmpty: Rule = (parsed, when = 'never') => { const negated = when === 'always'; diff --git a/@commitlint/rules/src/scope-case.ts b/@commitlint/rules/src/scope-case.ts index fc29fbe288..0d6781e2f5 100644 --- a/@commitlint/rules/src/scope-case.ts +++ b/@commitlint/rules/src/scope-case.ts @@ -1,6 +1,6 @@ -import {TargetCaseType, case as ensureCase} from '@commitlint/ensure'; +import {case as ensureCase} from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {TargetCaseType, Rule} from '@commitlint/types'; const negated = (when?: string) => when === 'never'; diff --git a/@commitlint/rules/src/scope-empty.ts b/@commitlint/rules/src/scope-empty.ts index 89358a4b6d..9d600372de 100644 --- a/@commitlint/rules/src/scope-empty.ts +++ b/@commitlint/rules/src/scope-empty.ts @@ -1,6 +1,6 @@ import * as ensure from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const scopeEmpty: Rule = (parsed, when = 'never') => { const negated = when === 'always'; diff --git a/@commitlint/rules/src/scope-enum.ts b/@commitlint/rules/src/scope-enum.ts index 0753ae0b8d..2aa8e149f1 100644 --- a/@commitlint/rules/src/scope-enum.ts +++ b/@commitlint/rules/src/scope-enum.ts @@ -1,6 +1,6 @@ import * as ensure from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const scopeEnum: Rule = ( parsed, diff --git a/@commitlint/rules/src/scope-max-length.ts b/@commitlint/rules/src/scope-max-length.ts index 24e3d5f478..8cdaea7256 100644 --- a/@commitlint/rules/src/scope-max-length.ts +++ b/@commitlint/rules/src/scope-max-length.ts @@ -1,5 +1,5 @@ import {maxLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const scopeMaxLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/scope-min-length.ts b/@commitlint/rules/src/scope-min-length.ts index ec088f6848..5492579c8c 100644 --- a/@commitlint/rules/src/scope-min-length.ts +++ b/@commitlint/rules/src/scope-min-length.ts @@ -1,5 +1,5 @@ import {minLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const scopeMinLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/signed-off-by.ts b/@commitlint/rules/src/signed-off-by.ts index 78d844b486..82762fa7cd 100644 --- a/@commitlint/rules/src/signed-off-by.ts +++ b/@commitlint/rules/src/signed-off-by.ts @@ -1,6 +1,6 @@ import message from '@commitlint/message'; import toLines from '@commitlint/to-lines'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const signedOffBy: Rule = ( parsed, diff --git a/@commitlint/rules/src/subject-case.ts b/@commitlint/rules/src/subject-case.ts index 4694cf7194..fb8a8ab024 100644 --- a/@commitlint/rules/src/subject-case.ts +++ b/@commitlint/rules/src/subject-case.ts @@ -1,6 +1,6 @@ -import {TargetCaseType, case as ensureCase} from '@commitlint/ensure'; +import {case as ensureCase} from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {TargetCaseType, Rule} from '@commitlint/types'; const negated = (when?: string) => when === 'never'; diff --git a/@commitlint/rules/src/subject-empty.ts b/@commitlint/rules/src/subject-empty.ts index 331adb5a4e..20e6f4863f 100644 --- a/@commitlint/rules/src/subject-empty.ts +++ b/@commitlint/rules/src/subject-empty.ts @@ -1,6 +1,6 @@ import * as ensure from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const subjectEmpty: Rule = (parsed, when = 'always') => { const negated = when === 'never'; diff --git a/@commitlint/rules/src/subject-full-stop.ts b/@commitlint/rules/src/subject-full-stop.ts index 133f03b647..7faa4910bc 100644 --- a/@commitlint/rules/src/subject-full-stop.ts +++ b/@commitlint/rules/src/subject-full-stop.ts @@ -1,5 +1,5 @@ import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const subjectFullStop: Rule = ( parsed, diff --git a/@commitlint/rules/src/subject-max-length.ts b/@commitlint/rules/src/subject-max-length.ts index c8d492c706..db65f1a468 100644 --- a/@commitlint/rules/src/subject-max-length.ts +++ b/@commitlint/rules/src/subject-max-length.ts @@ -1,5 +1,5 @@ import {maxLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const subjectMaxLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/subject-min-length.ts b/@commitlint/rules/src/subject-min-length.ts index 5cd7077c8a..43fee9701a 100644 --- a/@commitlint/rules/src/subject-min-length.ts +++ b/@commitlint/rules/src/subject-min-length.ts @@ -1,5 +1,5 @@ import {minLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const subjectMinLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/type-case.ts b/@commitlint/rules/src/type-case.ts index 2fc37ec35f..1a5bceef9c 100644 --- a/@commitlint/rules/src/type-case.ts +++ b/@commitlint/rules/src/type-case.ts @@ -1,6 +1,6 @@ -import {TargetCaseType, case as ensureCase} from '@commitlint/ensure'; +import {case as ensureCase} from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {TargetCaseType, Rule} from '@commitlint/types'; const negated = (when?: string) => when === 'never'; diff --git a/@commitlint/rules/src/type-empty.ts b/@commitlint/rules/src/type-empty.ts index 667f6dfba0..9d58864299 100644 --- a/@commitlint/rules/src/type-empty.ts +++ b/@commitlint/rules/src/type-empty.ts @@ -1,6 +1,6 @@ import * as ensure from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const typeEmpty: Rule = (parsed, when = 'always') => { const negated = when === 'never'; diff --git a/@commitlint/rules/src/type-enum.ts b/@commitlint/rules/src/type-enum.ts index 974f94fc6b..1aba3b61fa 100644 --- a/@commitlint/rules/src/type-enum.ts +++ b/@commitlint/rules/src/type-enum.ts @@ -1,6 +1,6 @@ import * as ensure from '@commitlint/ensure'; import message from '@commitlint/message'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const typeEnum: Rule = ( parsed, diff --git a/@commitlint/rules/src/type-max-length.ts b/@commitlint/rules/src/type-max-length.ts index 29fc60076c..29569ed79f 100644 --- a/@commitlint/rules/src/type-max-length.ts +++ b/@commitlint/rules/src/type-max-length.ts @@ -1,5 +1,5 @@ import {maxLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const typeMaxLength: Rule = ( parsed, diff --git a/@commitlint/rules/src/type-min-length.ts b/@commitlint/rules/src/type-min-length.ts index c48852c398..08ea3150d9 100644 --- a/@commitlint/rules/src/type-min-length.ts +++ b/@commitlint/rules/src/type-min-length.ts @@ -1,5 +1,5 @@ import {minLength} from '@commitlint/ensure'; -import {Rule} from './types'; +import {Rule} from '@commitlint/types'; export const typeMinLength: Rule = ( parsed, diff --git a/@commitlint/rules/tsconfig.json b/@commitlint/rules/tsconfig.json index 7824a8d568..1cafd13cb7 100644 --- a/@commitlint/rules/tsconfig.json +++ b/@commitlint/rules/tsconfig.json @@ -15,7 +15,7 @@ "references": [ { "path": "../ensure" }, { "path": "../message" }, - { "path": "../parse" }, - { "path": "../to-lines" } + { "path": "../to-lines" }, + { "path": "../types" }, ] } diff --git a/@commitlint/types/package.json b/@commitlint/types/package.json new file mode 100644 index 0000000000..12b349b704 --- /dev/null +++ b/@commitlint/types/package.json @@ -0,0 +1,32 @@ +{ + "name": "@commitlint/types", + "version": "8.3.5", + "description": "Shared types for commitlint packages", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "files": [ + "lib/" + ], + "scripts": { + "pkg": "pkg-check" + }, + "engines": { + "node": ">=4" + }, + "repository": { + "type": "git", + "url": "https://github.com/conventional-changelog/commitlint.git" + }, + "bugs": { + "url": "https://github.com/conventional-changelog/commitlint/issues" + }, + "homepage": "https://github.com/conventional-changelog/commitlint#readme", + "author": { + "name": "Mario Nebl", + "email": "hello@herebecode.com" + }, + "license": "MIT", + "devDependencies": { + "@commitlint/utils": "^8.3.4" + } +} diff --git a/@commitlint/ensure/src/types.ts b/@commitlint/types/src/ensure.ts similarity index 100% rename from @commitlint/ensure/src/types.ts rename to @commitlint/types/src/ensure.ts diff --git a/@commitlint/types/src/index.ts b/@commitlint/types/src/index.ts new file mode 100644 index 0000000000..f562854fed --- /dev/null +++ b/@commitlint/types/src/index.ts @@ -0,0 +1,6 @@ +export * from './ensure'; +export * from './is-ignored'; +export * from './rules'; +export * from './lint'; +export * from './load'; +export * from './parse'; diff --git a/@commitlint/types/src/is-ignored.ts b/@commitlint/types/src/is-ignored.ts new file mode 100644 index 0000000000..45227cdbfd --- /dev/null +++ b/@commitlint/types/src/is-ignored.ts @@ -0,0 +1,6 @@ +export type Matcher = (commit: string) => boolean; + +export interface IsIgnoredOptions { + ignores?: Matcher[]; + defaults?: boolean; +} diff --git a/@commitlint/types/src/lint.ts b/@commitlint/types/src/lint.ts new file mode 100644 index 0000000000..6ebf81e448 --- /dev/null +++ b/@commitlint/types/src/lint.ts @@ -0,0 +1,43 @@ +import {IsIgnoredOptions} from './is-ignored'; +import {RuleConfigTuple, PluginRecords, RuleSeverity} from './load'; +import {ParserOptions} from './parse'; + +export type LintRuleConfig = Record< + string, + | Readonly<[RuleSeverity.Disabled]> + | RuleConfigTuple + | RuleConfigTuple +>; + +export interface LintOptions { + /** If it should ignore the default commit messages (defaults to `true`) */ + defaultIgnores?: IsIgnoredOptions['defaults']; + /** Additional commits to ignore, defined by ignore matchers */ + ignores?: IsIgnoredOptions['ignores']; + /** The parser configuration to use when linting the commit */ + parserOpts?: ParserOptions; + + plugins?: PluginRecords; +} + +export interface LintOutcome { + /** The linted commit, as string */ + input: string; + /** If the linted commit is considered valid */ + valid: boolean; + /** All errors, per rule, for the commit */ + errors: LintRuleOutcome[]; + /** All warnings, per rule, for the commit */ + warnings: LintRuleOutcome[]; +} + +export interface LintRuleOutcome { + /** If the commit is considered valid for the rule */ + valid: boolean; + /** The "severity" of the rule (1 = warning, 2 = error) */ + level: RuleSeverity; + /** The name of the rule */ + name: string; + /** The message returned from the rule, if invalid */ + message: string; +} diff --git a/@commitlint/load/src/types.ts b/@commitlint/types/src/load.ts similarity index 85% rename from @commitlint/load/src/types.ts rename to @commitlint/types/src/load.ts index 37cdaa5a6b..6f446b1369 100644 --- a/@commitlint/load/src/types.ts +++ b/@commitlint/types/src/load.ts @@ -1,8 +1,13 @@ -import {TargetCaseType} from '@commitlint/ensure'; +import {TargetCaseType} from './ensure'; +import {Rule, RuleCondition} from './rules'; -export type RuleCondition = 'always' | 'never'; +export type PluginRecords = Record; -export type PluginRecords = Record; +export interface Plugin { + rules: { + [ruleName: string]: Rule; + }; +} export interface LoadOptions { cwd?: string; @@ -10,15 +15,14 @@ export interface LoadOptions { } export enum RuleSeverity { + Disabled = 0, Warning = 1, Error = 2 } -export type RuleConfigTuple = ReadonlyArray< - T extends void - ? [RuleSeverity, RuleCondition] - : [RuleSeverity, RuleCondition, T] ->; +export type RuleConfigTuple = T extends void + ? Readonly<[RuleSeverity, RuleCondition]> + : Readonly<[RuleSeverity, RuleCondition, T]>; export enum RuleConfigQuality { User, @@ -33,7 +37,9 @@ export type QualifiedRuleConfig = export type RuleConfig< V = RuleConfigQuality.Qualified, T = void -> = V extends false ? RuleConfigTuple : QualifiedRuleConfig; +> = V extends RuleConfigQuality.Qualified + ? RuleConfigTuple + : QualifiedRuleConfig; export type CaseRuleConfig = RuleConfig< V, diff --git a/@commitlint/parse/src/types.ts b/@commitlint/types/src/parse.ts similarity index 100% rename from @commitlint/parse/src/types.ts rename to @commitlint/types/src/parse.ts diff --git a/@commitlint/rules/src/types.ts b/@commitlint/types/src/rules.ts similarity index 95% rename from @commitlint/rules/src/types.ts rename to @commitlint/types/src/rules.ts index 968f80f358..b064cb4d32 100644 --- a/@commitlint/rules/src/types.ts +++ b/@commitlint/types/src/rules.ts @@ -1,4 +1,4 @@ -import {Commit} from '@commitlint/parse'; +import {Commit} from './parse'; /** * Rules always have a condition. diff --git a/@commitlint/types/tsconfig.json b/@commitlint/types/tsconfig.json new file mode 100644 index 0000000000..f9b6b7f3f1 --- /dev/null +++ b/@commitlint/types/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "outDir": "./lib" + }, + "include": [ + "./src" + ], + "exclude": [ + "./lib/**/*" + ] +} diff --git a/tsconfig.json b/tsconfig.json index 0065cef64f..314a1e218e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,7 @@ { "path": "@commitlint/to-lines" }, { "path": "@commitlint/top-level" }, { "path": "@commitlint/read" }, - { "path": "@commitlint/rules" } + { "path": "@commitlint/rules" }, + { "path": "@commitlint/lint" }, ] } diff --git a/tsconfig.shared.json b/tsconfig.shared.json index 3a76d85bb5..d86bf1bb65 100644 --- a/tsconfig.shared.json +++ b/tsconfig.shared.json @@ -18,6 +18,7 @@ "keyofStringsOnly": true, "noFallthroughCasesInSwitch": true, "isolatedModules": true, - "skipLibCheck": true + "skipLibCheck": true, + "downlevelIteration": true } }