@axis-backstage/plugin-readme-backend 0.1.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/README.md +114 -0
- package/dist/index.cjs.js +162 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Readme backend
|
|
2
|
+
|
|
3
|
+
Welcome to the readme backend plugin!
|
|
4
|
+
|
|
5
|
+
The plugin retrieves README.md files from the entity source location. The corresponding frontend plugin responsible for displaying this information is the [Readme plugin](https://github.com/AxisCommunications/backstage-plugins/blob/main/plugins/readme).
|
|
6
|
+
|
|
7
|
+
The plugin searches for a README file in the entity source location with any of the following file types:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
{ name: 'README', type: 'text/plain' },
|
|
11
|
+
{ name: 'README.md', type: 'text/markdown' },
|
|
12
|
+
{ name: 'README.rst', type: 'text/plain' },
|
|
13
|
+
{ name: 'README.txt', type: 'text/plain' },
|
|
14
|
+
{ name: 'README.MD', type: 'text/markdown' },
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The plugin can also handle symlinks.
|
|
18
|
+
|
|
19
|
+
## Setup
|
|
20
|
+
|
|
21
|
+
The following sections will help you get the Readme Backend plugin setup and running.
|
|
22
|
+
|
|
23
|
+
### Installation
|
|
24
|
+
|
|
25
|
+
Install the plugin by following the example below:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# From your Backstage root directory
|
|
29
|
+
yarn add --cwd packages/backend @axis-backstage/plugin-readme-backend
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Integrating
|
|
33
|
+
|
|
34
|
+
Here's how to get the backend plugin up and running:
|
|
35
|
+
|
|
36
|
+
1. Create a new file named `packages/backend/src/plugins/readme.ts`, and add the following to it:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { createRouter } from '@axis-backstage/plugin-readme-backend';
|
|
40
|
+
import { Router } from 'express';
|
|
41
|
+
import { PluginEnvironment } from '../types';
|
|
42
|
+
|
|
43
|
+
eexport default async function createPlugin(
|
|
44
|
+
env: PluginEnvironment,
|
|
45
|
+
): Promise<Router> {
|
|
46
|
+
return await createRouter({
|
|
47
|
+
logger: env.logger,
|
|
48
|
+
config: env.config,
|
|
49
|
+
reader: env.reader,
|
|
50
|
+
discovery: env.discovery,
|
|
51
|
+
tokenManager: env.tokenManager,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
2. Wire this into the overall backend router by adding the following to `packages/backend/src/index.ts`:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import readme from './plugins/readme';
|
|
60
|
+
...
|
|
61
|
+
|
|
62
|
+
async function main() {
|
|
63
|
+
// Add this line under the other lines that follow the useHotMemoize pattern
|
|
64
|
+
const readmeEnv = useHotMemoize(module, () => createEnv('readme'),
|
|
65
|
+
|
|
66
|
+
// Add this under the lines that add their routers to apiRouter
|
|
67
|
+
apiRouter.use('/readme', await readme(readmeEnv));
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. Now run `yarn start-backend` from the repo root.
|
|
72
|
+
|
|
73
|
+
4. In another terminal, run the command: `curl localhost:7007/api/readme/health`. The request should return `{"status":"ok"}`.
|
|
74
|
+
|
|
75
|
+
### New Backend System
|
|
76
|
+
|
|
77
|
+
The Readme backend plugin has support for the [new backend system](https://backstage.io/docs/backend-system/). Here is how you can set it up:
|
|
78
|
+
|
|
79
|
+
In your `packages/backend/src/index.ts` make the following changes:
|
|
80
|
+
|
|
81
|
+
```diff
|
|
82
|
+
+ import { readmePlugin } from '@axis-backstage/readme-backend';
|
|
83
|
+
|
|
84
|
+
const backend = createBackend();
|
|
85
|
+
+ backend.add(readmePlugin());
|
|
86
|
+
// ... other feature additions
|
|
87
|
+
|
|
88
|
+
backend.start();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Troubleshooting
|
|
92
|
+
|
|
93
|
+
If the backend fails to provide README content for an entity, it could be due to several reasons.
|
|
94
|
+
|
|
95
|
+
#### No Integration Found for Entity
|
|
96
|
+
|
|
97
|
+
This error message indicates that there is no current integration with the external provider where the README file is located, such as GitHub, GitLab, or Gerrit. When the integration is missing, the backend does not have permission to access the README content.
|
|
98
|
+
|
|
99
|
+
To resolve this issue, set up the integration for the external provider where the README file is located. You can find more information about Backstage integrations in the [Backstage upstream documentation](https://backstage.io/docs/integrations/).
|
|
100
|
+
|
|
101
|
+
#### Not a Valid Location for Source Target
|
|
102
|
+
|
|
103
|
+
This error means that the entity source location cannot be found or is not a valid URL. The `entity source location` is always the same directory as the catalog-info.yaml file.
|
|
104
|
+
|
|
105
|
+
To debug this error, ensure that the entity source location is valid for the current entity. You can find the entity source location in the entity's catalog-info.yaml file. See the example below:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
annotations:
|
|
109
|
+
backstage.io/source-location: url:https://github.com/AxisCommunications/backstage-plugins/blob/main/
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### README Not Found for Entity
|
|
113
|
+
|
|
114
|
+
This error indicates that no README, README.md, README.rst, README.txt, or README.MD file was found for that entity. To resolve this error, ensure that there is a README file located in the entity source location with one of the following formats: **md**, **rst**, or **txt**.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var backendCommon = require('@backstage/backend-common');
|
|
6
|
+
var express = require('express');
|
|
7
|
+
var Router = require('express-promise-router');
|
|
8
|
+
var integration = require('@backstage/integration');
|
|
9
|
+
var catalogModel = require('@backstage/catalog-model');
|
|
10
|
+
var catalogClient = require('@backstage/catalog-client');
|
|
11
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
12
|
+
|
|
13
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
|
+
|
|
15
|
+
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
16
|
+
var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
|
|
17
|
+
|
|
18
|
+
const DETECT_SYMLINKS_REGEX = "^(w+|.|/|-)+$";
|
|
19
|
+
const isSymLink = (content) => {
|
|
20
|
+
const lines = content.split("\n");
|
|
21
|
+
if (lines.length > 1)
|
|
22
|
+
return false;
|
|
23
|
+
const line = lines[0];
|
|
24
|
+
if (line.includes(" "))
|
|
25
|
+
return false;
|
|
26
|
+
const regex = RegExp(DETECT_SYMLINKS_REGEX);
|
|
27
|
+
return regex.test(content);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const DEFAULT_TTL = 1800 * 1e3;
|
|
31
|
+
const README_TYPES = [
|
|
32
|
+
{ name: "README", type: "text/plain" },
|
|
33
|
+
{ name: "README.md", type: "text/markdown" },
|
|
34
|
+
{ name: "README.rst", type: "text/plain" },
|
|
35
|
+
{ name: "README.txt", type: "text/plain" },
|
|
36
|
+
{ name: "README.MD", type: "text/markdown" }
|
|
37
|
+
];
|
|
38
|
+
async function createRouter(options) {
|
|
39
|
+
const { logger, config, reader, discovery, tokenManager } = options;
|
|
40
|
+
const catalogClient$1 = new catalogClient.CatalogClient({ discoveryApi: discovery });
|
|
41
|
+
const pluginCache = backendCommon.CacheManager.fromConfig(config).forPlugin("readme");
|
|
42
|
+
const cache = pluginCache.getClient({ defaultTtl: DEFAULT_TTL });
|
|
43
|
+
logger.info("Initializing readme backend");
|
|
44
|
+
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
45
|
+
const router = Router__default["default"]();
|
|
46
|
+
router.use(express__default["default"].json());
|
|
47
|
+
router.get("/health", (_, response) => {
|
|
48
|
+
response.json({ status: "ok" });
|
|
49
|
+
});
|
|
50
|
+
router.get("/:entityRef", async (request, response) => {
|
|
51
|
+
const { entityRef } = request.params;
|
|
52
|
+
const cacheDoc = await cache.get(entityRef);
|
|
53
|
+
if (cacheDoc) {
|
|
54
|
+
logger.info(`Loading README for ${entityRef} from cache.`);
|
|
55
|
+
response.type(cacheDoc.type);
|
|
56
|
+
response.send(cacheDoc.content);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const { token } = await tokenManager.getToken();
|
|
60
|
+
const entity = await catalogClient$1.getEntityByRef(entityRef, { token });
|
|
61
|
+
if (!entity) {
|
|
62
|
+
logger.info(`No integration found for ${entityRef}`);
|
|
63
|
+
response.status(500).json({ error: `No integration found for ${entityRef}` });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const source = catalogModel.getEntitySourceLocation(entity);
|
|
67
|
+
if (!source || source.type !== "url") {
|
|
68
|
+
logger.info(`Not valid location for ${source.target}`);
|
|
69
|
+
response.status(404).json({
|
|
70
|
+
error: `Not valid location for ${source.target}`
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const integration = integrations.byUrl(source.target);
|
|
75
|
+
if (!integration) {
|
|
76
|
+
logger.info(`No integration found for ${source.target}`);
|
|
77
|
+
response.status(500).json({ error: `No integration found for ${source.target}` });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
for (const fileType of README_TYPES) {
|
|
81
|
+
const url = integration.resolveUrl({
|
|
82
|
+
url: fileType.name,
|
|
83
|
+
base: source.target
|
|
84
|
+
});
|
|
85
|
+
let content;
|
|
86
|
+
try {
|
|
87
|
+
logger.info(`Fetch README ${entityRef}: ${url}, ${fileType.type} `);
|
|
88
|
+
response.type(fileType.type);
|
|
89
|
+
const urlResponse = await reader.readUrl(url);
|
|
90
|
+
content = (await urlResponse.buffer()).toString("utf-8");
|
|
91
|
+
if (isSymLink(content)) {
|
|
92
|
+
const symLinkUrl = integration.resolveUrl({
|
|
93
|
+
url: content,
|
|
94
|
+
base: source.target
|
|
95
|
+
});
|
|
96
|
+
const symLinkUrlResponse = await reader.readUrl(symLinkUrl);
|
|
97
|
+
content = (await symLinkUrlResponse.buffer()).toString("utf-8");
|
|
98
|
+
}
|
|
99
|
+
cache.set(entityRef, {
|
|
100
|
+
name: fileType.name,
|
|
101
|
+
type: fileType.type,
|
|
102
|
+
content
|
|
103
|
+
});
|
|
104
|
+
response.send(content);
|
|
105
|
+
return;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
if (error instanceof Error && error.name === "NotFoundError") {
|
|
108
|
+
continue;
|
|
109
|
+
} else {
|
|
110
|
+
response.status(500).json({
|
|
111
|
+
error: `Readme failure: ${error}`
|
|
112
|
+
});
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
logger.info(`Readme not found for ${entityRef}`);
|
|
118
|
+
response.status(404).json({
|
|
119
|
+
error: "Readme not found."
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
router.use(backendCommon.errorHandler());
|
|
123
|
+
return router;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const readmePlugin = backendPluginApi.createBackendPlugin({
|
|
127
|
+
pluginId: "readme",
|
|
128
|
+
register(env) {
|
|
129
|
+
env.registerInit({
|
|
130
|
+
deps: {
|
|
131
|
+
logger: backendPluginApi.coreServices.logger,
|
|
132
|
+
config: backendPluginApi.coreServices.rootConfig,
|
|
133
|
+
reader: backendPluginApi.coreServices.urlReader,
|
|
134
|
+
discovery: backendPluginApi.coreServices.discovery,
|
|
135
|
+
tokenManager: backendPluginApi.coreServices.tokenManager,
|
|
136
|
+
httpRouter: backendPluginApi.coreServices.httpRouter
|
|
137
|
+
},
|
|
138
|
+
async init({
|
|
139
|
+
logger,
|
|
140
|
+
config,
|
|
141
|
+
reader,
|
|
142
|
+
discovery,
|
|
143
|
+
tokenManager,
|
|
144
|
+
httpRouter
|
|
145
|
+
}) {
|
|
146
|
+
httpRouter.use(
|
|
147
|
+
await createRouter({
|
|
148
|
+
logger: backendCommon.loggerToWinstonLogger(logger),
|
|
149
|
+
config,
|
|
150
|
+
reader,
|
|
151
|
+
discovery,
|
|
152
|
+
tokenManager
|
|
153
|
+
})
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
exports.createRouter = createRouter;
|
|
161
|
+
exports["default"] = readmePlugin;
|
|
162
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/lib.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["const DETECT_SYMLINKS_REGEX = '^(w+|.|/|-)+$';\n\nexport const isSymLink = (content: string): boolean => {\n const lines = content.split('\\n');\n if (lines.length > 1) return false;\n const line = lines[0];\n if (line.includes(' ')) return false;\n\n const regex = RegExp(DETECT_SYMLINKS_REGEX);\n return regex.test(content);\n};\n","import {\n errorHandler,\n TokenManager,\n UrlReader,\n} from '@backstage/backend-common';\nimport { Config } from '@backstage/config';\nimport { CacheManager } from '@backstage/backend-common';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { getEntitySourceLocation } from '@backstage/catalog-model';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { DiscoveryApi } from '@backstage/plugin-permission-common';\nimport { isSymLink } from '../lib';\n\n/**\n * Constructs a readme router.\n * @public\n */\nexport interface RouterOptions {\n /**\n * Implementation of Winston logger\n */\n logger: Logger;\n\n /**\n * Backstage config object\n */\n config: Config;\n\n /**\n * Backstage url reader instance\n */\n reader: UrlReader;\n\n /**\n * Backstage discovery api instance\n */\n discovery: DiscoveryApi;\n\n /**\n * Backstage token manager instance\n */\n tokenManager: TokenManager;\n}\n\nconst DEFAULT_TTL = 1800 * 1000;\n\ninterface FileType {\n name: string;\n type: string;\n}\ninterface ReadmeFile extends FileType {\n content: string;\n}\n\nconst README_TYPES: FileType[] = [\n { name: 'README', type: 'text/plain' },\n { name: 'README.md', type: 'text/markdown' },\n { name: 'README.rst', type: 'text/plain' },\n { name: 'README.txt', type: 'text/plain' },\n { name: 'README.MD', type: 'text/markdown' },\n];\n\n/**\n * Constructs a readme router.\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, reader, discovery, tokenManager } = options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\n const pluginCache = CacheManager.fromConfig(config).forPlugin('readme');\n const cache = pluginCache.getClient({ defaultTtl: DEFAULT_TTL });\n\n logger.info('Initializing readme backend');\n const integrations = ScmIntegrations.fromConfig(config);\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n response.json({ status: 'ok' });\n });\n\n router.get('/:entityRef', async (request, response) => {\n const { entityRef } = request.params;\n const cacheDoc = (await cache.get(entityRef)) as ReadmeFile | undefined;\n\n if (cacheDoc) {\n logger.info(`Loading README for ${entityRef} from cache.`);\n response.type(cacheDoc.type);\n response.send(cacheDoc.content);\n return;\n }\n const { token } = await tokenManager.getToken();\n const entity = await catalogClient.getEntityByRef(entityRef, { token });\n if (!entity) {\n logger.info(`No integration found for ${entityRef}`);\n response\n .status(500)\n .json({ error: `No integration found for ${entityRef}` });\n return;\n }\n const source = getEntitySourceLocation(entity);\n\n if (!source || source.type !== 'url') {\n logger.info(`Not valid location for ${source.target}`);\n response.status(404).json({\n error: `Not valid location for ${source.target}`,\n });\n return;\n }\n const integration = integrations.byUrl(source.target);\n\n if (!integration) {\n logger.info(`No integration found for ${source.target}`);\n response\n .status(500)\n .json({ error: `No integration found for ${source.target}` });\n return;\n }\n\n for (const fileType of README_TYPES) {\n const url = integration.resolveUrl({\n url: fileType.name,\n base: source.target,\n });\n\n let content;\n\n try {\n logger.info(`Fetch README ${entityRef}: ${url}, ${fileType.type} `);\n response.type(fileType.type);\n\n const urlResponse = await reader.readUrl(url);\n content = (await urlResponse.buffer()).toString('utf-8');\n\n if (isSymLink(content)) {\n const symLinkUrl = integration.resolveUrl({\n url: content,\n base: source.target,\n });\n const symLinkUrlResponse = await reader.readUrl(symLinkUrl);\n content = (await symLinkUrlResponse.buffer()).toString('utf-8');\n }\n\n cache.set(entityRef, {\n name: fileType.name,\n type: fileType.type,\n content: content,\n });\n response.send(content);\n return;\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'NotFoundError') {\n // Try the next readme type\n continue;\n } else {\n response.status(500).json({\n error: `Readme failure: ${error}`,\n });\n break;\n }\n }\n }\n logger.info(`Readme not found for ${entityRef}`);\n response.status(404).json({\n error: 'Readme not found.',\n });\n });\n\n router.use(errorHandler());\n return router;\n}\n","import { loggerToWinstonLogger } from '@backstage/backend-common';\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\n\n/**\n * The Readme backend plugin.\n *\n * @public\n */\nexport const readmePlugin = createBackendPlugin({\n pluginId: 'readme',\n register(env) {\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n reader: coreServices.urlReader,\n discovery: coreServices.discovery,\n tokenManager: coreServices.tokenManager,\n httpRouter: coreServices.httpRouter,\n },\n async init({\n logger,\n config,\n reader,\n discovery,\n tokenManager,\n httpRouter,\n }) {\n httpRouter.use(\n await createRouter({\n logger: loggerToWinstonLogger(logger),\n config,\n reader,\n discovery,\n tokenManager,\n }),\n );\n },\n });\n },\n});\n"],"names":["catalogClient","CatalogClient","CacheManager","ScmIntegrations","Router","express","getEntitySourceLocation","errorHandler","createBackendPlugin","coreServices","loggerToWinstonLogger"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { UrlReader, TokenManager } from '@backstage/backend-common';
|
|
2
|
+
import { Config } from '@backstage/config';
|
|
3
|
+
import express from 'express';
|
|
4
|
+
import { Logger } from 'winston';
|
|
5
|
+
import { DiscoveryApi } from '@backstage/plugin-permission-common';
|
|
6
|
+
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Constructs a readme router.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
interface RouterOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Implementation of Winston logger
|
|
15
|
+
*/
|
|
16
|
+
logger: Logger;
|
|
17
|
+
/**
|
|
18
|
+
* Backstage config object
|
|
19
|
+
*/
|
|
20
|
+
config: Config;
|
|
21
|
+
/**
|
|
22
|
+
* Backstage url reader instance
|
|
23
|
+
*/
|
|
24
|
+
reader: UrlReader;
|
|
25
|
+
/**
|
|
26
|
+
* Backstage discovery api instance
|
|
27
|
+
*/
|
|
28
|
+
discovery: DiscoveryApi;
|
|
29
|
+
/**
|
|
30
|
+
* Backstage token manager instance
|
|
31
|
+
*/
|
|
32
|
+
tokenManager: TokenManager;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Constructs a readme router.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
declare function createRouter(options: RouterOptions): Promise<express.Router>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The Readme backend plugin.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
declare const readmePlugin: () => _backstage_backend_plugin_api.BackendFeature;
|
|
47
|
+
|
|
48
|
+
export { RouterOptions, createRouter, readmePlugin as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@axis-backstage/plugin-readme-backend",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "dist/index.cjs.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public",
|
|
9
|
+
"main": "dist/index.cjs.js",
|
|
10
|
+
"types": "dist/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"backstage": {
|
|
13
|
+
"role": "backend-plugin"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"start": "backstage-cli package start",
|
|
17
|
+
"build": "backstage-cli package build",
|
|
18
|
+
"lint": "backstage-cli package lint",
|
|
19
|
+
"test": "backstage-cli package test",
|
|
20
|
+
"clean": "backstage-cli package clean",
|
|
21
|
+
"prepack": "backstage-cli package prepack",
|
|
22
|
+
"postpack": "backstage-cli package postpack"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@backstage/backend-common": "^0.19.8",
|
|
26
|
+
"@backstage/backend-plugin-api": "^0.6.7",
|
|
27
|
+
"@backstage/catalog-client": "^1.4.6",
|
|
28
|
+
"@backstage/catalog-model": "^1.4.3",
|
|
29
|
+
"@backstage/config": "^1.1.1",
|
|
30
|
+
"@backstage/integration": "^1.7.2",
|
|
31
|
+
"@backstage/plugin-permission-common": "^0.7.10",
|
|
32
|
+
"@types/express": "*",
|
|
33
|
+
"express": "^4.17.1",
|
|
34
|
+
"express-promise-router": "^4.1.0",
|
|
35
|
+
"node-fetch": "^2.6.7",
|
|
36
|
+
"winston": "^3.2.1",
|
|
37
|
+
"yn": "^4.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@backstage/cli": "^0.23.0",
|
|
41
|
+
"@types/supertest": "^2.0.12",
|
|
42
|
+
"msw": "^1.0.0",
|
|
43
|
+
"supertest": "^6.2.4"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist"
|
|
47
|
+
]
|
|
48
|
+
}
|