@backstage/repo-tools 0.13.3 → 0.14.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,32 @@
1
1
  # @backstage/repo-tools
2
2
 
3
+ ## 0.14.0-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/backend-plugin-api@1.4.0-next.1
9
+ - @backstage/catalog-model@1.7.4
10
+ - @backstage/cli-common@0.1.15
11
+ - @backstage/cli-node@0.2.13
12
+ - @backstage/config-loader@1.10.1
13
+ - @backstage/errors@1.2.7
14
+
15
+ ## 0.14.0-next.0
16
+
17
+ ### Minor Changes
18
+
19
+ - bf9a173: Add support for caching the per-package output from the `package-docs` command.
20
+
21
+ ### Patch Changes
22
+
23
+ - 2d20024: Fix an issue where errors were not printed to console when running `backstage-repo-tools schema openapi generate` without the `--watch` flag.
24
+ - e643ee4: Add missing highlight language for the `package-docs` command.
25
+ - Updated dependencies
26
+ - @backstage/backend-plugin-api@1.4.0-next.0
27
+ - @backstage/cli-node@0.2.13
28
+ - @backstage/config-loader@1.10.1
29
+
3
30
  ## 0.13.3
4
31
 
5
32
  ### Patch Changes
@@ -76,6 +76,7 @@ async function command(opts) {
76
76
  try {
77
77
  await sharedCommand();
78
78
  } catch (err) {
79
+ console.error(chalk__default.default.red("Error: ", err));
79
80
  process.exit(1);
80
81
  }
81
82
  }
