@axis-backstage/plugin-jira-dashboard-backend 2.1.0 → 2.3.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
@@ -25,16 +25,16 @@ The Jira Dashboard plugin requires the following YAML to be added to your app-co
25
25
  jiraDashboard:
26
26
  token: ${JIRA_TOKEN}
27
27
  baseUrl: ${JIRA_BASE_URL}
28
- userEmailSuffix: ${JIRA_EMAIL_SUFFIX}
28
+ userEmailSuffix: ${JIRA_EMAIL_SUFFIX} # Optional
29
29
  annotationPrefix: ${JIRA_ANNOTATION_PREFIX} # Optional
30
30
  ```
31
31
 
32
32
  #### Configuration Details:
33
33
 
34
- - `JIRA_TOKEN`: The API token to authenticate towards Jira. It can be found by visiting Atlassians page at https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/. In case you are using a Bearer or Basic token, you need to add it in the beginning of the token. For instance: `Bearer your-secret-token`
34
+ - `JIRA_TOKEN`: The "Authorization" header used for Jira authentication.
35
35
  > Note: The JIRA_TOKEN variable from [Roadie's Backstage Jira plugin](https://roadie.io/backstage/plugins/jira) can not be reused here because of the added encoding in this token.
36
36
  - `JIRA_BASE_URL`: The base url for Jira in your company, including the API version. For instance: https://jira.se.your-company.com/rest/api/2/
37
- - `JIRA_EMAIL_SUFFIX`: The email suffix used for retrieving a specific Jira user in a company. For instance: @your-company.com
37
+ - `JIRA_EMAIL_SUFFIX`: Optional email suffix used for retrieving a specific Jira user in a company. For instance: @your-company.com. If not provided, the user entity profile email is used instead.
38
38
  - `JIRA_ANNOTATION_PREFIX`: Optional annotation prefix for retrieving a custom annotation. Defaut value is jira.com. If you want to configure the plugin to be compatible with [Roadie's Backstage Jira Plugin](https://roadie.io/backstage/plugins/jira/), use the following annotation prefix:
39
39
 
40
40
  ```yaml
@@ -43,6 +43,57 @@ jiraDashboard:
43
43
  annotationPrefix: jira
44
44
  ```
45
45
 
46
+ #### Authentication examples and trouble shooting
47
+
48
+ Either "Basic Auth" or "Personal Acccess Tokens" can be used.
49
+
50
+ This plugin will directly take the content of the "jiraDashboard.token" config string and
51
+ use as the "Authorization" header in all Jira REST API calls.
52
+
53
+ ##### Basic Auth example
54
+
55
+ To use "Basic Auth" for authentication you need to create the "Authentication" header. See the [Jira documentation](https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/#supply-basic-auth-headers) how to create and encode the token. This is the how to use the example token from the documentation (`ZnJlZDpmcmVk`) with `curl`.
56
+
57
+ ```sh
58
+ curl -D- \
59
+ -X GET \
60
+ -H "Authorization: Basic ZnJlZDpmcmVk" \
61
+ -H "Content-Type: application/json" \
62
+ "https://your-domain.atlassian.net/rest/api/2/project/BS"
63
+ ```
64
+
65
+ This would result in the following Backstage configuration:
66
+
67
+ ```yaml
68
+ jiraDashboard:
69
+ token: Basic ZnJlZDpmcmVk
70
+ baseUrl: https://your-domain.atlassian.net/rest/api/2/
71
+ userEmailSuffix: ${JIRA_EMAIL_SUFFIX}
72
+ ```
73
+
74
+ ##### Personal Acccess Tokens example
75
+
76
+ See the [Personal Acccess Tokens](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html) documentation how to use and create
77
+ a PAT. The generated token can be directly used, there is no need to encode it. Using
78
+ `curl` with a PAT.
79
+
80
+ ```sh
81
+ curl -D- \
82
+ -X GET \
83
+ -H "Authorization: Bearer <Token>" \
84
+ -H "Content-Type: application/json" \
85
+ "https://your-domain.atlassian.net/rest/api/2/project/BS"
86
+ ```
87
+
88
+ And the corresponding Backstage configuration:
89
+
90
+ ```yaml
91
+ jiraDashboard:
92
+ token: Bearer <Token>
93
+ baseUrl: https://your-domain.atlassian.net/rest/api/2/
94
+ userEmailSuffix: ${JIRA_EMAIL_SUFFIX}
95
+ ```
96
+
46
97
  ### Integrating
47
98
 
48
99
  Here's how to get the backend plugin up and running:
package/config.d.ts CHANGED
@@ -13,7 +13,7 @@ export interface Config {
13
13
  baseUrl: string;
14
14
 
15
15
  /**
16
- * Optional email suffix used for retreiving a specific Jira user in a company. For instance @your-company.com. Default value is ''
16
+ * Optional email suffix used for retrieving a specific Jira user in a company. For instance: @your-company.com. If not provided, the user entity profile email is used instead.
17
17
  */
18
18
  userEmailSuffix?: string;
19
19
 
package/dist/index.cjs.js CHANGED
@@ -38,42 +38,39 @@ function resolveJiraToken(config) {
38
38
  }
39
39
  }
40
40
  function resolveUserEmailSuffix(config) {
41
- return config.getOptionalString(JIRA_USER_CONFIG_EMAIL_SUFFIX) || "";
41
+ return config.getOptionalString(JIRA_USER_CONFIG_EMAIL_SUFFIX);
42
42
  }
43
43
  function resolveAnnotationPrefix(config) {
44
44
  const annotationPrefix = config.getOptionalString(JIRA_ANNOTATION);
45
45
  return annotationPrefix != null ? annotationPrefix : "jira.com";
46
46
  }
47
47
 
48
- const getUsernameFromRef = (userRef) => {
49
- return userRef == null ? void 0 : userRef.split("/").slice(1)[0];
50
- };
51
48
  const openFilter = {
52
49
  name: "Open Issues",
53
50
  shortName: "OPEN",
54
51
  query: "resolution = Unresolved ORDER BY updated DESC"
55
52
  };
56
- const incomingFilter = {
53
+ const getIncomingFilter = (incomingStatus) => ({
57
54
  name: "Incoming Issues",
58
55
  shortName: "INCOMING",
59
- query: "status = New ORDER BY created ASC"
60
- };
61
- const getDefaultFilters = (config, userRef) => {
62
- if (!userRef) {
63
- return [openFilter, incomingFilter];
64
- }
65
- const username = getUsernameFromRef(userRef);
66
- if (!username) {
67
- return [openFilter, incomingFilter];
68
- }
69
- const assignedToMeFilter = {
56
+ query: `status = ${incomingStatus} ORDER BY created ASC`
57
+ });
58
+ const getAssignedToMeFilter = (userEntity, config) => {
59
+ var _a, _b;
60
+ const emailSuffixConfig = resolveUserEmailSuffix(config);
61
+ const email = emailSuffixConfig ? `${userEntity.metadata.name}${emailSuffixConfig}` : (_b = (_a = userEntity.spec) == null ? void 0 : _a.profile) == null ? void 0 : _b.email;
62
+ return {
70
63
  name: "Assigned to me",
71
64
  shortName: "ME",
72
- query: `assignee = "${username}${resolveUserEmailSuffix(
73
- config
74
- )}" AND resolution = Unresolved ORDER BY updated DESC`
65
+ query: `assignee = "${email}" AND resolution = Unresolved ORDER BY updated DESC`
75
66
  };
76
- return [openFilter, incomingFilter, assignedToMeFilter];
67
+ };
68
+ const getDefaultFiltersForUser = (config, userEntity, incomingStatus) => {
69
+ const incomingFilter = getIncomingFilter(incomingStatus != null ? incomingStatus : "New");
70
+ if (!userEntity)
71
+ return [openFilter, incomingFilter];
72
+ const assigneeToMeFilter = getAssignedToMeFilter(userEntity, config);
73
+ return [openFilter, incomingFilter, assigneeToMeFilter];
77
74
  };
78
75
 
