@axis-backstage/plugin-jira-dashboard-backend 4.0.2 → 4.0.3
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 +7 -0
- package/dist/index.cjs.js +22 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +40 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @axis-backstage/plugin-jira-dashboard-backend
|
|
2
2
|
|
|
3
|
+
## 4.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1b47182: The backend now exports the `JiraConfig` class. This is needed to create config
|
|
8
|
+
instances for the `searchJira`function.
|
|
9
|
+
|
|
3
10
|
## 4.0.2
|
|
4
11
|
|
|
5
12
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -528,6 +528,9 @@ const JIRA_CONFIG_USER_EMAIL_SUFFIX = "userEmailSuffix";
|
|
|
528
528
|
const JIRA_CONFIG_ANNOTATION = "annotationPrefix";
|
|
529
529
|
class JiraConfig {
|
|
530
530
|
instances = {};
|
|
531
|
+
/**
|
|
532
|
+
* The annotation prefix to use for Jira annotations
|
|
533
|
+
*/
|
|
531
534
|
annotationPrefix;
|
|
532
535
|
constructor(config) {
|
|
533
536
|
const jira = config.getConfig("jiraDashboard");
|
|
@@ -559,6 +562,9 @@ class JiraConfig {
|
|
|
559
562
|
};
|
|
560
563
|
}
|
|
561
564
|
}
|
|
565
|
+
/**
|
|
566
|
+
* Create a JiraConfig from the root config
|
|
567
|
+
*/
|
|
562
568
|
static fromConfig(config) {
|
|
563
569
|
return new JiraConfig(config);
|
|
564
570
|
}
|
|
@@ -571,20 +577,35 @@ class JiraConfig {
|
|
|
571
577
|
}
|
|
572
578
|
return instance;
|
|
573
579
|
}
|
|
580
|
+
/**
|
|
581
|
+
* Returns the configuration all instances
|
|
582
|
+
*/
|
|
574
583
|
getInstances() {
|
|
575
584
|
return Object.getOwnPropertyNames(this.instances);
|
|
576
585
|
}
|
|
586
|
+
/**
|
|
587
|
+
* Get the jira config for a specific instance
|
|
588
|
+
*/
|
|
577
589
|
getInstance(instanceName) {
|
|
578
590
|
return this.forInstance(instanceName ?? "default");
|
|
579
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Get the jira base url for a given instance
|
|
594
|
+
*/
|
|
580
595
|
resolveJiraBaseUrl(instanceName) {
|
|
581
596
|
const instance = this.forInstance(instanceName);
|
|
582
597
|
return instance.baseUrl;
|
|
583
598
|
}
|
|
599
|
+
/**
|
|
600
|
+
* Get the auth token for a given instance
|
|
601
|
+
*/
|
|
584
602
|
resolveJiraToken(instanceName) {
|
|
585
603
|
const instance = this.forInstance(instanceName);
|
|
586
604
|
return instance.token;
|
|
587
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* Get the email suffice for a given instance
|
|
608
|
+
*/
|
|
588
609
|
resolveUserEmailSuffix(instanceName) {
|
|
589
610
|
const instance = this.forInstance(instanceName);
|
|
590
611
|
return instance.userEmailSuffix;
|
|
@@ -633,6 +654,7 @@ const jiraDashboardPlugin = backendPluginApi.createBackendPlugin({
|
|
|
633
654
|
}
|
|
634
655
|
});
|
|
635
656
|
|
|
657
|
+
exports.JiraConfig = JiraConfig;
|
|
636
658
|
exports.default = jiraDashboardPlugin;
|
|
637
659
|
exports.jqlQueryBuilder = jqlQueryBuilder;
|
|
638
660
|
exports.searchJira = searchJira;
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/lib.ts","../src/queries.ts","../src/api.ts","../src/service/service.ts","../src/service/defaultValues.ts","../src/filters.ts","../src/service/router.ts","../src/config.ts","../src/plugin.ts"],"sourcesContent":["import {\n COMPONENTS_NAME,\n PROJECT_KEY_NAME,\n FILTERS_NAME,\n INCOMING_ISSUES_STATUS,\n} from '@axis-backstage/plugin-jira-dashboard-common';\n\nimport type { ConfigInstance, JiraConfig } from './config';\n\nexport const getAnnotations = (config: JiraConfig) => {\n const prefix = config.annotationPrefix;\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\nexport interface JiraProject {\n instance: ConfigInstance;\n fullProjectKey: string;\n projectKey: string;\n}\n\n/**\n * Splits a project key \"instance/key\" into a config instance and a project\n * key, falling back to 'default' for unprefixed keys\n */\nexport function splitProjectKey(\n config: JiraConfig,\n fullProjectKey: string,\n): JiraProject {\n const [instance, projectKey] = fullProjectKey.split('/');\n if (!projectKey) {\n // No specific instance specified - use default\n return {\n instance: config.getInstance(),\n fullProjectKey,\n projectKey: instance,\n };\n }\n\n return {\n instance: config.getInstance(instance),\n fullProjectKey,\n projectKey,\n };\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 * @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 fetch, { RequestInit } from 'node-fetch';\nimport {\n Filter,\n Issue,\n Project,\n JiraQueryResults,\n} from '@axis-backstage/plugin-jira-dashboard-common';\n\nimport type { ConfigInstance } from './config';\nimport { jqlQueryBuilder } from './queries';\nimport type { JiraProject } from './lib';\nimport { ResponseError } from '@backstage/errors';\n\nexport const getProjectInfo = async (\n project: JiraProject,\n): Promise<Project> => {\n const { projectKey, instance } = project;\n const response = await callApi(\n instance,\n `${instance.baseUrl}project/${projectKey}`,\n {\n method: 'GET',\n headers: {\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 instance: ConfigInstance,\n): Promise<Filter> => {\n const response = await callApi(instance, `${instance.baseUrl}filter/${id}`, {\n method: 'GET',\n headers: {\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 project: JiraProject,\n components: string[],\n query: string,\n): Promise<Issue[]> => {\n const { projectKey, instance } = project;\n const jql = jqlQueryBuilder({ project: projectKey, components, query });\n const response = await callApi(\n instance,\n `${instance.baseUrl}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\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 * Asynchronously searches for Jira issues using JQL.\n *\n * For more information about the available options, see the API 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 * @public\n */\nexport const searchJira = async (\n instance: ConfigInstance,\n jqlQuery: string,\n options: SearchOptions,\n): Promise<JiraQueryResults> => {\n const response = await callApi(instance, `${instance.baseUrl}search`, {\n method: 'POST',\n body: JSON.stringify({ jql: jqlQuery, ...options }),\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const jsonResponse = await response.json();\n return jsonResponse as JiraQueryResults;\n};\n\nexport const getIssuesByComponent = async (\n project: JiraProject,\n componentKey: string,\n): Promise<Issue[]> => {\n const { projectKey, instance } = project;\n\n const jql = jqlQueryBuilder({\n project: projectKey,\n components: [componentKey],\n });\n const response = await callApi(\n instance,\n `${instance.baseUrl}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n },\n ).then(resp => resp.json());\n return response.issues;\n};\n\nexport async function getProjectAvatar(url: string, instance: ConfigInstance) {\n return callApi(instance, url);\n}\n\n/**\n * Call the Jira API using fetch.\n *\n * This function injects the auth token and custom headers.\n */\nasync function callApi(\n instance: ConfigInstance,\n url: string,\n init?: RequestInit,\n) {\n const requestInit = init ?? { method: 'GET' };\n\n // Inject custom headers from config, Authorization token and headers from the\n // request\n requestInit.headers = {\n ...instance.headers,\n Authorization: instance.token,\n ...requestInit.headers,\n };\n return fetch(url, requestInit);\n}\n","import { CacheService } from '@backstage/backend-plugin-api';\nimport {\n type Filter,\n Issue,\n type JiraDataResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport {\n getFilterById,\n getIssuesByComponent,\n getIssuesByFilter,\n getProjectInfo,\n searchJira,\n SearchOptions,\n} from '../api';\nimport { jqlQueryBuilder } from '../queries';\nimport type { ConfigInstance } from '../config';\nimport { JiraProject } from '../lib';\n\nexport const getProjectResponse = async (\n project: JiraProject,\n cache: CacheService,\n): Promise<Project> => {\n let projectResponse: Project;\n\n projectResponse = (await cache.get(project.fullProjectKey)) as Project;\n\n if (projectResponse) {\n return projectResponse as Project;\n }\n\n try {\n projectResponse = await getProjectInfo(project);\n cache.set(project.fullProjectKey, projectResponse);\n } catch (err: any) {\n if (err.message !== 200) {\n throw Error(\n `Failed to get project info for project key ${project.fullProjectKey} with error: ${err.message}`,\n );\n }\n }\n return projectResponse;\n};\n\nexport const getJqlResponse = async (\n jql: string,\n config: ConfigInstance,\n cache: CacheService,\n searchOptions: SearchOptions,\n): Promise<Issue[]> => {\n let issuesResponse: Issue[];\n\n const cacheKey = `${config.baseUrl} ${jql}`;\n\n issuesResponse = (await cache.get(cacheKey)) as Issue[];\n\n if (issuesResponse) {\n return issuesResponse;\n }\n\n try {\n issuesResponse = (await searchJira(config, jql, searchOptions)).issues;\n cache.set(cacheKey, issuesResponse);\n } catch (err: any) {\n if (err.message !== 200) {\n throw Error(\n `Failed to get issues for JQL ${jql} with error: ${err.message}`,\n );\n }\n }\n return issuesResponse;\n};\n\nexport const getUserIssues = async (\n username: string,\n maxResults: number,\n config: ConfigInstance,\n cache: CacheService,\n): Promise<Issue[]> => {\n const jql = `assignee = \"${username}\" AND resolution = Unresolved ORDER BY priority DESC, updated DESC`;\n\n return getJqlResponse(jql, config, cache, {\n fields: [\n 'key',\n 'issuetype',\n 'summary',\n 'status',\n 'priority',\n 'created',\n 'updated',\n ],\n maxResults,\n });\n};\n\nexport const getFiltersFromAnnotations = async (\n annotations: string[],\n config: ConfigInstance,\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 project: JiraProject,\n components: string[],\n filters: Filter[],\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n filters.map(async filter => ({\n name: filter.name,\n query: jqlQueryBuilder({\n project: project.projectKey,\n components,\n query: filter.query,\n }),\n type: 'filter',\n issues: await getIssuesByFilter(project, components, filter.query),\n })),\n );\n};\n\nexport const getIssuesFromComponents = async (\n project: JiraProject,\n componentAnnotations: string[],\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n componentAnnotations.map(async componentKey => ({\n name: componentKey,\n query: jqlQueryBuilder({\n project: project.projectKey,\n components: [componentKey],\n }),\n type: 'component',\n issues: await getIssuesByComponent(project, componentKey),\n })),\n );\n};\n","export const DEFAULT_TTL = 1000 * 60;\n\nexport const DEFAULT_MAX_RESULTS_USER_ISSUES = 10;\n","import { Filter } from '@axis-backstage/plugin-jira-dashboard-common';\nimport { UserEntity } from '@backstage/catalog-model';\nimport { ConfigInstance } from './config';\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\n/**\n * Get the username value for Jira assignee from the user entity.\n * If the email suffix is defined, the result combines `metadata.name` with the email suffix - otherwise if the user entity has a profile email or the metadata name is used.\n * Otherwise, the user entity name will be used.\n * @param config appConfig configuration\n * @param userEntity user entity instance\n */\nexport const getAssigneUser = (\n instance: ConfigInstance,\n userEntity: UserEntity,\n): string => {\n const emailSuffixConfig = instance.userEmailSuffix;\n\n return emailSuffixConfig\n ? `${userEntity.metadata.name}${emailSuffixConfig}`\n : userEntity.spec?.profile?.email || userEntity.metadata.name;\n};\n\nconst getAssignedToMeFilter = (\n userEntity: UserEntity,\n instance: ConfigInstance,\n): Filter => {\n const email = getAssigneUser(instance, userEntity);\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 instance: ConfigInstance,\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, instance);\n\n return [openFilter, incomingFilter, assigneeToMeFilter];\n};\n","import express from 'express';\nimport Router from 'express-promise-router';\nimport stream from 'stream';\n\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { CacheManager } from '@backstage/backend-defaults/cache';\nimport {\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n RootConfigService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { stringifyEntityRef, UserEntity } from '@backstage/catalog-model';\nimport { CatalogClient } from '@backstage/catalog-client';\n\nimport {\n type Filter,\n type JiraResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\n\nimport { getAnnotations, splitProjectKey } from '../lib';\nimport {\n getFiltersFromAnnotations,\n getIssuesFromComponents,\n getIssuesFromFilters,\n getProjectResponse,\n getUserIssues,\n} from './service';\nimport { DEFAULT_MAX_RESULTS_USER_ISSUES, DEFAULT_TTL } from './defaultValues';\nimport { getAssigneUser, getDefaultFiltersForUser } from '../filters';\nimport { getProjectAvatar } from '../api';\nimport type { ConfigInstance, JiraConfig } from '../config';\n\nexport interface RouterOptions {\n /**\n * Implementation of Authentication Service\n */\n auth: AuthService;\n /**\n * Implementation of Logger Service\n */\n logger: LoggerService;\n /**\n * Implementation of Config Service\n */\n rootConfig: RootConfigService;\n /**\n * Parsed Jira config\n */\n config: JiraConfig;\n /**\n * Implementation of Discovery Service\n */\n discovery: DiscoveryService;\n /**\n * Implementation of Http Authentication Service\n */\n httpAuth: HttpAuthService;\n /**\n * Implementation of User Info Service\n */\n userInfo: UserInfoService;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, logger, rootConfig, config, discovery, httpAuth, userInfo } =\n options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\n const pluginCache =\n CacheManager.fromConfig(rootConfig).forPlugin('jira-dashboard');\n const cache = pluginCache.getClient({ defaultTtl: DEFAULT_TTL });\n logger.info('Initializing Jira Dashboard backend');\n\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\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 fullProjectKeys =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n if (!fullProjectKeys) {\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 const projects = fullProjectKeys.map(fullProjectKey =>\n splitProjectKey(config, fullProjectKey),\n );\n\n let projectResponse;\n\n try {\n projectResponse = await getProjectResponse(projects[0], cache);\n } catch (err: any) {\n logger.error(\n `Could not find Jira project ${projects[0].fullProjectKey}: ${err.message}`,\n );\n response.status(404).json({\n error: `No Jira project found with key ${projects[0].projectKey}`,\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(\n projects[0].instance,\n userEntity,\n incomingStatus,\n );\n\n const customFilterAnnotations =\n entity.metadata.annotations?.[filtersAnnotation]?.split(',')!;\n\n if (customFilterAnnotations) {\n filters.push(\n ...(await getFiltersFromAnnotations(\n customFilterAnnotations,\n projects[0].instance,\n )),\n );\n }\n\n let components =\n entity.metadata.annotations?.[componentsAnnotation]?.split(',') ?? [];\n let issues = await getIssuesFromFilters(projects[0], components, filters);\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 projects[0],\n components,\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('/dashboards/user-issues', async (request, response) => {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n\n // we ignore guest and service users, no issues in response\n if (!auth.isPrincipal(credentials, 'user')) {\n response.status(200).json([]);\n return;\n }\n\n const info = await userInfo.getUserInfo(credentials);\n\n const userEntity = (await catalogClient.getEntityByRef(info.userEntityRef, {\n token,\n })) as UserEntity;\n\n if (!userEntity) {\n const error = `User entity cannot be determined from ${info.userEntityRef}`;\n logger.info(error);\n response.status(400).json(error);\n return;\n }\n\n const getUserIssuesForInstance = async (instance: ConfigInstance) => {\n const username = getAssigneUser(instance, userEntity);\n\n const maxResults = Number(\n request.query.maxResults || DEFAULT_MAX_RESULTS_USER_ISSUES,\n );\n\n try {\n const issues = await getUserIssues(\n username,\n maxResults,\n instance,\n cache,\n );\n return { issues, error: undefined };\n } catch (error: any) {\n return { error };\n }\n };\n\n const issuesList = await Promise.all(\n config\n .getInstances()\n .map(instanceName =>\n getUserIssuesForInstance(config.getInstance(instanceName)),\n ),\n );\n\n const issues = issuesList.flatMap(list => list.issues ?? []);\n const errors = issuesList\n .flatMap(list => list.error)\n .filter((v): v is NonNullable<typeof v> => !!v);\n\n if (issues.length > 0 || errors.length === 0) {\n response.status(200).json(issues);\n } else {\n const messages =\n errors.length > 1\n ? `\\n ${errors.map(err => err.message).join('\\n ')}`\n : ` ${errors[0].message}`;\n\n logger.error(`Error during getting user issues:${messages}`);\n response.status(503).json({\n error: `Error during getting user issues:${messages}`,\n });\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 fullProjectKeys =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n if (!fullProjectKeys) {\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 const projects = fullProjectKeys.map(fullProjectKey =>\n splitProjectKey(config, fullProjectKey),\n );\n\n const projectResponse = await getProjectResponse(projects[0], cache);\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 ${projects[0].projectKey}`,\n });\n return;\n }\n\n const url = projectResponse.avatarUrls['48x48'];\n\n const avatar = await getProjectAvatar(url, projects[0].instance);\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\n const middleware = MiddlewareFactory.create({ logger, config: rootConfig });\n\n router.use(middleware.error());\n return router;\n}\n","import { ConflictError, ServiceUnavailableError } from '@backstage/errors';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\n\ntype Config = ReturnType<RootConfigService['getConfig']>;\n\nfunction parseHeaders(config: Config | undefined): Record<string, string> {\n if (!config) {\n return {};\n }\n return Object.fromEntries(\n config.keys().map(key => {\n const value = config.getString(key);\n return [key, value] as const;\n }),\n );\n}\n\n/**\n * The configuration of a Jira instance\n *\n * @public\n */\nexport type ConfigInstance = {\n token: string;\n headers: Record<string, string>;\n baseUrl: string;\n userEmailSuffix?: string;\n};\n\nconst JIRA_CONFIG_BASE_URL = 'baseUrl';\nconst JIRA_CONFIG_TOKEN = 'token';\nconst JIRA_CONFIG_HEADERS = 'headers';\nconst JIRA_CONFIG_USER_EMAIL_SUFFIX = 'userEmailSuffix';\nconst JIRA_CONFIG_ANNOTATION = 'annotationPrefix';\n\nexport class JiraConfig {\n private instances: Record<string, ConfigInstance> = {};\n public readonly annotationPrefix: string;\n\n private constructor(config: RootConfigService) {\n const jira = config.getConfig('jiraDashboard');\n\n this.annotationPrefix =\n jira.getOptionalString(JIRA_CONFIG_ANNOTATION) ?? 'jira.com';\n\n const instances = jira.getOptionalConfigArray('instances');\n if (instances) {\n // Multiple instances form\n instances.forEach(inst => {\n const name = inst.getString('name');\n if (Object.getOwnPropertyNames(this.instances).includes(name)) {\n throw new ConflictError(\n `Duplicate jiraDashboard instances: '${name}'`,\n );\n }\n\n this.instances[name] = {\n token: inst.getString(JIRA_CONFIG_TOKEN),\n headers: parseHeaders(inst.getOptionalConfig(JIRA_CONFIG_HEADERS)),\n baseUrl: inst.getString(JIRA_CONFIG_BASE_URL),\n userEmailSuffix: inst.getOptionalString(\n JIRA_CONFIG_USER_EMAIL_SUFFIX,\n ),\n };\n });\n } else {\n // Default form\n this.instances.default = {\n token: jira.getString(JIRA_CONFIG_TOKEN),\n headers: parseHeaders(jira.getOptionalConfig(JIRA_CONFIG_HEADERS)),\n baseUrl: jira.getString(JIRA_CONFIG_BASE_URL),\n userEmailSuffix: jira.getOptionalString(JIRA_CONFIG_USER_EMAIL_SUFFIX),\n };\n }\n }\n\n public static fromConfig(config: RootConfigService): JiraConfig {\n return new JiraConfig(config);\n }\n\n private forInstance(instanceName: string) {\n const instance = this.instances[instanceName];\n if (!instance) {\n throw new ServiceUnavailableError(\n `No such jira instance '${instanceName}'`,\n );\n }\n return instance;\n }\n\n getInstances() {\n return Object.getOwnPropertyNames(this.instances);\n }\n\n getInstance(instanceName?: string): ConfigInstance {\n return this.forInstance(instanceName ?? 'default');\n }\n\n resolveJiraBaseUrl(instanceName: string): string {\n const instance = this.forInstance(instanceName);\n return instance.baseUrl;\n }\n\n resolveJiraToken(instanceName: string): string {\n const instance = this.forInstance(instanceName);\n return instance.token;\n }\n\n resolveUserEmailSuffix(instanceName: string): string | undefined {\n const instance = this.forInstance(instanceName);\n return instance.userEmailSuffix;\n }\n}\n","import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\nimport { JiraConfig } from './config';\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 auth: coreServices.auth,\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n rootConfig: coreServices.rootConfig,\n discovery: coreServices.discovery,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n },\n async init({\n auth,\n httpRouter,\n logger,\n rootConfig,\n discovery,\n httpAuth,\n userInfo,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n logger,\n rootConfig,\n config: JiraConfig.fromConfig(rootConfig),\n discovery,\n httpAuth,\n userInfo,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["PROJECT_KEY_NAME","COMPONENTS_NAME","FILTERS_NAME","INCOMING_ISSUES_STATUS","ResponseError","fetch","catalogClient","CatalogClient","CacheManager","cache","Router","express","stringifyEntityRef","issues","stream","MiddlewareFactory","ConflictError","ServiceUnavailableError","createBackendPlugin","coreServices"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/lib.ts","../src/queries.ts","../src/api.ts","../src/service/service.ts","../src/service/defaultValues.ts","../src/filters.ts","../src/service/router.ts","../src/config.ts","../src/plugin.ts"],"sourcesContent":["import {\n COMPONENTS_NAME,\n PROJECT_KEY_NAME,\n FILTERS_NAME,\n INCOMING_ISSUES_STATUS,\n} from '@axis-backstage/plugin-jira-dashboard-common';\n\nimport type { ConfigInstance, JiraConfig } from './config';\n\nexport const getAnnotations = (config: JiraConfig) => {\n const prefix = config.annotationPrefix;\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\nexport interface JiraProject {\n instance: ConfigInstance;\n fullProjectKey: string;\n projectKey: string;\n}\n\n/**\n * Splits a project key \"instance/key\" into a config instance and a project\n * key, falling back to 'default' for unprefixed keys\n */\nexport function splitProjectKey(\n config: JiraConfig,\n fullProjectKey: string,\n): JiraProject {\n const [instance, projectKey] = fullProjectKey.split('/');\n if (!projectKey) {\n // No specific instance specified - use default\n return {\n instance: config.getInstance(),\n fullProjectKey,\n projectKey: instance,\n };\n }\n\n return {\n instance: config.getInstance(instance),\n fullProjectKey,\n projectKey,\n };\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 * @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 fetch, { RequestInit } from 'node-fetch';\nimport {\n Filter,\n Issue,\n Project,\n JiraQueryResults,\n} from '@axis-backstage/plugin-jira-dashboard-common';\n\nimport type { ConfigInstance } from './config';\nimport { jqlQueryBuilder } from './queries';\nimport type { JiraProject } from './lib';\nimport { ResponseError } from '@backstage/errors';\n\nexport const getProjectInfo = async (\n project: JiraProject,\n): Promise<Project> => {\n const { projectKey, instance } = project;\n const response = await callApi(\n instance,\n `${instance.baseUrl}project/${projectKey}`,\n {\n method: 'GET',\n headers: {\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 instance: ConfigInstance,\n): Promise<Filter> => {\n const response = await callApi(instance, `${instance.baseUrl}filter/${id}`, {\n method: 'GET',\n headers: {\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 project: JiraProject,\n components: string[],\n query: string,\n): Promise<Issue[]> => {\n const { projectKey, instance } = project;\n const jql = jqlQueryBuilder({ project: projectKey, components, query });\n const response = await callApi(\n instance,\n `${instance.baseUrl}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\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 * Asynchronously searches for Jira issues using JQL.\n *\n * For more information about the available options, see the API 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 * @public\n */\nexport const searchJira = async (\n instance: ConfigInstance,\n jqlQuery: string,\n options: SearchOptions,\n): Promise<JiraQueryResults> => {\n const response = await callApi(instance, `${instance.baseUrl}search`, {\n method: 'POST',\n body: JSON.stringify({ jql: jqlQuery, ...options }),\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const jsonResponse = await response.json();\n return jsonResponse as JiraQueryResults;\n};\n\nexport const getIssuesByComponent = async (\n project: JiraProject,\n componentKey: string,\n): Promise<Issue[]> => {\n const { projectKey, instance } = project;\n\n const jql = jqlQueryBuilder({\n project: projectKey,\n components: [componentKey],\n });\n const response = await callApi(\n instance,\n `${instance.baseUrl}search?jql=${jql}`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n },\n ).then(resp => resp.json());\n return response.issues;\n};\n\nexport async function getProjectAvatar(url: string, instance: ConfigInstance) {\n return callApi(instance, url);\n}\n\n/**\n * Call the Jira API using fetch.\n *\n * This function injects the auth token and custom headers.\n */\nasync function callApi(\n instance: ConfigInstance,\n url: string,\n init?: RequestInit,\n) {\n const requestInit = init ?? { method: 'GET' };\n\n // Inject custom headers from config, Authorization token and headers from the\n // request\n requestInit.headers = {\n ...instance.headers,\n Authorization: instance.token,\n ...requestInit.headers,\n };\n return fetch(url, requestInit);\n}\n","import { CacheService } from '@backstage/backend-plugin-api';\nimport {\n type Filter,\n Issue,\n type JiraDataResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\nimport {\n getFilterById,\n getIssuesByComponent,\n getIssuesByFilter,\n getProjectInfo,\n searchJira,\n SearchOptions,\n} from '../api';\nimport { jqlQueryBuilder } from '../queries';\nimport type { ConfigInstance } from '../config';\nimport { JiraProject } from '../lib';\n\nexport const getProjectResponse = async (\n project: JiraProject,\n cache: CacheService,\n): Promise<Project> => {\n let projectResponse: Project;\n\n projectResponse = (await cache.get(project.fullProjectKey)) as Project;\n\n if (projectResponse) {\n return projectResponse as Project;\n }\n\n try {\n projectResponse = await getProjectInfo(project);\n cache.set(project.fullProjectKey, projectResponse);\n } catch (err: any) {\n if (err.message !== 200) {\n throw Error(\n `Failed to get project info for project key ${project.fullProjectKey} with error: ${err.message}`,\n );\n }\n }\n return projectResponse;\n};\n\nexport const getJqlResponse = async (\n jql: string,\n config: ConfigInstance,\n cache: CacheService,\n searchOptions: SearchOptions,\n): Promise<Issue[]> => {\n let issuesResponse: Issue[];\n\n const cacheKey = `${config.baseUrl} ${jql}`;\n\n issuesResponse = (await cache.get(cacheKey)) as Issue[];\n\n if (issuesResponse) {\n return issuesResponse;\n }\n\n try {\n issuesResponse = (await searchJira(config, jql, searchOptions)).issues;\n cache.set(cacheKey, issuesResponse);\n } catch (err: any) {\n if (err.message !== 200) {\n throw Error(\n `Failed to get issues for JQL ${jql} with error: ${err.message}`,\n );\n }\n }\n return issuesResponse;\n};\n\nexport const getUserIssues = async (\n username: string,\n maxResults: number,\n config: ConfigInstance,\n cache: CacheService,\n): Promise<Issue[]> => {\n const jql = `assignee = \"${username}\" AND resolution = Unresolved ORDER BY priority DESC, updated DESC`;\n\n return getJqlResponse(jql, config, cache, {\n fields: [\n 'key',\n 'issuetype',\n 'summary',\n 'status',\n 'priority',\n 'created',\n 'updated',\n ],\n maxResults,\n });\n};\n\nexport const getFiltersFromAnnotations = async (\n annotations: string[],\n config: ConfigInstance,\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 project: JiraProject,\n components: string[],\n filters: Filter[],\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n filters.map(async filter => ({\n name: filter.name,\n query: jqlQueryBuilder({\n project: project.projectKey,\n components,\n query: filter.query,\n }),\n type: 'filter',\n issues: await getIssuesByFilter(project, components, filter.query),\n })),\n );\n};\n\nexport const getIssuesFromComponents = async (\n project: JiraProject,\n componentAnnotations: string[],\n): Promise<JiraDataResponse[]> => {\n return await Promise.all(\n componentAnnotations.map(async componentKey => ({\n name: componentKey,\n query: jqlQueryBuilder({\n project: project.projectKey,\n components: [componentKey],\n }),\n type: 'component',\n issues: await getIssuesByComponent(project, componentKey),\n })),\n );\n};\n","export const DEFAULT_TTL = 1000 * 60;\n\nexport const DEFAULT_MAX_RESULTS_USER_ISSUES = 10;\n","import { Filter } from '@axis-backstage/plugin-jira-dashboard-common';\nimport { UserEntity } from '@backstage/catalog-model';\nimport { ConfigInstance } from './config';\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\n/**\n * Get the username value for Jira assignee from the user entity.\n * If the email suffix is defined, the result combines `metadata.name` with the email suffix - otherwise if the user entity has a profile email or the metadata name is used.\n * Otherwise, the user entity name will be used.\n * @param config appConfig configuration\n * @param userEntity user entity instance\n */\nexport const getAssigneUser = (\n instance: ConfigInstance,\n userEntity: UserEntity,\n): string => {\n const emailSuffixConfig = instance.userEmailSuffix;\n\n return emailSuffixConfig\n ? `${userEntity.metadata.name}${emailSuffixConfig}`\n : userEntity.spec?.profile?.email || userEntity.metadata.name;\n};\n\nconst getAssignedToMeFilter = (\n userEntity: UserEntity,\n instance: ConfigInstance,\n): Filter => {\n const email = getAssigneUser(instance, userEntity);\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 instance: ConfigInstance,\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, instance);\n\n return [openFilter, incomingFilter, assigneeToMeFilter];\n};\n","import express from 'express';\nimport Router from 'express-promise-router';\nimport stream from 'stream';\n\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { CacheManager } from '@backstage/backend-defaults/cache';\nimport {\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n RootConfigService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { stringifyEntityRef, UserEntity } from '@backstage/catalog-model';\nimport { CatalogClient } from '@backstage/catalog-client';\n\nimport {\n type Filter,\n type JiraResponse,\n type Project,\n} from '@axis-backstage/plugin-jira-dashboard-common';\n\nimport { getAnnotations, splitProjectKey } from '../lib';\nimport {\n getFiltersFromAnnotations,\n getIssuesFromComponents,\n getIssuesFromFilters,\n getProjectResponse,\n getUserIssues,\n} from './service';\nimport { DEFAULT_MAX_RESULTS_USER_ISSUES, DEFAULT_TTL } from './defaultValues';\nimport { getAssigneUser, getDefaultFiltersForUser } from '../filters';\nimport { getProjectAvatar } from '../api';\nimport type { ConfigInstance, JiraConfig } from '../config';\n\nexport interface RouterOptions {\n /**\n * Implementation of Authentication Service\n */\n auth: AuthService;\n /**\n * Implementation of Logger Service\n */\n logger: LoggerService;\n /**\n * Implementation of Config Service\n */\n rootConfig: RootConfigService;\n /**\n * Parsed Jira config\n */\n config: JiraConfig;\n /**\n * Implementation of Discovery Service\n */\n discovery: DiscoveryService;\n /**\n * Implementation of Http Authentication Service\n */\n httpAuth: HttpAuthService;\n /**\n * Implementation of User Info Service\n */\n userInfo: UserInfoService;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, logger, rootConfig, config, discovery, httpAuth, userInfo } =\n options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\n const pluginCache =\n CacheManager.fromConfig(rootConfig).forPlugin('jira-dashboard');\n const cache = pluginCache.getClient({ defaultTtl: DEFAULT_TTL });\n logger.info('Initializing Jira Dashboard backend');\n\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\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 fullProjectKeys =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n if (!fullProjectKeys) {\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 const projects = fullProjectKeys.map(fullProjectKey =>\n splitProjectKey(config, fullProjectKey),\n );\n\n let projectResponse;\n\n try {\n projectResponse = await getProjectResponse(projects[0], cache);\n } catch (err: any) {\n logger.error(\n `Could not find Jira project ${projects[0].fullProjectKey}: ${err.message}`,\n );\n response.status(404).json({\n error: `No Jira project found with key ${projects[0].projectKey}`,\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(\n projects[0].instance,\n userEntity,\n incomingStatus,\n );\n\n const customFilterAnnotations =\n entity.metadata.annotations?.[filtersAnnotation]?.split(',')!;\n\n if (customFilterAnnotations) {\n filters.push(\n ...(await getFiltersFromAnnotations(\n customFilterAnnotations,\n projects[0].instance,\n )),\n );\n }\n\n let components =\n entity.metadata.annotations?.[componentsAnnotation]?.split(',') ?? [];\n let issues = await getIssuesFromFilters(projects[0], components, filters);\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 projects[0],\n components,\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('/dashboards/user-issues', async (request, response) => {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n\n const credentials = await httpAuth.credentials(request, {\n allow: ['user'],\n });\n\n // we ignore guest and service users, no issues in response\n if (!auth.isPrincipal(credentials, 'user')) {\n response.status(200).json([]);\n return;\n }\n\n const info = await userInfo.getUserInfo(credentials);\n\n const userEntity = (await catalogClient.getEntityByRef(info.userEntityRef, {\n token,\n })) as UserEntity;\n\n if (!userEntity) {\n const error = `User entity cannot be determined from ${info.userEntityRef}`;\n logger.info(error);\n response.status(400).json(error);\n return;\n }\n\n const getUserIssuesForInstance = async (instance: ConfigInstance) => {\n const username = getAssigneUser(instance, userEntity);\n\n const maxResults = Number(\n request.query.maxResults || DEFAULT_MAX_RESULTS_USER_ISSUES,\n );\n\n try {\n const issues = await getUserIssues(\n username,\n maxResults,\n instance,\n cache,\n );\n return { issues, error: undefined };\n } catch (error: any) {\n return { error };\n }\n };\n\n const issuesList = await Promise.all(\n config\n .getInstances()\n .map(instanceName =>\n getUserIssuesForInstance(config.getInstance(instanceName)),\n ),\n );\n\n const issues = issuesList.flatMap(list => list.issues ?? []);\n const errors = issuesList\n .flatMap(list => list.error)\n .filter((v): v is NonNullable<typeof v> => !!v);\n\n if (issues.length > 0 || errors.length === 0) {\n response.status(200).json(issues);\n } else {\n const messages =\n errors.length > 1\n ? `\\n ${errors.map(err => err.message).join('\\n ')}`\n : ` ${errors[0].message}`;\n\n logger.error(`Error during getting user issues:${messages}`);\n response.status(503).json({\n error: `Error during getting user issues:${messages}`,\n });\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 fullProjectKeys =\n entity.metadata.annotations?.[projectKeyAnnotation]?.split(',')!;\n\n if (!fullProjectKeys) {\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 const projects = fullProjectKeys.map(fullProjectKey =>\n splitProjectKey(config, fullProjectKey),\n );\n\n const projectResponse = await getProjectResponse(projects[0], cache);\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 ${projects[0].projectKey}`,\n });\n return;\n }\n\n const url = projectResponse.avatarUrls['48x48'];\n\n const avatar = await getProjectAvatar(url, projects[0].instance);\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\n const middleware = MiddlewareFactory.create({ logger, config: rootConfig });\n\n router.use(middleware.error());\n return router;\n}\n","import { ConflictError, ServiceUnavailableError } from '@backstage/errors';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\n\ntype Config = ReturnType<RootConfigService['getConfig']>;\n\nfunction parseHeaders(config: Config | undefined): Record<string, string> {\n if (!config) {\n return {};\n }\n return Object.fromEntries(\n config.keys().map(key => {\n const value = config.getString(key);\n return [key, value] as const;\n }),\n );\n}\n\n/**\n * The configuration of a Jira instance\n *\n * @public\n */\nexport type ConfigInstance = {\n token: string;\n headers: Record<string, string>;\n baseUrl: string;\n userEmailSuffix?: string;\n};\n\nconst JIRA_CONFIG_BASE_URL = 'baseUrl';\nconst JIRA_CONFIG_TOKEN = 'token';\nconst JIRA_CONFIG_HEADERS = 'headers';\nconst JIRA_CONFIG_USER_EMAIL_SUFFIX = 'userEmailSuffix';\nconst JIRA_CONFIG_ANNOTATION = 'annotationPrefix';\n\n/**\n * Class for reading Jira configuration from the root config\n *\n * @public\n */\nexport class JiraConfig {\n private instances: Record<string, ConfigInstance> = {};\n /**\n * The annotation prefix to use for Jira annotations\n */\n public readonly annotationPrefix: string;\n\n private constructor(config: RootConfigService) {\n const jira = config.getConfig('jiraDashboard');\n\n this.annotationPrefix =\n jira.getOptionalString(JIRA_CONFIG_ANNOTATION) ?? 'jira.com';\n\n const instances = jira.getOptionalConfigArray('instances');\n if (instances) {\n // Multiple instances form\n instances.forEach(inst => {\n const name = inst.getString('name');\n if (Object.getOwnPropertyNames(this.instances).includes(name)) {\n throw new ConflictError(\n `Duplicate jiraDashboard instances: '${name}'`,\n );\n }\n\n this.instances[name] = {\n token: inst.getString(JIRA_CONFIG_TOKEN),\n headers: parseHeaders(inst.getOptionalConfig(JIRA_CONFIG_HEADERS)),\n baseUrl: inst.getString(JIRA_CONFIG_BASE_URL),\n userEmailSuffix: inst.getOptionalString(\n JIRA_CONFIG_USER_EMAIL_SUFFIX,\n ),\n };\n });\n } else {\n // Default form\n this.instances.default = {\n token: jira.getString(JIRA_CONFIG_TOKEN),\n headers: parseHeaders(jira.getOptionalConfig(JIRA_CONFIG_HEADERS)),\n baseUrl: jira.getString(JIRA_CONFIG_BASE_URL),\n userEmailSuffix: jira.getOptionalString(JIRA_CONFIG_USER_EMAIL_SUFFIX),\n };\n }\n }\n\n /**\n * Create a JiraConfig from the root config\n */\n public static fromConfig(config: RootConfigService): JiraConfig {\n return new JiraConfig(config);\n }\n\n private forInstance(instanceName: string) {\n const instance = this.instances[instanceName];\n if (!instance) {\n throw new ServiceUnavailableError(\n `No such jira instance '${instanceName}'`,\n );\n }\n return instance;\n }\n\n /**\n * Returns the configuration all instances\n */\n getInstances() {\n return Object.getOwnPropertyNames(this.instances);\n }\n\n /**\n * Get the jira config for a specific instance\n */\n getInstance(instanceName?: string): ConfigInstance {\n return this.forInstance(instanceName ?? 'default');\n }\n\n /**\n * Get the jira base url for a given instance\n */\n resolveJiraBaseUrl(instanceName: string): string {\n const instance = this.forInstance(instanceName);\n return instance.baseUrl;\n }\n\n /**\n * Get the auth token for a given instance\n */\n resolveJiraToken(instanceName: string): string {\n const instance = this.forInstance(instanceName);\n return instance.token;\n }\n\n /**\n * Get the email suffice for a given instance\n */\n resolveUserEmailSuffix(instanceName: string): string | undefined {\n const instance = this.forInstance(instanceName);\n return instance.userEmailSuffix;\n }\n}\n","import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\nimport { JiraConfig } from './config';\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 auth: coreServices.auth,\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n rootConfig: coreServices.rootConfig,\n discovery: coreServices.discovery,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n },\n async init({\n auth,\n httpRouter,\n logger,\n rootConfig,\n discovery,\n httpAuth,\n userInfo,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n logger,\n rootConfig,\n config: JiraConfig.fromConfig(rootConfig),\n discovery,\n httpAuth,\n userInfo,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["PROJECT_KEY_NAME","COMPONENTS_NAME","FILTERS_NAME","INCOMING_ISSUES_STATUS","ResponseError","fetch","catalogClient","CatalogClient","CacheManager","cache","Router","express","stringifyEntityRef","issues","stream","MiddlewareFactory","ConflictError","ServiceUnavailableError","createBackendPlugin","coreServices"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AASa,MAAA,cAAA,GAAiB,CAAC,MAAuB,KAAA;AACpD,EAAA,MAAM,SAAS,MAAO,CAAA,gBAAA,CAAA;AAEtB,EAAA,MAAM,oBAAuB,GAAA,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIA,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,CAAA;AAYgB,SAAA,eAAA,CACd,QACA,cACa,EAAA;AACb,EAAA,MAAM,CAAC,QAAU,EAAA,UAAU,CAAI,GAAA,cAAA,CAAe,MAAM,GAAG,CAAA,CAAA;AACvD,EAAA,IAAI,CAAC,UAAY,EAAA;AAEf,IAAO,OAAA;AAAA,MACL,QAAA,EAAU,OAAO,WAAY,EAAA;AAAA,MAC7B,cAAA;AAAA,MACA,UAAY,EAAA,QAAA;AAAA,KACd,CAAA;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,QAAA,EAAU,MAAO,CAAA,WAAA,CAAY,QAAQ,CAAA;AAAA,IACrC,cAAA;AAAA,IACA,UAAA;AAAA,GACF,CAAA;AACF;;AC3CO,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;;AC1Ba,MAAA,cAAA,GAAiB,OAC5B,OACqB,KAAA;AACrB,EAAM,MAAA,EAAE,UAAY,EAAA,QAAA,EAAa,GAAA,OAAA,CAAA;AACjC,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAG,EAAA,QAAA,CAAS,OAAO,CAAA,QAAA,EAAW,UAAU,CAAA,CAAA;AAAA,IACxC;AAAA,MACE,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,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,QACoB,KAAA;AACpB,EAAM,MAAA,QAAA,GAAW,MAAM,OAAQ,CAAA,QAAA,EAAU,GAAG,QAAS,CAAA,OAAO,CAAU,OAAA,EAAA,EAAE,CAAI,CAAA,EAAA;AAAA,IAC1E,MAAQ,EAAA,KAAA;AAAA,IACR,OAAS,EAAA;AAAA,MACP,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,OACA,EAAA,UAAA,EACA,KACqB,KAAA;AACrB,EAAM,MAAA,EAAE,UAAY,EAAA,QAAA,EAAa,GAAA,OAAA,CAAA;AACjC,EAAA,MAAM,MAAM,eAAgB,CAAA,EAAE,SAAS,UAAY,EAAA,UAAA,EAAY,OAAO,CAAA,CAAA;AACtE,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAG,EAAA,QAAA,CAAS,OAAO,CAAA,WAAA,EAAc,GAAG,CAAA,CAAA;AAAA,IACpC;AAAA,MACE,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,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;AA4BO,MAAM,UAAa,GAAA,OACxB,QACA,EAAA,QAAA,EACA,OAC8B,KAAA;AAC9B,EAAA,MAAM,WAAW,MAAM,OAAA,CAAQ,UAAU,CAAG,EAAA,QAAA,CAAS,OAAO,CAAU,MAAA,CAAA,EAAA;AAAA,IACpE,MAAQ,EAAA,MAAA;AAAA,IACR,IAAA,EAAM,KAAK,SAAU,CAAA,EAAE,KAAK,QAAU,EAAA,GAAG,SAAS,CAAA;AAAA,IAClD,OAAS,EAAA;AAAA,MACP,MAAQ,EAAA,kBAAA;AAAA,MACR,cAAgB,EAAA,kBAAA;AAAA,KAClB;AAAA,GACD,CAAA,CAAA;AACD,EAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,IAAM,MAAA,MAAMC,oBAAc,CAAA,YAAA,CAAa,QAAQ,CAAA,CAAA;AAAA,GACjD;AACA,EAAM,MAAA,YAAA,GAAe,MAAM,QAAA,CAAS,IAAK,EAAA,CAAA;AACzC,EAAO,OAAA,YAAA,CAAA;AACT,EAAA;AAEa,MAAA,oBAAA,GAAuB,OAClC,OAAA,EACA,YACqB,KAAA;AACrB,EAAM,MAAA,EAAE,UAAY,EAAA,QAAA,EAAa,GAAA,OAAA,CAAA;AAEjC,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,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAG,EAAA,QAAA,CAAS,OAAO,CAAA,WAAA,EAAc,GAAG,CAAA,CAAA;AAAA,IACpC;AAAA,MACE,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,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,QAA0B,EAAA;AAC5E,EAAO,OAAA,OAAA,CAAQ,UAAU,GAAG,CAAA,CAAA;AAC9B,CAAA;AAOA,eAAe,OAAA,CACb,QACA,EAAA,GAAA,EACA,IACA,EAAA;AACA,EAAA,MAAM,WAAc,GAAA,IAAA,IAAQ,EAAE,MAAA,EAAQ,KAAM,EAAA,CAAA;AAI5C,EAAA,WAAA,CAAY,OAAU,GAAA;AAAA,IACpB,GAAG,QAAS,CAAA,OAAA;AAAA,IACZ,eAAe,QAAS,CAAA,KAAA;AAAA,IACxB,GAAG,WAAY,CAAA,OAAA;AAAA,GACjB,CAAA;AACA,EAAO,OAAAC,sBAAA,CAAM,KAAK,WAAW,CAAA,CAAA;AAC/B;;AClJa,MAAA,kBAAA,GAAqB,OAChC,OAAA,EACA,KACqB,KAAA;AACrB,EAAI,IAAA,eAAA,CAAA;AAEJ,EAAA,eAAA,GAAmB,MAAM,KAAA,CAAM,GAAI,CAAA,OAAA,CAAQ,cAAc,CAAA,CAAA;AAEzD,EAAA,IAAI,eAAiB,EAAA;AACnB,IAAO,OAAA,eAAA,CAAA;AAAA,GACT;AAEA,EAAI,IAAA;AACF,IAAkB,eAAA,GAAA,MAAM,eAAe,OAAO,CAAA,CAAA;AAC9C,IAAM,KAAA,CAAA,GAAA,CAAI,OAAQ,CAAA,cAAA,EAAgB,eAAe,CAAA,CAAA;AAAA,WAC1C,GAAU,EAAA;AACjB,IAAI,IAAA,GAAA,CAAI,YAAY,GAAK,EAAA;AACvB,MAAM,MAAA,KAAA;AAAA,QACJ,CAA8C,2CAAA,EAAA,OAAA,CAAQ,cAAc,CAAA,aAAA,EAAgB,IAAI,OAAO,CAAA,CAAA;AAAA,OACjG,CAAA;AAAA,KACF;AAAA,GACF;AACA,EAAO,OAAA,eAAA,CAAA;AACT,CAAA,CAAA;AAEO,MAAM,cAAiB,GAAA,OAC5B,GACA,EAAA,MAAA,EACA,OACA,aACqB,KAAA;AACrB,EAAI,IAAA,cAAA,CAAA;AAEJ,EAAA,MAAM,QAAW,GAAA,CAAA,EAAG,MAAO,CAAA,OAAO,IAAI,GAAG,CAAA,CAAA,CAAA;AAEzC,EAAkB,cAAA,GAAA,MAAM,KAAM,CAAA,GAAA,CAAI,QAAQ,CAAA,CAAA;AAE1C,EAAA,IAAI,cAAgB,EAAA;AAClB,IAAO,OAAA,cAAA,CAAA;AAAA,GACT;AAEA,EAAI,IAAA;AACF,IAAA,cAAA,GAAA,CAAkB,MAAM,UAAA,CAAW,MAAQ,EAAA,GAAA,EAAK,aAAa,CAAG,EAAA,MAAA,CAAA;AAChE,IAAM,KAAA,CAAA,GAAA,CAAI,UAAU,cAAc,CAAA,CAAA;AAAA,WAC3B,GAAU,EAAA;AACjB,IAAI,IAAA,GAAA,CAAI,YAAY,GAAK,EAAA;AACvB,MAAM,MAAA,KAAA;AAAA,QACJ,CAAgC,6BAAA,EAAA,GAAG,CAAgB,aAAA,EAAA,GAAA,CAAI,OAAO,CAAA,CAAA;AAAA,OAChE,CAAA;AAAA,KACF;AAAA,GACF;AACA,EAAO,OAAA,cAAA,CAAA;AACT,CAAA,CAAA;AAEO,MAAM,aAAgB,GAAA,OAC3B,QACA,EAAA,UAAA,EACA,QACA,KACqB,KAAA;AACrB,EAAM,MAAA,GAAA,GAAM,eAAe,QAAQ,CAAA,kEAAA,CAAA,CAAA;AAEnC,EAAO,OAAA,cAAA,CAAe,GAAK,EAAA,MAAA,EAAQ,KAAO,EAAA;AAAA,IACxC,MAAQ,EAAA;AAAA,MACN,KAAA;AAAA,MACA,WAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA;AAAA,KACF;AAAA,IACA,UAAA;AAAA,GACD,CAAA,CAAA;AACH,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,OACA,EAAA,UAAA,EACA,OACgC,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,OAAO,eAAgB,CAAA;AAAA,QACrB,SAAS,OAAQ,CAAA,UAAA;AAAA,QACjB,UAAA;AAAA,QACA,OAAO,MAAO,CAAA,KAAA;AAAA,OACf,CAAA;AAAA,MACD,IAAM,EAAA,QAAA;AAAA,MACN,QAAQ,MAAM,iBAAA,CAAkB,OAAS,EAAA,UAAA,EAAY,OAAO,KAAK,CAAA;AAAA,KACjE,CAAA,CAAA;AAAA,GACJ,CAAA;AACF,CAAA,CAAA;AAEa,MAAA,uBAAA,GAA0B,OACrC,OAAA,EACA,oBACgC,KAAA;AAChC,EAAA,OAAO,MAAM,OAAQ,CAAA,GAAA;AAAA,IACnB,oBAAA,CAAqB,GAAI,CAAA,OAAM,YAAiB,MAAA;AAAA,MAC9C,IAAM,EAAA,YAAA;AAAA,MACN,OAAO,eAAgB,CAAA;AAAA,QACrB,SAAS,OAAQ,CAAA,UAAA;AAAA,QACjB,UAAA,EAAY,CAAC,YAAY,CAAA;AAAA,OAC1B,CAAA;AAAA,MACD,IAAM,EAAA,WAAA;AAAA,MACN,MAAQ,EAAA,MAAM,oBAAqB,CAAA,OAAA,EAAS,YAAY,CAAA;AAAA,KACxD,CAAA,CAAA;AAAA,GACJ,CAAA;AACF,CAAA;;ACpJO,MAAM,cAAc,GAAO,GAAA,EAAA,CAAA;AAE3B,MAAM,+BAAkC,GAAA,EAAA;;ACE/C,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,aAAa,cAAc,CAAA,sBAAA,CAAA;AACpC,CAAA,CAAA,CAAA;AASa,MAAA,cAAA,GAAiB,CAC5B,QAAA,EACA,UACW,KAAA;AACX,EAAA,MAAM,oBAAoB,QAAS,CAAA,eAAA,CAAA;AAEnC,EAAA,OAAO,iBACH,GAAA,CAAA,EAAG,UAAW,CAAA,QAAA,CAAS,IAAI,CAAA,EAAG,iBAAiB,CAAA,CAAA,GAC/C,UAAW,CAAA,IAAA,EAAM,OAAS,EAAA,KAAA,IAAS,WAAW,QAAS,CAAA,IAAA,CAAA;AAC7D,CAAA,CAAA;AAEA,MAAM,qBAAA,GAAwB,CAC5B,UAAA,EACA,QACW,KAAA;AACX,EAAM,MAAA,KAAA,GAAQ,cAAe,CAAA,QAAA,EAAU,UAAU,CAAA,CAAA;AAEjD,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,QACA,EAAA,UAAA,EACA,cACa,KAAA;AACb,EAAM,MAAA,cAAA,GAAiB,iBAAkB,CAAA,cAAA,IAAkB,KAAK,CAAA,CAAA;AAEhE,EAAA,IAAI,CAAC,UAAA,EAAmB,OAAA,CAAC,YAAY,cAAc,CAAA,CAAA;AAEnD,EAAM,MAAA,kBAAA,GAAqB,qBAAsB,CAAA,UAAA,EAAY,QAAQ,CAAA,CAAA;AAErE,EAAO,OAAA,CAAC,UAAY,EAAA,cAAA,EAAgB,kBAAkB,CAAA,CAAA;AACxD,CAAA;;ACQA,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAM,MAAA,EAAE,MAAM,MAAQ,EAAA,UAAA,EAAY,QAAQ,SAAW,EAAA,QAAA,EAAU,UAC7D,GAAA,OAAA,CAAA;AACF,EAAA,MAAMC,kBAAgB,IAAIC,2BAAA,CAAc,EAAE,YAAA,EAAc,WAAW,CAAA,CAAA;AAEnE,EAAA,MAAM,cACJC,kBAAa,CAAA,UAAA,CAAW,UAAU,CAAA,CAAE,UAAU,gBAAgB,CAAA,CAAA;AAChE,EAAA,MAAMC,UAAQ,WAAY,CAAA,SAAA,CAAU,EAAE,UAAA,EAAY,aAAa,CAAA,CAAA;AAC/D,EAAA,MAAA,CAAO,KAAK,qCAAqC,CAAA,CAAA;AAEjD,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,MAAA,CAAO,KAAK,OAAO,CAAA,CAAA;AACnB,IAAA,QAAA,CAAS,IAAK,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAM,CAAA,CAAA;AAAA,GAC/B,CAAA,CAAA;AAED,EAAO,MAAA,CAAA,GAAA;AAAA,IACL,kDAAA;AAAA,IACA,OAAO,SAAS,QAAa,KAAA;AAC3B,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,MAAMN,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,kBACJ,MAAO,CAAA,QAAA,CAAS,cAAc,oBAAoB,CAAA,EAAG,MAAM,GAAG,CAAA,CAAA;AAEhE,MAAA,IAAI,CAAC,eAAiB,EAAA;AACpB,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,MAAA,MAAM,WAAW,eAAgB,CAAA,GAAA;AAAA,QAAI,CAAA,cAAA,KACnC,eAAgB,CAAA,MAAA,EAAQ,cAAc,CAAA;AAAA,OACxC,CAAA;AAEA,MAAI,IAAA,eAAA,CAAA;AAEJ,MAAI,IAAA;AACF,QAAA,eAAA,GAAkB,MAAM,kBAAA,CAAmB,QAAS,CAAA,CAAC,GAAGG,OAAK,CAAA,CAAA;AAAA,eACtD,GAAU,EAAA;AACjB,QAAO,MAAA,CAAA,KAAA;AAAA,UACL,+BAA+B,QAAS,CAAA,CAAC,EAAE,cAAc,CAAA,EAAA,EAAK,IAAI,OAAO,CAAA,CAAA;AAAA,SAC3E,CAAA;AACA,QAAS,QAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,UACxB,KAAO,EAAA,CAAA,+BAAA,EAAkC,QAAS,CAAA,CAAC,EAAE,UAAU,CAAA,CAAA;AAAA,SAChE,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,MAAMH,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,MAAA,CAAO,QAAS,CAAA,WAAA,GAAc,wBAAwB,CAAA,CAAA;AAExD,MAAU,OAAA,GAAA,wBAAA;AAAA,QACR,QAAA,CAAS,CAAC,CAAE,CAAA,QAAA;AAAA,QACZ,UAAA;AAAA,QACA,cAAA;AAAA,OACF,CAAA;AAEA,MAAA,MAAM,0BACJ,MAAO,CAAA,QAAA,CAAS,cAAc,iBAAiB,CAAA,EAAG,MAAM,GAAG,CAAA,CAAA;AAE7D,MAAA,IAAI,uBAAyB,EAAA;AAC3B,QAAQ,OAAA,CAAA,IAAA;AAAA,UACN,GAAI,MAAM,yBAAA;AAAA,YACR,uBAAA;AAAA,YACA,QAAA,CAAS,CAAC,CAAE,CAAA,QAAA;AAAA,WACd;AAAA,SACF,CAAA;AAAA,OACF;AAEA,MAAI,IAAA,UAAA,GACF,OAAO,QAAS,CAAA,WAAA,GAAc,oBAAoB,CAAG,EAAA,KAAA,CAAM,GAAG,CAAA,IAAK,EAAC,CAAA;AACtE,MAAA,IAAI,SAAS,MAAM,oBAAA,CAAqB,SAAS,CAAC,CAAA,EAAG,YAAY,OAAO,CAAA,CAAA;AAGxE,MAAA,UAAA,GAAa,UAAW,CAAA,MAAA;AAAA,QACtB,MAAA,CAAO,SAAS,WAAc,GAAA,yBAAyB,GAAG,KAAM,CAAA,GAAG,KACjE,EAAC;AAAA,OACL,CAAA;AAEA,MAAA,IAAI,UAAY,EAAA;AACd,QAAA,MAAM,kBAAkB,MAAM,uBAAA;AAAA,UAC5B,SAAS,CAAC,CAAA;AAAA,UACV,UAAA;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,EAAA,MAAA,CAAO,GAAI,CAAA,yBAAA,EAA2B,OAAO,OAAA,EAAS,QAAa,KAAA;AACjE,IAAA,MAAM,EAAE,KAAA,EAAU,GAAA,MAAM,KAAK,qBAAsB,CAAA;AAAA,MACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAyB,EAAA;AAAA,MAChD,cAAgB,EAAA,SAAA;AAAA,KACjB,CAAA,CAAA;AAED,IAAA,MAAM,WAAc,GAAA,MAAM,QAAS,CAAA,WAAA,CAAY,OAAS,EAAA;AAAA,MACtD,KAAA,EAAO,CAAC,MAAM,CAAA;AAAA,KACf,CAAA,CAAA;AAGD,IAAA,IAAI,CAAC,IAAA,CAAK,WAAY,CAAA,WAAA,EAAa,MAAM,CAAG,EAAA;AAC1C,MAAA,QAAA,CAAS,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,EAAE,CAAA,CAAA;AAC5B,MAAA,OAAA;AAAA,KACF;AAEA,IAAA,MAAM,IAAO,GAAA,MAAM,QAAS,CAAA,WAAA,CAAY,WAAW,CAAA,CAAA;AAEnD,IAAA,MAAM,UAAc,GAAA,MAAMA,eAAc,CAAA,cAAA,CAAe,KAAK,aAAe,EAAA;AAAA,MACzE,KAAA;AAAA,KACD,CAAA,CAAA;AAED,IAAA,IAAI,CAAC,UAAY,EAAA;AACf,MAAM,MAAA,KAAA,GAAQ,CAAyC,sCAAA,EAAA,IAAA,CAAK,aAAa,CAAA,CAAA,CAAA;AACzE,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA,CAAA;AACjB,MAAA,QAAA,CAAS,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAC/B,MAAA,OAAA;AAAA,KACF;AAEA,IAAM,MAAA,wBAAA,GAA2B,OAAO,QAA6B,KAAA;AACnE,MAAM,MAAA,QAAA,GAAW,cAAe,CAAA,QAAA,EAAU,UAAU,CAAA,CAAA;AAEpD,MAAA,MAAM,UAAa,GAAA,MAAA;AAAA,QACjB,OAAA,CAAQ,MAAM,UAAc,IAAA,+BAAA;AAAA,OAC9B,CAAA;AAEA,MAAI,IAAA;AACF,QAAA,MAAMO,UAAS,MAAM,aAAA;AAAA,UACnB,QAAA;AAAA,UACA,UAAA;AAAA,UACA,QAAA;AAAA,UACAJ,OAAA;AAAA,SACF,CAAA;AACA,QAAA,OAAO,EAAE,MAAA,EAAAI,OAAQ,EAAA,KAAA,EAAO,KAAU,CAAA,EAAA,CAAA;AAAA,eAC3B,KAAY,EAAA;AACnB,QAAA,OAAO,EAAE,KAAM,EAAA,CAAA;AAAA,OACjB;AAAA,KACF,CAAA;AAEA,IAAM,MAAA,UAAA,GAAa,MAAM,OAAQ,CAAA,GAAA;AAAA,MAC/B,MAAA,CACG,cACA,CAAA,GAAA;AAAA,QAAI,CACH,YAAA,KAAA,wBAAA,CAAyB,MAAO,CAAA,WAAA,CAAY,YAAY,CAAC,CAAA;AAAA,OAC3D;AAAA,KACJ,CAAA;AAEA,IAAA,MAAM,SAAS,UAAW,CAAA,OAAA,CAAQ,UAAQ,IAAK,CAAA,MAAA,IAAU,EAAE,CAAA,CAAA;AAC3D,IAAA,MAAM,MAAS,GAAA,UAAA,CACZ,OAAQ,CAAA,CAAA,IAAA,KAAQ,IAAK,CAAA,KAAK,CAC1B,CAAA,MAAA,CAAO,CAAC,CAAA,KAAkC,CAAC,CAAC,CAAC,CAAA,CAAA;AAEhD,IAAA,IAAI,MAAO,CAAA,MAAA,GAAS,CAAK,IAAA,MAAA,CAAO,WAAW,CAAG,EAAA;AAC5C,MAAA,QAAA,CAAS,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,KAC3B,MAAA;AACL,MAAM,MAAA,QAAA,GACJ,MAAO,CAAA,MAAA,GAAS,CACZ,GAAA,CAAA;AAAA,EAAA,EAAO,MAAO,CAAA,GAAA,CAAI,CAAO,GAAA,KAAA,GAAA,CAAI,OAAO,CAAE,CAAA,IAAA,CAAK,MAAM,CAAC,CAClD,CAAA,GAAA,CAAA,CAAA,EAAI,MAAO,CAAA,CAAC,EAAE,OAAO,CAAA,CAAA,CAAA;AAE3B,MAAO,MAAA,CAAA,KAAA,CAAM,CAAoC,iCAAA,EAAA,QAAQ,CAAE,CAAA,CAAA,CAAA;AAC3D,MAAS,QAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,QACxB,KAAA,EAAO,oCAAoC,QAAQ,CAAA,CAAA;AAAA,OACpD,CAAA,CAAA;AAAA,KACH;AAAA,GACD,CAAA,CAAA;AAED,EAAO,MAAA,CAAA,GAAA;AAAA,IACL,8CAAA;AAAA,IACA,OAAO,SAAS,QAAa,KAAA;AAC3B,MAAA,MAAM,EAAE,IAAA,EAAM,SAAW,EAAA,IAAA,KAAS,OAAQ,CAAA,MAAA,CAAA;AAC1C,MAAA,MAAM,YAAYD,+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,MAAMN,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,kBACJ,MAAO,CAAA,QAAA,CAAS,cAAc,oBAAoB,CAAA,EAAG,MAAM,GAAG,CAAA,CAAA;AAEhE,MAAA,IAAI,CAAC,eAAiB,EAAA;AACpB,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,MAAA,MAAM,WAAW,eAAgB,CAAA,GAAA;AAAA,QAAI,CAAA,cAAA,KACnC,eAAgB,CAAA,MAAA,EAAQ,cAAc,CAAA;AAAA,OACxC,CAAA;AAEA,MAAA,MAAM,kBAAkB,MAAM,kBAAA,CAAmB,QAAS,CAAA,CAAC,GAAGG,OAAK,CAAA,CAAA;AAEnE,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,QAAS,CAAA,CAAC,EAAE,UAAU,CAAA,CAAA;AAAA,SACvE,CAAA,CAAA;AACD,QAAA,OAAA;AAAA,OACF;AAEA,MAAM,MAAA,GAAA,GAAM,eAAgB,CAAA,UAAA,CAAW,OAAO,CAAA,CAAA;AAE9C,MAAA,MAAM,SAAS,MAAM,gBAAA,CAAiB,KAAK,QAAS,CAAA,CAAC,EAAE,QAAQ,CAAA,CAAA;AAE/D,MAAM,MAAA,EAAA,GAAK,IAAIK,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,IAAO,EAAE,CAAA,CAAA;AAC5C,MAAAA,uBAAA,CAAO,QAAS,CAAA,MAAA,CAAO,IAAM,EAAA,EAAA,EAAI,CAAO,GAAA,KAAA;AACtC,QAAA,IAAI,GAAK,EAAA;AACP,UAAO,MAAA,CAAA,KAAA,CAAM,CAAG,EAAA,GAAG,CAAE,CAAA,CAAA,CAAA;AACrB,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;AAEA,EAAA,MAAM,aAAaC,gCAAkB,CAAA,MAAA,CAAO,EAAE,MAAQ,EAAA,MAAA,EAAQ,YAAY,CAAA,CAAA;AAE1E,EAAO,MAAA,CAAA,GAAA,CAAI,UAAW,CAAA,KAAA,EAAO,CAAA,CAAA;AAC7B,EAAO,OAAA,MAAA,CAAA;AACT;;ACxVA,SAAS,aAAa,MAAoD,EAAA;AACxE,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AACA,EAAA,OAAO,MAAO,CAAA,WAAA;AAAA,IACZ,MAAO,CAAA,IAAA,EAAO,CAAA,GAAA,CAAI,CAAO,GAAA,KAAA;AACvB,MAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,SAAA,CAAU,GAAG,CAAA,CAAA;AAClC,MAAO,OAAA,CAAC,KAAK,KAAK,CAAA,CAAA;AAAA,KACnB,CAAA;AAAA,GACH,CAAA;AACF,CAAA;AAcA,MAAM,oBAAuB,GAAA,SAAA,CAAA;AAC7B,MAAM,iBAAoB,GAAA,OAAA,CAAA;AAC1B,MAAM,mBAAsB,GAAA,SAAA,CAAA;AAC5B,MAAM,6BAAgC,GAAA,iBAAA,CAAA;AACtC,MAAM,sBAAyB,GAAA,kBAAA,CAAA;AAOxB,MAAM,UAAW,CAAA;AAAA,EACd,YAA4C,EAAC,CAAA;AAAA;AAAA;AAAA;AAAA,EAIrC,gBAAA,CAAA;AAAA,EAER,YAAY,MAA2B,EAAA;AAC7C,IAAM,MAAA,IAAA,GAAO,MAAO,CAAA,SAAA,CAAU,eAAe,CAAA,CAAA;AAE7C,IAAA,IAAA,CAAK,gBACH,GAAA,IAAA,CAAK,iBAAkB,CAAA,sBAAsB,CAAK,IAAA,UAAA,CAAA;AAEpD,IAAM,MAAA,SAAA,GAAY,IAAK,CAAA,sBAAA,CAAuB,WAAW,CAAA,CAAA;AACzD,IAAA,IAAI,SAAW,EAAA;AAEb,MAAA,SAAA,CAAU,QAAQ,CAAQ,IAAA,KAAA;AACxB,QAAM,MAAA,IAAA,GAAO,IAAK,CAAA,SAAA,CAAU,MAAM,CAAA,CAAA;AAClC,QAAA,IAAI,OAAO,mBAAoB,CAAA,IAAA,CAAK,SAAS,CAAE,CAAA,QAAA,CAAS,IAAI,CAAG,EAAA;AAC7D,UAAA,MAAM,IAAIC,oBAAA;AAAA,YACR,uCAAuC,IAAI,CAAA,CAAA,CAAA;AAAA,WAC7C,CAAA;AAAA,SACF;AAEA,QAAK,IAAA,CAAA,SAAA,CAAU,IAAI,CAAI,GAAA;AAAA,UACrB,KAAA,EAAO,IAAK,CAAA,SAAA,CAAU,iBAAiB,CAAA;AAAA,UACvC,OAAS,EAAA,YAAA,CAAa,IAAK,CAAA,iBAAA,CAAkB,mBAAmB,CAAC,CAAA;AAAA,UACjE,OAAA,EAAS,IAAK,CAAA,SAAA,CAAU,oBAAoB,CAAA;AAAA,UAC5C,iBAAiB,IAAK,CAAA,iBAAA;AAAA,YACpB,6BAAA;AAAA,WACF;AAAA,SACF,CAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACI,MAAA;AAEL,MAAA,IAAA,CAAK,UAAU,OAAU,GAAA;AAAA,QACvB,KAAA,EAAO,IAAK,CAAA,SAAA,CAAU,iBAAiB,CAAA;AAAA,QACvC,OAAS,EAAA,YAAA,CAAa,IAAK,CAAA,iBAAA,CAAkB,mBAAmB,CAAC,CAAA;AAAA,QACjE,OAAA,EAAS,IAAK,CAAA,SAAA,CAAU,oBAAoB,CAAA;AAAA,QAC5C,eAAA,EAAiB,IAAK,CAAA,iBAAA,CAAkB,6BAA6B,CAAA;AAAA,OACvE,CAAA;AAAA,KACF;AAAA,GACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,WAAW,MAAuC,EAAA;AAC9D,IAAO,OAAA,IAAI,WAAW,MAAM,CAAA,CAAA;AAAA,GAC9B;AAAA,EAEQ,YAAY,YAAsB,EAAA;AACxC,IAAM,MAAA,QAAA,GAAW,IAAK,CAAA,SAAA,CAAU,YAAY,CAAA,CAAA;AAC5C,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAA,MAAM,IAAIC,8BAAA;AAAA,QACR,0BAA0B,YAAY,CAAA,CAAA,CAAA;AAAA,OACxC,CAAA;AAAA,KACF;AACA,IAAO,OAAA,QAAA,CAAA;AAAA,GACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAe,GAAA;AACb,IAAO,OAAA,MAAA,CAAO,mBAAoB,CAAA,IAAA,CAAK,SAAS,CAAA,CAAA;AAAA,GAClD;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,YAAuC,EAAA;AACjD,IAAO,OAAA,IAAA,CAAK,WAAY,CAAA,YAAA,IAAgB,SAAS,CAAA,CAAA;AAAA,GACnD;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,YAA8B,EAAA;AAC/C,IAAM,MAAA,QAAA,GAAW,IAAK,CAAA,WAAA,CAAY,YAAY,CAAA,CAAA;AAC9C,IAAA,OAAO,QAAS,CAAA,OAAA,CAAA;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,YAA8B,EAAA;AAC7C,IAAM,MAAA,QAAA,GAAW,IAAK,CAAA,WAAA,CAAY,YAAY,CAAA,CAAA;AAC9C,IAAA,OAAO,QAAS,CAAA,KAAA,CAAA;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,YAA0C,EAAA;AAC/D,IAAM,MAAA,QAAA,GAAW,IAAK,CAAA,WAAA,CAAY,YAAY,CAAA,CAAA;AAC9C,IAAA,OAAO,QAAS,CAAA,eAAA,CAAA;AAAA,GAClB;AACF;;AC9HO,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,MAAMC,6BAAa,CAAA,IAAA;AAAA,QACnB,YAAYA,6BAAa,CAAA,UAAA;AAAA,QACzB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,YAAYA,6BAAa,CAAA,UAAA;AAAA,QACzB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,UAAUA,6BAAa,CAAA,QAAA;AAAA,OACzB;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,IAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA,UAAA;AAAA,QACA,SAAA;AAAA,QACA,QAAA;AAAA,QACA,QAAA;AAAA,OACC,EAAA;AACD,QAAW,UAAA,CAAA,GAAA;AAAA,UACT,MAAM,YAAa,CAAA;AAAA,YACjB,IAAA;AAAA,YACA,MAAA;AAAA,YACA,UAAA;AAAA,YACA,MAAA,EAAQ,UAAW,CAAA,UAAA,CAAW,UAAU,CAAA;AAAA,YACxC,SAAA;AAAA,YACA,QAAA;AAAA,YACA,QAAA;AAAA,WACD,CAAA;AAAA,SACH,CAAA;AACA,QAAA,UAAA,CAAW,aAAc,CAAA;AAAA,UACvB,IAAM,EAAA,SAAA;AAAA,UACN,KAAO,EAAA,iBAAA;AAAA,SACR,CAAA,CAAA;AAAA,OACH;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACF,CAAC;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
+
import { RootConfigService } from '@backstage/backend-plugin-api';
|
|
2
3
|
import { JiraQueryResults } from '@axis-backstage/plugin-jira-dashboard-common';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -19,6 +20,44 @@ type ConfigInstance = {
|
|
|
19
20
|
baseUrl: string;
|
|
20
21
|
userEmailSuffix?: string;
|
|
21
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Class for reading Jira configuration from the root config
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
declare class JiraConfig {
|
|
29
|
+
private instances;
|
|
30
|
+
/**
|
|
31
|
+
* The annotation prefix to use for Jira annotations
|
|
32
|
+
*/
|
|
33
|
+
readonly annotationPrefix: string;
|
|
34
|
+
private constructor();
|
|
35
|
+
/**
|
|
36
|
+
* Create a JiraConfig from the root config
|
|
37
|
+
*/
|
|
38
|
+
static fromConfig(config: RootConfigService): JiraConfig;
|
|
39
|
+
private forInstance;
|
|
40
|
+
/**
|
|
41
|
+
* Returns the configuration all instances
|
|
42
|
+
*/
|
|
43
|
+
getInstances(): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Get the jira config for a specific instance
|
|
46
|
+
*/
|
|
47
|
+
getInstance(instanceName?: string): ConfigInstance;
|
|
48
|
+
/**
|
|
49
|
+
* Get the jira base url for a given instance
|
|
50
|
+
*/
|
|
51
|
+
resolveJiraBaseUrl(instanceName: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Get the auth token for a given instance
|
|
54
|
+
*/
|
|
55
|
+
resolveJiraToken(instanceName: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Get the email suffice for a given instance
|
|
58
|
+
*/
|
|
59
|
+
resolveUserEmailSuffix(instanceName: string): string | undefined;
|
|
60
|
+
}
|
|
22
61
|
|
|
23
62
|
/**
|
|
24
63
|
* Options available for the Jira JQL query.
|
|
@@ -63,4 +102,4 @@ type JqlQueryBuilderArgs = {
|
|
|
63
102
|
*/
|
|
64
103
|
declare const jqlQueryBuilder: ({ project, components, query, }: JqlQueryBuilderArgs) => string;
|
|
65
104
|
|
|
66
|
-
export { type ConfigInstance, type JqlQueryBuilderArgs, type SearchOptions, jiraDashboardPlugin as default, jqlQueryBuilder, searchJira };
|
|
105
|
+
export { type ConfigInstance, JiraConfig, type JqlQueryBuilderArgs, type SearchOptions, jiraDashboardPlugin as default, jqlQueryBuilder, searchJira };
|