@axis-backstage/plugin-readme-backend 0.16.1 → 0.16.2

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,11 @@
1
1
  # @axis-backstage/plugin-readme-backend
2
2
 
3
+ ## 0.16.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 480d1a7: Replaced internally constructed `CatalogClient` with the injected `CatalogService` from `@backstage/plugin-catalog-node`. This removes the dependency on `@backstage/catalog-client` and `@backstage/backend-defaults`, improves testability, and fixes unawaited cache writes.
8
+
3
9
  ## 0.16.1
4
10
 
5
11
  ### Patch Changes
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var pluginCatalogNode = require('@backstage/plugin-catalog-node');
4
5
  var router = require('./service/router.cjs.js');
5
6
 
6
7
  const readmePlugin = backendPluginApi.createBackendPlugin({
@@ -10,7 +11,7 @@ const readmePlugin = backendPluginApi.createBackendPlugin({
10
11
  deps: {
11
12
  auth: backendPluginApi.coreServices.auth,
12
13
  config: backendPluginApi.coreServices.rootConfig,
13
- discovery: backendPluginApi.coreServices.discovery,
14
+ catalogApi: pluginCatalogNode.catalogServiceRef,
14
15
  httpRouter: backendPluginApi.coreServices.httpRouter,
15
16
  logger: backendPluginApi.coreServices.logger,
16
17
  reader: backendPluginApi.coreServices.urlReader,
@@ -19,9 +20,9 @@ const readmePlugin = backendPluginApi.createBackendPlugin({
19
20
  async init({
20
21
  auth,
21
22
  logger,
23
+ catalogApi,
22
24
  config,
23
25
  reader,
24
- discovery,
25
26
  httpRouter,
26
27
  cache
27
28
  }) {
@@ -29,9 +30,9 @@ const readmePlugin = backendPluginApi.createBackendPlugin({
29
30
  await router.createRouter({
30
31
  auth,
31
32
  logger,
33
+ catalogApi,
32
34
  config,
33
35
  reader,
34
- discovery,
35
36
  cache
36
37
  })
37
38
  );
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\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 auth: coreServices.auth,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n reader: coreServices.urlReader,\n cache: coreServices.cache,\n },\n async init({\n auth,\n logger,\n config,\n reader,\n discovery,\n httpRouter,\n cache,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n logger,\n config,\n reader,\n discovery,\n cache,\n }),\n );\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","createRouter"],"mappings":";;;;;AAWO,MAAM,eAAeA,oCAAoB,CAAA;AAAA,EAC9C,QAAU,EAAA,QAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,MAAMC,6BAAa,CAAA,IAAA;AAAA,QACnB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,YAAYA,6BAAa,CAAA,UAAA;AAAA,QACzB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,SAAA;AAAA,QACrB,OAAOA,6BAAa,CAAA;AAAA,OACtB;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,IAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAW,UAAA,CAAA,GAAA;AAAA,UACT,MAAMC,mBAAa,CAAA;AAAA,YACjB,IAAA;AAAA,YACA,MAAA;AAAA,YACA,MAAA;AAAA,YACA,MAAA;AAAA,YACA,SAAA;AAAA,YACA;AAAA,WACD;AAAA,SACH;AAAA;AACF,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\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 auth: coreServices.auth,\n config: coreServices.rootConfig,\n catalogApi: catalogServiceRef,\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n reader: coreServices.urlReader,\n cache: coreServices.cache,\n },\n async init({\n auth,\n logger,\n catalogApi,\n config,\n reader,\n httpRouter,\n cache,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n logger,\n catalogApi,\n config,\n reader,\n cache,\n }),\n );\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","catalogServiceRef","createRouter"],"mappings":";;;;;;AAYO,MAAM,eAAeA,oCAAoB,CAAA;AAAA,EAC9C,QAAU,EAAA,QAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,MAAMC,6BAAa,CAAA,IAAA;AAAA,QACnB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,UAAY,EAAAC,mCAAA;AAAA,QACZ,YAAYD,6BAAa,CAAA,UAAA;AAAA,QACzB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,SAAA;AAAA,QACrB,OAAOA,6BAAa,CAAA;AAAA,OACtB;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,IAAA;AAAA,QACA,MAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAW,UAAA,CAAA,GAAA;AAAA,UACT,MAAME,mBAAa,CAAA;AAAA,YACjB,IAAA;AAAA,YACA,MAAA;AAAA,YACA,UAAA;AAAA,YACA,MAAA;AAAA,YACA,MAAA;AAAA,YACA;AAAA,WACD;AAAA,SACH;AAAA;AACF,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
@@ -2,7 +2,6 @@
2
2
 
3
3
  var integration = require('@backstage/integration');
4
4
  var catalogModel = require('@backstage/catalog-model');
5
- var catalogClient = require('@backstage/catalog-client');
6
5
  var errors = require('@backstage/errors');
7
6
  var express = require('express');
8
7
  var Router = require('express-promise-router');
@@ -16,9 +15,9 @@ var express__default = /*#__PURE__*/_interopDefaultCompat(express);
16
15
  var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
17
16
 
18
17
  async function createRouter(options) {
19
- const { auth, logger, config: config$1, reader, discovery, cache } = options;
20
- const catalogClient$1 = new catalogClient.CatalogClient({ discoveryApi: discovery });
18
+ const { auth, logger, config: config$1, reader, catalogApi, cache } = options;
21
19
  const cacheTtl = config.getCacheTtl(config$1);
20
+ const readmeTypes = constants.getReadmeTypes(config$1);
22
21
  logger.info(`Initializing readme backend. Cache TTL: ${cacheTtl}ms`);
23
22
  const integrations = integration.ScmIntegrations.fromConfig(config$1);
24
23
  const router = Router__default.default();
@@ -39,11 +38,9 @@ async function createRouter(options) {
39
38
  response.send(cacheDoc.content);
40
39
  return;
41
40
  }
42
- const { token } = await auth.getPluginRequestToken({
43
- onBehalfOf: await auth.getOwnServiceCredentials(),
44
- targetPluginId: "catalog"
41
+ const entity = await catalogApi.getEntityByRef(entityRef, {
42
+ credentials: await auth.getOwnServiceCredentials()
45
43
  });
46
- const entity = await catalogClient$1.getEntityByRef(entityRef, { token });
47
44
  if (!entity) {
48
45
  logger.info(`No integration found for ${entityRef}`);
49
46
  response.status(500).json({ error: `No integration found for ${entityRef}` });
@@ -61,7 +58,6 @@ async function createRouter(options) {
61
58
  response.status(500).json({ error: `No integration found for ${source.target}` });
62
59
  return;
63
60
  }
64
- const readmeTypes = constants.getReadmeTypes(config$1);
65
61
  for (const fileType of readmeTypes) {
66
62
  const url = integration.resolveUrl({
67
63
  url: fileType.name,
@@ -81,7 +77,7 @@ async function createRouter(options) {
81
77
  const symLinkUrlResponse = await reader.readUrl(symLinkUrl);
82
78
  content = (await symLinkUrlResponse.buffer()).toString("utf-8");
83
79
  }
84
- cache.set(
80
+ await cache.set(
85
81
  entityRef,
86
82
  {
87
83
  name: fileType.name,
@@ -107,7 +103,7 @@ async function createRouter(options) {
107
103
  }
108
104
  }
109
105
  logger.info(`Readme not found for ${entityRef}`);
110
- cache.set(
106
+ await cache.set(
111
107
  entityRef,
112
108
  {
113
109
  name: constants.NOT_FOUND_PLACEHOLDER,
@@ -1 +1 @@
1
- {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["import {\n AuthService,\n CacheService,\n DiscoveryService,\n LoggerService,\n RootConfigService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n getEntitySourceLocation,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { isError, NotFoundError } from '@backstage/errors';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { isSymLink } from '../lib';\nimport { getCacheTtl } from './config';\nimport { NOT_FOUND_PLACEHOLDER, getReadmeTypes } from './constants';\nimport { ReadmeFile } from './types';\n\n/**\n * Constructs a readme router.\n *\n */\ninterface RouterOptions {\n auth: AuthService;\n config: RootConfigService;\n discovery: DiscoveryService;\n logger: LoggerService;\n reader: UrlReaderService;\n cache: CacheService;\n}\n\n/**\n * Constructs a readme router.\n *\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, logger, config, reader, discovery, cache } = options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n const cacheTtl = getCacheTtl(config);\n\n logger.info(`Initializing readme backend. Cache TTL: ${cacheTtl}ms`);\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 && cacheDoc.name === NOT_FOUND_PLACEHOLDER) {\n throw new NotFoundError('Readme could not be found');\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 const errorMessage = `Not valid location for ${source.target}`;\n logger.info(errorMessage);\n throw new NotFoundError(errorMessage);\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 const readmeTypes = getReadmeTypes(config);\n\n for (const fileType of readmeTypes) {\n const url = integration.resolveUrl({\n url: fileType.name,\n base: source.target,\n });\n\n let content;\n\n try {\n logger.debug(`Trying README location: ${url} for ${entityRef} `);\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(\n entityRef,\n {\n name: fileType.name,\n type: fileType.type,\n content: content,\n },\n { ttl: cacheTtl },\n );\n logger.info(\n `Found README for ${entityRef}: ${url} type ${fileType.type}`,\n );\n response.send(content);\n return;\n } catch (error: unknown) {\n if (isError(error) && error.name === 'NotFoundError') {\n continue;\n } else {\n response.status(500).json({\n error: `Readme failure: ${error}`,\n });\n return;\n }\n }\n }\n logger.info(`Readme not found for ${entityRef}`);\n cache.set(\n entityRef,\n {\n name: NOT_FOUND_PLACEHOLDER,\n type: '',\n content: '',\n },\n { ttl: cacheTtl },\n );\n throw new NotFoundError('Readme could not be found');\n });\n\n return router;\n}\n"],"names":["config","catalogClient","CatalogClient","getCacheTtl","ScmIntegrations","Router","express","stringifyEntityRef","NOT_FOUND_PLACEHOLDER","NotFoundError","getEntitySourceLocation","getReadmeTypes","isSymLink","isError"],"mappings":";;;;;;;;;;;;;;;;;AAuCA,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAA,MAAM,EAAE,IAAM,EAAA,MAAA,UAAQA,UAAQ,MAAQ,EAAA,SAAA,EAAW,OAAU,GAAA,OAAA;AAC3D,EAAA,MAAMC,kBAAgB,IAAIC,2BAAA,CAAc,EAAE,YAAA,EAAc,WAAW,CAAA;AACnE,EAAM,MAAA,QAAA,GAAWC,mBAAYH,QAAM,CAAA;AAEnC,EAAO,MAAA,CAAA,IAAA,CAAK,CAA2C,wCAAA,EAAA,QAAQ,CAAI,EAAA,CAAA,CAAA;AACnE,EAAM,MAAA,YAAA,GAAeI,2BAAgB,CAAA,UAAA,CAAWJ,QAAM,CAAA;AACtD,EAAA,MAAM,SAASK,uBAAO,EAAA;AACtB,EAAO,MAAA,CAAA,GAAA,CAAIC,wBAAQ,CAAA,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAA,CAAO,GAAI,CAAA,SAAA,EAAW,CAAC,CAAA,EAAG,QAAa,KAAA;AACrC,IAAA,QAAA,CAAS,IAAK,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAM,CAAA;AAAA,GAC/B,CAAA;AAED,EAAA,MAAA,CAAO,GAAI,CAAA,yBAAA,EAA2B,OAAO,OAAA,EAAS,QAAa,KAAA;AACjE,IAAA,MAAM,EAAE,IAAA,EAAM,SAAW,EAAA,IAAA,KAAS,OAAQ,CAAA,MAAA;AAC1C,IAAA,MAAM,YAAYC,+BAAmB,CAAA,EAAE,IAAM,EAAA,SAAA,EAAW,MAAM,CAAA;AAC9D,IAAA,MAAM,QAAY,GAAA,MAAM,KAAM,CAAA,GAAA,CAAI,SAAS,CAAA;AAE3C,IAAI,IAAA,QAAA,IAAY,QAAS,CAAA,IAAA,KAASC,+BAAuB,EAAA;AACvD,MAAM,MAAA,IAAIC,qBAAc,2BAA2B,CAAA;AAAA;AAErD,IAAA,IAAI,QAAU,EAAA;AACZ,MAAO,MAAA,CAAA,IAAA,CAAK,CAAsB,mBAAA,EAAA,SAAS,CAAc,YAAA,CAAA,CAAA;AACzD,MAAS,QAAA,CAAA,IAAA,CAAK,SAAS,IAAI,CAAA;AAC3B,MAAS,QAAA,CAAA,IAAA,CAAK,SAAS,OAAO,CAAA;AAC9B,MAAA;AAAA;AAEF,IAAA,MAAM,EAAE,KAAA,EAAU,GAAA,MAAM,KAAK,qBAAsB,CAAA;AAAA,MACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAyB,EAAA;AAAA,MAChD,cAAgB,EAAA;AAAA,KACjB,CAAA;AACD,IAAA,MAAM,SAAS,MAAMR,eAAA,CAAc,eAAe,SAAW,EAAA,EAAE,OAAO,CAAA;AACtE,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAO,MAAA,CAAA,IAAA,CAAK,CAA4B,yBAAA,EAAA,SAAS,CAAE,CAAA,CAAA;AACnD,MACG,QAAA,CAAA,MAAA,CAAO,GAAG,CACV,CAAA,IAAA,CAAK,EAAE,KAAO,EAAA,CAAA,yBAAA,EAA4B,SAAS,CAAA,CAAA,EAAI,CAAA;AAC1D,MAAA;AAAA;AAEF,IAAM,MAAA,MAAA,GAASS,qCAAwB,MAAM,CAAA;AAE7C,IAAA,IAAI,CAAC,MAAA,IAAU,MAAO,CAAA,IAAA,KAAS,KAAO,EAAA;AACpC,MAAM,MAAA,YAAA,GAAe,CAA0B,uBAAA,EAAA,MAAA,CAAO,MAAM,CAAA,CAAA;AAC5D,MAAA,MAAA,CAAO,KAAK,YAAY,CAAA;AACxB,MAAM,MAAA,IAAID,qBAAc,YAAY,CAAA;AAAA;AAEtC,IAAA,MAAM,WAAc,GAAA,YAAA,CAAa,KAAM,CAAA,MAAA,CAAO,MAAM,CAAA;AAEpD,IAAA,IAAI,CAAC,WAAa,EAAA;AAChB,MAAA,MAAA,CAAO,IAAK,CAAA,CAAA,yBAAA,EAA4B,MAAO,CAAA,MAAM,CAAE,CAAA,CAAA;AACvD,MACG,QAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CACV,IAAK,CAAA,EAAE,OAAO,CAA4B,yBAAA,EAAA,MAAA,CAAO,MAAM,CAAA,CAAA,EAAI,CAAA;AAC9D,MAAA;AAAA;AAGF,IAAM,MAAA,WAAA,GAAcE,yBAAeX,QAAM,CAAA;AAEzC,IAAA,KAAA,MAAW,YAAY,WAAa,EAAA;AAClC,MAAM,MAAA,GAAA,GAAM,YAAY,UAAW,CAAA;AAAA,QACjC,KAAK,QAAS,CAAA,IAAA;AAAA,QACd,MAAM,MAAO,CAAA;AAAA,OACd,CAAA;AAED,MAAI,IAAA,OAAA;AAEJ,MAAI,IAAA;AACF,QAAA,MAAA,CAAO,KAAM,CAAA,CAAA,wBAAA,EAA2B,GAAG,CAAA,KAAA,EAAQ,SAAS,CAAG,CAAA,CAAA,CAAA;AAC/D,QAAS,QAAA,CAAA,IAAA,CAAK,SAAS,IAAI,CAAA;AAE3B,QAAA,MAAM,WAAc,GAAA,MAAM,MAAO,CAAA,OAAA,CAAQ,GAAG,CAAA;AAC5C,QAAA,OAAA,GAAA,CAAW,MAAM,WAAA,CAAY,MAAO,EAAA,EAAG,SAAS,OAAO,CAAA;AAEvD,QAAI,IAAAY,aAAA,CAAU,OAAO,CAAG,EAAA;AACtB,UAAM,MAAA,UAAA,GAAa,YAAY,UAAW,CAAA;AAAA,YACxC,GAAK,EAAA,OAAA;AAAA,YACL,MAAM,MAAO,CAAA;AAAA,WACd,CAAA;AACD,UAAA,MAAM,kBAAqB,GAAA,MAAM,MAAO,CAAA,OAAA,CAAQ,UAAU,CAAA;AAC1D,UAAA,OAAA,GAAA,CAAW,MAAM,kBAAA,CAAmB,MAAO,EAAA,EAAG,SAAS,OAAO,CAAA;AAAA;AAGhE,QAAM,KAAA,CAAA,GAAA;AAAA,UACJ,SAAA;AAAA,UACA;AAAA,YACE,MAAM,QAAS,CAAA,IAAA;AAAA,YACf,MAAM,QAAS,CAAA,IAAA;AAAA,YACf;AAAA,WACF;AAAA,UACA,EAAE,KAAK,QAAS;AAAA,SAClB;AACA,QAAO,MAAA,CAAA,IAAA;AAAA,UACL,oBAAoB,SAAS,CAAA,EAAA,EAAK,GAAG,CAAA,MAAA,EAAS,SAAS,IAAI,CAAA;AAAA,SAC7D;AACA,QAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AACrB,QAAA;AAAA,eACO,KAAgB,EAAA;AACvB,QAAA,IAAIC,cAAQ,CAAA,KAAK,CAAK,IAAA,KAAA,CAAM,SAAS,eAAiB,EAAA;AACpD,UAAA;AAAA,SACK,MAAA;AACL,UAAS,QAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,YACxB,KAAA,EAAO,mBAAmB,KAAK,CAAA;AAAA,WAChC,CAAA;AACD,UAAA;AAAA;AACF;AACF;AAEF,IAAO,MAAA,CAAA,IAAA,CAAK,CAAwB,qBAAA,EAAA,SAAS,CAAE,CAAA,CAAA;AAC/C,IAAM,KAAA,CAAA,GAAA;AAAA,MACJ,SAAA;AAAA,MACA;AAAA,QACE,IAAM,EAAAL,+BAAA;AAAA,QACN,IAAM,EAAA,EAAA;AAAA,QACN,OAAS,EAAA;AAAA,OACX;AAAA,MACA,EAAE,KAAK,QAAS;AAAA,KAClB;AACA,IAAM,MAAA,IAAIC,qBAAc,2BAA2B,CAAA;AAAA,GACpD,CAAA;AAED,EAAO,OAAA,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["import {\n AuthService,\n CacheService,\n LoggerService,\n RootConfigService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n getEntitySourceLocation,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { isError, NotFoundError } from '@backstage/errors';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { isSymLink } from '../lib';\nimport { getCacheTtl } from './config';\nimport { NOT_FOUND_PLACEHOLDER, getReadmeTypes } from './constants';\nimport { ReadmeFile } from './types';\n\n/**\n * Constructs a readme router.\n *\n */\ninterface RouterOptions {\n auth: AuthService;\n catalogApi: CatalogService;\n config: RootConfigService;\n logger: LoggerService;\n reader: UrlReaderService;\n cache: CacheService;\n}\n\n/**\n * Constructs a readme router.\n *\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, logger, config, reader, catalogApi, cache } = options;\n const cacheTtl = getCacheTtl(config);\n const readmeTypes = getReadmeTypes(config);\n\n logger.info(`Initializing readme backend. Cache TTL: ${cacheTtl}ms`);\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 && cacheDoc.name === NOT_FOUND_PLACEHOLDER) {\n throw new NotFoundError('Readme could not be found');\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 entity = await catalogApi.getEntityByRef(entityRef, {\n credentials: await auth.getOwnServiceCredentials(),\n });\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 const errorMessage = `Not valid location for ${source.target}`;\n logger.info(errorMessage);\n throw new NotFoundError(errorMessage);\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 readmeTypes) {\n const url = integration.resolveUrl({\n url: fileType.name,\n base: source.target,\n });\n\n let content;\n\n try {\n logger.debug(`Trying README location: ${url} for ${entityRef} `);\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 await cache.set(\n entityRef,\n {\n name: fileType.name,\n type: fileType.type,\n content: content,\n },\n { ttl: cacheTtl },\n );\n logger.info(\n `Found README for ${entityRef}: ${url} type ${fileType.type}`,\n );\n response.send(content);\n return;\n } catch (error: unknown) {\n if (isError(error) && error.name === 'NotFoundError') {\n continue;\n } else {\n response.status(500).json({\n error: `Readme failure: ${error}`,\n });\n return;\n }\n }\n }\n logger.info(`Readme not found for ${entityRef}`);\n await cache.set(\n entityRef,\n {\n name: NOT_FOUND_PLACEHOLDER,\n type: '',\n content: '',\n },\n { ttl: cacheTtl },\n );\n throw new NotFoundError('Readme could not be found');\n });\n\n return router;\n}\n"],"names":["config","getCacheTtl","getReadmeTypes","ScmIntegrations","Router","express","stringifyEntityRef","NOT_FOUND_PLACEHOLDER","NotFoundError","getEntitySourceLocation","isSymLink","isError"],"mappings":"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"}
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "@axis-backstage/plugin-readme-backend",
3
- "version": "0.16.1",
3
+ "version": "0.16.2",
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",
11
- "directory": "_release/package"
10
+ "types": "dist/index.d.ts"
12
11
  },
13
12
  "backstage": {
14
13
  "role": "backend-plugin",
@@ -32,11 +31,11 @@
32
31
  },
33
32
  "dependencies": {
34
33
  "@backstage/backend-plugin-api": "^1.6.2",
35
- "@backstage/catalog-client": "^1.12.1",
36
34
  "@backstage/catalog-model": "^1.7.6",
37
35
  "@backstage/config": "^1.3.6",
38
36
  "@backstage/errors": "^1.2.7",
39
37
  "@backstage/integration": "^1.19.1",
38
+ "@backstage/plugin-catalog-node": "^1.20.0",
40
39
  "@backstage/types": "^1.2.2",
41
40
  "@types/express": "*",
42
41
  "express": "^4.17.1",
@@ -61,6 +60,5 @@
61
60
  "package.json"
62
61
  ]
63
62
  }
64
- },
65
- "directory": "_release/package"
63
+ }
66
64
  }