@backstage/repo-tools 0.9.7 → 0.10.0-next.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,39 @@
1
1
  # @backstage/repo-tools
2
2
 
3
+ ## 0.10.0-next.1
4
+
5
+ ### Minor Changes
6
+
7
+ - 8eb3033: Adds a new command `backstage-repo-tools peer-deps` for validating your usage of peer dependencies in your plugins. It currently supports react related peer dependencies. It also has a `--fix` mode for quickly fixing any issues that it finds.
8
+
9
+ ### Patch Changes
10
+
11
+ - 1f6706f: Properly log instructions when APIs do not match
12
+ - Updated dependencies
13
+ - @backstage/backend-plugin-api@1.0.1-next.0
14
+ - @backstage/catalog-model@1.7.0
15
+ - @backstage/cli-common@0.1.14
16
+ - @backstage/cli-node@0.2.8
17
+ - @backstage/config-loader@1.9.1
18
+ - @backstage/errors@1.2.4
19
+
20
+ ## 0.10.0-next.0
21
+
22
+ ### Minor Changes
23
+
24
+ - 30c2be9: Update @microsoft/api-extractor and use their api report resolution.
25
+ Change api report format from `api-report.md` to `report.api.md`
26
+
27
+ ### Patch Changes
28
+
29
+ - Updated dependencies
30
+ - @backstage/backend-plugin-api@1.0.1-next.0
31
+ - @backstage/catalog-model@1.7.0
32
+ - @backstage/cli-common@0.1.14
33
+ - @backstage/cli-node@0.2.8
34
+ - @backstage/config-loader@1.9.1
35
+ - @backstage/errors@1.2.4
36
+
3
37
  ## 0.9.7
4
38
 
5
39
  ### Patch Changes
