@toptal/davinci-monorepo 8.2.0 → 8.2.1

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,17 @@
1
1
  # @toptal/davinci-monorepo
2
2
 
3
+ ## 8.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2021](https://github.com/toptal/davinci/pull/2021) [`97abce92`](https://github.com/toptal/davinci/commit/97abce922d3a0720e0806ae9cd2f2866f355a1bc) Thanks [@dmaklygin](https://github.com/dmaklygin)!
8
+
9
+ ---
10
+
11
+ - standardize command syntax for consistency
12
+ - Updated dependencies [[`97abce92`](https://github.com/toptal/davinci/commit/97abce922d3a0720e0806ae9cd2f2866f355a1bc)]:
13
+ - @toptal/davinci-cli-shared@2.3.1
14
+
3
15
  ## 8.2.0
4
16
 
5
17
  ### Minor Changes
@@ -1,22 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import cliEngine from '@toptal/davinci-cli-shared'
4
+ import { commands } from '../src/index.js'
4
5
 
5
- import detectCircularityCommand from '../src/commands/detect-circularity.js'
6
- import { createGraphGenerateCommand } from '../src/commands/graph-generate.js'
7
- import metricsCommand from '../src/commands/metrics.js'
8
- // eslint-disable-next-line no-restricted-syntax
9
- import codeownersCommand from '../src/commands/codeowners/index.js'
10
- import { createCoverageCommand } from '../src/commands/coverage-command/index.js'
11
-
12
- cliEngine.loadCommands(
13
- [
14
- detectCircularityCommand,
15
- createGraphGenerateCommand,
16
- metricsCommand,
17
- codeownersCommand,
18
- createCoverageCommand,
19
- ],
20
- 'davinci-monorepo'
21
- )
6
+ cliEngine.loadCommands(commands, 'davinci-monorepo')
22
7
  cliEngine.bootstrap()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toptal/davinci-monorepo",
3
- "version": "8.2.0",
3
+ "version": "8.2.1",
4
4
  "description": "Monorepo utility tools",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@oclif/core": "^1.16.1",
37
- "@toptal/davinci-cli-shared": "2.3.0",
37
+ "@toptal/davinci-cli-shared": "2.3.1",
38
38
  "chalk": "^4.1.2",
39
39
  "dependency-cruiser": "^12.5.0",
40
40
  "execa": "^5.1.1",
@@ -0,0 +1,47 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`createDetectCircularityCommand creates a command with the correct parameters 1`] = `
4
+ "{
5
+ "_events": {},
6
+ "_eventsCount": 0,
7
+ "commands": [],
8
+ "options": [],
9
+ "parent": null,
10
+ "_allowUnknownOption": false,
11
+ "_allowExcessArguments": true,
12
+ "_args": [],
13
+ "args": [],
14
+ "rawArgs": [],
15
+ "processedArgs": [],
16
+ "_scriptPath": null,
17
+ "_name": "detect-circularity",
18
+ "_optionValues": {},
19
+ "_optionValueSources": {},
20
+ "_storeOptionsAsProperties": false,
21
+ "_executableHandler": false,
22
+ "_executableFile": null,
23
+ "_executableDir": null,
24
+ "_defaultCommandName": null,
25
+ "_exitCallback": null,
26
+ "_aliases": [],
27
+ "_combineFlagAndOptionalValue": true,
28
+ "_description": "Detects circular dependencies in a monorepo",
29
+ "_summary": "",
30
+ "_enablePositionalOptions": false,
31
+ "_passThroughOptions": false,
32
+ "_lifeCycleHooks": {},
33
+ "_showHelpAfterError": false,
34
+ "_showSuggestionAfterError": true,
35
+ "_outputConfiguration": {},
36
+ "_hidden": false,
37
+ "_hasHelpOption": true,
38
+ "_helpFlags": "-h, --help",
39
+ "_helpDescription": "display help for command",
40
+ "_helpShortFlag": "-h",
41
+ "_helpLongFlag": "--help",
42
+ "_helpCommandName": "help",
43
+ "_helpCommandnameAndArgs": "help [command]",
44
+ "_helpCommandDescription": "display help for command",
45
+ "_helpConfiguration": {}
46
+ }"
47
+ `;
@@ -1,29 +1,105 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`metricsCommandCreator has the correct command structure 1`] = `
4
- {
5
- "action": [Function],
6
- "command": "metrics",
7
- "description": "Calculates and shows monorepo quality metrics.
8
- See: https://github.com/toptal/davinci/wiki/packages:monorepo:docs:metrics",
3
+ exports[`createMetricsCommand creates a command with the correct parameters 1`] = `
4
+ "{
5
+ "_events": {},
6
+ "_eventsCount": 4,
7
+ "commands": [],
9
8
  "options": [
10
9
  {
11
- "label": "set of metrics to calculate separated by commas",
12
- "name": "-m, --metric [metrics]",
10
+ "flags": "-m, --metric [metrics]",
11
+ "description": "set of metrics to calculate separated by commas",
12
+ "required": false,
13
+ "optional": true,
14
+ "variadic": false,
15
+ "mandatory": false,
16
+ "short": "-m",
17
+ "long": "--metric",
18
+ "negate": false,
19
+ "hidden": false,
20
+ "conflictsWith": []
13
21
  },
14
22
  {
15
- "label": "File pathname to save metrics in",
16
- "name": "-o, --output-path <outputPath>",
23
+ "flags": "-o, --output-path <outputPath>",
24
+ "description": "File pathname to save metrics in",
25
+ "required": true,
26
+ "optional": false,
27
+ "variadic": false,
28
+ "mandatory": false,
29
+ "short": "-o",
30
+ "long": "--output-path",
31
+ "negate": false,
32
+ "hidden": false,
33
+ "conflictsWith": []
17
34
  },
18
35
  {
19
- "default": "raw",
20
- "label": "Supported formats: raw, json, csv",
21
- "name": "-f, --format <format>",
36
+ "flags": "-f, --format <format>",
37
+ "description": "Supported formats: raw, json, csv",
38
+ "required": true,
39
+ "optional": false,
40
+ "variadic": false,
41
+ "mandatory": false,
42
+ "short": "-f",
43
+ "long": "--format",
44
+ "negate": false,
45
+ "defaultValue": "raw",
46
+ "hidden": false,
47
+ "conflictsWith": []
22
48
  },
23
49
  {
24
- "label": "List of packages to exclude from calculation separated by commas",
25
- "name": "-e, --exclude-packages <excludedPackages>",
26
- },
50
+ "flags": "-e, --exclude-packages <excludedPackages>",
51
+ "description": "List of packages to exclude from calculation separated by commas",
52
+ "required": true,
53
+ "optional": false,
54
+ "variadic": false,
55
+ "mandatory": false,
56
+ "short": "-e",
57
+ "long": "--exclude-packages",
58
+ "negate": false,
59
+ "hidden": false,
60
+ "conflictsWith": []
61
+ }
27
62
  ],
