@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 +6 -0
- package/dist-package/package.json +23 -0
- package/package.json +2 -3
- package/src/commands.loader.js +9 -2
- package/src/index.js +6 -3
- package/src/utils/convert-to-cli-parameters.js +6 -4
- package/src/utils/davinci-project-config.js +3 -1
- package/src/utils/davinci-project-config.test.js +109 -0
- package/src/utils/files.js +4 -6
- package/src/utils/print.js +34 -1
- package/src/utils/to-vorpal-args.test.js +37 -0
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
|
|
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
|
}
|
package/src/commands.loader.js
CHANGED
|
@@ -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((
|
|
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 {
|
|
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 =
|
|
21
|
-
return vorpalInstance.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
|
-
|
|
5
|
+
result.push(`--${key}`)
|
|
6
|
+
|
|
7
|
+
const hasTrueValue = options[key] === true
|
|
8
|
+
const optionValue = hasTrueValue ? '' : String(options[key])
|
|
5
9
|
|
|
6
|
-
|
|
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) =>
|
|
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
|
+
})
|
package/src/utils/files.js
CHANGED
|
@@ -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
|
|
package/src/utils/print.js
CHANGED
|
@@ -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
|
+
})
|