@eclipse-glsp/cli 2.2.1 → 2.3.0-next.17

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.
Files changed (138) hide show
  1. package/README.md +143 -38
  2. package/dist/cli.js +21959 -0
  3. package/dist/cli.js.map +6 -0
  4. package/package.json +22 -29
  5. package/bin/glsp +0 -2
  6. package/lib/app.d.ts +0 -3
  7. package/lib/app.d.ts.map +0 -1
  8. package/lib/app.js +0 -36
  9. package/lib/app.js.map +0 -1
  10. package/lib/commands/check-header.d.ts +0 -21
  11. package/lib/commands/check-header.d.ts.map +0 -1
  12. package/lib/commands/check-header.js +0 -240
  13. package/lib/commands/check-header.js.map +0 -1
  14. package/lib/commands/checkout.d.ts +0 -27
  15. package/lib/commands/checkout.d.ts.map +0 -1
  16. package/lib/commands/checkout.js +0 -41
  17. package/lib/commands/checkout.js.map +0 -1
  18. package/lib/commands/coverage-report.d.ts +0 -29
  19. package/lib/commands/coverage-report.d.ts.map +0 -1
  20. package/lib/commands/coverage-report.js +0 -126
  21. package/lib/commands/coverage-report.js.map +0 -1
  22. package/lib/commands/generate-index.d.ts +0 -46
  23. package/lib/commands/generate-index.d.ts.map +0 -1
  24. package/lib/commands/generate-index.js +0 -172
  25. package/lib/commands/generate-index.js.map +0 -1
  26. package/lib/commands/release/common.d.ts +0 -68
  27. package/lib/commands/release/common.d.ts.map +0 -1
  28. package/lib/commands/release/common.js +0 -293
  29. package/lib/commands/release/common.js.map +0 -1
  30. package/lib/commands/release/release-client.d.ts +0 -3
  31. package/lib/commands/release/release-client.d.ts.map +0 -1
  32. package/lib/commands/release/release-client.js +0 -57
  33. package/lib/commands/release/release-client.js.map +0 -1
  34. package/lib/commands/release/release-eclipse-integration.d.ts +0 -18
  35. package/lib/commands/release/release-eclipse-integration.d.ts.map +0 -1
  36. package/lib/commands/release/release-eclipse-integration.js +0 -92
  37. package/lib/commands/release/release-eclipse-integration.js.map +0 -1
  38. package/lib/commands/release/release-java-server.d.ts +0 -3
  39. package/lib/commands/release/release-java-server.d.ts.map +0 -1
  40. package/lib/commands/release/release-java-server.js +0 -70
  41. package/lib/commands/release/release-java-server.js.map +0 -1
  42. package/lib/commands/release/release-server-node.d.ts +0 -18
  43. package/lib/commands/release/release-server-node.d.ts.map +0 -1
  44. package/lib/commands/release/release-server-node.js +0 -53
  45. package/lib/commands/release/release-server-node.js.map +0 -1
  46. package/lib/commands/release/release-theia-integration.d.ts +0 -18
  47. package/lib/commands/release/release-theia-integration.d.ts.map +0 -1
  48. package/lib/commands/release/release-theia-integration.js +0 -53
  49. package/lib/commands/release/release-theia-integration.js.map +0 -1
  50. package/lib/commands/release/release-vscode-integration.d.ts +0 -18
  51. package/lib/commands/release/release-vscode-integration.d.ts.map +0 -1
  52. package/lib/commands/release/release-vscode-integration.js +0 -53
  53. package/lib/commands/release/release-vscode-integration.js.map +0 -1
  54. package/lib/commands/release/release.d.ts +0 -14
  55. package/lib/commands/release/release.d.ts.map +0 -1
  56. package/lib/commands/release/release.js +0 -191
  57. package/lib/commands/release/release.js.map +0 -1
  58. package/lib/commands/repo/clone.d.ts +0 -28
  59. package/lib/commands/repo/clone.d.ts.map +0 -1
  60. package/lib/commands/repo/clone.js +0 -113
  61. package/lib/commands/repo/clone.js.map +0 -1
  62. package/lib/commands/repo/clone.spec.d.ts +0 -17
  63. package/lib/commands/repo/clone.spec.d.ts.map +0 -1
  64. package/lib/commands/repo/clone.spec.js +0 -126
  65. package/lib/commands/repo/clone.spec.js.map +0 -1
  66. package/lib/commands/repo/common.d.ts +0 -23
  67. package/lib/commands/repo/common.d.ts.map +0 -1
  68. package/lib/commands/repo/common.js +0 -18
  69. package/lib/commands/repo/common.js.map +0 -1
  70. package/lib/commands/repo/config.d.ts +0 -18
  71. package/lib/commands/repo/config.d.ts.map +0 -1
  72. package/lib/commands/repo/config.js +0 -28
  73. package/lib/commands/repo/config.js.map +0 -1
  74. package/lib/commands/repo/repo.d.ts +0 -17
  75. package/lib/commands/repo/repo.d.ts.map +0 -1
  76. package/lib/commands/repo/repo.js +0 -25
  77. package/lib/commands/repo/repo.js.map +0 -1
  78. package/lib/commands/update-next.d.ts +0 -20
  79. package/lib/commands/update-next.d.ts.map +0 -1
  80. package/lib/commands/update-next.js +0 -146
  81. package/lib/commands/update-next.js.map +0 -1
  82. package/lib/common/glsp-component.d.ts +0 -27
  83. package/lib/common/glsp-component.d.ts.map +0 -1
  84. package/lib/common/glsp-component.js +0 -13
  85. package/lib/common/glsp-component.js.map +0 -1
  86. package/lib/common/glsp-repo.d.ts +0 -44
  87. package/lib/common/glsp-repo.d.ts.map +0 -1
  88. package/lib/common/glsp-repo.js +0 -135
  89. package/lib/common/glsp-repo.js.map +0 -1
  90. package/lib/common/glsp-repo.spec.d.ts +0 -17
  91. package/lib/common/glsp-repo.spec.d.ts.map +0 -1
  92. package/lib/common/glsp-repo.spec.js +0 -130
  93. package/lib/common/glsp-repo.spec.js.map +0 -1
  94. package/lib/foo.spec.d.ts +0 -17
  95. package/lib/foo.spec.d.ts.map +0 -1
  96. package/lib/foo.spec.js +0 -23
  97. package/lib/foo.spec.js.map +0 -1
  98. package/lib/index.d.ts +0 -18
  99. package/lib/index.d.ts.map +0 -1
  100. package/lib/index.js +0 -18
  101. package/lib/index.js.map +0 -1
  102. package/lib/util/command-util.d.ts +0 -26
  103. package/lib/util/command-util.d.ts.map +0 -1
  104. package/lib/util/command-util.js +0 -59
  105. package/lib/util/command-util.js.map +0 -1
  106. package/lib/util/git-util.d.ts +0 -42
  107. package/lib/util/git-util.d.ts.map +0 -1
  108. package/lib/util/git-util.js +0 -124
  109. package/lib/util/git-util.js.map +0 -1
  110. package/lib/util/logger.d.ts +0 -23
  111. package/lib/util/logger.d.ts.map +0 -1
  112. package/lib/util/logger.js +0 -50
  113. package/lib/util/logger.js.map +0 -1
  114. package/lib/util/test-util.spec.d.ts +0 -2
  115. package/lib/util/test-util.spec.d.ts.map +0 -1
  116. package/lib/util/test-util.spec.js +0 -44
  117. package/lib/util/test-util.spec.js.map +0 -1
  118. package/lib/util/validation-util.d.ts +0 -5
  119. package/lib/util/validation-util.d.ts.map +0 -1
  120. package/lib/util/validation-util.js +0 -85
  121. package/lib/util/validation-util.js.map +0 -1
  122. package/src/app.ts +0 -35
  123. package/src/commands/check-header.ts +0 -280
  124. package/src/commands/coverage-report.ts +0 -113
  125. package/src/commands/generate-index.ts +0 -169
  126. package/src/commands/release/common.ts +0 -306
  127. package/src/commands/release/release-client.ts +0 -55
  128. package/src/commands/release/release-eclipse-integration.ts +0 -113
  129. package/src/commands/release/release-java-server.ts +0 -73
  130. package/src/commands/release/release-server-node.ts +0 -61
  131. package/src/commands/release/release-theia-integration.ts +0 -65
  132. package/src/commands/release/release-vscode-integration.ts +0 -67
  133. package/src/commands/release/release.ts +0 -215
  134. package/src/commands/update-next.ts +0 -129
  135. package/src/util/command-util.ts +0 -54
  136. package/src/util/git-util.ts +0 -123
  137. package/src/util/logger.ts +0 -57
  138. package/src/util/validation-util.ts +0 -62
