@toptal/davinci-cli-shared 1.5.2-alpha-FX-2734-upgrade-cypress.125 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.5.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1343](https://github.com/toptal/davinci/pull/1343) [`1212e098`](https://github.com/toptal/davinci/commit/1212e098c668fc1c87ee9b1824edf0bc80509bc4) Thanks [@dmaklygin](https://github.com/dmaklygin)! - - implement custom helper for davinci workflow package
8
+
3
9
  ## 1.5.1
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@toptal/davinci-cli-shared",
3
+ "version": "1.5.2",
4
+ "description": "Shared CLI code and CLI engine for davinci",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "src/index.js",
9
+ "scripts": {
10
+ "build:package": "../../bin/build-package.js",
11
+ "prepublishOnly": "../../bin/prepublish.js",
12
+ "test": "echo \"Error: no test specified\" && exit 1"
13
+ },
14
+ "author": "Toptal",
15
+ "license": "ISC",
16
+ "dependencies": {
17
+ "chalk": "^4.1.2",
18
+ "execa": "^5.1.1",
19
+ "inquirer": "^8.2.0",
20
+ "js-yaml": "^4.1.0",
21
+ "vorpal": "^1.12.0"
22
+ }
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toptal/davinci-cli-shared",
3
- "version": "1.5.2-alpha-FX-2734-upgrade-cypress.125+ac801e68",
3
+ "version": "1.5.2",
4
4
  "description": "Shared CLI code and CLI engine for davinci",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -19,6 +19,5 @@
19
19
  "inquirer": "^8.2.0",
20
20
  "js-yaml": "^4.1.0",
21
21
  "vorpal": "^1.12.0"
22
- },
23
- "gitHead": "ac801e68bf3fb45dc8769c859f14632885734b7e"
22
+ }
24
23
  }
@@ -7,15 +7,22 @@ const commandsLoader = (commandCreators, vorpalInstance) => {
7
7
  description,
8
8
  options = [],
9
9
  allowUnknownOptions = false,
10
- action
10
+ action,
11
+ help
11
12
  } = commandCreator
12
13
 
13
14
  const commandInstance = vorpalInstance
14
15
  .command(command)
15
- .parse((command, args) => command.replace(args, toVorpalArgs(args)))
16
+ .parse((commandText, args) =>
17
+ commandText.replace(args, toVorpalArgs(args))
18
+ )
16
19
 
17
20
  options.forEach(option => commandInstance.option(option.name, option.label))
18
21
 
22
+ if (help) {
23
+ commandInstance.help(help)
24
+ }
25
+
19
26
  if (allowUnknownOptions) {
20
27
  commandInstance.allowUnknownOptions()
21
28
  }
package/src/index.js CHANGED
@@ -3,7 +3,9 @@ const vorpal = require('vorpal')
3
3
  const print = require('../src/utils/print')
4
4
  const { run, runSync } = require('../src/utils/run')
5
5
  const prompt = require('../src/utils/prompt')
6
- const { convertToCLIParameters } = require('../src/utils/convert-to-cli-parameters')
6
+ const {
7
+ convertToCLIParameters
8
+ } = require('../src/utils/convert-to-cli-parameters')
7
9
  const davinciProjectConfig = require('./utils/davinci-project-config')
8
10
  const files = require('./utils/files')
9
11
 
@@ -17,11 +19,12 @@ const execCommand = (...args) => {
17
19
  return vorpalInstance.exec(...args)
18
20
  }
19
21
 
