@backstage/repo-tools 0.1.0-next.1 → 0.1.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @backstage/repo-tools
2
2
 
3
+ ## 0.1.0-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - a8611bcac4: Add new command options to the `api-report`
8
+
9
+ - added `--allow-warnings`, `-a` to continue processing packages if selected packages have warnings
10
+ - added `--allow-all-warnings` to continue processing packages any packages have warnings
11
+ - added `--omit-messages`, `-o` to pass some warnings messages code to be omitted from the api-report.md files
12
+ - The `paths` argument for this command now takes as default the value on `workspaces.packages` inside the root package.json
13
+ - change the path resolution to use the `@backstage/cli-common` packages instead
14
+
15
+ - Updated dependencies
16
+ - @backstage/cli-common@0.1.11-next.0
17
+ - @backstage/errors@1.1.4-next.1
18
+
3
19
  ## 0.1.0-next.1
4
20
 
5
21
  ### Minor Changes
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
4
3
  var fs = require('fs-extra');
4
+ var path = require('path');
5
5
  var child_process = require('child_process');
6
6
  var prettier = require('prettier');
7
7
  var apiExtractor = require('@microsoft/api-extractor');
@@ -13,11 +13,52 @@ var DocTable = require('@microsoft/api-documenter/lib/nodes/DocTable');
13
13
  var DocTableRow = require('@microsoft/api-documenter/lib/nodes/DocTableRow');
14
14
  var DocHeading = require('@microsoft/api-documenter/lib/nodes/DocHeading');
15
15
  var CustomMarkdownEmitter = require('@microsoft/api-documenter/lib/markdown/CustomMarkdownEmitter');
16
+ var cliCommon = require('@backstage/cli-common');
17
+ var g = require('glob');
18
+ var isGlob = require('is-glob');
19
+ var util = require('util');
20
+ var minimatch = require('minimatch');
16
21
 
17
22
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
18
23
 
19
24
  var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
20
25
  var prettier__default = /*#__PURE__*/_interopDefaultLegacy(prettier);
26
+ var g__default = /*#__PURE__*/_interopDefaultLegacy(g);
27
+ var isGlob__default = /*#__PURE__*/_interopDefaultLegacy(isGlob);
28
+ var minimatch__default = /*#__PURE__*/_interopDefaultLegacy(minimatch);
29
+
30
+ const glob = util.promisify(g__default["default"]);
31
+ const paths = cliCommon.findPaths(__dirname);
32
+ async function resolvePackagePath(packagePath) {
33
+ const fullPackageDir = paths.resolveTargetRoot(packagePath);
34
+ try {
35
+ const stat = await fs__default["default"].stat(fullPackageDir);
36
+ if (!stat.isDirectory()) {
37
+ return void 0;
38
+ }
39
+ const packageJsonPath = path.join(fullPackageDir, "package.json");
40
+ await fs__default["default"].access(packageJsonPath);
41
+ } catch (e) {
42
+ console.log(`folder omitted: ${fullPackageDir}, cause: ${e}`);
43
+ return void 0;
44
+ }
45
+ return path.relative(paths.targetRoot, fullPackageDir);
46
+ }
47
+ async function findPackageDirs(selectedPaths = []) {
48
+ const packageDirs = new Array();
49
+ for (const packageRoot of selectedPaths) {
50
+ const fullPath = paths.resolveTargetRoot(packageRoot);
51
+ const dirs = isGlob__default["default"](fullPath) ? await glob(fullPath) : [fullPath];
52
+ for (const dir of dirs) {
53
+ const packageDir = await resolvePackagePath(dir);
54
+ if (!packageDir) {
55
+ continue;
56
+ }
57
+ packageDirs.push(packageDir);
58
+ }
59
+ }
60
+ return packageDirs;
61
+ }
21
62
 
