@backstage/cli 0.28.0-next.2 → 0.29.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/config/jest.js +49 -25
  3. package/config/jestRejectNetworkRequests.js +59 -0
  4. package/config/nodeTransform.cjs +33 -0
  5. package/dist/commands/build/buildFrontend.cjs.js +11 -13
  6. package/dist/commands/build/command.cjs.js +5 -2
  7. package/dist/commands/buildWorkspace.cjs.js +1 -1
  8. package/dist/commands/index.cjs.js +9 -3
  9. package/dist/commands/repo/lint.cjs.js +23 -33
  10. package/dist/commands/repo/test.cjs.js +13 -32
  11. package/dist/commands/start/command.cjs.js +1 -0
  12. package/dist/commands/start/startBackend.cjs.js +23 -92
  13. package/dist/commands/start/startFrontend.cjs.js +6 -8
  14. package/dist/commands/versions/bump.cjs.js +9 -3
  15. package/dist/lib/bundler/bundle.cjs.js +5 -4
  16. package/dist/lib/bundler/config.cjs.js +75 -171
  17. package/dist/lib/bundler/hasReactDomClient.cjs.js +5 -1
  18. package/dist/lib/bundler/linkWorkspaces.cjs.js +31 -0
  19. package/dist/lib/bundler/optimization.cjs.js +10 -6
  20. package/dist/lib/bundler/server.cjs.js +47 -7
  21. package/dist/lib/bundler/transforms.cjs.js +7 -6
  22. package/dist/lib/cache/SuccessCache.cjs.js +70 -0
  23. package/dist/lib/packager/createDistWorkspace.cjs.js +3 -3
  24. package/dist/lib/{experimental/startBackendExperimental.cjs.js → runner/runBackend.cjs.js} +6 -5
  25. package/dist/lib/version.cjs.js +30 -22
  26. package/dist/packages/backend-defaults/package.json.cjs.js +1 -1
  27. package/dist/packages/backend-plugin-api/package.json.cjs.js +1 -1
  28. package/dist/packages/backend-test-utils/package.json.cjs.js +1 -1
  29. package/dist/packages/catalog-client/package.json.cjs.js +6 -0
  30. package/dist/packages/cli/package.json.cjs.js +15 -5
  31. package/dist/packages/core-app-api/package.json.cjs.js +1 -1
  32. package/dist/packages/core-components/package.json.cjs.js +1 -1
  33. package/dist/packages/core-plugin-api/package.json.cjs.js +1 -1
  34. package/dist/packages/dev-utils/package.json.cjs.js +1 -1
  35. package/dist/packages/errors/package.json.cjs.js +6 -0
  36. package/dist/packages/test-utils/package.json.cjs.js +1 -1
  37. package/dist/packages/theme/package.json.cjs.js +1 -1
  38. package/dist/plugins/auth-backend/package.json.cjs.js +1 -1
  39. package/dist/plugins/auth-backend-module-guest-provider/package.json.cjs.js +1 -1
  40. package/dist/plugins/catalog-node/package.json.cjs.js +6 -0
  41. package/dist/plugins/scaffolder-node/package.json.cjs.js +1 -1
  42. package/dist/plugins/scaffolder-node-test-utils/package.json.cjs.js +6 -0
  43. package/package.json +45 -19
  44. package/templates/default-backend-plugin/README.md.hbs +22 -8
  45. package/templates/default-backend-plugin/dev/index.ts.hbs +60 -0
  46. package/templates/default-backend-plugin/package.json.hbs +5 -5
  47. package/templates/default-backend-plugin/src/index.ts.hbs +0 -1
  48. package/templates/default-backend-plugin/src/plugin.test.ts.hbs +85 -0
  49. package/templates/default-backend-plugin/src/plugin.ts.hbs +16 -14
  50. package/templates/default-backend-plugin/src/router.test.ts +67 -0
  51. package/templates/default-backend-plugin/src/router.ts +51 -0
  52. package/templates/default-backend-plugin/src/services/TodoListService/createTodoListService.ts +100 -0
  53. package/templates/default-backend-plugin/src/services/TodoListService/index.ts +1 -0
  54. package/templates/default-backend-plugin/src/services/TodoListService/types.ts +27 -0
  55. package/templates/scaffolder-module/package.json.hbs +3 -1
  56. package/templates/scaffolder-module/src/actions/example.test.ts +24 -0
  57. package/templates/scaffolder-module/src/actions/{example/example.ts → example.ts} +7 -3
  58. package/templates/scaffolder-module/src/index.ts.hbs +1 -1
  59. package/templates/scaffolder-module/src/{actions/example/module.ts → module.ts} +3 -3
  60. package/dist/lib/bundler/LinkedPackageResolvePlugin.cjs.js +0 -47
  61. package/dist/lib/bundler/backend.cjs.js +0 -36
  62. package/templates/default-backend-plugin/dev/index.ts +0 -9
  63. package/templates/default-backend-plugin/src/service/router.test.ts +0 -30
  64. package/templates/default-backend-plugin/src/service/router.ts +0 -28
  65. package/templates/scaffolder-module/src/actions/example/example.test.ts +0 -32
  66. package/templates/scaffolder-module/src/actions/example/index.ts +0 -7
  67. package/templates/scaffolder-module/src/actions/index.ts +0 -1
  68. /package/dist/lib/{experimental → ipc}/IpcServer.cjs.js +0 -0
  69. /package/dist/lib/{experimental → ipc}/ServerDataStore.cjs.js +0 -0
