@toptal/davinci-cli-shared 1.10.3-alpha-fix-bundle-analyze-e1cf8407.5 → 1.10.3-alpha-feature-esm-migration-e551c09d.30
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/package.json +11 -4
- package/src/commands.loader.js +4 -4
- package/src/index.js +72 -19
- package/src/utils/convert-to-cli-parameters.js +2 -2
- package/src/utils/davinci-project-config.cjs +35 -0
- package/src/utils/davinci-project-config.test.js +106 -131
- package/src/utils/files.js +12 -10
- package/src/utils/metrics/id-config.js +8 -8
- package/src/utils/metrics/metrics.js +6 -5
- package/src/utils/metrics/usage-data.js +8 -8
- package/src/utils/package.js +6 -6
- package/src/utils/package.test.js +11 -11
- package/src/utils/print.js +10 -10
- package/src/utils/prompt.js +5 -5
- package/src/utils/run.js +5 -5
- package/src/utils/to-vorpal-args.js +1 -1
- package/src/utils/to-vorpal-args.test.js +1 -1
- package/src/utils/yarn-adapter.js +7 -4
- package/src/utils/yarn-adapter.test.js +15 -14
- package/src/utils/davinci-project-config.js +0 -35
package/package.json
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-cli-shared",
|
|
3
|
-
"version": "1.10.3-alpha-
|
|
3
|
+
"version": "1.10.3-alpha-feature-esm-migration-e551c09d.30+e551c09d",
|
|
4
4
|
"description": "Shared CLI code and CLI engine for davinci",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./src/index.js",
|
|
10
|
+
"./config": "./src/utils/davinci-project-config.cjs"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
9
13
|
"files": [
|
|
10
14
|
"src",
|
|
11
15
|
"CHANGELOG.md"
|
|
12
16
|
],
|
|
13
17
|
"scripts": {
|
|
14
|
-
"test": "
|
|
18
|
+
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' yarn jest"
|
|
15
19
|
},
|
|
16
20
|
"author": "Toptal",
|
|
17
21
|
"license": "ISC",
|
|
@@ -27,5 +31,8 @@
|
|
|
27
31
|
"uuid": "^9.0.0",
|
|
28
32
|
"vorpal": "^1.12.0"
|
|
29
33
|
},
|
|
30
|
-
"
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@jest/globals": "28.1.0"
|
|
36
|
+
},
|
|
37
|
+
"gitHead": "e551c09d98a4e340ab16afb27a42fe52a8548d00"
|
|
31
38
|
}
|
package/src/commands.loader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import toVorpalArgs from './utils/to-vorpal-args.js'
|
|
2
|
+
import metrics from './utils/metrics/metrics.js'
|
|
3
|
+
import { gatherUsageData } from './utils/metrics/usage-data.js'
|
|
4
4
|
|
|
5
5
|
const sendMetrics = async (commandIdentifier, packageCommand) => {
|
|
6
6
|
try {
|
|
@@ -53,4 +53,4 @@ const commandsLoader = (commandCreators, vorpalInstance, packageCommand) => {
|
|
|
53
53
|
})
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
export default commandsLoader
|
package/src/index.js
CHANGED
|
@@ -1,30 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import vorpal from 'vorpal'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
green,
|
|
5
|
+
cyan,
|
|
6
|
+
yellow,
|
|
7
|
+
red,
|
|
8
|
+
grey,
|
|
9
|
+
generatePadding,
|
|
10
|
+
prettifyCommands,
|
|
11
|
+
} from './utils/print.js'
|
|
12
|
+
import { run, runSync } from './utils/run.js'
|
|
13
|
+
import { confirm, password, input } from './utils/prompt.js'
|
|
14
|
+
import { convertToCLIParameters } from './utils/convert-to-cli-parameters.js'
|
|
15
|
+
import davinciConfig from './utils/davinci-project-config.cjs'
|
|
16
|
+
import {
|
|
17
|
+
getPackageFileContent,
|
|
18
|
+
getPackageFilePath,
|
|
19
|
+
getProjectRootFilePath,
|
|
20
|
+
getProjectRootFileContent,
|
|
21
|
+
projectHasPackage,
|
|
22
|
+
getDirectories,
|
|
23
|
+
} from './utils/files.js'
|
|
24
|
+
import { getPackagePackageJson, checkPrerequirement } from './utils/package.js'
|
|
25
|
+
import commandsLoader from './commands.loader.js'
|
|
26
|
+
import { identify, track } from './utils/metrics/metrics.js'
|
|
27
|
+
import { gatherUsageData } from './utils/metrics/usage-data.js'
|
|
28
|
+
|
|
29
|
+
const { config: davinciProjectConfig } = davinciConfig
|
|
12
30
|
|
|
13
31
|
const vorpalInstance = vorpal()
|
|
14
32
|
|
|
15
|
-
const bootstrap = (options = {}) => {
|
|
33
|
+
export const bootstrap = (options = {}) => {
|
|
16
34
|
return vorpalInstance.parse(process.argv, options)
|
|
17
35
|
}
|
|
18
36
|
|
|
19
|
-
const execCommand = (...args) => {
|
|
37
|
+
export const execCommand = (...args) => {
|
|
20
38
|
return vorpalInstance.exec(...args)
|
|
21
39
|
}
|
|
22
40
|
|
|
23
|
-
const help = helpText => {
|
|
41
|
+
export const help = helpText => {
|
|
24
42
|
return vorpalInstance.help(helpText)
|
|
25
43
|
}
|
|
26
44
|
|
|
27
|
-
const catchErrorCommand = callback => {
|
|
45
|
+
export const catchErrorCommand = callback => {
|
|
28
46
|
/* eslint-disable promise/catch-or-return, promise/valid-params */
|
|
29
47
|
vorpalInstance
|
|
30
48
|
.catch('[commands...]', 'Catches incorrect commands')
|
|
@@ -33,13 +51,48 @@ const catchErrorCommand = callback => {
|
|
|
33
51
|
})
|
|
34
52
|
}
|
|
35
53
|
|
|
36
|
-
const loadCommands = (commandCreators, packageCommand) => {
|
|
37
|
-
const commandsLoader = require('./commands.loader')
|
|
38
|
-
|
|
54
|
+
export const loadCommands = (commandCreators, packageCommand) => {
|
|
39
55
|
commandsLoader(commandCreators, vorpalInstance, packageCommand)
|
|
40
56
|
}
|
|
41
57
|
|
|
42
|
-
|
|
58
|
+
export { davinciProjectConfig, run, runSync, convertToCLIParameters }
|
|
59
|
+
|
|
60
|
+
export const packageUtils = {
|
|
61
|
+
getPackagePackageJson,
|
|
62
|
+
checkPrerequirement,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const files = {
|
|
66
|
+
getPackageFileContent,
|
|
67
|
+
getPackageFilePath,
|
|
68
|
+
getProjectRootFilePath,
|
|
69
|
+
getProjectRootFileContent,
|
|
70
|
+
projectHasPackage,
|
|
71
|
+
getDirectories,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const prompt = {
|
|
75
|
+
confirm,
|
|
76
|
+
password,
|
|
77
|
+
input,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const print = {
|
|
81
|
+
green,
|
|
82
|
+
cyan,
|
|
83
|
+
yellow,
|
|
84
|
+
red,
|
|
85
|
+
grey,
|
|
86
|
+
generatePadding,
|
|
87
|
+
prettifyCommands,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const metrics = {
|
|
91
|
+
identify,
|
|
92
|
+
track,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export default {
|
|
43
96
|
davinciProjectConfig,
|
|
44
97
|
files,
|
|
45
98
|
bootstrap,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const convertToCLIParameters = options =>
|
|
1
|
+
export const convertToCLIParameters = options =>
|
|
2
2
|
Object.entries(options).flatMap(([option, value]) => {
|
|
3
3
|
if (typeof value === 'boolean') {
|
|
4
4
|
return [`--${!value ? 'no-' : ''}${option}`]
|
|
@@ -7,4 +7,4 @@ const convertToCLIParameters = options =>
|
|
|
7
7
|
return [`--${option}`, String(value)]
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
export default { convertToCLIParameters }
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const yaml = require('js-yaml')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
5
|
+
const configPath = path.join(process.cwd(), './davinci.yaml')
|
|
6
|
+
const data = fs.existsSync(configPath)
|
|
7
|
+
? yaml.load(fs.readFileSync(configPath, 'utf8'))
|
|
8
|
+
: {}
|
|
9
|
+
|
|
10
|
+
const getDavinciProjectConfig = config => {
|
|
11
|
+
return {
|
|
12
|
+
master: {
|
|
13
|
+
conventionalCommits: !!config?.master?.conventional_commits,
|
|
14
|
+
deploy: !!config?.master?.deploy,
|
|
15
|
+
deployStaging: !!config?.master?.deploy_staging,
|
|
16
|
+
requireAssignee: !!config?.master?.require_assignee,
|
|
17
|
+
requireAssigneeWhitelist: config?.master?.require_assignee_whitelist ?? [
|
|
18
|
+
'dependabot-preview[bot]',
|
|
19
|
+
'dependabot[bot]',
|
|
20
|
+
],
|
|
21
|
+
publishAsPackage: !!config?.master?.publish_as_package,
|
|
22
|
+
},
|
|
23
|
+
pr: {
|
|
24
|
+
contractTesting: !!config?.pr?.contract_testing,
|
|
25
|
+
},
|
|
26
|
+
isProgressiveWebApp: Boolean(config?.is_progressive_web_app),
|
|
27
|
+
serviceWorkerFileName: config?.service_worker_filename,
|
|
28
|
+
safetyWorkers: config?.safety_workers,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
getDavinciProjectConfig,
|
|
34
|
+
config: getDavinciProjectConfig(data),
|
|
35
|
+
}
|
|
@@ -1,140 +1,115 @@
|
|
|
1
|
-
|
|
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')
|
|
1
|
+
import { getDavinciProjectConfig } from './davinci-project-config.cjs'
|
|
51
2
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const data = `
|
|
57
|
-
master:
|
|
58
|
-
require_assignee: true
|
|
59
|
-
`
|
|
60
|
-
|
|
61
|
-
fs.existsSync.mockReturnValue(true)
|
|
62
|
-
fs.readFileSync.mockReturnValue(data)
|
|
63
|
-
const davinciProjectConfig = require('./davinci-project-config')
|
|
64
|
-
|
|
65
|
-
expect(davinciProjectConfig.master.requireAssigneeWhitelist).toEqual([
|
|
66
|
-
'dependabot-preview[bot]',
|
|
67
|
-
'dependabot[bot]',
|
|
68
|
-
])
|
|
69
|
-
expect(davinciProjectConfig.master.requireAssignee).toBe(true)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('parses correctly require_assignee_whitelist master flag', () => {
|
|
73
|
-
const data = `
|
|
74
|
-
master:
|
|
75
|
-
require_assignee_whitelist: []
|
|
76
|
-
`
|
|
77
|
-
|
|
78
|
-
fs.existsSync.mockReturnValue(true)
|
|
79
|
-
fs.readFileSync.mockReturnValue(data)
|
|
80
|
-
const davinciProjectConfig = require('./davinci-project-config')
|
|
81
|
-
|
|
82
|
-
expect(davinciProjectConfig.master.requireAssigneeWhitelist).toEqual([])
|
|
83
|
-
expect(davinciProjectConfig.master.requireAssignee).toBe(false)
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it('parses correctly service_worker_filename root flag', () => {
|
|
87
|
-
const serviceWorkerFileName = 'service-worker-123.js'
|
|
88
|
-
const data = `
|
|
89
|
-
service_worker_filename: ${serviceWorkerFileName}
|
|
90
|
-
`
|
|
91
|
-
|
|
92
|
-
fs.existsSync.mockReturnValue(true)
|
|
93
|
-
fs.readFileSync.mockReturnValue(data)
|
|
94
|
-
const davinciProjectConfig = require('./davinci-project-config')
|
|
95
|
-
|
|
96
|
-
expect(davinciProjectConfig.serviceWorkerFileName).toBe(
|
|
97
|
-
serviceWorkerFileName
|
|
98
|
-
)
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it('when davinci.yml file exists and service_worker_filename is not specified in config', () => {
|
|
102
|
-
const data = `
|
|
103
|
-
master:
|
|
104
|
-
conventional_commits: true
|
|
105
|
-
`
|
|
106
|
-
|
|
107
|
-
fs.existsSync.mockReturnValue(true)
|
|
108
|
-
fs.readFileSync.mockReturnValue(data)
|
|
109
|
-
const davinciProjectConfig = require('./davinci-project-config')
|
|
3
|
+
describe('davinci-project-config', () => {
|
|
4
|
+
describe('when the file does not exist', () => {
|
|
5
|
+
it('returns the default config', async () => {
|
|
6
|
+
const davinciProjectConfig = getDavinciProjectConfig()
|
|
110
7
|
|
|
111
|
-
|
|
8
|
+
expect(davinciProjectConfig.master.deploy).toBe(false)
|
|
9
|
+
expect(davinciProjectConfig.pr.contractTesting).toBe(false)
|
|
10
|
+
})
|
|
112
11
|
})
|
|
113
12
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
fs.existsSync.mockReturnValue(true)
|
|
118
|
-
fs.readFileSync.mockReturnValue(data)
|
|
119
|
-
const davinciProjectConfig = require('./davinci-project-config')
|
|
13
|
+
describe('when the file is empty', () => {
|
|
14
|
+
it('returns the default config', () => {
|
|
15
|
+
const davinciProjectConfig = getDavinciProjectConfig({})
|
|
120
16
|
|
|
121
|
-
|
|
17
|
+
expect(davinciProjectConfig.master.deploy).toBe(false)
|
|
18
|
+
expect(davinciProjectConfig.pr.contractTesting).toBe(false)
|
|
19
|
+
expect(davinciProjectConfig.serviceWorkerFileName).toBeUndefined()
|
|
20
|
+
})
|
|
122
21
|
})
|
|
123
22
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
23
|
+
describe('when config exists', () => {
|
|
24
|
+
it('returns specified options merged with the default config', () => {
|
|
25
|
+
const data = {
|
|
26
|
+
master: {
|
|
27
|
+
conventional_commits: true,
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const davinciProjectConfig = getDavinciProjectConfig(data)
|
|
32
|
+
|
|
33
|
+
expect(davinciProjectConfig.master.deploy).toBe(false)
|
|
34
|
+
expect(davinciProjectConfig.master.conventionalCommits).toBe(true)
|
|
35
|
+
expect(davinciProjectConfig.pr.contractTesting).toBe(false)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('parses correctly is_progressive_web_app root flag', async () => {
|
|
39
|
+
const data = {
|
|
40
|
+
is_progressive_web_app: true,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const davinciProjectConfig = getDavinciProjectConfig(data)
|
|
44
|
+
|
|
45
|
+
expect(davinciProjectConfig.isProgressiveWebApp).toBe(true)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('parses correctly require_assignee master flag', () => {
|
|
49
|
+
const data = {
|
|
50
|
+
master: {
|
|
51
|
+
require_assignee: true,
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const davinciProjectConfig = getDavinciProjectConfig(data)
|
|
56
|
+
|
|
57
|
+
expect(davinciProjectConfig.master.requireAssigneeWhitelist).toEqual([
|
|
58
|
+
'dependabot-preview[bot]',
|
|
59
|
+
'dependabot[bot]',
|
|
60
|
+
])
|
|
61
|
+
expect(davinciProjectConfig.master.requireAssignee).toBe(true)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('parses correctly require_assignee_whitelist master flag', () => {
|
|
65
|
+
const data = {
|
|
66
|
+
master: {
|
|
67
|
+
require_assignee_whitelist: [],
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const davinciProjectConfig = getDavinciProjectConfig(data)
|
|
72
|
+
|
|
73
|
+
expect(davinciProjectConfig.master.requireAssigneeWhitelist).toEqual([])
|
|
74
|
+
expect(davinciProjectConfig.master.requireAssignee).toBe(false)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('parses correctly service_worker_filename root flag', async () => {
|
|
78
|
+
const serviceWorkerFileName = 'service-worker-123.js'
|
|
79
|
+
const data = {
|
|
80
|
+
service_worker_filename: serviceWorkerFileName,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const davinciProjectConfig = getDavinciProjectConfig(data)
|
|
84
|
+
|
|
85
|
+
expect(davinciProjectConfig.serviceWorkerFileName).toBe(
|
|
86
|
+
serviceWorkerFileName
|
|
87
|
+
)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('does this/that', async () => {
|
|
91
|
+
const data = {
|
|
92
|
+
master: {
|
|
93
|
+
conventional_commits: true,
|
|
94
|
+
},
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const davinciProjectConfig = getDavinciProjectConfig(data)
|
|
98
|
+
|
|
99
|
+
expect(davinciProjectConfig.serviceWorkerFileName).toBeUndefined()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('parses correctly safety_workers list', async () => {
|
|
103
|
+
const data = {
|
|
104
|
+
safety_workers: ['service-worker-1.js', 'service-worker-2.js'],
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const davinciProjectConfig = getDavinciProjectConfig(data)
|
|
108
|
+
|
|
109
|
+
expect(davinciProjectConfig.safetyWorkers).toEqual([
|
|
110
|
+
'service-worker-1.js',
|
|
111
|
+
'service-worker-2.js',
|
|
112
|
+
])
|
|
113
|
+
})
|
|
139
114
|
})
|
|
140
115
|
})
|
package/src/utils/files.js
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import { readdirSync } from 'fs'
|
|
3
|
+
import { createRequire } from 'module'
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const require = createRequire(import.meta.url)
|
|
6
|
+
|
|
7
|
+
export const getPackageFileContent = (davinciPackageName, filename) =>
|
|
5
8
|
require(getPackageFilePath(davinciPackageName, filename))
|
|
6
9
|
|
|
7
|
-
const getPackageFilePath = (davinciPackageName, filename) => {
|
|
10
|
+
export const getPackageFilePath = (davinciPackageName, filename) => {
|
|
8
11
|
const packageIndexPath = require.resolve(davinciPackageName)
|
|
9
12
|
const davinciQARoot = path.join(packageIndexPath, '../..')
|
|
10
13
|
|
|
11
14
|
return path.join(davinciQARoot, filename)
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
const getProjectRootFileContent = filename =>
|
|
17
|
+
export const getProjectRootFileContent = filename =>
|
|
15
18
|
require(getProjectRootFilePath(filename))
|
|
16
19
|
|
|
17
|
-
const getProjectRootFilePath = filename => {
|
|
20
|
+
export const getProjectRootFilePath = filename => {
|
|
18
21
|
const currentRunningDir = process.cwd()
|
|
19
22
|
|
|
20
23
|
return path.join(currentRunningDir, filename)
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
const projectHasPackage = pkg => {
|
|
26
|
+
export const projectHasPackage = pkg => {
|
|
24
27
|
try {
|
|
25
28
|
require.resolve(pkg)
|
|
26
29
|
|
|
@@ -30,16 +33,15 @@ const projectHasPackage = pkg => {
|
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
const getDirectories = source =>
|
|
36
|
+
export const getDirectories = source =>
|
|
34
37
|
readdirSync(source, { withFileTypes: true })
|
|
35
38
|
.filter(dirent => dirent.isDirectory())
|
|
36
39
|
.map(dirent => dirent.name)
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
export default {
|
|
39
42
|
getPackageFileContent,
|
|
40
43
|
getPackageFilePath,
|
|
41
44
|
getProjectRootFilePath,
|
|
42
|
-
getProjectRootFileContent,
|
|
43
45
|
projectHasPackage,
|
|
44
46
|
getDirectories,
|
|
45
47
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import os from 'os'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import yaml from 'js-yaml'
|
|
5
|
+
import { v1 as uuid } from 'uuid'
|
|
6
6
|
|
|
7
7
|
const homeDir = os.homedir()
|
|
8
8
|
const configDir = path.join(homeDir, '.davinci-metrics')
|
|
@@ -35,7 +35,7 @@ const updateConfig = config => {
|
|
|
35
35
|
fs.writeFileSync(configFile, yaml.dump(newConfig))
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const isTrackingEnabled = () => {
|
|
38
|
+
export const isTrackingEnabled = () => {
|
|
39
39
|
if (process.env.CI) {
|
|
40
40
|
return false
|
|
41
41
|
}
|
|
@@ -45,7 +45,7 @@ const isTrackingEnabled = () => {
|
|
|
45
45
|
return config.allow_tracking !== 'no'
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const getDeviceId = () => {
|
|
48
|
+
export const getDeviceId = () => {
|
|
49
49
|
const config = readConfig()
|
|
50
50
|
|
|
51
51
|
if (config && typeof config.uuid === 'string') {
|
|
@@ -61,7 +61,7 @@ const getDeviceId = () => {
|
|
|
61
61
|
return id
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
export default {
|
|
65
65
|
getDeviceId,
|
|
66
66
|
isTrackingEnabled,
|
|
67
67
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import Analytics from 'analytics-node'
|
|
2
|
+
|
|
3
|
+
import { getDeviceId, isTrackingEnabled } from './id-config.js'
|
|
2
4
|
|
|
3
|
-
const { getDeviceId, isTrackingEnabled } = require('./id-config')
|
|
4
5
|
const SEGMENT_WRITE_KEY = 'cwNYguEVVqdxFj5NyTKOhlrvaNQjlsXV'
|
|
5
6
|
const anonymousId = getDeviceId()
|
|
6
7
|
|
|
@@ -9,7 +10,7 @@ const analytics = new Analytics(SEGMENT_WRITE_KEY, {
|
|
|
9
10
|
flushAt: 1,
|
|
10
11
|
})
|
|
11
12
|
|
|
12
|
-
const identify = () =>
|
|
13
|
+
export const identify = () =>
|
|
13
14
|
new Promise((resolve, reject) => {
|
|
14
15
|
analytics.identify(
|
|
15
16
|
{
|
|
@@ -19,7 +20,7 @@ const identify = () =>
|
|
|
19
20
|
)
|
|
20
21
|
})
|
|
21
22
|
|
|
22
|
-
const track = properties =>
|
|
23
|
+
export const track = properties =>
|
|
23
24
|
new Promise((resolve, reject) => {
|
|
24
25
|
analytics.track(
|
|
25
26
|
{
|
|
@@ -31,7 +32,7 @@ const track = properties =>
|
|
|
31
32
|
)
|
|
32
33
|
})
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
export default {
|
|
35
36
|
identify,
|
|
36
37
|
track,
|
|
37
38
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import os from 'os'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import execa from 'execa'
|
|
5
|
+
import readPackageUp from 'read-pkg-up'
|
|
6
|
+
import findYarnWorkspaceRoot from 'find-yarn-workspace-root'
|
|
7
7
|
|
|
8
8
|
const TOPTAL_SSH_REPO_URL_REGEX =
|
|
9
9
|
/^git@github\.com:\/?toptal\/([A-Za-z0-9_.-]+)\.git$/
|
|
@@ -85,7 +85,7 @@ const sanitizeCommandDefinition = commandStr =>
|
|
|
85
85
|
.trim()
|
|
86
86
|
.replace(/ /g, '_')
|
|
87
87
|
|
|
88
|
-
const gatherUsageData = async (commandIdentifier, davinciCommand) => {
|
|
88
|
+
export const gatherUsageData = async (commandIdentifier, davinciCommand) => {
|
|
89
89
|
const [projectName, gitBranch, packageInfo] = await Promise.all([
|
|
90
90
|
getProjectName(),
|
|
91
91
|
getGitBranch(),
|
|
@@ -123,4 +123,4 @@ const gatherUsageData = async (commandIdentifier, davinciCommand) => {
|
|
|
123
123
|
return data
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
export default { gatherUsageData }
|
package/src/utils/package.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import semver from 'semver'
|
|
2
|
+
import readPkgUp from 'read-pkg-up'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import yarnAdapter from './yarn-adapter.js'
|
|
5
5
|
|
|
6
|
-
const getPackagePackageJson = cwd => {
|
|
6
|
+
export const getPackagePackageJson = cwd => {
|
|
7
7
|
return readPkgUp.sync({ cwd }).packageJson
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -17,7 +17,7 @@ const getInstalledPackageVersion = packageName => {
|
|
|
17
17
|
return packageInfoList.get(packageName)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const checkPrerequirement = ({ dependencies, packageName }) => {
|
|
20
|
+
export const checkPrerequirement = ({ dependencies, packageName }) => {
|
|
21
21
|
const validVersionOrRange = dependencies[packageName]
|
|
22
22
|
|
|
23
23
|
const installedVersion = getInstalledPackageVersion(packageName)
|
|
@@ -35,7 +35,7 @@ Installed version: ${installedVersion}
|
|
|
35
35
|
Should be: ${validVersionOrRange}`
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
export default {
|
|
39
39
|
getPackagePackageJson,
|
|
40
40
|
checkPrerequirement,
|
|
41
41
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
jest
|
|
2
|
-
list: jest.fn(),
|
|
3
|
-
}))
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { checkPrerequirement } from './package.js'
|
|
4
|
+
import yarnAdapter from './yarn-adapter.js'
|
|
5
|
+
|
|
6
|
+
const yarnAdapterListMock = jest.spyOn(yarnAdapter, 'list')
|
|
7
7
|
|
|
8
8
|
const packageName = '@toptal/davinci-engine'
|
|
9
9
|
const packageValidVersions = [
|
|
@@ -28,9 +28,9 @@ const packageJsonDependencies = {
|
|
|
28
28
|
describe('package utils', () => {
|
|
29
29
|
describe('checkPrerequirement', () => {
|
|
30
30
|
it('should return an error when package is not installed', () => {
|
|
31
|
-
|
|
31
|
+
yarnAdapterListMock.mockReturnValueOnce(new Map())
|
|
32
32
|
|
|
33
|
-
const result =
|
|
33
|
+
const result = checkPrerequirement({
|
|
34
34
|
dependencies: packageJsonDependencies,
|
|
35
35
|
packageName,
|
|
36
36
|
})
|
|
@@ -41,11 +41,11 @@ describe('package utils', () => {
|
|
|
41
41
|
it.each(packageValidVersions)(
|
|
42
42
|
`should return no errors for version %s in range ${validVersionRange}`,
|
|
43
43
|
packageValidVersion => {
|
|
44
|
-
|
|
44
|
+
yarnAdapterListMock.mockReturnValueOnce(
|
|
45
45
|
new Map([[packageName, packageValidVersion]])
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
-
const result =
|
|
48
|
+
const result = checkPrerequirement({
|
|
49
49
|
dependencies: packageJsonDependencies,
|
|
50
50
|
packageName,
|
|
51
51
|
})
|
|
@@ -57,11 +57,11 @@ describe('package utils', () => {
|
|
|
57
57
|
it.each(packageInvalidVersions)(
|
|
58
58
|
`should return an error for version %s in range ${validVersionRange}`,
|
|
59
59
|
packageInvalidVersion => {
|
|
60
|
-
|
|
60
|
+
yarnAdapterListMock.mockReturnValueOnce(
|
|
61
61
|
new Map([[packageName, packageInvalidVersion]])
|
|
62
62
|
)
|
|
63
63
|
|
|
64
|
-
const result =
|
|
64
|
+
const result = checkPrerequirement({
|
|
65
65
|
dependencies: packageJsonDependencies,
|
|
66
66
|
packageName,
|
|
67
67
|
})
|
package/src/utils/print.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import util from 'util'
|
|
3
3
|
|
|
4
4
|
const isObject = obj => typeof obj === 'object'
|
|
5
5
|
const inspectObject = obj =>
|
|
@@ -10,27 +10,27 @@ const inspectObject = obj =>
|
|
|
10
10
|
const prettifyObjectIfExist = args =>
|
|
11
11
|
args.map(arg => (isObject(arg) ? inspectObject(arg) : arg))
|
|
12
12
|
|
|
13
|
-
const cyan = (...args) => {
|
|
13
|
+
export const cyan = (...args) => {
|
|
14
14
|
console.log(chalk.cyan(...prettifyObjectIfExist(args)))
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const green = (...args) => {
|
|
17
|
+
export const green = (...args) => {
|
|
18
18
|
console.log(chalk.green(...prettifyObjectIfExist(args)))
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const yellow = (...args) => {
|
|
21
|
+
export const yellow = (...args) => {
|
|
22
22
|
console.log(chalk.yellow(...prettifyObjectIfExist(args)))
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const red = (...args) => {
|
|
25
|
+
export const red = (...args) => {
|
|
26
26
|
console.log(chalk.red(...prettifyObjectIfExist(args)))
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const grey = (...args) => {
|
|
29
|
+
export const grey = (...args) => {
|
|
30
30
|
console.log(chalk.grey(...prettifyObjectIfExist(args)))
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const generatePadding = (str, width, delimiter = ' ') => {
|
|
33
|
+
export const generatePadding = (str, width, delimiter = ' ') => {
|
|
34
34
|
const len = Math.max(0, Math.floor(width) - str.trim().length)
|
|
35
35
|
|
|
36
36
|
return str + Array(len + 1).join(delimiter)
|
|
@@ -40,7 +40,7 @@ const generatePadding = (str, width, delimiter = ' ') => {
|
|
|
40
40
|
* Build a list of commands
|
|
41
41
|
* @param commands Array<[name, description]>
|
|
42
42
|
*/
|
|
43
|
-
const prettifyCommands = commands => {
|
|
43
|
+
export const prettifyCommands = commands => {
|
|
44
44
|
if (!commands.length) {
|
|
45
45
|
return ''
|
|
46
46
|
}
|
|
@@ -61,7 +61,7 @@ const prettifyCommands = commands => {
|
|
|
61
61
|
.join('\n')
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
export default {
|
|
65
65
|
green,
|
|
66
66
|
cyan,
|
|
67
67
|
yellow,
|
package/src/utils/prompt.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import inquirer from 'inquirer'
|
|
2
2
|
|
|
3
|
-
const confirm = async (name, message) => {
|
|
3
|
+
export const confirm = async (name, message) => {
|
|
4
4
|
const result = await inquirer.prompt([
|
|
5
5
|
{
|
|
6
6
|
type: 'confirm',
|
|
@@ -12,7 +12,7 @@ const confirm = async (name, message) => {
|
|
|
12
12
|
return result[name]
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const input = async (name, message, validate) => {
|
|
15
|
+
export const input = async (name, message, validate) => {
|
|
16
16
|
const result = await inquirer.prompt([
|
|
17
17
|
{
|
|
18
18
|
type: 'input',
|
|
@@ -25,7 +25,7 @@ const input = async (name, message, validate) => {
|
|
|
25
25
|
return result[name]
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const password = async (name, message, validate) => {
|
|
28
|
+
export const password = async (name, message, validate) => {
|
|
29
29
|
const result = await inquirer.prompt([
|
|
30
30
|
{
|
|
31
31
|
type: 'password',
|
|
@@ -38,7 +38,7 @@ const password = async (name, message, validate) => {
|
|
|
38
38
|
return result[name]
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
export default {
|
|
42
42
|
confirm,
|
|
43
43
|
input,
|
|
44
44
|
password,
|
package/src/utils/run.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import execa from 'execa'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import print from './print.js'
|
|
4
4
|
|
|
5
|
-
const runSync = (command, args, options) => {
|
|
5
|
+
export const runSync = (command, args, options) => {
|
|
6
6
|
try {
|
|
7
7
|
print.grey([command, ...args].join(' '))
|
|
8
8
|
|
|
@@ -23,7 +23,7 @@ const runSync = (command, args, options) => {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const run = async (command, args, options) => {
|
|
26
|
+
export const run = async (command, args, options) => {
|
|
27
27
|
print.grey([command, ...args].join(' '))
|
|
28
28
|
|
|
29
29
|
const subprocess = execa(command, args, options)
|
|
@@ -33,7 +33,7 @@ const run = async (command, args, options) => {
|
|
|
33
33
|
await subprocess
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
export default {
|
|
37
37
|
run,
|
|
38
38
|
runSync,
|
|
39
39
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { runSync } from './run.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
@@ -12,8 +12,8 @@ const splitNameAndVersion = treeName => {
|
|
|
12
12
|
return [treeName.slice(0, atPos), treeName.slice(atPos + 1)]
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
const { stdout } =
|
|
15
|
+
export const createList = syncRun => packageName => {
|
|
16
|
+
const { stdout } = syncRun(
|
|
17
17
|
'yarn',
|
|
18
18
|
[
|
|
19
19
|
'list',
|
|
@@ -39,6 +39,9 @@ const list = packageName => {
|
|
|
39
39
|
return new Map(packagesFound.map(pkg => splitNameAndVersion(pkg.name)))
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
export const list = createList(runSync)
|
|
43
|
+
|
|
44
|
+
export default {
|
|
43
45
|
list,
|
|
46
|
+
createList,
|
|
44
47
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
jest
|
|
2
|
-
runSync: jest.fn(),
|
|
3
|
-
}))
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { createList } from './yarn-adapter.js'
|
|
4
|
+
import run from './run.js'
|
|
7
5
|
|
|
8
6
|
const packageName = 'find-up'
|
|
9
7
|
const packageVersion = '5.0.0'
|
|
@@ -11,46 +9,49 @@ const existingPackageResponseMock = `{"type":"tree","data":{"type":"list","trees
|
|
|
11
9
|
const nonExistingPackageResponseMock = `{"type":"tree","data":{"type":"list","trees":[]}}`
|
|
12
10
|
const invalidResponseMock = 'invalid-response'
|
|
13
11
|
|
|
12
|
+
const runSyncMock = jest.spyOn(run, 'runSync')
|
|
13
|
+
const yarnListInjected = createList(runSyncMock)
|
|
14
|
+
|
|
14
15
|
describe('yarnAdapter', () => {
|
|
15
16
|
describe('list', () => {
|
|
16
17
|
it('should return a version for the existing package', () => {
|
|
17
|
-
|
|
18
|
+
runSyncMock.mockReturnValueOnce({
|
|
18
19
|
stdout: existingPackageResponseMock,
|
|
19
20
|
})
|
|
20
21
|
|
|
21
|
-
const result =
|
|
22
|
+
const result = yarnListInjected(packageName)
|
|
22
23
|
|
|
23
24
|
expect(result.size).toBe(1)
|
|
24
25
|
expect(result.get(packageName)).toBe(packageVersion)
|
|
25
26
|
})
|
|
26
27
|
|
|
27
28
|
it('should return empty map for non-existing package', () => {
|
|
28
|
-
|
|
29
|
+
runSyncMock.mockImplementationOnce(() => ({
|
|
29
30
|
stdout: nonExistingPackageResponseMock,
|
|
30
|
-
})
|
|
31
|
+
}))
|
|
31
32
|
|
|
32
|
-
const result =
|
|
33
|
+
const result = yarnListInjected(packageName)
|
|
33
34
|
|
|
34
35
|
expect(result.size).toBe(0)
|
|
35
36
|
})
|
|
36
37
|
|
|
37
38
|
it('should throw an error for invalid response', () => {
|
|
38
|
-
|
|
39
|
+
runSyncMock.mockReturnValueOnce({
|
|
39
40
|
stdout: invalidResponseMock,
|
|
40
41
|
})
|
|
41
42
|
|
|
42
43
|
expect(() => {
|
|
43
|
-
|
|
44
|
+
yarnListInjected(packageName)
|
|
44
45
|
}).toThrow('Unexpected token i in JSON at position 0')
|
|
45
46
|
})
|
|
46
47
|
|
|
47
48
|
it('should throw an error for empty response', () => {
|
|
48
|
-
|
|
49
|
+
runSyncMock.mockReturnValueOnce({
|
|
49
50
|
stdout: '',
|
|
50
51
|
})
|
|
51
52
|
|
|
52
53
|
expect(() => {
|
|
53
|
-
|
|
54
|
+
yarnListInjected(packageName)
|
|
54
55
|
}).toThrow('Unexpected end of JSON input')
|
|
55
56
|
})
|
|
56
57
|
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const yaml = require('js-yaml')
|
|
3
|
-
|
|
4
|
-
const files = require('./files')
|
|
5
|
-
|
|
6
|
-
const path = files.getProjectRootFilePath('./davinci.yaml')
|
|
7
|
-
const data = fs.existsSync(path) ? yaml.load(fs.readFileSync(path, 'utf8')) : {}
|
|
8
|
-
const resolve = (sectionName, key) =>
|
|
9
|
-
Boolean(data && resolveKey(data[sectionName], key))
|
|
10
|
-
const resolveKey = (section, key) => section && section[key]
|
|
11
|
-
const resolveArray = (sectionName, key, defaultValue = []) =>
|
|
12
|
-
data?.[sectionName]?.[key] || defaultValue
|
|
13
|
-
|
|
14
|
-
const davinciProjectConfig = {
|
|
15
|
-
master: {
|
|
16
|
-
conventionalCommits: resolve('master', 'conventional_commits'),
|
|
17
|
-
deploy: resolve('master', 'deploy'),
|
|
18
|
-
deployStaging: resolve('master', 'deploy_staging'),
|
|
19
|
-
requireAssignee: resolve('master', 'require_assignee'),
|
|
20
|
-
requireAssigneeWhitelist: resolveArray(
|
|
21
|
-
'master',
|
|
22
|
-
'require_assignee_whitelist',
|
|
23
|
-
['dependabot-preview[bot]', 'dependabot[bot]']
|
|
24
|
-
),
|
|
25
|
-
publishAsPackage: resolve('master', 'publish_as_package'),
|
|
26
|
-
},
|
|
27
|
-
pr: {
|
|
28
|
-
contractTesting: resolve('pr', 'contract_testing'),
|
|
29
|
-
},
|
|
30
|
-
isProgressiveWebApp: Boolean(resolveKey(data, 'is_progressive_web_app')),
|
|
31
|
-
serviceWorkerFileName: resolveKey(data, 'service_worker_filename'),
|
|
32
|
-
safetyWorkers: resolveKey(data, 'safety_workers'),
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports = davinciProjectConfig
|