@backstage-community/plugin-tech-radar-backend 1.0.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 +12 -0
- package/README.md +91 -0
- package/config.d.ts +25 -0
- package/dist/index.cjs.js +12 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/plugin.cjs.js +34 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/service/router.cjs.js +36 -0
- package/dist/service/router.cjs.js.map +1 -0
- package/dist/utils/index.cjs.js +45 -0
- package/dist/utils/index.cjs.js.map +1 -0
- package/package.json +61 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @backstage-community/plugin-tech-radar-backend
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- e3ab8e9: Initial release of the `tech-radar-backend` plugin.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [e3ab8e9]
|
|
12
|
+
- @backstage-community/plugin-tech-radar-common@1.0.0
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# tech-radar
|
|
2
|
+
|
|
3
|
+
Welcome to the tech-radar backend plugin!
|
|
4
|
+
|
|
5
|
+
This plugin is an optional accompaniment the the [tech-radar plugin](../tech-radar/README.md). It uses the [URL Reader service](https://backstage.io/docs/backend-system/core-services/url-reader/) to retrieve tech radar response data from a URL, which must be provided in the config. This means a definition file can be stored in GitHub, versioned, and potentially consumed by other systems along with Backstage (and as long as Github is present in the integrations section of `app-config.yaml`, urlReader will handle authentication). The file must contain [TechRadarLoaderResponse](../tech-radar-common/src/schema.ts) data in JSON format - can use [this sample](../tech-radar-common/src/sampleTechRadarResponse.json) as a reference.
|
|
6
|
+
|
|
7
|
+
If using this plugin, make a modification to `app-config.yaml` to describe the source JSON:
|
|
8
|
+
|
|
9
|
+
```yaml title="app-config.yaml"
|
|
10
|
+
techRadar:
|
|
11
|
+
url: https://github.com/backstage/community-plugins/blob/main/workspaces/tech-radar/plugins/tech-radar-common/src/sampleTechRadarResponse.json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
If you are storing the JSON file in a private repository, you will need to configure the proper integration in the `app-config.yaml` file. For more information on how to configure integrations, see the [Backstage documentation](https://backstage.io/docs/integrations/).
|
|
15
|
+
|
|
16
|
+
## Integrating into a backstage instance
|
|
17
|
+
|
|
18
|
+
This plugin needs to be added to an existing backstage instance.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# From your Backstage root directory
|
|
22
|
+
yarn --cwd packages/backend add @backstage-community/plugin-tech-radar-backend
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## New Backend System
|
|
26
|
+
|
|
27
|
+
The Tech Radar backend plugin has support for the [new backend system](https://backstage.io/docs/backend-system/), here's how you can set that up:
|
|
28
|
+
|
|
29
|
+
In your `packages/backend/src/index.ts` make the following changes:
|
|
30
|
+
|
|
31
|
+
```diff
|
|
32
|
+
import { createBackend } from '@backstage/backend-defaults';
|
|
33
|
+
const backend = createBackend();
|
|
34
|
+
// ... other feature additions
|
|
35
|
+
+ backend.add(import('@backstage-community/plugin-tech-radar-backend'));
|
|
36
|
+
backend.start();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Legacy Backend System
|
|
40
|
+
|
|
41
|
+
If still using the legacy backend, do the following:
|
|
42
|
+
|
|
43
|
+
Creating a `src/plugins/techRadar.ts` file and adding a reference to it to `src/index.ts` in the backend package.
|
|
44
|
+
|
|
45
|
+
### techRadar.ts
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createRouter } from '@backstage-community/plugin-tech-radar-backend';
|
|
49
|
+
import { Router } from 'express';
|
|
50
|
+
import { PluginEnvironment } from '../types';
|
|
51
|
+
|
|
52
|
+
export default async function createPlugin(
|
|
53
|
+
env: PluginEnvironment,
|
|
54
|
+
): Promise<Router> {
|
|
55
|
+
return await createRouter({
|
|
56
|
+
logger: env.logger,
|
|
57
|
+
config: env.config,
|
|
58
|
+
reader: env.reader,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### src/index.ts
|
|
64
|
+
|
|
65
|
+
```diff
|
|
66
|
+
@@ -50,6 +50,7 @@ import scaffolder from './plugins/scaffolder';
|
|
67
|
+
import proxy from './plugins/proxy';
|
|
68
|
+
import search from './plugins/search';
|
|
69
|
+
import techdocs from './plugins/techdocs';
|
|
70
|
+
+import techRadar from './plugins/techRadar';
|
|
71
|
+
import techInsights from './plugins/techInsights';
|
|
72
|
+
import todo from './plugins/todo';
|
|
73
|
+
import graphql from './plugins/graphql';
|
|
74
|
+
@@ -133,6 +134,7 @@ async function main() {
|
|
75
|
+
createEnv('tech-insights'),
|
|
76
|
+
);
|
|
77
|
+
const permissionEnv = useHotMemoize(module, () => createEnv('permission'));
|
|
78
|
+
+ const techRadarEnv = useHotMemoize(module, () => createEnv('techRadar'));
|
|
79
|
+
|
|
80
|
+
const apiRouter = Router();
|
|
81
|
+
apiRouter.use('/catalog', await catalog(catalogEnv));
|
|
82
|
+
@@ -152,6 +154,7 @@ async function main() {
|
|
83
|
+
apiRouter.use('/badges', await badges(badgesEnv));
|
|
84
|
+
apiRouter.use('/jenkins', await jenkins(jenkinsEnv));
|
|
85
|
+
apiRouter.use('/permission', await permission(permissionEnv));
|
|
86
|
+
+ apiRouter.use('/tech-radar', await techRadar(techRadarEnv));
|
|
87
|
+
apiRouter.use(notFoundHandler());
|
|
88
|
+
|
|
89
|
+
const service = createServiceBuilder(module)
|
|
90
|
+
|
|
91
|
+
```
|
package/config.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 The Backstage Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export interface Config {
|
|
18
|
+
/** Configuration for the Tech Radar backend plugin */
|
|
19
|
+
techRadar: {
|
|
20
|
+
/**
|
|
21
|
+
* The url from which the tech radar graph data is fetched.
|
|
22
|
+
*/
|
|
23
|
+
url: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var router = require('./service/router.cjs.js');
|
|
6
|
+
var plugin = require('./plugin.cjs.js');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exports.createRouter = router.createRouter;
|
|
11
|
+
exports.default = plugin.techRadarPlugin;
|
|
12
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
+
import { LoggerService, RootConfigService, UrlReaderService } from '@backstage/backend-plugin-api';
|
|
3
|
+
import express from 'express';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* See UrlReader documentation: https://backstage.io/docs/backend-system/core-services/url-reader/
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
interface RouterOptions {
|
|
11
|
+
logger: LoggerService;
|
|
12
|
+
config: RootConfigService;
|
|
13
|
+
reader: UrlReaderService;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create the Tech Radar Router, used for reading the Tech Radar data from the provided URL.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*
|
|
20
|
+
* @param options - Router options
|
|
21
|
+
*/
|
|
22
|
+
declare function createRouter(options: RouterOptions): Promise<express.Router>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* techRadarPlugin backend plugin
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
declare const techRadarPlugin: _backstage_backend_plugin_api.BackendFeature;
|
|
30
|
+
|
|
31
|
+
export { type RouterOptions, createRouter, techRadarPlugin as default };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
4
|
+
var router = require('./service/router.cjs.js');
|
|
5
|
+
|
|
6
|
+
const techRadarPlugin = backendPluginApi.createBackendPlugin({
|
|
7
|
+
pluginId: "tech-radar",
|
|
8
|
+
register(env) {
|
|
9
|
+
env.registerInit({
|
|
10
|
+
deps: {
|
|
11
|
+
httpRouter: backendPluginApi.coreServices.httpRouter,
|
|
12
|
+
logger: backendPluginApi.coreServices.logger,
|
|
13
|
+
config: backendPluginApi.coreServices.rootConfig,
|
|
14
|
+
reader: backendPluginApi.coreServices.urlReader
|
|
15
|
+
},
|
|
16
|
+
async init({ httpRouter, logger, config, reader }) {
|
|
17
|
+
httpRouter.use(
|
|
18
|
+
await router.createRouter({
|
|
19
|
+
logger,
|
|
20
|
+
config,
|
|
21
|
+
reader
|
|
22
|
+
})
|
|
23
|
+
);
|
|
24
|
+
httpRouter.addAuthPolicy({
|
|
25
|
+
path: "/health",
|
|
26
|
+
allow: "unauthenticated"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
exports.techRadarPlugin = techRadarPlugin;
|
|
34
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.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 */\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\n\n/**\n * techRadarPlugin backend plugin\n *\n * @public\n */\nexport const techRadarPlugin = createBackendPlugin({\n pluginId: 'tech-radar',\n register(env) {\n env.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n reader: coreServices.urlReader,\n },\n async init({ httpRouter, logger, config, reader }) {\n httpRouter.use(\n await createRouter({\n logger,\n config,\n reader,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","createRouter"],"mappings":";;;;;AA0BO,MAAM,kBAAkBA,oCAAoB,CAAA;AAAA,EACjD,QAAU,EAAA,YAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,YAAYC,6BAAa,CAAA,UAAA;AAAA,QACzB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,SAAA;AAAA,OACvB;AAAA,MACA,MAAM,IAAK,CAAA,EAAE,YAAY,MAAQ,EAAA,MAAA,EAAQ,QAAU,EAAA;AACjD,QAAW,UAAA,CAAA,GAAA;AAAA,UACT,MAAMC,mBAAa,CAAA;AAAA,YACjB,MAAA;AAAA,YACA,MAAA;AAAA,YACA,MAAA;AAAA,WACD,CAAA;AAAA,SACH,CAAA;AACA,QAAA,UAAA,CAAW,aAAc,CAAA;AAAA,UACvB,IAAM,EAAA,SAAA;AAAA,UACN,KAAO,EAAA,iBAAA;AAAA,SACR,CAAA,CAAA;AAAA,OACH;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACF,CAAC;;;;"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var rootHttpRouter = require('@backstage/backend-defaults/rootHttpRouter');
|
|
4
|
+
var express = require('express');
|
|
5
|
+
var Router = require('express-promise-router');
|
|
6
|
+
var index = require('../utils/index.cjs.js');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
11
|
+
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
12
|
+
|
|
13
|
+
async function createRouter(options) {
|
|
14
|
+
const { logger, config, reader } = options;
|
|
15
|
+
const router = Router__default.default();
|
|
16
|
+
router.use(express__default.default.json());
|
|
17
|
+
const url = config.getString("techRadar.url");
|
|
18
|
+
router.get("/health", (_, response) => {
|
|
19
|
+
logger.info("PONG!");
|
|
20
|
+
response.json({ status: "ok" });
|
|
21
|
+
});
|
|
22
|
+
router.get("/data", async (_, response) => {
|
|
23
|
+
const dataFromUrl = await index.readTechRadarResponseFromURL(url, reader, logger);
|
|
24
|
+
if (!dataFromUrl) {
|
|
25
|
+
response.status(502).json({ message: "Unable to retrieve data from provided URL" });
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
response.json(dataFromUrl);
|
|
29
|
+
});
|
|
30
|
+
const middleware = rootHttpRouter.MiddlewareFactory.create({ logger, config });
|
|
31
|
+
router.use(middleware.error());
|
|
32
|
+
return router;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.createRouter = createRouter;
|
|
36
|
+
//# sourceMappingURL=router.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.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 */\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport {\n LoggerService,\n RootConfigService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { readTechRadarResponseFromURL } from '../utils';\n\n/**\n * See UrlReader documentation: https://backstage.io/docs/backend-system/core-services/url-reader/\n *\n * @public\n */\nexport interface RouterOptions {\n logger: LoggerService;\n config: RootConfigService;\n reader: UrlReaderService;\n}\n\n/**\n * Create the Tech Radar Router, used for reading the Tech Radar data from the provided URL.\n *\n * @public\n *\n * @param options - Router options\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, reader } = options;\n\n const router = Router();\n router.use(express.json());\n const url = config.getString('techRadar.url');\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\n response.json({ status: 'ok' });\n });\n\n router.get('/data', async (_, response) => {\n const dataFromUrl = await readTechRadarResponseFromURL(url, reader, logger);\n if (!dataFromUrl) {\n response\n .status(502)\n .json({ message: 'Unable to retrieve data from provided URL' });\n return;\n }\n response.json(dataFromUrl);\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n}\n"],"names":["Router","express","readTechRadarResponseFromURL","MiddlewareFactory"],"mappings":";;;;;;;;;;;;AA2CA,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAQ,EAAA,MAAA,EAAW,GAAA,OAAA,CAAA;AAEnC,EAAA,MAAM,SAASA,uBAAO,EAAA,CAAA;AACtB,EAAO,MAAA,CAAA,GAAA,CAAIC,wBAAQ,CAAA,IAAA,EAAM,CAAA,CAAA;AACzB,EAAM,MAAA,GAAA,GAAM,MAAO,CAAA,SAAA,CAAU,eAAe,CAAA,CAAA;AAE5C,EAAA,MAAA,CAAO,GAAI,CAAA,SAAA,EAAW,CAAC,CAAA,EAAG,QAAa,KAAA;AACrC,IAAA,MAAA,CAAO,KAAK,OAAO,CAAA,CAAA;AACnB,IAAA,QAAA,CAAS,IAAK,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAM,CAAA,CAAA;AAAA,GAC/B,CAAA,CAAA;AAED,EAAA,MAAA,CAAO,GAAI,CAAA,OAAA,EAAS,OAAO,CAAA,EAAG,QAAa,KAAA;AACzC,IAAA,MAAM,WAAc,GAAA,MAAMC,kCAA6B,CAAA,GAAA,EAAK,QAAQ,MAAM,CAAA,CAAA;AAC1E,IAAA,IAAI,CAAC,WAAa,EAAA;AAChB,MAAA,QAAA,CACG,OAAO,GAAG,CAAA,CACV,KAAK,EAAE,OAAA,EAAS,6CAA6C,CAAA,CAAA;AAChE,MAAA,OAAA;AAAA,KACF;AACA,IAAA,QAAA,CAAS,KAAK,WAAW,CAAA,CAAA;AAAA,GAC1B,CAAA,CAAA;AAED,EAAA,MAAM,aAAaC,gCAAkB,CAAA,MAAA,CAAO,EAAE,MAAA,EAAQ,QAAQ,CAAA,CAAA;AAE9D,EAAO,MAAA,CAAA,GAAA,CAAI,UAAW,CAAA,KAAA,EAAO,CAAA,CAAA;AAC7B,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var pluginTechRadarCommon = require('@backstage-community/plugin-tech-radar-common');
|
|
4
|
+
|
|
5
|
+
async function readTechRadarResponseFromURL(url, urlReader, logger) {
|
|
6
|
+
let buffer = void 0;
|
|
7
|
+
let responseJson = void 0;
|
|
8
|
+
try {
|
|
9
|
+
const response = await urlReader.readUrl(url);
|
|
10
|
+
buffer = await response.buffer();
|
|
11
|
+
} catch (e) {
|
|
12
|
+
logger.warn(
|
|
13
|
+
`Failed to read file from ${url} with provided integrations (error is "${e.message}").`
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (buffer) {
|
|
17
|
+
try {
|
|
18
|
+
responseJson = JSON.parse(buffer.toString());
|
|
19
|
+
const validationResult = pluginTechRadarCommon.TechRadarLoaderResponseParser.safeParse(responseJson);
|
|
20
|
+
if (!validationResult.success) {
|
|
21
|
+
const errorMessage = `Could not parse data from remote URL '${url}' because validation failed: ${aggregateErrorMessages(
|
|
22
|
+
validationResult.error
|
|
23
|
+
)}. URL must serve JSON that is compatible with the TechRadarLoaderResponse schema.`;
|
|
24
|
+
logger.error(errorMessage);
|
|
25
|
+
}
|
|
26
|
+
return validationResult.data;
|
|
27
|
+
} catch (e) {
|
|
28
|
+
logger.error(
|
|
29
|
+
`Failed to parse JSON from remote resource ${url}, data will not be loaded!`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
function aggregateErrorMessages(zodError) {
|
|
36
|
+
return zodError.issues.reduce((acc, issue) => {
|
|
37
|
+
if (issue) {
|
|
38
|
+
return [acc, `${issue.message} parameter '${issue.path}'`].filter(Boolean).join(". ");
|
|
39
|
+
}
|
|
40
|
+
return acc;
|
|
41
|
+
}, "");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.readTechRadarResponseFromURL = readTechRadarResponseFromURL;
|
|
45
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../src/utils/index.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 */\nimport { LoggerService, UrlReaderService } from '@backstage/backend-plugin-api';\nimport {\n TechRadarLoaderResponse,\n TechRadarLoaderResponseParser,\n} from '@backstage-community/plugin-tech-radar-common';\nimport { ZodError } from 'zod';\n\n/**\n * Reads data from a URL via the urlReader, then parses it into a TechRadarLoaderResponse.\n * Returns undefined if the data could not be read or parsed safely.\n * @param url - the URL to read from.\n * @param urlReader - a URLReader for reading from integrations.\n * @param LoggerService - a logger for logging errors.\n *\n * @internal\n */\nexport async function readTechRadarResponseFromURL(\n url: string,\n urlReader: UrlReaderService,\n logger: LoggerService,\n): Promise<TechRadarLoaderResponse | undefined> {\n let buffer = undefined;\n let responseJson = undefined;\n try {\n const response = await urlReader.readUrl(url);\n buffer = await response.buffer();\n } catch (e) {\n // Log a warning.\n logger.warn(\n `Failed to read file from ${url} with provided integrations (error is \"${e.message}\").`,\n );\n }\n\n if (buffer) {\n try {\n responseJson = JSON.parse(buffer.toString());\n const validationResult =\n TechRadarLoaderResponseParser.safeParse(responseJson);\n if (!validationResult.success) {\n const errorMessage = `Could not parse data from remote URL '${url}' because validation failed: ${aggregateErrorMessages(\n validationResult.error,\n )}. URL must serve JSON that is compatible with the TechRadarLoaderResponse schema.`;\n logger.error(errorMessage);\n }\n return validationResult.data;\n } catch (e) {\n logger.error(\n `Failed to parse JSON from remote resource ${url}, data will not be loaded!`,\n );\n }\n }\n\n return undefined;\n}\n\n/**\n * Aggregates error messages from a ZodError.\n * @internal\n * @param zodError\n */\nfunction aggregateErrorMessages(zodError: ZodError): string {\n return zodError.issues.reduce((acc, issue) => {\n if (issue) {\n return [acc, `${issue.message} parameter '${issue.path}'`]\n .filter(Boolean)\n .join('. ');\n }\n return acc;\n }, '');\n}\n"],"names":["TechRadarLoaderResponseParser"],"mappings":";;;;AA+BsB,eAAA,4BAAA,CACpB,GACA,EAAA,SAAA,EACA,MAC8C,EAAA;AAC9C,EAAA,IAAI,MAAS,GAAA,KAAA,CAAA,CAAA;AACb,EAAA,IAAI,YAAe,GAAA,KAAA,CAAA,CAAA;AACnB,EAAI,IAAA;AACF,IAAA,MAAM,QAAW,GAAA,MAAM,SAAU,CAAA,OAAA,CAAQ,GAAG,CAAA,CAAA;AAC5C,IAAS,MAAA,GAAA,MAAM,SAAS,MAAO,EAAA,CAAA;AAAA,WACxB,CAAG,EAAA;AAEV,IAAO,MAAA,CAAA,IAAA;AAAA,MACL,CAA4B,yBAAA,EAAA,GAAG,CAA0C,uCAAA,EAAA,CAAA,CAAE,OAAO,CAAA,GAAA,CAAA;AAAA,KACpF,CAAA;AAAA,GACF;AAEA,EAAA,IAAI,MAAQ,EAAA;AACV,IAAI,IAAA;AACF,MAAA,YAAA,GAAe,IAAK,CAAA,KAAA,CAAM,MAAO,CAAA,QAAA,EAAU,CAAA,CAAA;AAC3C,MAAM,MAAA,gBAAA,GACJA,mDAA8B,CAAA,SAAA,CAAU,YAAY,CAAA,CAAA;AACtD,MAAI,IAAA,CAAC,iBAAiB,OAAS,EAAA;AAC7B,QAAM,MAAA,YAAA,GAAe,CAAyC,sCAAA,EAAA,GAAG,CAAgC,6BAAA,EAAA,sBAAA;AAAA,UAC/F,gBAAiB,CAAA,KAAA;AAAA,SAClB,CAAA,iFAAA,CAAA,CAAA;AACD,QAAA,MAAA,CAAO,MAAM,YAAY,CAAA,CAAA;AAAA,OAC3B;AACA,MAAA,OAAO,gBAAiB,CAAA,IAAA,CAAA;AAAA,aACjB,CAAG,EAAA;AACV,MAAO,MAAA,CAAA,KAAA;AAAA,QACL,6CAA6C,GAAG,CAAA,0BAAA,CAAA;AAAA,OAClD,CAAA;AAAA,KACF;AAAA,GACF;AAEA,EAAO,OAAA,KAAA,CAAA,CAAA;AACT,CAAA;AAOA,SAAS,uBAAuB,QAA4B,EAAA;AAC1D,EAAA,OAAO,QAAS,CAAA,MAAA,CAAO,MAAO,CAAA,CAAC,KAAK,KAAU,KAAA;AAC5C,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,OAAO,CAAC,GAAA,EAAK,CAAG,EAAA,KAAA,CAAM,OAAO,CAAe,YAAA,EAAA,KAAA,CAAM,IAAI,CAAA,CAAA,CAAG,CACtD,CAAA,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,IAAI,CAAA,CAAA;AAAA,KACd;AACA,IAAO,OAAA,GAAA,CAAA;AAAA,KACN,EAAE,CAAA,CAAA;AACP;;;;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@backstage-community/plugin-tech-radar-backend",
|
|
3
|
+
"version": "1.0.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
|
+
"pluginId": "tech-radar",
|
|
15
|
+
"pluginPackages": [
|
|
16
|
+
"@backstage-community/plugin-tech-radar",
|
|
17
|
+
"@backstage-community/plugin-tech-radar-backend",
|
|
18
|
+
"@backstage-community/plugin-tech-radar-common"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://backstage.io",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/backstage/community-plugins",
|
|
25
|
+
"directory": "workspaces/tech-radar/plugins/tech-radar-backend"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"start": "backstage-cli package start",
|
|
29
|
+
"build": "backstage-cli package build",
|
|
30
|
+
"lint": "backstage-cli package lint",
|
|
31
|
+
"test": "backstage-cli package test",
|
|
32
|
+
"clean": "backstage-cli package clean",
|
|
33
|
+
"prepack": "backstage-cli package prepack",
|
|
34
|
+
"postpack": "backstage-cli package postpack"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@backstage-community/plugin-tech-radar-common": "^1.0.0",
|
|
38
|
+
"@backstage/backend-defaults": "^0.5.0",
|
|
39
|
+
"@backstage/backend-plugin-api": "^1.0.0",
|
|
40
|
+
"@backstage/config": "^1.2.0",
|
|
41
|
+
"express": "^4.17.1",
|
|
42
|
+
"express-promise-router": "^4.1.0",
|
|
43
|
+
"node-fetch": "^2.6.7",
|
|
44
|
+
"zod": "^3.20.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@backstage/backend-test-utils": "^1.0.0",
|
|
48
|
+
"@backstage/cli": "^0.27.1",
|
|
49
|
+
"@backstage/plugin-auth-backend": "^0.23.0",
|
|
50
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.0",
|
|
51
|
+
"@types/express": "*",
|
|
52
|
+
"@types/supertest": "^2.0.12",
|
|
53
|
+
"msw": "^2.3.1",
|
|
54
|
+
"supertest": "^6.2.4"
|
|
55
|
+
},
|
|
56
|
+
"files": [
|
|
57
|
+
"dist",
|
|
58
|
+
"config.d.ts"
|
|
59
|
+
],
|
|
60
|
+
"configSchema": "config.d.ts"
|
|
61
|
+
}
|