@@ -0,0 +1,133 @@
1
+ 'use strict';
2
+
3
+ var promises = require('fs/promises');
4
+ var globby = require('globby');
5
+ var path = require('path');
6
+ var crypto = require('crypto');
7
+ var fs = require('fs-extra');
8
+ var zod = require('zod');
9
+ var constants = require('./constants.cjs.js');
10
+
11
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
12
+
13
+ var globby__default = /*#__PURE__*/_interopDefaultCompat(globby);
14
+ var crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
15
+
16
+ const version = "1";
17
+ const cacheEntrySchema = zod.z.object({
18
+ hash: zod.z.string(),
19
+ packageName: zod.z.string(),
20
+ restoreTo: zod.z.string(),
21
+ version: zod.z.string()
22
+ });
23
+ class PackageDocsCache {
24
+ constructor(lockfile, cache, baseDirectory) {
25
+ this.lockfile = lockfile;
26
+ this.cache = cache;
27
+ this.baseDirectory = baseDirectory;
28
+ this.keyCache = /* @__PURE__ */ new Map();
29
+ }
30
+ // A map of package directory to package hash.
31
+ keyCache;
32
+ static async loadAsync(baseDirectory, lockfile) {
33
+ const cacheDir = path.join(baseDirectory, constants.CACHE_DIR);
34
+ await fs.mkdirp(cacheDir);
35
+ const cacheFiles = await globby__default.default(`**/${constants.CACHE_FILE}`, {
36
+ cwd: cacheDir
37
+ });
38
+ const map = /* @__PURE__ */ new Map();
39
+ for (const file of cacheFiles) {
40
+ const pkg = path.dirname(file);
41
+ const cache = await promises.readFile(path.join(cacheDir, file), "utf-8");
42
+ try {
43
+ const cacheJson = JSON.parse(cache);
44
+ const parsed = cacheEntrySchema.parse(cacheJson);
45
+ if (parsed.version !== version) {
46
+ console.warn(
47
+ `Skipping cache file ${file} due to version mismatch: ${parsed.version} !== ${version}`
48
+ );
49
+ continue;
50
+ }
51
+ map.set(pkg, parsed);
52
+ } catch (e) {
53
+ console.error(`Skipping unparseable cache file ${file}: ${e}`);
54
+ }
55
+ }
56
+ return new PackageDocsCache(lockfile, map, baseDirectory);
57
+ }
58
+ async directoryToName(directory) {
59
+ const packageJson = await promises.readFile(
60
+ path.join(this.baseDirectory, directory, "package.json"),
61
+ "utf-8"
62
+ );
63
+ return JSON.parse(packageJson).name;
64
+ }
65
+ async toKey(pkg) {
66
+ if (this.keyCache.has(pkg)) {
67
+ return this.keyCache.get(pkg);
68
+ }
69
+ const name = await this.directoryToName(pkg);
70
+ const result = await globby__default.default("src/**", {
71
+ gitignore: true,
72
+ onlyFiles: true,
73
+ cwd: pkg
74
+ });
75
+ const hash = crypto__default.default.createHash("sha1");
76
+ hash.update(version);
77
+ hash.update("\0");
78
+ for (const path$1 of result.sort()) {
79
+ const absPath = path.join(this.baseDirectory, pkg, path$1);
80
+ const pathInPackage = path.join(absPath, path$1);
81
+ hash.update(pathInPackage);
82
+ hash.update("\0");
83
+ hash.update(await promises.readFile(absPath));
84
+ hash.update("\0");
85
+ }
86
+ hash.update(this.lockfile.getDependencyTreeHash(name));
87
+ hash.update("\0");
88
+ const hashString = hash.digest("hex");
89
+ this.keyCache.set(pkg, hashString);
90
+ return hashString;
91
+ }
92
+ async has(pkg) {
93
+ const cache = this.cache.get(pkg);
94
+ if (!cache) {
95
+ return false;
96
+ }
97
+ const hashString = await this.toKey(pkg);
98
+ return cache.hash === hashString;
99
+ }
100
+ async restore(pkg) {
101
+ if (!this.has(pkg)) {
102
+ throw new Error(`Cache entry for ${pkg} not found`);
103
+ }
104
+ const cacheEntry = this.cache.get(pkg);
105
+ const restoreTo = cacheEntry.restoreTo;
106
+ const cacheDir = path.join(this.baseDirectory, constants.CACHE_DIR, pkg);
107
+ const contentsDir = path.join(cacheDir, "contents");
108
+ const targetDir = path.join(this.baseDirectory, restoreTo);
109
+ await fs.mkdirp(targetDir);
110
+ await promises.cp(contentsDir, targetDir, { recursive: true });
111
+ }
112
+ async write(pkg, contentDirectory) {
113
+ const cacheDir = path.join(this.baseDirectory, constants.CACHE_DIR, pkg);
114
+ const contentsDir = path.join(cacheDir, "contents");
115
+ if (await fs.exists(contentsDir)) {
116
+ await fs.rm(contentsDir, { recursive: true });
117
+ } else {
118
+ await fs.mkdirp(contentsDir);
119
+ }
120
+ const hashString = await this.toKey(pkg);
121
+ await promises.cp(contentDirectory, contentsDir, { recursive: true });
122
+ const cacheEntry = {
123
+ hash: hashString,
124
+ packageName: await this.directoryToName(pkg),
125
+ restoreTo: path.relative(this.baseDirectory, contentDirectory),
126
+ version
127
+ };
128
+ await promises.writeFile(path.join(cacheDir, constants.CACHE_FILE), JSON.stringify(cacheEntry));
129
+ }
130
+ }
131
+
132
+ exports.PackageDocsCache = PackageDocsCache;
133
+ //# sourceMappingURL=Cache.cjs.js.map
@@ -8,6 +8,9 @@ var paths = require('../../lib/paths.cjs.js');
8
8
  var utils = require('./utils.cjs.js');
9
9
  var promises = require('fs/promises');
10
10
  var pLimit = require('p-limit');
11
+ var fs = require('fs-extra');
12
+ var Cache = require('./Cache.cjs.js');
13
+ var cliNode = require('@backstage/cli-node');
11
14
 
12
15
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
13
16
 