@@ -2,40 +2,20 @@
2
2
 
3
3
  var os = require('os');
4
4
  var crypto = require('node:crypto');
5
- var fs = require('fs-extra');
6
5
  var yargs = require('yargs');
7
6
  var path = require('path');
8
7
  var cliNode = require('@backstage/cli-node');
9
8
  var paths = require('../../lib/paths.cjs.js');
10
9
  var run = require('../../lib/run.cjs.js');
11
10
  var cliCommon = require('@backstage/cli-common');
11
+ var SuccessCache = require('../../lib/cache/SuccessCache.cjs.js');
12
12
 
13
13
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
14
14
 
15
15
  var os__default = /*#__PURE__*/_interopDefaultCompat(os);
16
16
  var crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
17
- var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
18
17
  var yargs__default = /*#__PURE__*/_interopDefaultCompat(yargs);
19
18
 
20
- const CACHE_FILE_NAME = "test-cache.json";
21
- async function readCache(dir) {
22
- try {
23
- const data = await fs__default.default.readJson(path.resolve(dir, CACHE_FILE_NAME));
24
- if (!Array.isArray(data)) {
25
- return void 0;
26
- }
27
- if (data.some((x) => typeof x !== "string")) {
28
- return void 0;
29
- }
30
- return data;
31
- } catch {
32
- return void 0;
33
- }
34
- }
35
- function writeCache(dir, cache) {
36
- fs__default.default.mkdirpSync(dir);
37
- fs__default.default.writeJsonSync(path.resolve(dir, CACHE_FILE_NAME), cache, { spaces: 2 });
38
- }
39
19
  async function readPackageTreeHashes(graph) {
40
20
  const pkgs = Array.from(graph.values());
41
21
  const output = await run.runPlain(
@@ -116,7 +96,7 @@ async function command(opts, cmd) {
116
96
  if (!hasFlags("--passWithNoTests")) {
117
97
  args.push("--passWithNoTests");
118
98
  }
119
- if (!process.env.CI && !hasFlags("--coverage", "--watch", "--watchAll")) {
99
+ if (!opts.since && !process.env.CI && !hasFlags("--coverage", "--watch", "--watchAll")) {
120
100
  const isGitRepo = () => run.runCheck("git", "rev-parse", "--is-inside-work-tree");
121
101
  const isMercurialRepo = () => run.runCheck("hg", "--cwd", ".", "root");
122
102
  if (await isGitRepo() || await isMercurialRepo()) {
@@ -143,23 +123,24 @@ async function command(opts, cmd) {
143
123
  packageGraph = cliNode.PackageGraph.fromPackages(packages);
144
124
  return packageGraph;
145
125
  }
126
+ let selectedProjects = void 0;
146
127
  if (opts.since && !hasFlags("--selectProjects")) {
147
128
  const graph = await getPackageGraph();
148
129
  const changedPackages = await graph.listChangedPackages({
149
130
  ref: opts.since,
150
131
  analyzeLockfile: true
151
132
  });
152
- const packageNames = Array.from(
133
+ selectedProjects = Array.from(
153
134
  graph.collectPackageNames(
154
135
  changedPackages.map((pkg) => pkg.name),
155
136
  (pkg) => pkg.allLocalDependents.keys()
156
137
  )
157
138
  );
158
- if (packageNames.length === 0) {
139
+ if (selectedProjects.length === 0) {
159
140
  console.log(`No packages changed since ${opts.since}`);
160
141
  return;
161
142
  }
162
- args.push("--selectProjects", ...packageNames);
143
+ args.push("--selectProjects", ...selectedProjects);
163
144
  }
164
145
  if (!process.env.NODE_ENV) {
165
146
  process.env.NODE_ENV = "test";
@@ -176,9 +157,6 @@ async function command(opts, cmd) {
176
157
  if (opts.successCache) {
177
158
  removeOptionArg(args, "--successCache", 1);
178
159
  removeOptionArg(args, "--successCacheDir");
179
- const cacheDir = path.resolve(
180
- opts.successCacheDir ?? "node_modules/.cache/backstage-cli"
181
- );
182
160
  const { _: parsedArgs } = await yargs__default.default(args).options(jestCli.yargsOptions).argv;
183
161
  if (parsedArgs.length > 0) {
184
162
  throw new Error(
@@ -192,6 +170,7 @@ async function command(opts, cmd) {
192
170
  `The --successCache flag can not be combined with the --shard flag`
193
171
  );
194
172
  }
173
+ const cache = new SuccessCache.SuccessCache("test", opts.successCacheDir);
195
174
  const graph = await getPackageGraph();
196
175
  const projectHashes = /* @__PURE__ */ new Map();
197
176
  const outputSuccessCache = new Array();
@@ -199,7 +178,7 @@ async function command(opts, cmd) {
199
178
  globalWithCache.__backstageCli_jestSuccessCache = {
200
179
  // This is called by `config/jest.js` after the project configs have been gathered
201
180
  async filterConfigs(projectConfigs, globalRootConfig) {
202
- const cache = await readCache(cacheDir);
181
+ const cacheEntries = await cache.read();
203
182
  const lockfile = await cliNode.Lockfile.load(
204
183
  paths.paths.resolveTargetRoot("yarn.lock")
205
184
  );
@@ -231,8 +210,10 @@ async function command(opts, cmd) {
231
210
  hash.update(lockfile.getDependencyTreeHash(packageName));
232
211
  const sha = hash.digest("hex");
233
212
  projectHashes.set(packageName, sha);
234
- if (cache?.includes(sha)) {
235
- console.log(`Skipped ${packageName} due to cache hit`);
213
+ if (cacheEntries.has(sha)) {
214
+ if (!selectedProjects || selectedProjects.includes(packageName)) {
215
+ console.log(`Skipped ${packageName} due to cache hit`);
216
+ }
236
217
  outputSuccessCache.push(sha);
237
218
  return void 0;
238
219
  }
@@ -262,7 +243,7 @@ async function command(opts, cmd) {
262
243
  outputSuccessCache.push(sha);
263
244
  }
264
245
  }
265
- await writeCache(cacheDir, outputSuccessCache);
246
+ await cache.write(outputSuccessCache);
266
247
  }
267
248
  };
268
249
  }
@@ -9,6 +9,7 @@ async function command(opts) {
9
9
  const options = {
10
10
  configPaths: opts.config,
11
11
  checksEnabled: Boolean(opts.check),
12
+ linkedWorkspace: opts.link,
12
13
  inspectEnabled: opts.inspect,
13
14
  inspectBrkEnabled: opts.inspectBrk,
14
15
  require: opts.require
@@ -2,109 +2,40 @@
2
2
 
3
3
  var fs = require('fs-extra');
4
4
  var paths = require('../../lib/paths.cjs.js');
5
- var backend = require('../../lib/bundler/backend.cjs.js');
6
- require('yn');
7
- require('path');
8
- require('webpack');
9
- require('react-dev-utils/FileSizeReporter');
10
- require('react-dev-utils/formatWebpackMessages');
11
- require('chalk');
12
- require('eslint-webpack-plugin');
13
- require('fork-ts-checker-webpack-plugin');
14
- require('html-webpack-plugin');
15
- require('@module-federation/enhanced/webpack');
16
- require('@backstage/cli-common');
17
- require('react-dev-utils/ModuleScopePlugin');
18
- require('run-script-webpack-plugin');
19
- require('@pmmmwh/react-refresh-webpack-plugin');
20
- require('@manypkg/get-packages');
21
- require('webpack-node-externals');
22
- require('../../lib/bundler/optimization.cjs.js');
23
- require('lodash/pickBy');
24
- require('../../lib/run.cjs.js');
25
- require('mini-css-extract-plugin');
26
- require('../../lib/version.cjs.js');
27
- require('../../lib/bundler/packageDetection.cjs.js');
28
- require('react-dev-utils/openBrowser');
29
- require('webpack-dev-server');
30
- require('@backstage/config-loader');
31
- require('@backstage/config');
32
- require('@backstage/cli-node');
33
- var startBackendExperimental = require('../../lib/experimental/startBackendExperimental.cjs.js');
5
+ var runBackend = require('../../lib/runner/runBackend.cjs.js');
34
6
 
35
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
36
8
 
37
9
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
38
10
 
39
11
  async function startBackend(options) {
40
- if (!process.env.LEGACY_BACKEND_START) {
41
- const waitForExit = await startBackendExperimental.startBackendExperimental({
42
- entry: "src/index",
43
- checksEnabled: false,
44
- // not supported
45
- inspectEnabled: options.inspectEnabled,
46
- inspectBrkEnabled: options.inspectBrkEnabled,
47
- require: options.require
48
- });
49
- await waitForExit();
50
- } else {
51
- console.warn(
52
- "LEGACY_BACKEND_START is deprecated and will be removed in a future release"
53
- );
54
- const waitForExit = await cleanDistAndServeBackend({
55
- entry: "src/index",
56
- checksEnabled: options.checksEnabled,
57
- inspectEnabled: options.inspectEnabled,
58
- inspectBrkEnabled: options.inspectBrkEnabled,
59
- require: options.require
60
- });
61
- await waitForExit();
62
- }
12
+ const waitForExit = await runBackend.runBackend({
13
+ entry: "src/index",
14
+ inspectEnabled: options.inspectEnabled,
15
+ inspectBrkEnabled: options.inspectBrkEnabled,
16
+ linkedWorkspace: options.linkedWorkspace,
17
+ require: options.require
18
+ });
19
+ await waitForExit();
63
20
  }
64
21
  async function startBackendPlugin(options) {
65
- if (!process.env.LEGACY_BACKEND_START) {
66
- const hasDevIndexEntry = await fs__default.default.pathExists(
67
- paths.paths.resolveTarget("dev", "index.ts")
68
- );
69
- if (!hasDevIndexEntry) {
70
- console.warn(
71
- `The 'dev' directory is missing. Please create a proper dev/index.ts in order to start the plugin.`
72
- );
73
- return;
74
- }
75
- const waitForExit = await startBackendExperimental.startBackendExperimental({
76
- entry: "dev/index",
77
- checksEnabled: false,
78
- // not supported
79
- inspectEnabled: options.inspectEnabled,
80
- inspectBrkEnabled: options.inspectBrkEnabled,
81
- require: options.require
82
- });
83
- await waitForExit();
84
- } else {
85
- const hasEntry = await fs__default.default.pathExists(paths.paths.resolveTarget("src", "run.ts"));
86
- if (!hasEntry) {
87
- console.warn(
88
- `src/run.ts is missing. Please create the file or run the command without LEGACY_BACKEND_START`
89
- );
90
- return;
91
- }
22
+ const hasDevIndexEntry = await fs__default.default.pathExists(
23
+ paths.paths.resolveTarget("dev", "index.ts")
24
+ );
25
+ if (!hasDevIndexEntry) {
92
26
  console.warn(
93
- "LEGACY_BACKEND_START is deprecated and will be removed in a future release"
27
+ `The 'dev' directory is missing. Please create a proper dev/index.ts in order to start the plugin.`
94
28
  );
95
- const waitForExit = await cleanDistAndServeBackend({
96
- entry: "src/run",
97
- checksEnabled: options.checksEnabled,
98
- inspectEnabled: options.inspectEnabled,
99
- inspectBrkEnabled: options.inspectBrkEnabled,
100
- require: options.require
101
- });
102
- await waitForExit();
29
+ return;
103
30
  }
104
- }
105
- async function cleanDistAndServeBackend(options) {
106
- await fs__default.default.remove(paths.paths.resolveTarget("dist"));
107
- return backend.serveBackend(options);
31
+ const waitForExit = await runBackend.runBackend({
32
+ entry: "dev/index",
33
+ inspectEnabled: options.inspectEnabled,
34
+ inspectBrkEnabled: options.inspectBrkEnabled,
35
+ require: options.require,
36
+ linkedWorkspace: options.linkedWorkspace
37
+ });
38
+ await waitForExit();
108
39
  }
109
40
 
110
41
  exports.startBackend = startBackend;
@@ -1,28 +1,25 @@
1
1
  'use strict';
2
2
 
3
3
  var fs = require('fs-extra');
4
- require('webpack');
4
+ require('yn');
5
5
  require('path');
6
+ require('webpack');
7
+ require('react-dev-utils/FileSizeReporter');
8
+ require('react-dev-utils/formatWebpackMessages');
6
9
  require('chalk');
7
10
  require('eslint-webpack-plugin');
8
11
  require('fork-ts-checker-webpack-plugin');
9
12
  require('html-webpack-plugin');
10
13
  require('@module-federation/enhanced/webpack');
11
- require('@backstage/cli-common');
12
14
  require('react-dev-utils/ModuleScopePlugin');
13
- require('run-script-webpack-plugin');
14
15
  require('@pmmmwh/react-refresh-webpack-plugin');
15
16
  var paths = require('../../lib/paths.cjs.js');
16
- require('@manypkg/get-packages');
17
- require('webpack-node-externals');
18
17
  require('../../lib/bundler/optimization.cjs.js');
19
18
  require('lodash/pickBy');
20
19
  require('../../lib/run.cjs.js');
21
20
  require('mini-css-extract-plugin');
22
21
  require('../../lib/version.cjs.js');
23
- require('yn');
24
- require('react-dev-utils/FileSizeReporter');
25
- require('react-dev-utils/formatWebpackMessages');
22
+ require('@manypkg/get-packages');
26
23
  require('../../lib/bundler/packageDetection.cjs.js');
27
24
  var moduleFederation = require('../../lib/bundler/moduleFederation.cjs.js');
28
25
  var server = require('../../lib/bundler/server.cjs.js');
@@ -35,6 +32,7 @@ async function startFrontend(options) {
35
32
  configPaths: options.configPaths,
36
33
  verifyVersions: options.verifyVersions,
37
34
  skipOpenBrowser: options.skipOpenBrowser,
35
+ linkedWorkspace: options.linkedWorkspace,
38
36
  moduleFederation: moduleFederation.getModuleFederationOptions(
39
37
  name,
40
38
  options.isModuleFederationRemote
@@ -160,7 +160,10 @@ var bump = async (opts) => {
160
160
  });
161
161
  console.log();
162
162
  if (pattern === DEFAULT_PATTERN_GLOB) {
163
- await bumpBackstageJsonVersion(releaseManifest.releaseVersion);
163
+ await bumpBackstageJsonVersion(
164
+ releaseManifest.releaseVersion,
165
+ hasYarnPlugin
166
+ );
164
167
  } else {
165
168
  console.log(
166
169
  chalk__default.default.yellow(
@@ -306,7 +309,7 @@ async function getBackstageJson() {
306
309
  throw e;
307
310
  });
308
311
  }
309
- async function bumpBackstageJsonVersion(version) {
312
+ async function bumpBackstageJsonVersion(version, useYarnPlugin) {
310
313
  const backstageJson = await getBackstageJson();
311
314
  const prevVersion = backstageJson?.version;
312
315
  if (prevVersion === version) {
@@ -316,7 +319,10 @@ async function bumpBackstageJsonVersion(version) {
316
319
  if (prevVersion) {
317
320
  const from = encodeURIComponent(prevVersion);
318
321
  const to = encodeURIComponent(version);
319
- const link = `https://backstage.github.io/upgrade-helper/?from=${from}&to=${to}`;
322
+ let link = `https://backstage.github.io/upgrade-helper/?from=${from}&to=${to}`;
323
+ if (useYarnPlugin) {
324
+ link += "&yarnPlugin=1";
325
+ }
320
326
  console.log(
321
327
  yellow(
322
328
  `Upgraded from release ${green(prevVersion)} to ${green(
@@ -26,7 +26,7 @@ function applyContextToError(error, moduleName) {
26
26
  ${error}`;
27
27
  }
28
28
  async function buildBundle(options) {
29
- const { statsJsonEnabled, schema: configSchema } = options;
29
+ const { statsJsonEnabled, schema: configSchema, rspack } = options;
30
30
  const paths$1 = paths.resolveBundlingPaths(options);
31
31
  const publicPaths = await paths.resolveOptionalBundlingPaths({
32
32
  targetDir: options.targetDir,
@@ -91,7 +91,7 @@ async function buildBundle(options) {
91
91
  { spaces: 2 }
92
92
  );
93
93
  }
94
- const { stats } = await build(configs, isCi);
94
+ const { stats } = await build(configs, isCi, rspack);
95
95
  if (!stats) {
96
96
  throw new Error("No stats returned");
97
97
  }
@@ -119,10 +119,11 @@ async function buildBundle(options) {
119
119
  );
120
120
  }
121
121
  }
122
- async function build(configs, isCi) {
122
+ async function build(configs, isCi, rspack) {
123
+ const bundler = rspack ?? webpack__default.default;
123
124
  const stats = await new Promise(
124
125
  (resolve, reject) => {
125
- webpack__default.default(configs, (err, buildStats) => {
126
+ bundler(configs, (err, buildStats) => {
126
127
  if (err) {
127
128
  if (err.message) {
128
129
  const { errors: errors2 } = formatWebpackMessages__default.default({