79
76
  const jqlQueryBuilder = ({
@@ -246,12 +243,14 @@ const getAnnotations = (config) => {
246
243
  const projectKeyAnnotation = `${prefix}/${pluginJiraDashboardCommon.PROJECT_KEY_NAME}`;
247
244
  const componentsAnnotation = `${prefix}/${pluginJiraDashboardCommon.COMPONENTS_NAME}`;
248
245
  const filtersAnnotation = `${prefix}/${pluginJiraDashboardCommon.FILTERS_NAME}`;
246
+ const incomingIssuesAnnotation = `${prefix}/${pluginJiraDashboardCommon.INCOMING_ISSUES_STATUS}`;
249
247
  const componentRoadieAnnotation = `${prefix}/component`;
250
248
  return {
251
249
  projectKeyAnnotation,
252
250
  componentsAnnotation,
253
- componentRoadieAnnotation,
254
- filtersAnnotation
251
+ filtersAnnotation,
252
+ incomingIssuesAnnotation,
253
+ componentRoadieAnnotation
255
254
  };
256
255
  };
257
256
 
@@ -271,7 +270,7 @@ async function createRouter(options) {
271
270
  router.get(
272
271
  "/dashboards/by-entity-ref/:kind/:namespace/:name",
273
272
  async (request, response) => {
274
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
273
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
275
274
  const { kind, namespace, name } = request.params;
276
275
  const entityRef = catalogModel.stringifyEntityRef({ kind, namespace, name });
277
276
  const { token } = await auth.getPluginRequestToken({
@@ -282,8 +281,9 @@ async function createRouter(options) {
282
281
  const {
283
282
  projectKeyAnnotation,
284
283
  componentsAnnotation,
285
- componentRoadieAnnotation,
286
- filtersAnnotation
284
+ filtersAnnotation,
285
+ incomingIssuesAnnotation,
286
+ componentRoadieAnnotation
287
287
  } = getAnnotations(config);
288
288
  if (!entity) {
289
289
  logger.info(`No entity found for ${entityRef}`);
@@ -313,22 +313,28 @@ async function createRouter(options) {
313
313
  });
314
314
  return;
315
315
  }
316
- const credentials = await httpAuth.credentials(request, {
317
- allow: ["user"]
318
- });
319
- const userEntityRef = credentials.principal.userEntityRef;
320
- if (!userEntityRef) {
321
- logger.warn(`Could not find user identity`);
316
+ let userEntity;
317
+ try {
318
+ const credentials = await httpAuth.credentials(request, {
319
+ allow: ["user"]
320
+ });
321
+ const userIdentity = credentials.principal.userEntityRef;
322
+ userEntity = await catalogClient$1.getEntityByRef(userIdentity, {
323
+ token
324
+ });
325
+ } catch (err) {
326
+ logger.warn("Could not find user identity");
322
327
  }
323
328
  let filters = [];
324
- const customFilterAnnotations = (_d = (_c = entity.metadata.annotations) == null ? void 0 : _c[filtersAnnotation]) == null ? void 0 : _d.split(",");
325
- filters = getDefaultFilters(config, userEntityRef);
329
+ const incomingStatus = (_c = entity.metadata.annotations) == null ? void 0 : _c[incomingIssuesAnnotation];
330
+ filters = getDefaultFiltersForUser(config, userEntity, incomingStatus);
331
+ const customFilterAnnotations = (_e = (_d = entity.metadata.annotations) == null ? void 0 : _d[filtersAnnotation]) == null ? void 0 : _e.split(",");
326
332
  if (customFilterAnnotations) {
327
333
  filters.push(
328
334
  ...await getFiltersFromAnnotations(customFilterAnnotations, config)
329
335
  );
330
336
  }
331
- let components = (_g = (_f = (_e = entity.metadata.annotations) == null ? void 0 : _e[componentsAnnotation]) == null ? void 0 : _f.split(",")) != null ? _g : [];
337
+ let components = (_h = (_g = (_f = entity.metadata.annotations) == null ? void 0 : _f[componentsAnnotation]) == null ? void 0 : _g.split(",")) != null ? _h : [];
332
338
  let issues = await getIssuesFromFilters(
333
339
  projectKey[0],
334
340
  components,
@@ -336,7 +342,7 @@ async function createRouter(options) {
336
342
  config
337
343
  );
338
344
  components = components.concat(
339
- (_j = (_i = (_h = entity.metadata.annotations) == null ? void 0 : _h[componentRoadieAnnotation]) == null ? void 0 : _i.split(",")) != null ? _j : []
345
+ (_k = (_j = (_i = entity.metadata.annotations) == null ? void 0 : _i[componentRoadieAnnotation]) == null ? void 0 : _j.split(",")) != null ? _k : []
340
346
  );
341
347
  if (components) {
342
348
  const componentIssues = await getIssuesFromComponents(
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/config.ts","../src/filters.ts","../src/queries.ts","../src/api.ts","../src/service/service.ts","../src/lib.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["import { Config } from '@backstage/config';\n\nconst JIRA_BASE_URL_CONFIG_PATH = 'jiraDashboard.baseUrl';\nconst JIRA_TOKEN_CONFIG_PATH = 'jiraDashboard.token';\nconst JIRA_USER_CONFIG_EMAIL_SUFFIX = 'jiraDashboard.userEmailSuffix';\nconst JIRA_ANNOTATION = 'jiraDashboard.annotationPrefix';\n\nexport function resolveJiraBaseUrl(config: Config): string {\n try {\n return config.getString(JIRA_BASE_URL_CONFIG_PATH);\n } catch (error) {\n throw new Error(`Invalid Jira baseUrl, ${error}`);\n }\n}\n\nexport function resolveJiraToken(config: Config): string {\n try {\n return config.getString(JIRA_TOKEN_CONFIG_PATH);\n } catch (error) {\n throw new Error(`Invalid Jira token, ${error}`);\n }\n}\n\nexport function resolveUserEmailSuffix(config: Config): string {\n return config.getOptionalString(JIRA_USER_CONFIG_EMAIL_SUFFIX) || '';\n}\n\nexport function resolveAnnotationPrefix(config: Config): string {\n const annotationPrefix = config.getOptionalString(JIRA_ANNOTATION);\n return annotationPrefix ?? 'jira.com';\n}\n","import { Config } from '@backstage/config';\nimport { resolveUserEmailSuffix } from './config';\nimport { Filter } from '@axis-backstage/plugin-jira-dashboard-common';\n\nconst getUsernameFromRef = (userRef: string) => {\n return userRef?.split('/').slice(1)[0];\n};\n\nconst openFilter: Filter = {\n name: 'Open Issues',\n shortName: 'OPEN',\n query: 'resolution = Unresolved ORDER BY updated DESC',\n};\n\nconst incomingFilter: Filter = {\n name: 'Incoming Issues',\n shortName: 'INCOMING',\n query: 'status = New ORDER BY created ASC',\n};\n\nexport const getDefaultFilters = (\n config: Config,\n userRef?: string,\n): Filter[] => {\n if (!userRef) {\n return [openFilter, incomingFilter];\n }\n const username = getUsernameFromRef(userRef);\n\n if (!username) {\n return [openFilter, incomingFilter];\n }\n\n const assignedToMeFilter: Filter = {\n name: 'Assigned to me',\n shortName: 'ME',\n query: `assignee = \"${username}${resolveUserEmailSuffix(\n config,\n )}\" AND resolution = Unresolved ORDER BY updated DESC`,\n };\n\n return [openFilter, incomingFilter, assignedToMeFilter];\n};\n","/**\n * Types for the arguments to the jqlQueryBuilder function.\n *\n * @public\n */\nexport type JqlQueryBuilderArgs = {\n project: string;\n components?: string[];\n query?: string;\n};\n\n/**\n * Creates a jql query string.\n *\n * @public\n */\nexport const jqlQueryBuilder = ({\n project,\n components,\n query,\n}: JqlQueryBuilderArgs) => {\n let jql = `project in (${project})`;\n if (components && components.length > 0) {\n let componentsInclude = '(';\n for (let index = 0; index < components.length; index++) {\n const component = components[index];\n componentsInclude += `'${component}'`;\n // Add either the \",\" separator or close the parentheses.\n if (index === components.length - 1) {\n componentsInclude += ')';\n } else {\n componentsInclude += ',';\n }\n }\n jql += ` AND component in ${componentsInclude}`;\n }\n if (query) {\n jql += ` AND ${query}`;\n }\n return jql;\n};\n","import { Config } from '@backstage/config';\nimport fetch from 'node-fetch';\nimport {\n Filter,\n Issue,\n Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport { resolveJiraBaseUrl, resolveJiraToken } from './config';\nimport { jqlQueryBuilder } from './queries';\n\nexport const getProjectInfo = async (\n projectKey: string,\n config: Config,\n): Promise<Project> => {\n const response = await fetch(\n `${resolveJiraBaseUrl(config)}project/${projectKey}`,\n {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n },\n );\n if (response.status !== 200) {\n throw Error(\n `Request failed with status code ${response.status}: ${response.statusText}`,\n );\n }\n return response.json();\n};\n\nexport const getFilterById = async (\n id: string,\n config: Config,\n): Promise<Filter> => {\n const response = await fetch(`${resolveJiraBaseUrl(config)}filter/${id}`, {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n });\n if (response.status !== 200) {\n throw Error(`${response.status}`);\n }\n const jsonResponse = await response.json();\n return { name: jsonResponse.name, query: jsonResponse.jql } as Filter;\n};\n\nexport const getIssuesByFilter = async (\n projectKey: string,\n components: string[],\n query: string,\n config: Config,\n): Promise<Issue[]> => {\n const jql = jqlQueryBuilder({ project: projectKey, components, query });\n const response = await fetch(\n `${resolveJiraBaseUrl(config)}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n },\n ).then(resp => resp.json());\n return response.issues;\n};\n\n/**\n * Options available for the Jira JQL query.\n *\n * @public\n */\nexport type SearchOptions = {\n expand?: string[];\n fields?: string[];\n fieldsByKey?: boolean;\n properties?: string[];\n startAt?: number;\n maxResults?: number;\n validateQuery?: string;\n};\n\n/**\n * Search for Jira issues using JQL.\n *\n * For more information about the available options see the API\n * documentation at:\n * https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-search/#api-rest-api-2-search-post\n *\n * @param config - A Backstage config\n * @param jqlQuery - A string containing the jql query.\n * @param options - Query options that will be passed on to the POST request.\n *\n * @public\n */\nexport const searchJira = async (\n config: Config,\n jqlQuery: string,\n options: SearchOptions,\n): Promise<Issue[]> => {\n const response = await fetch(`${resolveJiraBaseUrl(config)}search`, {\n method: 'POST',\n body: JSON.stringify({ jql: jqlQuery, ...options }),\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n }).then(resp => resp.json());\n return response.issues;\n};\n\nexport const getIssuesByComponent = async (\n projectKey: string,\n componentKey: string,\n config: Config,\n): Promise<Issue[]> => {\n const jql = jqlQueryBuilder({\n project: projectKey,\n components: [componentKey],\n });\n const response = await fetch(\n `${resolveJiraBaseUrl(config)}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n },\n ).then(resp => resp.json());\n return response.issues;\n};\n\nexport async function getProjectAvatar(url: string, config: Config) {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n },\n });\n return response;\n}\n","import { CacheClient } from '@backstage/backend-common';\nimport { Config } from '@backstage/config';\nimport {\n type Filter,\n type JiraDataResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport {\n getFilterById,\n getIssuesByComponent,\n getIssuesByFilter,\n getProjectInfo,\n} from '../api';\n\nexport const getProjectResponse = async (\n projectKey: string,\n config: Config,\n cache: CacheClient,\n): Promise<Project> => {\n let projectResponse: Project;\n\n projectResponse = (await cache.get(projectKey)) as Project;\n\n if (projectResponse) return projectResponse as Project;\n\n try {\n projectResponse = await getProjectInfo(projectKey, config);\n cache.set(projectKey, projectResponse);\n } catch (err: any) {\n if (err.message !== 200) {\n throw Error(\n `Failed to get project info for project key ${projectKey} with error: ${err.message}`,\n );\n }\n }\n return projectResponse;\n};\n\nexport const getFiltersFromAnnotations = async (\n annotations: string[],\n config: Config,\n): Promise<Filter[]> => {\n const filters: Filter[] = [];\n\n for (const filter of annotations) {\n try {\n const response = await getFilterById(filter, config);\n filters.push(response);\n } catch (err: any) {\n console.warn(\n `${err.message} : Could not find filter with filter id ${filter}`,\n );\n }\n }\n return filters;\n};\n\nexport const getIssuesFromFilters = async (\n projectKey: string,\n components: string[],\n filters: Filter[],\n config: Config,\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n filters.map(async filter => ({\n name: filter.name,\n type: 'filter',\n issues: await getIssuesByFilter(\n projectKey,\n components,\n filter.query,\n config,\n ),\n })),\n );\n};\n\nexport const getIssuesFromComponents = async (\n projectKey: string,\n componentAnnotations: string[],\n config: Config,\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n componentAnnotations.map(async componentKey => ({\n name: componentKey,\n type: 'component',\n issues: await getIssuesByComponent(projectKey, componentKey, config),\n })),\n );\n};\n","import { resolveAnnotationPrefix } from './config';\nimport {\n COMPONENTS_NAME,\n PROJECT_KEY_NAME,\n FILTERS_NAME,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport { Config } from '@backstage/config';\n\nexport const getAnnotations = (config: Config) => {\n const prefix = resolveAnnotationPrefix(config);\n\n const projectKeyAnnotation = `${prefix}/${PROJECT_KEY_NAME}`;\n const componentsAnnotation = `${prefix}/${COMPONENTS_NAME}`;\n const filtersAnnotation = `${prefix}/${FILTERS_NAME}`;\n\n /* Adding support for Roadie's component annotation */\n const componentRoadieAnnotation = `${prefix}/component`;\n\n return {\n projectKeyAnnotation,\n componentsAnnotation,\n componentRoadieAnnotation,\n filtersAnnotation,\n };\n};\n","import {\n CacheManager,\n TokenManager,\n createLegacyAuthAdapters,\n errorHandler,\n} from '@backstage/backend-common';\nimport {\n AuthService,\n DiscoveryService,\n HttpAuthService,\n} from '@backstage/backend-plugin-api';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { IdentityApi } from '@backstage/plugin-auth-node';\n\nimport { getDefaultFilters } from '../filters';\nimport {\n type Filter,\n type JiraResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport stream from 'stream';\nimport { getProjectAvatar } from '../api';\nimport {\n getProjectResponse,\n getFiltersFromAnnotations,\n getIssuesFromFilters,\n getIssuesFromComponents,\n} from './service';\nimport { getAnnotations } from '../lib';\n\n/**\n * Constructs a jira dashboard 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 discovery api instance\n */\n discovery: DiscoveryService;\n\n /**\n * Backstage identity api instance\n */\n identity?: IdentityApi;\n\n /**\n * Backstage token manager instance\n */\n tokenManager?: TokenManager;\n /**\n * Backstage auth service\n */\n auth?: AuthService;\n /**\n * Backstage httpAuth service\n */\n httpAuth?: HttpAuthService;\n}\n\nconst DEFAULT_TTL = 1000 * 60;\n\n/**\n * Constructs a jira dashboard router.\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, httpAuth } = createLegacyAuthAdapters(options);\n const { logger, config, discovery } = options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n logger.info('Initializing Jira Dashboard backend');\n\n const pluginCache =\n CacheManager.fromConfig(config).forPlugin('jira-dashboard');\n const cache = pluginCache.getClient({ defaultTtl: DEFAULT_TTL });\n\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(\n '/dashboards/by-entity-ref/:kind/:namespace/:name',\n async (request, response) => {\n const { kind, namespace, name } = request.params;\n const entityRef = stringifyEntityRef({ kind, namespace, name });\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(entityRef, { token });\n const {\n projectKeyAnnotation,\n componentsAnnotation,\n componentRoadieAnnotation,\n filtersAnnotation,\n } = getAnnotations(config);\n\n if (!entity) {\n logger.info(`No entity found for ${entityRef}`);\n response\n .status(500)\n .json({ error: `No entity found for ${entityRef}` });\n return;\n }\n\n const projectKey =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n if (!projectKey) {\n const error = `No jira.com/project-key annotation found for ${entityRef}`;\n logger.info(error);\n response.status(404).json(error);\n return;\n }\n\n let projectResponse;\n\n try {\n projectResponse = await getProjectResponse(\n projectKey[0],\n config,\n cache,\n );\n } catch (err: any) {\n logger.error(\n `Could not find Jira project ${projectKey[0]}: ${err.message}`,\n );\n response.status(404).json({\n error: `No Jira project found with key ${projectKey[0]}`,\n });\n return;\n }\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n\n const userEntityRef = credentials.principal.userEntityRef;\n\n if (!userEntityRef) {\n logger.warn(`Could not find user identity`);\n }\n\n let filters: Filter[] = [];\n\n const customFilterAnnotations =\n entity.metadata.annotations?.[filtersAnnotation]?.split(',')!;\n\n filters = getDefaultFilters(config, userEntityRef);\n\n if (customFilterAnnotations) {\n filters.push(\n ...(await getFiltersFromAnnotations(customFilterAnnotations, config)),\n );\n }\n\n let components =\n entity.metadata.annotations?.[componentsAnnotation]?.split(',') ?? [];\n let issues = await getIssuesFromFilters(\n projectKey[0],\n components,\n filters,\n config,\n );\n\n /* Adding support for Roadie's component annotation */\n components = components.concat(\n entity.metadata.annotations?.[componentRoadieAnnotation]?.split(',') ??\n [],\n );\n\n if (components) {\n const componentIssues = await getIssuesFromComponents(\n projectKey[0],\n components,\n config,\n );\n issues = issues.concat(componentIssues);\n }\n\n const jiraResponse: JiraResponse = {\n project: projectResponse as Project,\n data: issues,\n };\n response.json(jiraResponse);\n },\n );\n\n router.get(\n '/avatar/by-entity-ref/:kind/:namespace/:name',\n async (request, response) => {\n const { kind, namespace, name } = request.params;\n const entityRef = stringifyEntityRef({ kind, namespace, name });\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(entityRef, { token });\n const { projectKeyAnnotation } = getAnnotations(config);\n\n if (!entity) {\n logger.info(`No entity found for ${entityRef}`);\n response\n .status(500)\n .json({ error: `No entity found for ${entityRef}` });\n return;\n }\n\n const projectKey =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n const projectResponse = await getProjectResponse(\n projectKey[0],\n config,\n cache,\n );\n\n if (!projectResponse) {\n logger.error('Could not find project in Jira');\n response.status(400).json({\n error: `No Jira project found for project key ${projectKey[0]}`,\n });\n return;\n }\n\n const url = projectResponse.avatarUrls['48x48'];\n\n const avatar = await getProjectAvatar(url, config);\n\n const ps = new stream.PassThrough();\n const val = avatar.headers.get('content-type');\n\n response.setHeader('content-type', val ?? '');\n stream.pipeline(avatar.body, ps, err => {\n if (err) {\n logger.error(err);\n response.sendStatus(400);\n }\n return;\n });\n ps.pipe(response);\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 Jira Dashboard backend plugin.\n *\n * @public\n */\nexport const jiraDashboardPlugin = createBackendPlugin({\n pluginId: 'jira-dashboard',\n register(env) {\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n },\n async init({ logger, config, discovery, httpRouter, auth, httpAuth }) {\n httpRouter.use(\n await createRouter({\n logger: loggerToWinstonLogger(logger),\n config,\n discovery,\n auth,\n httpAuth,\n }),\n );\n },\n });\n },\n});\n"],"names":["fetch","PROJECT_KEY_NAME","COMPONENTS_NAME","FILTERS_NAME","createLegacyAuthAdapters","catalogClient","CatalogClient","CacheManager","Router","express","stringifyEntityRef","stream","errorHandler","createBackendPlugin","coreServices","loggerToWinstonLogger"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/config.ts","../src/filters.ts","../src/queries.ts","../src/api.ts","../src/service/service.ts","../src/lib.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["import { Config } from '@backstage/config';\n\nconst JIRA_BASE_URL_CONFIG_PATH = 'jiraDashboard.baseUrl';\nconst JIRA_TOKEN_CONFIG_PATH = 'jiraDashboard.token';\nconst JIRA_USER_CONFIG_EMAIL_SUFFIX = 'jiraDashboard.userEmailSuffix';\nconst JIRA_ANNOTATION = 'jiraDashboard.annotationPrefix';\n\nexport function resolveJiraBaseUrl(config: Config): string {\n try {\n return config.getString(JIRA_BASE_URL_CONFIG_PATH);\n } catch (error) {\n throw new Error(`Invalid Jira baseUrl, ${error}`);\n }\n}\n\nexport function resolveJiraToken(config: Config): string {\n try {\n return config.getString(JIRA_TOKEN_CONFIG_PATH);\n } catch (error) {\n throw new Error(`Invalid Jira token, ${error}`);\n }\n}\n\nexport function resolveUserEmailSuffix(config: Config): string | undefined {\n return config.getOptionalString(JIRA_USER_CONFIG_EMAIL_SUFFIX);\n}\n\nexport function resolveAnnotationPrefix(config: Config): string {\n const annotationPrefix = config.getOptionalString(JIRA_ANNOTATION);\n return annotationPrefix ?? 'jira.com';\n}\n","import { Config } from '@backstage/config';\nimport { resolveUserEmailSuffix } from './config';\nimport { Filter } from '@axis-backstage/plugin-jira-dashboard-common';\nimport { UserEntity } from '@backstage/catalog-model';\n\nconst openFilter: Filter = {\n name: 'Open Issues',\n shortName: 'OPEN',\n query: 'resolution = Unresolved ORDER BY updated DESC',\n};\n\nconst getIncomingFilter = (incomingStatus: string): Filter => ({\n name: 'Incoming Issues',\n shortName: 'INCOMING',\n query: `status = ${incomingStatus} ORDER BY created ASC`,\n});\n\nconst getAssignedToMeFilter = (\n userEntity: UserEntity,\n config: Config,\n): Filter => {\n const emailSuffixConfig = resolveUserEmailSuffix(config);\n\n const email = emailSuffixConfig\n ? `${userEntity.metadata.name}${emailSuffixConfig}`\n : userEntity.spec?.profile?.email;\n\n return {\n name: 'Assigned to me',\n shortName: 'ME',\n query: `assignee = \"${email}\" AND resolution = Unresolved ORDER BY updated DESC`,\n };\n};\n\nexport const getDefaultFiltersForUser = (\n config: Config,\n userEntity?: UserEntity,\n incomingStatus?: string,\n): Filter[] => {\n const incomingFilter = getIncomingFilter(incomingStatus ?? 'New');\n\n if (!userEntity) return [openFilter, incomingFilter];\n\n const assigneeToMeFilter = getAssignedToMeFilter(userEntity, config);\n\n return [openFilter, incomingFilter, assigneeToMeFilter];\n};\n","/**\n * Types for the arguments to the jqlQueryBuilder function.\n *\n * @public\n */\nexport type JqlQueryBuilderArgs = {\n project: string;\n components?: string[];\n query?: string;\n};\n\n/**\n * Creates a jql query string.\n *\n * @public\n */\nexport const jqlQueryBuilder = ({\n project,\n components,\n query,\n}: JqlQueryBuilderArgs) => {\n let jql = `project in (${project})`;\n if (components && components.length > 0) {\n let componentsInclude = '(';\n for (let index = 0; index < components.length; index++) {\n const component = components[index];\n componentsInclude += `'${component}'`;\n // Add either the \",\" separator or close the parentheses.\n if (index === components.length - 1) {\n componentsInclude += ')';\n } else {\n componentsInclude += ',';\n }\n }\n jql += ` AND component in ${componentsInclude}`;\n }\n if (query) {\n jql += ` AND ${query}`;\n }\n return jql;\n};\n","import { Config } from '@backstage/config';\nimport fetch from 'node-fetch';\nimport {\n Filter,\n Issue,\n Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport { resolveJiraBaseUrl, resolveJiraToken } from './config';\nimport { jqlQueryBuilder } from './queries';\n\nexport const getProjectInfo = async (\n projectKey: string,\n config: Config,\n): Promise<Project> => {\n const response = await fetch(\n `${resolveJiraBaseUrl(config)}project/${projectKey}`,\n {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n },\n );\n if (response.status !== 200) {\n throw Error(\n `Request failed with status code ${response.status}: ${response.statusText}`,\n );\n }\n return response.json();\n};\n\nexport const getFilterById = async (\n id: string,\n config: Config,\n): Promise<Filter> => {\n const response = await fetch(`${resolveJiraBaseUrl(config)}filter/${id}`, {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n });\n if (response.status !== 200) {\n throw Error(`${response.status}`);\n }\n const jsonResponse = await response.json();\n return { name: jsonResponse.name, query: jsonResponse.jql } as Filter;\n};\n\nexport const getIssuesByFilter = async (\n projectKey: string,\n components: string[],\n query: string,\n config: Config,\n): Promise<Issue[]> => {\n const jql = jqlQueryBuilder({ project: projectKey, components, query });\n const response = await fetch(\n `${resolveJiraBaseUrl(config)}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n },\n ).then(resp => resp.json());\n return response.issues;\n};\n\n/**\n * Options available for the Jira JQL query.\n *\n * @public\n */\nexport type SearchOptions = {\n expand?: string[];\n fields?: string[];\n fieldsByKey?: boolean;\n properties?: string[];\n startAt?: number;\n maxResults?: number;\n validateQuery?: string;\n};\n\n/**\n * Search for Jira issues using JQL.\n *\n * For more information about the available options see the API\n * documentation at:\n * https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-search/#api-rest-api-2-search-post\n *\n * @param config - A Backstage config\n * @param jqlQuery - A string containing the jql query.\n * @param options - Query options that will be passed on to the POST request.\n *\n * @public\n */\nexport const searchJira = async (\n config: Config,\n jqlQuery: string,\n options: SearchOptions,\n): Promise<Issue[]> => {\n const response = await fetch(`${resolveJiraBaseUrl(config)}search`, {\n method: 'POST',\n body: JSON.stringify({ jql: jqlQuery, ...options }),\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n }).then(resp => resp.json());\n return response.issues;\n};\n\nexport const getIssuesByComponent = async (\n projectKey: string,\n componentKey: string,\n config: Config,\n): Promise<Issue[]> => {\n const jql = jqlQueryBuilder({\n project: projectKey,\n components: [componentKey],\n });\n const response = await fetch(\n `${resolveJiraBaseUrl(config)}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n Accept: 'application/json',\n },\n },\n ).then(resp => resp.json());\n return response.issues;\n};\n\nexport async function getProjectAvatar(url: string, config: Config) {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n Authorization: resolveJiraToken(config),\n },\n });\n return response;\n}\n","import { CacheClient } from '@backstage/backend-common';\nimport { Config } from '@backstage/config';\nimport {\n type Filter,\n type JiraDataResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport {\n getFilterById,\n getIssuesByComponent,\n getIssuesByFilter,\n getProjectInfo,\n} from '../api';\n\nexport const getProjectResponse = async (\n projectKey: string,\n config: Config,\n cache: CacheClient,\n): Promise<Project> => {\n let projectResponse: Project;\n\n projectResponse = (await cache.get(projectKey)) as Project;\n\n if (projectResponse) return projectResponse as Project;\n\n try {\n projectResponse = await getProjectInfo(projectKey, config);\n cache.set(projectKey, projectResponse);\n } catch (err: any) {\n if (err.message !== 200) {\n throw Error(\n `Failed to get project info for project key ${projectKey} with error: ${err.message}`,\n );\n }\n }\n return projectResponse;\n};\n\nexport const getFiltersFromAnnotations = async (\n annotations: string[],\n config: Config,\n): Promise<Filter[]> => {\n const filters: Filter[] = [];\n\n for (const filter of annotations) {\n try {\n const response = await getFilterById(filter, config);\n filters.push(response);\n } catch (err: any) {\n console.warn(\n `${err.message} : Could not find filter with filter id ${filter}`,\n );\n }\n }\n return filters;\n};\n\nexport const getIssuesFromFilters = async (\n projectKey: string,\n components: string[],\n filters: Filter[],\n config: Config,\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n filters.map(async filter => ({\n name: filter.name,\n type: 'filter',\n issues: await getIssuesByFilter(\n projectKey,\n components,\n filter.query,\n config,\n ),\n })),\n );\n};\n\nexport const getIssuesFromComponents = async (\n projectKey: string,\n componentAnnotations: string[],\n config: Config,\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n componentAnnotations.map(async componentKey => ({\n name: componentKey,\n type: 'component',\n issues: await getIssuesByComponent(projectKey, componentKey, config),\n })),\n );\n};\n","import { resolveAnnotationPrefix } from './config';\nimport {\n COMPONENTS_NAME,\n PROJECT_KEY_NAME,\n FILTERS_NAME,\n INCOMING_ISSUES_STATUS,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport { Config } from '@backstage/config';\n\nexport const getAnnotations = (config: Config) => {\n const prefix = resolveAnnotationPrefix(config);\n\n const projectKeyAnnotation = `${prefix}/${PROJECT_KEY_NAME}`;\n const componentsAnnotation = `${prefix}/${COMPONENTS_NAME}`;\n const filtersAnnotation = `${prefix}/${FILTERS_NAME}`;\n const incomingIssuesAnnotation = `${prefix}/${INCOMING_ISSUES_STATUS}`;\n\n /* Adding support for Roadie's component annotation */\n const componentRoadieAnnotation = `${prefix}/component`;\n\n return {\n projectKeyAnnotation,\n componentsAnnotation,\n filtersAnnotation,\n incomingIssuesAnnotation,\n componentRoadieAnnotation,\n };\n};\n","import {\n CacheManager,\n TokenManager,\n createLegacyAuthAdapters,\n errorHandler,\n} from '@backstage/backend-common';\nimport {\n AuthService,\n DiscoveryService,\n HttpAuthService,\n} from '@backstage/backend-plugin-api';\nimport { UserEntity, stringifyEntityRef } from '@backstage/catalog-model';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { IdentityApi } from '@backstage/plugin-auth-node';\n\nimport { getDefaultFiltersForUser } from '../filters';\nimport {\n type Filter,\n type JiraResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport stream from 'stream';\nimport { getProjectAvatar } from '../api';\nimport {\n getProjectResponse,\n getFiltersFromAnnotations,\n getIssuesFromFilters,\n getIssuesFromComponents,\n} from './service';\nimport { getAnnotations } from '../lib';\n\n/**\n * Constructs a jira dashboard 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 discovery api instance\n */\n discovery: DiscoveryService;\n\n /**\n * Backstage identity api instance\n */\n identity?: IdentityApi;\n\n /**\n * Backstage token manager instance\n */\n tokenManager?: TokenManager;\n /**\n * Backstage auth service\n */\n auth?: AuthService;\n /**\n * Backstage httpAuth service\n */\n httpAuth?: HttpAuthService;\n}\n\nconst DEFAULT_TTL = 1000 * 60;\n\n/**\n * Constructs a jira dashboard router.\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, httpAuth } = createLegacyAuthAdapters(options);\n const { logger, config, discovery } = options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n logger.info('Initializing Jira Dashboard backend');\n\n const pluginCache =\n CacheManager.fromConfig(config).forPlugin('jira-dashboard');\n const cache = pluginCache.getClient({ defaultTtl: DEFAULT_TTL });\n\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(\n '/dashboards/by-entity-ref/:kind/:namespace/:name',\n async (request, response) => {\n const { kind, namespace, name } = request.params;\n const entityRef = stringifyEntityRef({ kind, namespace, name });\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(entityRef, { token });\n const {\n projectKeyAnnotation,\n componentsAnnotation,\n filtersAnnotation,\n incomingIssuesAnnotation,\n componentRoadieAnnotation,\n } = getAnnotations(config);\n\n if (!entity) {\n logger.info(`No entity found for ${entityRef}`);\n response\n .status(500)\n .json({ error: `No entity found for ${entityRef}` });\n return;\n }\n\n const projectKey =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n if (!projectKey) {\n const error = `No jira.com/project-key annotation found for ${entityRef}`;\n logger.info(error);\n response.status(404).json(error);\n return;\n }\n\n let projectResponse;\n\n try {\n projectResponse = await getProjectResponse(\n projectKey[0],\n config,\n cache,\n );\n } catch (err: any) {\n logger.error(\n `Could not find Jira project ${projectKey[0]}: ${err.message}`,\n );\n response.status(404).json({\n error: `No Jira project found with key ${projectKey[0]}`,\n });\n return;\n }\n\n let userEntity: UserEntity | undefined;\n\n try {\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n const userIdentity = credentials.principal.userEntityRef;\n\n userEntity = (await catalogClient.getEntityByRef(userIdentity, {\n token,\n })) as UserEntity;\n } catch (err) {\n logger.warn('Could not find user identity');\n }\n\n let filters: Filter[] = [];\n\n const incomingStatus =\n entity.metadata.annotations?.[incomingIssuesAnnotation];\n\n filters = getDefaultFiltersForUser(config, userEntity, incomingStatus);\n\n const customFilterAnnotations =\n entity.metadata.annotations?.[filtersAnnotation]?.split(',')!;\n\n if (customFilterAnnotations) {\n filters.push(\n ...(await getFiltersFromAnnotations(customFilterAnnotations, config)),\n );\n }\n\n let components =\n entity.metadata.annotations?.[componentsAnnotation]?.split(',') ?? [];\n let issues = await getIssuesFromFilters(\n projectKey[0],\n components,\n filters,\n config,\n );\n\n /* Adding support for Roadie's component annotation */\n components = components.concat(\n entity.metadata.annotations?.[componentRoadieAnnotation]?.split(',') ??\n [],\n );\n\n if (components) {\n const componentIssues = await getIssuesFromComponents(\n projectKey[0],\n components,\n config,\n );\n issues = issues.concat(componentIssues);\n }\n\n const jiraResponse: JiraResponse = {\n project: projectResponse as Project,\n data: issues,\n };\n response.json(jiraResponse);\n },\n );\n\n router.get(\n '/avatar/by-entity-ref/:kind/:namespace/:name',\n async (request, response) => {\n const { kind, namespace, name } = request.params;\n const entityRef = stringifyEntityRef({ kind, namespace, name });\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(entityRef, { token });\n const { projectKeyAnnotation } = getAnnotations(config);\n\n if (!entity) {\n logger.info(`No entity found for ${entityRef}`);\n response\n .status(500)\n .json({ error: `No entity found for ${entityRef}` });\n return;\n }\n\n const projectKey =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n const projectResponse = await getProjectResponse(\n projectKey[0],\n config,\n cache,\n );\n\n if (!projectResponse) {\n logger.error('Could not find project in Jira');\n response.status(400).json({\n error: `No Jira project found for project key ${projectKey[0]}`,\n });\n return;\n }\n\n const url = projectResponse.avatarUrls['48x48'];\n\n const avatar = await getProjectAvatar(url, config);\n\n const ps = new stream.PassThrough();\n const val = avatar.headers.get('content-type');\n\n response.setHeader('content-type', val ?? '');\n stream.pipeline(avatar.body, ps, err => {\n if (err) {\n logger.error(err);\n response.sendStatus(400);\n }\n return;\n });\n ps.pipe(response);\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 Jira Dashboard backend plugin.\n *\n * @public\n */\nexport const jiraDashboardPlugin = createBackendPlugin({\n pluginId: 'jira-dashboard',\n register(env) {\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n },\n async init({ logger, config, discovery, httpRouter, auth, httpAuth }) {\n httpRouter.use(\n await createRouter({\n logger: loggerToWinstonLogger(logger),\n config,\n discovery,\n auth,\n httpAuth,\n }),\n );\n },\n });\n },\n});\n"],"names":["fetch","PROJECT_KEY_NAME","COMPONENTS_NAME","FILTERS_NAME","INCOMING_ISSUES_STATUS","createLegacyAuthAdapters","catalogClient","CatalogClient","CacheManager","Router","express","stringifyEntityRef","stream","errorHandler","createBackendPlugin","coreServices","loggerToWinstonLogger"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAEA,MAAM,yBAA4B,GAAA,uBAAA,CAAA;AAClC,MAAM,sBAAyB,GAAA,qBAAA,CAAA;AAC/B,MAAM,6BAAgC,GAAA,+BAAA,CAAA;AACtC,MAAM,eAAkB,GAAA,gCAAA,CAAA;AAEjB,SAAS,mBAAmB,MAAwB,EAAA;AACzD,EAAI,IAAA;AACF,IAAO,OAAA,MAAA,CAAO,UAAU,yBAAyB,CAAA,CAAA;AAAA,WAC1C,KAAO,EAAA;AACd,IAAA,MAAM,IAAI,KAAA,CAAM,CAAyB,sBAAA,EAAA,KAAK,CAAE,CAAA,CAAA,CAAA;AAAA,GAClD;AACF,CAAA;AAEO,SAAS,iBAAiB,MAAwB,EAAA;AACvD,EAAI,IAAA;AACF,IAAO,OAAA,MAAA,CAAO,UAAU,sBAAsB,CAAA,CAAA;AAAA,WACvC,KAAO,EAAA;AACd,IAAA,MAAM,IAAI,KAAA,CAAM,CAAuB,oBAAA,EAAA,KAAK,CAAE,CAAA,CAAA,CAAA;AAAA,GAChD;AACF,CAAA;AAEO,SAAS,uBAAuB,MAAoC,EAAA;AACzE,EAAO,OAAA,MAAA,CAAO,kBAAkB,6BAA6B,CAAA,CAAA;AAC/D,CAAA;AAEO,SAAS,wBAAwB,MAAwB,EAAA;AAC9D,EAAM,MAAA,gBAAA,GAAmB,MAAO,CAAA,iBAAA,CAAkB,eAAe,CAAA,CAAA;AACjE,EAAA,OAAO,gBAAoB,IAAA,IAAA,GAAA,gBAAA,GAAA,UAAA,CAAA;AAC7B;;ACzBA,MAAM,UAAqB,GAAA;AAAA,EACzB,IAAM,EAAA,aAAA;AAAA,EACN,SAAW,EAAA,MAAA;AAAA,EACX,KAAO,EAAA,+CAAA;AACT,CAAA,CAAA;AAEA,MAAM,iBAAA,GAAoB,CAAC,cAAoC,MAAA;AAAA,EAC7D,IAAM,EAAA,iBAAA;AAAA,EACN,SAAW,EAAA,UAAA;AAAA,EACX,KAAA,EAAO,YAAY,cAAc,CAAA,qBAAA,CAAA;AACnC,CAAA,CAAA,CAAA;AAEA,MAAM,qBAAA,GAAwB,CAC5B,UAAA,EACA,MACW,KAAA;AApBb,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAqBE,EAAM,MAAA,iBAAA,GAAoB,uBAAuB,MAAM,CAAA,CAAA;AAEvD,EAAA,MAAM,KAAQ,GAAA,iBAAA,GACV,CAAG,EAAA,UAAA,CAAW,QAAS,CAAA,IAAI,CAAG,EAAA,iBAAiB,CAC/C,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,UAAA,CAAW,IAAX,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAiB,YAAjB,IAA0B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,CAAA;AAE9B,EAAO,OAAA;AAAA,IACL,IAAM,EAAA,gBAAA;AAAA,IACN,SAAW,EAAA,IAAA;AAAA,IACX,KAAA,EAAO,eAAe,KAAK,CAAA,mDAAA,CAAA;AAAA,GAC7B,CAAA;AACF,CAAA,CAAA;AAEO,MAAM,wBAA2B,GAAA,CACtC,MACA,EAAA,UAAA,EACA,cACa,KAAA;AACb,EAAM,MAAA,cAAA,GAAiB,iBAAkB,CAAA,cAAA,IAAA,IAAA,GAAA,cAAA,GAAkB,KAAK,CAAA,CAAA;AAEhE,EAAA,IAAI,CAAC,UAAA;AAAY,IAAO,OAAA,CAAC,YAAY,cAAc,CAAA,CAAA;AAEnD,EAAM,MAAA,kBAAA,GAAqB,qBAAsB,CAAA,UAAA,EAAY,MAAM,CAAA,CAAA;AAEnE,EAAO,OAAA,CAAC,UAAY,EAAA,cAAA,EAAgB,kBAAkB,CAAA,CAAA;AACxD,CAAA;;AC9BO,MAAM,kBAAkB,CAAC;AAAA,EAC9B,OAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AACF,CAA2B,KAAA;AACzB,EAAI,IAAA,GAAA,GAAM,eAAe,OAAO,CAAA,CAAA,CAAA,CAAA;AAChC,EAAI,IAAA,UAAA,IAAc,UAAW,CAAA,MAAA,GAAS,CAAG,EAAA;AACvC,IAAA,IAAI,iBAAoB,GAAA,GAAA,CAAA;AACxB,IAAA,KAAA,IAAS,KAAQ,GAAA,CAAA,EAAG,KAAQ,GAAA,UAAA,CAAW,QAAQ,KAAS,EAAA,EAAA;AACtD,MAAM,MAAA,SAAA,GAAY,WAAW,KAAK,CAAA,CAAA;AAClC,MAAA,iBAAA,IAAqB,IAAI,SAAS,CAAA,CAAA,CAAA,CAAA;AAElC,MAAI,IAAA,KAAA,KAAU,UAAW,CAAA,MAAA,GAAS,CAAG,EAAA;AACnC,QAAqB,iBAAA,IAAA,GAAA,CAAA;AAAA,OAChB,MAAA;AACL,QAAqB,iBAAA,IAAA,GAAA,CAAA;AAAA,OACvB;AAAA,KACF;AACA,IAAA,GAAA,IAAO,qBAAqB,iBAAiB,CAAA,CAAA,CAAA;AAAA,GAC/C;AACA,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,GAAA,IAAO,QAAQ,KAAK,CAAA,CAAA,CAAA;AAAA,GACtB;AACA,EAAO,OAAA,GAAA,CAAA;AACT;;AC9Ba,MAAA,cAAA,GAAiB,OAC5B,UAAA,EACA,MACqB,KAAA;AACrB,EAAA,MAAM,WAAW,MAAMA,sBAAA;AAAA,IACrB,CAAG,EAAA,kBAAA,CAAmB,MAAM,CAAC,WAAW,UAAU,CAAA,CAAA;AAAA,IAClD;AAAA,MACE,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,aAAA,EAAe,iBAAiB,MAAM,CAAA;AAAA,QACtC,MAAQ,EAAA,kBAAA;AAAA,OACV;AAAA,KACF;AAAA,GACF,CAAA;AACA,EAAI,IAAA,QAAA,CAAS,WAAW,GAAK,EAAA;AAC3B,IAAM,MAAA,KAAA;AAAA,MACJ,CAAmC,gCAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAAA,KAC5E,CAAA;AAAA,GACF;AACA,EAAA,OAAO,SAAS,IAAK,EAAA,CAAA;AACvB,CAAA,CAAA;AAEa,MAAA,aAAA,GAAgB,OAC3B,EAAA,EACA,MACoB,KAAA;AACpB,EAAM,MAAA,QAAA,GAAW,MAAMA,sBAAM,CAAA,CAAA,EAAG,mBAAmB,MAAM,CAAC,CAAU,OAAA,EAAA,EAAE,CAAI,CAAA,EAAA;AAAA,IACxE,MAAQ,EAAA,KAAA;AAAA,IACR,OAAS,EAAA;AAAA,MACP,aAAA,EAAe,iBAAiB,MAAM,CAAA;AAAA,MACtC,MAAQ,EAAA,kBAAA;AAAA,KACV;AAAA,GACD,CAAA,CAAA;AACD,EAAI,IAAA,QAAA,CAAS,WAAW,GAAK,EAAA;AAC3B,IAAA,MAAM,KAAM,CAAA,CAAA,EAAG,QAAS,CAAA,MAAM,CAAE,CAAA,CAAA,CAAA;AAAA,GAClC;AACA,EAAM,MAAA,YAAA,GAAe,MAAM,QAAA,CAAS,IAAK,EAAA,CAAA;AACzC,EAAA,OAAO,EAAE,IAAM,EAAA,YAAA,CAAa,IAAM,EAAA,KAAA,EAAO,aAAa,GAAI,EAAA,CAAA;AAC5D,CAAA,CAAA;AAEO,MAAM,iBAAoB,GAAA,OAC/B,UACA,EAAA,UAAA,EACA,OACA,MACqB,KAAA;AACrB,EAAA,MAAM,MAAM,eAAgB,CAAA,EAAE,SAAS,UAAY,EAAA,UAAA,EAAY,OAAO,CAAA,CAAA;AACtE,EAAA,MAAM,WAAW,MAAMA,sBAAA;AAAA,IACrB,CAAG,EAAA,kBAAA,CAAmB,MAAM,CAAC,cAAc,GAAG,CAAA,CAAA;AAAA,IAC9C;AAAA,MACE,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,aAAA,EAAe,iBAAiB,MAAM,CAAA;AAAA,QACtC,MAAQ,EAAA,kBAAA;AAAA,OACV;AAAA,KACF;AAAA,GACA,CAAA,IAAA,CAAK,CAAQ,IAAA,KAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AAC1B,EAAA,OAAO,QAAS,CAAA,MAAA,CAAA;AAClB,CAAA,CAAA;AA8BO,MAAM,UAAa,GAAA,OACxB,MACA,EAAA,QAAA,EACA,OACqB,KAAA;AACrB,EAAA,MAAM,WAAW,MAAMA,sBAAA,CAAM,GAAG,kBAAmB,CAAA,MAAM,CAAC,CAAU,MAAA,CAAA,EAAA;AAAA,IAClE,MAAQ,EAAA,MAAA;AAAA,IACR,IAAA,EAAM,KAAK,SAAU,CAAA,EAAE,KAAK,QAAU,EAAA,GAAG,SAAS,CAAA;AAAA,IAClD,OAAS,EAAA;AAAA,MACP,aAAA,EAAe,iBAAiB,MAAM,CAAA;AAAA,MACtC,MAAQ,EAAA,kBAAA;AAAA,MACR,cAAgB,EAAA,kBAAA;AAAA,KAClB;AAAA,GACD,CAAE,CAAA,IAAA,CAAK,CAAQ,IAAA,KAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AAC3B,EAAA,OAAO,QAAS,CAAA,MAAA,CAAA;AAClB,EAAA;AAEO,MAAM,oBAAuB,GAAA,OAClC,UACA,EAAA,YAAA,EACA,MACqB,KAAA;AACrB,EAAA,MAAM,MAAM,eAAgB,CAAA;AAAA,IAC1B,OAAS,EAAA,UAAA;AAAA,IACT,UAAA,EAAY,CAAC,YAAY,CAAA;AAAA,GAC1B,CAAA,CAAA;AACD,EAAA,MAAM,WAAW,MAAMA,sBAAA;AAAA,IACrB,CAAG,EAAA,kBAAA,CAAmB,MAAM,CAAC,cAAc,GAAG,CAAA,CAAA;AAAA,IAC9C;AAAA,MACE,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,aAAA,EAAe,iBAAiB,MAAM,CAAA;AAAA,QACtC,MAAQ,EAAA,kBAAA;AAAA,OACV;AAAA,KACF;AAAA,GACA,CAAA,IAAA,CAAK,CAAQ,IAAA,KAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AAC1B,EAAA,OAAO,QAAS,CAAA,MAAA,CAAA;AAClB,CAAA,CAAA;AAEsB,eAAA,gBAAA,CAAiB,KAAa,MAAgB,EAAA;AAClE,EAAM,MAAA,QAAA,GAAW,MAAMA,sBAAA,CAAM,GAAK,EAAA;AAAA,IAChC,MAAQ,EAAA,KAAA;AAAA,IACR,OAAS,EAAA;AAAA,MACP,aAAA,EAAe,iBAAiB,MAAM,CAAA;AAAA,KACxC;AAAA,GACD,CAAA,CAAA;AACD,EAAO,OAAA,QAAA,CAAA;AACT;;ACnIO,MAAM,kBAAqB,GAAA,OAChC,UACA,EAAA,MAAA,EACA,KACqB,KAAA;AACrB,EAAI,IAAA,eAAA,CAAA;AAEJ,EAAmB,eAAA,GAAA,MAAM,KAAM,CAAA,GAAA,CAAI,UAAU,CAAA,CAAA;AAE7C,EAAI,IAAA,eAAA;AAAiB,IAAO,OAAA,eAAA,CAAA;AAE5B,EAAI,IAAA;AACF,IAAkB,eAAA,GAAA,MAAM,cAAe,CAAA,UAAA,EAAY,MAAM,CAAA,CAAA;AACzD,IAAM,KAAA,CAAA,GAAA,CAAI,YAAY,eAAe,CAAA,CAAA;AAAA,WAC9B,GAAU,EAAA;AACjB,IAAI,IAAA,GAAA,CAAI,YAAY,GAAK,EAAA;AACvB,MAAM,MAAA,KAAA;AAAA,QACJ,CAA8C,2CAAA,EAAA,UAAU,CAAgB,aAAA,EAAA,GAAA,CAAI,OAAO,CAAA,CAAA;AAAA,OACrF,CAAA;AAAA,KACF;AAAA,GACF;AACA,EAAO,OAAA,eAAA,CAAA;AACT,CAAA,CAAA;AAEa,MAAA,yBAAA,GAA4B,OACvC,WAAA,EACA,MACsB,KAAA;AACtB,EAAA,MAAM,UAAoB,EAAC,CAAA;AAE3B,EAAA,KAAA,MAAW,UAAU,WAAa,EAAA;AAChC,IAAI,IAAA;AACF,MAAA,MAAM,QAAW,GAAA,MAAM,aAAc,CAAA,MAAA,EAAQ,MAAM,CAAA,CAAA;AACnD,MAAA,OAAA,CAAQ,KAAK,QAAQ,CAAA,CAAA;AAAA,aACd,GAAU,EAAA;AACjB,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,CAAG,EAAA,GAAA,CAAI,OAAO,CAAA,wCAAA,EAA2C,MAAM,CAAA,CAAA;AAAA,OACjE,CAAA;AAAA,KACF;AAAA,GACF;AACA,EAAO,OAAA,OAAA,CAAA;AACT,CAAA,CAAA;AAEO,MAAM,oBAAuB,GAAA,OAClC,UACA,EAAA,UAAA,EACA,SACA,MACgC,KAAA;AAChC,EAAA,OAAO,MAAM,OAAQ,CAAA,GAAA;AAAA,IACnB,OAAA,CAAQ,GAAI,CAAA,OAAM,MAAW,MAAA;AAAA,MAC3B,MAAM,MAAO,CAAA,IAAA;AAAA,MACb,IAAM,EAAA,QAAA;AAAA,MACN,QAAQ,MAAM,iBAAA;AAAA,QACZ,UAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAO,CAAA,KAAA;AAAA,QACP,MAAA;AAAA,OACF;AAAA,KACA,CAAA,CAAA;AAAA,GACJ,CAAA;AACF,CAAA,CAAA;AAEO,MAAM,uBAA0B,GAAA,OACrC,UACA,EAAA,oBAAA,EACA,MACgC,KAAA;AAChC,EAAA,OAAO,MAAM,OAAQ,CAAA,GAAA;AAAA,IACnB,oBAAA,CAAqB,GAAI,CAAA,OAAM,YAAiB,MAAA;AAAA,MAC9C,IAAM,EAAA,YAAA;AAAA,MACN,IAAM,EAAA,WAAA;AAAA,MACN,MAAQ,EAAA,MAAM,oBAAqB,CAAA,UAAA,EAAY,cAAc,MAAM,CAAA;AAAA,KACnE,CAAA,CAAA;AAAA,GACJ,CAAA;AACF,CAAA;;AChFa,MAAA,cAAA,GAAiB,CAAC,MAAmB,KAAA;AAChD,EAAM,MAAA,MAAA,GAAS,wBAAwB,MAAM,CAAA,CAAA;AAE7C,EAAA,MAAM,oBAAuB,GAAA,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,0CAAgB,CAAA,CAAA,CAAA;AAC1D,EAAA,MAAM,oBAAuB,GAAA,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,yCAAe,CAAA,CAAA,CAAA;AACzD,EAAA,MAAM,iBAAoB,GAAA,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,sCAAY,CAAA,CAAA,CAAA;AACnD,EAAA,MAAM,wBAA2B,GAAA,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,gDAAsB,CAAA,CAAA,CAAA;AAGpE,EAAM,MAAA,yBAAA,GAA4B,GAAG,MAAM,CAAA,UAAA,CAAA,CAAA;AAE3C,EAAO,OAAA;AAAA,IACL,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,iBAAA;AAAA,IACA,wBAAA;AAAA,IACA,yBAAA;AAAA,GACF,CAAA;AACF,CAAA;;AC+CA,MAAM,cAAc,GAAO,GAAA,EAAA,CAAA;AAO3B,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAA,MAAM,EAAE,IAAA,EAAM,QAAS,EAAA,GAAIC,uCAAyB,OAAO,CAAA,CAAA;AAC3D,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAQ,EAAA,SAAA,EAAc,GAAA,OAAA,CAAA;AACtC,EAAA,MAAMC,kBAAgB,IAAIC,2BAAA,CAAc,EAAE,YAAA,EAAc,WAAW,CAAA,CAAA;AACnE,EAAA,MAAA,CAAO,KAAK,qCAAqC,CAAA,CAAA;AAEjD,EAAA,MAAM,cACJC,0BAAa,CAAA,UAAA,CAAW,MAAM,CAAA,CAAE,UAAU,gBAAgB,CAAA,CAAA;AAC5D,EAAA,MAAM,QAAQ,WAAY,CAAA,SAAA,CAAU,EAAE,UAAA,EAAY,aAAa,CAAA,CAAA;AAE/D,EAAA,MAAM,SAASC,uBAAO,EAAA,CAAA;AACtB,EAAO,MAAA,CAAA,GAAA,CAAIC,wBAAQ,CAAA,IAAA,EAAM,CAAA,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,CAAA;AAAA,GAC/B,CAAA,CAAA;AAED,EAAO,MAAA,CAAA,GAAA;AAAA,IACL,kDAAA;AAAA,IACA,OAAO,SAAS,QAAa,KAAA;AAtGjC,MAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AAuGM,MAAA,MAAM,EAAE,IAAA,EAAM,SAAW,EAAA,IAAA,KAAS,OAAQ,CAAA,MAAA,CAAA;AAC1C,MAAA,MAAM,YAAYC,+BAAmB,CAAA,EAAE,IAAM,EAAA,SAAA,EAAW,MAAM,CAAA,CAAA;AAC9D,MAAA,MAAM,EAAE,KAAA,EAAU,GAAA,MAAM,KAAK,qBAAsB,CAAA;AAAA,QACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAyB,EAAA;AAAA,QAChD,cAAgB,EAAA,SAAA;AAAA,OACjB,CAAA,CAAA;AACD,MAAA,MAAM,SAAS,MAAML,eAAA,CAAc,eAAe,SAAW,EAAA,EAAE,OAAO,CAAA,CAAA;AACtE,MAAM,MAAA;AAAA,QACJ,oBAAA;AAAA,QACA,oBAAA;AAAA,QACA,iBAAA;AAAA,QACA,wBAAA;AAAA,QACA,yBAAA;AAAA,OACF,GAAI,eAAe,MAAM,CAAA,CAAA;AAEzB,MAAA,IAAI,CAAC,MAAQ,EAAA;AACX,QAAO,MAAA,CAAA,IAAA,CAAK,CAAuB,oBAAA,EAAA,SAAS,CAAE,CAAA,CAAA,CAAA;AAC9C,QACG,QAAA,CAAA,MAAA,CAAO,GAAG,CACV,CAAA,IAAA,CAAK,EAAE,KAAO,EAAA,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,CAAA,CAAA;AACrD,QAAA,OAAA;AAAA,OACF;AAEA,MAAA,MAAM,cACJ,EAAO,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,QAAA,CAAS,gBAAhB,IAA8B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,KAA9B,mBAAqD,KAAM,CAAA,GAAA,CAAA,CAAA;AAE7D,MAAA,IAAI,CAAC,UAAY,EAAA;AACf,QAAM,MAAA,KAAA,GAAQ,gDAAgD,SAAS,CAAA,CAAA,CAAA;AACvE,QAAA,MAAA,CAAO,KAAK,KAAK,CAAA,CAAA;AACjB,QAAA,QAAA,CAAS,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAC/B,QAAA,OAAA;AAAA,OACF;AAEA,MAAI,IAAA,eAAA,CAAA;AAEJ,MAAI,IAAA;AACF,QAAA,eAAA,GAAkB,MAAM,kBAAA;AAAA,UACtB,WAAW,CAAC,CAAA;AAAA,UACZ,MAAA;AAAA,UACA,KAAA;AAAA,SACF,CAAA;AAAA,eACO,GAAU,EAAA;AACjB,QAAO,MAAA,CAAA,KAAA;AAAA,UACL,+BAA+B,UAAW,CAAA,CAAC,CAAC,CAAA,EAAA,EAAK,IAAI,OAAO,CAAA,CAAA;AAAA,SAC9D,CAAA;AACA,QAAS,QAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,UACxB,KAAO,EAAA,CAAA,+BAAA,EAAkC,UAAW,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA,SACvD,CAAA,CAAA;AACD,QAAA,OAAA;AAAA,OACF;AAEA,MAAI,IAAA,UAAA,CAAA;AAEJ,MAAI,IAAA;AACF,QAAA,MAAM,WAAc,GAAA,MAAM,QAAS,CAAA,WAAA,CAAY,OAAS,EAAA;AAAA,UACtD,KAAA,EAAO,CAAC,MAAM,CAAA;AAAA,SACf,CAAA,CAAA;AACD,QAAM,MAAA,YAAA,GAAe,YAAY,SAAU,CAAA,aAAA,CAAA;AAE3C,QAAc,UAAA,GAAA,MAAMA,eAAc,CAAA,cAAA,CAAe,YAAc,EAAA;AAAA,UAC7D,KAAA;AAAA,SACD,CAAA,CAAA;AAAA,eACM,GAAK,EAAA;AACZ,QAAA,MAAA,CAAO,KAAK,8BAA8B,CAAA,CAAA;AAAA,OAC5C;AAEA,MAAA,IAAI,UAAoB,EAAC,CAAA;AAEzB,MAAA,MAAM,cACJ,GAAA,CAAA,EAAA,GAAA,MAAA,CAAO,QAAS,CAAA,WAAA,KAAhB,IAA8B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,wBAAA,CAAA,CAAA;AAEhC,MAAU,OAAA,GAAA,wBAAA,CAAyB,MAAQ,EAAA,UAAA,EAAY,cAAc,CAAA,CAAA;AAErE,MAAA,MAAM,2BACJ,EAAO,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,QAAA,CAAS,gBAAhB,IAA8B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,iBAAA,CAAA,KAA9B,mBAAkD,KAAM,CAAA,GAAA,CAAA,CAAA;AAE1D,MAAA,IAAI,uBAAyB,EAAA;AAC3B,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,GAAI,MAAM,yBAA0B,CAAA,uBAAA,EAAyB,MAAM,CAAA;AAAA,SACrE,CAAA;AAAA,OACF;AAEA,MAAI,IAAA,UAAA,GAAA,CACF,EAAO,GAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,QAAA,CAAS,WAAhB,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAA8B,0BAA9B,IAAqD,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,CAAM,GAA3D,CAAA,KAAA,IAAA,GAAA,EAAA,GAAmE,EAAC,CAAA;AACtE,MAAA,IAAI,SAAS,MAAM,oBAAA;AAAA,QACjB,WAAW,CAAC,CAAA;AAAA,QACZ,UAAA;AAAA,QACA,OAAA;AAAA,QACA,MAAA;AAAA,OACF,CAAA;AAGA,MAAA,UAAA,GAAa,UAAW,CAAA,MAAA;AAAA,QACtB,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,MAAA,CAAO,SAAS,WAAhB,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAA8B,+BAA9B,IAA0D,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,CAAM,GAAhE,CAAA,KAAA,IAAA,GAAA,EAAA,GACE,EAAC;AAAA,OACL,CAAA;AAEA,MAAA,IAAI,UAAY,EAAA;AACd,QAAA,MAAM,kBAAkB,MAAM,uBAAA;AAAA,UAC5B,WAAW,CAAC,CAAA;AAAA,UACZ,UAAA;AAAA,UACA,MAAA;AAAA,SACF,CAAA;AACA,QAAS,MAAA,GAAA,MAAA,CAAO,OAAO,eAAe,CAAA,CAAA;AAAA,OACxC;AAEA,MAAA,MAAM,YAA6B,GAAA;AAAA,QACjC,OAAS,EAAA,eAAA;AAAA,QACT,IAAM,EAAA,MAAA;AAAA,OACR,CAAA;AACA,MAAA,QAAA,CAAS,KAAK,YAAY,CAAA,CAAA;AAAA,KAC5B;AAAA,GACF,CAAA;AAEA,EAAO,MAAA,CAAA,GAAA;AAAA,IACL,8CAAA;AAAA,IACA,OAAO,SAAS,QAAa,KAAA;AA3NjC,MAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AA4NM,MAAA,MAAM,EAAE,IAAA,EAAM,SAAW,EAAA,IAAA,KAAS,OAAQ,CAAA,MAAA,CAAA;AAC1C,MAAA,MAAM,YAAYK,+BAAmB,CAAA,EAAE,IAAM,EAAA,SAAA,EAAW,MAAM,CAAA,CAAA;AAC9D,MAAA,MAAM,EAAE,KAAA,EAAU,GAAA,MAAM,KAAK,qBAAsB,CAAA;AAAA,QACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAyB,EAAA;AAAA,QAChD,cAAgB,EAAA,SAAA;AAAA,OACjB,CAAA,CAAA;AACD,MAAA,MAAM,SAAS,MAAML,eAAA,CAAc,eAAe,SAAW,EAAA,EAAE,OAAO,CAAA,CAAA;AACtE,MAAA,MAAM,EAAE,oBAAA,EAAyB,GAAA,cAAA,CAAe,MAAM,CAAA,CAAA;AAEtD,MAAA,IAAI,CAAC,MAAQ,EAAA;AACX,QAAO,MAAA,CAAA,IAAA,CAAK,CAAuB,oBAAA,EAAA,SAAS,CAAE,CAAA,CAAA,CAAA;AAC9C,QACG,QAAA,CAAA,MAAA,CAAO,GAAG,CACV,CAAA,IAAA,CAAK,EAAE,KAAO,EAAA,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,CAAA,CAAA;AACrD,QAAA,OAAA;AAAA,OACF;AAEA,MAAA,MAAM,cACJ,EAAO,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,QAAA,CAAS,gBAAhB,IAA8B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,KAA9B,mBAAqD,KAAM,CAAA,GAAA,CAAA,CAAA;AAE7D,MAAA,MAAM,kBAAkB,MAAM,kBAAA;AAAA,QAC5B,WAAW,CAAC,CAAA;AAAA,QACZ,MAAA;AAAA,QACA,KAAA;AAAA,OACF,CAAA;AAEA,MAAA,IAAI,CAAC,eAAiB,EAAA;AACpB,QAAA,MAAA,CAAO,MAAM,gCAAgC,CAAA,CAAA;AAC7C,QAAS,QAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,UACxB,KAAO,EAAA,CAAA,sCAAA,EAAyC,UAAW,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA,SAC9D,CAAA,CAAA;AACD,QAAA,OAAA;AAAA,OACF;AAEA,MAAM,MAAA,GAAA,GAAM,eAAgB,CAAA,UAAA,CAAW,OAAO,CAAA,CAAA;AAE9C,MAAA,MAAM,MAAS,GAAA,MAAM,gBAAiB,CAAA,GAAA,EAAK,MAAM,CAAA,CAAA;AAEjD,MAAM,MAAA,EAAA,GAAK,IAAIM,uBAAA,CAAO,WAAY,EAAA,CAAA;AAClC,MAAA,MAAM,GAAM,GAAA,MAAA,CAAO,OAAQ,CAAA,GAAA,CAAI,cAAc,CAAA,CAAA;AAE7C,MAAS,QAAA,CAAA,SAAA,CAAU,cAAgB,EAAA,GAAA,IAAA,IAAA,GAAA,GAAA,GAAO,EAAE,CAAA,CAAA;AAC5C,MAAAA,uBAAA,CAAO,QAAS,CAAA,MAAA,CAAO,IAAM,EAAA,EAAA,EAAI,CAAO,GAAA,KAAA;AACtC,QAAA,IAAI,GAAK,EAAA;AACP,UAAA,MAAA,CAAO,MAAM,GAAG,CAAA,CAAA;AAChB,UAAA,QAAA,CAAS,WAAW,GAAG,CAAA,CAAA;AAAA,SACzB;AACA,QAAA,OAAA;AAAA,OACD,CAAA,CAAA;AACD,MAAA,EAAA,CAAG,KAAK,QAAQ,CAAA,CAAA;AAAA,KAClB;AAAA,GACF,CAAA;AACA,EAAO,MAAA,CAAA,GAAA,CAAIC,4BAAc,CAAA,CAAA;AACzB,EAAO,OAAA,MAAA,CAAA;AACT;;ACtQO,MAAM,sBAAsBC,oCAAoB,CAAA;AAAA,EACrD,QAAU,EAAA,gBAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,YAAYA,6BAAa,CAAA,UAAA;AAAA,QACzB,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,UAAUA,6BAAa,CAAA,QAAA;AAAA,OACzB;AAAA,MACA,MAAM,KAAK,EAAE,MAAA,EAAQ,QAAQ,SAAW,EAAA,UAAA,EAAY,IAAM,EAAA,QAAA,EAAY,EAAA;AACpE,QAAW,UAAA,CAAA,GAAA;AAAA,UACT,MAAM,YAAa,CAAA;AAAA,YACjB,MAAA,EAAQC,oCAAsB,MAAM,CAAA;AAAA,YACpC,MAAA;AAAA,YACA,SAAA;AAAA,YACA,IAAA;AAAA,YACA,QAAA;AAAA,WACD,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACF,CAAC;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-backstage/plugin-jira-dashboard-backend",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "main": "dist/index.cjs.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -23,13 +23,13 @@
23
23
  "postpack": "backstage-cli package postpack"
24
24
  },
25
25
  "dependencies": {
26
- "@axis-backstage/plugin-jira-dashboard-common": "^1.0.1",
27
- "@backstage/backend-common": "^0.21.7",
28
- "@backstage/backend-plugin-api": "^0.6.17",
29
- "@backstage/catalog-client": "^1.6.4",
30
- "@backstage/catalog-model": "^1.4.5",
26
+ "@axis-backstage/plugin-jira-dashboard-common": "^1.2.0",
27
+ "@backstage/backend-common": "^0.22.0",
28
+ "@backstage/backend-plugin-api": "^0.6.18",
29
+ "@backstage/catalog-client": "^1.6.5",
30
+ "@backstage/catalog-model": "^1.5.0",
31
31
  "@backstage/config": "^1.2.0",
32
- "@backstage/plugin-auth-node": "^0.4.12",
32
+ "@backstage/plugin-auth-node": "^0.4.13",
33
33
  "@backstage/plugin-permission-common": "^0.7.13",
34
34
  "@types/express": "*",
35
35
  "express": "^4.17.1",
@@ -39,7 +39,8 @@
39
39
  "yn": "^4.0.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@backstage/cli": "^0.26.3",
42
+ "@backstage/backend-test-utils": "^0.3.8",
43
+ "@backstage/cli": "^0.26.6",
43
44
  "@types/supertest": "^2.0.12",
44
45
  "msw": "^1.0.0",
45
46
  "supertest": "^6.2.4"