@@ -28,7 +31,8 @@ const EXCLUDE = [
28
31
  "packages/techdocs-cli",
29
32
  "packages/techdocs-cli-embedded-app",
30
33
  "packages/yarn-plugin",
31
- "packages/backend"
34
+ "packages/backend",
35
+ "packages/backend-legacy"
32
36
  ];
33
37
  const HIGHLIGHT_LANGUAGES = [
34
38
  "ts",
@@ -41,7 +45,8 @@ const HIGHLIGHT_LANGUAGES = [
41
45
  "jsx",
42
46
  "diff",
43
47
  "js",
44
- "json"
48
+ "json",
49
+ "docker"
45
50
  ];
46
51
  function getExports(packageJson) {
47
52
  if (packageJson.exports) {
@@ -58,39 +63,33 @@ async function generateDocJson(pkg) {
58
63
  );
59
64
  const exports = getExports(packageJson);
60
65
  if (!exports.length || !exports.some((e) => e.startsWith("src") || e.startsWith("./src"))) {
61
- return;
62
- }
63
- try {
64
- await promises.mkdir(paths.paths.resolveTargetRoot(`dist-types`, pkg), {
65
- recursive: true
66
- });
67
- const { stdout, stderr } = await execAsync(
68
- [
69
- paths.paths.resolveTargetRoot("node_modules/.bin/typedoc"),
70
- "--json",
71
- paths.paths.resolveTargetRoot(`dist-types`, pkg, "docs.json"),
72
- "--tsconfig",
73
- temporaryTsConfigPath,
74
- "--basePath",
75
- paths.paths.targetRoot,
76
- "--skipErrorChecking",
77
- ...getExports(packageJson).flatMap((e) => [
78
- "--entryPoints",
79
- e
80
- ])
81
- ].join(" "),
82
- {
83
- cwd: pkg,
84
- env: { ...process.env, NODE_OPTIONS: "--max-old-space-size=12288" }
85
- }
86
- );
87
- console.log(`### Processed ${pkg}`);
88
- console.log(stdout);
89
- console.error(stderr);
90
- } catch (e) {
91
- console.error("Failed to generate docs for", pkg);
92
- console.error(e);
66
+ return false;
93
67
  }
68
+ await fs.mkdirp(paths.paths.resolveTargetRoot(`dist-types`, pkg));
69
+ const { stdout, stderr } = await execAsync(
70
+ [
71
+ paths.paths.resolveTargetRoot("node_modules/.bin/typedoc"),
72
+ "--json",
73
+ paths.paths.resolveTargetRoot(`dist-types`, pkg, "docs.json"),
74
+ "--tsconfig",
75
+ temporaryTsConfigPath,
76
+ "--basePath",
77
+ paths.paths.targetRoot,
78
+ "--skipErrorChecking",
79
+ ...getExports(packageJson).flatMap((e) => [
80
+ "--entryPoints",
81
+ e
82
+ ])
83
+ ].join(" "),
84
+ {
85
+ cwd: pkg,
86
+ env: { ...process.env, NODE_OPTIONS: "--max-old-space-size=12288" }
87
+ }
88
+ );
89
+ console.log(`### Processed ${pkg}`);
90
+ console.log(stdout);
91
+ console.error(stderr);
92
+ return true;
94
93
  }
95
94
  async function packageDocs(paths$1 = [], opts) {
96
95
  console.warn("!!! This is an experimental command !!!");
@@ -99,6 +98,10 @@ async function packageDocs(paths$1 = [], opts) {
99
98
  include: opts.include,
100
99
  exclude: opts.exclude
101
100
  });
101
+ const cache = await Cache.PackageDocsCache.loadAsync(
102
+ paths.paths.resolveTargetRoot(),
103
+ await cliNode.Lockfile.load(paths.paths.resolveTargetRoot("yarn.lock"))
104
+ );
102
105
  console.log(`### Generating docs.`);
103
106
  await Promise.all(
104
107
  selectedPackageDirs.map(
@@ -106,8 +109,29 @@ async function packageDocs(paths$1 = [], opts) {
106
109
  if (EXCLUDE.includes(pkg)) {
107
110
  return;
108
111
  }
109
- console.log(`### Processing ${pkg}`);
110
- await generateDocJson(pkg);
112
+ if (await cache.has(pkg)) {
113
+ console.log(`### Skipping ${pkg} due to cache hit`);
114
+ try {
115
+ await cache.restore(pkg);
116
+ return;
117
+ } catch (e) {
118
+ console.error("Failed to restore cache for", pkg);
119
+ console.error(e);
120
+ }
121
+ }
122
+ try {
123
+ console.log(`### Processing ${pkg}`);
124
+ const success = await generateDocJson(pkg);
125
+ if (success) {
126
+ await cache.write(
127
+ pkg,
128
+ paths.paths.resolveTargetRoot(`dist-types`, pkg)
129
+ );
130
+ }
131
+ } catch (e) {
132
+ console.error("Failed to generate docs for", pkg);
133
+ console.error(e);
134
+ }
111
135
  })
112
136
  )
113
137
  );
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const CACHE_FILE = "cache.json";
4
+ const CACHE_DIR = ".cache/package-docs";
5
+
6
+ exports.CACHE_DIR = CACHE_DIR;
7
+ exports.CACHE_FILE = CACHE_FILE;
8
+ //# sourceMappingURL=constants.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.13.3";
3
+ var version = "0.14.0-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/repo-tools",
3
- "version": "0.13.3",
3
+ "version": "0.14.0-next.1",
4
4
  "description": "CLI for Backstage repo tooling ",
5
5
  "backstage": {
6
6
  "role": "cli"
@@ -43,12 +43,12 @@
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.3.1",
47
- "@backstage/catalog-model": "^1.7.4",
48
- "@backstage/cli-common": "^0.1.15",
49
- "@backstage/cli-node": "^0.2.13",
50
- "@backstage/config-loader": "^1.10.1",
51
- "@backstage/errors": "^1.2.7",
46
+ "@backstage/backend-plugin-api": "1.4.0-next.1",
47
+ "@backstage/catalog-model": "1.7.4",
48
+ "@backstage/cli-common": "0.1.15",
49
+ "@backstage/cli-node": "0.2.13",
50
+ "@backstage/config-loader": "1.10.1",
51
+ "@backstage/errors": "1.2.7",
52
52
  "@electric-sql/pglite": "^0.2.15",
53
53
  "@manypkg/get-packages": "^1.1.3",
54
54
  "@microsoft/api-documenter": "^7.25.7",
@@ -69,6 +69,7 @@
69
69
  "commander": "^12.0.0",
70
70
  "fs-extra": "^11.2.0",
71
71
  "glob": "^8.0.3",
72
+ "globby": "^11.0.0",
72
73
  "is-glob": "^4.0.3",
73
74
  "js-yaml": "^4.1.0",
74
75
  "just-diff": "^6.0.2",
@@ -81,12 +82,13 @@
81
82
  "portfinder": "^1.0.32",
82
83
  "tar": "^6.1.12",
83
84
  "ts-morph": "^24.0.0",
84
- "yaml-diff-patch": "^2.0.0"
85
+ "yaml-diff-patch": "^2.0.0",
86
+ "zod": "^3.22.4"
85
87
  },
86
88
  "devDependencies": {
87
- "@backstage/backend-test-utils": "^1.5.0",
88
- "@backstage/cli": "^0.32.1",
89
- "@backstage/types": "^1.2.1",
89
+ "@backstage/backend-test-utils": "1.6.0-next.1",
90
+ "@backstage/cli": "0.32.2-next.0",
91
+ "@backstage/types": "1.2.1",
90
92
  "@types/is-glob": "^4.0.2",
91
93
  "@types/node": "^20.16.0",
92
94
  "@types/prettier": "^2.0.0",