@backstage/repo-tools 0.10.0-next.2 → 0.11.0-next.0

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,46 @@
1
1
  # @backstage/repo-tools
2
2
 
3
+ ## 0.11.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 47fdbb4: Adds a `--watch` mode to the `schema openapi generate` command for a better local schema writing experience.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @backstage/backend-plugin-api@1.0.2-next.0
13
+ - @backstage/catalog-model@1.7.0
14
+ - @backstage/cli-common@0.1.14
15
+ - @backstage/cli-node@0.2.9
16
+ - @backstage/config-loader@1.9.1
17
+ - @backstage/errors@1.2.4
18
+
19
+ ## 0.10.0
20
+
21
+ ### Minor Changes
22
+
23
+ - 30c2be9: Update @microsoft/api-extractor and use their api report resolution.
24
+ Change api report format from `api-report.md` to `report.api.md`
25
+ - 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.
26
+
27
+ ### Patch Changes
28
+
29
+ - 1f6706f: Properly log instructions when APIs do not match
30
+ - 35e735b: Fix issues with warnings in API reports not being checked or reported.
31
+
32
+ Due to the recent version bump of API Extractor you may now see a lot of `ae-undocumented` warnings,
33
+ these can be ignored using the `-o` option, for example, `backstage-repo-tools api-reports -o ae-undocumented,ae-wrong-input-file-type`.
34
+
35
+ - 248793e: Updated dependency `@useoptic/optic` to `^1.0.0`.
36
+ - Updated dependencies
37
+ - @backstage/cli-node@0.2.9
38
+ - @backstage/backend-plugin-api@1.0.1
39
+ - @backstage/catalog-model@1.7.0
40
+ - @backstage/cli-common@0.1.14
41
+ - @backstage/config-loader@1.9.1
42
+ - @backstage/errors@1.2.4
43
+
3
44
  ## 0.10.0-next.2
4
45
 
5
46
  ### Patch Changes
