@backstage/backend-dynamic-feature-service 0.7.9-next.0 → 0.7.9
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 +37 -0
- package/README.md +147 -24
- package/dist/schemas/frontend.cjs.js +1 -1
- package/dist/schemas/frontend.cjs.js.map +1 -1
- package/package.json +26 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# @backstage/backend-dynamic-feature-service
|
|
2
2
|
|
|
3
|
+
## 0.7.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7455dae: Use node prefix on native imports
|
|
8
|
+
- fdbd404: Updated `@module-federation/enhanced`, `@module-federation/runtime`, and `@module-federation/sdk` dependencies from `^0.9.0` to `^0.21.6`.
|
|
9
|
+
- 9b4c414: Updated README for backend-dynamic-feature-service
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
- @backstage/plugin-catalog-backend@3.4.0
|
|
12
|
+
- @backstage/backend-openapi-utils@0.6.6
|
|
13
|
+
- @backstage/backend-plugin-api@1.7.0
|
|
14
|
+
- @backstage/plugin-search-backend-node@1.4.1
|
|
15
|
+
- @backstage/backend-defaults@0.15.2
|
|
16
|
+
- @backstage/plugin-scaffolder-node@0.12.5
|
|
17
|
+
- @backstage/config-loader@1.10.8
|
|
18
|
+
- @backstage/plugin-events-backend@0.5.11
|
|
19
|
+
- @backstage/plugin-search-common@1.2.22
|
|
20
|
+
- @backstage/cli-common@0.1.18
|
|
21
|
+
- @backstage/cli-node@0.2.18
|
|
22
|
+
- @backstage/plugin-auth-node@0.6.13
|
|
23
|
+
- @backstage/plugin-app-node@0.1.42
|
|
24
|
+
- @backstage/plugin-permission-common@0.9.6
|
|
25
|
+
- @backstage/plugin-permission-node@0.10.10
|
|
26
|
+
- @backstage/plugin-events-node@0.4.19
|
|
27
|
+
|
|
28
|
+
## 0.7.9-next.1
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- 9b4c414: Updated README for backend-dynamic-feature-service
|
|
33
|
+
- Updated dependencies
|
|
34
|
+
- @backstage/cli-node@0.2.18-next.1
|
|
35
|
+
- @backstage/plugin-catalog-backend@3.4.0-next.1
|
|
36
|
+
- @backstage/backend-plugin-api@1.7.0-next.1
|
|
37
|
+
- @backstage/backend-defaults@0.15.2-next.1
|
|
38
|
+
- @backstage/plugin-scaffolder-node@0.12.5-next.1
|
|
39
|
+
|
|
3
40
|
## 0.7.9-next.0
|
|
4
41
|
|
|
5
42
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,47 +1,170 @@
|
|
|
1
1
|
# @backstage/backend-dynamic-feature-service
|
|
2
2
|
|
|
3
|
-
This package
|
|
3
|
+
This package provides experimental support for **dynamic backend features (plugins and modules)** in Backstage, allowing you to load plugins at runtime from a separate directory without including them in your main application's package.json.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Purpose
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This enables:
|
|
8
|
+
|
|
9
|
+
- **Plugin distribution**: Distributing plugins as standalone artifacts
|
|
10
|
+
- **Runtime flexibility**: Adding or updating plugins without rebuilding the entire application
|
|
11
|
+
- **Isolation**: Keeping plugin-specific dependencies separate from core application dependencies
|
|
12
|
+
- **Modular deployments**: Different environments can load different sets of plugins
|
|
13
|
+
|
|
14
|
+
**Important:** This service handles loading only - packaging and distribution are separate concerns with multiple approaches available (see Packaging Approaches section).
|
|
15
|
+
|
|
16
|
+
## Related Packages
|
|
17
|
+
|
|
18
|
+
- **`@backstage/frontend-dynamic-feature-loader`**: Companion package for loading dynamic frontend plugins. This is **only** supported in the New Frontend System. For more details, checkout the [README](../frontend-dynamic-feature-loader/README.md).
|
|
8
19
|
|
|
9
20
|
## How it works
|
|
10
21
|
|
|
11
|
-
|
|
22
|
+
### Core Architecture
|
|
23
|
+
|
|
24
|
+
The service consists of several key components:
|
|
25
|
+
|
|
26
|
+
1. **Plugin Scanner**: Scans a configured directory (`dynamicPlugins.rootDirectory`) for plugin packages
|
|
27
|
+
2. **Module Loader**: Loads plugin modules
|
|
28
|
+
3. **Feature Loader**: Integrates loaded plugins into the Backstage backend system
|
|
29
|
+
4. **Frontend Asset Server**: Serves frontend plugin assets (JavaScript, CSS, manifests) over HTTP for dynamic frontend plugins
|
|
30
|
+
|
|
31
|
+
### Loading Process
|
|
32
|
+
|
|
33
|
+
1. **Discovery**: The scanner identifies valid plugin packages in the dynamic plugins root directory
|
|
34
|
+
2. **Validation**: Each package is validated for required fields (`main`, `backstage.role`)
|
|
35
|
+
3. **Loading**: The module loader loads the plugin code
|
|
36
|
+
4. **Integration**: Plugins are registered as Backstage features and made available to the backend
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### Basic Setup
|
|
41
|
+
|
|
42
|
+
Add the service to your backend application:
|
|
12
43
|
|
|
13
|
-
|
|
44
|
+
1. **Install the package**:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
yarn add @backstage/backend-dynamic-feature-service
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
2. **Add one line to your backend**:
|
|
14
51
|
|
|
15
52
|
```ts
|
|
53
|
+
import { createBackend } from '@backstage/backend-defaults';
|
|
54
|
+
import { dynamicPluginsFeatureLoader } from '@backstage/backend-dynamic-feature-service';
|
|
55
|
+
|
|
16
56
|
const backend = createBackend();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
57
|
+
// Add this line to enable dynamic plugin support:
|
|
58
|
+
backend.add(dynamicPluginsFeatureLoader);
|
|
59
|
+
// ... your other plugins
|
|
60
|
+
backend.start();
|
|
20
61
|
```
|
|
21
62
|
|
|
22
|
-
###
|
|
63
|
+
### Configuration
|
|
64
|
+
|
|
65
|
+
Configure the dynamic plugins directory in your `app-config.yaml`:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
dynamicPlugins:
|
|
69
|
+
rootDirectory: dynamic-plugins-root
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Dynamic Plugin Packaging
|
|
73
|
+
|
|
74
|
+
### Package Structure Requirements
|
|
75
|
+
|
|
76
|
+
Before exploring specific packaging approaches, it's important to understand what constitutes a valid dynamic plugin package. Dynamic plugins follow the basic rules of Node.js packages, including:
|
|
77
|
+
|
|
78
|
+
**Package contents:**
|
|
23
79
|
|
|
24
|
-
|
|
80
|
+
- **package.json**: Package metadata and configuration
|
|
81
|
+
- **JavaScript files**: Either loadable by the Node.js CommonJS module loaders for backend plugins, or RSPack/webpack assets for frontend plugins
|
|
82
|
+
- **Configuration schema** (optional): JSON schema file (typically `dist/.config-schema.json`) for plugin configuration validation
|
|
83
|
+
- **Private dependencies** (optional): Embedded `node_modules` folder containing private dependencies for backend plugins
|
|
25
84
|
|
|
26
|
-
|
|
27
|
-
2. they would have a modified `package.json` file in which dependencies are updated to share `@backstage` dependencies with the main application.
|
|
28
|
-
3. they may embed some dependency whose code is then merged with the plugin code.
|
|
85
|
+
**Required package.json fields:**
|
|
29
86
|
|
|
30
|
-
|
|
87
|
+
- `name`: Package identifier
|
|
88
|
+
- `version`: Package version
|
|
89
|
+
- `main`: Entry point to the plugin's JavaScript code
|
|
90
|
+
- `backstage.role`: Must be set to `"backend-plugin"` or `"backend-plugin-module"`
|
|
31
91
|
|
|
32
|
-
###
|
|
92
|
+
### Packaging Approaches
|
|
33
93
|
|
|
34
|
-
|
|
94
|
+
Since this service only handles loading, you would choose a packaging approach based on your plugin's dependencies:
|
|
35
95
|
|
|
36
|
-
|
|
96
|
+
### 1. Simple npm pack
|
|
37
97
|
|
|
38
|
-
|
|
98
|
+
**When to use:** Plugin only uses dependencies that are already provided by the main Backstage application.
|
|
39
99
|
|
|
40
|
-
|
|
41
|
-
However some level of compatibility is provided with current backstage codebase, which still uses the legacy backend system, in order to allow testing and exploring dynamic backend plugin support on the widest range of contexts and installations.
|
|
42
|
-
However, this is temporary and will be removed once the next backend is ready to be used and has completely replaced the old one.
|
|
43
|
-
This is why the API related to the old backend is already marked as deprecated.
|
|
100
|
+
**How to apply:**
|
|
44
101
|
|
|
45
|
-
|
|
102
|
+
```bash
|
|
103
|
+
cd my-backstage-plugin
|
|
104
|
+
yarn pack
|
|
105
|
+
# Results in: package.tgz
|
|
46
106
|
|
|
47
|
-
|
|
107
|
+
# Extract to dynamic plugins directory
|
|
108
|
+
mkdir -p /path/to/dynamic-plugins-root/my-backstage-plugin
|
|
109
|
+
tar -xzf package.tgz -C /path/to/dynamic-plugins-root/my-backstage-plugin --strip-components=1
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Why this works:** The plugin can resolve all its dependencies from the main application's `node_modules`.
|
|
113
|
+
|
|
114
|
+
**Reality:** Most plugins have private dependencies not available in the main application, so this approach has limited applicability.
|
|
115
|
+
|
|
116
|
+
### 2. Manual packaging with dependency installation
|
|
117
|
+
|
|
118
|
+
**When to use:** Plugin has private dependencies not available in the main Backstage application.
|
|
119
|
+
|
|
120
|
+
**How to apply:**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Package the plugin
|
|
124
|
+
cd my-backstage-plugin
|
|
125
|
+
yarn pack
|
|
126
|
+
|
|
127
|
+
# Extract and install dependencies
|
|
128
|
+
mkdir -p /path/to/dynamic-plugins-root/my-backstage-plugin
|
|
129
|
+
tar -xzf package.tgz -C /path/to/dynamic-plugin-root/my-backstage-plugin --strip-components=1
|
|
130
|
+
cp yarn.lock /path/to/dynamic-plugin-root/my-backstage-plugin
|
|
131
|
+
cd /path/to/dynamic-plugins-root/my-backstage-plugin
|
|
132
|
+
yarn install # Installs all the plugin's dependencies
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Why this works:** Each plugin gets its own `node_modules` directory with all its dependencies.
|
|
136
|
+
|
|
137
|
+
**Example scenario:** Plugin needs `axios@1.4.0` which isn't available in the main application.
|
|
138
|
+
|
|
139
|
+
### 3. Custom packaging CLI tool
|
|
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.
|
|
142
|
+
|
|
143
|
+
**What a packaging CLI needs to do:**
|
|
144
|
+
|
|
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
|
|
152
|
+
|
|
153
|
+
**Benefits:**
|
|
154
|
+
|
|
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
|
|
160
|
+
|
|
161
|
+
**Example implementation:** The [`@red-hat-developer-hub/cli`](https://github.com/redhat-developer/rhdh-cli) tool implements this approach:
|
|
162
|
+
|
|
163
|
+
```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
|
|
167
|
+
|
|
168
|
+
# Deploy the generated package
|
|
169
|
+
cp -r dist-dynamic /path/to/dynamic-plugins-root/my-backstage-plugin
|
|
170
|
+
```
|
|
@@ -6,7 +6,7 @@ var pluginAppNode = require('@backstage/plugin-app-node');
|
|
|
6
6
|
|
|
7
7
|
const dynamicPluginsFrontendSchemas = backendPluginApi.createBackendModule({
|
|
8
8
|
pluginId: "app",
|
|
9
|
-
moduleId: "core
|
|
9
|
+
moduleId: "core-dynamicplugins-frontendSchemas",
|
|
10
10
|
register(reg) {
|
|
11
11
|
reg.registerInit({
|
|
12
12
|
deps: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend.cjs.js","sources":["../../src/schemas/frontend.ts"],"sourcesContent":["/*\n * Copyright 2024 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 */\n\nimport {\n coreServices,\n createBackendModule,\n resolvePackagePath,\n} from '@backstage/backend-plugin-api';\nimport { dynamicPluginsSchemasServiceRef } from './schemas';\nimport {\n configSchemaExtensionPoint,\n loadCompiledConfigSchema,\n} from '@backstage/plugin-app-node';\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsFrontendSchemas = createBackendModule({\n pluginId: 'app',\n moduleId: 'core
|
|
1
|
+
{"version":3,"file":"frontend.cjs.js","sources":["../../src/schemas/frontend.ts"],"sourcesContent":["/*\n * Copyright 2024 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 */\n\nimport {\n coreServices,\n createBackendModule,\n resolvePackagePath,\n} from '@backstage/backend-plugin-api';\nimport { dynamicPluginsSchemasServiceRef } from './schemas';\nimport {\n configSchemaExtensionPoint,\n loadCompiledConfigSchema,\n} from '@backstage/plugin-app-node';\n\n/**\n * @public\n * @deprecated Use {@link dynamicPluginsFeatureLoader} instead, which gathers all services and features required for dynamic plugins.\n */\nexport const dynamicPluginsFrontendSchemas = createBackendModule({\n pluginId: 'app',\n moduleId: 'core-dynamicplugins-frontendSchemas',\n register(reg) {\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n schemas: dynamicPluginsSchemasServiceRef,\n configSchemaExtension: configSchemaExtensionPoint,\n },\n async init({ config, schemas, configSchemaExtension }) {\n const appPackageName =\n config.getOptionalString('app.packageName') ?? 'app';\n const appDistDir = resolvePackagePath(appPackageName, 'dist');\n const compiledConfigSchema = await loadCompiledConfigSchema(appDistDir);\n // TODO(davidfestal): Add dynamic pliugin config schemas even if the compiled schemas are empty.\n if (compiledConfigSchema) {\n configSchemaExtension.setConfigSchema(\n (await schemas.addDynamicPluginsSchemas(compiledConfigSchema))\n .schema,\n );\n }\n },\n });\n },\n});\n"],"names":["createBackendModule","coreServices","dynamicPluginsSchemasServiceRef","configSchemaExtensionPoint","resolvePackagePath","loadCompiledConfigSchema"],"mappings":";;;;;;AA+BO,MAAM,gCAAgCA,oCAAA,CAAoB;AAAA,EAC/D,QAAA,EAAU,KAAA;AAAA,EACV,QAAA,EAAU,qCAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,QAAQC,6BAAA,CAAa,UAAA;AAAA,QACrB,OAAA,EAASC,uCAAA;AAAA,QACT,qBAAA,EAAuBC;AAAA,OACzB;AAAA,MACA,MAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,OAAA,EAAS,uBAAsB,EAAG;AACrD,QAAA,MAAM,cAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,iBAAiB,CAAA,IAAK,KAAA;AACjD,QAAA,MAAM,UAAA,GAAaC,mCAAA,CAAmB,cAAA,EAAgB,MAAM,CAAA;AAC5D,QAAA,MAAM,oBAAA,GAAuB,MAAMC,sCAAA,CAAyB,UAAU,CAAA;AAEtE,QAAA,IAAI,oBAAA,EAAsB;AACxB,UAAA,qBAAA,CAAsB,eAAA;AAAA,YAAA,CACnB,MAAM,OAAA,CAAQ,wBAAA,CAAyB,oBAAoB,CAAA,EACzD;AAAA,WACL;AAAA,QACF;AAAA,MACF;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-dynamic-feature-service",
|
|
3
|
-
"version": "0.7.9
|
|
3
|
+
"version": "0.7.9",
|
|
4
4
|
"description": "Backstage dynamic feature service",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -52,27 +52,27 @@
|
|
|
52
52
|
"test": "backstage-cli package test"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@backstage/backend-defaults": "0.15.
|
|
56
|
-
"@backstage/backend-openapi-utils": "0.6.6
|
|
57
|
-
"@backstage/backend-plugin-api": "1.7.0
|
|
58
|
-
"@backstage/cli-common": "0.1.18
|
|
59
|
-
"@backstage/cli-node": "0.2.
|
|
60
|
-
"@backstage/config": "1.3.6",
|
|
61
|
-
"@backstage/config-loader": "1.10.8
|
|
62
|
-
"@backstage/errors": "1.2.7",
|
|
63
|
-
"@backstage/plugin-app-node": "0.1.42
|
|
64
|
-
"@backstage/plugin-auth-node": "0.6.
|
|
65
|
-
"@backstage/plugin-catalog-backend": "3.4.0
|
|
66
|
-
"@backstage/plugin-events-backend": "0.5.11
|
|
67
|
-
"@backstage/plugin-events-node": "0.4.19
|
|
68
|
-
"@backstage/plugin-permission-common": "0.9.
|
|
69
|
-
"@backstage/plugin-permission-node": "0.10.
|
|
70
|
-
"@backstage/plugin-scaffolder-node": "0.12.
|
|
71
|
-
"@backstage/plugin-search-backend-node": "1.4.1
|
|
72
|
-
"@backstage/plugin-search-common": "1.2.22
|
|
73
|
-
"@backstage/types": "1.2.2",
|
|
55
|
+
"@backstage/backend-defaults": "^0.15.2",
|
|
56
|
+
"@backstage/backend-openapi-utils": "^0.6.6",
|
|
57
|
+
"@backstage/backend-plugin-api": "^1.7.0",
|
|
58
|
+
"@backstage/cli-common": "^0.1.18",
|
|
59
|
+
"@backstage/cli-node": "^0.2.18",
|
|
60
|
+
"@backstage/config": "^1.3.6",
|
|
61
|
+
"@backstage/config-loader": "^1.10.8",
|
|
62
|
+
"@backstage/errors": "^1.2.7",
|
|
63
|
+
"@backstage/plugin-app-node": "^0.1.42",
|
|
64
|
+
"@backstage/plugin-auth-node": "^0.6.13",
|
|
65
|
+
"@backstage/plugin-catalog-backend": "^3.4.0",
|
|
66
|
+
"@backstage/plugin-events-backend": "^0.5.11",
|
|
67
|
+
"@backstage/plugin-events-node": "^0.4.19",
|
|
68
|
+
"@backstage/plugin-permission-common": "^0.9.6",
|
|
69
|
+
"@backstage/plugin-permission-node": "^0.10.10",
|
|
70
|
+
"@backstage/plugin-scaffolder-node": "^0.12.5",
|
|
71
|
+
"@backstage/plugin-search-backend-node": "^1.4.1",
|
|
72
|
+
"@backstage/plugin-search-common": "^1.2.22",
|
|
73
|
+
"@backstage/types": "^1.2.2",
|
|
74
74
|
"@manypkg/get-packages": "^1.1.3",
|
|
75
|
-
"@module-federation/sdk": "^0.
|
|
75
|
+
"@module-federation/sdk": "^0.21.6",
|
|
76
76
|
"chokidar": "^3.5.3",
|
|
77
77
|
"express": "^4.22.0",
|
|
78
78
|
"express-promise-router": "^4.1.0",
|
|
@@ -81,11 +81,11 @@
|
|
|
81
81
|
"winston": "^3.2.1"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@backstage/backend-app-api": "1.5.0
|
|
85
|
-
"@backstage/backend-test-utils": "1.
|
|
86
|
-
"@backstage/cli": "0.35.
|
|
87
|
-
"@backstage/plugin-app-backend": "0.5.11
|
|
88
|
-
"@backstage/repo-tools": "0.16.
|
|
84
|
+
"@backstage/backend-app-api": "^1.5.0",
|
|
85
|
+
"@backstage/backend-test-utils": "^1.11.0",
|
|
86
|
+
"@backstage/cli": "^0.35.4",
|
|
87
|
+
"@backstage/plugin-app-backend": "^0.5.11",
|
|
88
|
+
"@backstage/repo-tools": "^0.16.4",
|
|
89
89
|
"@types/express": "^4.17.6",
|
|
90
90
|
"triple-beam": "^1.4.1",
|
|
91
91
|
"wait-for-expect": "^3.0.2"
|