28
- }
63
+ "parent": null,
64
+ "_allowUnknownOption": false,
65
+ "_allowExcessArguments": true,
66
+ "_args": [],
67
+ "args": [],
68
+ "rawArgs": [],
69
+ "processedArgs": [],
70
+ "_scriptPath": null,
71
+ "_name": "metrics",
72
+ "_optionValues": {
73
+ "format": "raw"
74
+ },
75
+ "_optionValueSources": {
76
+ "format": "default"
77
+ },
78
+ "_storeOptionsAsProperties": false,
79
+ "_executableHandler": false,
80
+ "_executableFile": null,
81
+ "_executableDir": null,
82
+ "_defaultCommandName": null,
83
+ "_exitCallback": null,
84
+ "_aliases": [],
85
+ "_combineFlagAndOptionalValue": true,
86
+ "_description": "Calculates and shows monorepo quality metrics. \\n See: https://github.com/toptal/davinci/wiki/packages:monorepo:docs:metrics",
87
+ "_summary": "",
88
+ "_enablePositionalOptions": false,
89
+ "_passThroughOptions": false,
90
+ "_lifeCycleHooks": {},
91
+ "_showHelpAfterError": false,
92
+ "_showSuggestionAfterError": true,
93
+ "_outputConfiguration": {},
94
+ "_hidden": false,
95
+ "_hasHelpOption": true,
96
+ "_helpFlags": "-h, --help",
97
+ "_helpDescription": "display help for command",
98
+ "_helpShortFlag": "-h",
99
+ "_helpLongFlag": "--help",
100
+ "_helpCommandName": "help",
101
+ "_helpCommandnameAndArgs": "help [command]",
102
+ "_helpCommandDescription": "display help for command",
103
+ "_helpConfiguration": {}
104
+ }"
29
105
  `;
@@ -5,7 +5,7 @@ import listCommand from './commands/list.js'
5
5
  import ownersInformationCommand from './commands/owners-information.js'
6
6
  import packagesInformationCommand from './commands/packages-information.js'
7
7
 
8
- const codeownersCommand = program => {
8
+ export const createCodeownersCommand = program => {
9
9
  const codeowners = program
10
10
  .createCommand('codeowners')
11
11
  .description(
@@ -23,5 +23,3 @@ const codeownersCommand = program => {
23
23
  }
24
24
 
25
25
  export { asyncCodeownersImport } from './services/async-codeowners-import/async-codeowners-import.js'
26
-
27
- export default codeownersCommand
@@ -5,10 +5,8 @@ import getWorkspaces from '../utils/get-workspaces.js'
5
5
  import makeWorkspacesGraph from '../utils/make-workspaces-graph.js'
6
6
  import getGraphCyclePaths from '../utils/get-graph-cycle-paths.js'
7
7
  import getCircularityErrorMessage from '../utils/get-circularity-error-message.js'
8
-
9
8
  const detectCircularityCommand = () => {
10
9
  print.header('Running circular dependencies check')
11
-
12
10
  const workspaces = getWorkspaces(path.resolve())
13
11
  const workspacesGraph = makeWorkspacesGraph(workspaces)
14
12
  const cyclePaths = getGraphCyclePaths(workspacesGraph)
@@ -17,14 +15,12 @@ const detectCircularityCommand = () => {
17
15
  print.red(getCircularityErrorMessage(cyclePaths))
18
16
  process.exit(1)
19
17
  }
20
-
21
18
  print.success('No circular dependencies found.')
22
19
  }
23
20
 
24
- const detectCircularityCommandCreator = {
25
- action: detectCircularityCommand,
26
- command: 'detect-circularity',
27
- description: 'Detects circular dependencies in a monorepo',
21
+ export const createDetectCircularityCommand = program => {
22
+ return program
23
+ .createCommand('detect-circularity')
24
+ .description('Detects circular dependencies in a monorepo')
25
+ .action(detectCircularityCommand)
28
26
  }
29
-
30
- export default detectCircularityCommandCreator
@@ -0,0 +1,26 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+ import { jest } from '@jest/globals'
3
+ // eslint-disable-next-line import/no-extraneous-dependencies
4
+ import { Command } from 'commander'
5
+
6
+ const { createDetectCircularityCommand } = await import(
7
+ './detect-circularity.js'
8
+ )
9
+
10
+ describe('createDetectCircularityCommand', () => {
11
+ let program
12
+
13
+ beforeEach(() => {
14
+ program = new Command()
15
+ })
16
+
17
+ afterEach(() => {
18
+ jest.clearAllMocks()
19
+ })
20
+
21
+ it('creates a command with the correct parameters', () => {
22
+ const command = createDetectCircularityCommand(program)
23
+
24
+ expect(JSON.stringify(command, null, 2)).toMatchSnapshot()
25
+ })
26
+ })
@@ -12,11 +12,9 @@ import fs from 'fs'
12
12
  import metrics from '../services/metrics/index.js'
13
13
  import { raw, csv, json } from '../services/renderers/index.js'
14
14
  import { getLernaGraph } from '../utils/index.js'
15
-
16
15
  const defaultMetricKeysList = metrics.reduce((acc, { info }) => {
17
16
  return acc.concat(Object.keys(info))
18
17
  }, [])
19
-
20
18
  const getSelectedMetrics = (metrics, metricKeys = []) => {
21
19
  if (!metricKeys.length) {
22
20
  return metrics
@@ -26,7 +24,6 @@ const getSelectedMetrics = (metrics, metricKeys = []) => {
26
24
  ({ info }) => length(intersection(keys(info), metricKeys)) > 0
27
25
  )
28
26
  }
29
-
30
27
  const proceedPackagesMetric = (packagesGraph, metrics, metricKeysList = []) => {
31
28
  const packageNames = Object.keys(packagesGraph)
32
29
  let packages = {}
@@ -41,7 +38,6 @@ const proceedPackagesMetric = (packagesGraph, metrics, metricKeysList = []) => {
41
38
  ),
42
39
  }
43
40
  })
44
-
45
41
  packages = Object.keys(packages).reduce((acc, packageName) => {
46
42
  const packageInfo = packages[packageName]
47
43
 
@@ -54,7 +50,6 @@ const proceedPackagesMetric = (packagesGraph, metrics, metricKeysList = []) => {
54
50
 
55
51
  return acc
56
52
  }
57
-
58
53
  acc[packageName] = packageInfo
59
54
 
60
55
  return acc
@@ -64,7 +59,6 @@ const proceedPackagesMetric = (packagesGraph, metrics, metricKeysList = []) => {
64
59
  return metrics.reduce(
65
60
  (previousValue, metric) => {
66
61
  const { info, calculate } = metric
67
-
68
62
  const filteredMetricList = intersection(metricKeysList, keys(info))
69
63
 
70
64
  filteredMetricList.forEach(metricKey => {
@@ -77,12 +71,18 @@ const proceedPackagesMetric = (packagesGraph, metrics, metricKeysList = []) => {
77
71
  : [calculate]
78
72
 
79
73
  return reduce(
80
- (acc, fn) => mergeDeepRight(acc, { packagesInfo: fn(acc) }),
74
+ (acc, fn) =>
75
+ mergeDeepRight(acc, {
76
+ packagesInfo: fn(acc),
77
+ }),
81
78
  previousValue,
82
79
  calculationChain
83
80
  )
84
81
  },
85
- { metricInfo: {}, packagesInfo: packages }
82
+ {
83
+ metricInfo: {},
84
+ packagesInfo: packages,
85
+ }
86
86
  )
87
87
  }
88
88
 
@@ -92,14 +92,12 @@ const proceedPackagesMetric = (packagesGraph, metrics, metricKeysList = []) => {
92
92
  */
93
93
  const metricsCommand = options => {
94
94
  print.header('Start calculating quality metrics')
95
-
96
95
  const {
97
96
  metric: metricKeys = '',
98
97
  format,
99
98
  outputPath,
100
99
  excludedPackages = '',
101
100
  } = options
102
-
103
101
  const metricKeysList = metricKeys
104
102
  ? metricKeys.split(',')
105
103
  : defaultMetricKeysList
@@ -115,7 +113,6 @@ const metricsCommand = options => {
115
113
  print.red(err)
116
114
  process.exit(1)
117
115
  }
118
-
119
116
  print.green('Searching for metrics information...')
120
117
  const filteredMetrics = getSelectedMetrics(metrics, metricKeysList)
121
118
 
@@ -123,7 +120,6 @@ const metricsCommand = options => {
123
120
  print.red('Metric not found')
124
121
  process.exit(1)
125
122
  }
126
-
127
123
  print.green('Calculating metrics...')
128
124
 
129
125
  // for each metric procedure, we have to go through the list of packages
@@ -132,7 +128,6 @@ const metricsCommand = options => {
132
128
  filteredMetrics,
133
129
  metricKeysList
134
130
  )
135
-
136
131
  let output
137
132
 
138
133
  switch (format) {
@@ -145,7 +140,6 @@ const metricsCommand = options => {
145
140
  default:
146
141
  output = raw(metricInfo, packagesInfo)
147
142
  }
148
-
149
143
  if (outputPath) {
150
144
  try {
151
145
  fs.writeFileSync(outputPath, output)
@@ -159,30 +153,24 @@ const metricsCommand = options => {
159
153
  }
160
154
  }
161
155
 
162
- const metricsCommandCreator = {
163
- action: metricsCommand,
164
- command: 'metrics',
165
- description:
166
- 'Calculates and shows monorepo quality metrics. \n See: https://github.com/toptal/davinci/wiki/packages:monorepo:docs:metrics',
167
- options: [
168
- {
169
- name: '-m, --metric [metrics]',
170
- label: 'set of metrics to calculate separated by commas',
171
- },
172
- {
173
- name: '-o, --output-path <outputPath>',
174
- label: 'File pathname to save metrics in',
175
- },
176
- {
177
- name: '-f, --format <format>',
178
- label: 'Supported formats: raw, json, csv',
179
- default: 'raw',
180
- },
181
- {
182
- name: '-e, --exclude-packages <excludedPackages>',
183
- label: 'List of packages to exclude from calculation separated by commas',
184
- },
185
- ],
156
+ export const createMetricsCommand = program => {
157
+ return program
158
+ .createCommand('metrics')
159
+ .description(
160
+ 'Calculates and shows monorepo quality metrics. \n See: https://github.com/toptal/davinci/wiki/packages:monorepo:docs:metrics'
161
+ )
162
+ .action(metricsCommand)
163
+ .option(
164
+ '-m, --metric [metrics]',
165
+ 'set of metrics to calculate separated by commas'
166
+ )
167
+ .option(
168
+ '-o, --output-path <outputPath>',
169
+ 'File pathname to save metrics in'
170
+ )
171
+ .option('-f, --format <format>', 'Supported formats: raw, json, csv', 'raw')
172
+ .option(
173
+ '-e, --exclude-packages <excludedPackages>',
174
+ 'List of packages to exclude from calculation separated by commas'
175
+ )
186
176
  }
187
-
188
- export default metricsCommandCreator
@@ -1,7 +1,24 @@
1
- import metricsCommandCreator from './metrics.js'
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+ import { jest } from '@jest/globals'
3
+ // eslint-disable-next-line import/no-extraneous-dependencies
4
+ import { Command } from 'commander'
2
5
 
3
- describe('metricsCommandCreator', () => {
4
- it('has the correct command structure', () => {
5
- expect(metricsCommandCreator).toMatchSnapshot()
6
+ const { createMetricsCommand } = await import('./metrics.js')
7
+
8
+ describe('createMetricsCommand', () => {
9
+ let program
10
+
11
+ beforeEach(() => {
12
+ program = new Command()
13
+ })
14
+
15
+ afterEach(() => {
16
+ jest.clearAllMocks()
17
+ })
18
+
19
+ it('creates a command with the correct parameters', () => {
20
+ const command = createMetricsCommand(program)
21
+
22
+ expect(JSON.stringify(command, null, 2)).toMatchSnapshot()
6
23
  })
7
24
  })
package/src/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import detectCircularityCommandCreator from './commands/detect-circularity.js'
2
- import metricsCommandCreator from './commands/metrics.js'
1
+ import { createDetectCircularityCommand } from './commands/detect-circularity.js'
2
+ import { createMetricsCommand } from './commands/metrics.js'
3
3
  import { createGraphGenerateCommand } from './commands/graph-generate.js'
4
- import codeownersCommand from './commands/codeowners/index.js'
4
+ import { createCodeownersCommand } from './commands/codeowners/index.js'
5
5
  import { createCoverageCommand } from './commands/coverage-command/index.js'
6
6
  import checkIfMonorepo from './utils/check-if-monorepo.js'
7
7
  import getPackages from './utils/get-packages.js'
@@ -12,10 +12,10 @@ export const utils = {
12
12
  }
13
13
 
14
14
  export const commands = [
15
- detectCircularityCommandCreator,
16
- metricsCommandCreator,
15
+ createDetectCircularityCommand,
16
+ createMetricsCommand,
17
17
  createGraphGenerateCommand,
18
- codeownersCommand,
18
+ createCodeownersCommand,
19
19
  createCoverageCommand,
20
20
  ]
21
21