@backstage/backend-dynamic-feature-service 0.8.0-next.1 → 0.8.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,50 @@
1
1
  # @backstage/backend-dynamic-feature-service
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0fbcf23: Migrated OpenAPI schemas to 3.1.
8
+
9
+ ### Patch Changes
10
+
11
+ - 4074a22: Fixed `resolvePackagePath` resolution for bundled dynamic plugins. When a plugin bundles its own copy of `@backstage/backend-plugin-api` inside `node_modules`, the `CommonJSModuleLoader` fallback now correctly resolves the plugin's `package.json` by name. Previously the fallback only applied when the resolution originated from the host application; it now also applies when originating from a bundled dependency, which is the case for plugins produced by the `backstage-cli package bundle` command.
12
+ - 70fc178: Migrated from deprecated `findPaths` to `targetPaths` and `findOwnPaths` from `@backstage/cli-common`.
13
+ - Updated dependencies
14
+ - @backstage/backend-plugin-api@1.8.0
15
+ - @backstage/backend-defaults@0.16.0
16
+ - @backstage/cli-node@0.3.0
17
+ - @backstage/plugin-catalog-backend@3.5.0
18
+ - @backstage/cli-common@0.2.0
19
+ - @backstage/plugin-scaffolder-node@0.13.0
20
+ - @backstage/plugin-events-backend@0.6.0
21
+ - @backstage/config-loader@1.10.9
22
+ - @backstage/plugin-permission-common@0.9.7
23
+ - @backstage/plugin-permission-node@0.10.11
24
+ - @backstage/plugin-auth-node@0.6.14
25
+ - @backstage/backend-openapi-utils@0.6.7
26
+ - @backstage/plugin-app-node@0.1.43
27
+ - @backstage/plugin-events-node@0.4.20
28
+ - @backstage/plugin-search-backend-node@1.4.2
29
+
30
+ ## 0.8.0-next.2
31
+
32
+ ### Patch Changes
33
+
34
+ - Updated dependencies
35
+ - @backstage/backend-plugin-api@1.8.0-next.1
36
+ - @backstage/backend-defaults@0.16.0-next.2
37
+ - @backstage/cli-common@0.2.0-next.2
38
+ - @backstage/plugin-catalog-backend@3.5.0-next.2
39
+ - @backstage/backend-openapi-utils@0.6.7-next.1
40
+ - @backstage/plugin-app-node@0.1.43-next.1
41
+ - @backstage/plugin-auth-node@0.6.14-next.2
42
+ - @backstage/plugin-events-backend@0.6.0-next.2
43
+ - @backstage/plugin-events-node@0.4.20-next.1
44
+ - @backstage/plugin-permission-node@0.10.11-next.1
45
+ - @backstage/plugin-scaffolder-node@0.13.0-next.2
46
+ - @backstage/plugin-search-backend-node@1.4.2-next.1
47
+
3
48
  ## 0.8.0-next.1
4
49
 
5
50
  ### Minor Changes
package/README.md CHANGED
@@ -97,7 +97,7 @@ Since this service only handles loading, you would choose a packaging approach b
97
97
 
98
98
  **When to use:** Plugin only uses dependencies that are already provided by the main Backstage application.
99
99
 
100
- **How to apply:**
100
+ **How to use:**
101
101
 
102
102
  ```bash
103
103
  cd my-backstage-plugin
@@ -117,7 +117,7 @@ tar -xzf package.tgz -C /path/to/dynamic-plugins-root/my-backstage-plugin --stri
117
117
 
118
118
  **When to use:** Plugin has private dependencies not available in the main Backstage application.
119
119
 
120
- **How to apply:**
120
+ **How to use:**
121
121
 
122
122
  ```bash
123
123
  # Package the plugin
@@ -136,35 +136,47 @@ yarn install # Installs all the plugin's dependencies
136
136
 
137
137
  **Example scenario:** Plugin needs `axios@1.4.0` which isn't available in the main application.
