@axis-backstage/plugin-readme-backend 0.4.0 → 0.6.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 CHANGED
@@ -63,10 +63,9 @@ The Readme backend plugin has support for the [new backend system](https://backs
63
63
  In your `packages/backend/src/index.ts` make the following changes:
64
64
 
65
65
  ```diff
66
- + import { readmePlugin } from '@axis-backstage/readme-backend';
67
66
 
68
67
  const backend = createBackend();
69
- + backend.add(readmePlugin());
68
+ + backend.add(import('@axis-backstage/plugin-readme-backend'));
70
69
  // ... other feature additions
71
70
 
72
71
  backend.start();
package/dist/index.cjs.js CHANGED
@@ -10,10 +10,10 @@ var catalogModel = require('@backstage/catalog-model');
10
10
  var catalogClient = require('@backstage/catalog-client');
11
11
  var backendPluginApi = require('@backstage/backend-plugin-api');
12
12
 
13
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
14
14
 
15
- var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
16
- var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
15
+ var express__default = /*#__PURE__*/_interopDefaultCompat(express);
16
+ var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
17
17
 
18
18
  const DETECT_SYMLINKS_REGEX = "^(w+|.|/|-)+$";
19
19
  const isSymLink = (content) => {
@@ -36,19 +36,21 @@ const README_TYPES = [
36
36
  { name: "README.MD", type: "text/markdown" }
37
37
  ];
38
38
  async function createRouter(options) {
39
- const { logger, config, reader, discovery, tokenManager } = options;
39
+ const { logger, config, reader, discovery } = options;
40
+ const { auth } = backendCommon.createLegacyAuthAdapters(options);
40
41
  const catalogClient$1 = new catalogClient.CatalogClient({ discoveryApi: discovery });
41
42
  const pluginCache = backendCommon.CacheManager.fromConfig(config).forPlugin("readme");
42
43
  const cache = pluginCache.getClient({ defaultTtl: DEFAULT_TTL });
43
44
  logger.info("Initializing readme backend");
44
45
  const integrations = integration.ScmIntegrations.fromConfig(config);
45
- const router = Router__default["default"]();
46
- router.use(express__default["default"].json());
46
+ const router = Router__default.default();
47
+ router.use(express__default.default.json());
47
48
  router.get("/health", (_, response) => {
48
49
  response.json({ status: "ok" });
49
50
  });
50
- router.get("/:entityRef", async (request, response) => {
51
- const { entityRef } = request.params;
51
+ router.get("/:kind/:namespace/:name", async (request, response) => {
52
+ const { kind, namespace, name } = request.params;
53
+ const entityRef = catalogModel.stringifyEntityRef({ kind, namespace, name });
52
54
  const cacheDoc = await cache.get(entityRef);
53
55
  if (cacheDoc) {
54
56
  logger.info(`Loading README for ${entityRef} from cache.`);
@@ -56,7 +58,10 @@ async function createRouter(options) {
56
58
  response.send(cacheDoc.content);
57
59
  return;
58
60
  }
59
- const { token } = await tokenManager.getToken();
61
+ const { token } = await auth.getPluginRequestToken({
62
+ onBehalfOf: await auth.getOwnServiceCredentials(),
63
+ targetPluginId: "catalog"
64
+ });
60
65
  const entity = await catalogClient$1.getEntityByRef(entityRef, { token });
61
66
  if (!entity) {
62
67
  logger.info(`No integration found for ${entityRef}`);
@@ -132,6 +137,7 @@ const readmePlugin = backendPluginApi.createBackendPlugin({
132
137
  config: backendPluginApi.coreServices.rootConfig,
133
138
  reader: backendPluginApi.coreServices.urlReader,
134
139
  discovery: backendPluginApi.coreServices.discovery,
140
+ auth: backendPluginApi.coreServices.auth,
135
141
  tokenManager: backendPluginApi.coreServices.tokenManager,
136
142
  httpRouter: backendPluginApi.coreServices.httpRouter
137
143
  },
@@ -158,5 +164,5 @@ const readmePlugin = backendPluginApi.createBackendPlugin({
158
164
  });
159
165
 
160
166
  exports.createRouter = createRouter;
161
- exports["default"] = readmePlugin;
167
+ exports.default = readmePlugin;
162
168
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +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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"}
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 { AuthService, DiscoveryService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport {\n CacheManager,\n createLegacyAuthAdapters,\n} from '@backstage/backend-common';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n getEntitySourceLocation,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { CatalogClient } from '@backstage/catalog-client';\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 * Backstage discovery service\n */\n discovery: DiscoveryService;\n /**\n * Backstage token manager service\n */\n tokenManager: TokenManager;\n /**\n * Backstage auth service\n */\n auth?: AuthService;\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 } = options;\n const { auth } = createLegacyAuthAdapters(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('/:kind/:namespace/:name', async (request, response) => {\n const { kind, namespace, name } = request.params;\n const entityRef = stringifyEntityRef({ kind, namespace, name });\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 auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\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 auth: coreServices.auth,\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":["createLegacyAuthAdapters","catalogClient","CatalogClient","CacheManager","ScmIntegrations","Router","express","stringifyEntityRef","getEntitySourceLocation","errorHandler","createBackendPlugin","coreServices","loggerToWinstonLogger"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { UrlReader, TokenManager } from '@backstage/backend-common';
2
+ import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
3
+ import { DiscoveryService, AuthService } from '@backstage/backend-plugin-api';
2
4
  import { Config } from '@backstage/config';
3
5
  import express from 'express';
4
6
  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
7
 
8
8
  /**
9
9
  * Constructs a readme router.
@@ -23,13 +23,17 @@ interface RouterOptions {
23
23
  */
24
24
  reader: UrlReader;
25
25
  /**
26
- * Backstage discovery api instance
26
+ * Backstage discovery service
27
27
  */
28
- discovery: DiscoveryApi;
28
+ discovery: DiscoveryService;
29
29
  /**
30
- * Backstage token manager instance
30
+ * Backstage token manager service
31
31
  */
32
32
  tokenManager: TokenManager;
33
+ /**
34
+ * Backstage auth service
35
+ */
36
+ auth?: AuthService;
33
37
  }
34
38
  /**
35
39
  * Constructs a readme router.
@@ -45,4 +49,4 @@ declare function createRouter(options: RouterOptions): Promise<express.Router>;
45
49
  */
46
50
  declare const readmePlugin: () => _backstage_backend_plugin_api.BackendFeature;
47
51
 
48
- export { RouterOptions, createRouter, readmePlugin as default };
52
+ export { type RouterOptions, createRouter, readmePlugin as default };
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@axis-backstage/plugin-readme-backend",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "main": "dist/index.cjs.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
7
7
  "publishConfig": {
8
8
  "access": "public",
9
9
  "main": "dist/index.cjs.js",
10
- "types": "dist/index.d.ts"
10
+ "types": "dist/index.d.ts",
11
+ "directory": "_release/package"
11
12
  },
12
13
  "backstage": {
13
14
  "role": "backend-plugin"
@@ -22,13 +23,13 @@
22
23
  "postpack": "backstage-cli package postpack"
23
24
  },
24
25
  "dependencies": {
25
- "@backstage/backend-common": "^0.20.1",
26
- "@backstage/backend-plugin-api": "^0.6.9",
27
- "@backstage/catalog-client": "^1.5.2",
28
- "@backstage/catalog-model": "^1.4.3",
29
- "@backstage/config": "^1.1.1",
30
- "@backstage/integration": "^1.8.0",
31
- "@backstage/plugin-permission-common": "^0.7.12",
26
+ "@backstage/backend-common": "^0.21.7",
27
+ "@backstage/backend-plugin-api": "^0.6.17",
28
+ "@backstage/catalog-client": "^1.6.4",
29
+ "@backstage/catalog-model": "^1.4.5",
30
+ "@backstage/config": "^1.2.0",
31
+ "@backstage/integration": "^1.10.0",
32
+ "@backstage/plugin-permission-common": "^0.7.13",
32
33
  "@types/express": "*",
33
34
  "express": "^4.17.1",
34
35
  "express-promise-router": "^4.1.0",
@@ -37,12 +38,13 @@
37
38
  "yn": "^4.0.0"
38
39
  },
39
40
  "devDependencies": {
40
- "@backstage/cli": "^0.25.1",
41
+ "@backstage/cli": "^0.26.3",
41
42
  "@types/supertest": "^2.0.12",
42
43
  "msw": "^1.0.0",
43
44
  "supertest": "^6.2.4"
44
45
  },
45
46
  "files": [
46
47
  "dist"
47
- ]
48
- }
48
+ ],
49
+ "directory": "_release/package"
50
+ }
package/CHANGELOG.md DELETED
@@ -1,19 +0,0 @@
1
- # @axis-backstage/plugin-readme-backend
2
-
3
- ## 0.4.0
4
-
5
- ### Minor Changes
6
-
7
- - 864d983: Bumped Backstage version to v.1.22.0
8
-
9
- ## 0.3.0
10
-
11
- ### Minor Changes
12
-
13
- - 23ff76a: Bumped Backstage version to v.1.21.0 in whole monorepo
14
-
15
- ## 0.2.0
16
-
17
- ### Minor Changes
18
-
19
- - a67c963: Bumped Backstage to version 1.20.3