3a87b8969e3bd4601eed0e240f30b690bd78ad735c12b55072bbbd2f1375af10a94cbf95266bb24016c80e163e02393df4b0b8515ec08f37a081a68658d104 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. 'use strict'
  2. const cliTruncate = require('cli-truncate')
  3. const debug = require('debug')('lint-staged:make-cmd-tasks')
  4. const resolveTaskFn = require('./resolveTaskFn')
  5. const { createError } = require('./validateConfig')
  6. const STDOUT_COLUMNS_DEFAULT = 80
  7. const listrPrefixLength = {
  8. update: ` X `.length, // indented task title where X is a checkmark or a cross (failure)
  9. verbose: `[STARTED] `.length, // verbose renderer uses 7-letter STARTED/SUCCESS prefixes
  10. }
  11. /**
  12. * Get length of title based on the number of available columns prefix length
  13. * @param {string} renderer The name of the Listr renderer
  14. * @returns {number}
  15. */
  16. const getTitleLength = (renderer, columns = process.stdout.columns) => {
  17. const prefixLength = listrPrefixLength[renderer] || 0
  18. return (columns || STDOUT_COLUMNS_DEFAULT) - prefixLength
  19. }
  20. /**
  21. * Creates and returns an array of listr tasks which map to the given commands.
  22. *
  23. * @param {object} options
  24. * @param {Array<string|Function>|string|Function} options.commands
  25. * @param {Array<string>} options.files
  26. * @param {string} options.gitDir
  27. * @param {string} options.renderer
  28. * @param {Boolean} shell
  29. * @param {Boolean} verbose
  30. */
  31. const makeCmdTasks = async ({ commands, files, gitDir, renderer, shell, verbose }) => {
  32. debug('Creating listr tasks for commands %o', commands)
  33. const commandArray = Array.isArray(commands) ? commands : [commands]
  34. const cmdTasks = []
  35. for (const cmd of commandArray) {
  36. // command function may return array of commands that already include `stagedFiles`
  37. const isFn = typeof cmd === 'function'
  38. const resolved = isFn ? await cmd(files) : cmd
  39. const resolvedArray = Array.isArray(resolved) ? resolved : [resolved] // Wrap non-array command as array
  40. for (const command of resolvedArray) {
  41. // If the function linter didn't return string | string[] it won't work
  42. // Do the validation here instead of `validateConfig` to skip evaluating the function multiple times
  43. if (isFn && typeof command !== 'string') {
  44. throw new Error(
  45. createError(
  46. '[Function]',
  47. 'Function task should return a string or an array of strings',
  48. resolved
  49. )
  50. )
  51. }
  52. // Truncate title to single line based on renderer
  53. const title = cliTruncate(command, getTitleLength(renderer))
  54. const task = resolveTaskFn({ command, files, gitDir, isFn, shell, verbose })
  55. cmdTasks.push({ title, command, task })
  56. }
  57. }
  58. return cmdTasks
  59. }
  60. module.exports = makeCmdTasks