From da3c596016bc04e662e05d5e5ed6ecb7f99ab181 Mon Sep 17 00:00:00 2001 From: Armano Date: Sun, 10 Jan 2021 23:35:28 +0100 Subject: [PATCH] fix: improve config validation --- @commitlint/load/src/load.ts | 12 +++-- .../load/src/utils/load-parser-opts.ts | 13 +++--- @commitlint/load/src/utils/validators.ts | 45 +++++++++++++------ 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/@commitlint/load/src/load.ts b/@commitlint/load/src/load.ts index 8fd64d9f24..fc9231c140 100644 --- a/@commitlint/load/src/load.ts +++ b/@commitlint/load/src/load.ts @@ -38,9 +38,6 @@ export default async function load( extends: [], plugins: [], rules: {}, - formatter: '@commitlint/format', - helpUrl: - 'https://github.com/conventional-changelog/commitlint/#what-is-commitlint', }, loaded ? loaded.config : null, seed @@ -67,6 +64,15 @@ export default async function load( validateConfig(extended); + if (!extended.formatter) { + extended.formatter = '@commitlint/format'; + } + + if (!extended.helpUrl) { + extended.helpUrl = + 'https://github.com/conventional-changelog/commitlint/#what-is-commitlint'; + } + let plugins: PluginRecords = {}; uniq(extended.plugins || []).forEach((plugin) => { if (typeof plugin === 'string') { diff --git a/@commitlint/load/src/utils/load-parser-opts.ts b/@commitlint/load/src/utils/load-parser-opts.ts index f168fd642a..9978f54172 100644 --- a/@commitlint/load/src/utils/load-parser-opts.ts +++ b/@commitlint/load/src/utils/load-parser-opts.ts @@ -1,5 +1,10 @@ import {ParserPreset} from '@commitlint/types'; -import {isObjectLike, isParserOptsFunction, isPromiseLike} from './validators'; +import { + isObjectLike, + isParserOptsFunction, + isPromiseLike, + validateParser, +} from './validators'; export async function loadParser( pendingParser: unknown @@ -10,9 +15,7 @@ export async function loadParser( // Await for the module, loaded with require const parser = await pendingParser; - if (!isObjectLike(parser)) { - throw new Error('Invalid configuration, `parserPreset` must be an object'); - } + validateParser(parser); // Await parser opts if applicable if (isPromiseLike(parser.parserOpts)) { @@ -23,7 +26,7 @@ export async function loadParser( // Create parser opts from factory if ( isParserOptsFunction(parser) && - typeof parser.name === 'string' && + parser.name && parser.name.startsWith('conventional-changelog-') ) { return new Promise((resolve) => { diff --git a/@commitlint/load/src/utils/validators.ts b/@commitlint/load/src/utils/validators.ts index 7b76e17b88..80c0ba1cbf 100644 --- a/@commitlint/load/src/utils/validators.ts +++ b/@commitlint/load/src/utils/validators.ts @@ -1,4 +1,4 @@ -import {Plugin, RulesConfig} from '@commitlint/types'; +import {UserConfig} from '@commitlint/types'; export function isObjectLike(obj: unknown): obj is Record { return Boolean(obj) && typeof obj === 'object'; // typeof null === 'object' @@ -21,21 +21,22 @@ export function isParserOptsFunction>( return typeof obj.parserOpts === 'function'; } -export function validateConfig( - config: Record -): asserts config is { - formatter: string; - ignores?: ((commit: string) => boolean)[]; - defaultIgnores?: boolean; - plugins?: (Plugin | string)[]; - rules: Partial; - helpUrl: string; - [key: string]: unknown; -} { +export function validateConfig>( + config: T +): asserts config is Omit & T { if (!isObjectLike(config)) { throw new Error('Invalid configuration, `parserPreset` must be an object'); } - if (typeof config.formatter !== 'string') { + if ( + config.extends && + typeof config.extends !== 'string' && + !Array.isArray(config.extends) + ) { + throw new Error( + 'Invalid configuration, `extends` must be a array or string' + ); + } + if (config.formatter && typeof config.formatter !== 'string') { throw new Error('Invalid configuration, `formatter` must be a string'); } if (config.ignores && !Array.isArray(config.ignores)) { @@ -44,7 +45,11 @@ export function validateConfig( if (config.plugins && !Array.isArray(config.plugins)) { throw new Error('Invalid configuration, `plugins` must ba an array'); } + if (config.rules && typeof config.rules !== 'object') { + throw new Error('Invalid configuration, `rules` must ba an object'); + } if ( + config.defaultIgnores && typeof config.defaultIgnores !== 'boolean' && typeof config.defaultIgnores !== 'undefined' ) { @@ -56,3 +61,17 @@ export function validateConfig( throw new Error('Invalid configuration, `helpUrl` must be a string'); } } + +export function validateParser( + parser: unknown +): asserts parser is {name?: string; path?: string; [key: string]: unknown} { + if (!isObjectLike(parser)) { + throw new Error('Invalid configuration, `parserPreset` must be an object'); + } + if (parser.name && typeof parser.name !== 'string') { + throw new Error('Invalid configuration, `parserPreset` must have a name'); + } + if (parser.path && typeof parser.path !== 'string') { + throw new Error('Invalid configuration, `parserPreset` must have a name'); + } +}