20
- const help = help => {
21
- return vorpalInstance.help(help)
22
+ const help = helpText => {
23
+ return vorpalInstance.help(helpText)
22
24
  }
23
25
 
24
26
  const catchErrorCommand = callback => {
27
+ /* eslint-disable promise/catch-or-return, promise/valid-params */
25
28
  vorpalInstance
26
29
  .catch('[commands...]', 'Catches incorrect commands')
27
30
  .action((args, cb) => {
@@ -1,11 +1,13 @@
1
1
  const convertToCLIParameters = options => {
2
2
  const result = []
3
+
3
4
  Object.keys(options).forEach(key => {
4
- result.push(`--${key}`)
5
+ result.push(`--${key}`)
6
+
7
+ const hasTrueValue = options[key] === true
8
+ const optionValue = hasTrueValue ? '' : String(options[key])
5
9
 
6
- const hasTrueValue = options[key] === true
7
- const optionValue = hasTrueValue ? '' : String(options[key])
8
- result.push(optionValue)
10
+ result.push(optionValue)
9
11
  })
10
12
 
11
13
  return result
@@ -1,10 +1,12 @@
1
1
  const fs = require('fs')
2
2
  const yaml = require('js-yaml')
3
+
3
4
  const files = require('./files')
4
5
 
5
6
  const path = files.getProjectRootFilePath('./davinci.yaml')
6
7
  const data = fs.existsSync(path) ? yaml.load(fs.readFileSync(path, 'utf8')) : {}
7
- const resolve = (sectionName, key) => Boolean(data && resolveKey(data[sectionName], key))
8
+ const resolve = (sectionName, key) =>
9
+ Boolean(data && resolveKey(data[sectionName], key))
8
10
  const resolveKey = (section, key) => section && section[key]
9
11
 
10
12
  const davinciProjectConfig = {
@@ -0,0 +1,109 @@
1
+ describe('davinci-project-config', () => {
2
+ let fs
3
+
4
+ beforeEach(() => {
5
+ jest.resetModules()
6
+
7
+ jest.mock('fs')
8
+ fs = require('fs')
9
+ })
10
+
11
+ it('returns the default config when the file does not exist', () => {
12
+ fs.existsSync.mockReturnValue(false)
13
+ const davinciProjectConfig = require('./davinci-project-config')
14
+
15
+ expect(davinciProjectConfig.master.deploy).toBe(false)
16
+ expect(davinciProjectConfig.pr.contractTesting).toBe(false)
17
+ })
18
+
19
+ it('returns the default config when the file is empty', () => {
20
+ fs.existsSync.mockReturnValue(true)
21
+ fs.readFileSync.mockReturnValue('')
22
+ const davinciProjectConfig = require('./davinci-project-config')
23
+
24
+ expect(davinciProjectConfig.master.deploy).toBe(false)
25
+ expect(davinciProjectConfig.pr.contractTesting).toBe(false)
26
+ })
27
+
28
+ it('returns specified options merged with the default config', () => {
29
+ const data = `
30
+ master:
31
+ conventional_commits: true
32
+ `
33
+
34
+ fs.existsSync.mockReturnValue(true)
35
+ fs.readFileSync.mockReturnValue(data)
36
+ const davinciProjectConfig = require('./davinci-project-config')
37
+
38
+ expect(davinciProjectConfig.master.deploy).toBe(false)
39
+ expect(davinciProjectConfig.master.conventionalCommits).toBe(true)
40
+ expect(davinciProjectConfig.pr.contractTesting).toBe(false)
41
+ })
42
+
43
+ it('parses correctly is_progressive_web_app root flag', () => {
44
+ const data = `
45
+ is_progressive_web_app: true
46
+ `
47
+
48
+ fs.existsSync.mockReturnValue(true)
49
+ fs.readFileSync.mockReturnValue(data)
50
+ const davinciProjectConfig = require('./davinci-project-config')
51
+
52
+ expect(davinciProjectConfig.isProgressiveWebApp).toBe(true)
53
+ })
54
+
55
+ it('parses correctly service_worker_filename root flag', () => {
56
+ const serviceWorkerFileName = 'service-worker-123.js'
57
+ const data = `
58
+ service_worker_filename: ${serviceWorkerFileName}
59
+ `
60
+
61
+ fs.existsSync.mockReturnValue(true)
62
+ fs.readFileSync.mockReturnValue(data)
63
+ const davinciProjectConfig = require('./davinci-project-config')
64
+
65
+ expect(davinciProjectConfig.serviceWorkerFileName).toBe(
66
+ serviceWorkerFileName
67
+ )
68
+ })
69
+
70
+ it('when davinci.yml file exists and service_worker_filename is not specified in config', () => {
71
+ const data = `
72
+ master:
73
+ conventional_commits: true
74
+ `
75
+
76
+ fs.existsSync.mockReturnValue(true)
77
+ fs.readFileSync.mockReturnValue(data)
78
+ const davinciProjectConfig = require('./davinci-project-config')
79
+
80
+ expect(davinciProjectConfig.serviceWorkerFileName).toBeUndefined()
81
+ })
82
+
83
+ it('when davinci.yml file is empty and service_worker_filename is not specified in config', () => {
84
+ const data = ''
85
+
86
+ fs.existsSync.mockReturnValue(true)
87
+ fs.readFileSync.mockReturnValue(data)
88
+ const davinciProjectConfig = require('./davinci-project-config')
89
+
90
+ expect(davinciProjectConfig.serviceWorkerFileName).toBeUndefined()
91
+ })
92
+
93
+ it('parses correctly safety_workers list', () => {
94
+ const data = `
95
+ safety_workers:
96
+ - service-worker-1.js
97
+ - service-worker-2.js
98
+ `
99
+
100
+ fs.existsSync.mockReturnValue(true)
101
+ fs.readFileSync.mockReturnValue(data)
102
+ const davinciProjectConfig = require('./davinci-project-config')
103
+
104
+ expect(davinciProjectConfig.safetyWorkers).toEqual([
105
+ 'service-worker-1.js',
106
+ 'service-worker-2.js'
107
+ ])
108
+ })
109
+ })
@@ -1,23 +1,21 @@
1
1
  const path = require('path')
2
2
 
3
3
  const getPackageFileContent = (davinciPackageName, filename) =>
4
- require(
5
- getPackageFilePath(davinciPackageName, filename)
6
- )
4
+ require(getPackageFilePath(davinciPackageName, filename))
7
5
 
8
6
  const getPackageFilePath = (davinciPackageName, filename) => {
9
7
  const packageIndexPath = require.resolve(davinciPackageName)
10
8
  const davinciQARoot = path.join(packageIndexPath, '../..')
9
+
11
10
  return path.join(davinciQARoot, filename)
12
11
  }
13
12
 
14
13
  const getProjectRootFileContent = filename =>
15
- require(
16
- getProjectRootFilePath(filename)
17
- )
14
+ require(getProjectRootFilePath(filename))
18
15
 
19
16
  const getProjectRootFilePath = filename => {
20
17
  const currentRunningDir = process.cwd()
18
+
21
19
  return path.join(currentRunningDir, filename)
22
20
  }
23
21
 
@@ -26,9 +26,42 @@ const grey = (...args) => {
26
26
  console.log(chalk.grey(...prettifyObjectIfExist(args)))
27
27
  }
28
28
 
29
+ const generatePadding = (str, width, delimiter = ' ') => {
30
+ const len = Math.max(0, Math.floor(width) - str.trim().length)
31
+
32
+ return str + Array(len + 1).join(delimiter)
33
+ }
34
+
35
+ /**
36
+ * Build a list of commands
37
+ * @param commands Array<[name, description]>
38
+ */
39
+ const prettifyCommands = commands => {
40
+ if (!commands.length) {
41
+ return ''
42
+ }
43
+
44
+ const width = commands.reduce(
45
+ (max, commandX) => Math.max(max, commandX[0].length),
46
+ 0
47
+ )
48
+
49
+ return commands
50
+ .map(([command, description]) => {
51
+ const prefix =
52
+ ' ' + chalk.green(generatePadding(command, width)) + ' '
53
+ const suffix = generatePadding('', width + 6) + description
54
+
55
+ return prefix + suffix
56
+ })
57
+ .join('\n')
58
+ }
59
+
29
60
  module.exports = {
30
61
  green,
31
62
  yellow,
32
63
  red,
33
- grey
64
+ grey,
65
+ generatePadding,
66
+ prettifyCommands
34
67
  }
@@ -0,0 +1,37 @@
1
+ const toVorpalArgs = require('./to-vorpal-args')
2
+
3
+ describe('toVorpalArgs', () => {
4
+ it('transforms numbers', () => {
5
+ const initialArgs = '--foo=1 --bar=2'
6
+ const expectedArgs = '--foo 1 --bar 2'
7
+
8
+ expect(toVorpalArgs(initialArgs)).toEqual(expectedArgs)
9
+ })
10
+
11
+ it('transforms strings', () => {
12
+ const initialArgs = '--foo="hello" --bar="world"'
13
+ const expectedArgs = '--foo "hello" --bar "world"'
14
+
15
+ expect(toVorpalArgs(initialArgs)).toEqual(expectedArgs)
16
+ })
17
+
18
+ it('transforms booleans', () => {
19
+ const initialArgs = '--foo=true --bar=false'
20
+ const expectedArgs = '--foo true --bar false'
21
+
22
+ expect(toVorpalArgs(initialArgs)).toEqual(expectedArgs)
23
+ })
24
+
25
+ it('transforms short arguments', () => {
26
+ const initialArgs = '-f=1 -b="hello"'
27
+ const expectedArgs = '-f 1 -b "hello"'
28
+
29
+ expect(toVorpalArgs(initialArgs)).toEqual(expectedArgs)
30
+ })
31
+
32
+ it('ignores formatted arguments', () => {
33
+ const formattedArgs = '--foo 1 --bar "hello" -f true'
34
+
35
+ expect(toVorpalArgs(formattedArgs)).toEqual(formattedArgs)
36
+ })
37
+ })