@@ -250,7 +250,7 @@ async function runApiExtraction({
250
250
  for (const packageEntryPoint of packageEntryPoints) {
251
251
  const suffix = packageEntryPoint.name === "index" ? "" : `-${packageEntryPoint.name}`;
252
252
  const reportFileName = `report${suffix}`;
253
- const reportPath = path.resolve(projectFolder, reportFileName);
253
+ const reportPath = path.resolve(projectFolder, `${reportFileName}.api.md`);
254
254
  const warningCountBefore = await countApiReportWarnings(reportPath);
255
255
  const extractorConfig = apiExtractor.ExtractorConfig.prepare({
256
256
  configObject: {
@@ -23,7 +23,7 @@ function registerPackageCommand(program) {
23
23
  "Command to generate a client and/or a server stub from an OpenAPI spec."
24
24
  ).option("--client-additional-properties [properties]").description(
25
25
  "Additional properties that can be passed to @openapitools/openapi-generator-cli"
26
- ).action(
26
+ ).option("--watch").description("Watch the OpenAPI spec for changes and regenerate on save.").action(
27
27
  lazy(
28
28
  () => Promise.resolve().then(function () { return require('./package/schema/openapi/generate/index.cjs.js'); }).then((m) => m.command)
29
29
  )
@@ -14,7 +14,7 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
14
14
  var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
15
15
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
16
16
 
17
- async function generate(outputDirectory, clientAdditionalProperties) {
17
+ async function generate(outputDirectory, clientAdditionalProperties, abortSignal) {
18
18
  const resolvedOpenapiPath = await helpers.getPathToCurrentOpenApiSpec();
19
19
  const resolvedOutputDirectory = paths.paths.resolveTargetRoot(
20
20
  outputDirectory,
@@ -48,6 +48,7 @@ async function generate(outputDirectory, clientAdditionalProperties) {
48
48
  additionalProperties
49
49
  ],
50
50
  {
51
+ signal: abortSignal?.signal,
51
52
  maxBuffer: Number.MAX_VALUE,
52
53
  cwd: backendPluginApi.resolvePackagePath("@backstage/repo-tools"),
53
54
  env: {
@@ -56,11 +57,15 @@ async function generate(outputDirectory, clientAdditionalProperties) {
56
57
  }
57
58
  );
58
59
  await exec.exec(
59
- `yarn backstage-cli package lint --fix ${resolvedOutputDirectory}`
60
+ `yarn backstage-cli package lint --fix ${resolvedOutputDirectory}`,
61
+ [],
62
+ { signal: abortSignal?.signal }
60
63
  );
61
64
  const prettier = paths.paths.resolveTargetRoot("node_modules/.bin/prettier");
62
65
  if (prettier) {
63
- await exec.exec(`${prettier} --write ${resolvedOutputDirectory}`);
66
+ await exec.exec(`${prettier} --write ${resolvedOutputDirectory}`, [], {
67
+ signal: abortSignal?.signal
68
+ });
64
69
  }
65
70
  fs__default.default.removeSync(path.resolve(resolvedOutputDirectory, ".openapi-generator-ignore"));
66
71
  fs__default.default.rmSync(path.resolve(resolvedOutputDirectory, ".openapi-generator"), {
@@ -68,17 +73,29 @@ async function generate(outputDirectory, clientAdditionalProperties) {
68
73
  force: true
69
74
  });
70
75
  }
71
- async function command(outputPackage, clientAdditionalProperties) {
76
+ async function command(outputPackage, clientAdditionalProperties, {
77
+ abortSignal,
78
+ isWatch = false
79
+ } = {}) {
72
80
  try {
73
- await generate(outputPackage, clientAdditionalProperties);
81
+ await generate(outputPackage, clientAdditionalProperties, abortSignal);
74
82
  console.log(
75
83
  chalk__default.default.green(`Generated client in ${outputPackage}/${constants.OUTPUT_PATH}`)
76
84
  );
77
85
  } catch (err) {
78
- console.log();
79
- console.log(chalk__default.default.red(`Client generation failed:`));
80
- console.log(err);
81
- process.exit(1);
86
+ if (err.name === "AbortError") {
87
+ console.debug("Server generation aborted.");
88
+ return;
89
+ }
90
+ if (isWatch) {
91
+ console.log(chalk__default.default.red(`Client generation failed:`));
92
+ console.group();
93
+ console.log(chalk__default.default.red(err.message));
94
+ console.groupEnd();
95
+ } else {
96
+ console.log(chalk__default.default.red(`Client generation failed.`));
97
+ console.log(chalk__default.default.red(err.message));
98
+ }
82
99
  }
83
100
  }
84
101
 
@@ -3,10 +3,15 @@
3
3
  var chalk = require('chalk');
4
4
  var client = require('./client.cjs.js');
5
5
  var server = require('./server.cjs.js');
6
+ var chokidar = require('chokidar');
7
+ var helpers = require('../../../../../lib/openapi/helpers.cjs.js');
8
+ var lodash = require('lodash');
9
+ var runner = require('../../../../../lib/runner.cjs.js');
6
10
 
7
11
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
8
12
 
9
13
  var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
14
+ var chokidar__default = /*#__PURE__*/_interopDefaultCompat(chokidar);
10
15
 
11
16
  async function command(opts) {
12
17
  if (!opts.clientPackage && !opts.server) {
@@ -15,11 +20,64 @@ async function command(opts) {
15
20
  );
16
21
  process.exit(1);
17
22
  }
18
- if (opts.clientPackage) {
19
- await client.command(opts.clientPackage, opts.clientAdditionalProperties);
20
- }
21
- if (opts.server) {
22
- await server.command();
23
+ const sharedCommand = async (abortSignal) => {
24
+ const resolvedOpenapiPath = await helpers.getPathToCurrentOpenApiSpec();
25
+ await helpers.loadAndValidateOpenApiYaml(resolvedOpenapiPath);
26
+ const promises = [];
27
+ const options = {
28
+ isWatch: opts.watch,
29
+ abortSignal
30
+ };
31
+ if (opts.clientPackage) {
32
+ promises.push(
33
+ client.command(
34
+ opts.clientPackage,
35
+ opts.clientAdditionalProperties,
36
+ options
37
+ )
38
+ );
39
+ }
40
+ if (opts.server) {
41
+ promises.push(server.command(options));
42
+ }
43
+ await Promise.all(promises);
44
+ };
45
+ if (opts.watch) {
46
+ try {
47
+ const resolvedOpenapiPath = await helpers.getPathToCurrentOpenApiSpec();
48
+ let abortController = new AbortController();
49
+ const watcher = chokidar__default.default.watch(resolvedOpenapiPath);
50
+ const debouncedCommand = lodash.debounce(() => {
51
+ console.log("Detected changes! Regenerating...");
52
+ abortController.abort();
53
+ abortController = new AbortController();
54
+ sharedCommand(abortController).catch((err) => {
55
+ console.error(chalk__default.default.red("Error: ", err));
56
+ });
57
+ }, 500);
58
+ watcher.on("change", () => {
59
+ debouncedCommand();
60
+ });
61
+ watcher.on("error", (error) => {
62
+ console.error("Error happened", error);
63
+ });
64
+ watcher.on("ready", async () => {
65
+ console.log(
66
+ "Watching for changes in OpenAPI spec. Press Ctrl+C to stop."
67
+ );
68
+ });
69
+ debouncedCommand();
70
+ await runner.block();
71
+ } catch (err) {
72
+ console.error(chalk__default.default.red("Error: ", err));
73
+ process.exit(1);
74
+ }
75
+ } else {
76
+ try {
77
+ await sharedCommand();
78
+ } catch (err) {
79
+ process.exit(1);
80
+ }
23
81
  }
24
82
  }
25
83
 
@@ -16,7 +16,7 @@ var YAML__default = /*#__PURE__*/_interopDefaultCompat(YAML);
16
16
  var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
17
17
 
18
18
  const exec = util.promisify(child_process.exec);
19
- async function generate() {
19
+ async function generate(abortSignal) {
20
20
  const openapiPath = await helpers.getPathToCurrentOpenApiSpec();
21
21
  const yaml = YAML__default.default.load(await fs__default.default.readFile(openapiPath, "utf8"));
22
22
  const tsPath = paths.paths.resolveTarget(constants.TS_SCHEMA_PATH);
@@ -34,21 +34,37 @@ export const createOpenApiRouter = async (
34
34
  ) => createValidatedOpenApiRouter<typeof spec>(spec, options);
35
35
  `
36
36
  );
37
- await exec(`yarn backstage-cli package lint --fix ${tsPath}`);
37
+ await exec(`yarn backstage-cli package lint --fix ${tsPath}`, {
38
+ signal: abortSignal?.signal
39
+ });
38
40
  if (await paths.paths.resolveTargetRoot("node_modules/.bin/prettier")) {
39
41
  await exec(`yarn prettier --write ${tsPath}`, {
40
- cwd: paths.paths.targetRoot
42
+ cwd: paths.paths.targetRoot,
43
+ signal: abortSignal?.signal
41
44
  });
42
45
  }
43
46
  }
44
- async function command() {
47
+ async function command({
48
+ abortSignal,
49
+ isWatch = false
50
+ }) {
45
51
  try {
46
- await generate();
47
- console.log(chalk__default.default.green("Generated all files."));
52
+ await generate(abortSignal);
53
+ console.log(chalk__default.default.green("Generated server files."));
48
54
  } catch (err) {
49
- console.log(chalk__default.default.red(`OpenAPI server stub generation failed.`));
50
- console.log(err.message);
51
- process.exit(1);
55
+ if (err.name === "AbortError") {
56
+ console.debug("Server generation aborted.");
57
+ return;
58
+ }
59
+ if (isWatch) {
60
+ console.log(chalk__default.default.red(`Server generation failed:`));
61
+ console.group();
62
+ console.log(chalk__default.default.red(err.message));
63
+ console.groupEnd();
64
+ } else {
65
+ console.log(chalk__default.default.red(err.message));
66
+ console.log(chalk__default.default.red(`OpenAPI server stub generation failed.`));
67
+ }
52
68
  }
53
69
  }
54
70
 
@@ -1,11 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var fs = require('fs-extra');
4
- var YAML = require('js-yaml');
5
4
  var lodash = require('lodash');
6
5
  var path = require('path');
7
6
  var chalk = require('chalk');
8
- var Parser = require('@apidevtools/swagger-parser');
9
7
  var runner = require('../../../../lib/runner.cjs.js');
10
8
  var paths = require('../../../../lib/paths.cjs.js');
11
9
  var constants = require('../../../../lib/openapi/constants.cjs.js');
@@ -14,9 +12,7 @@ var helpers = require('../../../../lib/openapi/helpers.cjs.js');
14
12
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
15
13
 
16
14
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
17
- var YAML__default = /*#__PURE__*/_interopDefaultCompat(YAML);
18
15
  var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
19
- var Parser__default = /*#__PURE__*/_interopDefaultCompat(Parser);
20
16
 
21
17
  async function verify(directoryPath) {
22
18
  let openapiPath = "";
@@ -25,8 +21,7 @@ async function verify(directoryPath) {
25
21
  } catch {
26
22
  return;
27
23
  }
28
- const yaml = YAML__default.default.load(await fs__default.default.readFile(openapiPath, "utf8"));
29
- await Parser__default.default.validate(lodash.cloneDeep(yaml));
24
+ const yaml = await helpers.loadAndValidateOpenApiYaml(openapiPath);
30
25
  const schemaPath = path.join(directoryPath, constants.TS_SCHEMA_PATH);
31
26
  if (!await fs__default.default.pathExists(schemaPath)) {
32
27
  throw new Error(`No \`${constants.TS_SCHEMA_PATH}\` file found.`);
@@ -4,6 +4,15 @@ var fs = require('fs-extra');
4
4
  var paths = require('../paths.cjs.js');
5
5
  var constants = require('./constants.cjs.js');
6
6
  var path = require('path');
7
+ var YAML = require('js-yaml');
8
+ var lodash = require('lodash');
9
+ var Parser = require('@apidevtools/swagger-parser');
10
+
11
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
12
+
13
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
14
+ var YAML__default = /*#__PURE__*/_interopDefaultCompat(YAML);
15
+ var Parser__default = /*#__PURE__*/_interopDefaultCompat(Parser);
7
16
 
8
17
  const getPathToFile = async (directory, filename) => {
9
18
  return path.resolve(directory, filename);
@@ -23,10 +32,16 @@ const getPathToOpenApiSpec = async (directory) => {
23
32
  const getPathToCurrentOpenApiSpec = async () => {
24
33
  return await assertExists(await getRelativePathToFile(constants.YAML_SCHEMA_PATH));
25
34
  };
35
+ async function loadAndValidateOpenApiYaml(path) {
36
+ const yaml = YAML__default.default.load(await fs__default.default.readFile(path, "utf8"));
37
+ await Parser__default.default.validate(lodash.cloneDeep(yaml));
38
+ return yaml;
39
+ }
26
40
 
27
41
  exports.assertExists = assertExists;
28
42
  exports.getPathToCurrentOpenApiSpec = getPathToCurrentOpenApiSpec;
29
43
  exports.getPathToFile = getPathToFile;
30
44
  exports.getPathToOpenApiSpec = getPathToOpenApiSpec;
31
45
  exports.getRelativePathToFile = getRelativePathToFile;
46
+ exports.loadAndValidateOpenApiYaml = loadAndValidateOpenApiYaml;
32
47
  //# sourceMappingURL=helpers.cjs.js.map
@@ -43,6 +43,11 @@ async function runner(paths$1, command, options) {
43
43
  );
44
44
  return resultsList;
45
45
  }
46
+ async function block() {
47
+ return new Promise(() => {
48
+ });
49
+ }
46
50
 
51
+ exports.block = block;
47
52
  exports.runner = runner;
48
53
  //# sourceMappingURL=runner.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.10.0-next.2";
3
+ var version = "0.11.0-next.0";
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.10.0-next.2",
3
+ "version": "0.11.0-next.0",
4
4
  "description": "CLI for Backstage repo tooling ",
5
5
  "backstage": {
6
6
  "role": "cli"
@@ -43,10 +43,10 @@
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.1-next.1",
46
+ "@backstage/backend-plugin-api": "1.0.2-next.0",
47
47
  "@backstage/catalog-model": "1.7.0",
48
48
  "@backstage/cli-common": "0.1.14",
49
- "@backstage/cli-node": "0.2.9-next.0",
49
+ "@backstage/cli-node": "0.2.9",
50
50
  "@backstage/config-loader": "1.9.1",
51
51
  "@backstage/errors": "1.2.4",
52
52
  "@manypkg/get-packages": "^1.1.3",
@@ -62,6 +62,7 @@
62
62
  "@stoplight/types": "^14.0.0",
63
63
  "@useoptic/openapi-utilities": "^0.55.0",
64
64
  "chalk": "^4.0.0",
65
+ "chokidar": "^3.5.3",
65
66
  "codeowners-utils": "^1.0.2",
66
67
  "command-exists": "^1.2.9",
67
68
  "commander": "^12.0.0",
@@ -77,8 +78,8 @@
77
78
  "yaml-diff-patch": "^2.0.0"
78
79
  },
79
80
  "devDependencies": {
80
- "@backstage/backend-test-utils": "1.0.1-next.2",
81
- "@backstage/cli": "0.28.0-next.2",
81
+ "@backstage/backend-test-utils": "1.0.3-next.0",
82
+ "@backstage/cli": "0.29.0-next.0",
82
83
  "@backstage/types": "1.1.1",
83
84
  "@types/is-glob": "^4.0.2",
84
85
  "@types/node": "^18.17.8",
@@ -88,7 +89,7 @@
88
89
  "@microsoft/api-extractor-model": "*",
89
90
  "@microsoft/tsdoc": "*",
90
91
  "@microsoft/tsdoc-config": "*",
91
- "@useoptic/optic": "^0.50.7",
92
+ "@useoptic/optic": "^1.0.0",
92
93
  "prettier": "^2.8.1",
93
94
  "typescript": "> 3.0.0"
94
95
  },