@@ -1,280 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2022-2024 EclipseSource and others.
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * This Source Code may also be made available under the following Secondary
9
- * Licenses when the conditions for such availability set forth in the Eclipse
10
- * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- * with the GNU Classpath Exception which is available at
12
- * https://www.gnu.org/software/classpath/license.html.
13
- *
14
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
- ********************************************************************************/
16
- /* eslint-disable max-len */
17
- import { Option } from 'commander';
18
- import * as fs from 'fs';
19
- import { glob } from 'glob';
20
- import * as minimatch from 'minimatch';
21
- import * as readline from 'readline-sync';
22
- import sh from 'shelljs';
23
- import { baseCommand, configureShell, getShellConfig } from '../util/command-util';
24
- import { getChangesOfLastCommit, getLastModificationDate, getUncommittedChanges } from '../util/git-util';
25
-
26
- import * as path from 'path';
27
- import { LOGGER } from '../util/logger';
28
- import { validateGitDirectory } from '../util/validation-util';
29
-
30
- export interface HeaderCheckOptions {
31
- type: CheckType;
32
- exclude: string[];
33
- fileExtensions: string[];
34
- json: boolean;
35
- excludeDefaults: boolean;
36
- autoFix: boolean;
37
- }
38
-
39
- const checkTypes = ['full', 'changes', 'lastCommit'] as const;
40
- type CheckType = (typeof checkTypes)[number];
41
-
42
- const DEFAULT_EXCLUDES = ['**/@(node_modules|lib|dist|bundle)/**'];
43
- const YEAR_RANGE_REGEX = /\d{4}/g;
44
- const HEADER_PATTERN = 'Copyright \\([cC]\\) \\d{4}';
45
- const AUTO_FIX_MESSAGE = 'Fix copyright header violations';
46
-
47
- export const CheckHeaderCommand = baseCommand() //
48
- .name('checkHeaders')
49
- .description('Validates the copyright year range (end year) of license header files')
50
- .argument('<rootDir>', 'The starting directory for the check', validateGitDirectory)
51
- .addOption(
52
- new Option(
53
- '-t, --type <type>',
54
- 'The scope of the check. In addition to a full recursive check, is also possible to only' +
55
- ' consider pending changes or the last commit'
56
- )
57
- .choices(checkTypes)
58
- .default('full')
59
- )
60
- .option('-f, --fileExtensions <extensions...>', 'File extensions that should be checked', ['ts', 'tsx'])
61
- .addOption(
62
- new Option(
63
- '-e, --exclude <exclude...>',
64
- 'File patterns that should be excluded from the check. New exclude patterns are added to the default patterns'
65
- ).default([], `[${DEFAULT_EXCLUDES}]`)
66
- )
67
- .option(
68
- '--no-exclude-defaults',
69
- 'Disables the default excludes patterns. Only explicitly passed exclude patterns (-e, --exclude) are considered'
70
- )
71
- .option('-j, --json', 'Also persist validation results as json file', false)
72
- .option('-a, --autoFix', 'Auto apply & commit fixes without prompting the user', false)
73
- .action(checkHeaders);
74
-
75
- export function checkHeaders(rootDir: string, options: HeaderCheckOptions): void {
76
- configureShell({ silent: true, fatal: true });
77
-
78
- if (options.excludeDefaults) {
79
- options.exclude.push(...DEFAULT_EXCLUDES);
80
- }
81
-
82
- sh.cd(rootDir);
83
- const files = getFiles(rootDir, options);
84
- LOGGER.info(`Check copy right headers of ${files.length} files`);
85
- if (files.length === 0) {
86
- LOGGER.info('Check completed');
87
- return;
88
- }
89
- const results = validate(rootDir, files, options);
90
- handleValidationResults(rootDir, results, options);
91
- }
92
-
93
- function getFiles(rootDir: string, options: HeaderCheckOptions): string[] {
94
- const includePattern = `**/*.@(${options.fileExtensions.join('|')})`;
95
- const excludePattern = options.exclude;
96
-
97
- if (options.type === 'full') {
98
- return glob.sync(includePattern, {
99
- cwd: rootDir,
100
- ignore: excludePattern
101
- });
102
- }
103
-
104
- let changedFiles = options.type === 'changes' ? getUncommittedChanges(rootDir) : getChangesOfLastCommit(rootDir);
105
- changedFiles = changedFiles.filter(minimatch.filter(includePattern));
106
-
107
- excludePattern.forEach(pattern => {
108
- changedFiles = changedFiles.filter(minimatch.filter(`!${pattern}`));
109
- });
110
- return changedFiles.filter(file => fs.existsSync(file));
111
- }
112
-
113
- function validate(rootDir: string, files: string[], options: HeaderCheckOptions): ValidationResult[] {
114
- // Derives all files with valid headers and all files with no or invalid headers
115
- const filesWithHeader = sh.grep('-l', HEADER_PATTERN, files).stdout.trim().split('\n');
116
- const noHeaders = files.filter(file => !filesWithHeader.includes(file));
117
-
118
- const results: ValidationResult[] = [];
119
- const allFilesLength = files.length;
120
-
121
- // Create validation results for all files with no or invalid headers
122
- const noHeadersLength = noHeaders.length;
123
- if (noHeadersLength > 0) {
124
- LOGGER.info(`Found ${noHeadersLength} files with no (or an invalid) copyright header`);
125
- }
126
- noHeaders.forEach((file, i) => {
127
- printFileProgress(i + 1, allFilesLength, `Validating ${file}`);
128
- results.push({ file: path.resolve(rootDir, file), violation: 'noOrMissingHeader' });
129
- });
130
-
131
- // Performance optimization: avoid retrieving the dates for each individual file by precalculating the endYear if possible.
132
- let defaultEndYear: number | undefined;
133
- if (options.type === 'changes') {
134
- defaultEndYear = new Date().getFullYear();
135
- } else if (options.type === 'lastCommit') {
136
- defaultEndYear = getLastModificationDate(undefined, rootDir)?.getFullYear();
137
- }
138
-
139
- // Create validation results for all files with valid headers
140
- filesWithHeader.forEach((file, i) => {
141
- printFileProgress(i + 1 + noHeadersLength, allFilesLength, `Validating ${file}`);
142
- const copyrightLine = sh.head({ '-n': 2 }, file).stdout.trim().split('\n')[1];
143
- const copyRightYears = copyrightLine.match(YEAR_RANGE_REGEX)!;
144
- if (!copyRightYears) {
145
- const result: ValidationResult = { file, violation: 'noYear', line: copyrightLine };
146
- results.push(result);
147
- } else {
148
- const currentStartYear = Number.parseInt(copyRightYears[0], 10);
149
- const currentEndYear = copyRightYears[1] ? Number.parseInt(copyRightYears[1], 10) : undefined;
150
- const result: DateValidationResult = {
151
- currentStartYear,
152
- currentEndYear,
153
- expectedEndYear: defaultEndYear ?? getLastModificationDate(file, rootDir, AUTO_FIX_MESSAGE)!.getFullYear(),
154
- file,
155
- violation: 'none'
156
- };
157
- validateEndYear(result);
158
- results.push(result);
159
- }
160
- });
161
-
162
- results.sort((a, b) => a.file.localeCompare(b.file));
163
-
164
- process.stdout.clearLine(0);
165
- return results;
166
- }
167
-
168
- function validateEndYear(result: DateValidationResult): void {
169
- const { currentStartYear, expectedEndYear, currentEndYear } = result;
170
- result.violation = 'invalidEndYear';
171
-
172
- const valid = currentEndYear ? currentEndYear === expectedEndYear : currentStartYear === expectedEndYear;
173
-
174
- if (valid) {
175
- result.violation = 'none';
176
- return;
177
- }
178
- }
179
-
180
- function printFileProgress(currentFileCount: number, maxFileCount: number, message: string, clear = true): void {
181
- if (clear) {
182
- process.stdout.clearLine(0);
183
- process.stdout.cursorTo(0);
184
- }
185
- process.stdout.write(`[${currentFileCount} of ${maxFileCount}] ${message}`);
186
- if (!clear) {
187
- process.stdout.write('\n');
188
- }
189
- }
190
-
191
- export function handleValidationResults(rootDir: string, results: ValidationResult[], options: HeaderCheckOptions): void {
192
- LOGGER.newLine();
193
- LOGGER.info(`Header validation for ${results.length} files completed`);
194
- const violations = results.filter(result => result.violation !== 'none');
195
- // Adjust results to print based on configured severity level
196
- const toPrint = violations;
197
-
198
- LOGGER.info(`Found ${toPrint.length} copyright header violations:`);
199
- LOGGER.newLine();
200
-
201
- toPrint.forEach((result, i) => LOGGER.info(`${i + 1}. `, result.file, ':', toPrintMessage(result)));
202
-
203
- LOGGER.newLine();
204
-
205
- if (options.json) {
206
- fs.writeFileSync(path.join(rootDir, 'headerCheck.json'), JSON.stringify(results, undefined, 2));
207
- }
208
-
209
- if (
210
- violations.length > 0 &&
211
- (options.autoFix || readline.keyInYN('Do you want to automatically fix copyright year range violations?'))
212
- ) {
213
- const toFix = violations.filter(violation => isDateValidationResult(violation)) as DateValidationResult[];
214
- fixViolations(rootDir, toFix, options);
215
- }
216
-
217
- LOGGER.info('Check completed');
218
- }
219
-
220
- function toPrintMessage(result: ValidationResult): string {
221
- const error = '\x1b[31m';
222
- const info = '\x1b[32m';
223
-
224
- if (isDateValidationResult(result) && result.violation === 'invalidEndYear') {
225
- const expected = result.expectedEndYear.toString();
226
- const actual = result.currentEndYear
227
- ? `${result.currentEndYear} (${result.currentStartYear}-${result.currentEndYear})`
228
- : result.currentStartYear.toString();
229
- const message = 'Invalid copyright end year';
230
- return `${error} ${message}! Expected end year '${expected}' but is '${actual}'`;
231
- } else if (result.violation === 'noOrMissingHeader') {
232
- return `${error} No or invalid copyright header!`;
233
- } else if (result.violation === 'noYear') {
234
- return `${error} No year found!${result.line ? ' (line: ' + result.line + ')' : ''}`;
235
- }
236
-
237
- return `${info} OK`;
238
- }
239
-
240
- function fixViolations(rootDir: string, violations: DateValidationResult[], options: HeaderCheckOptions): void {
241
- LOGGER.newLine();
242
- violations.forEach((violation, i) => {
243
- printFileProgress(i + 1, violations.length, `Fix ${violation.file}`, false);
244
-
245
- const currentRange = `${violation.currentStartYear}${violation.currentEndYear ? '-' + violation.currentEndYear : ''}`;
246
- const fixedRange =
247
- violation.currentEndYear || violation.currentStartYear < violation.expectedEndYear
248
- ? `${violation.currentStartYear}-${violation.expectedEndYear}`
249
- : `${violation.expectedEndYear}`;
250
-
251
- sh.sed('-i', RegExp('Copyright \\([cC]\\) ' + currentRange), `Copyright (c) ${fixedRange}`, violation.file);
252
- });
253
- LOGGER.newLine();
254
- if (options.autoFix || readline.keyInYN('Do you want to create a commit for the fixed files?')) {
255
- LOGGER.newLine();
256
- const files = violations.map(violation => violation.file).join(' ');
257
- sh.exec(`git add ${files}`, getShellConfig());
258
- sh.exec(`git commit -m "${AUTO_FIX_MESSAGE}"`);
259
- LOGGER.newLine();
260
- }
261
- }
262
-
263
- // Helper types
264
- interface ValidationResult {
265
- file: string;
266
- violation: Violation;
267
- line?: string;
268
- }
269
-
270
- interface DateValidationResult extends ValidationResult {
271
- currentStartYear: number;
272
- currentEndYear?: number;
273
- expectedEndYear: number;
274
- }
275
-
276
- function isDateValidationResult(object: ValidationResult): object is DateValidationResult {
277
- return 'currentStartYear' in object && 'expectedEndYear' in object;
278
- }
279
-
280
- type Violation = 'none' | 'noOrMissingHeader' | 'invalidEndYear' | 'noYear';
@@ -1,113 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2022-2024 EclipseSource and others.
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * This Source Code may also be made available under the following Secondary
9
- * Licenses when the conditions for such availability set forth in the Eclipse
10
- * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- * with the GNU Classpath Exception which is available at
12
- * https://www.gnu.org/software/classpath/license.html.
13
- *
14
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
- ********************************************************************************/
16
-
17
- import * as fs from 'fs';
18
- import * as path from 'path';
19
- import sh from 'shelljs';
20
- import { baseCommand, fatalExec, getShellConfig } from '../util/command-util';
21
- import { LOGGER } from '../util/logger';
22
- import { validateDirectory } from '../util/validation-util';
23
-
24
- export interface CoverageCmdOptions {
25
- coverageScript: string;
26
- projectRoot: string;
27
- }
28
-
29
- export const CoverageReportCommand = baseCommand() //
30
- .name('coverageReport')
31
- .description('Generate a test coverage report for a glsp component')
32
- .option('-p, --projectRoot <projectRoot>', 'The root directory of the GLSP component', validateDirectory, process.cwd())
33
- .option('-c, --coverageScript <script>', 'Script command of the package root for creating coverage reports', 'test:coverage')
34
- .action(generateCoverageReport);
35
-
36
- /**
37
- * Generates and aggregates an 'nyc' coverage report for lerna/yarn mono repositories.
38
- * First, individual reports for each package are generated. Then, they are aggregated into one combined HTML report.
39
- * @param options configuration options
40
- */
41
- export function generateCoverageReport(options: CoverageCmdOptions): void {
42
- sh.cd(options.projectRoot);
43
- const packages = validateAndRetrievePackages(options);
44
- LOGGER.info('Create individual package coverage reports');
45
- const jsonReports = collectPackageReportFiles(packages, options);
46
- combineReports(jsonReports, options);
47
- LOGGER.info('Coverage reported generation successful');
48
- }
49
-
50
- export function validateAndRetrievePackages(options: CoverageCmdOptions): string[] {
51
- const packagePath = path.join(options.projectRoot, 'package.json');
52
- if (!fs.existsSync(packagePath)) {
53
- CoverageReportCommand.error(`Invalid root directory. '${options.projectRoot}' does not contain a package.json.`);
54
- }
55
-
56
- fatalExec('yarn nyc -h', 'Nyc is not installed!', getShellConfig({ silent: true }));
57
-
58
- const packageJson = JSON.parse(fs.readFileSync(packagePath).toString());
59
-
60
- if (!packageJson?.scripts?.[options.coverageScript]) {
61
- CoverageReportCommand.error(
62
- `Invalid coverage script! The package.json does not have a script with name '${options.coverageScript}'!`
63
- );
64
- }
65
-
66
- if (!Array.isArray(packageJson.workspaces)) {
67
- CoverageReportCommand.error('Invalid package.json! No yarn workspaces are configured!');
68
- }
69
- return (packageJson.workspaces as string[]).map(pkg => pkg.replace('/*', ''));
70
- }
71
-
72
- export function collectPackageReportFiles(packages: string[], options: CoverageCmdOptions): string[] {
73
- LOGGER.info('Create combined report');
74
- sh.exec(`yarn ${options.coverageScript}`);
75
- // collect reports
76
- const reports: string[] = [];
77
- packages.forEach(pkg => {
78
- sh.find(pkg)
79
- .filter(file => file.endsWith('coverage-final.json'))
80
- .forEach(json => reports.push(path.resolve(options.projectRoot, json)));
81
- });
82
- return reports;
83
- }
84
-
85
- function combineReports(reportFiles: string[], options: CoverageCmdOptions): void {
86
- // Copy coverage into root/.nyc_output
87
- const reportsDir = path.join(options.projectRoot, '.nyc_output');
88
- if (fs.existsSync(reportsDir)) {
89
- fs.rmSync(reportsDir, { force: true, recursive: true });
90
- }
91
- fs.mkdirSync(reportsDir);
92
-
93
- for (let i = 0; i < reportFiles.length; i++) {
94
- fs.copyFileSync(reportFiles[i], path.resolve('.nyc_output', `coverage-final-${i}.json`));
95
- }
96
-
97
- // Temporarily remove root nyc configs otherwise the report command might fail.
98
- sh.cd(options.projectRoot);
99
- const configFiles = ['.nycrc', '.nycrc.json', '.nyc-config.js'];
100
- const tempFiles: string[] = [];
101
- configFiles.forEach(config => {
102
- if (fs.existsSync(path.join(options.projectRoot, config))) {
103
- sh.mv(config, '_' + config);
104
- tempFiles.push('_' + config);
105
- }
106
- });
107
-
108
- // Generate report
109
- sh.exec('yarn nyc report --reporter html', getShellConfig());
110
-
111
- // Restore nyc configs (if any)
112
- tempFiles.forEach(config => sh.mv(config, config.substring(1)));
113
- }
@@ -1,169 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2023-2024 EclipseSource and others.
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * This Source Code may also be made available under the following Secondary
9
- * Licenses when the conditions for such availability set forth in the Eclipse
10
- * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- * with the GNU Classpath Exception which is available at
12
- * https://www.gnu.org/software/classpath/license.html.
13
- *
14
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
- ********************************************************************************/
16
-
17
- import { createOption } from 'commander';
18
- import * as fs from 'fs';
19
- import * as os from 'os';
20
- import * as path from 'path';
21
- import sh from 'shelljs';
22
- import { baseCommand } from '../util/command-util';
23
- import { LOGGER, configureLogger } from '../util/logger';
24
- import { validateDirectory } from '../util/validation-util';
25
-
26
- export interface GenerateIndexCmdOptions {
27
- singleIndex: boolean;
28
- forceOverwrite: boolean;
29
- match: string[] | boolean;
30
- ignore: string[] | boolean;
31
- ignoreFile: string;
32
- style: 'commonjs' | 'esm';
33
- verbose: boolean;
34
- }
35
-
36
- // Partial type of the globby imports since we can not use the esm type directly
37
- interface GlobbyOptions {
38
- ignore: string[];
39
- cwd: string;
40
- onlyFiles: boolean;
41
- markDirectories: true;
42
- ignoreFiles: string;
43
- }
44
-
45
- export const GenerateIndex = baseCommand() //
46
- .name('generateIndex')
47
- .description('Generate index files in a given source directory.')
48
- .argument('<rootDir...>', 'The source directory for index generation.')
49
- .option('-s, --singleIndex', 'Generate a single index file in the source directory instead of indices in each sub-directory', false)
50
- .option('-f, --forceOverwrite', 'Overwrite existing index files and remove them if there are no entries', false)
51
- .option('-m, --match [match patterns...]', 'File patterns to consider during indexing', ['**/*.ts', '**/*.tsx'])
52
- .option('-i, --ignore [ignore patterns...]', 'File patterns to ignore during indexing', ['**/*.spec.ts', '**/*.spec.tsx', '**/*.d.ts'])
53
- .addOption(createOption('-s, --style <importStyle>', 'Import Style').choices(['commonjs', 'esm']).default('commonjs'))
54
- .option('--ignoreFile <ignoreFile>', 'The file that is used to specify patterns that should be ignored during indexing', '.indexignore')
55
- .option('-v, --verbose', 'Generate verbose output during generation', false)
56
- .action(generateIndices);
57
-
58
- export async function generateIndices(rootDirs: string[], options: GenerateIndexCmdOptions): Promise<void> {
59
- const dirs = rootDirs.map(rootDir => validateDirectory(path.resolve(rootDir)));
60
- const globby = await import('globby');
61
- const ignoreFilter: (pattern: string[], options: GlobbyOptions) => string[] = (pattern, globbyOptions) =>
62
- globby.globbySync(pattern, globbyOptions);
63
- dirs.forEach(dir => generateIndex(dir, ignoreFilter, options));
64
- }
65
-
66
- export async function generateIndex(
67
- rootDir: string,
68
- ignoreFilter: (pattern: string[], options: GlobbyOptions) => string[],
69
- options: GenerateIndexCmdOptions
70
- ): Promise<void> {
71
- configureLogger(options.verbose);
72
- LOGGER.debug('Run generateIndex for', rootDir, 'with the following options:', options);
73
- sh.cd(rootDir);
74
- const cwd = process.cwd();
75
-
76
- // we want to match all given patterns and subdirectories and ignore all given patterns and (generated) index files
77
- const pattern = typeof options.match === 'boolean' ? ['**/'] : [...options.match, '**/'];
78
- const ignore = typeof options.ignore === 'boolean' ? ['**/index.ts'] : [...options.ignore, '**/index.ts'];
79
- const globbyOptions: GlobbyOptions = {
80
- ignore,
81
- cwd,
82
- onlyFiles: options.singleIndex,
83
- markDirectories: true, // directories have '/' at the end
84
- ignoreFiles: '**/' + options.ignoreFile // users can add this file in their directories to ignore files for indexing
85
- };
86
- LOGGER.debug('Search for children using the following globby options', globbyOptions);
87
- const files = ignoreFilter(pattern, globbyOptions);
88
- LOGGER.debug('All children considered in the input directory', files);
89
-
90
- const relativeRootDirectory = '';
91
- if (options.singleIndex) {
92
- writeIndex(relativeRootDirectory, files.filter(isFile), options);
93
- } else {
94
- // sort by length so we deal with sub-directories before we deal with their parents to determine whether they are empty
95
- const directories = [...files.filter(isDirectory), relativeRootDirectory].sort((left, right) => right.length - left.length);
96
- const directoryChildren = new Map<string, string[]>();
97
- for (const directory of directories) {
98
- const children = files.filter(file => isDirectChild(directory, file, () => !!directoryChildren.get(file)?.length));
99
- directoryChildren.set(directory, children);
100
- writeIndex(directory, children, options);
101
- }
102
- }
103
- }
104
-
105
- export function isDirectChild(parent: string, child: string, childHasChildren: () => boolean): boolean {
106
- return isChildFile(parent, child) || (isChildDirectory(parent, child) && childHasChildren());
107
- }
108
-
109
- export function isDirectory(file: string): boolean {
110
- return file.endsWith('/');
111
- }
112
-
113
- export function isFile(file: string): boolean {
114
- return !isDirectory(file);
115
- }
116
-
117
- export function getLevel(file: string): number {
118
- return file.split('/').length;
119
- }
120
-
121
- export function isChild(parent: string, child: string): boolean {
122
- return child.startsWith(parent);
123
- }
124
-
125
- export function isChildDirectory(parent: string, child: string): boolean {
126
- return isDirectory(child) && isChild(parent, child) && getLevel(child) === getLevel(parent) + 1;
127
- }
128
-
129
- export function isChildFile(parent: string, child: string): boolean {
130
- return isFile(child) && isChild(parent, child) && getLevel(child) === getLevel(parent);
131
- }
132
-
133
- export function writeIndex(directory: string, exports: string[], options: GenerateIndexCmdOptions): void {
134
- const indexFile = path.join(process.cwd(), directory, 'index.ts');
135
- if (exports.length === 0) {
136
- if (options.forceOverwrite && fs.existsSync(indexFile)) {
137
- LOGGER.info('Remove index file', indexFile);
138
- fs.rmSync(indexFile);
139
- }
140
- return;
141
- }
142
- const exists = fs.existsSync(indexFile);
143
- if (exists && !options.forceOverwrite) {
144
- LOGGER.info("Do not overwrite existing index file. Use '-f' to force an overwrite.", indexFile);
145
- return;
146
- }
147
-
148
- const headerContent = exists ? extractReusableContent(fs.readFileSync(indexFile, { encoding: 'utf-8' })) : '';
149
- const exportContent = exports.map(exported => createExport(directory, exported, options)).sort();
150
- const content = headerContent + exportContent.join(os.EOL) + os.EOL; // end with an empty line
151
- LOGGER.info((exists ? 'Overwrite' : 'Write') + ' index file', indexFile);
152
- LOGGER.debug(' ' + content.split(os.EOL).join(os.EOL + ' '));
153
- fs.writeFileSync(indexFile, content, { flag: 'w' });
154
- }
155
-
156
- export function createExport(directory: string, relativePath: string, options: GenerateIndexCmdOptions): string {
157
- // remove directory prefix, file extension and directory ending '/'
158
- const parentPrefix = directory.length;
159
- const suffix = isFile(relativePath) ? path.extname(relativePath).length : 1;
160
- const relativeName = relativePath.substring(parentPrefix, relativePath.length - suffix);
161
- const exportName = options.style === 'esm' && isFile(relativePath) ? relativeName + '.js' : relativeName;
162
- const exportLine = `export * from './${exportName}';`;
163
- return exportLine;
164
- }
165
-
166
- export function extractReusableContent(fileContent: string): string {
167
- // all code before any actual export lines are considered re-usable
168
- return fileContent.match(/^(.*?)(?=^export)/ms)?.[0] ?? '';
169
- }