lint.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. const util_1 = __importDefault(require("util"));
  7. const is_ignored_1 = __importDefault(require("@commitlint/is-ignored"));
  8. const parse_1 = __importDefault(require("@commitlint/parse"));
  9. const rules_1 = __importDefault(require("@commitlint/rules"));
  10. const commit_message_1 = require("./commit-message");
  11. const types_1 = require("@commitlint/types");
  12. async function lint(message, rawRulesConfig, rawOpts) {
  13. const opts = rawOpts
  14. ? rawOpts
  15. : { defaultIgnores: undefined, ignores: undefined };
  16. const rulesConfig = rawRulesConfig || {};
  17. // Found a wildcard match, skip
  18. if ((0, is_ignored_1.default)(message, { defaults: opts.defaultIgnores, ignores: opts.ignores })) {
  19. return {
  20. valid: true,
  21. errors: [],
  22. warnings: [],
  23. input: message,
  24. };
  25. }
  26. // Parse the commit message
  27. const parsed = message === ''
  28. ? { header: null, body: null, footer: null }
  29. : await (0, parse_1.default)(message, undefined, opts.parserOpts);
  30. if (parsed.header === null &&
  31. parsed.body === null &&
  32. parsed.footer === null) {
  33. // Commit is empty, skip
  34. return {
  35. valid: true,
  36. errors: [],
  37. warnings: [],
  38. input: message,
  39. };
  40. }
  41. const allRules = new Map(Object.entries(rules_1.default));
  42. if (opts.plugins) {
  43. Object.values(opts.plugins).forEach((plugin) => {
  44. if (plugin.rules) {
  45. Object.keys(plugin.rules).forEach((ruleKey) => allRules.set(ruleKey, plugin.rules[ruleKey]));
  46. }
  47. });
  48. }
  49. // Find invalid rules configs
  50. const missing = Object.keys(rulesConfig).filter((name) => typeof allRules.get(name) !== 'function');
  51. if (missing.length > 0) {
  52. const names = [...allRules.keys()];
  53. throw new RangeError(`Found invalid rule names: ${missing.join(', ')}. Supported rule names are: ${names.join(', ')}`);
  54. }
  55. const invalid = Object.entries(rulesConfig)
  56. .map(([name, config]) => {
  57. if (!Array.isArray(config)) {
  58. return new Error(`config for rule ${name} must be array, received ${util_1.default.inspect(config)} of type ${typeof config}`);
  59. }
  60. const [level] = config;
  61. if (level === types_1.RuleConfigSeverity.Disabled && config.length === 1) {
  62. return null;
  63. }
  64. const [, when] = config;
  65. if (typeof level !== 'number' || isNaN(level)) {
  66. return new Error(`level for rule ${name} must be number, received ${util_1.default.inspect(level)} of type ${typeof level}`);
  67. }
  68. if (config.length < 2 || config.length > 3) {
  69. return new Error(`config for rule ${name} must be 2 or 3 items long, received ${util_1.default.inspect(config)} of length ${config.length}`);
  70. }
  71. if (level < 0 || level > 2) {
  72. return new RangeError(`level for rule ${name} must be between 0 and 2, received ${util_1.default.inspect(level)}`);
  73. }
  74. if (typeof when !== 'string') {
  75. return new Error(`condition for rule ${name} must be string, received ${util_1.default.inspect(when)} of type ${typeof when}`);
  76. }
  77. if (when !== 'never' && when !== 'always') {
  78. return new Error(`condition for rule ${name} must be "always" or "never", received ${util_1.default.inspect(when)}`);
  79. }
  80. return null;
  81. })
  82. .filter((item) => item instanceof Error);
  83. if (invalid.length > 0) {
  84. throw new Error(invalid.map((i) => i.message).join('\n'));
  85. }
  86. // Validate against all rules
  87. const pendingResults = Object.entries(rulesConfig)
  88. // Level 0 rules are ignored
  89. .filter(([, config]) => !!config && config.length && config[0] > 0)
  90. .map(async (entry) => {
  91. const [name, config] = entry;
  92. const [level, when, value] = config; //
  93. const rule = allRules.get(name);
  94. if (!rule) {
  95. throw new Error(`Could not find rule implementation for ${name}`);
  96. }
  97. const executableRule = rule;
  98. const [valid, message] = await executableRule(parsed, when, value);
  99. return {
  100. level,
  101. valid,
  102. name,
  103. message,
  104. };
  105. });
  106. const results = (await Promise.all(pendingResults)).filter((result) => result !== null);
  107. const errors = results.filter((result) => result.level === 2 && !result.valid);
  108. const warnings = results.filter((result) => result.level === 1 && !result.valid);
  109. const valid = errors.length === 0;
  110. return {
  111. valid,
  112. errors,
  113. warnings,
  114. input: (0, commit_message_1.buildCommitMesage)(parsed),
  115. };
  116. }
  117. exports.default = lint;
  118. //# sourceMappingURL=lint.js.map