@@ -245,14 +245,17 @@ async function runApiExtraction({
245
245
  );
246
246
  const remainingReportFiles = new Set(
247
247
  fs__default.default.readdirSync(projectFolder).filter(
248
- (filename) => filename.match(/^(.+)-api-report\.md$/) || filename.match(/^api-report(-.+)?\.md$/)
248
+ (filename) => (
249
+ // https://regex101.com/r/QDZIV0/2
250
+ filename !== "knip-report.md" && // this has to temporarily match all old api report formats
251
+ filename.match(/^.*?(api-)?report(-[^.-]+)?(.*?)\.md$/)
252
+ )
249
253
  )
250
254
  );
251
255
  for (const packageEntryPoint of packageEntryPoints) {
252
256
  const suffix = packageEntryPoint.name === "index" ? "" : `-${packageEntryPoint.name}`;
253
- const reportFileName = `api-report${suffix}.md`;
257
+ const reportFileName = `report${suffix}`;
254
258
  const reportPath = path.resolve(projectFolder, reportFileName);
255
- remainingReportFiles.delete(reportFileName);
256
259
  const warningCountBefore = await countApiReportWarnings(reportPath);
257
260
  const extractorConfig = apiExtractor.ExtractorConfig.prepare({
258
261
  configObject: {
@@ -319,6 +322,9 @@ async function runApiExtraction({
319
322
  tsdocConfigFile: await getTsDocConfig(),
320
323
  ignoreMissingEntryPoint: true
321
324
  });
325
+ for (const reportConfig of extractorConfig.reportConfigs) {
326
+ remainingReportFiles.delete(reportConfig.fileName);
327
+ }
322
328
  extractorConfig.packageFolder = packageFolder;
323
329
  if (!compilerState) {
324
330
  compilerState = apiExtractor.CompilerState.create(extractorConfig, {
@@ -338,11 +344,11 @@ async function runApiExtraction({
338
344
  shouldLogInstructions = true;
339
345
  }
340
346
  if (message.text.includes(
341
- "You have changed the public API signature for this project."
347
+ "You have changed the API signature for this project."
342
348
  )) {
343
349
  shouldLogInstructions = true;
344
350
  const match = message.text.match(
345
- /Please copy the file "(.*)" to "api-report\.md"/
351
+ /Please copy the file "(.*)" to "report\.api\.md"/
346
352
  );
347
353
  if (match) {
348
354
  conflictingFile = match[1];
@@ -1122,4 +1128,4 @@ function parseArrayOption(value) {
1122
1128
  }
1123
1129
 
1124
1130
  exports.buildApiReports = buildApiReports;
1125
- //# sourceMappingURL=api-reports-_IpmreNR.cjs.js.map
1131
+ //# sourceMappingURL=api-reports-BqwD6i_J.cjs.js.map
@@ -0,0 +1,173 @@
1
+ 'use strict';
2
+
3
+ var path = require('path');
4
+ var getPackages = require('@manypkg/get-packages');
5
+ var fs = require('fs');
6
+
7
+ const desiredLocalVersionsOfDependencies = {
8
+ "@types/react": "^18.0.0",
9
+ react: "^18.0.2",
10
+ "react-dom": "^18.0.2",
11
+ "react-router-dom": "^6.3.0"
12
+ };
13
+ const peerDependencies = {
14
+ "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
15
+ react: "^16.13.1 || ^17.0.0 || ^18.0.0",
16
+ "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0",
17
+ "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
18
+ };
19
+ const groupsOfPeerDependencies = [["@types/react", "react", "react-dom"]];
20
+ const optionalPeerDependencies = /* @__PURE__ */ new Set(["@types/react"]);
21
+ const isOptional = (dep) => {
22
+ return optionalPeerDependencies.has(dep);
23
+ };
24
+ const isMarkedAsOptional = (dep, packageJson) => {
25
+ return packageJson.peerDependenciesMeta?.[dep]?.optional;
26
+ };
27
+ const isDevDependency = (dep, packageJson) => {
28
+ return !!packageJson.devDependencies?.[dep];
29
+ };
30
+ const isProdDependency = (dep, packageJson) => {
31
+ return !!packageJson.dependencies?.[dep];
32
+ };
33
+ const isPeerDependency = (dep, packageJson) => {
34
+ return !!packageJson.peerDependencies?.[dep];
35
+ };
36
+ const isStandaloneApplication = (packageJson) => {
37
+ return ["cli", "frontend", "backend"].includes(
38
+ packageJson.backstage?.role || ""
39
+ );
40
+ };
41
+ const matchesDependency = (dep, packageJson) => {
42
+ return packageJson.devDependencies && packageJson.devDependencies[dep] === desiredLocalVersionsOfDependencies[dep];
43
+ };
44
+ const matchesPeerDependency = (dep, packageJson) => {
45
+ return packageJson.peerDependencies && packageJson.peerDependencies[dep] === peerDependencies[dep];
46
+ };
47
+ var peerDeps = async ({ fix }) => {
48
+ let failed = false;
49
+ const attemptToApplyFix = (fn) => {
50
+ if (fix) {
51
+ fn();
52
+ } else {
53
+ failed = true;
54
+ }
55
+ };
56
+ const { packages } = await getPackages.getPackages(path.resolve("."));
57
+ const packagesWithRelevantDependencies = [];
58
+ for (const pkg of packages) {
59
+ if (isStandaloneApplication(pkg.packageJson)) {
60
+ continue;
61
+ }
62
+ const dependencies = {
63
+ ...pkg.packageJson.dependencies,
64
+ ...pkg.packageJson.devDependencies,
65
+ ...pkg.packageJson.peerDependencies
66
+ };
67
+ for (const dep in peerDependencies) {
68
+ if (dependencies?.[dep]) {
69
+ packagesWithRelevantDependencies.push(pkg);
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ for (const pkg of packagesWithRelevantDependencies) {
75
+ const packageJson = pkg.packageJson;
76
+ for (const dep of Object.keys(peerDependencies)) {
77
+ if (isPeerDependency(dep, packageJson)) {
78
+ if (isOptional(dep) && !isMarkedAsOptional(dep, packageJson)) {
79
+ console.error(
80
+ `Optional peer dependency ${dep} in ${pkg.packageJson.name} is not marked as optional`
81
+ );
82
+ attemptToApplyFix(() => {
83
+ packageJson.peerDependenciesMeta = packageJson.peerDependenciesMeta || {};
84
+ packageJson.peerDependenciesMeta[dep] = { optional: true };
85
+ });
86
+ } else if (!isOptional(dep) && isMarkedAsOptional(dep, packageJson)) {
87
+ console.error(
88
+ `Peer dependency ${dep} in ${pkg.packageJson.name} is marked as optional but should not be`
89
+ );
90
+ attemptToApplyFix(() => {
91
+ packageJson.peerDependenciesMeta = packageJson.peerDependenciesMeta || {};
92
+ delete packageJson.peerDependenciesMeta[dep];
93
+ });
94
+ }
95
+ if (!isDevDependency(dep, packageJson)) {
96
+ console.error(
97
+ `Peer dependency ${dep} in ${pkg.packageJson.name} is not listed as a devDependency`
98
+ );
99
+ attemptToApplyFix(() => {
100
+ delete packageJson.dependencies?.[dep];
101
+ packageJson.devDependencies = packageJson.devDependencies || {};
102
+ packageJson.devDependencies[dep] = desiredLocalVersionsOfDependencies[dep];
103
+ });
104
+ } else if (isProdDependency(dep, packageJson)) {
105
+ console.error(
106
+ `Peer dependency ${dep} in ${pkg.packageJson.name} is listed as a dependency`
107
+ );
108
+ attemptToApplyFix(() => {
109
+ delete packageJson.dependencies?.[dep];
110
+ });
111
+ }
112
+ const groups = groupsOfPeerDependencies.filter(
113
+ (group) => group.includes(dep)
114
+ );
115
+ if (groups.length) {
116
+ for (const group of groups) {
117
+ for (const groupDep of group) {
118
+ if (!isPeerDependency(groupDep, packageJson)) {
119
+ console.error(
120
+ `Peer dependency ${groupDep} in ${pkg.packageJson.name} is missing`
121
+ );
122
+ attemptToApplyFix(() => {
123
+ packageJson.peerDependencies = packageJson.peerDependencies || {};
124
+ packageJson.peerDependencies[groupDep] = peerDependencies[groupDep];
125
+ });
126
+ }
127
+ }
128
+ }
129
+ }
130
+ if (!matchesDependency(dep, packageJson)) {
131
+ console.error(
132
+ `Incorrect dependency ${dep} in ${pkg.packageJson.name}`
133
+ );
134
+ attemptToApplyFix(() => {
135
+ packageJson.devDependencies = packageJson.devDependencies || {};
136
+ packageJson.devDependencies[dep] = desiredLocalVersionsOfDependencies[dep];
137
+ });
138
+ }
139
+ if (!matchesPeerDependency(dep, packageJson)) {
140
+ console.error(
141
+ `Incorrect peer dependency ${dep} in ${pkg.packageJson.name}`
142
+ );
143
+ attemptToApplyFix(() => {
144
+ packageJson.peerDependencies = packageJson.peerDependencies || {};
145
+ packageJson.peerDependencies[dep] = peerDependencies[dep];
146
+ });
147
+ }
148
+ } else {
149
+ console.error(
150
+ `Missing peer dependency ${dep} in ${pkg.packageJson.name}`
151
+ );
152
+ attemptToApplyFix(() => {
153
+ packageJson.peerDependencies = packageJson.peerDependencies || {};
154
+ packageJson.peerDependencies[dep] = peerDependencies[dep];
155
+ });
156
+ }
157
+ }
158
+ if (fix) {
159
+ fs.writeFileSync(
160
+ path.resolve(pkg.dir, "package.json"),
161
+ `${JSON.stringify(packageJson, null, 2)}
162
+ `
163
+ );
164
+ }
165
+ }
166
+ if (failed) {
167
+ console.error("Some packages have incorrect peer dependencies");
168
+ process.exit(1);
169
+ }
170
+ };
171
+
172
+ exports.default = peerDeps;
173
+ //# sourceMappingURL=peer-deps-wmxV4fVq.cjs.js.map
@@ -144,6 +144,9 @@ function findTypeDepErrors(typeDeps, pkg) {
144
144
  }
145
145
  }
146
146
  for (const dep of deps) {
147
+ if (["@types/react"].includes(dep)) {
148
+ continue;
149
+ }
147
150
  errors.push(
148
151
  mkErr("WrongDepError", `Should be dev dep ${dep}`, {
149
152
  dep,
@@ -166,4 +169,4 @@ function mkErr(name, msg, extra) {
166
169
  }
167
170
 
168
171
  exports.default = typeDeps;
169
- //# sourceMappingURL=type-deps-DgJcEpV_.cjs.js.map
172
+ //# sourceMappingURL=type-deps-CYUUkOZo.cjs.js.map
package/dist/index.cjs.js CHANGED
@@ -148,10 +148,13 @@ function registerCommands(program) {
148
148
  "Turn on release tag validation for the public, beta, and alpha APIs"
149
149
  ).description("Generate an API report for selected packages").action(
150
150
  lazy(
151
- () => Promise.resolve().then(function () { return require('./cjs/api-reports-_IpmreNR.cjs.js'); }).then((m) => m.buildApiReports)
151
+ () => Promise.resolve().then(function () { return require('./cjs/api-reports-BqwD6i_J.cjs.js'); }).then((m) => m.buildApiReports)
152
152
  )
153
153
  );
154
- 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-DgJcEpV_.cjs.js'); }).then((m) => m.default)));
154
+ 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-CYUUkOZo.cjs.js'); }).then((m) => m.default)));
155
+ program.command("peer-deps").description(
156
+ "Ensure your packages are using the correct peer dependency format."
157
+ ).option("--fix", "Fix the issues found").action(lazy(() => Promise.resolve().then(function () { return require('./cjs/peer-deps-wmxV4fVq.cjs.js'); }).then((m) => m.default)));
155
158
  program.command("generate-catalog-info").option(
156
159
  "--dry-run",
157
160
  "Shows what would happen without actually writing any yaml."
@@ -187,7 +190,7 @@ function lazy(getActionFunc) {
187
190
  };
188
191
  }
189
192
 
190
- var version = "0.9.7";
193
+ var version = "0.10.0-next.1";
191
194
 
192
195
  const main = (argv) => {
193
196
  commander.program.name("backstage-repo-tools").version(version);
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@backstage/repo-tools",
3
+ "version": "0.10.0-next.1",
3
4
  "description": "CLI for Backstage repo tooling ",
4
- "version": "0.9.7",
5
- "publishConfig": {
6
- "access": "public"
7
- },
8
5
  "backstage": {
9
6
  "role": "cli"
10
7
  },
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
11
  "keywords": [
12
12
  "backstage"
13
13
  ],
@@ -43,15 +43,15 @@
43
43
  "dependencies": {
44
44
  "@apidevtools/swagger-parser": "^10.1.0",
45
45
  "@apisyouwonthate/style-guide": "^1.4.0",
46
- "@backstage/backend-plugin-api": "^1.0.0",
47
- "@backstage/catalog-model": "^1.7.0",
48
- "@backstage/cli-common": "^0.1.14",
49
- "@backstage/cli-node": "^0.2.8",
50
- "@backstage/config-loader": "^1.9.1",
51
- "@backstage/errors": "^1.2.4",
46
+ "@backstage/backend-plugin-api": "1.0.1-next.0",
47
+ "@backstage/catalog-model": "1.7.0",
48
+ "@backstage/cli-common": "0.1.14",
49
+ "@backstage/cli-node": "0.2.8",
50
+ "@backstage/config-loader": "1.9.1",
51
+ "@backstage/errors": "1.2.4",
52
52
  "@manypkg/get-packages": "^1.1.3",
53
- "@microsoft/api-documenter": "^7.22.33",
54
- "@microsoft/api-extractor": "^7.36.4",
53
+ "@microsoft/api-documenter": "^7.25.7",
54
+ "@microsoft/api-extractor": "^7.47.2",
55
55
  "@openapitools/openapi-generator-cli": "^2.7.0",
56
56
  "@stoplight/spectral-core": "^1.18.0",
57
57
  "@stoplight/spectral-formatters": "^1.1.0",
@@ -77,9 +77,9 @@
77
77
  "yaml-diff-patch": "^2.0.0"
78
78
  },
79
79
  "devDependencies": {
80
- "@backstage/backend-test-utils": "^1.0.0",
81
- "@backstage/cli": "^0.27.1",
82
- "@backstage/types": "^1.1.1",
80
+ "@backstage/backend-test-utils": "1.0.1-next.1",
81
+ "@backstage/cli": "0.28.0-next.1",
82
+ "@backstage/types": "1.1.1",
83
83
  "@types/is-glob": "^4.0.2",
84
84
  "@types/node": "^18.17.8",
85
85
  "@types/prettier": "^2.0.0"