22
63
  var __accessCheck = (obj, member, msg) => {
23
64
  if (!member.has(obj))
@@ -38,8 +79,7 @@ var __privateSet = (obj, member, value, setter) => {
38
79
  return value;
39
80
  };
40
81
  var _tokens;
41
- const tmpDir = path.resolve(
42
- process.cwd(),
82
+ const tmpDir = paths.resolveTargetRoot(
43
83
  "./node_modules/.cache/api-extractor"
44
84
  );
45
85
  const {
@@ -131,61 +171,8 @@ ApiReportGenerator.generateReviewFileContent = function decoratedGenerateReviewF
131
171
  parser: "markdown"
132
172
  });
133
173
  };
134
- const PACKAGE_ROOTS = ["packages", "plugins"];
135
- const ALLOW_WARNINGS = [
136
- "packages/core-components",
137
- "plugins/catalog",
138
- "plugins/catalog-import",
139
- "plugins/git-release-manager",
140
- "plugins/jenkins",
141
- "plugins/kubernetes"
142
- ];
143
- async function resolvePackagePath(packagePath) {
144
- const projectRoot = path.resolve(process.cwd());
145
- const fullPackageDir = path.resolve(projectRoot, packagePath);
146
- const stat = await fs__default["default"].stat(fullPackageDir);
147
- if (!stat.isDirectory()) {
148
- return void 0;
149
- }
150
- try {
151
- const packageJsonPath = path.join(fullPackageDir, "package.json");
152
- await fs__default["default"].access(packageJsonPath);
153
- } catch (_) {
154
- return void 0;
155
- }
156
- return path.relative(projectRoot, fullPackageDir);
157
- }
158
- async function findSpecificPackageDirs(unresolvedPackageDirs) {
159
- const packageDirs = new Array();
160
- for (const unresolvedPackageDir of unresolvedPackageDirs) {
161
- const packageDir = await resolvePackagePath(unresolvedPackageDir);
162
- if (!packageDir) {
163
- throw new Error(`'${unresolvedPackageDir}' is not a valid package path`);
164
- }
165
- packageDirs.push(packageDir);
166
- }
167
- if (packageDirs.length === 0) {
168
- return void 0;
169
- }
170
- return packageDirs;
171
- }
172
- async function findPackageDirs() {
173
- const packageDirs = new Array();
174
- const projectRoot = path.resolve(process.cwd());
175
- for (const packageRoot of PACKAGE_ROOTS) {
176
- const dirs = await fs__default["default"].readdir(path.resolve(projectRoot, packageRoot));
177
- for (const dir of dirs) {
178
- const packageDir = await resolvePackagePath(path.join(packageRoot, dir));
179
- if (!packageDir) {
180
- continue;
181
- }
182
- packageDirs.push(packageDir);
183
- }
184
- }
185
- return packageDirs;
186
- }
187
174
  async function createTemporaryTsConfig(includedPackageDirs) {
188
- const path$1 = path.resolve(process.cwd(), "tsconfig.tmp.json");
175
+ const path$1 = paths.resolveTargetRoot("tsconfig.tmp.json");
189
176
  process.once("exit", () => {
190
177
  fs__default["default"].removeSync(path$1);
191
178
  });
@@ -254,22 +241,30 @@ async function runApiExtraction({
254
241
  packageDirs,
255
242
  outputDir,
256
243
  isLocalBuild,
257
- tsconfigFilePath
244
+ tsconfigFilePath,
245
+ allowWarnings = false,
246
+ omitMessages = []
258
247
  }) {
259
248
  await fs__default["default"].remove(outputDir);
260
249
  const entryPoints = packageDirs.map((packageDir) => {
261
- return path.resolve(
262
- process.cwd(),
250
+ return paths.resolveTargetRoot(
263
251
  `./dist-types/${packageDir}/src/index.d.ts`
264
252
  );
265
253
  });
266
254
  let compilerState = void 0;
255
+ const allowWarningPkg = Array.isArray(allowWarnings) ? allowWarnings : [];
256
+ const messagesConf = {};
257
+ for (const messageCode of omitMessages) {
258
+ messagesConf[messageCode] = {
259
+ logLevel: "none"
260
+ };
261
+ }
267
262
  const warnings = new Array();
268
263
  for (const packageDir of packageDirs) {
269
264
  console.log(`## Processing ${packageDir}`);
270
- const projectFolder = path.resolve(process.cwd(), packageDir);
271
- const packageFolder = path.resolve(
272
- process.cwd(),
265
+ const noBail = Array.isArray(allowWarnings) ? allowWarnings.some((aw) => aw === packageDir || minimatch__default["default"](packageDir, aw)) : allowWarnings;
266
+ const projectFolder = paths.resolveTargetRoot(packageDir);
267
+ const packageFolder = paths.resolveTargetRoot(
273
268
  "./dist-types",
274
269
  packageDir
275
270
  );
@@ -310,7 +305,8 @@ async function runApiExtraction({
310
305
  default: {
311
306
  logLevel: "warning",
312
307
  addToApiReportFile: true
313
- }
308
+ },
309
+ ...messagesConf
314
310
  },
315
311
  tsdocMessageReporting: {
316
312
  default: {
@@ -377,12 +373,15 @@ async function runApiExtraction({
377
373
  );
378
374
  }
379
375
  const warningCountAfter = await countApiReportWarnings(projectFolder);
380
- if (warningCountAfter > 0 && !ALLOW_WARNINGS.includes(packageDir)) {
376
+ if (noBail) {
377
+ console.log(`Skipping warnings check for ${packageDir}`);
378
+ }
379
+ if (warningCountAfter > 0 && !noBail) {
381
380
  throw new Error(
382
381
  `The API Report for ${packageDir} is not allowed to have warnings`
383
382
  );
384
383
  }
385
- if (warningCountAfter === 0 && ALLOW_WARNINGS.includes(packageDir)) {
384
+ if (warningCountAfter === 0 && allowWarningPkg.includes(packageDir)) {
386
385
  console.log(
387
386
  `No need to allow warnings for ${packageDir}, it does not have any`
388
387
  );
@@ -816,7 +815,7 @@ async function buildDocs({
816
815
  await fs__default["default"].ensureDir(outputDir);
817
816
  documenter.generateFiles();
818
817
  }
819
- async function categorizePackageDirs(projectRoot, packageDirs) {
818
+ async function categorizePackageDirs(packageDirs) {
820
819
  const dirs = packageDirs.slice();
821
820
  const tsPackageDirs = new Array();
822
821
  const cliPackageDirs = new Array();
@@ -828,7 +827,7 @@ async function categorizePackageDirs(projectRoot, packageDirs) {
828
827
  if (!dir) {
829
828
  return;
830
829
  }
831
- const pkgJson = await fs__default["default"].readJson(path.resolve(projectRoot, dir, "package.json")).catch((error) => {
830
+ const pkgJson = await fs__default["default"].readJson(paths.resolveTargetRoot(dir, "package.json")).catch((error) => {
832
831
  if (error.code === "ENOENT") {
833
832
  return void 0;
834
833
  }
@@ -878,6 +877,7 @@ function parseHelpPage(helpPageContent) {
878
877
  const lines = helpPageContent.split(/\r?\n/);
879
878
  let options = new Array();
880
879
  let commands = new Array();
880
+ let commandArguments = new Array();
881
881
  while (lines.length > 0) {
882
882
  while (lines.length > 0 && !lines[0].endsWith(":")) {
883
883
  lines.shift();
@@ -897,6 +897,8 @@ function parseHelpPage(helpPageContent) {
897
897
  options = sectionItems;
898
898
  } else if ((sectionName == null ? void 0 : sectionName.toLocaleLowerCase("en-US")) === "commands:") {
899
899
  commands = sectionItems;
900
+ } else if ((sectionName == null ? void 0 : sectionName.toLocaleLowerCase("en-US")) === "arguments:") {
901
+ commandArguments = sectionItems;
900
902
  } else {
901
903
  throw new Error(`Unknown CLI section: ${sectionName}`);
902
904
  }
@@ -905,7 +907,8 @@ function parseHelpPage(helpPageContent) {
905
907
  return {
906
908
  usage,
907
909
  options,
908
- commands
910
+ commands,
911
+ commandArguments
909
912
  };
910
913
  }
911
914
  async function exploreCliHelpPages(run) {
@@ -955,13 +958,12 @@ function generateCliReport(name, models) {
955
958
  return content.join("\n");
956
959
  }
957
960
  async function runCliExtraction({
958
- projectRoot,
959
961
  packageDirs,
960
962
  isLocalBuild
961
963
  }) {
962
964
  for (const packageDir of packageDirs) {
963
965
  console.log(`## Processing ${packageDir}`);
964
- const fullDir = path.resolve(projectRoot, packageDir);
966
+ const fullDir = paths.resolveTargetRoot(packageDir);
965
967
  const pkgJson = await fs__default["default"].readJson(path.resolve(fullDir, "package.json"));
966
968
  if (!pkgJson.bin) {
967
969
  throw new Error(`CLI Package in ${packageDir} has no bin field`);
@@ -996,7 +998,7 @@ async function runCliExtraction({
996
998
  console.log("");
997
999
  console.log(
998
1000
  `The conflicting file is ${path.relative(
999
- projectRoot,
1001
+ paths.targetRoot,
1000
1002
  reportPath
1001
1003
  )}, expecting the following content:`
1002
1004
  );
@@ -1010,29 +1012,48 @@ async function runCliExtraction({
1010
1012
  }
1011
1013
  }
1012
1014
 
1013
- var apiReports = async (paths, opts) => {
1014
- const tmpDir = path.resolve(
1015
- process.cwd(),
1015
+ async function generateTypeDeclarations(tsconfigFilePath) {
1016
+ await fs__default["default"].remove(paths.resolveTargetRoot("dist-types"));
1017
+ const { status } = child_process.spawnSync(
1018
+ "yarn",
1019
+ [
1020
+ "tsc",
1021
+ ["--project", tsconfigFilePath],
1022
+ ["--skipLibCheck", "false"],
1023
+ ["--incremental", "false"]
1024
+ ].flat(),
1025
+ {
1026
+ stdio: "inherit",
1027
+ shell: true,
1028
+ cwd: paths.targetRoot
1029
+ }
1030
+ );
1031
+ if (status !== 0) {
1032
+ process.exit(status || void 0);
1033
+ }
1034
+ }
1035
+
1036
+ const buildApiReports = async (paths$1 = [], opts) => {
1037
+ const tmpDir = paths.resolveTargetRoot(
1016
1038
  "./node_modules/.cache/api-extractor"
1017
1039
  );
1018
- const projectRoot = path.resolve(process.cwd());
1019
1040
  const isCiBuild = opts.ci;
1020
1041
  const isDocsBuild = opts.docs;
1021
1042
  const runTsc = opts.tsc;
1022
- const selectedPackageDirs = await findSpecificPackageDirs(paths);
1023
- if (selectedPackageDirs && isCiBuild) {
1024
- throw new Error(
1025
- "Package path arguments are not supported together with the --ci flag"
1026
- );
1027
- }
1028
- if (!selectedPackageDirs && !isCiBuild && !isDocsBuild) {
1043
+ const allowWarnings = parseArrayOption(opts.allowWarnings);
1044
+ const allowAllWarnings = opts.allowAllWarnings;
1045
+ const omitMessages = parseArrayOption(opts.omitMessages);
1046
+ const isAllPackages = !(paths$1 == null ? void 0 : paths$1.length);
1047
+ const selectedPaths = isAllPackages ? await getWorkspacePackagePathPatterns() : paths$1;
1048
+ const selectedPackageDirs = await findPackageDirs(selectedPaths);
1049
+ if (isAllPackages && !isCiBuild && !isDocsBuild) {
1029
1050
  console.log("");
1030
1051
  console.log(
1031
1052
  "TIP: You can generate api-reports for select packages by passing package paths:"
1032
1053
  );
1033
1054
  console.log("");
1034
1055
  console.log(
1035
- " yarn build:api-reports packages/config packages/core-plugin-api"
1056
+ " yarn build:api-reports packages/config packages/core-plugin-api plugins/*"
1036
1057
  );
1037
1058
  console.log("");
1038
1059
  }
@@ -1040,31 +1061,13 @@ var apiReports = async (paths, opts) => {
1040
1061
  if (selectedPackageDirs) {
1041
1062
  temporaryTsConfigPath = await createTemporaryTsConfig(selectedPackageDirs);
1042
1063
  }
1043
- const tsconfigFilePath = temporaryTsConfigPath != null ? temporaryTsConfigPath : path.resolve(projectRoot, "tsconfig.json");
1064
+ const tsconfigFilePath = temporaryTsConfigPath != null ? temporaryTsConfigPath : paths.resolveTargetRoot("tsconfig.json");
1044
1065
  if (runTsc) {
1045
- await fs__default["default"].remove(path.resolve(projectRoot, "dist-types"));
1046
- const { status } = child_process.spawnSync(
1047
- "yarn",
1048
- [
1049
- "tsc",
1050
- ["--project", tsconfigFilePath],
1051
- ["--skipLibCheck", "false"],
1052
- ["--incremental", "false"]
1053
- ].flat(),
1054
- {
1055
- stdio: "inherit",
1056
- shell: true,
1057
- cwd: projectRoot
1058
- }
1059
- );
1060
- if (status !== 0) {
1061
- process.exit(status || void 0);
1062
- }
1066
+ console.log("# Compiling TypeScript");
1067
+ await generateTypeDeclarations(tsconfigFilePath);
1063
1068
  }
1064
- const packageDirs = selectedPackageDirs != null ? selectedPackageDirs : await findPackageDirs();
1065
1069
  const { tsPackageDirs, cliPackageDirs } = await categorizePackageDirs(
1066
- projectRoot,
1067
- packageDirs
1070
+ selectedPackageDirs
1068
1071
  );
1069
1072
  if (tsPackageDirs.length > 0) {
1070
1073
  console.log("# Generating package API reports");
@@ -1072,13 +1075,14 @@ var apiReports = async (paths, opts) => {
1072
1075
  packageDirs: tsPackageDirs,
1073
1076
  outputDir: tmpDir,
1074
1077
  isLocalBuild: !isCiBuild,
1075
- tsconfigFilePath
1078
+ tsconfigFilePath,
1079
+ allowWarnings: allowAllWarnings || allowWarnings,
1080
+ omitMessages: Array.isArray(omitMessages) ? omitMessages : []
1076
1081
  });
1077
1082
  }
1078
1083
  if (cliPackageDirs.length > 0) {
1079
1084
  console.log("# Generating package CLI reports");
1080
1085
  await runCliExtraction({
1081
- projectRoot,
1082
1086
  packageDirs: cliPackageDirs,
1083
1087
  isLocalBuild: !isCiBuild
1084
1088
  });
@@ -1087,10 +1091,24 @@ var apiReports = async (paths, opts) => {
1087
1091
  console.log("# Generating package documentation");
1088
1092
  await buildDocs({
1089
1093
  inputDir: tmpDir,
1090
- outputDir: path.resolve(projectRoot, "docs/reference")
1094
+ outputDir: paths.resolveTargetRoot("docs/reference")
1091
1095
  });
1092
1096
  }
1093
1097
  };
1098
+ async function getWorkspacePackagePathPatterns() {
1099
+ var _a;
1100
+ const pkgJson = await fs__default["default"].readJson(paths.resolveTargetRoot("package.json")).catch((error) => {
1101
+ if (error.code === "ENOENT") {
1102
+ return void 0;
1103
+ }
1104
+ throw error;
1105
+ });
1106
+ const workspaces = (_a = pkgJson == null ? void 0 : pkgJson.workspaces) == null ? void 0 : _a.packages;
1107
+ return workspaces;
1108
+ }
1109
+ function parseArrayOption(value) {
1110
+ return value ? value.split(",").map((s) => s.trim()) : [];
1111
+ }
1094
1112
 
1095
- exports["default"] = apiReports;
1096
- //# sourceMappingURL=api-reports-b4f0424b.cjs.js.map
1113
+ exports.buildApiReports = buildApiReports;
1114
+ //# sourceMappingURL=api-reports-bc48eddc.cjs.js.map
package/dist/index.cjs.js CHANGED
@@ -38,8 +38,20 @@ ${chalk__default["default"].red(`${error}`)}
38
38
  }
39
39
 
40
40
  function registerCommands(program) {
41
- program.command("api-reports [path...]").option("--ci", "CI run checks that there is no changes on API reports").option("--tsc", "executes the tsc compilation before extracting the APIs").option("--docs", "generates the api documentation").description("Generate an API report for selected packages").action(
42
- lazy(() => Promise.resolve().then(function () { return require('./cjs/api-reports-b4f0424b.cjs.js'); }).then((m) => m.default))
41
+ program.command("api-reports [paths...]").option("--ci", "CI run checks that there is no changes on API reports").option("--tsc", "executes the tsc compilation before extracting the APIs").option("--docs", "generates the api documentation").option(
42
+ "-a, --allow-warnings <allowWarningsPaths>",
43
+ "continue processing packages after getting errors on selected packages Allows glob patterns and comma separated values (i.e. packages/core,plugins/core-*)"
44
+ ).option(
45
+ "--allow-all-warnings",
46
+ "continue processing packages after getting errors on all packages",
47
+ false
48
+ ).option(
49
+ "-o, --omit-messages <messageCodes>",
50
+ "select some message code to be omited on the API Extractor (comma separated values i.e ae-cyclic-inherit-doc,ae-missing-getter )"
51
+ ).description("Generate an API report for selected packages").action(
52
+ lazy(
53
+ () => Promise.resolve().then(function () { return require('./cjs/api-reports-bc48eddc.cjs.js'); }).then((m) => m.buildApiReports)
54
+ )
43
55
  );
44
56
  program.command("type-deps").description("Find inconsistencies in types of all packages and plugins").action(lazy(() => Promise.resolve().then(function () { return require('./cjs/type-deps-fba15630.cjs.js'); }).then((m) => m.default)));
45
57
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/repo-tools",
3
3
  "description": "CLI for Backstage repo tooling ",
4
- "version": "0.1.0-next.1",
4
+ "version": "0.1.0-next.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -30,6 +30,7 @@
30
30
  "backstage-repo-tools": "bin/backstage-repo-tools"
31
31
  },
32
32
  "dependencies": {
33
+ "@backstage/cli-common": "^0.1.11-next.0",
33
34
  "@backstage/errors": "^1.1.4-next.1",
34
35
  "@manypkg/get-packages": "^1.1.3",
35
36
  "@microsoft/api-documenter": "^7.17.11",
@@ -39,8 +40,17 @@
39
40
  "chalk": "^4.0.0",
40
41
  "commander": "^9.1.0",
41
42
  "fs-extra": "10.1.0",
43
+ "glob": "^8.0.3",
44
+ "is-glob": "^4.0.3",
45
+ "minimatch": "^5.1.1",
42
46
  "ts-node": "^10.0.0"
43
47
  },
48
+ "devDependencies": {
49
+ "@backstage/cli": "^0.22.0-next.4",
50
+ "@types/is-glob": "^4.0.2",
51
+ "@types/mock-fs": "^4.13.0",
52
+ "mock-fs": "^5.1.0"
53
+ },
44
54
  "files": [
45
55
  "bin",
46
56
  "dist/**/*.js"