138
138
 
139
- ### 3. Custom packaging CLI tool
139
+ ### 3. Dedicated bundling CLI command
140
140
 
141
- **When to use:** When you want to produce self-contained dynamic plugin packages that can be directly extracted without any post-action, and systematically use the core `@backstage` dependencies provided by the Backstage application.
141
+ **When to use:**
142
142
 
143
- **What a packaging CLI needs to do:**
143
+ - When you want to produce self-contained dynamic plugin packages that can be directly extracted and loaded without any post-action,
144
+ - especially when your plugin depends on other packages in the same monorepo.
144
145
 
145
- 1. **Analyze plugin dependencies** - Identify which are Backstage core vs private dependencies
146
- 2. **Create distribution package** - Generate a new directory with modified structure:
147
- - Move `@backstage/*` packages from `dependencies` to `peerDependencies` in package.json
148
- - Keep only private dependencies in the `dependencies` section
149
- - Keep the built JavaScript code unchanged
150
- - Include only the filtered private dependencies in `node_modules`
151
- 3. **Result** - A self-contained package that uses the main app's `@backstage/*` packages but includes its own private dependencies
146
+ **How to use:**
152
147
 
153
- **Benefits:**
148
+ The [`backstage-cli package bundle`](../cli/cli-report.md) command automates the required steps. Run it from within a plugin directory:
154
149
 
155
- - Systematic use of main application's `@backstage/*` packages (no version conflicts), enabling the future implementation of `@backstage` dependency version checking at start time
156
- - Self-contained packages with only necessary private dependencies
157
- - No post-installation steps required (extract and run)
158
- - Consistent dependency structure across all dynamic plugins
159
- - Production-ready distribution format
150
+ ```bash
151
+ cd my-backstage-plugin
152
+ yarn backstage-cli package bundle --output-destination /path/to/dynamic-plugins-root
153
+ # Creates a self-contained bundle in the /path/to/dynamic-plugins-root/my-backstage-plugin/ sub-folder
154
+ ```
160
155
 
161
- **Example implementation:** The [`@red-hat-developer-hub/cli`](https://github.com/redhat-developer/rhdh-cli) tool implements this approach:
156
+ **Batch bundling:** When bundling many plugins from the same monorepo, use `--pre-packed-dir` to avoid redundant work:
162
157
 
163
158
  ```bash
164
- cd my-backstage-plugin
165
- npx @red-hat-developer-hub/cli@latest plugin export
166
- # Creates a self-contained package with embedded dependencies in the `/dist-dynamic` sub-folder
159
+ # First, build a shared dist workspace
160
+ backstage-cli build-workspace dist-workspace --alwaysPack ...plugin-packages
167
161
 
168
- # Deploy the generated package
169
- cp -r dist-dynamic /path/to/dynamic-plugins-root/my-backstage-plugin
162
+ # Then bundle each plugin using the pre-packed output
163
+ cd plugins/my-backstage-plugin
164
+ backstage-cli package bundle --pre-packed-dir ../../dist-workspace
170
165
  ```
166
+
167
+ See the full list of options in the [CLI reference](../cli/cli-report.md).
168
+
169
+ **What the command does:**
170
+
171
+ 1. **Builds the plugin** — Produces CJS output for the backend plugin and its transitively-required monorepo packages (`*-node` or `*-common`)
172
+ 2. **Packs local packages** — Resolves `workspace:^` and `backstage:^` dependencies on both the main plugin package and its transitively-required monorepo packages (`*-node` or `*-common`)
173
+ 3. **Installs private dependencies** — Seeds a lockfile from the plugin source monorepo and prunes it, then installs a private `node_modules` containing all required dependencies
174
+ 4. **Collects configuration schemas** — Gathers plugin config schemas and writes them to `dist/.config-schema.json` so they are available for validation at load time
175
+
176
+ **Benefits:**
177
+
178
+ - Self-contained packages with all necessary dependencies
179
+ - No post-installation steps required (extract and run)
180
+ - Consistent dependency structure across all dynamic plugins
181
+ - Automatic configuration schema collection
182
+ - Production-ready distribution format
@@ -44,8 +44,10 @@ class CommonJSModuleLoader {
44
44
  e instanceof Error ? e : void 0
45
45
  );
46
46
  }
47
- const resolvingPackageJsonFromBackstageApplication = request?.endsWith("/package.json") && mod?.path && !dynamicPluginsPaths.some((p) => mod.path.startsWith(p));
48
- if (!resolvingPackageJsonFromBackstageApplication) {
47
+ const resolvingPackageJsonViaResolvePackagePath = request?.endsWith("/package.json") && /[/\\](?:@backstage|packages)[/\\]backend-plugin-api(?:[/\\]|$)/.test(
48
+ mod?.path ?? ""
49
+ );
50
+ if (!resolvingPackageJsonViaResolvePackagePath) {
49
51
  throw errorToThrow;
50
52
  }
51
53
  this.options.logger.info(
@@ -1 +1 @@
1
- {"version":3,"file":"CommonJSModuleLoader.cjs.js","sources":["../../src/loader/CommonJSModuleLoader.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ModuleLoader } from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport path from 'node:path';\nimport { ScannedPluginManifest } from '../scanner';\n\n/**\n * @public\n */\nexport type CommonJSModuleLoaderOptions = {\n logger: LoggerService;\n dynamicPluginPackageNameSuffixes?: String[];\n customResolveDynamicPackage?: (\n logger: LoggerService,\n searchedPackageName: string,\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ) => string | undefined;\n};\n\n/**\n * @public\n */\nexport class CommonJSModuleLoader implements ModuleLoader {\n private module: any;\n public readonly options: CommonJSModuleLoaderOptions;\n\n constructor(options: CommonJSModuleLoaderOptions) {\n this.options = options;\n this.module = require('node:module');\n }\n\n async bootstrap(\n backstageRoot: string,\n dynamicPluginsPaths: string[],\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ): Promise<void> {\n const backstageRootNodeModulesPath = `${backstageRoot}/node_modules`;\n const dynamicNodeModulesPaths = [\n ...dynamicPluginsPaths.map(p => path.resolve(p, 'node_modules')),\n ];\n const oldNodeModulePaths = this.module._nodeModulePaths;\n this.module._nodeModulePaths = (from: string): string[] => {\n const result: string[] = oldNodeModulePaths(from);\n if (!dynamicPluginsPaths.some(p => from.startsWith(p))) {\n return result;\n }\n const filtered = result.filter(nodeModulePath => {\n return (\n nodeModulePath === backstageRootNodeModulesPath ||\n dynamicNodeModulesPaths.some(p => nodeModulePath.startsWith(p))\n );\n });\n this.options.logger.debug(\n `Overriding node_modules search path for dynamic plugin ${from} to: ${filtered}`,\n );\n return filtered;\n };\n\n // The whole piece of code below is a way to accommodate the limitations of\n // the current `resolvePackagePath` implementation, which cannot be provided\n // some custom locations where it should find the assets of some given packages.\n //\n // Since the packages for dynamic plugins are not located in the main backstage\n // monorepo structure, and since dynamic plugins could also be repackaged\n // (typically renamed with a `-dynamic` suffix), for now we have to customize\n // module file name resolution here to support these use-cases.\n //\n // This might not be necessary anymore according to future enhancements to the\n // `resolvePackagePath` feature.\n const oldResolveFileName = this.module._resolveFilename;\n this.module._resolveFilename = (\n request: string,\n mod: NodeModule,\n _: boolean,\n options: any,\n ): any => {\n let errorToThrow: any;\n try {\n return oldResolveFileName(request, mod, _, options);\n } catch (e) {\n errorToThrow = e;\n this.options.logger.debug(\n `Could not resolve '${request}' inside the Core backstage backend application`,\n e instanceof Error ? e : undefined,\n );\n }\n\n // Are we trying to resolve a `package.json` from an originating module of the core backstage application\n // (this is mostly done by calling `@backstage/backend-plugin-api/resolvePackagePath`).\n const resolvingPackageJsonFromBackstageApplication =\n request?.endsWith('/package.json') &&\n mod?.path &&\n !dynamicPluginsPaths.some(p => mod.path.startsWith(p));\n\n // If not, we don't need the dedicated specific case below.\n if (!resolvingPackageJsonFromBackstageApplication) {\n throw errorToThrow;\n }\n\n this.options.logger.info(\n `Resolving '${request}' in the dynamic backend plugins`,\n );\n const searchedPackageName = request.replace(/\\/package.json$/, '');\n\n // First search for a dynamic plugin package matching the expected package name,\n // taking in account accepted dynamic plugin package name suffixes\n // (suffix accepted by default is '-dynamic').\n const searchedPackageNamesWithSuffixes = (\n this.options.dynamicPluginPackageNameSuffixes ?? ['-dynamic']\n ).map(s => `${searchedPackageName}${s}`);\n for (const [realPath, pkg] of scannedPluginManifests.entries()) {\n if (\n [searchedPackageName, ...searchedPackageNamesWithSuffixes].includes(\n pkg.name,\n )\n ) {\n const resolvedPath = path.resolve(realPath, 'package.json');\n this.options.logger.info(`Resolved '${request}' at ${resolvedPath}`);\n return resolvedPath;\n }\n }\n\n // If a custom resolution is provided, use it.\n // This allows accommodating alternate ways to package dynamic plugins:\n // static plugin package wrapped inside a distinct dynamic plugin package for example.\n if (this.options.customResolveDynamicPackage) {\n const resolvedPath = this.options.customResolveDynamicPackage(\n this.options.logger,\n searchedPackageName,\n scannedPluginManifests,\n );\n if (resolvedPath) {\n return resolvedPath;\n }\n }\n throw errorToThrow;\n };\n }\n\n async load(packagePath: string): Promise<any> {\n return await this.module.prototype.require(packagePath);\n }\n}\n"],"names":["path"],"mappings":"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"}
1
+ {"version":3,"file":"CommonJSModuleLoader.cjs.js","sources":["../../src/loader/CommonJSModuleLoader.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ModuleLoader } from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport path from 'node:path';\nimport { ScannedPluginManifest } from '../scanner';\n\n/**\n * @public\n */\nexport type CommonJSModuleLoaderOptions = {\n logger: LoggerService;\n dynamicPluginPackageNameSuffixes?: String[];\n customResolveDynamicPackage?: (\n logger: LoggerService,\n searchedPackageName: string,\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ) => string | undefined;\n};\n\n/**\n * @public\n */\nexport class CommonJSModuleLoader implements ModuleLoader {\n private module: any;\n public readonly options: CommonJSModuleLoaderOptions;\n\n constructor(options: CommonJSModuleLoaderOptions) {\n this.options = options;\n this.module = require('node:module');\n }\n\n async bootstrap(\n backstageRoot: string,\n dynamicPluginsPaths: string[],\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ): Promise<void> {\n const backstageRootNodeModulesPath = `${backstageRoot}/node_modules`;\n const dynamicNodeModulesPaths = [\n ...dynamicPluginsPaths.map(p => path.resolve(p, 'node_modules')),\n ];\n const oldNodeModulePaths = this.module._nodeModulePaths;\n this.module._nodeModulePaths = (from: string): string[] => {\n const result: string[] = oldNodeModulePaths(from);\n if (!dynamicPluginsPaths.some(p => from.startsWith(p))) {\n return result;\n }\n const filtered = result.filter(nodeModulePath => {\n return (\n nodeModulePath === backstageRootNodeModulesPath ||\n dynamicNodeModulesPaths.some(p => nodeModulePath.startsWith(p))\n );\n });\n this.options.logger.debug(\n `Overriding node_modules search path for dynamic plugin ${from} to: ${filtered}`,\n );\n return filtered;\n };\n\n // The whole piece of code below is a way to accommodate the limitations of\n // the current `resolvePackagePath` implementation, which cannot be provided\n // some custom locations where it should find the assets of some given packages.\n //\n // Since the packages for dynamic plugins are not located in the main backstage\n // monorepo structure, and since dynamic plugins could also be repackaged\n // (typically renamed with a `-dynamic` suffix), for now we have to customize\n // module file name resolution here to support these use-cases.\n //\n // This might not be necessary anymore according to future enhancements to the\n // `resolvePackagePath` feature.\n const oldResolveFileName = this.module._resolveFilename;\n this.module._resolveFilename = (\n request: string,\n mod: NodeModule,\n _: boolean,\n options: any,\n ): any => {\n let errorToThrow: any;\n try {\n return oldResolveFileName(request, mod, _, options);\n } catch (e) {\n errorToThrow = e;\n this.options.logger.debug(\n `Could not resolve '${request}' inside the Core backstage backend application`,\n e instanceof Error ? e : undefined,\n );\n }\n\n // Is this a `resolvePackagePath` call from `@backstage/backend-plugin-api`?\n // This covers both the host application's copy and a bundled copy living\n // inside a dynamic plugin's own node_modules.\n // The regex matches mod.path against the various ways the package can be resolved on disk\n // (with optional subdirectory such as /src or /dist after the package name):\n // - .../node_modules/@backstage/backend-plugin-api[/...] (npm-installed)\n // - .../<plugin>/node_modules/@backstage/backend-plugin-api[/...] (bundled)\n // - .../packages/backend-plugin-api[/...] (symlinked workspace in monorepo)\n const resolvingPackageJsonViaResolvePackagePath =\n request?.endsWith('/package.json') &&\n /[/\\\\](?:@backstage|packages)[/\\\\]backend-plugin-api(?:[/\\\\]|$)/.test(\n mod?.path ?? '',\n );\n\n if (!resolvingPackageJsonViaResolvePackagePath) {\n throw errorToThrow;\n }\n\n this.options.logger.info(\n `Resolving '${request}' in the dynamic backend plugins`,\n );\n const searchedPackageName = request.replace(/\\/package.json$/, '');\n\n // First search for a dynamic plugin package matching the expected package name,\n // taking in account accepted dynamic plugin package name suffixes\n // (suffix accepted by default is '-dynamic').\n const searchedPackageNamesWithSuffixes = (\n this.options.dynamicPluginPackageNameSuffixes ?? ['-dynamic']\n ).map(s => `${searchedPackageName}${s}`);\n for (const [realPath, pkg] of scannedPluginManifests.entries()) {\n if (\n [searchedPackageName, ...searchedPackageNamesWithSuffixes].includes(\n pkg.name,\n )\n ) {\n const resolvedPath = path.resolve(realPath, 'package.json');\n this.options.logger.info(`Resolved '${request}' at ${resolvedPath}`);\n return resolvedPath;\n }\n }\n\n // If a custom resolution is provided, use it.\n // This allows accommodating alternate ways to package dynamic plugins:\n // static plugin package wrapped inside a distinct dynamic plugin package for example.\n if (this.options.customResolveDynamicPackage) {\n const resolvedPath = this.options.customResolveDynamicPackage(\n this.options.logger,\n searchedPackageName,\n scannedPluginManifests,\n );\n if (resolvedPath) {\n return resolvedPath;\n }\n }\n throw errorToThrow;\n };\n }\n\n async load(packagePath: string): Promise<any> {\n return await this.module.prototype.require(packagePath);\n }\n}\n"],"names":["path"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-dynamic-feature-service",
3
- "version": "0.8.0-next.1",
3
+ "version": "0.8.0",
4
4
  "description": "Backstage dynamic feature service",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -52,25 +52,25 @@
52
52
  "test": "backstage-cli package test"
53
53
  },
54
54
  "dependencies": {
55
- "@backstage/backend-defaults": "0.16.0-next.1",
56
- "@backstage/backend-openapi-utils": "0.6.7-next.0",
57
- "@backstage/backend-plugin-api": "1.7.1-next.0",
58
- "@backstage/cli-common": "0.2.0-next.1",
59
- "@backstage/cli-node": "0.2.19-next.1",
60
- "@backstage/config": "1.3.6",
61
- "@backstage/config-loader": "1.10.9-next.0",
62
- "@backstage/errors": "1.2.7",
63
- "@backstage/plugin-app-node": "0.1.43-next.0",
64
- "@backstage/plugin-auth-node": "0.6.14-next.1",
65
- "@backstage/plugin-catalog-backend": "3.5.0-next.1",
66
- "@backstage/plugin-events-backend": "0.6.0-next.1",
67
- "@backstage/plugin-events-node": "0.4.20-next.0",
68
- "@backstage/plugin-permission-common": "0.9.6",
69
- "@backstage/plugin-permission-node": "0.10.11-next.0",
70
- "@backstage/plugin-scaffolder-node": "0.13.0-next.1",
71
- "@backstage/plugin-search-backend-node": "1.4.2-next.0",
72
- "@backstage/plugin-search-common": "1.2.22",
73
- "@backstage/types": "1.2.2",
55
+ "@backstage/backend-defaults": "^0.16.0",
56
+ "@backstage/backend-openapi-utils": "^0.6.7",
57
+ "@backstage/backend-plugin-api": "^1.8.0",
58
+ "@backstage/cli-common": "^0.2.0",
59
+ "@backstage/cli-node": "^0.3.0",
60
+ "@backstage/config": "^1.3.6",
61
+ "@backstage/config-loader": "^1.10.9",
62
+ "@backstage/errors": "^1.2.7",
63
+ "@backstage/plugin-app-node": "^0.1.43",
64
+ "@backstage/plugin-auth-node": "^0.6.14",
65
+ "@backstage/plugin-catalog-backend": "^3.5.0",
66
+ "@backstage/plugin-events-backend": "^0.6.0",
67
+ "@backstage/plugin-events-node": "^0.4.20",
68
+ "@backstage/plugin-permission-common": "^0.9.7",
69
+ "@backstage/plugin-permission-node": "^0.10.11",
70
+ "@backstage/plugin-scaffolder-node": "^0.13.0",
71
+ "@backstage/plugin-search-backend-node": "^1.4.2",
72
+ "@backstage/plugin-search-common": "^1.2.22",
73
+ "@backstage/types": "^1.2.2",
74
74
  "@manypkg/get-packages": "^1.1.3",
75
75
  "@module-federation/sdk": "^0.21.6",
76
76
  "chokidar": "^3.5.3",
@@ -81,11 +81,11 @@
81
81
  "winston": "^3.2.1"
82
82
  },
83
83
  "devDependencies": {
84
- "@backstage/backend-app-api": "1.5.1-next.0",
85
- "@backstage/backend-test-utils": "1.11.1-next.1",
86
- "@backstage/cli": "0.36.0-next.1",
87
- "@backstage/plugin-app-backend": "0.5.12-next.0",
88
- "@backstage/repo-tools": "0.17.0-next.1",
84
+ "@backstage/backend-app-api": "^1.6.0",
85
+ "@backstage/backend-test-utils": "^1.11.1",
86
+ "@backstage/cli": "^0.36.0",
87
+ "@backstage/plugin-app-backend": "^0.5.12",
88
+ "@backstage/repo-tools": "^0.17.0",
89
89
  "@types/express": "^4.17.6",
90
90
  "triple-beam": "^1.4.1",
91
91
  "wait-for-expect": "^3.0.2"